From 61a00aa75220d42fcb448fcd273c58e6e45f7af9 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 17:09:58 +0530 Subject: [PATCH 1/7] forge install: v4-core --- .gitmodules | 3 +++ packages/foundry/lib/v4-core | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/foundry/lib/v4-core diff --git a/.gitmodules b/.gitmodules index 249ca4d..505298c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "packages/foundry/lib/v4-periphery"] path = packages/foundry/lib/v4-periphery url = https://github.com/Uniswap/v4-periphery +[submodule "packages/foundry/lib/v4-core"] + path = packages/foundry/lib/v4-core + url = https://github.com/Uniswap/v4-core diff --git a/packages/foundry/lib/v4-core b/packages/foundry/lib/v4-core new file mode 160000 index 0000000..b619b67 --- /dev/null +++ b/packages/foundry/lib/v4-core @@ -0,0 +1 @@ +Subproject commit b619b6718e31aa5b4fa0286520c455ceb950276d From 6d10a7644055026596be8009b0474992feb1c948 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 17:12:08 +0530 Subject: [PATCH 2/7] forge install: solmate --- .gitmodules | 3 +++ packages/foundry/lib/solmate | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/foundry/lib/solmate diff --git a/.gitmodules b/.gitmodules index 505298c..0c92e1f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "packages/foundry/lib/v4-core"] path = packages/foundry/lib/v4-core url = https://github.com/Uniswap/v4-core +[submodule "packages/foundry/lib/solmate"] + path = packages/foundry/lib/solmate + url = https://github.com/transmissions11/solmate diff --git a/packages/foundry/lib/solmate b/packages/foundry/lib/solmate new file mode 160000 index 0000000..c93f771 --- /dev/null +++ b/packages/foundry/lib/solmate @@ -0,0 +1 @@ +Subproject commit c93f7716c9909175d45f6ef80a34a650e2d24e56 From 0ec3f867591e5ccfddf87ffdb315438cf6e2181c Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 17:52:51 +0530 Subject: [PATCH 3/7] feat: added chronicle oracle --- packages/foundry/src/EtfHook.sol | 33 ++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/foundry/src/EtfHook.sol b/packages/foundry/src/EtfHook.sol index 6b24f51..19fe889 100644 --- a/packages/foundry/src/EtfHook.sol +++ b/packages/foundry/src/EtfHook.sol @@ -11,11 +11,36 @@ import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol"; import {ETFManager} from "./EtfToken.sol"; + +// Copied from [chronicle-std](https://github.com/chronicleprotocol/chronicle-std/blob/main/src/IChronicle.sol). +interface IChronicle { + /* + * @notice Returns the oracle's current value. + * @dev Reverts if no value set. + * @return value The oracle's current value. + */ + function read() external view returns (uint256 value); +} + + +interface ISelfKisser { + /// @notice Kisses caller on oracle `oracle`. + function selfKiss(address oracle) external; +} contract ETFHook is ETFManager, BaseHook { address[2] public tokens; // the underlying tokens will be stored in this hook contract uint256[2] public weights; uint256 public rebalanceThreshold; + // chronicle oracle addresses + address public Chronicle_BTC_USD_3 =0xdc3ef3E31AdAe791d9D5054B575f7396851Fa432; + address public Chronicle_ETH_USD_3 =0xdd6D76262Fd7BdDe428dcfCd94386EbAe0151603; + + // Chainlink oracle addresses + address public Chainlink_ETH_USD = 0x694AA1769357215DE4FAC081bf1f309aDC325306; + address public Chainlink_BTC_USD = 0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43; + + // token balances uint256[2] public tokenBalances; constructor( @@ -30,6 +55,10 @@ contract ETFHook is ETFManager, BaseHook { for (uint256 i= 0; i < 2; i++) { tokenBalances[i] = 0; } + + // This allows the contract to read from the chronicle oracle. + ISelfKisser(Chronicle_BTC_USD_3).selfKiss(address(this)); + ISelfKisser(Chronicle_ETH_USD_3).selfKiss(address(this)); } function getHookPermissions() public pure override returns (Hooks.Permissions memory) { @@ -89,9 +118,9 @@ contract ETFHook is ETFManager, BaseHook { } // returns each token prices from oracle - function getPrices() public returns (uint256[2] memory prices) { + function chroniclegetPrices() public view returns (uint256[2] memory prices) { // TODO: use chainlink, pyth, chronicle - return prices; + return [IChronicle(Chronicle_ETH_USD_3).read(), IChronicle(Chronicle_BTC_USD_3).read()]; } function checkIfRebalanceNeeded() private returns (bool) { From a48ccae49410d241240745469bcfc771b7986fc6 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 17:53:31 +0530 Subject: [PATCH 4/7] forge install: foundry-chainlink-toolkit --- .gitmodules | 3 +++ packages/foundry/lib/foundry-chainlink-toolkit | 1 + 2 files changed, 4 insertions(+) create mode 160000 packages/foundry/lib/foundry-chainlink-toolkit diff --git a/.gitmodules b/.gitmodules index 0c92e1f..d496012 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "packages/foundry/lib/solmate"] path = packages/foundry/lib/solmate url = https://github.com/transmissions11/solmate +[submodule "packages/foundry/lib/foundry-chainlink-toolkit"] + path = packages/foundry/lib/foundry-chainlink-toolkit + url = https://github.com/smartcontractkit/foundry-chainlink-toolkit diff --git a/packages/foundry/lib/foundry-chainlink-toolkit b/packages/foundry/lib/foundry-chainlink-toolkit new file mode 160000 index 0000000..d610ec9 --- /dev/null +++ b/packages/foundry/lib/foundry-chainlink-toolkit @@ -0,0 +1 @@ +Subproject commit d610ec9ef54c325de7de1a5622c19933b2ae26cf From b343924a7c4db8d57ec8c991c10a6d1bb13009c3 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 18:39:08 +0530 Subject: [PATCH 5/7] feat: chainlink oracle added --- package.json | 3 + .../foundry/lib/chainlink/contracts/README.md | 75 + .../contracts/abi/v0.8/AccessControl.json | 227 + .../abi/v0.8/AccessControllerInterface.json | 26 + .../chainlink/contracts/abi/v0.8/Address.json | 29 + .../abi/v0.8/AggregatorInterface.json | 129 + .../abi/v0.8/AggregatorV2V3Interface.json | 240 + .../abi/v0.8/AggregatorV3Interface.json | 113 + .../v0.8/AggregatorValidatorInterface.json | 36 + .../contracts/abi/v0.8/ArbGasInfo.json | 406 + .../chainlink/contracts/abi/v0.8/ArbSys.json | 355 + .../v0.8/ArbitrumCrossDomainForwarder.json | 199 + .../abi/v0.8/ArbitrumCrossDomainGovernor.json | 217 + .../abi/v0.8/ArbitrumL1BridgeAdapter.json | 272 + .../abi/v0.8/ArbitrumL2BridgeAdapter.json | 155 + .../contracts/abi/v0.8/ArbitrumModule.json | 90 + .../abi/v0.8/ArbitrumSequencerUptimeFeed.json | 621 + .../contracts/abi/v0.8/ArbitrumValidator.json | 565 + .../contracts/abi/v0.8/AuthorizedCallers.json | 164 + .../abi/v0.8/AuthorizedForwarder.json | 286 + .../abi/v0.8/AuthorizedReceiver.json | 66 + .../contracts/abi/v0.8/AutomationBase.json | 7 + .../abi/v0.8/AutomationCompatible.json | 44 + .../v0.8/AutomationCompatibleInterface.json | 39 + .../abi/v0.8/AutomationCompatibleUtils.json | 212 + .../abi/v0.8/AutomationConsumerBenchmark.json | 212 + .../abi/v0.8/AutomationForwarder.json | 69 + .../abi/v0.8/AutomationForwarderLogic.json | 41 + .../abi/v0.8/AutomationRegistrar2_1.json | 761 + .../abi/v0.8/AutomationRegistrar2_3.json | 745 + .../abi/v0.8/AutomationRegistry2_2.json | 1367 ++ .../abi/v0.8/AutomationRegistry2_3.json | 1580 ++ .../abi/v0.8/AutomationRegistryBase2_2.json | 952 ++ .../abi/v0.8/AutomationRegistryBase2_3.json | 1180 ++ .../v0.8/AutomationRegistryBaseInterface.json | 403 + ...AutomationRegistryExecutableInterface.json | 447 + .../abi/v0.8/AutomationRegistryInterface.json | 447 + .../abi/v0.8/AutomationRegistryLogicA2_2.json | 1334 ++ .../abi/v0.8/AutomationRegistryLogicA2_3.json | 1329 ++ .../abi/v0.8/AutomationRegistryLogicB2_2.json | 1998 +++ .../abi/v0.8/AutomationRegistryLogicB2_3.json | 1672 ++ .../abi/v0.8/AutomationRegistryLogicC2_3.json | 2678 +++ .../abi/v0.8/AutomationUtils2_1.json | 302 + .../abi/v0.8/AutomationUtils2_2.json | 302 + .../abi/v0.8/AutomationUtils2_3.json | 47 + .../abi/v0.8/BaseSequencerUptimeFeed.json | 562 + .../contracts/abi/v0.8/BaseValidator.json | 314 + .../contracts/abi/v0.8/BasicConsumer.json | 211 + .../abi/v0.8/BatchBlockhashStore.json | 76 + .../abi/v0.8/BatchVRFCoordinatorV2.json | 156 + .../abi/v0.8/BatchVRFCoordinatorV2Plus.json | 161 + .../contracts/abi/v0.8/BlockhashStore.json | 52 + .../abi/v0.8/BlockhashStoreInterface.json | 21 + .../chainlink/contracts/abi/v0.8/Broken.json | 45 + .../contracts/abi/v0.8/BurnMintERC677.json | 784 + .../contracts/abi/v0.8/ByteUtil.json | 7 + .../contracts/abi/v0.8/CallWithExactGas.json | 17 + .../abi/v0.8/CallWithExactGasHelper.json | 124 + .../contracts/abi/v0.8/Callback.json | 39 + .../abi/v0.8/CapabilitiesRegistry.json | 1324 ++ .../v0.8/CapabilityConfigurationContract.json | 74 + .../contracts/abi/v0.8/ChainModuleBase.json | 90 + .../contracts/abi/v0.8/ChainReaderTester.json | 888 + .../abi/v0.8/ChainSpecificUtilHelper.json | 72 + .../contracts/abi/v0.8/Chainable.json | 30 + .../contracts/abi/v0.8/ChainlinkClient.json | 41 + .../abi/v0.8/ChainlinkClientHelper.json | 125 + .../abi/v0.8/ChainlinkClientTestHelper.json | 357 + .../abi/v0.8/ChainlinkRequestInterface.json | 78 + .../abi/v0.8/ChainlinkTestHelper.json | 125 + .../contracts/abi/v0.8/Chainlinked.json | 41 + .../abi/v0.8/ChannelConfigStore.json | 164 + .../contracts/abi/v0.8/Configurator.json | 257 + .../contracts/abi/v0.8/ConfirmedOwner.json | 84 + .../abi/v0.8/ConfirmedOwnerTestHelper.json | 91 + .../abi/v0.8/ConfirmedOwnerWithProposal.json | 89 + .../contracts/abi/v0.8/Consumer.json | 190 + .../chainlink/contracts/abi/v0.8/Counter.json | 54 + .../chainlink/contracts/abi/v0.8/Cron.json | 1218 ++ .../abi/v0.8/CronExternalTestHelper.json | 78 + .../abi/v0.8/CronInternalTestHelper.json | 115 + .../contracts/abi/v0.8/CronReceiver.json | 35 + .../contracts/abi/v0.8/CronUpkeep.json | 449 + .../abi/v0.8/CronUpkeepDelegate.json | 31 + .../contracts/abi/v0.8/CronUpkeepFactory.json | 204 + .../abi/v0.8/CronUpkeepTestHelper.json | 517 + .../v0.8/CrossDomainDelegateForwarder.json | 162 + .../abi/v0.8/CrossDomainForwarder.json | 162 + .../abi/v0.8/CrossDomainOwnable.json | 155 + .../contracts/abi/v0.8/Denominations.json | 262 + .../abi/v0.8/DestinationFeeManager.json | 805 + .../abi/v0.8/DestinationFeeManagerProxy.json | 61 + .../abi/v0.8/DestinationRewardManager.json | 554 + .../abi/v0.8/DestinationVerifier.json | 581 + .../abi/v0.8/DestinationVerifierProxy.json | 213 + .../contracts/abi/v0.8/DummyProtocol.json | 214 + .../chainlink/contracts/abi/v0.8/ECDSA.json | 29 + .../chainlink/contracts/abi/v0.8/EIP712.json | 67 + .../contracts/abi/v0.8/ENSInterface.json | 218 + .../contracts/abi/v0.8/ENSResolver.json | 21 + .../chainlink/contracts/abi/v0.8/ERC165.json | 21 + .../chainlink/contracts/abi/v0.8/ERC20.json | 310 + .../abi/v0.8/ERC20BalanceMonitor.json | 505 + .../abi/v0.8/ERC20BalanceMonitorExposed.json | 523 + .../contracts/abi/v0.8/ERC20Burnable.json | 341 + .../contracts/abi/v0.8/ERC20Mock.json | 380 + .../abi/v0.8/ERC20Mock6Decimals.json | 380 + .../contracts/abi/v0.8/ERC20Permit.json | 347 + .../chainlink/contracts/abi/v0.8/ERC677.json | 348 + .../contracts/abi/v0.8/EmptyOracle.json | 213 + .../contracts/abi/v0.8/EntryPoint.json | 1242 ++ .../contracts/abi/v0.8/EnumerableMap.json | 13 + .../abi/v0.8/EnumerableMapBytes32.json | 7 + .../contracts/abi/v0.8/ErroredVerifier.json | 340 + .../contracts/abi/v0.8/EthBalanceMonitor.json | 478 + .../abi/v0.8/EthBalanceMonitorExposed.json | 496 + .../abi/v0.8/ExecutionPrevention.json | 7 + .../abi/v0.8/ExposedChannelConfigStore.json | 183 + .../abi/v0.8/ExposedConfigurator.json | 288 + .../abi/v0.8/ExposedVRFCoordinatorV2_5.json | 2155 +++ .../ExposedVRFCoordinatorV2_5_Arbitrum.json | 1858 ++ .../ExposedVRFCoordinatorV2_5_Optimism.json | 1943 +++ .../contracts/abi/v0.8/ExposedVerifier.json | 71 + .../ExtendedVRFCoordinatorV2Interface.json | 309 + .../contracts/abi/v0.8/FeeManager.json | 698 + .../contracts/abi/v0.8/FeeManagerProxy.json | 51 + .../contracts/abi/v0.8/FeedConsumer.json | 214 + .../abi/v0.8/FeedRegistryInterface.json | 803 + .../chainlink/contracts/abi/v0.8/Flags.json | 423 + .../contracts/abi/v0.8/FlagsInterface.json | 92 + .../contracts/abi/v0.8/FlagsTestHelper.json | 64 + .../contracts/abi/v0.8/FunctionsBilling.json | 533 + .../FunctionsBillingRegistryEventsMock.json | 839 + .../contracts/abi/v0.8/FunctionsClient.json | 56 + .../abi/v0.8/FunctionsClientExample.json | 280 + .../abi/v0.8/FunctionsClientHarness.json | 460 + .../abi/v0.8/FunctionsClientTestHelper.json | 375 + .../v0.8/FunctionsClientUpgradeHelper.json | 413 + .../FunctionsClientWithEmptyCallback.json | 161 + .../abi/v0.8/FunctionsCoordinator.json | 1267 ++ .../abi/v0.8/FunctionsCoordinatorHarness.json | 1664 ++ .../v0.8/FunctionsCoordinatorTestHelper.json | 1318 ++ .../abi/v0.8/FunctionsLoadTestClient.json | 421 + .../abi/v0.8/FunctionsOracleEventsMock.json | 586 + .../contracts/abi/v0.8/FunctionsRequest.json | 35 + .../contracts/abi/v0.8/FunctionsRouter.json | 1720 ++ .../abi/v0.8/FunctionsRouterHarness.json | 1772 ++ .../abi/v0.8/FunctionsSubscriptions.json | 761 + .../v0.8/FunctionsSubscriptionsHarness.json | 887 + .../abi/v0.8/FunctionsTestHelper.json | 93 + .../abi/v0.8/FunctionsV1EventsMock.json | 957 ++ .../contracts/abi/v0.8/GasConsumer.json | 16 + .../abi/v0.8/GasGuzzlingConsumer.json | 273 + .../contracts/abi/v0.8/GasPriceOracle.json | 242 + .../contracts/abi/v0.8/GenericReceiver.json | 56 + .../contracts/abi/v0.8/GetterSetter.json | 190 + .../chainlink/contracts/abi/v0.8/Greeter.json | 117 + .../abi/v0.8/HeartbeatRequester.json | 184 + .../v0.8/IAbstractArbitrumTokenGateway.json | 163 + .../contracts/abi/v0.8/IAccessControl.json | 195 + .../contracts/abi/v0.8/IAccessController.json | 26 + .../contracts/abi/v0.8/IAccount.json | 88 + .../contracts/abi/v0.8/IAggregator.json | 229 + .../contracts/abi/v0.8/IAggregatorProxy.json | 15 + .../contracts/abi/v0.8/IArbRollupCore.json | 880 + .../chainlink/contracts/abi/v0.8/IArbSys.json | 21 + .../abi/v0.8/IArbitrumDelayedInbox.json | 407 + .../abi/v0.8/IArbitrumGatewayRouter.json | 232 + .../contracts/abi/v0.8/IArbitrumInbox.json | 326 + .../abi/v0.8/IArbitrumL1GatewayRouter.json | 304 + .../abi/v0.8/IArbitrumTokenGateway.json | 137 + .../abi/v0.8/IAuthorizedReceiver.json | 47 + .../abi/v0.8/IAutomationForwarder.json | 83 + .../abi/v0.8/IAutomationRegistryConsumer.json | 115 + .../abi/v0.8/IAutomationRegistryMaster.json | 2725 +++ .../v0.8/IAutomationRegistryMaster2_3.json | 3606 ++++ .../abi/v0.8/IAutomationV21PlusCommon.json | 1441 ++ .../chainlink/contracts/abi/v0.8/IBridge.json | 227 + .../contracts/abi/v0.8/IBridgeAdapter.json | 131 + .../contracts/abi/v0.8/IBurnMintERC20.json | 252 + .../abi/v0.8/ICapabilityConfiguration.json | 55 + .../contracts/abi/v0.8/IChainModule.json | 90 + .../abi/v0.8/IChannelConfigStore.json | 44 + .../contracts/abi/v0.8/IConfigurator.json | 112 + .../abi/v0.8/ICrossDomainOwnable.json | 73 + .../abi/v0.8/IDelegateForwarder.json | 20 + .../abi/v0.8/IDestinationFeeManager.json | 236 + .../abi/v0.8/IDestinationRewardManager.json | 197 + .../abi/v0.8/IDestinationVerifier.json | 147 + .../v0.8/IDestinationVerifierFeeManager.json | 107 + .../abi/v0.8/IDestinationVerifierProxy.json | 108 + .../IDestinationVerifierProxyVerifier.json | 105 + .../contracts/abi/v0.8/IERC1155Errors.json | 104 + .../chainlink/contracts/abi/v0.8/IERC165.json | 21 + .../chainlink/contracts/abi/v0.8/IERC20.json | 185 + .../contracts/abi/v0.8/IERC20Errors.json | 88 + .../contracts/abi/v0.8/IERC20Metadata.json | 224 + .../contracts/abi/v0.8/IERC20Permit.json | 77 + .../contracts/abi/v0.8/IERC5267.json | 51 + .../chainlink/contracts/abi/v0.8/IERC677.json | 62 + .../contracts/abi/v0.8/IERC677Receiver.json | 25 + .../contracts/abi/v0.8/IERC721Errors.json | 105 + .../contracts/abi/v0.8/IEntryPoint.json | 1065 ++ .../contracts/abi/v0.8/IFeeManager.json | 250 + .../chainlink/contracts/abi/v0.8/IFlags.json | 118 + .../contracts/abi/v0.8/IForwarder.json | 20 + .../contracts/abi/v0.8/IFunctionsBilling.json | 150 + .../contracts/abi/v0.8/IFunctionsClient.json | 25 + .../abi/v0.8/IFunctionsCoordinator.json | 187 + .../contracts/abi/v0.8/IFunctionsRouter.json | 338 + .../abi/v0.8/IFunctionsSubscriptions.json | 463 + .../contracts/abi/v0.8/IGasBoundCaller.json | 25 + .../contracts/abi/v0.8/IGasToken.json | 59 + .../chainlink/contracts/abi/v0.8/IInbox.json | 383 + .../abi/v0.8/IKeeperRegistryMaster.json | 2655 +++ .../abi/v0.8/IL2ArbitrumGateway.json | 322 + .../abi/v0.8/IL2ArbitrumMessenger.json | 33 + .../contracts/abi/v0.8/IL2GatewayRouter.json | 36 + .../contracts/abi/v0.8/IL2StandardBridge.json | 35 + .../contracts/abi/v0.8/ILinkAvailable.json | 15 + .../abi/v0.8/ILiquidityContainer.json | 66 + .../contracts/abi/v0.8/ILiquidityManager.json | 55 + .../contracts/abi/v0.8/ILogAutomation.json | 86 + .../contracts/abi/v0.8/IMessageProvider.json | 34 + .../contracts/abi/v0.8/INodeInterface.json | 320 + .../abi/v0.8/IOffchainAggregator.json | 15 + .../v0.8/IOptimismCrossDomainMessenger.json | 77 + .../abi/v0.8/IOptimismDisputeGameFactory.json | 71 + .../abi/v0.8/IOptimismL1StandardBridge.json | 25 + .../abi/v0.8/IOptimismL2OutputOracle.json | 57 + .../v0.8/IOptimismL2ToL1MessagePasser.json | 51 + .../abi/v0.8/IOptimismMintableERC20.json | 83 + .../v0.8/IOptimismMintableERC20Minimal.json | 47 + .../contracts/abi/v0.8/IOptimismPortal.json | 142 + .../contracts/abi/v0.8/IOptimismPortal2.json | 28 + .../abi/v0.8/IOptimismStandardBridge.json | 83 + .../chainlink/contracts/abi/v0.8/IOutbox.json | 55 + .../contracts/abi/v0.8/IOwnable.json | 35 + .../abi/v0.8/IOwnableFunctionsRouter.json | 371 + .../contracts/abi/v0.8/IPaymaster.json | 116 + .../contracts/abi/v0.8/IReceiver.json | 20 + .../contracts/abi/v0.8/IRewardManager.json | 184 + .../chainlink/contracts/abi/v0.8/IRouter.json | 239 + .../abi/v0.8/IScrollL1GasPriceOracle.json | 131 + .../contracts/abi/v0.8/IScrollMessenger.json | 145 + .../chainlink/contracts/abi/v0.8/ISemver.json | 15 + .../abi/v0.8/ISequencerUptimeFeed.json | 20 + .../contracts/abi/v0.8/IStakeManager.json | 244 + .../contracts/abi/v0.8/ISystemContext.json | 41 + .../abi/v0.8/ITermsOfServiceAllowList.json | 191 + .../contracts/abi/v0.8/ITypeAndVersion.json | 15 + .../contracts/abi/v0.8/IVRFCoordinatorV2.json | 375 + .../abi/v0.8/IVRFCoordinatorV2Plus.json | 246 + .../v0.8/IVRFCoordinatorV2PlusFulfill.json | 110 + .../v0.8/IVRFCoordinatorV2PlusInternal.json | 490 + .../v0.8/IVRFCoordinatorV2PlusMigration.json | 15 + .../v0.8/IVRFMigratableConsumerV2Plus.json | 28 + .../abi/v0.8/IVRFSubscriptionV2Plus.json | 195 + .../contracts/abi/v0.8/IVRFV2PlusMigrate.json | 20 + .../contracts/abi/v0.8/IVRFV2PlusWrapper.json | 181 + .../contracts/abi/v0.8/IVerifier.json | 300 + .../abi/v0.8/IVerifierFeeManager.json | 97 + .../contracts/abi/v0.8/IVerifierProxy.json | 21 + .../chainlink/contracts/abi/v0.8/IWERC20.json | 22 + .../contracts/abi/v0.8/IWithdrawal.json | 33 + .../contracts/abi/v0.8/IWrappedNative.json | 205 + .../IZKSyncAutomationRegistryMaster2_3.json | 3567 ++++ .../abi/v0.8/KeeperCompatibleTestHelper.json | 51 + .../contracts/abi/v0.8/KeeperConsumer.json | 94 + .../abi/v0.8/KeeperConsumerPerformance.json | 289 + .../contracts/abi/v0.8/KeeperRegistrar.json | 594 + .../abi/v0.8/KeeperRegistrar1_2Mock.json | 491 + .../abi/v0.8/KeeperRegistrar2_0.json | 654 + .../contracts/abi/v0.8/KeeperRegistry1_2.json | 1486 ++ .../contracts/abi/v0.8/KeeperRegistry1_3.json | 1744 ++ .../contracts/abi/v0.8/KeeperRegistry2_0.json | 1951 +++ .../contracts/abi/v0.8/KeeperRegistry2_1.json | 1349 ++ .../abi/v0.8/KeeperRegistryBase1_3.json | 857 + .../abi/v0.8/KeeperRegistryBase2_0.json | 882 + .../abi/v0.8/KeeperRegistryBase2_1.json | 944 ++ ...RegistryCheckUpkeepGasUsageWrapper1_2.json | 131 + ...stryCheckUpkeepGasUsageWrapper1_2Mock.json | 172 + .../abi/v0.8/KeeperRegistryLogic1_3.json | 1208 ++ .../abi/v0.8/KeeperRegistryLogic2_0.json | 1290 ++ .../abi/v0.8/KeeperRegistryLogicA2_1.json | 1326 ++ .../abi/v0.8/KeeperRegistryLogicB2_1.json | 1938 +++ .../abi/v0.8/KeepersVRFConsumer.json | 242 + .../abi/v0.8/KeystoneFeedsConsumer.json | 215 + .../v0.8/KeystoneFeedsPermissionHandler.json | 185 + .../contracts/abi/v0.8/KeystoneForwarder.json | 585 + .../chainlink/contracts/abi/v0.8/L1Block.json | 347 + .../abi/v0.8/LinkAvailableBalanceMonitor.json | 946 ++ .../contracts/abi/v0.8/LinkToken.json | 763 + .../abi/v0.8/LinkTokenInterface.json | 245 + .../contracts/abi/v0.8/LinkTokenReceiver.json | 38 + .../abi/v0.8/LinkTokenTestHelper.json | 763 + .../contracts/abi/v0.8/LiquidityManager.json | 1147 ++ .../abi/v0.8/LiquidityManagerHelper.json | 1165 ++ .../contracts/abi/v0.8/LogEmitter.json | 122 + .../abi/v0.8/LogTriggeredStreamsLookup.json | 419 + .../contracts/abi/v0.8/LogUpkeepCounter.json | 321 + .../abi/v0.8/MaliciousChainlinked.json | 41 + .../v0.8/MaliciousConfigurationContract.json | 85 + .../contracts/abi/v0.8/MaliciousConsumer.json | 194 + .../abi/v0.8/MaliciousMultiWordConsumer.json | 194 + .../abi/v0.8/MaliciousReportReceiver.json | 71 + .../abi/v0.8/MaliciousRequester.json | 167 + .../abi/v0.8/MaliciousRevertingReceiver.json | 39 + .../chainlink/contracts/abi/v0.8/Math.json | 7 + .../contracts/abi/v0.8/MercuryRegistry.json | 594 + .../abi/v0.8/MercuryRegistryBatchUpkeep.json | 306 + .../MigratableKeeperRegistryInterface.json | 46 + .../MigratableKeeperRegistryInterfaceV2.json | 46 + .../contracts/abi/v0.8/MockAggregator.json | 67 + .../abi/v0.8/MockAggregatorProxy.json | 39 + .../abi/v0.8/MockAggregatorV2V3.json | 240 + .../abi/v0.8/MockAggregatorValidator.json | 84 + .../contracts/abi/v0.8/MockArbGasInfo.json | 53 + .../contracts/abi/v0.8/MockArbSys.json | 34 + .../contracts/abi/v0.8/MockArbitrumInbox.json | 462 + .../contracts/abi/v0.8/MockBridgehub.json | 795 + .../abi/v0.8/MockETHLINKAggregator.json | 137 + .../abi/v0.8/MockETHUSDAggregator.json | 150 + .../abi/v0.8/MockGasBoundCaller.json | 36 + .../abi/v0.8/MockKeeperRegistry2_1.json | 138 + .../abi/v0.8/MockL1BridgeAdapter.json | 322 + .../abi/v0.8/MockL2BridgeAdapter.json | 131 + .../contracts/abi/v0.8/MockLinkToken.json | 135 + .../abi/v0.8/MockOVMCrossDomainMessenger.json | 101 + .../abi/v0.8/MockOVMGasPriceOracle.json | 40 + .../abi/v0.8/MockOffchainAggregator.json | 41 + .../MockOptimismL1CrossDomainMessenger.json | 238 + .../MockOptimismL2CrossDomainMessenger.json | 146 + .../contracts/abi/v0.8/MockReceiver.json | 35 + .../v0.8/MockScrollCrossDomainMessenger.json | 169 + .../MockScrollL1CrossDomainMessenger.json | 284 + .../abi/v0.8/MockScrollL1MessageQueue.json | 302 + .../MockScrollL2CrossDomainMessenger.json | 195 + .../contracts/abi/v0.8/MockUpkeep.json | 218 + .../contracts/abi/v0.8/MockV3Aggregator.json | 297 + .../abi/v0.8/MockZKSyncSystemContext.json | 41 + .../contracts/abi/v0.8/MultiSend.json | 20 + .../contracts/abi/v0.8/MultiWordConsumer.json | 432 + .../contracts/abi/v0.8/NoOpOCR3.json | 396 + .../contracts/abi/v0.8/OCR2Abstract.json | 212 + .../contracts/abi/v0.8/OCR2Base.json | 318 + .../contracts/abi/v0.8/OCR3Abstract.json | 189 + .../contracts/abi/v0.8/OCR3Base.json | 391 + .../contracts/abi/v0.8/OCR3Capability.json | 299 + .../contracts/abi/v0.8/OCR3Helper.json | 463 + .../abi/v0.8/OVM_GasPriceOracle.json | 298 + .../abi/v0.8/OpStackBurnMintERC677.json | 820 + .../contracts/abi/v0.8/Operator.json | 738 + .../contracts/abi/v0.8/OperatorFactory.json | 176 + .../contracts/abi/v0.8/OperatorInterface.json | 287 + .../v0.8/OptimismCrossDomainForwarder.json | 204 + .../abi/v0.8/OptimismCrossDomainGovernor.json | 222 + .../abi/v0.8/OptimismL1BridgeAdapter.json | 200 + .../v0.8/OptimismL1BridgeAdapterEncoder.json | 168 + .../contracts/abi/v0.8/OptimismL1Fees.json | 158 + .../abi/v0.8/OptimismL2BridgeAdapter.json | 172 + .../contracts/abi/v0.8/OptimismModule.json | 90 + .../contracts/abi/v0.8/OptimismModuleV2.json | 216 + .../abi/v0.8/OptimismSequencerUptimeFeed.json | 583 + .../contracts/abi/v0.8/OptimismValidator.json | 335 + .../contracts/abi/v0.8/OracleInterface.json | 77 + .../contracts/abi/v0.8/OwnerIsCreator.json | 78 + .../contracts/abi/v0.8/Pausable.json | 51 + .../contracts/abi/v0.8/Paymaster.json | 359 + .../abi/v0.8/PerformDataChecker.json | 89 + .../abi/v0.8/PermissionedForwardProxy.json | 183 + .../contracts/abi/v0.8/PoRAddressList.json | 39 + .../contracts/abi/v0.8/PointerInterface.json | 15 + .../chainlink/contracts/abi/v0.8/Proxy.json | 10 + .../contracts/abi/v0.8/ReceiveEmitter.json | 25 + .../abi/v0.8/ReceiveFallbackEmitter.json | 25 + .../contracts/abi/v0.8/ReceiveReverter.json | 6 + .../contracts/abi/v0.8/Receiver.json | 76 + .../contracts/abi/v0.8/ReportEncoder.json | 124 + .../contracts/abi/v0.8/RewardManager.json | 535 + .../contracts/abi/v0.8/Routable.json | 30 + .../lib/chainlink/contracts/abi/v0.8/SCA.json | 235 + .../contracts/abi/v0.8/SafeCast.json | 56 + .../contracts/abi/v0.8/SafeERC20.json | 34 + .../abi/v0.8/ScrollCrossDomainForwarder.json | 204 + .../abi/v0.8/ScrollCrossDomainGovernor.json | 222 + .../contracts/abi/v0.8/ScrollModule.json | 216 + .../abi/v0.8/ScrollSequencerUptimeFeed.json | 588 + .../contracts/abi/v0.8/ScrollValidator.json | 353 + .../contracts/abi/v0.8/SenderCreator.json | 21 + .../contracts/abi/v0.8/ShortStrings.json | 18 + .../abi/v0.8/SimpleLogUpkeepCounter.json | 445 + .../abi/v0.8/SimpleReadAccessController.json | 188 + .../abi/v0.8/SimpleWriteAccessController.json | 193 + .../abi/v0.8/SmartContractAccountFactory.json | 44 + .../abi/v0.8/SmartContractAccountHelper.json | 171 + .../abi/v0.8/SortedSetValidationUtil.json | 34 + .../contracts/abi/v0.8/StakeManager.json | 287 + .../StreamsLookupCompatibleInterface.json | 91 + .../abi/v0.8/StreamsLookupUpkeep.json | 448 + .../chainlink/contracts/abi/v0.8/Strings.json | 18 + .../contracts/abi/v0.8/SubscriptionAPI.json | 843 + .../abi/v0.8/TermsOfServiceAllowList.json | 466 + .../abi/v0.8/TrustedBlockhashStore.json | 235 + .../abi/v0.8/TypeAndVersionInterface.json | 15 + .../contracts/abi/v0.8/UpkeepAutoFunder.json | 261 + .../abi/v0.8/UpkeepBalanceMonitor.json | 524 + .../contracts/abi/v0.8/UpkeepCounter.json | 201 + .../contracts/abi/v0.8/UpkeepCounterNew.json | 427 + .../contracts/abi/v0.8/UpkeepMock.json | 239 + .../v0.8/UpkeepPerformCounterRestrictive.json | 266 + .../contracts/abi/v0.8/UpkeepReverter.json | 44 + .../contracts/abi/v0.8/UpkeepTranscoder.json | 49 + .../abi/v0.8/UpkeepTranscoder3_0.json | 49 + .../abi/v0.8/UpkeepTranscoder4_0.json | 49 + .../abi/v0.8/UpkeepTranscoder5_0.json | 49 + .../abi/v0.8/UpkeepTranscoderInterface.json | 31 + .../abi/v0.8/UpkeepTranscoderInterfaceV2.json | 31 + .../contracts/abi/v0.8/VRFConsumer.json | 86 + .../contracts/abi/v0.8/VRFConsumerBase.json | 20 + .../contracts/abi/v0.8/VRFConsumerBaseV2.json | 36 + .../abi/v0.8/VRFConsumerBaseV2Plus.json | 172 + .../v0.8/VRFConsumerBaseV2Upgradeable.json | 49 + .../contracts/abi/v0.8/VRFConsumerV2.json | 188 + .../contracts/abi/v0.8/VRFConsumerV2Plus.json | 336 + .../VRFConsumerV2PlusUpgradeableExample.json | 229 + .../v0.8/VRFConsumerV2UpgradeableExample.json | 229 + .../abi/v0.8/VRFCoordinatorMock.json | 103 + .../abi/v0.8/VRFCoordinatorTestV2.json | 1463 ++ .../abi/v0.8/VRFCoordinatorTestV2_5.json | 1750 ++ .../contracts/abi/v0.8/VRFCoordinatorV2.json | 100 + .../abi/v0.8/VRFCoordinatorV2Interface.json | 215 + .../abi/v0.8/VRFCoordinatorV2Mock.json | 765 + .../VRFCoordinatorV2PlusUpgradedVersion.json | 1778 ++ .../v0.8/VRFCoordinatorV2Plus_V2Example.json | 329 + .../abi/v0.8/VRFCoordinatorV2TestHelper.json | 78 + .../abi/v0.8/VRFCoordinatorV2_5.json | 1763 ++ .../abi/v0.8/VRFCoordinatorV2_5Mock.json | 1180 ++ .../abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json | 1763 ++ .../abi/v0.8/VRFCoordinatorV2_5_Optimism.json | 1848 ++ .../abi/v0.8/VRFExternalSubOwnerExample.json | 130 + .../abi/v0.8/VRFLoadTestExternalSubOwner.json | 190 + .../v0.8/VRFLoadTestOwnerlessConsumer.json | 90 + .../contracts/abi/v0.8/VRFLogEmitter.json | 164 + .../abi/v0.8/VRFMaliciousConsumerV2.json | 155 + .../abi/v0.8/VRFMaliciousConsumerV2Plus.json | 278 + .../abi/v0.8/VRFMockETHLINKAggregator.json | 150 + .../contracts/abi/v0.8/VRFOwner.json | 455 + .../abi/v0.8/VRFOwnerlessConsumerExample.json | 90 + .../abi/v0.8/VRFRequestIDBaseTestHelper.json | 60 + .../abi/v0.8/VRFSingleConsumerExample.json | 208 + .../v0.8/VRFSubscriptionBalanceMonitor.json | 606 + .../VRFSubscriptionBalanceMonitorExposed.json | 624 + .../contracts/abi/v0.8/VRFTestHelper.json | 474 + .../abi/v0.8/VRFV2LoadTestWithMetrics.json | 370 + .../abi/v0.8/VRFV2OwnerTestConsumer.json | 406 + .../contracts/abi/v0.8/VRFV2PlusClient.json | 15 + .../abi/v0.8/VRFV2PlusConsumerExample.json | 392 + .../VRFV2PlusExternalSubOwnerExample.json | 258 + .../v0.8/VRFV2PlusLoadTestWithMetrics.json | 476 + .../abi/v0.8/VRFV2PlusMaliciousMigrator.json | 39 + .../abi/v0.8/VRFV2PlusRevertingExample.json | 324 + .../v0.8/VRFV2PlusSingleConsumerExample.json | 354 + .../contracts/abi/v0.8/VRFV2PlusWrapper.json | 954 ++ .../v0.8/VRFV2PlusWrapperConsumerBase.json | 75 + .../v0.8/VRFV2PlusWrapperConsumerExample.json | 366 + .../VRFV2PlusWrapperLoadTestConsumer.json | 513 + .../abi/v0.8/VRFV2PlusWrapper_Arbitrum.json | 954 ++ .../abi/v0.8/VRFV2PlusWrapper_Optimism.json | 1050 ++ .../contracts/abi/v0.8/VRFV2ProxyAdmin.json | 151 + .../abi/v0.8/VRFV2RevertingExample.json | 188 + .../VRFV2TransparentUpgradeableProxy.json | 76 + .../contracts/abi/v0.8/VRFV2Wrapper.json | 495 + .../abi/v0.8/VRFV2WrapperConsumerBase.json | 20 + .../abi/v0.8/VRFV2WrapperConsumerExample.json | 246 + .../abi/v0.8/VRFV2WrapperInterface.json | 58 + .../v0.8/VRFV2WrapperLoadTestConsumer.json | 387 + .../VRFV2WrapperOutOfGasConsumerExample.json | 136 + .../VRFV2WrapperRevertingConsumerExample.json | 136 + .../VRFV2WrapperUnderFundingConsumer.json | 112 + .../contracts/abi/v0.8/VRFv2Consumer.json | 275 + .../contracts/abi/v0.8/ValidatorProxy.json | 323 + .../abi/v0.8/VerifiableLoadBase.json | 1524 ++ .../v0.8/VerifiableLoadLogTriggerUpkeep.json | 1757 ++ .../VerifiableLoadStreamsLookupUpkeep.json | 1666 ++ .../abi/v0.8/VerifiableLoadUpkeep.json | 1577 ++ .../contracts/abi/v0.8/Verifier.json | 714 + .../contracts/abi/v0.8/VerifierProxy.json | 435 + .../contracts/abi/v0.8/WERC20Mock.json | 375 + .../chainlink/contracts/abi/v0.8/WETH9.json | 309 + .../abi/v0.8/ZKSyncAutomationForwarder.json | 80 + .../abi/v0.8/ZKSyncAutomationRegistry2_3.json | 1580 ++ .../v0.8/ZKSyncAutomationRegistryBase2_3.json | 1180 ++ .../ZKSyncAutomationRegistryLogicA2_3.json | 1329 ++ .../ZKSyncAutomationRegistryLogicB2_3.json | 1672 ++ .../ZKSyncAutomationRegistryLogicC2_3.json | 2639 +++ .../abi/v0.8/ZKSyncSequencerUptimeFeed.json | 578 + .../contracts/abi/v0.8/ZKSyncValidator.json | 402 + .../abi/v0.8/iOVM_CrossDomainMessenger.json | 77 + .../lib/chainlink/contracts/package.json | 84 + .../contracts/src/v0.8/ChainSpecificUtil.sol | 163 + .../src/v0.8/ChainSpecificUtil_v0_8_6.sol | 163 + .../contracts/src/v0.8/Chainlink.sol | 116 + .../contracts/src/v0.8/ChainlinkClient.sol | 318 + .../contracts/src/v0.8/Denominations.sol | 28 + .../chainlink/contracts/src/v0.8/Flags.sol | 124 + .../src/v0.8/PermissionedForwardProxy.sol | 65 + .../contracts/src/v0.8/ValidatorProxy.sol | 230 + .../src/v0.8/automation/AutomationBase.sol | 26 + .../v0.8/automation/AutomationCompatible.sol | 7 + .../automation/AutomationCompatibleUtils.sol | 17 + .../v0.8/automation/AutomationForwarder.sol | 92 + .../automation/AutomationForwarderLogic.sol | 24 + .../src/v0.8/automation/Chainable.sol | 61 + .../v0.8/automation/ExecutionPrevention.sol | 26 + .../v0.8/automation/HeartbeatRequester.sol | 72 + .../src/v0.8/automation/KeeperBase.sol | 7 + .../src/v0.8/automation/KeeperCompatible.sol | 11 + .../contracts/src/v0.8/automation/README.md | 43 + .../src/v0.8/automation/UpkeepFormat.sol | 13 + .../src/v0.8/automation/UpkeepTranscoder.sol | 44 + .../automation/ZKSyncAutomationForwarder.sol | 107 + .../v0.8/automation/chains/ArbitrumModule.sol | 51 + .../automation/chains/ChainModuleBase.sol | 37 + .../v0.8/automation/chains/OptimismModule.sol | 53 + .../automation/chains/OptimismModuleV2.sol | 78 + .../v0.8/automation/chains/ScrollModule.sol | 78 + .../v0.8/automation/dev/MercuryRegistry.sol | 320 + .../dev/MercuryRegistryBatchUpkeep.sol | 88 + .../AutomationCompatibleInterface.sol | 42 + .../interfaces/IAutomationForwarder.sol | 15 + .../IAutomationRegistryConsumer.sol | 24 + .../interfaces/IAutomationV21PlusCommon.sol | 272 + .../automation/interfaces/IChainModule.sol | 42 + .../automation/interfaces/ILogAutomation.sol | 64 + .../interfaces/KeeperCompatibleInterface.sol | 7 + .../MigratableKeeperRegistryInterface.sol | 26 + .../MigratableKeeperRegistryInterfaceV2.sol | 24 + .../StreamsLookupCompatibleInterface.sol | 34 + .../interfaces/UpkeepTranscoderInterface.sol | 13 + .../UpkeepTranscoderInterfaceV2.sol | 11 + .../v1_2/AutomationRegistryInterface1_2.sol | 123 + .../v1_2/KeeperRegistryInterface1_2.sol | 13 + .../v1_3/AutomationRegistryInterface1_3.sol | 156 + .../v2_0/AutomationRegistryInterface2_0.sol | 185 + .../interfaces/v2_1/IKeeperRegistryMaster.sol | 315 + .../v2_2/IAutomationRegistryMaster.sol | 341 + .../v2_3/IAutomationRegistryMaster2_3.sol | 435 + .../interfaces/v2_3/IWrappedNative.sol | 10 + .../interfaces/zksync/IGasBoundCaller.sol | 8 + .../interfaces/zksync/ISystemContext.sol | 10 + .../IZKSyncAutomationRegistryMaster2_3.sol | 441 + .../automation/libraries/external/Cron.sol | 78 + .../automation/libraries/internal/Cron.sol | 544 + .../automation/mocks/ERC20Mock6Decimals.sol | 17 + .../mocks/KeeperRegistrar1_2Mock.sol | 122 + ...istryCheckUpkeepGasUsageWrapper1_2Mock.sol | 32 + .../v0.8/automation/mocks/MockAggregator.sol | 22 + .../automation/mocks/MockAggregatorProxy.sol | 20 + .../mocks/MockKeeperRegistry2_1.sol | 31 + .../src/v0.8/automation/mocks/MockUpkeep.sol | 53 + .../automation/test/AutomationForwarder.t.sol | 74 + .../test/AutomationRegistry2_2.t.sol | 198 + .../src/v0.8/automation/test/BaseTest.t.sol | 14 + .../automation/test/HeartbeatRequester.t.sol | 112 + .../automation/test/MercuryRegistry.t.sol | 336 + .../src/v0.8/automation/test/WETH9.sol | 93 + .../test/v2_3/AutomationRegistrar2_3.t.sol | 409 + .../test/v2_3/AutomationRegistry2_3.t.sol | 2753 +++ .../v0.8/automation/test/v2_3/BaseTest.t.sol | 503 + .../test/v2_3_zksync/BaseTest.t.sol | 500 + .../ZKSyncAutomationRegistry2_3.t.sol | 2772 +++ .../automation/testhelpers/CronTestHelper.sol | 100 + .../testhelpers/CronUpkeepTestHelper.sol | 41 + .../automation/testhelpers/DummyProtocol.sol | 87 + .../automation/testhelpers/KeeperConsumer.sol | 26 + .../testhelpers/KeeperConsumerPerformance.sol | 88 + .../testhelpers/LogTriggeredStreamsLookup.sol | 155 + .../testhelpers/LogUpkeepCounter.sol | 103 + .../testhelpers/MockETHUSDAggregator.sol | 53 + .../testhelpers/PerformDataChecker.sol | 29 + .../testhelpers/SimpleLogUpkeepCounter.sol | 143 + .../testhelpers/UpkeepAutoFunder.sol | 60 + .../automation/testhelpers/UpkeepCounter.sol | 58 + .../testhelpers/UpkeepCounterNew.sol | 126 + .../automation/testhelpers/UpkeepMock.sol | 81 + .../UpkeepPerformCounterRestrictive.sol | 85 + .../automation/testhelpers/UpkeepReverter.sol | 17 + .../v0.8/automation/upkeeps/CronUpkeep.sol | 263 + .../automation/upkeeps/CronUpkeepDelegate.sol | 71 + .../automation/upkeeps/CronUpkeepFactory.sol | 80 + .../upkeeps/ERC20BalanceMonitor.sol | 279 + .../automation/upkeeps/EthBalanceMonitor.sol | 254 + .../upkeeps/LinkAvailableBalanceMonitor.sol | 480 + .../upkeeps/UpkeepBalanceMonitor.sol | 258 + .../automation/v1_2/KeeperRegistrar1_2.sol | 425 + .../automation/v1_2/KeeperRegistry1_2.sol | 909 + ...rRegistryCheckUpkeepGasUsageWrapper1_2.sol | 48 + .../automation/v1_3/KeeperRegistry1_3.sol | 548 + .../automation/v1_3/KeeperRegistryBase1_3.sol | 304 + .../v1_3/KeeperRegistryLogic1_3.sol | 404 + .../automation/v2_0/KeeperRegistrar2_0.sol | 489 + .../automation/v2_0/KeeperRegistry2_0.sol | 1012 ++ .../automation/v2_0/KeeperRegistryBase2_0.sol | 479 + .../v2_0/KeeperRegistryLogic2_0.sol | 474 + .../automation/v2_0/UpkeepTranscoder3_0.sol | 104 + .../v2_1/AutomationRegistrar2_1.sol | 532 + .../automation/v2_1/AutomationUtils2_1.sol | 41 + .../automation/v2_1/KeeperRegistry2_1.sol | 397 + .../automation/v2_1/KeeperRegistryBase2_1.sol | 861 + .../v2_1/KeeperRegistryLogicA2_1.sol | 438 + .../v2_1/KeeperRegistryLogicB2_1.sol | 517 + .../src/v0.8/automation/v2_1/LICENSE | 56 + .../src/v0.8/automation/v2_1/README.md | 40 + .../automation/v2_1/UpkeepTranscoder4_0.sol | 176 + .../automation/v2_2/AutomationRegistry2_2.sol | 416 + .../v2_2/AutomationRegistryBase2_2.sol | 861 + .../v2_2/AutomationRegistryLogicA2_2.sol | 433 + .../v2_2/AutomationRegistryLogicB2_2.sol | 540 + .../automation/v2_2/AutomationUtils2_2.sol | 41 + .../src/v0.8/automation/v2_2/LICENSE | 57 + .../src/v0.8/automation/v2_2/README.md | 40 + .../v2_3/AutomationRegistrar2_3.sol | 442 + .../automation/v2_3/AutomationRegistry2_3.sol | 391 + .../v2_3/AutomationRegistryBase2_3.sol | 1216 ++ .../v2_3/AutomationRegistryLogicA2_3.sol | 283 + .../v2_3/AutomationRegistryLogicB2_3.sol | 449 + .../v2_3/AutomationRegistryLogicC2_3.sol | 638 + .../automation/v2_3/AutomationUtils2_3.sol | 17 + .../src/v0.8/automation/v2_3/LICENSE | 57 + .../automation/v2_3/UpkeepTranscoder5_0.sol | 46 + .../ZKSyncAutomationRegistry2_3.sol | 386 + .../ZKSyncAutomationRegistryBase2_3.sol | 1197 ++ .../ZKSyncAutomationRegistryLogicA2_3.sol | 283 + .../ZKSyncAutomationRegistryLogicB2_3.sol | 449 + .../ZKSyncAutomationRegistryLogicC2_3.sol | 626 + .../contracts/src/v0.8/ccip/FeeQuoter.sol | 1020 ++ .../contracts/src/v0.8/ccip/LICENSE-MIT.md | 21 + .../contracts/src/v0.8/ccip/LICENSE.md | 56 + .../v0.8/ccip/MultiAggregateRateLimiter.sol | 281 + .../contracts/src/v0.8/ccip/NonceManager.sol | 158 + .../contracts/src/v0.8/ccip/Router.sol | 298 + .../ccip/applications/CCIPClientExample.sol | 175 + .../v0.8/ccip/applications/CCIPReceiver.sol | 67 + .../ccip/applications/DefensiveExample.sol | 114 + .../ccip/applications/EtherSenderReceiver.sol | 184 + .../v0.8/ccip/applications/PingPongDemo.sol | 130 + .../src/v0.8/ccip/capability/CCIPHome.sol | 624 + .../interfaces/IAny2EVMMessageReceiver.sol | 17 + .../v0.8/ccip/interfaces/IAny2EVMOffRamp.sol | 11 + .../ccip/interfaces/ICapabilitiesRegistry.sol | 35 + .../src/v0.8/ccip/interfaces/ICommitStore.sol | 17 + .../v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol | 17 + .../ccip/interfaces/IEVM2AnyOnRampClient.sol | 45 + .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 46 + .../v0.8/ccip/interfaces/IGetCCIPAdmin.sol | 8 + .../ccip/interfaces/IMessageInterceptor.sol | 24 + .../v0.8/ccip/interfaces/INonceManager.sol | 23 + .../src/v0.8/ccip/interfaces/IOwner.sol | 8 + .../src/v0.8/ccip/interfaces/IPool.sol | 41 + .../v0.8/ccip/interfaces/IPoolPriorTo1_5.sol | 46 + .../v0.8/ccip/interfaces/IPriceRegistry.sol | 70 + .../src/v0.8/ccip/interfaces/IRMN.sol | 25 + .../src/v0.8/ccip/interfaces/IRMNRemote.sol | 41 + .../src/v0.8/ccip/interfaces/IRouter.sol | 37 + .../v0.8/ccip/interfaces/IRouterClient.sol | 39 + .../ccip/interfaces/ITokenAdminRegistry.sol | 14 + .../v0.8/ccip/interfaces/IWrappedNative.sol | 12 + .../interfaces/automation/ILinkAvailable.sol | 8 + .../encodingutils/ICCIPEncodingUtils.sol | 25 + .../src/v0.8/ccip/libraries/Client.sol | 59 + .../src/v0.8/ccip/libraries/Internal.sol | 275 + .../v0.8/ccip/libraries/MerkleMultiProof.sol | 113 + .../src/v0.8/ccip/libraries/Pool.sol | 57 + .../src/v0.8/ccip/libraries/RateLimiter.sol | 159 + .../ccip/libraries/USDPriceWith18Decimals.sol | 45 + .../src/v0.8/ccip/ocr/MultiOCR3Base.sol | 335 + .../src/v0.8/ccip/offRamp/OffRamp.sol | 1044 ++ .../contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 526 + .../v0.8/ccip/pools/BurnFromMintTokenPool.sol | 40 + .../src/v0.8/ccip/pools/BurnMintTokenPool.sol | 32 + .../ccip/pools/BurnMintTokenPoolAbstract.sol | 45 + .../ccip/pools/BurnWithFromMintTokenPool.sol | 42 + .../v0.8/ccip/pools/LockReleaseTokenPool.sol | 139 + .../src/v0.8/ccip/pools/TokenPool.sol | 464 + .../USDC/HybridLockReleaseUSDCTokenPool.sol | 261 + .../ccip/pools/USDC/IMessageTransmitter.sol | 46 + .../v0.8/ccip/pools/USDC/ITokenMessenger.sol | 65 + .../ccip/pools/USDC/USDCBridgeMigrator.sol | 162 + .../v0.8/ccip/pools/USDC/USDCTokenPool.sol | 232 + .../contracts/src/v0.8/ccip/rmn/ARMProxy.sol | 77 + .../contracts/src/v0.8/ccip/rmn/RMNHome.sol | 395 + .../contracts/src/v0.8/ccip/rmn/RMNRemote.sol | 261 + .../src/v0.8/ccip/test/BaseTest.t.sol | 151 + .../src/v0.8/ccip/test/NonceManager.t.sol | 520 + .../contracts/src/v0.8/ccip/test/README.md | 89 + .../src/v0.8/ccip/test/TokenSetup.t.sol | 178 + .../contracts/src/v0.8/ccip/test/WETH9.sol | 84 + .../test/applications/DefensiveExample.t.sol | 97 + .../applications/EtherSenderReceiver.t.sol | 724 + .../test/applications/ImmutableExample.t.sol | 61 + .../ccip/test/applications/PingPongDemo.t.sol | 122 + .../ccip/test/attacks/onRamp/FacadeClient.sol | 56 + .../onRamp/OnRampTokenPoolReentrancy.t.sol | 82 + .../onRamp/ReentrantMaliciousTokenPool.sol | 46 + .../v0.8/ccip/test/capability/CCIPHome.t.sol | 969 ++ .../src/v0.8/ccip/test/e2e/End2End.t.sol | 305 + .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 2251 +++ .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 442 + .../test/helpers/BurnMintERC677Helper.sol | 20 + .../test/helpers/BurnMintMultiTokenPool.sol | 50 + .../v0.8/ccip/test/helpers/CCIPHomeHelper.sol | 22 + .../ccip/test/helpers/ERC20RebasingHelper.sol | 31 + .../test/helpers/EVM2EVMOffRampHelper.sol | 25 + .../helpers/EtherSenderReceiverHelper.sol | 29 + .../ccip/test/helpers/FeeQuoterHelper.sol | 80 + .../ccip/test/helpers/IgnoreContractSize.sol | 10 + .../MaybeRevertingBurnMintTokenPool.sol | 77 + .../v0.8/ccip/test/helpers/MerkleHelper.sol | 57 + .../v0.8/ccip/test/helpers/MessageHasher.sol | 91 + .../test/helpers/MessageInterceptorHelper.sol | 32 + .../MultiAggregateRateLimiterHelper.sol | 18 + .../ccip/test/helpers/MultiOCR3Helper.sol | 49 + .../v0.8/ccip/test/helpers/MultiTokenPool.sol | 438 + .../v0.8/ccip/test/helpers/OffRampHelper.sol | 114 + .../v0.8/ccip/test/helpers/OnRampHelper.sol | 13 + .../ccip/test/helpers/RateLimiterHelper.sol | 40 + .../v0.8/ccip/test/helpers/ReportCodec.sol | 22 + .../ccip/test/helpers/TokenPoolHelper.sol | 40 + .../ccip/test/helpers/USDCReaderTester.sol | 62 + .../ccip/test/helpers/USDCTokenPoolHelper.sol | 21 + .../helpers/receivers/ConformingReceiver.sol | 17 + .../receivers/MaybeRevertMessageReceiver.sol | 65 + .../MaybeRevertMessageReceiverNo165.sol | 36 + .../helpers/receivers/ReentrancyAbuser.sol | 64 + .../receivers/ReentrancyAbuserMultiRamp.sol | 49 + .../test/libraries/MerkleMultiProof.t.sol | 196 + .../ccip/test/libraries/RateLimiter.t.sol | 297 + .../test/mocks/MockE2EUSDCTokenMessenger.sol | 128 + .../test/mocks/MockE2EUSDCTransmitter.sol | 180 + .../src/v0.8/ccip/test/mocks/MockRMN.sol | 61 + .../src/v0.8/ccip/test/mocks/MockRouter.sol | 169 + .../test/mocks/MockUSDCTokenMessenger.sol | 52 + .../IMessageTransmitterWithRelay.sol | 55 + .../ccip/test/mocks/test/MockRouterTest.t.sol | 68 + .../v0.8/ccip/test/ocr/MultiOCR3Base.t.sol | 1006 ++ .../ccip/test/ocr/MultiOCR3BaseSetup.t.sol | 115 + .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 3797 +++++ .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 497 + .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 1080 ++ .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 200 + .../test/pools/BurnFromMintTokenPool.t.sol | 103 + .../v0.8/ccip/test/pools/BurnMintSetup.t.sol | 45 + .../ccip/test/pools/BurnMintTokenPool.t.sol | 168 + .../pools/BurnWithFromMintTokenPool.t.sol | 104 + .../HybridLockReleaseUSDCTokenPool.t.sol | 886 + .../test/pools/LockReleaseTokenPool.t.sol | 438 + .../src/v0.8/ccip/test/pools/TokenPool.t.sol | 785 + .../v0.8/ccip/test/pools/USDCTokenPool.t.sol | 702 + .../MultiAggregateRateLimiter.t.sol | 1196 ++ .../src/v0.8/ccip/test/rmn/ARMProxy.t.sol | 79 + .../src/v0.8/ccip/test/rmn/RMNHome.t.sol | 377 + .../src/v0.8/ccip/test/rmn/RMNRemote.t.sol | 280 + .../v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol | 148 + .../src/v0.8/ccip/test/router/Router.t.sol | 819 + .../v0.8/ccip/test/router/RouterSetup.t.sol | 50 + .../RegistryModuleOwnerCustom.t.sol | 104 + .../TokenAdminRegistry.t.sol | 395 + .../RegistryModuleOwnerCustom.sol | 60 + .../tokenAdminRegistry/TokenAdminRegistry.sol | 237 + .../src/v0.8/ccip/v1.5-CCIP-License-grants.md | 8 + .../functions/dev/v1_X/FunctionsBilling.sol | 448 + .../functions/dev/v1_X/FunctionsClient.sol | 63 + .../dev/v1_X/FunctionsCoordinator.sol | 227 + .../functions/dev/v1_X/FunctionsRouter.sol | 587 + .../dev/v1_X/FunctionsSubscriptions.sol | 552 + .../src/v0.8/functions/dev/v1_X/Routable.sol | 45 + .../accessControl/TermsOfServiceAllowList.sol | 220 + .../interfaces/ITermsOfServiceAllowList.sol | 84 + .../v1_X/example/FunctionsClientExample.sol | 69 + .../dev/v1_X/interfaces/IFunctionsBilling.sol | 74 + .../dev/v1_X/interfaces/IFunctionsClient.sol | 13 + .../v1_X/interfaces/IFunctionsCoordinator.sol | 37 + .../dev/v1_X/interfaces/IFunctionsRouter.sol | 109 + .../interfaces/IFunctionsSubscriptions.sol | 140 + .../interfaces/IOwnableFunctionsRouter.sol | 8 + .../dev/v1_X/libraries/ChainSpecificUtil.sol | 75 + .../dev/v1_X/libraries/FunctionsRequest.sol | 155 + .../dev/v1_X/libraries/FunctionsResponse.sol | 44 + .../dev/v1_X/mocks/FunctionsV1EventsMock.sol | 183 + .../functions/dev/v1_X/ocr/OCR2Abstract.sol | 103 + .../v0.8/functions/dev/v1_X/ocr/OCR2Base.sol | 353 + .../src/v0.8/functions/interfaces/.gitkeep | 0 .../v0.8/functions/tests/v1_X/BaseTest.t.sol | 25 + .../tests/v1_X/ChainSpecificUtil.t.sol | 271 + .../tests/v1_X/FunctionsBilling.t.sol | 520 + .../tests/v1_X/FunctionsClient.t.sol | 78 + .../tests/v1_X/FunctionsCoordinator.t.sol | 258 + .../tests/v1_X/FunctionsRequest.t.sol | 48 + .../tests/v1_X/FunctionsRouter.t.sol | 1603 ++ .../tests/v1_X/FunctionsSubscriptions.t.sol | 1291 ++ .../FunctionsTermsOfServiceAllowList.t.sol | 557 + .../src/v0.8/functions/tests/v1_X/Gas.t.sol | 377 + .../src/v0.8/functions/tests/v1_X/OCR2.t.sol | 38 + .../src/v0.8/functions/tests/v1_X/README.md | 25 + .../src/v0.8/functions/tests/v1_X/Setup.t.sol | 721 + .../testhelpers/FunctionsClientHarness.sol | 24 + .../testhelpers/FunctionsClientTestHelper.sol | 128 + .../FunctionsClientUpgradeHelper.sol | 157 + .../FunctionsClientWithEmptyCallback.sol | 31 + .../FunctionsCoordinatorHarness.sol | 127 + .../FunctionsCoordinatorTestHelper.sol | 58 + .../testhelpers/FunctionsLoadTestClient.sol | 152 + .../testhelpers/FunctionsRouterHarness.sol | 30 + .../FunctionsSubscriptionsHarness.sol | 54 + .../v1_X/testhelpers/FunctionsTestHelper.sol | 52 + .../functions/v1_0_0/FunctionsBilling.sol | 372 + .../v0.8/functions/v1_0_0/FunctionsClient.sol | 62 + .../functions/v1_0_0/FunctionsCoordinator.sol | 176 + .../v0.8/functions/v1_0_0/FunctionsRouter.sol | 585 + .../v1_0_0/FunctionsSubscriptions.sol | 552 + .../src/v0.8/functions/v1_0_0/Routable.sol | 45 + .../accessControl/TermsOfServiceAllowList.sol | 142 + .../interfaces/ITermsOfServiceAllowList.sol | 40 + .../v1_0_0/example/FunctionsClientExample.sol | 69 + .../v1_0_0/interfaces/IFunctionsBilling.sol | 44 + .../v1_0_0/interfaces/IFunctionsClient.sol | 13 + .../interfaces/IFunctionsCoordinator.sol | 37 + .../v1_0_0/interfaces/IFunctionsRouter.sol | 109 + .../interfaces/IFunctionsSubscriptions.sol | 140 + .../interfaces/IOwnableFunctionsRouter.sol | 8 + .../v1_0_0/libraries/FunctionsRequest.sol | 155 + .../v1_0_0/libraries/FunctionsResponse.sol | 44 + .../v1_0_0/mocks/FunctionsV1EventsMock.sol | 181 + .../functions/v1_0_0/ocr/OCR2Abstract.sol | 134 + .../v0.8/functions/v1_0_0/ocr/OCR2Base.sol | 357 + .../functions/v1_1_0/FunctionsBilling.sol | 391 + .../functions/v1_1_0/FunctionsCoordinator.sol | 183 + .../v1_1_0/libraries/ChainSpecificUtil.sol | 78 + .../functions/v1_1_0/ocr/OCR2Abstract.sol | 103 + .../v0.8/functions/v1_1_0/ocr/OCR2Base.sol | 348 + .../functions/v1_3_0/FunctionsBilling.sol | 440 + .../v0.8/functions/v1_3_0/FunctionsClient.sol | 62 + .../functions/v1_3_0/FunctionsCoordinator.sol | 228 + .../accessControl/TermsOfServiceAllowList.sol | 205 + .../interfaces/ITermsOfServiceAllowList.sol | 80 + .../v1_3_0/interfaces/IFunctionsBilling.sol | 73 + .../functions/v1_3_0/ocr/OCR2Abstract.sol | 103 + .../v0.8/functions/v1_3_0/ocr/OCR2Base.sol | 353 + .../interfaces/ChainlinkRequestInterface.sol | 23 + .../src/v0.8/interfaces/ENSInterface.sol | 31 + .../v0.8/interfaces/FeedRegistryInterface.sol | 124 + .../src/v0.8/interfaces/FlagsInterface.sol | 17 + .../src/v0.8/interfaces/OperatorInterface.sol | 31 + .../src/v0.8/interfaces/OracleInterface.sol | 18 + .../src/v0.8/interfaces/PoRAddressList.sol | 29 + .../src/v0.8/interfaces/PointerInterface.sol | 7 + .../interfaces/TypeAndVersionInterface.sol | 6 + .../v0.8/keystone/CapabilitiesRegistry.sol | 1055 ++ .../v0.8/keystone/KeystoneFeedsConsumer.sol | 107 + .../KeystoneFeedsPermissionHandler.sol | 85 + .../src/v0.8/keystone/KeystoneForwarder.sol | 335 + .../src/v0.8/keystone/OCR3Capability.sol | 168 + .../interfaces/ICapabilityConfiguration.sol | 34 + .../v0.8/keystone/interfaces/IReceiver.sol | 12 + .../src/v0.8/keystone/interfaces/IRouter.sol | 66 + .../lib/KeystoneFeedDefaultMetadataLib.sol | 35 + .../src/v0.8/keystone/ocr/OCR2Abstract.sol | 103 + .../src/v0.8/keystone/test/BaseTest.t.sol | 62 + ...bilitiesRegistry_AddCapabilitiesTest.t.sol | 114 + .../CapabilitiesRegistry_AddDONTest.t.sol | 326 + ...ilitiesRegistry_AddNodeOperatorsTest.t.sol | 51 + .../CapabilitiesRegistry_AddNodesTest.t.sol | 264 + ...esRegistry_DeprecateCapabilitiesTest.t.sol | 80 + ...bilitiesRegistry_GetCapabilitiesTest.t.sol | 48 + .../CapabilitiesRegistry_GetDONsTest.t.sol | 97 + ...esRegistry_GetHashedCapabilityIdTest.t.sol | 28 + ...ilitiesRegistry_GetNodeOperatorsTest.t.sol | 42 + .../CapabilitiesRegistry_GetNodesTest.t.sol | 83 + .../CapabilitiesRegistry_RemoveDONsTest.t.sol | 97 + ...tiesRegistry_RemoveNodeOperatorsTest.t.sol | 46 + ...CapabilitiesRegistry_RemoveNodesTest.t.sol | 243 + ...abilitiesRegistry_TypeAndVersionTest.t.sol | 10 + .../CapabilitiesRegistry_UpdateDONTest.t.sol | 241 + ...tiesRegistry_UpdateNodeOperatorsTest.t.sol | 103 + ...CapabilitiesRegistry_UpdateNodesTest.t.sol | 386 + .../src/v0.8/keystone/test/Constants.t.sol | 38 + .../test/KeystoneForwarderBaseTest.t.sol | 73 + .../test/KeystoneForwarder_ReportTest.t.sol | 326 + .../KeystoneForwarder_SetConfigTest.t.sol | 61 + ...KeystoneForwarder_TypeAndVersionTest.t.sol | 10 + .../test/KeystoneRouter_AccessTest.t.sol | 67 + .../mocks/CapabilityConfigurationContract.sol | 23 + .../mocks/MaliciousConfigurationContract.sol | 49 + .../test/mocks/MaliciousReportReceiver.sol | 23 + .../test/mocks/MaliciousRevertingReceiver.sol | 22 + .../src/v0.8/keystone/test/mocks/Receiver.sol | 24 + .../contracts/src/v0.8/l2ep/README.md | 148 + .../l2ep/dev/CrossDomainDelegateForwarder.sol | 13 + .../v0.8/l2ep/dev/CrossDomainForwarder.sol | 13 + .../src/v0.8/l2ep/dev/CrossDomainOwnable.sol | 81 + .../contracts/src/v0.8/l2ep/dev/Flags.sol | 177 + .../arbitrum/ArbitrumCrossDomainForwarder.sol | 72 + .../arbitrum/ArbitrumCrossDomainGovernor.sol | 63 + .../arbitrum/ArbitrumSequencerUptimeFeed.sol | 313 + .../l2ep/dev/arbitrum/ArbitrumValidator.sol | 355 + .../dev/interfaces/IArbitrumDelayedInbox.sol | 15 + .../dev/interfaces/ICrossDomainOwnable.sol | 15 + .../dev/interfaces/IDelegateForwarder.sol | 10 + .../src/v0.8/l2ep/dev/interfaces/IFlags.sol | 20 + .../v0.8/l2ep/dev/interfaces/IForwarder.sol | 10 + .../dev/interfaces/ISequencerUptimeFeed.sol | 6 + .../optimism/OptimismCrossDomainForwarder.sol | 92 + .../optimism/OptimismCrossDomainGovernor.sol | 74 + .../optimism/OptimismSequencerUptimeFeed.sol | 39 + .../l2ep/dev/optimism/OptimismValidator.sol | 47 + .../dev/scroll/ScrollCrossDomainForwarder.sol | 64 + .../dev/scroll/ScrollCrossDomainGovernor.sol | 91 + .../dev/scroll/ScrollSequencerUptimeFeed.sol | 40 + .../v0.8/l2ep/dev/scroll/ScrollValidator.sol | 55 + .../dev/shared/BaseSequencerUptimeFeed.sol | 231 + .../v0.8/l2ep/dev/shared/BaseValidator.sol | 59 + .../dev/zksync/ZKSyncSequencerUptimeFeed.sol | 25 + .../v0.8/l2ep/dev/zksync/ZKSyncValidator.sol | 104 + .../l2ep/test/mocks/MockAggregatorV2V3.sol | 56 + .../optimism/MockOVMCrossDomainMessenger.sol | 31 + .../scroll/MockScrollCrossDomainMessenger.sol | 36 + .../MockScrollL1CrossDomainMessenger.sol | 60 + .../mocks/scroll/MockScrollL1MessageQueue.sol | 77 + .../MockScrollL2CrossDomainMessenger.sol | 50 + .../test/mocks/zksync/MockZKSyncL1Bridge.sol | 147 + .../src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol | 67 + .../ArbitrumCrossDomainForwarder.t.sol | 159 + .../ArbitrumCrossDomainGovernor.t.sol | 258 + .../ArbitrumSequencerUptimeFeed.t.sol | 248 + .../v1_0_0/arbitrum/ArbitrumValidator.t.sol | 87 + .../OptimismCrossDomainForwarder.t.sol | 187 + .../OptimismCrossDomainGovernor.t.sol | 294 + .../OptimismSequencerUptimeFeed.t.sol | 321 + .../v1_0_0/optimism/OptimismValidator.t.sol | 110 + .../scroll/ScrollCrossDomainForwarder.t.sol | 191 + .../scroll/ScrollCrossDomainGovernor.t.sol | 305 + .../scroll/ScrollSequencerUptimeFeed.t.sol | 325 + .../test/v1_0_0/scroll/ScrollValidator.t.sol | 123 + .../zksync/ZKSyncSequencerUptimeFeed.t.sol | 291 + .../test/v1_0_0/zksync/ZKSyncValidator.t.sol | 149 + .../liquiditymanager/LiquidityManager.sol | 575 + .../ArbitrumL1BridgeAdapter.sol | 175 + .../ArbitrumL2BridgeAdapter.sol | 78 + .../OptimismL1BridgeAdapter.sol | 196 + .../OptimismL2BridgeAdapter.sol | 119 + .../OptimismL1BridgeAdapterEncoder.sol | 21 + .../liquiditymanager/interfaces/IBridge.sol | 49 + .../interfaces/ILiquidityContainer.sol | 16 + .../interfaces/ILiquidityManager.sol | 62 + .../IAbstractArbitrumTokenGateway.sol | 7 + .../interfaces/arbitrum/IArbRollupCore.sol | 7 + .../interfaces/arbitrum/IArbSys.sol | 7 + .../arbitrum/IArbitrumGatewayRouter.sol | 7 + .../interfaces/arbitrum/IArbitrumInbox.sol | 7 + .../arbitrum/IArbitrumL1GatewayRouter.sol | 7 + .../arbitrum/IArbitrumTokenGateway.sol | 7 + .../arbitrum/IL2ArbitrumGateway.sol | 7 + .../arbitrum/IL2ArbitrumMessenger.sol | 7 + .../interfaces/arbitrum/INodeInterface.sol | 7 + .../interfaces/optimism/DisputeTypes.sol | 23 + .../IOptimismCrossDomainMessenger.sol | 31 + .../optimism/IOptimismDisputeGameFactory.sol | 31 + .../optimism/IOptimismL1StandardBridge.sol | 18 + .../optimism/IOptimismL2OutputOracle.sol | 19 + .../optimism/IOptimismL2ToL1MessagePasser.sol | 23 + .../interfaces/optimism/IOptimismPortal.sol | 26 + .../interfaces/optimism/IOptimismPortal2.sol | 12 + .../optimism/IOptimismStandardBridge.sol | 40 + .../interfaces/optimism/Types.sol | 72 + .../liquiditymanager/ocr/OCR3Abstract.sol | 108 + .../v0.8/liquiditymanager/ocr/OCR3Base.sol | 280 + .../test/LiquidityManager.t.sol | 945 ++ .../test/LiquidityManagerBaseTest.t.sol | 43 + .../ArbitrumL1BridgeAdapter.t.sol | 98 + .../ArbitrumL2BridgeAdapter.t.sol | 51 + .../OptimismL1BridgeAdapter.t.sol | 129 + .../test/helpers/LiquidityManagerHelper.sol | 22 + .../test/helpers/OCR3Helper.sol | 41 + .../test/helpers/ReportEncoder.sol | 10 + .../test/mocks/MockBridgeAdapter.sol | 191 + .../liquiditymanager/test/mocks/NoOpOCR3.sol | 18 + .../liquiditymanager/test/ocr/OCR3Base.t.sol | 337 + .../liquiditymanager/test/ocr/OCR3Setup.t.sol | 34 + .../llo-feeds/interfaces/IConfigurator.sol | 28 + .../src/v0.8/llo-feeds/libraries/ByteUtil.sol | 86 + .../src/v0.8/llo-feeds/libraries/Common.sol | 89 + .../libraries/test/ByteUtilTest.t.sol | 177 + .../src/v0.8/llo-feeds/v0.3.0/FeeManager.sol | 507 + .../v0.8/llo-feeds/v0.3.0/RewardManager.sol | 321 + .../src/v0.8/llo-feeds/v0.3.0/Verifier.sol | 559 + .../v0.8/llo-feeds/v0.3.0/VerifierProxy.sol | 229 + .../v0.3.0/interfaces/IFeeManager.sol | 78 + .../v0.3.0/interfaces/IRewardManager.sol | 69 + .../llo-feeds/v0.3.0/interfaces/IVerifier.sol | 123 + .../v0.3.0/interfaces/IVerifierFeeManager.sol | 37 + .../v0.3.0/interfaces/IVerifierProxy.sol | 80 + .../test/fee-manager/BaseFeeManager.t.sol | 379 + .../test/fee-manager/FeeManager.general.t.sol | 242 + .../FeeManager.getFeeAndReward.t.sol | 606 + .../fee-manager/FeeManager.processFee.t.sol | 492 + .../FeeManager.processFeeBulk.t.sol | 193 + .../v0.3.0/test/gas/Gas_VerifierTest.t.sol | 230 + .../v0.3.0/test/mocks/ErroredVerifier.sol | 95 + .../v0.3.0/test/mocks/ExposedVerifier.sol | 69 + .../v0.3.0/test/mocks/FeeManagerProxy.sol | 20 + .../reward-manager/BaseRewardManager.t.sol | 262 + .../reward-manager/RewardManager.claim.t.sol | 790 + .../RewardManager.general.t.sol | 69 + .../RewardManager.payRecipients.t.sol | 194 + .../RewardManager.setRecipients.t.sol | 148 + ...RewardManager.updateRewardRecipients.t.sol | 450 + .../test/verifier/BaseVerifierTest.t.sol | 502 + .../verifier/VerifierActivateConfigTest.t.sol | 63 + .../verifier/VerifierDeactivateFeedTest.t.sol | 108 + .../VerifierProxyConstructorTest.t.sol | 24 + .../VerifierProxyInitializeVerifierTest.t.sol | 30 + ...VerifierProxySetAccessControllerTest.t.sol | 34 + .../VerifierProxySetVerifierTest.t.sol | 41 + .../test/verifier/VerifierProxyTest.t.sol | 23 + .../VerifierProxyUnsetVerifierTest.t.sol | 42 + .../VerifierSetConfigFromSourceTest.t.sol | 134 + .../test/verifier/VerifierSetConfigTest.t.sol | 243 + .../v0.3.0/test/verifier/VerifierTest.t.sol | 42 + .../verifier/VerifierTestBillingReport.t.sol | 218 + .../verifier/VerifierUnsetConfigTest.t.sol | 56 + .../test/verifier/VerifierVerifyTest.t.sol | 314 + .../v0.4.0/DestinationFeeManager.sol | 573 + .../v0.4.0/DestinationRewardManager.sol | 328 + .../llo-feeds/v0.4.0/DestinationVerifier.sol | 443 + .../v0.4.0/DestinationVerifierProxy.sol | 70 + .../interfaces/IDestinationFeeManager.sol | 103 + .../interfaces/IDestinationRewardManager.sol | 75 + .../interfaces/IDestinationVerifier.sol | 57 + .../IDestinationVerifierFeeManager.sol | 45 + .../interfaces/IDestinationVerifierProxy.sol | 52 + .../IDestinationVerifierProxyVerifier.sol | 48 + .../BaseDestinationFeeManager.t.sol | 406 + .../DestinationFeeManager.general.t.sol | 299 + ...estinationFeeManager.getFeeAndReward.t.sol | 720 + .../DestinationFeeManager.processFee.t.sol | 492 + ...DestinationFeeManager.processFeeBulk.t.sol | 310 + .../test/mocks/DestinationFeeManagerProxy.sol | 24 + .../BaseDestinationRewardManager.t.sol | 264 + .../DestinationRewardManager.claim.t.sol | 790 + .../DestinationRewardManager.general.t.sol | 99 + ...stinationRewardManager.payRecipients.t.sol | 194 + ...stinationRewardManager.setRecipients.t.sol | 148 + ...RewardManager.updateRewardRecipients.t.sol | 450 + .../BaseDestinationVerifierTest.t.sol | 347 + .../DestinationVerifierInterfacesTest.t.sol | 128 + .../DestinationVerifierProxyTest.t.sol | 38 + ...nationVerifierRemoveLatestConfigTest.t.sol | 126 + ...ationVerifierSetAccessControllerTest.t.sol | 33 + .../DestinationVerifierSetConfigTest.t.sol | 176 + ...DestinationVerifierSetFeeManagerTest.t.sol | 28 + .../verifier/DestinationVerifierTest.t.sol | 34 + ...DestinationVerifierTestBillingReport.t.sol | 189 + .../DestinationVerifierTestRewards.t.sol | 227 + ...erTestRewardsMultiVefifierFeeManager.t.sol | 141 + .../DestinationVerifierVerifyBulkTest.t.sol | 140 + .../DestinationVerifierVerifyTest.t.sol | 714 + .../configuration/ChannelConfigStore.sol | 29 + .../v0.5.0/configuration/Configurator.sol | 188 + .../interfaces/IChannelConfigStore.sol | 8 + .../test/ChannelConfigStore.t.sol | 41 + .../test/mocks/ExposedChannelConfigStore.sol | 15 + .../test/mocks/ExposedConfigurator.sol | 15 + .../FunctionsBillingRegistryEventsMock.sol | 80 + .../v0.8/mocks/FunctionsOracleEventsMock.sol | 63 + .../v0.8/mocks/MockAggregatorValidator.sol | 30 + .../contracts/src/v0.8/mocks/MockArbSys.sol | 17 + .../src/v0.8/mocks/MockLinkToken.sol | 54 + .../src/v0.8/mocks/MockOffchainAggregator.sol | 14 + .../operatorforwarder/AuthorizedForwarder.sol | 91 + .../operatorforwarder/AuthorizedReceiver.sol | 65 + .../operatorforwarder/LinkTokenReceiver.sol | 50 + .../src/v0.8/operatorforwarder/Operator.sol | 497 + .../operatorforwarder/OperatorFactory.sol | 73 + .../interfaces/IAuthorizedReceiver.sol | 10 + .../interfaces/IWithdrawal.sol | 13 + .../v0.8/operatorforwarder/test/Factory.t.sol | 69 + .../operatorforwarder/test/Forwarder.t.sol | 183 + .../operatorforwarder/test/operator.t.sol | 291 + .../test/testhelpers/BasicConsumer.sol | 12 + .../test/testhelpers/Callback.sol | 22 + .../testhelpers/ChainlinkClientHelper.sol | 22 + .../test/testhelpers/Chainlinked.sol | 127 + .../test/testhelpers/Consumer.sol | 60 + .../test/testhelpers/Deployer.t.sol | 33 + .../test/testhelpers/EmptyOracle.sol | 28 + .../test/testhelpers/GasGuzzlingConsumer.sol | 41 + .../test/testhelpers/GetterSetter.sol | 50 + .../test/testhelpers/MaliciousChainlink.sol | 67 + .../test/testhelpers/MaliciousChainlinked.sol | 116 + .../test/testhelpers/MaliciousConsumer.sol | 49 + .../MaliciousMultiWordConsumer.sol | 54 + .../test/testhelpers/MaliciousRequester.sol | 52 + .../test/testhelpers/MockReceiver.sol | 19 + .../test/testhelpers/MultiWordConsumer.sol | 145 + .../v0.8/shared/access/AuthorizedCallers.sol | 82 + .../src/v0.8/shared/access/ConfirmedOwner.sol | 10 + .../access/ConfirmedOwnerWithProposal.sol | 68 + .../src/v0.8/shared/access/OwnerIsCreator.sol | 10 + .../access/SimpleReadAccessController.sol | 22 + .../access/SimpleWriteAccessController.sol | 73 + .../src/v0.8/shared/call/CallWithExactGas.sol | 162 + .../enumerable/EnumerableMapAddresses.sol | 225 + .../enumerable/EnumerableMapBytes32.sol | 136 + .../enumerable/EnumerableSetWithBytes16.sol | 454 + .../interfaces/AccessControllerInterface.sol | 7 + .../shared/interfaces/AggregatorInterface.sol | 19 + .../interfaces/AggregatorV2V3Interface.sol | 8 + .../interfaces/AggregatorV3Interface.sol | 20 + .../AggregatorValidatorInterface.sol | 12 + .../shared/interfaces/IAccessController.sol | 6 + .../shared/interfaces/IERC677Receiver.sol | 6 + .../src/v0.8/shared/interfaces/IOwnable.sol | 10 + .../shared/interfaces/ITypeAndVersion.sol | 6 + .../src/v0.8/shared/interfaces/IWERC20.sol | 8 + .../shared/interfaces/LinkTokenInterface.sol | 29 + .../src/v0.8/shared/mocks/WERC20Mock.sol | 36 + .../src/v0.8/shared/ocr2/OCR2Abstract.sol | 122 + .../src/v0.8/shared/ocr2/OCR2Base.sol | 330 + .../contracts/src/v0.8/shared/ocr2/README.md | 5 + .../src/v0.8/shared/test/BaseTest.t.sol | 29 + .../test/access/AuthorizedCallers.t.sol | 186 + .../shared/test/call/CallWithExactGas.t.sol | 512 + .../test/call/CallWithExactGasHelper.sol | 35 + .../enumerable/EnumerableMapAddresses.t.sol | 249 + .../shared/test/helpers/ChainReaderTester.sol | 202 + .../test/helpers/LinkTokenTestHelper.sol | 12 + .../testhelpers/ConfirmedOwnerTestHelper.sol | 14 + .../shared/test/testhelpers/GasConsumer.sol | 24 + .../test/testhelpers/GenericReceiver.sol | 29 + .../test/token/ERC677/BurnMintERC677.t.sol | 347 + .../token/ERC677/OpStackBurnMintERC677.t.sol | 117 + .../test/util/SortedSetValidationUtil.t.sol | 168 + .../shared/token/ERC20/IBurnMintERC20.sol | 29 + .../token/ERC20/IOptimismMintableERC20.sol | 26 + .../shared/token/ERC677/BurnMintERC677.sol | 217 + .../src/v0.8/shared/token/ERC677/ERC677.sol | 21 + .../src/v0.8/shared/token/ERC677/IERC677.sol | 13 + .../v0.8/shared/token/ERC677/LinkToken.sol | 8 + .../token/ERC677/OpStackBurnMintERC677.sol | 49 + .../shared/util/SortedSetValidationUtil.sol | 60 + .../tests/AutomationConsumerBenchmark.sol | 82 + .../contracts/src/v0.8/tests/Broken.sol | 18 + .../v0.8/tests/ChainlinkClientTestHelper.sol | 83 + .../src/v0.8/tests/ChainlinkTestHelper.sol | 57 + .../contracts/src/v0.8/tests/Counter.sol | 26 + .../contracts/src/v0.8/tests/CronReceiver.sol | 20 + .../v0.8/tests/ERC20BalanceMonitorExposed.sol | 17 + .../v0.8/tests/EthBalanceMonitorExposed.sol | 16 + .../contracts/src/v0.8/tests/FeedConsumer.sol | 62 + .../src/v0.8/tests/FlagsTestHelper.sol | 20 + .../contracts/src/v0.8/tests/Greeter.sol | 18 + .../v0.8/tests/KeeperCompatibleTestHelper.sol | 12 + .../contracts/src/v0.8/tests/LogEmitter.sol | 33 + .../src/v0.8/tests/MockArbGasInfo.sol | 11 + .../src/v0.8/tests/MockArbitrumInbox.sol | 125 + .../src/v0.8/tests/MockETHLINKAggregator.sol | 44 + .../src/v0.8/tests/MockGasBoundCaller.sol | 32 + .../src/v0.8/tests/MockOVMGasPriceOracle.sol | 12 + .../MockOptimismL1CrossDomainMessenger.sol | 41 + .../MockOptimismL2CrossDomainMessenger.sol | 28 + .../src/v0.8/tests/MockV3Aggregator.sol | 78 + .../v0.8/tests/MockZKSyncSystemContext.sol | 16 + .../src/v0.8/tests/ReceiveEmitter.sol | 11 + .../src/v0.8/tests/ReceiveFallbackEmitter.sol | 11 + .../src/v0.8/tests/ReceiveReverter.sol | 9 + .../src/v0.8/tests/StreamsLookupUpkeep.sol | 159 + .../src/v0.8/tests/VRFLogEmitter.sol | 42 + .../src/v0.8/tests/VerifiableLoadBase.sol | 572 + .../tests/VerifiableLoadLogTriggerUpkeep.sol | 127 + .../VerifiableLoadStreamsLookupUpkeep.sol | 85 + .../src/v0.8/tests/VerifiableLoadUpkeep.sol | 52 + .../transmission/dev/ERC-4337/Paymaster.sol | 134 + .../v0.8/transmission/dev/ERC-4337/SCA.sol | 73 + .../transmission/dev/ERC-4337/SCALibrary.sol | 48 + .../ERC-4337/SmartContractAccountFactory.sol | 33 + .../transmission/dev/testhelpers/Greeter.sol | 15 + .../SmartContractAccountHelper.sol | 78 + .../src/v0.8/transmission/test/BaseTest.t.sol | 17 + .../transmission/test/EIP_712_1014_4337.t.sol | 365 + .../src/precompiles/ArbGasInfo.sol | 152 + .../src/precompiles/ArbSys.sol | 153 + .../@ensdomains/buffer/v0.1.0/Buffer.sol | 260 + .../v0.16.2/src/L2/GasPriceOracle.sol | 99 + .../v0.16.2/src/L2/L1Block.sol | 76 + .../v0.16.2/src/libraries/Predeploys.sol | 77 + .../v0.16.2/src/universal/ISemver.sol | 13 + .../v0.17.3/src/L2/GasPriceOracle.sol | 251 + .../v0.17.3/src/L2/L1Block.sol | 169 + .../v0.17.3/src/deps/LibString.sol | 54 + .../v0.17.3/src/deps/LibZip.sol | 108 + .../v0.17.3/src/libraries/Constants.sol | 43 + .../v0.17.3/src/libraries/GasPayingToken.sol | 93 + .../v0.17.3/src/libraries/L1BlockErrors.sol | 23 + .../v0.17.3/src/libraries/Predeploys.sol | 171 + .../v0.17.3/src/libraries/Storage.sol | 94 + .../v0.17.3/src/universal/ISemver.sol | 19 + .../messaging/iOVM_CrossDomainMessenger.sol | 33 + .../L2/predeploys/OVM_GasPriceOracle.sol | 162 + .../L2/predeploys/OVM_GasPriceOracle.sol | 162 + .../L2/predeploys/IScrollL1GasPriceOracle.sol | 55 + .../src/v0.8/vendor/BufferChainlink.sol | 337 + .../src/v0.8/vendor/CBORChainlink.sol | 94 + .../contracts/src/v0.8/vendor/DateTime.sol | 254 + .../contracts/src/v0.8/vendor/ENSResolver.sol | 6 + .../contracts/src/v0.8/vendor/IERC165.sol | 12 + .../vendor/MockOVMCrossDomainMessenger.sol | 74 + .../vendor/MockScrollCrossDomainMessenger.sol | 101 + .../contracts/src/v0.8/vendor/MultiSend.sol | 66 + .../contracts/src/v0.8/vendor/Strings.sol | 842 + .../contracts/bridge/interfaces/IBridge.sol | 60 + .../contracts/bridge/interfaces/IInbox.sol | 92 + .../bridge/interfaces/IMessageProvider.sol | 26 + .../libraries/AddressAliasHelper.sol | 44 + .../vendor/entrypoint/core/EntryPoint.sol | 861 + .../v0.8/vendor/entrypoint/core/Helpers.sol | 68 + .../vendor/entrypoint/core/SenderCreator.sol | 28 + .../vendor/entrypoint/core/StakeManager.sol | 124 + .../vendor/entrypoint/interfaces/IAccount.sol | 34 + .../entrypoint/interfaces/IAggregator.sol | 36 + .../entrypoint/interfaces/IEntryPoint.sol | 197 + .../entrypoint/interfaces/IPaymaster.sol | 51 + .../entrypoint/interfaces/IStakeManager.sol | 104 + .../entrypoint/interfaces/UserOperation.sol | 84 + .../src/v0.8/vendor/entrypoint/utils/Exec.sol | 70 + .../src/v0.8/vendor/forge-std/src/Base.sol | 35 + .../src/v0.8/vendor/forge-std/src/Script.sol | 27 + .../vendor/forge-std/src/StdAssertions.sol | 669 + .../v0.8/vendor/forge-std/src/StdChains.sol | 263 + .../v0.8/vendor/forge-std/src/StdCheats.sol | 817 + .../v0.8/vendor/forge-std/src/StdError.sol | 15 + .../vendor/forge-std/src/StdInvariant.sol | 122 + .../src/v0.8/vendor/forge-std/src/StdJson.sol | 283 + .../src/v0.8/vendor/forge-std/src/StdMath.sol | 43 + .../v0.8/vendor/forge-std/src/StdStorage.sol | 473 + .../v0.8/vendor/forge-std/src/StdStyle.sol | 333 + .../src/v0.8/vendor/forge-std/src/StdToml.sol | 283 + .../v0.8/vendor/forge-std/src/StdUtils.sol | 226 + .../src/v0.8/vendor/forge-std/src/Test.sol | 33 + .../src/v0.8/vendor/forge-std/src/Vm.sol | 1968 +++ .../src/v0.8/vendor/forge-std/src/console.sol | 1560 ++ .../v0.8/vendor/forge-std/src/console2.sol | 4 + .../forge-std/src/interfaces/IERC1155.sol | 105 + .../forge-std/src/interfaces/IERC165.sol | 12 + .../forge-std/src/interfaces/IERC20.sol | 43 + .../forge-std/src/interfaces/IERC4626.sol | 190 + .../forge-std/src/interfaces/IERC721.sol | 164 + .../forge-std/src/interfaces/IMulticall3.sol | 73 + .../vendor/forge-std/src/mocks/MockERC20.sol | 234 + .../vendor/forge-std/src/mocks/MockERC721.sol | 231 + .../v0.8/vendor/forge-std/src/safeconsole.sol | 13937 ++++++++++++++++ .../v4.7.3/contracts/proxy/Proxy.sol | 86 + .../v4.7.3/contracts/utils/Address.sol | 244 + .../v4.7.3/contracts/utils/Context.sol | 24 + .../contracts/utils/structs/EnumerableMap.sol | 529 + .../contracts/utils/structs/EnumerableSet.sol | 376 + .../v4.8.3/contracts/access/AccessControl.sol | 247 + .../contracts/access/IAccessControl.sol | 88 + .../v4.8.3/contracts/interfaces/IERC165.sol | 6 + .../v4.8.3/contracts/interfaces/IERC20.sol | 6 + .../interfaces/draft-IERC20Permit.sol | 160 + .../v4.8.3/contracts/mocks/ERC20Mock.sol | 41 + .../v4.8.3/contracts/security/Pausable.sol | 105 + .../v4.8.3/contracts/token/ERC20/ERC20.sol | 365 + .../v4.8.3/contracts/token/ERC20/IERC20.sol | 78 + .../token/ERC20/extensions/ERC20Burnable.sol | 39 + .../token/ERC20/extensions/IERC20Metadata.sol | 28 + .../ERC20/extensions/draft-ERC20Permit.sol | 95 + .../ERC20/extensions/draft-IERC20Permit.sol | 60 + .../contracts/token/ERC20/utils/SafeERC20.sol | 95 + .../v4.8.3/contracts/utils/Address.sol | 236 + .../v4.8.3/contracts/utils/Context.sol | 24 + .../v4.8.3/contracts/utils/Counters.sol | 43 + .../v4.8.3/contracts/utils/StorageSlot.sol | 88 + .../v4.8.3/contracts/utils/Strings.sol | 70 + .../contracts/utils/cryptography/ECDSA.sol | 195 + .../contracts/utils/cryptography/EIP712.sol | 102 + .../contracts/utils/introspection/ERC165.sol | 29 + .../utils/introspection/ERC165Checker.sol | 127 + .../contracts/utils/introspection/IERC165.sol | 25 + .../v4.8.3/contracts/utils/math/Math.sol | 336 + .../v4.8.3/contracts/utils/math/SafeCast.sol | 1136 ++ .../contracts/utils/math/SignedMath.sol | 43 + .../contracts/utils/structs/EnumerableMap.sol | 530 + .../contracts/utils/structs/EnumerableSet.sol | 378 + .../v5.0.2/contracts/access/AccessControl.sol | 209 + .../contracts/access/IAccessControl.sol | 98 + .../v5.0.2/contracts/interfaces/IERC165.sol | 6 + .../v5.0.2/contracts/interfaces/IERC20.sol | 6 + .../v5.0.2/contracts/interfaces/IERC5267.sol | 28 + .../contracts/interfaces/draft-IERC6093.sol | 161 + .../v5.0.2/contracts/token/ERC20/ERC20.sol | 316 + .../v5.0.2/contracts/token/ERC20/IERC20.sol | 79 + .../token/ERC20/extensions/ERC20Burnable.sol | 39 + .../token/ERC20/extensions/IERC20Metadata.sol | 26 + .../token/ERC20/extensions/IERC20Permit.sol | 90 + .../contracts/token/ERC20/utils/SafeERC20.sol | 118 + .../v5.0.2/contracts/utils/Address.sol | 159 + .../v5.0.2/contracts/utils/Context.sol | 28 + .../v5.0.2/contracts/utils/Pausable.sol | 119 + .../v5.0.2/contracts/utils/ShortStrings.sol | 123 + .../v5.0.2/contracts/utils/StorageSlot.sol | 135 + .../v5.0.2/contracts/utils/Strings.sol | 94 + .../contracts/utils/cryptography/ECDSA.sol | 174 + .../contracts/utils/cryptography/EIP712.sol | 160 + .../utils/cryptography/MessageHashUtils.sol | 86 + .../contracts/utils/introspection/ERC165.sol | 27 + .../utils/introspection/ERC165Checker.sol | 124 + .../contracts/utils/introspection/IERC165.sol | 25 + .../v5.0.2/contracts/utils/math/Math.sol | 415 + .../v5.0.2/contracts/utils/math/SafeCast.sol | 1153 ++ .../contracts/utils/math/SignedMath.sol | 43 + .../contracts/utils/structs/EnumerableMap.sol | 533 + .../contracts/utils/structs/EnumerableSet.sol | 378 + .../vendor/solidity-cborutils/v2.0.0/CBOR.sol | 222 + .../src/v0.8/vrf/AuthorizedReceiver.sol | 86 + .../src/v0.8/vrf/BatchBlockhashStore.sol | 90 + .../src/v0.8/vrf/BatchVRFCoordinatorV2.sol | 68 + .../src/v0.8/vrf/KeepersVRFConsumer.sol | 119 + .../chainlink/contracts/src/v0.8/vrf/VRF.sol | 588 + .../src/v0.8/vrf/VRFConsumerBase.sol | 200 + .../src/v0.8/vrf/VRFConsumerBaseV2.sol | 135 + .../src/v0.8/vrf/VRFCoordinatorV2.sol | 840 + .../contracts/src/v0.8/vrf/VRFOwner.sol | 348 + .../src/v0.8/vrf/VRFRequestIDBase.sol | 42 + .../contracts/src/v0.8/vrf/VRFTypes.sol | 44 + .../contracts/src/v0.8/vrf/VRFV2Wrapper.sol | 450 + .../src/v0.8/vrf/VRFV2WrapperConsumerBase.sol | 86 + .../src/v0.8/vrf/dev/ArbitrumL1Fees.sol | 31 + .../vrf/dev/BatchVRFCoordinatorV2Plus.sol | 71 + .../src/v0.8/vrf/dev/BlockhashStore.sol | 81 + .../src/v0.8/vrf/dev/OptimismL1Fees.sol | 97 + .../src/v0.8/vrf/dev/SubscriptionAPI.sol | 475 + .../v0.8/vrf/dev/TrustedBlockhashStore.sol | 66 + .../v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol | 165 + .../vrf/dev/VRFConsumerBaseV2Upgradeable.sol | 158 + .../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol | 791 + .../vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol | 43 + .../vrf/dev/VRFCoordinatorV2_5_Optimism.sol | 21 + .../vrf/dev/VRFSubscriptionBalanceMonitor.sol | 281 + .../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol | 725 + .../vrf/dev/VRFV2PlusWrapperConsumerBase.sol | 121 + .../vrf/dev/VRFV2PlusWrapper_Arbitrum.sol | 23 + .../vrf/dev/VRFV2PlusWrapper_Optimism.sol | 40 + .../dev/interfaces/IVRFCoordinatorV2Plus.sol | 36 + .../IVRFCoordinatorV2PlusInternal.sol | 67 + .../IVRFCoordinatorV2PlusMigration.sol | 14 + .../IVRFMigratableConsumerV2Plus.sol | 13 + .../dev/interfaces/IVRFSubscriptionV2Plus.sol | 98 + .../vrf/dev/interfaces/IVRFV2PlusMigrate.sol | 15 + .../vrf/dev/interfaces/IVRFV2PlusWrapper.sol | 83 + .../vrf/dev/libraries/VRFV2PlusClient.sol | 24 + .../testhelpers/ExposedVRFCoordinatorV2_5.sol | 78 + .../ExposedVRFCoordinatorV2_5_Arbitrum.sol | 33 + .../ExposedVRFCoordinatorV2_5_Optimism.sol | 33 + .../VRFConsumerV2PlusUpgradeableExample.sol | 75 + .../testhelpers/VRFCoordinatorTestV2_5.sol | 773 + .../VRFCoordinatorV2PlusUpgradedVersion.sol | 809 + .../VRFCoordinatorV2Plus_V2Example.sol | 159 + .../VRFMaliciousConsumerV2Plus.sol | 67 + .../src/v0.8/vrf/dev/testhelpers/VRFOld.sol | 588 + .../testhelpers/VRFV2PlusConsumerExample.sol | 113 + .../VRFV2PlusExternalSubOwnerExample.sol | 48 + .../VRFV2PlusLoadTestWithMetrics.sol | 183 + .../VRFV2PlusMaliciousMigrator.sol | 32 + .../testhelpers/VRFV2PlusRevertingExample.sol | 69 + .../VRFV2PlusSingleConsumerExample.sol | 115 + .../VRFV2PlusWrapperConsumerExample.sol | 87 + .../VRFV2PlusWrapperLoadTestConsumer.sol | 199 + .../interfaces/BlockhashStoreInterface.sol | 7 + .../vrf/interfaces/IAuthorizedReceiver.sol | 10 + .../interfaces/VRFCoordinatorV2Interface.sol | 113 + .../vrf/interfaces/VRFV2WrapperInterface.sol | 33 + .../src/v0.8/vrf/mocks/VRFCoordinatorMock.sol | 36 + .../v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol | 323 + .../v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol | 269 + .../src/v0.8/vrf/test/BaseTest.t.sol | 34 + .../vrf/test/BatchVRFCoordinatorV2Plus.t.sol | 196 + .../src/v0.8/vrf/test/ChainSpecificUtil.t.sol | 196 + .../vrf/test/FixtureVRFCoordinatorV2_5.t.sol | 134 + .../v0.8/vrf/test/TrustedBlockhashStore.t.sol | 89 + .../v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol | 381 + .../test/VRFCoordinatorV2Plus_Migration.t.sol | 352 + .../vrf/test/VRFCoordinatorV2_5Mock.t.sol | 511 + .../test/VRFCoordinatorV2_5_Arbitrum.t.sol | 179 + .../test/VRFCoordinatorV2_5_Optimism.t.sol | 413 + .../src/v0.8/vrf/test/VRFV2Plus.t.sol | 1160 ++ .../vrf/test/VRFV2PlusSubscriptionAPI.t.sol | 649 + .../src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol | 488 + .../vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol | 109 + .../vrf/test/VRFV2PlusWrapper_Migration.t.sol | 388 + .../vrf/test/VRFV2PlusWrapper_Optimism.t.sol | 216 + .../testhelpers/ChainSpecificUtilHelper.sol | 23 + .../src/v0.8/vrf/testhelpers/Counter.sol | 26 + .../src/v0.8/vrf/testhelpers/VRFConsumer.sol | 28 + .../v0.8/vrf/testhelpers/VRFConsumerV2.sol | 60 + .../vrf/testhelpers/VRFConsumerV2Plus.sol | 55 + .../VRFConsumerV2UpgradeableExample.sol | 62 + .../vrf/testhelpers/VRFCoordinatorTestV2.sol | 840 + .../VRFCoordinatorV2TestHelper.sol | 88 + .../VRFExternalSubOwnerExample.sol | 46 + .../VRFLoadTestExternalSubOwner.sol | 38 + .../VRFLoadTestOwnerlessConsumer.sol | 42 + .../testhelpers/VRFMaliciousConsumerV2.sol | 50 + .../testhelpers/VRFMockETHLINKAggregator.sol | 53 + .../VRFOwnerlessConsumerExample.sol | 38 + .../VRFRequestIDBaseTestHelper.sol | 19 + .../testhelpers/VRFSingleConsumerExample.sol | 110 + .../VRFSubscriptionBalanceMonitorExposed.sol | 18 + .../v0.8/vrf/testhelpers/VRFTestHelper.sol | 104 + .../testhelpers/VRFV2LoadTestWithMetrics.sol | 163 + .../testhelpers/VRFV2OwnerTestConsumer.sol | 138 + .../v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol | 8 + .../vrf/testhelpers/VRFV2RevertingExample.sol | 61 + .../VRFV2TransparentUpgradeableProxy.sol | 13 + .../VRFV2WrapperConsumerExample.sol | 57 + .../VRFV2WrapperLoadTestConsumer.sol | 137 + .../VRFV2WrapperOutOfGasConsumerExample.sol | 24 + .../VRFV2WrapperRevertingConsumerExample.sol | 24 + .../VRFV2WrapperUnderFundingConsumer.sol | 25 + .../v0.8/vrf/testhelpers/VRFv2Consumer.sol | 64 + .../foundry/lib/foundry-chainlink-toolkit | 1 - packages/foundry/remappings.txt | 3 +- packages/foundry/src/EtfHook.sol | 9 +- yarn.lock | 1745 +- 1435 files changed, 371196 insertions(+), 268 deletions(-) create mode 100644 packages/foundry/lib/chainlink/contracts/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json create mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json create mode 100644 packages/foundry/lib/chainlink/contracts/package.json create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol create mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol delete mode 160000 packages/foundry/lib/foundry-chainlink-toolkit diff --git a/package.json b/package.json index c5126a3..a468d98 100644 --- a/package.json +++ b/package.json @@ -42,5 +42,8 @@ "packageManager": "yarn@3.2.3", "engines": { "node": ">=18.18.0" + }, + "dependencies": { + "@chainlink/contracts": "^1.3.0" } } diff --git a/packages/foundry/lib/chainlink/contracts/README.md b/packages/foundry/lib/chainlink/contracts/README.md new file mode 100644 index 0000000..182891c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/README.md @@ -0,0 +1,75 @@ +# Chainlink Smart Contracts + +## Installation + +```sh +# via pnpm +$ pnpm add @chainlink/contracts +# via npm +$ npm install @chainlink/contracts --save +``` + +### Directory Structure + +```sh +@chainlink/contracts +├── src # Solidity contracts +│ └── v0.8 +└── abi # ABI json output + └── v0.8 +``` + +### Usage + +The solidity smart contracts themselves can be imported via the `src` directory of `@chainlink/contracts`: + +```solidity +import '@chainlink/contracts/src/v0.8/AutomationCompatibleInterface.sol'; +``` + +## Local Development + +Note: Contracts in `dev/` directories are under active development and are likely unaudited. Please refrain from using these in production applications. + +```bash +# Clone Chainlink repository +$ git clone https://github.com/smartcontractkit/chainlink.git +# Continuing via pnpm +$ cd contracts/ +$ pnpm +$ pnpm test +``` + +## Contributing + +Please try to adhere to [Solidity Style Guide](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/STYLE.md). + +Contributions are welcome! Please refer to +[Chainlink's contributing guidelines](https://github.com/smartcontractkit/chainlink/blob/develop/docs/CONTRIBUTING.md) for detailed +contribution information. + +Thank you! + +### Changesets + +We use [changesets](https://github.com/changesets/changesets) to manage versioning the contracts. + +Every PR that modifies any configuration or code, should most likely accompanied by a changeset file. + +To install `changesets`: + 1. Install `pnpm` if it is not already installed - [docs](https://pnpm.io/installation). + 2. Run `pnpm install`. + +Either after or before you create a commit, run the `pnpm changeset` command in the `contracts` directory to create an accompanying changeset entry which will reflect on the CHANGELOG for the next release. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), + +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## License +Most of the contracts are licensed under the [MIT](https://choosealicense.com/licenses/mit/) license. +An exception to this is the ccip folder, which defaults to be licensed under the [BUSL-1.1](./src/v0.8/ccip/LICENSE.md) license, however, there are a few exceptions + +- `src/v0.8/ccip/applications/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license +- `src/v0.8/ccip/interfaces/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license +- `src/v0.8/ccip/libraries/{Client.sol, Internal.sol}` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json new file mode 100644 index 0000000..5756029 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json @@ -0,0 +1,227 @@ +[ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json new file mode 100644 index 0000000..d018c95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json @@ -0,0 +1,26 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json new file mode 100644 index 0000000..e1a1ad8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json @@ -0,0 +1,29 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json new file mode 100644 index 0000000..7fb29aa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json @@ -0,0 +1,129 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json new file mode 100644 index 0000000..4667a49 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json @@ -0,0 +1,240 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json new file mode 100644 index 0000000..9fe8722 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json @@ -0,0 +1,113 @@ +[ + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json new file mode 100644 index 0000000..54a6a92 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json @@ -0,0 +1,36 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json new file mode 100644 index 0000000..375b188 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json @@ -0,0 +1,406 @@ +[ + { + "inputs": [], + "name": "getAmortizedCostCapBips", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentTxL1GasFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasAccountingParams", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasBacklog", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasBacklogTolerance", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1BaseFeeEstimate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1BaseFeeEstimateInertia", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1FeesAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1GasPriceEstimate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1PricingEquilibrationUnits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1PricingFundsDueForRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1PricingSurplus", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1PricingUnitsSinceUpdate", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1RewardRate", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1RewardRecipient", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastL1PricingSurplus", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastL1PricingUpdateTime", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinimumGasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerBatchGasCharge", + "outputs": [ + { + "internalType": "int64", + "name": "", + "type": "int64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricesInArbGas", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "getPricesInArbGasWithAggregator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricesInWei", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "getPricesInWeiWithAggregator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricingInertia", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json new file mode 100644 index 0000000..76bb647 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json @@ -0,0 +1,355 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "uniqueId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "batchNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "indexInBatch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "arbBlockNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethBlockNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "callvalue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "L2ToL1Transaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "hash", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "position", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "arbBlockNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethBlockNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "callvalue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "L2ToL1Tx", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "reserved", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "position", + "type": "uint256" + } + ], + "name": "SendMerkleUpdate", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "arbBlockNum", + "type": "uint256" + } + ], + "name": "arbBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbChainID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbOSVersion", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStorageGasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isTopLevelCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "unused", + "type": "address" + } + ], + "name": "mapL1SenderContractAddressToL2Alias", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "myCallersAddressWithoutAliasing", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendMerkleTreeState", + "outputs": [ + { + "internalType": "uint256", + "name": "size", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "partials", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendTxToL1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "wasMyCallersAddressAliased", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json new file mode 100644 index 0000000..b6f66e0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json @@ -0,0 +1,199 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json new file mode 100644 index 0000000..6df7093 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json @@ -0,0 +1,217 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json new file mode 100644 index 0000000..a25dd05 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json @@ -0,0 +1,272 @@ +[ + { + "inputs": [ + { + "internalType": "contract IL1GatewayRouter", + "name": "l1GatewayRouter", + "type": "address" + }, + { + "internalType": "contract IOutbox", + "name": "l1Outbox", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "NoGatewayForToken", + "type": "error" + }, + { + "inputs": [], + "name": "Unimplemented", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "address", + "name": "l2Sender", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l1Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2Timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct ArbitrumL1BridgeAdapter.ArbitrumFinalizationPayload", + "name": "payload", + "type": "tuple" + } + ], + "name": "exposeArbitrumFinalizationPayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + } + ], + "internalType": "struct ArbitrumL1BridgeAdapter.SendERC20Params", + "name": "params", + "type": "tuple" + } + ], + "name": "exposeSendERC20Params", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "arbitrumFinalizationPayload", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1Token", + "type": "address" + } + ], + "name": "getL2Token", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json new file mode 100644 index 0000000..3e51a25 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json @@ -0,0 +1,155 @@ +[ + { + "inputs": [ + { + "internalType": "contract IL2GatewayRouter", + "name": "l2GatewayRouter", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "depositNativeToL1", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json new file mode 100644 index 0000000..7a398a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json new file mode 100644 index 0000000..c9a61dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json @@ -0,0 +1,621 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "flagsAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l1SenderAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "NoDataPresent", + "type": "error" + }, + { + "inputs": [], + "name": "Uninitialized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1SenderTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "latestStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "latestTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bool", + "name": "incomingStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "incomingTimestamp", + "type": "uint64" + } + ], + "name": "UpdateIgnored", + "type": "event" + }, + { + "inputs": [], + "name": "FLAGS", + "outputs": [ + { + "internalType": "contract IFlags", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FLAG_L2_SEQ_OFFLINE", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "aliasedL1MessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Sender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json new file mode 100644 index 0000000..8faac8f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json @@ -0,0 +1,565 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "crossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l2ArbitrumSequencerUptimeFeedAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "configACAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasPriceL1FeedAddr", + "type": "address" + }, + { + "internalType": "enum ArbitrumValidator.PaymentStrategy", + "name": "_paymentStrategy", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previous", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "current", + "type": "address" + } + ], + "name": "ConfigACSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "gasPriceL1FeedAddr", + "type": "address" + } + ], + "name": "GasConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "refundAddr", + "type": "address" + } + ], + "name": "L2WithdrawalRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum ArbitrumValidator.PaymentStrategy", + "name": "paymentStrategy", + "type": "uint8" + } + ], + "name": "PaymentStrategySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "CROSS_DOMAIN_MESSENGER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_ALIAS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_SEQ_STATUS_RECORDER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "configAC", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gasConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasPriceL1FeedAddr", + "type": "address" + } + ], + "internalType": "struct ArbitrumValidator.GasConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paymentStrategy", + "outputs": [ + { + "internalType": "enum ArbitrumValidator.PaymentStrategy", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessController", + "type": "address" + } + ], + "name": "setConfigAC", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + }, + { + "internalType": "address", + "name": "gasPriceL1FeedAddr", + "type": "address" + } + ], + "name": "setGasConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum ArbitrumValidator.PaymentStrategy", + "name": "_paymentStrategy", + "type": "uint8" + } + ], + "name": "setPaymentStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "refundAddr", + "type": "address" + } + ], + "name": "withdrawFundsFromL2", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawFundsTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json new file mode 100644 index 0000000..07c084e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json @@ -0,0 +1,164 @@ +[ + { + "inputs": [ + { + "internalType": "address[]", + "name": "authorizedCallers", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "UnauthorizedCaller", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "AuthorizedCallerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "AuthorizedCallerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address[]", + "name": "addedCallers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "removedCallers", + "type": "address[]" + } + ], + "internalType": "struct AuthorizedCallers.AuthorizedCallerArgs", + "name": "authorizedCallerArgs", + "type": "tuple" + } + ], + "name": "applyAuthorizedCallerUpdates", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllAuthorizedCallers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json new file mode 100644 index 0000000..a810c4c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json @@ -0,0 +1,286 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "OwnershipTransferRequestedWithMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isAuthorizedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tos", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "datas", + "type": "bytes[]" + } + ], + "name": "multiForward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ownerForward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSenders", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "transferOwnershipWithMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json new file mode 100644 index 0000000..946d5ed --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json @@ -0,0 +1,66 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "inputs": [], + "name": "getAuthorizedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isAuthorizedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSenders", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json new file mode 100644 index 0000000..b544978 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json @@ -0,0 +1,7 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json new file mode 100644 index 0000000..aae2720 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json @@ -0,0 +1,44 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json new file mode 100644 index 0000000..e934ed8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json new file mode 100644 index 0000000..1976f74 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json @@ -0,0 +1,212 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct IAutomationV21PlusCommon.ConditionalTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_conditionalTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "", + "type": "tuple" + } + ], + "name": "_log", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "logBlockHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "logIndex", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct IAutomationV21PlusCommon.LogTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_logTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "filterSelector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "internalType": "struct IAutomationV21PlusCommon.LogTriggerConfig", + "name": "", + "type": "tuple" + } + ], + "name": "_logTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "gasLimits", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "triggers", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "performDatas", + "type": "bytes[]" + } + ], + "internalType": "struct IAutomationV21PlusCommon.Report", + "name": "", + "type": "tuple" + } + ], + "name": "_report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json new file mode 100644 index 0000000..b165a3b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json @@ -0,0 +1,212 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialCall", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nextEligible", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "range", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "firstEligibleBuffer", + "type": "uint256" + } + ], + "name": "checkEligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getCountPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "initialCall", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nextEligible", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json new file mode 100644 index 0000000..b7d64b9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json @@ -0,0 +1,69 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "logic", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json new file mode 100644 index 0000000..7b3cdce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json @@ -0,0 +1,41 @@ +[ + { + "inputs": [], + "name": "getRegistry", + "outputs": [ + { + "internalType": "contract IAutomationRegistryConsumer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newRegistry", + "type": "address" + } + ], + "name": "updateRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json new file mode 100644 index 0000000..be5426f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json @@ -0,0 +1,761 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "LINKAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "enum AutomationRegistrar2_1.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistrar2_1.InitialTriggerConfig[]", + "name": "triggerConfigs", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "FunctionNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "HashMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientPayment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAdminAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "LinkTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdminOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyLink", + "type": "error" + }, + { + "inputs": [], + "name": "RegistrationRequestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "RequestNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "SenderMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AutoApproveAllowedSenderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "ConfigChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "RegistrationApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "RegistrationRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "RegistrationRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum AutomationRegistrar2_1.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "name": "TriggerConfigSet", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + } + ], + "name": "getAutoApproveAllowedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minLINKJuels", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getPendingRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + } + ], + "name": "getTriggerRegistrationDetails", + "outputs": [ + { + "components": [ + { + "internalType": "enum AutomationRegistrar2_1.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "approvedCount", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistrar2_1.TriggerRegistrationStorage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistrar2_1.RegistrationParams", + "name": "requestParams", + "type": "tuple" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAutoApproveAllowedSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "enum AutomationRegistrar2_1.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "name": "setTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json new file mode 100644 index 0000000..77d85ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json @@ -0,0 +1,745 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "LINKAddress", + "type": "address" + }, + { + "internalType": "contract IAutomationRegistryMaster2_3", + "name": "registry", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "enum AutomationRegistrar2_3.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistrar2_3.InitialTriggerConfig[]", + "name": "triggerConfigs", + "type": "tuple[]" + }, + { + "internalType": "contract IERC20Metadata[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "minRegistrationFees", + "type": "uint256[]" + }, + { + "internalType": "contract IWrappedNative", + "name": "wrappedNativeToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "HashMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientPayment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAdminAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBillingToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdminOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyLink", + "type": "error" + }, + { + "inputs": [], + "name": "RequestNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "TransferFailed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AutoApproveAllowedSenderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ConfigChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "RegistrationApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "RegistrationRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "RegistrationRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum AutomationRegistrar2_3.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "name": "TriggerConfigSet", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct AutomationRegistrar2_3.RegistrationParams", + "name": "requestParams", + "type": "tuple" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + } + ], + "name": "getAutoApproveAllowedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getMinimumRegistrationAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getPendingRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRegistry", + "outputs": [ + { + "internalType": "contract IAutomationRegistryMaster2_3", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + } + ], + "name": "getTriggerRegistrationDetails", + "outputs": [ + { + "components": [ + { + "internalType": "enum AutomationRegistrar2_3.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "approvedCount", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistrar2_3.TriggerRegistrationStorage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_WRAPPED_NATIVE_TOKEN", + "outputs": [ + { + "internalType": "contract IWrappedNative", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct AutomationRegistrar2_3.RegistrationParams", + "name": "requestParams", + "type": "tuple" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAutoApproveAllowedSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAutomationRegistryMaster2_3", + "name": "registry", + "type": "address" + }, + { + "internalType": "contract IERC20Metadata[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "minBalances", + "type": "uint256[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "enum AutomationRegistrar2_3.AutoApproveType", + "name": "autoApproveType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + } + ], + "name": "setTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json new file mode 100644 index 0000000..15eee02 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json @@ -0,0 +1,1367 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryLogicB2_2", + "name": "logicA", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "internalType": "struct AutomationRegistryBase2_2.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json new file mode 100644 index 0000000..741f78a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json @@ -0,0 +1,1580 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryLogicA2_3", + "name": "logicA", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "contract IERC20Metadata[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig[]", + "name": "billingConfigs", + "type": "tuple[]" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json new file mode 100644 index 0000000..f954e83 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json @@ -0,0 +1,952 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json new file mode 100644 index 0000000..65619c1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json @@ -0,0 +1,1180 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json new file mode 100644 index 0000000..fa6a597 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json @@ -0,0 +1,403 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getKeeperInfo", + "outputs": [ + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + } + ], + "internalType": "struct State", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "lastKeeper", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json new file mode 100644 index 0000000..d90e80e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maxLinkPayment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adjustedGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkEth", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getKeeperInfo", + "outputs": [ + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + } + ], + "internalType": "struct State", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "lastKeeper", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json new file mode 100644 index 0000000..f4401b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json @@ -0,0 +1,447 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maxLinkPayment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "gasWei", + "type": "int256" + }, + { + "internalType": "int256", + "name": "linkEth", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getKeeperInfo", + "outputs": [ + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + } + ], + "internalType": "struct State", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "lastKeeper", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json new file mode 100644 index 0000000..dc01d9e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json @@ -0,0 +1,1334 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryLogicB2_2", + "name": "logicB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "enum AutomationRegistryBase2_2.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json new file mode 100644 index 0000000..b62adce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json @@ -0,0 +1,1329 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryLogicB2_3", + "name": "logicB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "enum AutomationRegistryBase2_3.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json new file mode 100644 index 0000000..17ee845 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json @@ -0,0 +1,1998 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "automationForwarderLogic", + "type": "address" + }, + { + "internalType": "address", + "name": "allowedReadOnlyAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "contract IAutomationForwarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum AutomationRegistryBase2_2.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum AutomationRegistryBase2_2.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataFixedBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataPerSignerBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "enum AutomationRegistryBase2_2.Trigger", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum AutomationRegistryBase2_2.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json new file mode 100644 index 0000000..58d04d2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json @@ -0,0 +1,1672 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryLogicC2_3", + "name": "logicC", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "removeBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "billingOverrides", + "type": "tuple" + } + ], + "name": "setBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawERC20Fees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json new file mode 100644 index 0000000..163ac51 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json @@ -0,0 +1,2678 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkUSDFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeUSDFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "automationForwarderLogic", + "type": "address" + }, + { + "internalType": "address", + "name": "allowedReadOnlyAddress", + "type": "address" + }, + { + "internalType": "enum AutomationRegistryBase2_3.PayoutMode", + "name": "payoutMode", + "type": "uint8" + }, + { + "internalType": "address", + "name": "wrappedNativeTokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableOffchainPayments", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getAvailableERC20ForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getBillingConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverrides", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverridesEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingToken", + "outputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + } + ], + "name": "getBillingTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBillingTokens", + "outputs": [ + { + "internalType": "contract IERC20Metadata[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackNativePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "contract IAutomationForwarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getHotVars", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reentrancyGuard", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.HotVars", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "enum AutomationRegistryBase2_3.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNativeUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNumUpkeeps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPayoutMode", + "outputs": [ + { + "internalType": "enum AutomationRegistryBase2_3.PayoutMode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum AutomationRegistryBase2_3.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getReserveAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStorage", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistryBase2_3.Storage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataFixedBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataPerSignerBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmittersWithPayees", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transmitterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "payeeAddress", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "enum AutomationRegistryBase2_3.Trigger", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNativeTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum AutomationRegistryBase2_3.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "settleNOPsOffchain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + } + ], + "name": "supportsBillingToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json new file mode 100644 index 0000000..a05ca44 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json @@ -0,0 +1,302 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct KeeperRegistryBase2_1.ConditionalTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_conditionalTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "", + "type": "tuple" + } + ], + "name": "_log", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "logBlockHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "logIndex", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct KeeperRegistryBase2_1.LogTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_logTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "filterSelector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "internalType": "struct LogTriggerConfig", + "name": "", + "type": "tuple" + } + ], + "name": "_logTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "", + "type": "tuple" + } + ], + "name": "_onChainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "gasLimits", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "triggers", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "performDatas", + "type": "bytes[]" + } + ], + "internalType": "struct KeeperRegistryBase2_1.Report", + "name": "", + "type": "tuple" + } + ], + "name": "_report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json new file mode 100644 index 0000000..10f5012 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json @@ -0,0 +1,302 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct AutomationRegistryBase2_2.ConditionalTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_conditionalTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "", + "type": "tuple" + } + ], + "name": "_log", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "logBlockHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "logIndex", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNum", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "internalType": "struct AutomationRegistryBase2_2.LogTrigger", + "name": "", + "type": "tuple" + } + ], + "name": "_logTrigger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint8", + "name": "filterSelector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "internalType": "struct LogTriggerConfig", + "name": "", + "type": "tuple" + } + ], + "name": "_logTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "", + "type": "tuple" + } + ], + "name": "_onChainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "gasLimits", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "triggers", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "performDatas", + "type": "bytes[]" + } + ], + "internalType": "struct AutomationRegistryBase2_2.Report", + "name": "", + "type": "tuple" + } + ], + "name": "_report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json new file mode 100644 index 0000000..9f044b0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json @@ -0,0 +1,47 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "gasLimits", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "triggers", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "performDatas", + "type": "bytes[]" + } + ], + "internalType": "struct AutomationRegistryBase2_3.Report", + "name": "", + "type": "tuple" + } + ], + "name": "_report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json new file mode 100644 index 0000000..dc34fd9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json @@ -0,0 +1,562 @@ +[ + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "NoDataPresent", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1SenderTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int256", + "name": "status", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "updatedAt", + "type": "uint64" + } + ], + "name": "RoundUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "latestStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "latestTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bool", + "name": "incomingStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "incomingTimestamp", + "type": "uint64" + } + ], + "name": "UpdateIgnored", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Sender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json new file mode 100644 index 0000000..a91c406 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json @@ -0,0 +1,314 @@ +[ + { + "inputs": [], + "name": "L1CrossDomainMessengerAddressZero", + "type": "error" + }, + { + "inputs": [], + "name": "L2UptimeFeedAddrZero", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "GasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_UPTIME_FEED_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json new file mode 100644 index 0000000..234365f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json @@ -0,0 +1,211 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_specId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "price", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + } + ], + "name": "addExternalRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "_callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_expiration", + "type": "uint256" + } + ], + "name": "cancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_price", + "type": "bytes32" + } + ], + "name": "fulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPrice", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestEthereumPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_callback", + "type": "address" + } + ], + "name": "requestEthereumPriceByCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json new file mode 100644 index 0000000..0c7bfe4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json @@ -0,0 +1,76 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStoreAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BHS", + "outputs": [ + { + "internalType": "contract BlockhashStore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "blockNumbers", + "type": "uint256[]" + } + ], + "name": "getBlockhashes", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "blockNumbers", + "type": "uint256[]" + } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "blockNumbers", + "type": "uint256[]" + }, + { + "internalType": "bytes[]", + "name": "headers", + "type": "bytes[]" + } + ], + "name": "storeVerifyHeader", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json new file mode 100644 index 0000000..9a97cfa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json @@ -0,0 +1,156 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "ErrorReturned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lowLevelData", + "type": "bytes" + } + ], + "name": "RawErrorReturned", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof[]", + "name": "proofs", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "internalType": "struct VRFTypes.RequestCommitment[]", + "name": "rcs", + "type": "tuple[]" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json new file mode 100644 index 0000000..9f5642c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json @@ -0,0 +1,161 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "ErrorReturned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lowLevelData", + "type": "bytes" + } + ], + "name": "RawErrorReturned", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2PlusFulfill", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof[]", + "name": "proofs", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus[]", + "name": "rcs", + "type": "tuple[]" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json new file mode 100644 index 0000000..fdf9512 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json @@ -0,0 +1,52 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getBlockhash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "header", + "type": "bytes" + } + ], + "name": "storeVerifyHeader", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json new file mode 100644 index 0000000..7e9ac19 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + } + ], + "name": "getBlockhash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json new file mode 100644 index 0000000..8b54d23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json @@ -0,0 +1,45 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "reason", + "type": "string" + }, + { + "internalType": "int256", + "name": "reason2", + "type": "int256" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "revertSilently", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "revertWithCustomError", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "revertWithMessage", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json new file mode 100644 index 0000000..283b77c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json @@ -0,0 +1,784 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "maxSupply_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "supplyAfterMint", + "type": "uint256" + } + ], + "name": "MaxSupplyExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotBurner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotMinter", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBurners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "grantBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAndMinter", + "type": "address" + } + ], + "name": "grantMintAndBurnRoles", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "isBurner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "revokeBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "revokeMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json new file mode 100644 index 0000000..ba347ee --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json @@ -0,0 +1,7 @@ +[ + { + "inputs": [], + "name": "MalformedData", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json new file mode 100644 index 0000000..d5bdb35 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json @@ -0,0 +1,17 @@ +[ + { + "inputs": [], + "name": "NoContract", + "type": "error" + }, + { + "inputs": [], + "name": "NoGasForCallExactCheck", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGasForCall", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json new file mode 100644 index 0000000..67a5c4f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json @@ -0,0 +1,124 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + } + ], + "name": "callWithExactGas", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + } + ], + "name": "callWithExactGasEvenIfTargetIsNoContract", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bool", + "name": "sufficientGas", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxReturnBytes", + "type": "uint16" + } + ], + "name": "callWithExactGasSafeReturnData", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "retData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json new file mode 100644 index 0000000..589b6ad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "callback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCallbacksReceived", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json new file mode 100644 index 0000000..14e1f1a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json @@ -0,0 +1,1324 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AccessForbidden", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "CapabilityAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "CapabilityDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "CapabilityIsDeprecated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "CapabilityRequiredByDON", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "DONDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + } + ], + "name": "DuplicateDONCapability", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + } + ], + "name": "DuplicateDONNode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedConfigurationContract", + "type": "address" + } + ], + "name": "InvalidCapabilityConfigurationContractInterface", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "nodeCount", + "type": "uint256" + } + ], + "name": "InvalidFaultTolerance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + } + ], + "name": "InvalidNodeCapabilities", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "encryptionPublicKey", + "type": "bytes32" + } + ], + "name": "InvalidNodeEncryptionPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidNodeOperatorAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + } + ], + "name": "InvalidNodeP2PId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidNodeSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "lengthOne", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lengthTwo", + "type": "uint256" + } + ], + "name": "LengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + } + ], + "name": "NodeAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + } + ], + "name": "NodeDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + } + ], + "name": "NodeDoesNotSupportCapability", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + } + ], + "name": "NodeOperatorDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + } + ], + "name": "NodePartOfCapabilitiesDON", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "nodeP2PId", + "type": "bytes32" + } + ], + "name": "NodePartOfWorkflowDON", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "CapabilityConfigured", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "CapabilityDeprecated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + } + ], + "name": "NodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NodeOperatorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + } + ], + "name": "NodeOperatorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "NodeOperatorUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + } + ], + "name": "NodeRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + } + ], + "name": "NodeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "labelledName", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityType", + "name": "capabilityType", + "type": "uint8" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", + "name": "responseType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "configurationContract", + "type": "address" + } + ], + "internalType": "struct CapabilitiesRegistry.Capability[]", + "name": "capabilities", + "type": "tuple[]" + } + ], + "name": "addCapabilities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "nodes", + "type": "bytes32[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", + "name": "capabilityConfigurations", + "type": "tuple[]" + }, + { + "internalType": "bool", + "name": "isPublic", + "type": "bool" + }, + { + "internalType": "bool", + "name": "acceptsWorkflows", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "name": "addDON", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeOperator[]", + "name": "nodeOperators", + "type": "tuple[]" + } + ], + "name": "addNodeOperators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "encryptionPublicKey", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeParams[]", + "name": "nodes", + "type": "tuple[]" + } + ], + "name": "addNodes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + } + ], + "name": "deprecateCapabilities", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCapabilities", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "hashedId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "labelledName", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityType", + "name": "capabilityType", + "type": "uint8" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", + "name": "responseType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "configurationContract", + "type": "address" + }, + { + "internalType": "bool", + "name": "isDeprecated", + "type": "bool" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedId", + "type": "bytes32" + } + ], + "name": "getCapability", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "hashedId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "labelledName", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityType", + "name": "capabilityType", + "type": "uint8" + }, + { + "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", + "name": "responseType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "configurationContract", + "type": "address" + }, + { + "internalType": "bool", + "name": "isDeprecated", + "type": "bool" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + } + ], + "name": "getCapabilityConfigs", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "getDON", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "id", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "isPublic", + "type": "bool" + }, + { + "internalType": "bool", + "name": "acceptsWorkflows", + "type": "bool" + }, + { + "internalType": "bytes32[]", + "name": "nodeP2PIds", + "type": "bytes32[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", + "name": "capabilityConfigurations", + "type": "tuple[]" + } + ], + "internalType": "struct CapabilitiesRegistry.DONInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDONs", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "id", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "isPublic", + "type": "bool" + }, + { + "internalType": "bool", + "name": "acceptsWorkflows", + "type": "bool" + }, + { + "internalType": "bytes32[]", + "name": "nodeP2PIds", + "type": "bytes32[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", + "name": "capabilityConfigurations", + "type": "tuple[]" + } + ], + "internalType": "struct CapabilitiesRegistry.DONInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "labelledName", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + } + ], + "name": "getHashedCapabilityId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + } + ], + "name": "getNode", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "workflowDONId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "encryptionPublicKey", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + }, + { + "internalType": "uint256[]", + "name": "capabilitiesDONIds", + "type": "uint256[]" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeInfo", + "name": "nodeInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + } + ], + "name": "getNodeOperator", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeOperator", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNodeOperators", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeOperator[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNodes", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "workflowDONId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "encryptionPublicKey", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + }, + { + "internalType": "uint256[]", + "name": "capabilitiesDONIds", + "type": "uint256[]" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hashedCapabilityId", + "type": "bytes32" + } + ], + "name": "isCapabilityDeprecated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "donIds", + "type": "uint32[]" + } + ], + "name": "removeDONs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "nodeOperatorIds", + "type": "uint32[]" + } + ], + "name": "removeNodeOperators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "removedNodeP2PIds", + "type": "bytes32[]" + } + ], + "name": "removeNodes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "nodes", + "type": "bytes32[]" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "capabilityId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", + "name": "capabilityConfigurations", + "type": "tuple[]" + }, + { + "internalType": "bool", + "name": "isPublic", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "name": "updateDON", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "nodeOperatorIds", + "type": "uint32[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeOperator[]", + "name": "nodeOperators", + "type": "tuple[]" + } + ], + "name": "updateNodeOperators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nodeOperatorId", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "signer", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "p2pId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "encryptionPublicKey", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "hashedCapabilityIds", + "type": "bytes32[]" + } + ], + "internalType": "struct CapabilitiesRegistry.NodeParams[]", + "name": "nodes", + "type": "tuple[]" + } + ], + "name": "updateNodes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json new file mode 100644 index 0000000..e340a6e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json @@ -0,0 +1,74 @@ +[ + { + "anonymous": false, + "inputs": [], + "name": "CapabilityConfigurationSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "beforeCapabilityConfigSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "getCapabilityConfiguration", + "outputs": [ + { + "internalType": "bytes", + "name": "configuration", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json new file mode 100644 index 0000000..256eeb1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "l1Fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "maxL1Fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json new file mode 100644 index 0000000..3612098 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json @@ -0,0 +1,888 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "StaticBytes", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int32", + "name": "field", + "type": "int32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "oracleId", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "indexed": false, + "internalType": "struct MidLevelDynamicTestStruct", + "name": "nestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "indexed": false, + "internalType": "struct MidLevelStaticTestStruct", + "name": "nestedStaticStruct", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint8[32]", + "name": "oracleIds", + "type": "uint8[32]" + }, + { + "indexed": false, + "internalType": "address", + "name": "Account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "Accounts", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "string", + "name": "differentField", + "type": "string" + }, + { + "indexed": false, + "internalType": "int192", + "name": "bigField", + "type": "int192" + } + ], + "name": "Triggered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "fieldHash", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "field", + "type": "string" + } + ], + "name": "TriggeredEventWithDynamicTopic", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int32", + "name": "field1", + "type": "int32" + }, + { + "indexed": true, + "internalType": "int32", + "name": "field2", + "type": "int32" + }, + { + "indexed": true, + "internalType": "int32", + "name": "field3", + "type": "int32" + } + ], + "name": "TriggeredWithFourTopics", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "string", + "name": "field1", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint8[32]", + "name": "field2", + "type": "uint8[32]" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "field3", + "type": "bytes32" + } + ], + "name": "TriggeredWithFourTopicsWithHashed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int32", + "name": "field", + "type": "int32" + }, + { + "internalType": "string", + "name": "differentField", + "type": "string" + }, + { + "internalType": "uint8", + "name": "oracleId", + "type": "uint8" + }, + { + "internalType": "uint8[32]", + "name": "oracleIds", + "type": "uint8[32]" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "int192", + "name": "bigField", + "type": "int192" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelDynamicTestStruct", + "name": "nestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelStaticTestStruct", + "name": "nestedStaticStruct", + "type": "tuple" + } + ], + "name": "addTestStruct", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAlterablePrimitiveValue", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDifferentPrimitiveValue", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "i", + "type": "uint256" + } + ], + "name": "getElementAtIndex", + "outputs": [ + { + "components": [ + { + "internalType": "int32", + "name": "Field", + "type": "int32" + }, + { + "internalType": "string", + "name": "DifferentField", + "type": "string" + }, + { + "internalType": "uint8", + "name": "OracleId", + "type": "uint8" + }, + { + "internalType": "uint8[32]", + "name": "OracleIds", + "type": "uint8[32]" + }, + { + "internalType": "address", + "name": "Account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "Accounts", + "type": "address[]" + }, + { + "internalType": "int192", + "name": "BigField", + "type": "int192" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelDynamicTestStruct", + "name": "NestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelStaticTestStruct", + "name": "NestedStaticStruct", + "type": "tuple" + } + ], + "internalType": "struct TestStruct", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPrimitiveValue", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getSliceValue", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int32", + "name": "field", + "type": "int32" + }, + { + "internalType": "string", + "name": "differentField", + "type": "string" + }, + { + "internalType": "uint8", + "name": "oracleId", + "type": "uint8" + }, + { + "internalType": "uint8[32]", + "name": "oracleIds", + "type": "uint8[32]" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "int192", + "name": "bigField", + "type": "int192" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelDynamicTestStruct", + "name": "nestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelStaticTestStruct", + "name": "nestedStaticStruct", + "type": "tuple" + } + ], + "name": "returnSeen", + "outputs": [ + { + "components": [ + { + "internalType": "int32", + "name": "Field", + "type": "int32" + }, + { + "internalType": "string", + "name": "DifferentField", + "type": "string" + }, + { + "internalType": "uint8", + "name": "OracleId", + "type": "uint8" + }, + { + "internalType": "uint8[32]", + "name": "OracleIds", + "type": "uint8[32]" + }, + { + "internalType": "address", + "name": "Account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "Accounts", + "type": "address[]" + }, + { + "internalType": "int192", + "name": "BigField", + "type": "int192" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelDynamicTestStruct", + "name": "NestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelStaticTestStruct", + "name": "NestedStaticStruct", + "type": "tuple" + } + ], + "internalType": "struct TestStruct", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "value", + "type": "uint64" + } + ], + "name": "setAlterablePrimitiveValue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int32", + "name": "field", + "type": "int32" + }, + { + "internalType": "uint8", + "name": "oracleId", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "string", + "name": "S", + "type": "string" + } + ], + "internalType": "struct InnerDynamicTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelDynamicTestStruct", + "name": "nestedDynamicStruct", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes2", + "name": "FixedBytes", + "type": "bytes2" + }, + { + "components": [ + { + "internalType": "int64", + "name": "IntVal", + "type": "int64" + }, + { + "internalType": "address", + "name": "A", + "type": "address" + } + ], + "internalType": "struct InnerStaticTestStruct", + "name": "Inner", + "type": "tuple" + } + ], + "internalType": "struct MidLevelStaticTestStruct", + "name": "nestedStaticStruct", + "type": "tuple" + }, + { + "internalType": "uint8[32]", + "name": "oracleIds", + "type": "uint8[32]" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "string", + "name": "differentField", + "type": "string" + }, + { + "internalType": "int192", + "name": "bigField", + "type": "int192" + } + ], + "name": "triggerEvent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "field", + "type": "string" + } + ], + "name": "triggerEventWithDynamicTopic", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "val1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "val2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "val3", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "val4", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "val5", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "val6", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "val7", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "raw", + "type": "bytes" + } + ], + "name": "triggerStaticBytes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int32", + "name": "field1", + "type": "int32" + }, + { + "internalType": "int32", + "name": "field2", + "type": "int32" + }, + { + "internalType": "int32", + "name": "field3", + "type": "int32" + } + ], + "name": "triggerWithFourTopics", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "field1", + "type": "string" + }, + { + "internalType": "uint8[32]", + "name": "field2", + "type": "uint8[32]" + }, + { + "internalType": "bytes32", + "name": "field3", + "type": "bytes32" + } + ], + "name": "triggerWithFourTopicsWithHashed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json new file mode 100644 index 0000000..85ca246 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json @@ -0,0 +1,72 @@ +[ + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "name": "getBlockhash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "txCallData", + "type": "string" + } + ], + "name": "getCurrentTxL1GasFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "calldataSize", + "type": "uint256" + } + ], + "name": "getL1CalldataGasCost", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json new file mode 100644 index 0000000..6037a4b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json @@ -0,0 +1,30 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "fallbackAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json new file mode 100644 index 0000000..57999bd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json @@ -0,0 +1,41 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json new file mode 100644 index 0000000..e5c226d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json @@ -0,0 +1,125 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "inputs": [], + "name": "FULFILL_SELECTOR", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "cancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "fulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "op", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json new file mode 100644 index 0000000..14bfa8f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json @@ -0,0 +1,357 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LinkAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "callbackfunctionSelector", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Request", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "fulfillRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + } + ], + "name": "publicAddExternalRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "_callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_expiration", + "type": "uint256" + } + ], + "name": "publicCancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "publicChainlinkToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "publicFulfillChainlinkRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "publicLINK", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_fulfillmentSignature", + "type": "bytes" + } + ], + "name": "publicNewRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "publicOracleAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_fulfillmentSignature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_wei", + "type": "uint256" + } + ], + "name": "publicRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_fulfillmentSignature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_wei", + "type": "uint256" + } + ], + "name": "publicRequestOracleData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_fulfillmentSignature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_wei", + "type": "uint256" + } + ], + "name": "publicRequestOracleDataFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_fulfillmentSignature", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_wei", + "type": "uint256" + } + ], + "name": "publicRequestRunTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json new file mode 100644 index 0000000..35ea584 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json @@ -0,0 +1,78 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "cancelOracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "requestPrice", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "serviceAgreementID", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "oracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json new file mode 100644 index 0000000..7470682 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json @@ -0,0 +1,125 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "RequestData", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_key", + "type": "string" + }, + { + "internalType": "string", + "name": "_value", + "type": "string" + } + ], + "name": "add", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "_value", + "type": "bytes" + } + ], + "name": "addBytes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_key", + "type": "string" + }, + { + "internalType": "int256", + "name": "_value", + "type": "int256" + } + ], + "name": "addInt", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_key", + "type": "string" + }, + { + "internalType": "string[]", + "name": "_values", + "type": "string[]" + } + ], + "name": "addStringArray", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_key", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "addUint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeEvent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setBuffer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json new file mode 100644 index 0000000..57999bd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json @@ -0,0 +1,41 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json new file mode 100644 index 0000000..62eaf54 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json @@ -0,0 +1,164 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "donId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "sha", + "type": "bytes32" + } + ], + "name": "NewChannelDefinition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "sha", + "type": "bytes32" + } + ], + "name": "setChannelDefinitions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json new file mode 100644 index 0000000..c8ea294 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json @@ -0,0 +1,257 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSigners", + "type": "uint256" + } + ], + "name": "ExcessSigners", + "type": "error" + }, + { + "inputs": [], + "name": "FaultToleranceMustBePositive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSigners", + "type": "uint256" + } + ], + "name": "InsufficientSigners", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "isVerifier", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json new file mode 100644 index 0000000..73d188c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json @@ -0,0 +1,84 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json new file mode 100644 index 0000000..81f35ae --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json @@ -0,0 +1,91 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "Here", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "modifierOnlyOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json new file mode 100644 index 0000000..db68d10 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json @@ -0,0 +1,89 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "pendingOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json new file mode 100644 index 0000000..7b93800 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json @@ -0,0 +1,190 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "price", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + } + ], + "name": "addExternalRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "_callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_expiration", + "type": "uint256" + } + ], + "name": "cancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_price", + "type": "bytes32" + } + ], + "name": "fulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPrice", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestEthereumPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_callback", + "type": "address" + } + ], + "name": "requestEthereumPriceByCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json new file mode 100644 index 0000000..1d93c6e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json @@ -0,0 +1,54 @@ +[ + { + "inputs": [], + "name": "AlwaysRevert", + "type": "error" + }, + { + "inputs": [], + "name": "alwaysRevert", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "alwaysRevertWithString", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "increment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json new file mode 100644 index 0000000..1af3931 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json @@ -0,0 +1,1218 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "field", + "type": "string" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidField", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidSpec", + "type": "error" + }, + { + "inputs": [], + "name": "ListTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownFieldType", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "minute", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "hour", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "day", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "month", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "dayOfWeek", + "type": "tuple" + } + ], + "internalType": "struct Spec", + "name": "spec", + "type": "tuple" + } + ], + "name": "lastTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "minute", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "hour", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "day", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "month", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "dayOfWeek", + "type": "tuple" + } + ], + "internalType": "struct Spec", + "name": "spec", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "matches", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "minute", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "hour", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "day", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "month", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "dayOfWeek", + "type": "tuple" + } + ], + "internalType": "struct Spec", + "name": "spec", + "type": "tuple" + } + ], + "name": "nextTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "minute", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "hour", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "day", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "month", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "dayOfWeek", + "type": "tuple" + } + ], + "internalType": "struct Spec", + "name": "spec", + "type": "tuple" + } + ], + "name": "toCronString", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "toEncodedSpec", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "toSpec", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "minute", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "hour", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "day", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "month", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "enum FieldType", + "name": "fieldType", + "type": "FieldType" + }, + { + "internalType": "uint8", + "name": "singleValue", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "interval", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeStart", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "rangeEnd", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "listLength", + "type": "uint8" + }, + { + "internalType": "uint8[26]", + "name": "list", + "type": "uint8[26]" + } + ], + "internalType": "struct Field", + "name": "dayOfWeek", + "type": "tuple" + } + ], + "internalType": "struct Spec", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json new file mode 100644 index 0000000..3db6c40 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json @@ -0,0 +1,78 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "calculateLastTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "calculateNextTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "encodeCronString", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedSpec", + "type": "bytes" + } + ], + "name": "encodedSpecToString", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json new file mode 100644 index 0000000..e7e643b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json @@ -0,0 +1,115 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "field", + "type": "string" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidField", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidSpec", + "type": "error" + }, + { + "inputs": [], + "name": "ListTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownFieldType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "calculateLastTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "calculateNextTick", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "encodeCronString", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedSpec", + "type": "bytes" + } + ], + "name": "encodedSpecToString", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json new file mode 100644 index 0000000..b08bb5d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json @@ -0,0 +1,35 @@ +[ + { + "anonymous": false, + "inputs": [], + "name": "Received1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Received2", + "type": "event" + }, + { + "inputs": [], + "name": "handler1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "handler2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revertHandler", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json new file mode 100644 index 0000000..15f9c31 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json @@ -0,0 +1,449 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxJobs", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "firstJob", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CronJobIDNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ExceedsMaxJobs", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHandler", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "TickDoesntMatchSpec", + "type": "error" + }, + { + "inputs": [], + "name": "TickInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "TickTooOld", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownFieldType", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "handler", + "type": "bytes" + } + ], + "name": "CronJobCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CronJobDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "CronJobExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "handler", + "type": "bytes" + } + ], + "name": "CronJobUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "encodedCronSpec", + "type": "bytes" + } + ], + "name": "createCronJobFromEncodedSpec", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "deleteCronJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveCronJobIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getCronJob", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "string", + "name": "cronString", + "type": "string" + }, + { + "internalType": "uint256", + "name": "nextTick", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_maxJobs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newTarget", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newHandler", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "newEncodedCronSpec", + "type": "bytes" + } + ], + "name": "updateCronJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json new file mode 100644 index 0000000..46baaac --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json @@ -0,0 +1,31 @@ +[ + { + "inputs": [], + "name": "UnknownFieldType", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json new file mode 100644 index 0000000..3c413d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json @@ -0,0 +1,204 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "upkeep", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "NewCronUpkeepCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cronDelegateAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "encodeCronJob", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "encodeCronString", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "newCronUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedJob", + "type": "bytes" + } + ], + "name": "newCronUpkeepWithJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_maxJobs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxJobs", + "type": "uint256" + } + ], + "name": "setMaxJobs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json new file mode 100644 index 0000000..b569368 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json @@ -0,0 +1,517 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxJobs", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "firstJob", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CronJobIDNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ExceedsMaxJobs", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "field", + "type": "string" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidField", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidHandler", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "InvalidSpec", + "type": "error" + }, + { + "inputs": [], + "name": "ListTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "TickDoesntMatchSpec", + "type": "error" + }, + { + "inputs": [], + "name": "TickInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "TickTooOld", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownFieldType", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "handler", + "type": "bytes" + } + ], + "name": "CronJobCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CronJobDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "CronJobExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "handler", + "type": "bytes" + } + ], + "name": "CronJobUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "encodedCronSpec", + "type": "bytes" + } + ], + "name": "createCronJobFromEncodedSpec", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "string", + "name": "cronString", + "type": "string" + } + ], + "name": "createCronJobFromString", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "deleteCronJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveCronJobIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getCronJob", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + }, + { + "internalType": "string", + "name": "cronString", + "type": "string" + }, + { + "internalType": "uint256", + "name": "nextTick", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_maxJobs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "txCheckUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newTarget", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newHandler", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "newEncodedCronSpec", + "type": "bytes" + } + ], + "name": "updateCronJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json new file mode 100644 index 0000000..d64def7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json @@ -0,0 +1,162 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json new file mode 100644 index 0000000..693d75c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json @@ -0,0 +1,162 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json new file mode 100644 index 0000000..1e093a2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json @@ -0,0 +1,155 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "newl1Owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json new file mode 100644 index 0000000..1d16b21 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json @@ -0,0 +1,262 @@ +[ + { + "inputs": [], + "name": "ARS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "AUD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BRL", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BTC", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CAD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CHF", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CNY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EUR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GBP", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "JPY", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KRW", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NGN", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NZD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PHP", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RUB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SGD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USD", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ZAR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json new file mode 100644 index 0000000..3fd4237 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json @@ -0,0 +1,805 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_linkAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_nativeAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifierAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardManagerAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ExpiredReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDiscount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidQuote", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivingAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSurcharge", + "type": "error" + }, + { + "inputs": [], + "name": "PoolIdMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroDeficit", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct Common.Asset", + "name": "fee", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct Common.Asset", + "name": "reward", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "appliedDiscount", + "type": "uint256" + } + ], + "name": "DiscountApplied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "indexed": false, + "internalType": "struct IDestinationRewardManager.FeePayment[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "name": "InsufficientLink", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "linkQuantity", + "type": "uint256" + } + ], + "name": "LinkDeficitCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newSurcharge", + "type": "uint64" + } + ], + "name": "NativeSurchargeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "SubscriberDiscountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "addVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "address", + "name": "quoteAddress", + "type": "address" + } + ], + "name": "getFeeAndReward", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_nativeAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_rewardManager", + "outputs": [ + { + "internalType": "contract IDestinationRewardManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "payLinkDeficit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "removeVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_globalDiscounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_linkDeficit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_nativeSurcharge", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_subscriberDiscounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_verifierAddressList", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setFeeRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "surcharge", + "type": "uint64" + } + ], + "name": "setNativeSurcharge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rewardManagerAddress", + "type": "address" + } + ], + "name": "setRewardManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberGlobalDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json new file mode 100644 index 0000000..3974bc2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json @@ -0,0 +1,61 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeManager", + "type": "address" + } + ], + "name": "setDestinationFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json new file mode 100644 index 0000000..9aae5b2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json @@ -0,0 +1,554 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPoolId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPoolLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWeights", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newFeeManagerAddress", + "type": "address" + } + ], + "name": "FeeManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "indexed": false, + "internalType": "struct IDestinationRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "FeePaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "RewardRecipientsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "RewardsClaimed", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newFeeManagerAddress", + "type": "address" + } + ], + "name": "addFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "getAvailableRewardPoolIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "internalType": "struct IDestinationRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "onFeePaid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "payRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeManagerAddress", + "type": "address" + } + ], + "name": "removeFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_feeManagerAddressList", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_registeredPoolIds", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_rewardRecipientWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_rewardRecipientWeightsSet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_totalRewardRecipientFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_totalRewardRecipientFeesLastClaimedAmounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "updateRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json new file mode 100644 index 0000000..16b2372 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json @@ -0,0 +1,581 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "verifierProxy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessForbidden", + "type": "error" + }, + { + "inputs": [], + "name": "BadActivationTime", + "type": "error" + }, + { + "inputs": [], + "name": "BadVerification", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes24", + "name": "donConfigId", + "type": "bytes24" + } + ], + "name": "DonConfigAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "DonConfigDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSigners", + "type": "uint256" + } + ], + "name": "ExcessSigners", + "type": "error" + }, + { + "inputs": [], + "name": "FaultToleranceMustBePositive", + "type": "error" + }, + { + "inputs": [], + "name": "FeeManagerInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSigners", + "type": "uint256" + } + ], + "name": "InsufficientSigners", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ssLength", + "type": "uint256" + } + ], + "name": "MismatchedSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "NoSigners", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessController", + "type": "address" + } + ], + "name": "AccessControllerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes24", + "name": "donConfigId", + "type": "bytes24" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isActive", + "type": "bool" + } + ], + "name": "ConfigActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes24", + "name": "donConfigId", + "type": "bytes24" + } + ], + "name": "ConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes24", + "name": "donConfigId", + "type": "bytes24" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "donConfigIndex", + "type": "uint16" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldFeeManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newFeeManager", + "type": "address" + } + ], + "name": "FeeManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "requester", + "type": "address" + } + ], + "name": "ReportVerified", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "i_verifierProxy", + "outputs": [ + { + "internalType": "contract IDestinationVerifierProxy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "removeLatestConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_accessController", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessController", + "type": "address" + } + ], + "name": "setAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "donConfigIndex", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + } + ], + "name": "setConfigActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + }, + { + "internalType": "uint32", + "name": "activationTime", + "type": "uint32" + } + ], + "name": "setConfigWithActivationTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signedReport", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "signedReports", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verifyBulk", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json new file mode 100644 index 0000000..6a8e0cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json @@ -0,0 +1,213 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "VerifierInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_accessController", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "setVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verifyBulk", + "outputs": [ + { + "internalType": "bytes[]", + "name": "verifiedReports", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json new file mode 100644 index 0000000..010a2c4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json @@ -0,0 +1,214 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "exchange", + "type": "address" + } + ], + "name": "LimitOrderExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "LimitOrderSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "LimitOrderWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "exchange", + "type": "address" + } + ], + "name": "executeLimitOrder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetContract", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "t0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "t1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "t2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "t3", + "type": "bytes32" + } + ], + "name": "getAdvancedLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "t0", + "type": "bytes32" + } + ], + "name": "getBasicLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "sendLimitedOrder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "withdrawLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json new file mode 100644 index 0000000..618c81c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json @@ -0,0 +1,29 @@ +[ + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json new file mode 100644 index 0000000..24d1cb5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json @@ -0,0 +1,67 @@ +[ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json new file mode 100644 index 0000000..e622e77 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json @@ -0,0 +1,218 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "label", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "NewOwner", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "NewResolver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "ttl", + "type": "uint64" + } + ], + "name": "NewTTL", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "resolver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "label", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "setSubnodeOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "ttl", + "type": "uint64" + } + ], + "name": "setTTL", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "ttl", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json new file mode 100644 index 0000000..44ea5ee --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json new file mode 100644 index 0000000..53fa000 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json new file mode 100644 index 0000000..048513c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json @@ -0,0 +1,310 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json new file mode 100644 index 0000000..d74eb99 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json @@ -0,0 +1,505 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20TokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "duplicate", + "type": "address" + } + ], + "name": "DuplicateAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "ERC20TokenAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "topUpAddress", + "type": "address" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "oldWatchlist", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "newWatchlist", + "type": "address[]" + } + ], + "name": "WatchlistUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "getAccountInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpLevel", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getERC20TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "erc20TokenAddress", + "type": "address" + } + ], + "name": "setERC20TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "minBalances", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpLevels", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "needsFunding", + "type": "address[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json new file mode 100644 index 0000000..9f4be22 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json @@ -0,0 +1,523 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "erc20TokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "duplicate", + "type": "address" + } + ], + "name": "DuplicateAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "ERC20TokenAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "topUpAddress", + "type": "address" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "oldWatchlist", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "newWatchlist", + "type": "address[]" + } + ], + "name": "WatchlistUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "getAccountInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpLevel", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getERC20TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "erc20TokenAddress", + "type": "address" + } + ], + "name": "setERC20TokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "name": "setLastTopUpXXXTestOnly", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "minBalances", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpLevels", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "needsFunding", + "type": "address[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json new file mode 100644 index 0000000..59f1c94 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json @@ -0,0 +1,341 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json new file mode 100644 index 0000000..23105cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json @@ -0,0 +1,380 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "initialAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json new file mode 100644 index 0000000..23105cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json @@ -0,0 +1,380 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "address", + "name": "initialAccount", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approveInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferInternal", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json new file mode 100644 index 0000000..1e5f78e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json @@ -0,0 +1,347 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json new file mode 100644 index 0000000..9a10657 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json @@ -0,0 +1,348 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json new file mode 100644 index 0000000..dc9fef1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json @@ -0,0 +1,213 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "cancelOracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "fulfillOracleRequest", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getAuthorizationStatus", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "oracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "name": "setFulfillmentPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json new file mode 100644 index 0000000..d37f36b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json @@ -0,0 +1,1242 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bool", + "name": "targetSuccess", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "targetResult", + "type": "bytes" + } + ], + "name": "ExecutionResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "FailedOp", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderAddressResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureValidationFailed", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sigFailed", + "type": "bool" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "paymasterContext", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.ReturnInfo", + "name": "returnInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "senderInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "factoryInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "paymasterInfo", + "type": "tuple" + } + ], + "name": "ValidationResult", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sigFailed", + "type": "bool" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "paymasterContext", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.ReturnInfo", + "name": "returnInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "senderInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "factoryInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "paymasterInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "stakeInfo", + "type": "tuple" + } + ], + "internalType": "struct IEntryPoint.AggregatorStakeInfo", + "name": "aggregatorInfo", + "type": "tuple" + } + ], + "name": "ValidationResultWithAggregation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "factory", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "AccountDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDeposit", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureAggregatorChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawTime", + "type": "uint256" + } + ], + "name": "StakeUnlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasUsed", + "type": "uint256" + } + ], + "name": "UserOperationEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "revertReason", + "type": "bytes" + } + ], + "name": "UserOperationRevertReason", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [], + "name": "SIG_VALIDATION_FAILED", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + } + ], + "name": "_validateSenderAndPaymaster", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDepositInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "internalType": "struct IStakeManager.DepositInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "name": "getSenderAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "getUserOpHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "contract IAggregator", + "name": "aggregator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", + "name": "opsPerAggregator", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleAggregatedOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "ops", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + } + ], + "internalType": "struct EntryPoint.MemoryUserOp", + "name": "mUserOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "contextOffset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + } + ], + "internalType": "struct EntryPoint.UserOpInfo", + "name": "opInfo", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ], + "name": "innerHandleOp", + "outputs": [ + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "op", + "type": "tuple" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "targetCallData", + "type": "bytes" + } + ], + "name": "simulateHandleOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "simulateValidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json new file mode 100644 index 0000000..63ff459 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json @@ -0,0 +1,13 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "EnumerableMapNonexistentKey", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json new file mode 100644 index 0000000..162046f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json @@ -0,0 +1,7 @@ +[ + { + "inputs": [], + "name": "NonexistentKeyError", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json new file mode 100644 index 0000000..20ad3fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json @@ -0,0 +1,340 @@ +[ + { + "inputs": [], + "name": "FailedToActivateConfig", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToActivateFeed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToDeactivateConfig", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToDeactivateFeed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToGetLatestConfigDetails", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToGetLatestConfigDigestAndEpoch", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSetConfig", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToVerify", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "activateConfig", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "activateFeed", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "deactivateConfig", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "deactivateFeed", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "", + "type": "tuple[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "", + "type": "tuple[]" + } + ], + "name": "setConfigFromSource", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json new file mode 100644 index 0000000..67ccd39 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json @@ -0,0 +1,478 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "duplicate", + "type": "address" + } + ], + "name": "DuplicateAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "getAccountInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalanceWei", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpAmountWei", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "minBalancesWei", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmountsWei", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "needsFunding", + "type": "address[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json new file mode 100644 index 0000000..d7114e3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json @@ -0,0 +1,496 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriod", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "duplicate", + "type": "address" + } + ], + "name": "DuplicateAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "getAccountInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalanceWei", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpAmountWei", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "name": "setLastTopUpXXXTestOnly", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "minBalancesWei", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmountsWei", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "needsFunding", + "type": "address[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json new file mode 100644 index 0000000..b544978 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json @@ -0,0 +1,7 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json new file mode 100644 index 0000000..bbc6671 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json @@ -0,0 +1,183 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "donId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "version", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "sha", + "type": "bytes32" + } + ], + "name": "NewChannelDefinition", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "donId", + "type": "uint256" + } + ], + "name": "exposedReadChannelDefinitionStates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "sha", + "type": "bytes32" + } + ], + "name": "setChannelDefinitions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json new file mode 100644 index 0000000..68a50f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json @@ -0,0 +1,288 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSigners", + "type": "uint256" + } + ], + "name": "ExcessSigners", + "type": "error" + }, + { + "inputs": [], + "name": "FaultToleranceMustBePositive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSigners", + "type": "uint256" + } + ], + "name": "InsufficientSigners", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "exposedReadConfigurationStates", + "outputs": [ + { + "components": [ + { + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + } + ], + "internalType": "struct Configurator.ConfigurationState", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "isVerifier", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json new file mode 100644 index 0000000..8002cfd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json @@ -0,0 +1,2155 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "calculatePaymentAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "nonce", + "type": "uint64" + } + ], + "name": "computeRequestIdExternal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveSubscriptionIdsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + } + ], + "name": "getRandomnessFromProofExternal", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "internalType": "struct VRFCoordinatorV2_5.ProvingKey", + "name": "provingKey", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "internalType": "struct VRFCoordinatorV2_5.Output", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscriptionConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "internalType": "struct SubscriptionAPI.SubscriptionConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscriptionStruct", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + } + ], + "internalType": "struct SubscriptionAPI.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWithdrawableNativeTestingOnlyXXX", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWithdrawableTokensTestingOnlyXXX", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "isTargetRegisteredExternal", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "newBalance", + "type": "uint96" + } + ], + "name": "setTotalBalanceTestingOnlyXXX", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "newBalance", + "type": "uint96" + } + ], + "name": "setTotalNativeBalanceTestingOnlyXXX", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "newBalance", + "type": "uint96" + } + ], + "name": "setWithdrawableNativeTestingOnlyXXX", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "newBalance", + "type": "uint96" + } + ], + "name": "setWithdrawableTokensTestingOnlyXXX", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json new file mode 100644 index 0000000..8cf0307 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json @@ -0,0 +1,1858 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "calculatePaymentAmountLinkExternal", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "calculatePaymentAmountNativeExternal", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumberExternal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "name": "getBlockhashExternal", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json new file mode 100644 index 0000000..ac2a223 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json @@ -0,0 +1,1943 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCalculationMode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCalculationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "calculatePaymentAmountLinkExternal", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "calculatePaymentAmountNativeExternal", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumberExternal", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockNumber", + "type": "uint64" + } + ], + "name": "getBlockhashExternal", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCalculationMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCoefficient", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json new file mode 100644 index 0000000..de868ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json @@ -0,0 +1,71 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_feedId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_contractAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "_configCount", + "type": "uint64" + }, + { + "internalType": "address[]", + "name": "_signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "_offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_encodedConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_encodedConfig", + "type": "bytes" + } + ], + "name": "exposedConfigDigestFromConfigData", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json new file mode 100644 index 0000000..8e08d03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json @@ -0,0 +1,309 @@ +[ + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeConfig", + "outputs": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRequestConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json new file mode 100644 index 0000000..4acbde3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json @@ -0,0 +1,698 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_linkAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_nativeAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_proxyAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardManagerAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ExpiredReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDeposit", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDiscount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidQuote", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReceivingAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSurcharge", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroDeficit", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct Common.Asset", + "name": "fee", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct Common.Asset", + "name": "reward", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "appliedDiscount", + "type": "uint256" + } + ], + "name": "DiscountApplied", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "indexed": false, + "internalType": "struct IRewardManager.FeePayment[]", + "name": "rewards", + "type": "tuple[]" + } + ], + "name": "InsufficientLink", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "linkQuantity", + "type": "uint256" + } + ], + "name": "LinkDeficitCleared", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "newSurcharge", + "type": "uint64" + } + ], + "name": "NativeSurchargeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "SubscriberDiscountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "Withdraw", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "address", + "name": "quoteAddress", + "type": "address" + } + ], + "name": "getFeeAndReward", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_nativeAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_proxyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_rewardManager", + "outputs": [ + { + "internalType": "contract IRewardManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "payLinkDeficit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_linkDeficit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_nativeSurcharge", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_subscriberDiscounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setFeeRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "surcharge", + "type": "uint64" + } + ], + "name": "setNativeSurcharge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json new file mode 100644 index 0000000..45384ec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json @@ -0,0 +1,51 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFeeManager", + "name": "feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json new file mode 100644 index 0000000..6e3c561 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json @@ -0,0 +1,214 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "feedAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AGGREGATOR", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "answer", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json new file mode 100644 index 0000000..5c017df --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json @@ -0,0 +1,803 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "denomination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "latestAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "previousAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "nextPhaseId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeedConfirmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "denomination", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "proposedAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "currentAggregator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeedProposed", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "confirmFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "answer", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "getCurrentPhaseId", + "outputs": [ + { + "internalType": "uint16", + "name": "currentPhaseId", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "getFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + } + ], + "name": "getNextRoundId", + "outputs": [ + { + "internalType": "uint80", + "name": "nextRoundId", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint16", + "name": "phaseId", + "type": "uint16" + } + ], + "name": "getPhase", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "phaseId", + "type": "uint16" + }, + { + "internalType": "uint80", + "name": "startingAggregatorRoundId", + "type": "uint80" + }, + { + "internalType": "uint80", + "name": "endingAggregatorRoundId", + "type": "uint80" + } + ], + "internalType": "struct FeedRegistryInterface.Phase", + "name": "phase", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint16", + "name": "phaseId", + "type": "uint16" + } + ], + "name": "getPhaseFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint16", + "name": "phaseId", + "type": "uint16" + } + ], + "name": "getPhaseRange", + "outputs": [ + { + "internalType": "uint80", + "name": "startingRoundId", + "type": "uint80" + }, + { + "internalType": "uint80", + "name": "endingRoundId", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + } + ], + "name": "getPreviousRoundId", + "outputs": [ + { + "internalType": "uint80", + "name": "previousRoundId", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "getProposedFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "proposedAggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + } + ], + "name": "getRoundFeed", + "outputs": [ + { + "internalType": "contract AggregatorV2V3Interface", + "name": "aggregator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "isFeedEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "answer", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "proposeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + }, + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + } + ], + "name": "proposedGetRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "id", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "proposedLatestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "id", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "base", + "type": "address" + }, + { + "internalType": "address", + "name": "quote", + "type": "address" + } + ], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json new file mode 100644 index 0000000..b3129b3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json @@ -0,0 +1,423 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "racAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "lacAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "FlagLowered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "FlagRaised", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previous", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "current", + "type": "address" + } + ], + "name": "LoweringAccessControllerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previous", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "current", + "type": "address" + } + ], + "name": "RaisingAccessControllerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "getFlag", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "subjects", + "type": "address[]" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "lowerFlag", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "subjects", + "type": "address[]" + } + ], + "name": "lowerFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "loweringAccessController", + "outputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "raiseFlag", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "subjects", + "type": "address[]" + } + ], + "name": "raiseFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "raisingAccessController", + "outputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "lacAddress", + "type": "address" + } + ], + "name": "setLoweringAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "racAddress", + "type": "address" + } + ], + "name": "setRaisingAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json new file mode 100644 index 0000000..0bba7df --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json @@ -0,0 +1,92 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getFlag", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "lowerFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "raiseFlag", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "raiseFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setRaisingAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json new file mode 100644 index 0000000..f42ff6d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json @@ -0,0 +1,64 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "flagsContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "flags", + "outputs": [ + { + "internalType": "contract Flags", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subject", + "type": "address" + } + ], + "name": "getFlag", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "subjects", + "type": "address[]" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json new file mode 100644 index 0000000..e2cf0ce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json @@ -0,0 +1,533 @@ +[ + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "usdLink", + "type": "int256" + } + ], + "name": "InvalidUsdLinkPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoTransmittersSet", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouterOwner", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "RouterMustBeSet", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedRequestDataVersion", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "CommitmentDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "indexed": false, + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l1FeeShareWei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "callbackCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "donFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "adminFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "operationFeeJuels", + "type": "uint72" + } + ], + "name": "RequestBilled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "deleteCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + } + ], + "name": "estimateCost", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "getDONFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperationFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUsdPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeiPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracleWithdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json new file mode 100644 index 0000000..847c66f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json @@ -0,0 +1,839 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "signerPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "transmitterPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalCost", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "BillingEnd", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "don", + "type": "address" + }, + { + "internalType": "uint96", + "name": "donFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "registryFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "estimatedCost", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct FunctionsBillingRegistryEventsMock.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "BillingStart", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasAfterPaymentCalculation", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasOverhead", + "type": "uint32" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "emitAuthorizedSendersChanged", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "signerPayment", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "transmitterPayment", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "totalCost", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "emitBillingEnd", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "don", + "type": "address" + }, + { + "internalType": "uint96", + "name": "donFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "registryFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "estimatedCost", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct FunctionsBillingRegistryEventsMock.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "emitBillingStart", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasAfterPaymentCalculation", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "gasOverhead", + "type": "uint32" + } + ], + "name": "emitConfigSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitFundsRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "emitInitialized", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "emitRequestTimedOut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitSubscriptionCanceled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "emitSubscriptionConsumerAdded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "emitSubscriptionConsumerRemoved", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "emitSubscriptionCreated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "emitSubscriptionFunded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitSubscriptionOwnerTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitSubscriptionOwnerTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitUnpaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json new file mode 100644 index 0000000..450f733 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json @@ -0,0 +1,56 @@ +[ + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json new file mode 100644 index 0000000..7bef985 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json @@ -0,0 +1,280 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "UnexpectedRequestID", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_CALLBACK_GAS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastError", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastErrorLength", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastResponse", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastResponseLength", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedSecretsReferences", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "jobId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json new file mode 100644 index 0000000..4eed938 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json @@ -0,0 +1,460 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "ResponseReceived", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getRouter_HARNESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "bytesArgs", + "type": "bytes[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestBytes", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "bytesArgs", + "type": "bytes[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "uint8", + "name": "slotId", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "slotVersion", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestToProposedWithDONHostedSecrets", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "uint8", + "name": "slotId", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "slotVersion", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestWithDONHostedSecrets", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest_HARNESS", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json new file mode 100644 index 0000000..11784d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json @@ -0,0 +1,375 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "FulfillRequestInvoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "sourceCode", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "SendRequestInvoked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "acceptor", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + } + ], + "name": "acceptTermsOfService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "bytesArgs", + "type": "bytes[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourceCode", + "type": "string" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourceCode", + "type": "string" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendSimpleRequestWithJavaScript", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "on", + "type": "bool" + } + ], + "name": "setDoInvalidOperation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "on", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "setDoInvalidReentrantOperation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "on", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "setDoValidReentrantOperation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "on", + "type": "bool" + } + ], + "name": "setRevertFulfillRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "setRevertFulfillRequestMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json new file mode 100644 index 0000000..92d6d88 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json @@ -0,0 +1,413 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "result", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "ResponseReceived", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "bytesArgs", + "type": "bytes[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestBytes", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "bytes[]", + "name": "bytesArgs", + "type": "bytes[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "uint8", + "name": "slotId", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "slotVersion", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestToProposedWithDONHostedSecrets", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "uint8", + "name": "slotId", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "slotVersion", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendRequestWithDONHostedSecrets", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json new file mode 100644 index 0000000..03a59d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json @@ -0,0 +1,161 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "FulfillRequestInvoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "sourceCode", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "SendRequestInvoked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourceCode", + "type": "string" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "sendSimpleRequestWithJavaScript", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json new file mode 100644 index 0000000..ac8cfd2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json @@ -0,0 +1,1267 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address", + "name": "linkToNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "linkToUsdFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InconsistentReportData", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "usdLink", + "type": "int256" + } + ], + "name": "InvalidUsdLinkPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoTransmittersSet", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouterOwner", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "ReportInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "RouterMustBeSet", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedPublicKeyChange", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedRequestDataVersion", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "CommitmentDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "indexed": false, + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "callbackGasLimit", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "indexed": false, + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "OracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "OracleResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l1FeeShareWei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "callbackCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "donFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "adminFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "operationFeeJuels", + "type": "uint72" + } + ], + "name": "RequestBilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "deleteCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + } + ], + "name": "estimateCost", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "getDONFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDONPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperationFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThresholdPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUsdPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeiPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracleWithdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "donPublicKey", + "type": "bytes" + } + ], + "name": "setDONPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "thresholdPublicKey", + "type": "bytes" + } + ], + "name": "setThresholdPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "availableBalance", + "type": "uint96" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + } + ], + "internalType": "struct FunctionsResponse.RequestMeta", + "name": "request", + "type": "tuple" + } + ], + "name": "startRequest", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json new file mode 100644 index 0000000..0f719ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json @@ -0,0 +1,1664 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address", + "name": "linkToNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "linkToUsdFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InconsistentReportData", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "usdLink", + "type": "int256" + } + ], + "name": "InvalidUsdLinkPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoTransmittersSet", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouterOwner", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "ReportInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "RouterMustBeSet", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedPublicKeyChange", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedRequestDataVersion", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "CommitmentDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "indexed": false, + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "callbackGasLimit", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "indexed": false, + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "OracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "OracleResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l1FeeShareWei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "callbackCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "donFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "adminFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "operationFeeJuels", + "type": "uint72" + } + ], + "name": "RequestBilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + } + ], + "name": "beforeSetConfig_HARNESS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "operationFee", + "type": "uint72" + } + ], + "name": "calculateCostEstimate_HARNESS", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "deleteCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disperseFeePool_HARNESS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + } + ], + "name": "estimateCost", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "onchainMetadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainMetadata", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "reportBatchSize", + "type": "uint8" + } + ], + "name": "fulfillAndBill_HARNESS", + "outputs": [ + { + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "getDONFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDONPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkToNativeFeed_HARNESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkToUsdFeed_HARNESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperationFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRouter_HARNESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThresholdPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters_HARNESS", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUsdPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeiPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "isTransmitter_HARNESS", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onlyOwner_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracleWithdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner_HARNESS", + "outputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32[]", + "name": "requestIds", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "errors", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "onchainMetadata", + "type": "bytes[]" + }, + { + "internalType": "bytes[]", + "name": "offchainMetadata", + "type": "bytes[]" + } + ], + "internalType": "struct OCR2Base.DecodedReport", + "name": "decodedReport", + "type": "tuple" + } + ], + "name": "report_HARNESS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "donPublicKey", + "type": "bytes" + } + ], + "name": "setDONPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "thresholdPublicKey", + "type": "bytes" + } + ], + "name": "setThresholdPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "availableBalance", + "type": "uint96" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + } + ], + "internalType": "struct FunctionsResponse.RequestMeta", + "name": "request", + "type": "tuple" + } + ], + "name": "startBilling_HARNESS", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + }, + { + "internalType": "uint72", + "name": "operationFee", + "type": "uint72" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "availableBalance", + "type": "uint96" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + } + ], + "internalType": "struct FunctionsResponse.RequestMeta", + "name": "request", + "type": "tuple" + } + ], + "name": "startRequest", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json new file mode 100644 index 0000000..aba6e09 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json @@ -0,0 +1,1318 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address", + "name": "linkToNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "linkToUsdFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyPublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InconsistentReportData", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "usdLink", + "type": "int256" + } + ], + "name": "InvalidUsdLinkPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoTransmittersSet", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouterOwner", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "ReportInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "RouterMustBeSet", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedPublicKeyChange", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "inputs": [], + "name": "UnsupportedRequestDataVersion", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "CommitmentDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "indexed": false, + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "callbackGasLimit", + "type": "uint64" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "indexed": false, + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "OracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "OracleResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "l1FeeShareWei", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "callbackCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "donFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "adminFeeJuels", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint72", + "name": "operationFeeJuels", + "type": "uint72" + } + ], + "name": "RequestBilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + } + ], + "name": "callReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "address", + "name": "secondSigner", + "type": "address" + } + ], + "name": "callReportMultipleSigners", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "deleteCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + } + ], + "name": "estimateCost", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "getDONFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getDONPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperationFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThresholdPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUsdPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeiPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracleWithdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "donPublicKey", + "type": "bytes" + } + ], + "name": "setDONPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "thresholdPublicKey", + "type": "bytes" + } + ], + "name": "setThresholdPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "availableBalance", + "type": "uint96" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + } + ], + "internalType": "struct FunctionsResponse.RequestMeta", + "name": "request", + "type": "tuple" + } + ], + "name": "startRequest", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentGasPriceOverEstimationBP", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "feedStalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadBeforeCallback", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasOverheadAfterCallback", + "type": "uint32" + }, + { + "internalType": "uint40", + "name": "minimumEstimateGasPriceWei", + "type": "uint40" + }, + { + "internalType": "uint16", + "name": "maxSupportedRequestDataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "fallbackUsdPerUnitLink", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "fallbackUsdPerUnitLinkDecimals", + "type": "uint8" + }, + { + "internalType": "uint224", + "name": "fallbackNativePerUnitLink", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "requestTimeoutSeconds", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "donFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "operationFeeCentsUsd", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "transmitTxSizeBytes", + "type": "uint16" + } + ], + "internalType": "struct FunctionsBillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json new file mode 100644 index 0000000..a9f3b78 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json @@ -0,0 +1,421 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "router", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRouterCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_CALLBACK_GAS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getStats", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastError", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastResponse", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "resetStats", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "times", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "cborEncodedRequest", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendEncodedRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "times", + "type": "uint32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedSecretsReferences", + "type": "bytes" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "times", + "type": "uint32" + }, + { + "internalType": "string", + "name": "source", + "type": "string" + }, + { + "internalType": "uint8", + "name": "slotId", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "slotVersion", + "type": "uint64" + }, + { + "internalType": "string[]", + "name": "args", + "type": "string[]" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestWithDONHostedSecrets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalEmptyResponses", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalFailedResponses", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalRequests", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSucceededResponses", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json new file mode 100644 index 0000000..54abd34 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json @@ -0,0 +1,586 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AuthorizedSendersActive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AuthorizedSendersDeactive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "InvalidRequestID", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "OracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "OracleResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "ResponseTransmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "UserCallbackError", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lowLevelData", + "type": "bytes" + } + ], + "name": "UserCallbackRawError", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitAuthorizedSendersActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "emitAuthorizedSendersChanged", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitAuthorizedSendersDeactive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "emitConfigSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "emitInitialized", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "emitInvalidRequestID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "emitOracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "emitOracleResponse", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "emitResponseTransmitted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "emitTransmitted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "emitUserCallbackError", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "lowLevelData", + "type": "bytes" + } + ], + "name": "emitUserCallbackRawError", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json new file mode 100644 index 0000000..61a5674 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json @@ -0,0 +1,35 @@ +[ + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "inputs": [], + "name": "REQUEST_DATA_VERSION", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json new file mode 100644 index 0000000..305caa0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json @@ -0,0 +1,1720 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CannotRemoveWithPendingRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "DuplicateRequestId", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyRequestData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "limit", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "IdentifierIsReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "currentBalanceJuels", + "type": "uint96" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "value", + "type": "uint8" + } + ], + "name": "InvalidGasFlagValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProposal", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeProposedOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MustBeSubscriptionOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RouteNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderMustAcceptTermsOfService", + "type": "error" + }, + { + "inputs": [], + "name": "TimeoutNotExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maximumConsumers", + "type": "uint16" + } + ], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "indexed": false, + "internalType": "struct FunctionsRouter.Config", + "name": "", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "proposedContractSetId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetFromAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetToAddress", + "type": "address" + } + ], + "name": "ContractProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + } + ], + "name": "RequestNotProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "callbackReturnData", + "type": "bytes" + } + ], + "name": "RequestProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + } + ], + "name": "RequestStart", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_CALLBACK_RETURN_BYTES", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "createSubscriptionWithConsumer", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "costWithoutCallback", + "type": "uint96" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "fulfill", + "outputs": [ + { + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFee", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowListId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getConsumer", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + } + ], + "internalType": "struct IFunctionsSubscriptions.Consumer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getProposedContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProposedContractSet", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionIdStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subscriptionIdEnd", + "type": "uint64" + } + ], + "name": "getSubscriptionsInRange", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription[]", + "name": "subscriptions", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "isValidCallbackGasLimit", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "ownerWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proposedContractSetIds", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "proposedContractSetAddresses", + "type": "address[]" + } + ], + "name": "proposeContractsUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "proposeSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "allowListId", + "type": "bytes32" + } + ], + "name": "setAllowListId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "name": "setFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment[]", + "name": "requestsToTimeoutByCommitment", + "type": "tuple[]" + } + ], + "name": "timeoutRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json new file mode 100644 index 0000000..1587fb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json @@ -0,0 +1,1772 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CannotRemoveWithPendingRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "DuplicateRequestId", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyRequestData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "limit", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "IdentifierIsReserved", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "currentBalanceJuels", + "type": "uint96" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "value", + "type": "uint8" + } + ], + "name": "InvalidGasFlagValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProposal", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeProposedOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MustBeSubscriptionOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "RouteNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderMustAcceptTermsOfService", + "type": "error" + }, + { + "inputs": [], + "name": "TimeoutNotExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maximumConsumers", + "type": "uint16" + } + ], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "indexed": false, + "internalType": "struct FunctionsRouter.Config", + "name": "", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "proposedContractSetId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetFromAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetToAddress", + "type": "address" + } + ], + "name": "ContractProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + } + ], + "name": "RequestNotProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "callbackReturnData", + "type": "bytes" + } + ], + "name": "RequestProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + } + ], + "name": "RequestStart", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_CALLBACK_RETURN_BYTES", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "createSubscriptionWithConsumer", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "costWithoutFulfillment", + "type": "uint96" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "fulfill", + "outputs": [ + { + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "resultCode", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFee", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowListId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getConsumer", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + } + ], + "internalType": "struct IFunctionsSubscriptions.Consumer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxConsumers_HARNESS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getProposedContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProposedContractSet", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionDepositDetails_HARNESS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionIdStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subscriptionIdEnd", + "type": "uint64" + } + ], + "name": "getSubscriptionsInRange", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription[]", + "name": "subscriptions", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "isValidCallbackGasLimit", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "onlyRouterOwner_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "onlySenderThatAcceptedToS_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "ownerWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proposedContractSetIds", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "proposedContractSetAddresses", + "type": "address[]" + } + ], + "name": "proposeContractsUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "proposeSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "allowListId", + "type": "bytes32" + } + ], + "name": "setAllowListId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "name": "setFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment[]", + "name": "requestsToTimeoutByCommitment", + "type": "tuple[]" + } + ], + "name": "timeoutRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + }, + { + "internalType": "uint16", + "name": "subscriptionDepositMinimumRequests", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "subscriptionDepositJuels", + "type": "uint72" + } + ], + "internalType": "struct FunctionsRouter.Config", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "whenNotPaused_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json new file mode 100644 index 0000000..79d8d54 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json @@ -0,0 +1,761 @@ +[ + { + "inputs": [], + "name": "CannotRemoveWithPendingRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "currentBalanceJuels", + "type": "uint96" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeProposedOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MustBeSubscriptionOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "TimeoutNotExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maximumConsumers", + "type": "uint16" + } + ], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "createSubscriptionWithConsumer", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getConsumer", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + } + ], + "internalType": "struct IFunctionsSubscriptions.Consumer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionIdStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subscriptionIdEnd", + "type": "uint64" + } + ], + "name": "getSubscriptionsInRange", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription[]", + "name": "subscriptions", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "ownerWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "proposeSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "name": "setFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment[]", + "name": "requestsToTimeoutByCommitment", + "type": "tuple[]" + } + ], + "name": "timeoutRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json new file mode 100644 index 0000000..23b9975 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json @@ -0,0 +1,887 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CannotRemoveWithPendingRequests", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "currentBalanceJuels", + "type": "uint96" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeProposedOwner", + "type": "error" + }, + { + "inputs": [], + "name": "MustBeSubscriptionOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "TimeoutNotExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maximumConsumers", + "type": "uint16" + } + ], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "createSubscriptionWithConsumer", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getConsumer", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + } + ], + "internalType": "struct IFunctionsSubscriptions.Consumer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionIdStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subscriptionIdEnd", + "type": "uint64" + } + ], + "name": "getSubscriptionsInRange", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription[]", + "name": "subscriptions", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "isAllowedConsumer_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "isExistingSubscription_HARNESS", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + } + ], + "name": "markRequestInFlight_HARNESS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "ownerWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint96", + "name": "adminFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasUsed", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "costWithoutCallbackJuels", + "type": "uint96" + } + ], + "name": "pay_HARNESS", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "callbackGasCostJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "totalCostJuels", + "type": "uint96" + } + ], + "internalType": "struct FunctionsSubscriptions.Receipt", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "proposeSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "name": "setFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment[]", + "name": "requestsToTimeoutByCommitment", + "type": "tuple[]" + } + ], + "name": "timeoutRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json new file mode 100644 index 0000000..56284be --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json @@ -0,0 +1,93 @@ +[ + { + "inputs": [], + "name": "EmptyArgs", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySecrets", + "type": "error" + }, + { + "inputs": [], + "name": "EmptySource", + "type": "error" + }, + { + "inputs": [], + "name": "NoInlineSecrets", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "RequestData", + "type": "event" + }, + { + "inputs": [], + "name": "addEmptyArgs", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "secrets", + "type": "bytes" + } + ], + "name": "addSecretsReference", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "arg1", + "type": "string" + }, + { + "internalType": "string", + "name": "arg2", + "type": "string" + } + ], + "name": "addTwoArgs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeEvent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "sourceCode", + "type": "string" + } + ], + "name": "initializeRequestForInlineJavaScript", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json new file mode 100644 index 0000000..587f960 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json @@ -0,0 +1,957 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + } + ], + "indexed": false, + "internalType": "struct FunctionsV1EventsMock.Config", + "name": "param1", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "proposedContractSetId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetFromAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "proposedContractSetToAddress", + "type": "address" + } + ], + "name": "ContractProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ContractUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "resultCode", + "type": "uint8" + } + ], + "name": "RequestNotProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalCostJuels", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "resultCode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "callbackReturnData", + "type": "bytes" + } + ], + "name": "RequestProcessed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + } + ], + "name": "RequestStart", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "RequestTimedOut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "maxConsumersPerSubscription", + "type": "uint16" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "bytes4", + "name": "handleOracleFulfillmentSelector", + "type": "bytes4" + }, + { + "internalType": "uint16", + "name": "gasForCallExactCheck", + "type": "uint16" + }, + { + "internalType": "uint32[]", + "name": "maxCallbackGasLimits", + "type": "uint32[]" + } + ], + "internalType": "struct FunctionsV1EventsMock.Config", + "name": "param1", + "type": "tuple" + } + ], + "name": "emitConfigUpdated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "proposedContractSetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "proposedContractSetFromAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "proposedContractSetToAddress", + "type": "address" + } + ], + "name": "emitContractProposed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitContractUpdated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "emitFundsRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "uint8", + "name": "resultCode", + "type": "uint8" + } + ], + "name": "emitRequestNotProcessed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "totalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "uint8", + "name": "resultCode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callbackReturnData", + "type": "bytes" + } + ], + "name": "emitRequestProcessed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "address", + "name": "requestInitiator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + } + ], + "name": "emitRequestStart", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "emitRequestTimedOut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "fundsRecipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fundsAmount", + "type": "uint256" + } + ], + "name": "emitSubscriptionCanceled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "emitSubscriptionConsumerAdded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "emitSubscriptionConsumerRemoved", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "emitSubscriptionCreated", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "emitSubscriptionFunded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitSubscriptionOwnerTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitSubscriptionOwnerTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "emitUnpaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json new file mode 100644 index 0000000..e7c2127 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json @@ -0,0 +1,16 @@ +[ + { + "inputs": [], + "name": "consumeAllGas", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "throwOutOfGasError", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json new file mode 100644 index 0000000..8b220ab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json @@ -0,0 +1,273 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_specId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "price", + "type": "bytes32" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + } + ], + "name": "addExternalRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "_callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_expiration", + "type": "uint256" + } + ], + "name": "cancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_price", + "type": "bytes32" + } + ], + "name": "fulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "gassyFulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "gassyMultiWordFulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "gassyMultiWordRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "gassyRequestEthereumPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPrice", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestEthereumPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_currency", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_callback", + "type": "address" + } + ], + "name": "requestEthereumPriceByCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json new file mode 100644 index 0000000..c5f29ef --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json @@ -0,0 +1,242 @@ +[ + { + "inputs": [], + "name": "DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseFeeScalar", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blobBaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blobBaseFeeScalar", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_unsignedTxSize", + "type": "uint256" + } + ], + "name": "getL1FeeUpperBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getL1GasUsed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isEcotone", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isFjord", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1BaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "overhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "scalar", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "setEcotone", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setFjord", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json new file mode 100644 index 0000000..31660a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json @@ -0,0 +1,56 @@ +[ + { + "inputs": [ + { + "internalType": "bool", + "name": "toRevert", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "s_toRevert", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "setErr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "toRevert", + "type": "bool" + } + ], + "name": "setRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json new file mode 100644 index 0000000..f849c9d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json @@ -0,0 +1,190 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "b32", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "u256", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "b322", + "type": "bytes32" + } + ], + "name": "Output", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "SetBytes", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + } + ], + "name": "SetBytes32", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SetUint256", + "type": "event" + }, + { + "inputs": [], + "name": "getBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "_value", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_value", + "type": "bytes" + } + ], + "name": "requestedBytes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_value", + "type": "bytes32" + } + ], + "name": "requestedBytes32", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "requestedUint256", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_value", + "type": "bytes" + } + ], + "name": "setBytes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_value", + "type": "bytes32" + } + ], + "name": "setBytes32", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "setUint256", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json new file mode 100644 index 0000000..edf4dea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json @@ -0,0 +1,117 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "greeting", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_greeting", + "type": "string" + } + ], + "name": "setGreeting", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "triggerRevert", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json new file mode 100644 index 0000000..62b9b47 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json @@ -0,0 +1,184 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "HeartbeatNotPermitted", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "permittedCaller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newProxy", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldProxy", + "type": "address" + } + ], + "name": "HeartbeatPermitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "permittedCaller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "removedProxy", + "type": "address" + } + ], + "name": "HeartbeatRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "getAggregatorAndRequestHeartbeat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "permittedCaller", + "type": "address" + }, + { + "internalType": "contract IAggregatorProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "permitHeartbeat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "permittedCaller", + "type": "address" + } + ], + "name": "removeHeartbeat", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json new file mode 100644 index 0000000..45fe1fb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json @@ -0,0 +1,163 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counterpartGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json new file mode 100644 index 0000000..eb8c7b2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json @@ -0,0 +1,195 @@ +[ + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json new file mode 100644 index 0000000..d018c95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json @@ -0,0 +1,26 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json new file mode 100644 index 0000000..98ebff4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json @@ -0,0 +1,88 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "missingAccountFunds", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json new file mode 100644 index 0000000..3883c6a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json @@ -0,0 +1,229 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "userOps", + "type": "tuple[]" + } + ], + "name": "aggregateSignatures", + "outputs": [ + { + "internalType": "bytes", + "name": "aggregatedSignature", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "validateSignatures", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "validateUserOpSignature", + "outputs": [ + { + "internalType": "bytes", + "name": "sigForUserOp", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json new file mode 100644 index 0000000..4efa177 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "aggregator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json new file mode 100644 index 0000000..5f319cb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json @@ -0,0 +1,880 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "sendRoot", + "type": "bytes32" + } + ], + "name": "NodeConfirmed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "parentNodeHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "nodeHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "executionHash", + "type": "bytes32" + }, + { + "components": [ + { + "components": [ + { + "components": [ + { + "internalType": "bytes32[2]", + "name": "bytes32Vals", + "type": "bytes32[2]" + }, + { + "internalType": "uint64[2]", + "name": "u64Vals", + "type": "uint64[2]" + } + ], + "internalType": "struct GlobalState", + "name": "globalState", + "type": "tuple" + }, + { + "internalType": "enum MachineStatus", + "name": "machineStatus", + "type": "uint8" + } + ], + "internalType": "struct ExecutionState", + "name": "beforeState", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "bytes32[2]", + "name": "bytes32Vals", + "type": "bytes32[2]" + }, + { + "internalType": "uint64[2]", + "name": "u64Vals", + "type": "uint64[2]" + } + ], + "internalType": "struct GlobalState", + "name": "globalState", + "type": "tuple" + }, + { + "internalType": "enum MachineStatus", + "name": "machineStatus", + "type": "uint8" + } + ], + "internalType": "struct ExecutionState", + "name": "afterState", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "numBlocks", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Assertion", + "name": "assertion", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "afterInboxBatchAcc", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "wasmModuleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "inboxMaxCount", + "type": "uint256" + } + ], + "name": "NodeCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + } + ], + "name": "NodeRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "challengeIndex", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "asserter", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "challenger", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "challengedNode", + "type": "uint64" + } + ], + "name": "RollupChallengeStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "machineHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "RollupInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalBalance", + "type": "uint256" + } + ], + "name": "UserStakeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "finalBalance", + "type": "uint256" + } + ], + "name": "UserWithdrawableFundsUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "amountStaked", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "challengeManager", + "outputs": [ + { + "internalType": "contract IChallengeManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "confirmPeriodBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "currentChallenge", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "extraChallengeTimeBlocks", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "firstUnresolvedNode", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + } + ], + "name": "getNode", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "stateHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "challengeHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "confirmData", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "prevNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "deadlineBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "noChildConfirmedBeforeBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "stakerCount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "childStakerCount", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "firstChildBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestChildNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "createdAtBlock", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "nodeHash", + "type": "bytes32" + } + ], + "internalType": "struct Node", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + } + ], + "name": "getNodeCreationBlockForLogLookup", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "getStaker", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amountStaked", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "index", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestStakedNode", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "currentChallenge", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "isStaked", + "type": "bool" + } + ], + "internalType": "struct IRollupCore.Staker", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "stakerNum", + "type": "uint64" + } + ], + "name": "getStakerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "isStaked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "isZombie", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastStakeBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfirmed", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestNodeCreated", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "latestStakedNode", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "loserStakeEscrow", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumAssertionPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "nodeNum", + "type": "uint64" + }, + { + "internalType": "address", + "name": "staker", + "type": "address" + } + ], + "name": "nodeHasStaker", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "outbox", + "outputs": [ + { + "internalType": "contract IOutbox", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rollupEventInbox", + "outputs": [ + { + "internalType": "contract IRollupEventInbox", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sequencerInbox", + "outputs": [ + { + "internalType": "contract ISequencerInbox", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakeToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakerCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorWhitelistDisabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wasmModuleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "withdrawableFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "zombieNum", + "type": "uint256" + } + ], + "name": "zombieAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "zombieCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "zombieNum", + "type": "uint256" + } + ], + "name": "zombieLatestStakedNode", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json new file mode 100644 index 0000000..3837092 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json new file mode 100644 index 0000000..086ef65 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json @@ -0,0 +1,407 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InboxMessageDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + } + ], + "name": "InboxMessageDeliveredFromOrigin", + "type": "event" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + } + ], + "name": "calculateRetryableSubmissionFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "createRetryableTicket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "createRetryableTicketNoRefundAliasRewrite", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + } + ], + "name": "depositEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGasPrice", + "type": "uint256" + } + ], + "name": "depositEthRetryable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendL1FundedContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendL1FundedUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "messageData", + "type": "bytes" + } + ], + "name": "sendL2Message", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json new file mode 100644 index 0000000..0e68e95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json @@ -0,0 +1,232 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newDefaultGateway", + "type": "address" + } + ], + "name": "DefaultGatewayUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "GatewaySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_userFrom", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_userTo", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "name": "TransferRouted", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "defaultGateway", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "getGateway", + "outputs": [ + { + "internalType": "address", + "name": "gateway", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json new file mode 100644 index 0000000..d71213f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json @@ -0,0 +1,326 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InboxMessageDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + } + ], + "name": "InboxMessageDeliveredFromOrigin", + "type": "event" + }, + { + "inputs": [], + "name": "allowListEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + } + ], + "name": "calculateRetryableSubmissionFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IBridge", + "name": "_bridge", + "type": "address" + }, + { + "internalType": "contract ISequencerInbox", + "name": "_sequencerInbox", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "isAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxDataSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "messageData", + "type": "bytes" + } + ], + "name": "sendL2Message", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "messageData", + "type": "bytes" + } + ], + "name": "sendL2MessageFromOrigin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sequencerInbox", + "outputs": [ + { + "internalType": "contract ISequencerInbox", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "user", + "type": "address[]" + }, + { + "internalType": "bool[]", + "name": "val", + "type": "bool[]" + } + ], + "name": "setAllowList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_allowListEnabled", + "type": "bool" + } + ], + "name": "setAllowListEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json new file mode 100644 index 0000000..0f841b8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json @@ -0,0 +1,304 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "inbox", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_refundTo", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransferCustomRefund", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gateway", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_creditBackAddress", + "type": "address" + } + ], + "name": "setGateway", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_gateway", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSubmissionCost", + "type": "uint256" + } + ], + "name": "setGateway", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json new file mode 100644 index 0000000..4cc15e0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json @@ -0,0 +1,137 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json new file mode 100644 index 0000000..57336ef --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json @@ -0,0 +1,47 @@ +[ + { + "inputs": [], + "name": "getAuthorizedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isAuthorizedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSenders", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json new file mode 100644 index 0000000..1cd5abe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json @@ -0,0 +1,83 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getRegistry", + "outputs": [ + { + "internalType": "contract IAutomationRegistryConsumer", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newRegistry", + "type": "address" + } + ], + "name": "updateRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json new file mode 100644 index 0000000..07e8ba9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json @@ -0,0 +1,115 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json new file mode 100644 index 0000000..db2c933 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json @@ -0,0 +1,2725 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataFixedBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataPerSignerBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "internalType": "struct AutomationRegistryBase2_2.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "uint8", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json new file mode 100644 index 0000000..c676289 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json @@ -0,0 +1,3606 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableOffchainPayments", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getAvailableERC20ForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getBillingConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverrides", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverridesEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getBillingTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBillingTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackNativePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getHotVars", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reentrancyGuard", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.HotVars", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNativeUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNumUpkeeps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPayoutMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getReserveAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStorage", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + } + ], + "internalType": "struct AutomationRegistryBase2_3.Storage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataFixedBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitCalldataPerSignerBytesOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmittersWithPayees", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transmitterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "payeeAddress", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNativeTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "removeBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", + "name": "billingOverrides", + "type": "tuple" + } + ], + "name": "setBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "address[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct AutomationRegistryBase2_3.BillingConfig[]", + "name": "billingConfigs", + "type": "tuple[]" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "uint8", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "settleNOPsOffchain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "supportsBillingToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawERC20Fees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json new file mode 100644 index 0000000..16f31aa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json @@ -0,0 +1,1441 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json new file mode 100644 index 0000000..31fc615 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json @@ -0,0 +1,227 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageIndex", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "beforeInboxAcc", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "inbox", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "kind", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "messageDataHash", + "type": "bytes32" + } + ], + "name": "MessageDelivered", + "type": "event" + }, + { + "inputs": [], + "name": "activeOutbox", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "inbox", + "type": "address" + } + ], + "name": "allowedInboxes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "outbox", + "type": "address" + } + ], + "name": "allowedOutboxes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "kind", + "type": "uint8" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "messageDataHash", + "type": "bytes32" + } + ], + "name": "deliverMessageToInbox", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "executeCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "inboxAccs", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "messageCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "inbox", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setInbox", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "inbox", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setOutbox", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json new file mode 100644 index 0000000..61ea600 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json @@ -0,0 +1,131 @@ +[ + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "remoteSender", + "type": "address" + }, + { + "internalType": "address", + "name": "localReceiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json new file mode 100644 index 0000000..897cb35 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json @@ -0,0 +1,252 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json new file mode 100644 index 0000000..6a14448 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json @@ -0,0 +1,55 @@ +[ + { + "anonymous": false, + "inputs": [], + "name": "CapabilityConfigurationSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "nodes", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "donCapabilityConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "donCapabilityConfigCount", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "beforeCapabilityConfigSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + } + ], + "name": "getCapabilityConfiguration", + "outputs": [ + { + "internalType": "bytes", + "name": "configuration", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json new file mode 100644 index 0000000..c12d857 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "l1Fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "maxL1Fee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json new file mode 100644 index 0000000..2a123a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json @@ -0,0 +1,44 @@ +[ + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "string", + "name": "url", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "sha", + "type": "bytes32" + } + ], + "name": "setChannelDefinitions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json new file mode 100644 index 0000000..17947ca --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json @@ -0,0 +1,112 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "configId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json new file mode 100644 index 0000000..663cd86 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json @@ -0,0 +1,73 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json new file mode 100644 index 0000000..10f01bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json new file mode 100644 index 0000000..1644031 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json @@ -0,0 +1,236 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "addVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "address", + "name": "quoteAddress", + "type": "address" + } + ], + "name": "getFeeAndReward", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "payLinkDeficit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "removeVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "surcharge", + "type": "uint64" + } + ], + "name": "setNativeSurcharge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "rewardManager", + "type": "address" + } + ], + "name": "setRewardManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberGlobalDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "recipientAddress", + "type": "address" + }, + { + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json new file mode 100644 index 0000000..46aa2bd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json @@ -0,0 +1,197 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "newFeeManager", + "type": "address" + } + ], + "name": "addFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "getAvailableRewardPoolIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "internalType": "struct IDestinationRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "onFeePaid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "payRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeManager", + "type": "address" + } + ], + "name": "removeFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "updateRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json new file mode 100644 index 0000000..a4a8e97 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json @@ -0,0 +1,147 @@ +[ + { + "inputs": [], + "name": "removeLatestConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessController", + "type": "address" + } + ], + "name": "setAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "donConfigId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + } + ], + "name": "setConfigActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + }, + { + "internalType": "uint32", + "name": "activationTime", + "type": "uint32" + } + ], + "name": "setConfigWithActivationTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json new file mode 100644 index 0000000..4962feb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json @@ -0,0 +1,107 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + }, + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setFeeRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json new file mode 100644 index 0000000..fafe41e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json @@ -0,0 +1,108 @@ +[ + { + "inputs": [], + "name": "s_accessController", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "setVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "verifierResponse", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verifyBulk", + "outputs": [ + { + "internalType": "bytes[]", + "name": "verifiedReports", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json new file mode 100644 index 0000000..0fea245 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json @@ -0,0 +1,105 @@ +[ + { + "inputs": [], + "name": "s_accessController", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signedReport", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "verifierResponse", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "signedReports", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verifyBulk", + "outputs": [ + { + "internalType": "bytes[]", + "name": "verifiedReports", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json new file mode 100644 index 0000000..f2d2b1d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json @@ -0,0 +1,104 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC1155InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC1155InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "idsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "valuesLength", + "type": "uint256" + } + ], + "name": "ERC1155InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC1155InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC1155InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC1155InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC1155MissingApprovalForAll", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json new file mode 100644 index 0000000..0656ec3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceID", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json new file mode 100644 index 0000000..018d966 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json @@ -0,0 +1,185 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json new file mode 100644 index 0000000..d2e35dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json @@ -0,0 +1,88 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json new file mode 100644 index 0000000..5b64237 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json @@ -0,0 +1,224 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json new file mode 100644 index 0000000..5e41277 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json @@ -0,0 +1,77 @@ +[ + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json new file mode 100644 index 0000000..ae7ca78 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json @@ -0,0 +1,51 @@ +[ + { + "anonymous": false, + "inputs": [], + "name": "EIP712DomainChanged", + "type": "event" + }, + { + "inputs": [], + "name": "eip712Domain", + "outputs": [ + { + "internalType": "bytes1", + "name": "fields", + "type": "bytes1" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "version", + "type": "string" + }, + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifyingContract", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "salt", + "type": "bytes32" + }, + { + "internalType": "uint256[]", + "name": "extensions", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json new file mode 100644 index 0000000..e3d1461 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json @@ -0,0 +1,62 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json new file mode 100644 index 0000000..fd79f59 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json @@ -0,0 +1,25 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json new file mode 100644 index 0000000..719d8f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json @@ -0,0 +1,105 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721IncorrectOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721InsufficientApproval", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC721InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "ERC721InvalidOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "ERC721InvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC721InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC721InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721NonexistentToken", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json new file mode 100644 index 0000000..53d47e6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json @@ -0,0 +1,1065 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bool", + "name": "targetSuccess", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "targetResult", + "type": "bytes" + } + ], + "name": "ExecutionResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "opIndex", + "type": "uint256" + }, + { + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "FailedOp", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderAddressResult", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureValidationFailed", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sigFailed", + "type": "bool" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "paymasterContext", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.ReturnInfo", + "name": "returnInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "senderInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "factoryInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "paymasterInfo", + "type": "tuple" + } + ], + "name": "ValidationResult", + "type": "error" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "preOpGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prefund", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "sigFailed", + "type": "bool" + }, + { + "internalType": "uint48", + "name": "validAfter", + "type": "uint48" + }, + { + "internalType": "uint48", + "name": "validUntil", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "paymasterContext", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.ReturnInfo", + "name": "returnInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "senderInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "factoryInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "paymasterInfo", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "stake", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "internalType": "struct IStakeManager.StakeInfo", + "name": "stakeInfo", + "type": "tuple" + } + ], + "internalType": "struct IEntryPoint.AggregatorStakeInfo", + "name": "aggregatorInfo", + "type": "tuple" + } + ], + "name": "ValidationResultWithAggregation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "factory", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "AccountDeployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDeposit", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "SignatureAggregatorChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawTime", + "type": "uint256" + } + ], + "name": "StakeUnlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "actualGasUsed", + "type": "uint256" + } + ], + "name": "UserOperationEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "revertReason", + "type": "bytes" + } + ], + "name": "UserOperationRevertReason", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDepositInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "internalType": "struct IStakeManager.DepositInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "name": "getSenderAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "getUserOpHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "userOps", + "type": "tuple[]" + }, + { + "internalType": "contract IAggregator", + "name": "aggregator", + "type": "address" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", + "name": "opsPerAggregator", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleAggregatedOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation[]", + "name": "ops", + "type": "tuple[]" + }, + { + "internalType": "address payable", + "name": "beneficiary", + "type": "address" + } + ], + "name": "handleOps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "op", + "type": "tuple" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "targetCallData", + "type": "bytes" + } + ], + "name": "simulateHandleOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + } + ], + "name": "simulateValidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json new file mode 100644 index 0000000..da8ee5a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json @@ -0,0 +1,250 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "address", + "name": "quoteAddress", + "type": "address" + } + ], + "name": "getFeeAndReward", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct Common.Asset", + "name": "", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "payLinkDeficit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setFeeRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "surcharge", + "type": "uint64" + } + ], + "name": "setNativeSurcharge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "subscriber", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "discount", + "type": "uint64" + } + ], + "name": "updateSubscriberDiscount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "recipientAddress", + "type": "address" + }, + { + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json new file mode 100644 index 0000000..843160e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json @@ -0,0 +1,118 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getFlag", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bool[]", + "name": "", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lowerFlag", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "lowerFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "raiseFlag", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "name": "raiseFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setLoweringAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setRaisingAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json new file mode 100644 index 0000000..301144c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json new file mode 100644 index 0000000..22bd2b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json @@ -0,0 +1,150 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "deleteCommitment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "gasPriceWei", + "type": "uint256" + } + ], + "name": "estimateCost", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "requestCBOR", + "type": "bytes" + } + ], + "name": "getDONFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOperationFeeJuels", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUsdPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWeiPerUnitLink", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracleWithdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json new file mode 100644 index 0000000..af92e6d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json @@ -0,0 +1,25 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + } + ], + "name": "handleOracleFulfillment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json new file mode 100644 index 0000000..c647a60 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json @@ -0,0 +1,187 @@ +[ + { + "inputs": [], + "name": "getDONPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getThresholdPublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "donPublicKey", + "type": "bytes" + } + ], + "name": "setDONPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "thresholdPublicKey", + "type": "bytes" + } + ], + "name": "setThresholdPublicKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "requestingContract", + "type": "address" + }, + { + "internalType": "uint96", + "name": "availableBalance", + "type": "uint96" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subscriptionOwner", + "type": "address" + } + ], + "internalType": "struct FunctionsResponse.RequestMeta", + "name": "request", + "type": "tuple" + } + ], + "name": "startRequest", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json new file mode 100644 index 0000000..0dc1ff1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json @@ -0,0 +1,338 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "costWithoutFulfillment", + "type": "uint96" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "fulfill", + "outputs": [ + { + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFee", + "outputs": [ + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowListId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getProposedContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProposedContractSet", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "isValidCallbackGasLimit", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proposalSetIds", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "proposalSetAddresses", + "type": "address[]" + } + ], + "name": "proposeContractsUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "allowListId", + "type": "bytes32" + } + ], + "name": "setAllowListId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json new file mode 100644 index 0000000..16ab897 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json @@ -0,0 +1,463 @@ +[ + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "createSubscriptionWithConsumer", + "outputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getConsumer", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "initiatedRequests", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "completedRequests", + "type": "uint64" + } + ], + "internalType": "struct IFunctionsSubscriptions.Consumer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getFlags", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSubscriptionCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionIdStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subscriptionIdEnd", + "type": "uint64" + } + ], + "name": "getSubscriptionsInRange", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint96", + "name": "blockedBalance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "internalType": "struct IFunctionsSubscriptions.Subscription[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "proposeSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "flags", + "type": "bytes32" + } + ], + "name": "setFlags", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment[]", + "name": "requestsToTimeoutByCommitment", + "type": "tuple[]" + } + ], + "name": "timeoutRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json new file mode 100644 index 0000000..6893dd4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json @@ -0,0 +1,25 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxTotalGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "gasBoundCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json new file mode 100644 index 0000000..691cdd3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json @@ -0,0 +1,59 @@ +[ + { + "inputs": [], + "name": "gasPayingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPayingTokenName", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPayingTokenSymbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCustomGasToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json new file mode 100644 index 0000000..aa899e6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json @@ -0,0 +1,383 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InboxMessageDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + } + ], + "name": "InboxMessageDeliveredFromOrigin", + "type": "event" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "createRetryableTicket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "createRetryableTicketNoRefundAliasRewrite", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + } + ], + "name": "depositEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGasPrice", + "type": "uint256" + } + ], + "name": "depositEthRetryable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendL1FundedContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendL1FundedUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "messageData", + "type": "bytes" + } + ], + "name": "sendL2Message", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "sendUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json new file mode 100644 index 0000000..d5e68ad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json @@ -0,0 +1,2655 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "uint8", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json new file mode 100644 index 0000000..cd3afa0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json @@ -0,0 +1,322 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "DepositFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_l2ToL1Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_exitNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "WithdrawalInitiated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1ERC20", + "type": "address" + } + ], + "name": "calculateL2TokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counterpartGateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exitNum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "finalizeInboundTransfer", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getOutboundCalldata", + "outputs": [ + { + "internalType": "bytes", + "name": "outboundCalldata", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "res", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "postUpgradeInit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "router", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json new file mode 100644 index 0000000..ba76cfb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json @@ -0,0 +1,33 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "TxToL1", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json new file mode 100644 index 0000000..e3d5c12 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json @@ -0,0 +1,36 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "outboundTransfer", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json new file mode 100644 index 0000000..87f9d84 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json @@ -0,0 +1,35 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json new file mode 100644 index 0000000..73eb86c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "int256", + "name": "availableBalance", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json new file mode 100644 index 0000000..dfe76ef --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json @@ -0,0 +1,66 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityRemoved", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "provideLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json new file mode 100644 index 0000000..8c184f6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json @@ -0,0 +1,55 @@ +[ + { + "inputs": [], + "name": "getAllCrossChainRebalancers", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "currentLiquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json new file mode 100644 index 0000000..0a1d0cb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json @@ -0,0 +1,86 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "log", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkLog", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json new file mode 100644 index 0000000..04cf0ab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json @@ -0,0 +1,34 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InboxMessageDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + } + ], + "name": "InboxMessageDeliveredFromOrigin", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json new file mode 100644 index 0000000..ade281c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json @@ -0,0 +1,320 @@ +[ + { + "inputs": [ + { + "internalType": "uint64", + "name": "l2BlockNum", + "type": "uint64" + } + ], + "name": "blockL1Num", + "outputs": [ + { + "internalType": "uint64", + "name": "l1BlockNum", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "size", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "leaf", + "type": "uint64" + } + ], + "name": "constructOutboxProof", + "outputs": [ + { + "internalType": "bytes32", + "name": "send", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2CallValue", + "type": "uint256" + }, + { + "internalType": "address", + "name": "excessFeeRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "callValueRefundAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "estimateRetryableTicket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + } + ], + "name": "findBatchContainingBlock", + "outputs": [ + { + "internalType": "uint64", + "name": "batch", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "contractCreation", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "gasEstimateComponents", + "outputs": [ + { + "internalType": "uint64", + "name": "gasEstimate", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "gasEstimateForL1", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l1BaseFeeEstimate", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bool", + "name": "contractCreation", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "gasEstimateL1Component", + "outputs": [ + { + "internalType": "uint64", + "name": "gasEstimateForL1", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l1BaseFeeEstimate", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "name": "getL1Confirmations", + "outputs": [ + { + "internalType": "uint64", + "name": "confirmations", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + } + ], + "name": "l2BlockRangeForL1", + "outputs": [ + { + "internalType": "uint64", + "name": "firstBlock", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastBlock", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchNum", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "index", + "type": "uint64" + } + ], + "name": "legacyLookupMessageBatchProof", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "path", + "type": "uint256" + }, + { + "internalType": "address", + "name": "l2Sender", + "type": "address" + }, + { + "internalType": "address", + "name": "l1Dest", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l1Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "calldataForL1", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nitroGenesisBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json new file mode 100644 index 0000000..1fa1332 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "requestNewRound", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json new file mode 100644 index 0000000..acf91b1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json @@ -0,0 +1,77 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minGasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json new file mode 100644 index 0000000..29d5e65 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json @@ -0,0 +1,71 @@ +[ + { + "inputs": [ + { + "internalType": "GameType", + "name": "_gameType", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_n", + "type": "uint256" + } + ], + "name": "findLatestGames", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "GameId", + "name": "metadata", + "type": "bytes32" + }, + { + "internalType": "Timestamp", + "name": "timestamp", + "type": "uint64" + }, + { + "internalType": "Claim", + "name": "rootClaim", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "internalType": "struct IOptimismDisputeGameFactory.GameSearchResult[]", + "name": "games_", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gameCount", + "outputs": [ + { + "internalType": "uint256", + "name": "gameCount_", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json new file mode 100644 index 0000000..0100348 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json @@ -0,0 +1,25 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_minGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "depositETHTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json new file mode 100644 index 0000000..9fe0ee8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json @@ -0,0 +1,57 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2OutputIndex", + "type": "uint256" + } + ], + "name": "getL2Output", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "outputRoot", + "type": "bytes32" + }, + { + "internalType": "uint128", + "name": "timestamp", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "l2BlockNumber", + "type": "uint128" + } + ], + "internalType": "struct Types.OutputProposal", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2BlockNumber", + "type": "uint256" + } + ], + "name": "getL2OutputIndexAfter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json new file mode 100644 index 0000000..bdf64ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json @@ -0,0 +1,51 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "withdrawalHash", + "type": "bytes32" + } + ], + "name": "MessagePassed", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json new file mode 100644 index 0000000..fa9c36b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json @@ -0,0 +1,83 @@ +[ + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "remoteToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json new file mode 100644 index 0000000..eadb295 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json @@ -0,0 +1,47 @@ +[ + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "remoteToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json new file mode 100644 index 0000000..8e562c4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json @@ -0,0 +1,142 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Types.WithdrawalTransaction", + "name": "_tx", + "type": "tuple" + } + ], + "name": "finalizeWithdrawalTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Types.WithdrawalTransaction", + "name": "_tx", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_l2OutputIndex", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "version", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagePasserStorageRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "latestBlockhash", + "type": "bytes32" + } + ], + "internalType": "struct Types.OutputRootProof", + "name": "_outputRootProof", + "type": "tuple" + }, + { + "internalType": "bytes[]", + "name": "_withdrawalProof", + "type": "bytes[]" + } + ], + "name": "proveWithdrawalTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json new file mode 100644 index 0000000..5c6c934 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json @@ -0,0 +1,28 @@ +[ + { + "inputs": [], + "name": "disputeGameFactory", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "respectedGameType", + "outputs": [ + { + "internalType": "GameType", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json new file mode 100644 index 0000000..c173046 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json @@ -0,0 +1,83 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "ERC20BridgeFinalized", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_remoteToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_extraData", + "type": "bytes" + } + ], + "name": "finalizeBridgeERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json new file mode 100644 index 0000000..a646f82 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json @@ -0,0 +1,55 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "address", + "name": "l2Sender", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l1Block", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2Timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "executeTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json new file mode 100644 index 0000000..ee9d817 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json @@ -0,0 +1,35 @@ +[ + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json new file mode 100644 index 0000000..59332ab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json @@ -0,0 +1,371 @@ +[ + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "response", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "err", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "juelsPerGas", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "costWithoutFulfillment", + "type": "uint96" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + }, + { + "internalType": "uint96", + "name": "estimatedTotalCostJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "client", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + }, + { + "internalType": "uint72", + "name": "donFee", + "type": "uint72" + }, + { + "internalType": "uint40", + "name": "gasOverheadBeforeCallback", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "gasOverheadAfterCallback", + "type": "uint40" + }, + { + "internalType": "uint32", + "name": "timeoutTimestamp", + "type": "uint32" + } + ], + "internalType": "struct FunctionsResponse.Commitment", + "name": "commitment", + "type": "tuple" + } + ], + "name": "fulfill", + "outputs": [ + { + "internalType": "enum FunctionsResponse.FulfillResult", + "name": "", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAdminFee", + "outputs": [ + { + "internalType": "uint72", + "name": "adminFee", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowListId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "getProposedContractById", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProposedContractSet", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + } + ], + "name": "isValidCallbackGasLimit", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "proposalSetIds", + "type": "bytes32[]" + }, + { + "internalType": "address[]", + "name": "proposalSetAddresses", + "type": "address[]" + } + ], + "name": "proposeContractsUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequest", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint16", + "name": "dataVersion", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "donId", + "type": "bytes32" + } + ], + "name": "sendRequestToProposed", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "allowListId", + "type": "bytes32" + } + ], + "name": "setAllowListId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json new file mode 100644 index 0000000..b617778 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json @@ -0,0 +1,116 @@ +[ + { + "inputs": [ + { + "internalType": "enum IPaymaster.PostOpMode", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + } + ], + "name": "postOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxCost", + "type": "uint256" + } + ], + "name": "validatePaymasterUserOp", + "outputs": [ + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json new file mode 100644 index 0000000..2b6a061 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + } + ], + "name": "onReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json new file mode 100644 index 0000000..5f34d15 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json @@ -0,0 +1,184 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "getAvailableRewardPoolIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "internalType": "struct IRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "onFeePaid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "payRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newFeeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "updateRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json new file mode 100644 index 0000000..2d3c49f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json @@ -0,0 +1,239 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + } + ], + "name": "AlreadyAttempted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + } + ], + "name": "InsufficientGasForRouting", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedForwarder", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "ForwarderAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "ForwarderRemoved", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "addForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmissionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmissionInfo", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + }, + { + "internalType": "enum IRouter.TransmissionState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "bool", + "name": "invalidReceiver", + "type": "bool" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint80", + "name": "gasLimit", + "type": "uint80" + } + ], + "internalType": "struct IRouter.TransmissionInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmitter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "removeForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + } + ], + "name": "route", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json new file mode 100644 index 0000000..f568519 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json @@ -0,0 +1,131 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "l1BaseFee", + "type": "uint256" + } + ], + "name": "L1BaseFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "overhead", + "type": "uint256" + } + ], + "name": "OverheadUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "scalar", + "type": "uint256" + } + ], + "name": "ScalarUpdated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "getL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "getL1GasUsed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1BaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "overhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "scalar", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l1BaseFee", + "type": "uint256" + } + ], + "name": "setL1BaseFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json new file mode 100644 index 0000000..ec46f23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json @@ -0,0 +1,145 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "refundAddress", + "type": "address" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json new file mode 100644 index 0000000..c4aed5f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json new file mode 100644 index 0000000..a67bc9d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json new file mode 100644 index 0000000..b8fa2d1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json @@ -0,0 +1,244 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDeposit", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawTime", + "type": "uint256" + } + ], + "name": "StakeUnlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDepositInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "internalType": "struct IStakeManager.DepositInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json new file mode 100644 index 0000000..a9cb145 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json @@ -0,0 +1,41 @@ +[ + { + "inputs": [], + "name": "gasPerPubdataByte", + "outputs": [ + { + "internalType": "uint256", + "name": "gasPerPubdataByte", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPubdataSpent", + "outputs": [ + { + "internalType": "uint256", + "name": "currentPubdataSpent", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json new file mode 100644 index 0000000..5c2804d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json @@ -0,0 +1,191 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "acceptor", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + } + ], + "name": "acceptTermsOfService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "blockSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllAllowedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedSendersCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "allowedSenderIdxStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "allowedSenderIdxEnd", + "type": "uint64" + } + ], + "name": "getAllowedSendersInRange", + "outputs": [ + { + "internalType": "address[]", + "name": "allowedSenders", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockedSendersCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockedSenderIdxStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockedSenderIdxEnd", + "type": "uint64" + } + ], + "name": "getBlockedSendersInRange", + "outputs": [ + { + "internalType": "address[]", + "name": "blockedSenders", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "acceptor", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getMessage", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isBlockedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "unblockSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json new file mode 100644 index 0000000..99725a5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json new file mode 100644 index 0000000..14be06d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json @@ -0,0 +1,375 @@ +[ + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "internalType": "struct VRFTypes.RequestCommitment", + "name": "rc", + "type": "tuple" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeConfig", + "outputs": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "internalType": "struct FeeConfig", + "name": "feeConfig", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json new file mode 100644 index 0000000..01b7fe4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json @@ -0,0 +1,246 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json new file mode 100644 index 0000000..6fb3e61 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json @@ -0,0 +1,110 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json new file mode 100644 index 0000000..b6efb18 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json @@ -0,0 +1,490 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct IVRFCoordinatorV2PlusInternal.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct IVRFCoordinatorV2PlusInternal.RequestCommitment", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestID", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json new file mode 100644 index 0000000..7bf40b8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedData", + "type": "bytes" + } + ], + "name": "onMigration", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json new file mode 100644 index 0000000..c08f818 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json @@ -0,0 +1,28 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json new file mode 100644 index 0000000..7413236 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json @@ -0,0 +1,195 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json new file mode 100644 index 0000000..e8dc559 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json new file mode 100644 index 0000000..4d25e6a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json @@ -0,0 +1,181 @@ +[ + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "link", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkNativeFeed", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "name": "requestRandomWordsInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json new file mode 100644 index 0000000..6b5d2dc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json @@ -0,0 +1,300 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "activateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "activateFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "deactivateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "deactivateFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "sourceChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sourceAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newConfigCount", + "type": "uint32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfigFromSource", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signedReport", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "verifierResponse", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json new file mode 100644 index 0000000..1635137 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json @@ -0,0 +1,97 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFee", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + }, + { + "internalType": "address", + "name": "subscriber", + "type": "address" + } + ], + "name": "processFeeBulk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setFeeRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json new file mode 100644 index 0000000..263abee --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "signedReport", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "verifierResponse", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json new file mode 100644 index 0000000..569a62d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json @@ -0,0 +1,22 @@ +[ + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json new file mode 100644 index 0000000..efdb2d8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json @@ -0,0 +1,33 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json new file mode 100644 index 0000000..8a2916f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json @@ -0,0 +1,205 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json new file mode 100644 index 0000000..bd2887e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json @@ -0,0 +1,3567 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableOffchainPayments", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint8", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getAvailableERC20ForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getBillingConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverrides", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverridesEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getBillingTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBillingTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackNativePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getHotVars", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reentrancyGuard", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.HotVars", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNativeUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNumUpkeeps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPayoutMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "billingToken", + "type": "address" + } + ], + "name": "getReserveAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStorage", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.Storage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmittersWithPayees", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transmitterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "payeeAddress", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNativeTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "address", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "removeBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "billingOverrides", + "type": "tuple" + } + ], + "name": "setBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "address[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "address", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]", + "name": "billingConfigs", + "type": "tuple[]" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "uint8", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "settleNOPsOffchain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "supportsBillingToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawERC20Fees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json new file mode 100644 index 0000000..df62e86 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json @@ -0,0 +1,51 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "verifyCannotExecute", + "outputs": [], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json new file mode 100644 index 0000000..37deb69 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json @@ -0,0 +1,94 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "updateInterval", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "interval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimeStamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json new file mode 100644 index 0000000..e4628be --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json @@ -0,0 +1,289 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_averageEligibilityCadence", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_checkGasToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_performGasToBurn", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "eligible", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialCall", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nextEligible", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [], + "name": "averageEligibilityCadence", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCountPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialCall", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextEligible", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setCheckGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newTestRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newAverageEligibilityCadence", + "type": "uint256" + } + ], + "name": "setSpread", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json new file mode 100644 index 0000000..2159111 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json @@ -0,0 +1,594 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "LINKAddress", + "type": "address" + }, + { + "internalType": "enum KeeperRegistrar.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "autoApproveMaxAllowed", + "type": "uint16" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "FunctionNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "HashMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientPayment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAdminAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "LinkTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdminOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyLink", + "type": "error" + }, + { + "inputs": [], + "name": "RegistrationRequestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "RequestNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "SenderMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AutoApproveAllowedSenderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum KeeperRegistrar.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "ConfigChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "RegistrationApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "RegistrationRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "source", + "type": "uint8" + } + ], + "name": "RegistrationRequested", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + } + ], + "name": "getAutoApproveAllowedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getPendingRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRegistrationConfig", + "outputs": [ + { + "internalType": "enum KeeperRegistrar.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "approvedCount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minLINKJuels", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint8", + "name": "source", + "type": "uint8" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAutoApproveAllowedSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum KeeperRegistrar.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "autoApproveMaxAllowed", + "type": "uint16" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "setRegistrationConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json new file mode 100644 index 0000000..c0a11e7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json @@ -0,0 +1,491 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AutoApproveAllowedSenderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "ConfigChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "RegistrationApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "RegistrationRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "source", + "type": "uint8" + } + ], + "name": "RegistrationRequested", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "emitAutoApproveAllowedSenderSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "emitConfigChanged", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "emitRegistrationApproved", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "emitRegistrationRejected", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint8", + "name": "source", + "type": "uint8" + } + ], + "name": "emitRegistrationRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getRegistrationConfig", + "outputs": [ + { + "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "approvedCount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minLINKJuels", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_approvedCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_autoApproveConfigType", + "outputs": [ + { + "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_autoApproveMaxAllowed", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_keeperRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_minLINKJuels", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", + "name": "_autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "_autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_approvedCount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "_keeperRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_minLINKJuels", + "type": "uint256" + } + ], + "name": "setRegistrationConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json new file mode 100644 index 0000000..2286e96 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json @@ -0,0 +1,654 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "LINKAddress", + "type": "address" + }, + { + "internalType": "enum KeeperRegistrar2_0.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "autoApproveMaxAllowed", + "type": "uint16" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "FunctionNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "HashMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientPayment", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAdminAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "LinkTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdminOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyLink", + "type": "error" + }, + { + "inputs": [], + "name": "RegistrationRequestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "RequestNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "SenderMismatch", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "AutoApproveAllowedSenderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum KeeperRegistrar2_0.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "ConfigChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "displayName", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "RegistrationApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "RegistrationRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "RegistrationRequested", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "cancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + } + ], + "name": "getAutoApproveAllowedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getPendingRequest", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRegistrationConfig", + "outputs": [ + { + "internalType": "enum KeeperRegistrar2_0.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "autoApproveMaxAllowed", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "approvedCount", + "type": "uint32" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minLINKJuels", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "register", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes", + "name": "encryptedEmail", + "type": "bytes" + }, + { + "internalType": "address", + "name": "upkeepContract", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "adminAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "internalType": "struct KeeperRegistrar2_0.RegistrationParams", + "name": "requestParams", + "type": "tuple" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "setAutoApproveAllowedSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum KeeperRegistrar2_0.AutoApproveType", + "name": "autoApproveConfigType", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "autoApproveMaxAllowed", + "type": "uint16" + }, + { + "internalType": "address", + "name": "keeperRegistry", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minLINKJuels", + "type": "uint96" + } + ], + "name": "setRegistrationConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json new file mode 100644 index 0000000..0166311 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json @@ -0,0 +1,1486 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkEthFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "KeepersMustTakeTurns", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveKeepers", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotActive", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "KeepersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "inputs": [], + "name": "FAST_GAS_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maxLinkPayment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adjustedGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkEth", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getKeeperInfo", + "outputs": [ + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum KeeperRegistry1_2.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + } + ], + "internalType": "struct State", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "lastKeeper", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setKeepers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistry1_2.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json new file mode 100644 index 0000000..44f3d33 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json @@ -0,0 +1,1744 @@ +[ + { + "inputs": [ + { + "internalType": "contract KeeperRegistryLogic1_3", + "name": "keeperRegistryLogic", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "KeepersMustTakeTurns", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveKeepers", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "KeepersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "ARB_NITRO_ORACLE", + "outputs": [ + { + "internalType": "contract ArbGasInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FAST_GAS_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEEPER_REGISTRY_LOGIC", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPTIMISM_ORACLE", + "outputs": [ + { + "internalType": "contract OVM_GasPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAYMENT_MODEL", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase1_3.PaymentModel", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REGISTRY_GAS_OVERHEAD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maxLinkPayment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adjustedGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkEth", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getKeeperInfo", + "outputs": [ + { + "internalType": "address", + "name": "payee", + "type": "address" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + } + ], + "internalType": "struct State", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "lastKeeper", + "type": "address" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setKeepers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json new file mode 100644 index 0000000..edb6ac6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json @@ -0,0 +1,1951 @@ +[ + { + "inputs": [ + { + "internalType": "contract KeeperRegistryBase2_0", + "name": "keeperRegistryLogic", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnchainConfigNonEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "checkBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistryLogicAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMode", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_0.Mode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct State", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "internalType": "struct OnchainConfig", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct UpkeepInfo", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json new file mode 100644 index 0000000..e94e2d7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json @@ -0,0 +1,1349 @@ +[ + { + "inputs": [ + { + "internalType": "contract KeeperRegistryLogicB2_1", + "name": "logicA", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json new file mode 100644 index 0000000..f02568b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json @@ -0,0 +1,857 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "KeepersMustTakeTurns", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveKeepers", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "KeepersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "ARB_NITRO_ORACLE", + "outputs": [ + { + "internalType": "contract ArbGasInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FAST_GAS_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPTIMISM_ORACLE", + "outputs": [ + { + "internalType": "contract OVM_GasPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAYMENT_MODEL", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase1_3.PaymentModel", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REGISTRY_GAS_OVERHEAD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json new file mode 100644 index 0000000..ef56a9f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json @@ -0,0 +1,882 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnchainConfigNonEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "checkBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMode", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_0.Mode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json new file mode 100644 index 0000000..0d90ae5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json @@ -0,0 +1,944 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json new file mode 100644 index 0000000..910cb03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json @@ -0,0 +1,131 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistryExecutableInterface", + "name": "keeperRegistry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getKeeperRegistry", + "outputs": [ + { + "internalType": "contract AutomationRegistryExecutableInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "measureCheckGas", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json new file mode 100644 index 0000000..cdec278 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json @@ -0,0 +1,172 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "emitOwnershipTransferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "measureCheckGas", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_mockGas", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_mockPayload", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_mockResult", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "result", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "gas", + "type": "uint256" + } + ], + "name": "setMeasureCheckGasResult", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json new file mode 100644 index 0000000..e81632a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json @@ -0,0 +1,1208 @@ +[ + { + "inputs": [ + { + "internalType": "enum KeeperRegistryBase1_3.PaymentModel", + "name": "paymentModel", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "registryGasOverhead", + "type": "uint256" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkEthFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyAddress", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "KeepersMustTakeTurns", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveKeepers", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "blockCountPerTurn", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address", + "name": "registrar", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct Config", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "KeepersUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "ARB_NITRO_ORACLE", + "outputs": [ + { + "internalType": "contract ArbGasInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FAST_GAS_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "OPTIMISM_ORACLE", + "outputs": [ + { + "internalType": "contract OVM_GasPriceOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAYMENT_MODEL", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase1_3.PaymentModel", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REGISTRY_GAS_OVERHEAD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "maxLinkPayment", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "adjustedGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkEth", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "keepers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setKeepers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json new file mode 100644 index 0000000..c6ba131 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json @@ -0,0 +1,1290 @@ +[ + { + "inputs": [ + { + "internalType": "enum KeeperRegistryBase2_0.Mode", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnchainConfigNonEmpty", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "checkBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "executeGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMode", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_0.Mode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json new file mode 100644 index 0000000..ba56eaa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json @@ -0,0 +1,1326 @@ +[ + { + "inputs": [ + { + "internalType": "contract KeeperRegistryLogicB2_1", + "name": "logicB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkNative", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase2_1.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json new file mode 100644 index 0000000..12f4abe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json @@ -0,0 +1,1938 @@ +[ + { + "inputs": [ + { + "internalType": "enum KeeperRegistryBase2_1.Mode", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "automationForwarderLogic", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MaxCheckDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MaxPerformDataSizeCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentGreaterThanAllLINK", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "OwnerFundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "contract IAutomationForwarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkNativeFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum KeeperRegistryBase2_1.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMode", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_1.Mode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_1.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerPerformByteGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "enum KeeperRegistryBase2_1.Trigger", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum KeeperRegistryBase2_1.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawOwnerFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json new file mode 100644 index 0000000..aa95d60 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json @@ -0,0 +1,242 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "upkeepInterval", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEY_HASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUBSCRIPTION_ID", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UPKEEP_INTERVAL", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastTimeStamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfRequestCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfResponseCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json new file mode 100644 index 0000000..8816e0e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json @@ -0,0 +1,215 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes10", + "name": "workflowName", + "type": "bytes10" + } + ], + "name": "UnauthorizedWorkflowName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "workflowOwner", + "type": "address" + } + ], + "name": "UnauthorizedWorkflowOwner", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint224", + "name": "price", + "type": "uint224" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "timestamp", + "type": "uint32" + } + ], + "name": "FeedReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + } + ], + "name": "onReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_allowedSendersList", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_allowedWorkflowOwnersList", + "type": "address[]" + }, + { + "internalType": "bytes10[]", + "name": "_allowedWorkflowNamesList", + "type": "bytes10[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json new file mode 100644 index 0000000..6bbbef4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json @@ -0,0 +1,185 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "internalType": "address", + "name": "workflowOwner", + "type": "address" + }, + { + "internalType": "bytes10", + "name": "workflowName", + "type": "bytes10" + }, + { + "internalType": "bytes2", + "name": "reportName", + "type": "bytes2" + } + ], + "name": "ReportForwarderUnauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "reportId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "internalType": "bytes10", + "name": "workflowName", + "type": "bytes10" + }, + { + "internalType": "bytes2", + "name": "reportName", + "type": "bytes2" + }, + { + "internalType": "address", + "name": "workflowOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "isAllowed", + "type": "bool" + } + ], + "indexed": false, + "internalType": "struct KeystoneFeedsPermissionHandler.Permission", + "name": "permission", + "type": "tuple" + } + ], + "name": "ReportPermissionSet", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "internalType": "bytes10", + "name": "workflowName", + "type": "bytes10" + }, + { + "internalType": "bytes2", + "name": "reportName", + "type": "bytes2" + }, + { + "internalType": "address", + "name": "workflowOwner", + "type": "address" + }, + { + "internalType": "bool", + "name": "isAllowed", + "type": "bool" + } + ], + "internalType": "struct KeystoneFeedsPermissionHandler.Permission[]", + "name": "permissions", + "type": "tuple[]" + } + ], + "name": "setReportPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json new file mode 100644 index 0000000..f62e5b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json @@ -0,0 +1,585 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + } + ], + "name": "AlreadyAttempted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "DuplicateSigner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSigners", + "type": "uint256" + } + ], + "name": "ExcessSigners", + "type": "error" + }, + { + "inputs": [], + "name": "FaultToleranceMustBePositive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + } + ], + "name": "InsufficientGasForRouting", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSigners", + "type": "uint256" + } + ], + "name": "InsufficientSigners", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "configId", + "type": "uint64" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "received", + "type": "uint256" + } + ], + "name": "InvalidSignatureCount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedForwarder", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "uint32", + "name": "configVersion", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "ForwarderAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "ForwarderRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + }, + { + "indexed": false, + "internalType": "bool", + "name": "result", + "type": "bool" + } + ], + "name": "ReportProcessed", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "addForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configVersion", + "type": "uint32" + } + ], + "name": "clearConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmissionId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmissionInfo", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + }, + { + "internalType": "enum IRouter.TransmissionState", + "name": "state", + "type": "uint8" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "bool", + "name": "invalidReceiver", + "type": "bool" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint80", + "name": "gasLimit", + "type": "uint80" + } + ], + "internalType": "struct IRouter.TransmissionInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "workflowExecutionId", + "type": "bytes32" + }, + { + "internalType": "bytes2", + "name": "reportId", + "type": "bytes2" + } + ], + "name": "getTransmitter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "removeForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "reportContext", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "signatures", + "type": "bytes[]" + } + ], + "name": "report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "transmissionId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "validatedReport", + "type": "bytes" + } + ], + "name": "route", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "donId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "configVersion", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json new file mode 100644 index 0000000..ffd9177 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json @@ -0,0 +1,347 @@ +[ + { + "inputs": [], + "name": "NotDepositor", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "name", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "symbol", + "type": "bytes32" + } + ], + "name": "GasPayingTokenSet", + "type": "event" + }, + { + "inputs": [], + "name": "DEPOSITOR_ACCOUNT", + "outputs": [ + { + "internalType": "address", + "name": "addr_", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "baseFeeScalar", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "basefee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batcherHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blobBaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blobBaseFeeScalar", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPayingToken", + "outputs": [ + { + "internalType": "address", + "name": "addr_", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPayingTokenName", + "outputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPayingTokenSymbol", + "outputs": [ + { + "internalType": "string", + "name": "symbol_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isCustomGasToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1FeeOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1FeeScalar", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "number", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint8", + "name": "_decimals", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_name", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_symbol", + "type": "bytes32" + } + ], + "name": "setGasPayingToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_timestamp", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "_basefee", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_hash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "_sequenceNumber", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "_batcherHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_l1FeeOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_l1FeeScalar", + "type": "uint256" + } + ], + "name": "setL1BlockValues", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "setL1BlockValuesEcotone", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timestamp", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json new file mode 100644 index 0000000..766dff9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json @@ -0,0 +1,946 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "linkToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "maxPerform", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "maxCheck", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "upkeepInterval", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "duplicate", + "type": "address" + } + ], + "name": "DuplicateAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidChainSelector", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "lt", + "type": "address" + } + ], + "name": "InvalidLinkTokenAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maxCheck", + "type": "uint16" + } + ], + "name": "InvalidMaxCheck", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "name": "InvalidMinBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "topUpAmount", + "type": "uint96" + } + ], + "name": "InvalidTopUpAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "upkeepInterval", + "type": "uint8" + } + ], + "name": "InvalidUpkeepInterval", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maxPerform", + "type": "uint16" + } + ], + "name": "InvalixMaxPerform", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "BalanceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxCheck", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMaxCheck", + "type": "uint256" + } + ], + "name": "MaxCheckSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxPerform", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMaxPerform", + "type": "uint256" + } + ], + "name": "MaxPerformSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "s_minWaitPeriodSeconds", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "name": "MinWaitPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "topUpAddress", + "type": "address" + } + ], + "name": "TopUpBlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "topUpAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldTopUpAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTopUpAmount", + "type": "uint256" + } + ], + "name": "TopUpUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldUpkeepInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newUpkeepInterval", + "type": "uint256" + } + ], + "name": "UpkeepIntervalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "WatchlistUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "dstChainSelector", + "type": "uint64" + } + ], + "name": "addToWatchListOrDecommission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "getAccountInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpAmount", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxCheck", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxPerform", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "dstChainSelector", + "type": "uint64" + } + ], + "name": "getOnRampAddressAtChainSelector", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUpkeepInterval", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "targetAddress", + "type": "address" + } + ], + "name": "removeFromWatchList", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sampleUnderfundedAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maxCheck", + "type": "uint16" + } + ], + "name": "setMaxCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maxPerform", + "type": "uint16" + } + ], + "name": "setMaxPerform", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "name": "setMinBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint96", + "name": "topUpAmount", + "type": "uint96" + } + ], + "name": "setTopUpAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "upkeepInterval", + "type": "uint8" + } + ], + "name": "setUpkeepInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "addresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "minBalances", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmounts", + "type": "uint96[]" + }, + { + "internalType": "uint64[]", + "name": "dstChainSelectors", + "type": "uint64[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targetAddresses", + "type": "address[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json new file mode 100644 index 0000000..f1c86bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json @@ -0,0 +1,763 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "supplyAfterMint", + "type": "uint256" + } + ], + "name": "MaxSupplyExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotBurner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotMinter", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBurners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "grantBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAndMinter", + "type": "address" + } + ], + "name": "grantMintAndBurnRoles", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "isBurner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "revokeBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "revokeMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json new file mode 100644 index 0000000..dc470f1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json @@ -0,0 +1,245 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "remaining", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "decimalPlaces", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "tokenName", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "tokenSymbol", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "totalTokensIssued", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json new file mode 100644 index 0000000..37baafd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json @@ -0,0 +1,38 @@ +[ + { + "inputs": [], + "name": "getChainlinkToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json new file mode 100644 index 0000000..f1c86bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json @@ -0,0 +1,763 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "supplyAfterMint", + "type": "uint256" + } + ], + "name": "MaxSupplyExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotBurner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotMinter", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBurners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "grantBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAndMinter", + "type": "address" + } + ], + "name": "grantMintAndBurnRoles", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "isBurner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "revokeBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "revokeMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json new file mode 100644 index 0000000..92fc9cb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json @@ -0,0 +1,1147 @@ +[ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "localChainSelector", + "type": "uint64" + }, + { + "internalType": "contract ILiquidityContainer", + "name": "localLiquidityContainer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + }, + { + "internalType": "address", + "name": "finance", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "expected", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actual", + "type": "bytes32" + } + ], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyReport", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ForkedChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve", + "type": "uint256" + } + ], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + } + ], + "name": "InvalidRemoteChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestSequenceNumber", + "type": "uint64" + } + ], + "name": "NonIncreasingSequenceNumber", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceRole", + "type": "error" + }, + { + "inputs": [], + "name": "OracleCannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "SignaturesOutOfRegistration", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongMessageLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroChainSelector", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "CrossChainRebalancerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "FinalizationFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + } + ], + "name": "FinalizationStepCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "financeRole", + "type": "address" + } + ], + "name": "FinanceRoleSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityAddedToContainer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newLiquidityContainer", + "type": "address" + } + ], + "name": "LiquidityContainerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "remover", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityRemovedFromContainer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "fromChainSelector", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "toChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeReturnData", + "type": "bytes" + } + ], + "name": "LiquidityTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "MinimumLiquiditySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + } + ], + "name": "NativeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "NativeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllCrossChainRebalancers", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + } + ], + "name": "getCrossChainRebalancer", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct LiquidityManager.CrossChainRebalancer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFinanceRole", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "currentLiquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLocalLiquidityContainer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinimumLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSupportedDestChains", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_localToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestSequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nativeBridgeFee", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "rebalanceLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "shouldWrapNative", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "receiveLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs", + "name": "crossChainLiqManager", + "type": "tuple" + } + ], + "name": "setCrossChainRebalancer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "crossChainRebalancers", + "type": "tuple[]" + } + ], + "name": "setCrossChainRebalancers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "finance", + "type": "address" + } + ], + "name": "setFinanceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ILiquidityContainer", + "name": "localLiquidityContainer", + "type": "address" + } + ], + "name": "setLocalLiquidityContainer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + } + ], + "name": "setMinimumLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json new file mode 100644 index 0000000..5418612 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json @@ -0,0 +1,1165 @@ +[ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint64", + "name": "localChainSelector", + "type": "uint64" + }, + { + "internalType": "contract ILiquidityContainer", + "name": "localLiquidityContainer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "targetTokens", + "type": "uint256" + }, + { + "internalType": "address", + "name": "finance", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "expected", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actual", + "type": "bytes32" + } + ], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyReport", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ForkedChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "reserve", + "type": "uint256" + } + ], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + } + ], + "name": "InvalidRemoteChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestSequenceNumber", + "type": "uint64" + } + ], + "name": "NonIncreasingSequenceNumber", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceRole", + "type": "error" + }, + { + "inputs": [], + "name": "OracleCannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "SignaturesOutOfRegistration", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongMessageLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroChainSelector", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "CrossChainRebalancerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "FinalizationFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + } + ], + "name": "FinalizationStepCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "financeRole", + "type": "address" + } + ], + "name": "FinanceRoleSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityAddedToContainer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newLiquidityContainer", + "type": "address" + } + ], + "name": "LiquidityContainerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "remover", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityRemovedFromContainer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "fromChainSelector", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "toChainSelector", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeSpecificData", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "bridgeReturnData", + "type": "bytes" + } + ], + "name": "LiquidityTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "MinimumLiquiditySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + } + ], + "name": "NativeDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "NativeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllCrossChainRebalancers", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + } + ], + "name": "getCrossChainRebalancer", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct LiquidityManager.CrossChainRebalancer", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFinanceRole", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "currentLiquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLocalLiquidityContainer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinimumLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSupportedDestChains", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_localToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestSequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "chainSelector", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nativeBridgeFee", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "rebalanceLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "shouldWrapNative", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "receiveLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "removeLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "rep", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "ocrSeqNum", + "type": "uint64" + } + ], + "name": "report", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs", + "name": "crossChainLiqManager", + "type": "tuple" + } + ], + "name": "setCrossChainRebalancer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "crossChainRebalancers", + "type": "tuple[]" + } + ], + "name": "setCrossChainRebalancers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "finance", + "type": "address" + } + ], + "name": "setFinanceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ILiquidityContainer", + "name": "localLiquidityContainer", + "type": "address" + } + ], + "name": "setLocalLiquidityContainer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minimumLiquidity", + "type": "uint256" + } + ], + "name": "setMinimumLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawERC20", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "destination", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json new file mode 100644 index 0000000..83a5b5b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json @@ -0,0 +1,122 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "Log1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "Log2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "Log3", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "Log4", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "v", + "type": "uint256[]" + } + ], + "name": "EmitLog1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "v", + "type": "uint256[]" + } + ], + "name": "EmitLog2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "v", + "type": "string[]" + } + ], + "name": "EmitLog3", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "v", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "w", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + } + ], + "name": "EmitLog4", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json new file mode 100644 index 0000000..877d5fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json @@ -0,0 +1,419 @@ +[ + { + "inputs": [ + { + "internalType": "bool", + "name": "_useArbitrumBlockNum", + "type": "bool" + }, + { + "internalType": "bool", + "name": "_verify", + "type": "bool" + }, + { + "internalType": "bool", + "name": "_checkErrReturnBool", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "IgnoringErrorHandlerData", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "exchange", + "type": "address" + } + ], + "name": "LimitOrderExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "orderId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "exchange", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "blob", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "verified", + "type": "bytes" + } + ], + "name": "PerformingLogTriggerUpkeep", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkErrReturnBool", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "log", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkLog", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feedsHex", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParam", + "type": "string" + } + ], + "name": "setFeedParamKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "newFeeds", + "type": "string[]" + } + ], + "name": "setFeedsHex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "timeParam", + "type": "string" + } + ], + "name": "setTimeParamKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbitrumBlockNum", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json new file mode 100644 index 0000000..c9b1fd9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json @@ -0,0 +1,321 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lastBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "counter", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Trigger", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "a", + "type": "uint256" + } + ], + "name": "Trigger", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "Trigger", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "b", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "c", + "type": "uint256" + } + ], + "name": "Trigger", + "type": "event" + }, + { + "inputs": [], + "name": "autoExecution", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "log", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkLog", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "previousPerformBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_auto", + "type": "bool" + } + ], + "name": "setAuto", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + } + ], + "name": "setSpread", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "start", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json new file mode 100644 index 0000000..57999bd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json @@ -0,0 +1,41 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json new file mode 100644 index 0000000..3c6f738 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json @@ -0,0 +1,85 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "capabilityWithConfigContractId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapabilityConfigurationSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "beforeCapabilityConfigSet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "getCapabilityConfiguration", + "outputs": [ + { + "internalType": "bytes", + "name": "configuration", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json new file mode 100644 index 0000000..394fcb4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json @@ -0,0 +1,194 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "assertFail", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "cancelRequestOnFulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "doesNothing", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_callbackFunc", + "type": "bytes" + } + ], + "name": "requestData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "stealEthCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "stealEthSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "stealEthTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json new file mode 100644 index 0000000..3f3c063 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json @@ -0,0 +1,194 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "assertFail", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "cancelRequestOnFulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "doesNothing", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_callbackFunc", + "type": "bytes" + } + ], + "name": "requestData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "stealEthCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "stealEthSend", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "stealEthTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json new file mode 100644 index 0000000..d66181e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json @@ -0,0 +1,71 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "mercuryReports", + "type": "bytes[]" + } + ], + "name": "MessageReceived", + "type": "event" + }, + { + "inputs": [], + "name": "latestReport", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + } + ], + "name": "onReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json new file mode 100644 index 0000000..ef0dd9d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json @@ -0,0 +1,167 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "doesNothing", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + } + ], + "name": "maliciousPrice", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_callbackFunc", + "type": "bytes" + } + ], + "name": "maliciousRequestCancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "maliciousTargetConsumer", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maliciousWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_id", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_callbackFunc", + "type": "bytes" + } + ], + "name": "request", + "outputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json new file mode 100644 index 0000000..624fce5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "onReport", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json new file mode 100644 index 0000000..e75de3c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json @@ -0,0 +1,7 @@ +[ + { + "inputs": [], + "name": "MathOverflowedMulDiv", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json new file mode 100644 index 0000000..831a2be --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json @@ -0,0 +1,594 @@ +[ + { + "inputs": [ + { + "internalType": "string[]", + "name": "feedIds", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "feedNames", + "type": "string[]" + }, + { + "internalType": "int192[]", + "name": "deviationPercentagePPMs", + "type": "int192[]" + }, + { + "internalType": "uint32[]", + "name": "stalenessSeconds", + "type": "uint32[]" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedId", + "type": "string" + } + ], + "name": "DuplicateFeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedId", + "type": "string" + } + ], + "name": "FeedNotActive", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeeds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedId", + "type": "string" + }, + { + "internalType": "uint32", + "name": "currentTimestamp", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "incomingTimestamp", + "type": "uint32" + } + ], + "name": "StaleReport", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "observationsTimestamp", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int192", + "name": "price", + "type": "int192" + }, + { + "indexed": false, + "internalType": "int192", + "name": "bid", + "type": "int192" + }, + { + "indexed": false, + "internalType": "int192", + "name": "ask", + "type": "int192" + }, + { + "indexed": false, + "internalType": "string", + "name": "feedId", + "type": "string" + } + ], + "name": "FeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "feedIds", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "feedNames", + "type": "string[]" + }, + { + "internalType": "int192[]", + "name": "deviationPercentagePPMs", + "type": "int192[]" + }, + { + "internalType": "uint32[]", + "name": "stalenessSeconds", + "type": "uint32[]" + } + ], + "name": "addFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "lookupData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int192", + "name": "onChain", + "type": "int192" + }, + { + "internalType": "int192", + "name": "offChain", + "type": "int192" + }, + { + "internalType": "int192", + "name": "deviationPercentagePPM", + "type": "int192" + } + ], + "name": "deviationExceedsThreshold", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "feedIds", + "type": "string[]" + } + ], + "name": "getLatestFeedData", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "observationsTimestamp", + "type": "uint32" + }, + { + "internalType": "int192", + "name": "price", + "type": "int192" + }, + { + "internalType": "int192", + "name": "bid", + "type": "int192" + }, + { + "internalType": "int192", + "name": "ask", + "type": "int192" + }, + { + "internalType": "string", + "name": "feedName", + "type": "string" + }, + { + "internalType": "string", + "name": "feedId", + "type": "string" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "int192", + "name": "deviationPercentagePPM", + "type": "int192" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + } + ], + "internalType": "struct MercuryRegistry.Feed[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + } + ], + "name": "revertForFeedLookup", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "s_feedMapping", + "outputs": [ + { + "internalType": "uint32", + "name": "observationsTimestamp", + "type": "uint32" + }, + { + "internalType": "int192", + "name": "price", + "type": "int192" + }, + { + "internalType": "int192", + "name": "bid", + "type": "int192" + }, + { + "internalType": "int192", + "name": "ask", + "type": "int192" + }, + { + "internalType": "string", + "name": "feedName", + "type": "string" + }, + { + "internalType": "string", + "name": "feedId", + "type": "string" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "int192", + "name": "deviationPercentagePPM", + "type": "int192" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_feeds", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_verifier", + "outputs": [ + { + "internalType": "contract IVerifierProxy", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "feedIds", + "type": "string[]" + }, + { + "internalType": "string[]", + "name": "feedNames", + "type": "string[]" + }, + { + "internalType": "int192[]", + "name": "deviationPercentagePPMs", + "type": "int192[]" + }, + { + "internalType": "uint32[]", + "name": "stalenessSeconds", + "type": "uint32[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "setVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json new file mode 100644 index 0000000..4d6c39f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json @@ -0,0 +1,306 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "mercuryRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "batchStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "batchEnd", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchsize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxBatchSize", + "type": "uint256" + } + ], + "name": "BatchSizeTooLarge", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_BATCH_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "lookupData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_registry", + "outputs": [ + { + "internalType": "contract MercuryRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_batchEnd", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_batchStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "batchStart", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "batchEnd", + "type": "uint256" + } + ], + "name": "updateBatchingWindow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json new file mode 100644 index 0000000..f938ae8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json @@ -0,0 +1,46 @@ +[ + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIDs", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTranscoderVersion", + "outputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "version", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json new file mode 100644 index 0000000..09b1ae3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json @@ -0,0 +1,46 @@ +[ + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIDs", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json new file mode 100644 index 0000000..da51df1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json @@ -0,0 +1,67 @@ +[ + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newRoundCalled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "requestNewRound", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_answer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "answer", + "type": "int256" + } + ], + "name": "setLatestAnswer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json new file mode 100644 index 0000000..3178781 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_aggregator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "aggregator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_aggregator", + "type": "address" + } + ], + "name": "updateAggregator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json new file mode 100644 index 0000000..f105b55 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json @@ -0,0 +1,240 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json new file mode 100644 index 0000000..130b3bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json @@ -0,0 +1,84 @@ +[ + { + "inputs": [ + { + "internalType": "uint8", + "name": "id_", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "id", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "ValidateCalled", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json new file mode 100644 index 0000000..ba3d9bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json @@ -0,0 +1,53 @@ +[ + { + "inputs": [], + "name": "getCurrentTxL1GasFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricesInWei", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json new file mode 100644 index 0000000..4170e94 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json @@ -0,0 +1,34 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "arbBlockNum", + "type": "uint256" + } + ], + "name": "arbBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "arbBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json new file mode 100644 index 0000000..20aa581 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json @@ -0,0 +1,462 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InboxMessageDelivered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "messageNum", + "type": "uint256" + } + ], + "name": "InboxMessageDeliveredFromOrigin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "RetryableTicketNoRefundAliasRewriteCreated", + "type": "event" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "contract IBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "baseFee", + "type": "uint256" + } + ], + "name": "calculateRetryableSubmissionFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "createRetryableTicket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "destAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "arbTxCallValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSubmissionCost", + "type": "uint256" + }, + { + "internalType": "address", + "name": "submissionRefundAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "valueRefundAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasPriceBid", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "createRetryableTicketNoRefundAliasRewrite", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "depositEth", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "depositEthRetryable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendL1FundedContractTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendL1FundedUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendL2Message", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendUnsignedTransaction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json new file mode 100644 index 0000000..5761ba0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json @@ -0,0 +1,795 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "NotAuthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "stateTransitionManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "chainGovernance", + "type": "address" + } + ], + "name": "NewChain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_stateTransitionManager", + "type": "address" + } + ], + "name": "addStateTransitionManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "name": "addToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + } + ], + "name": "baseToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "baseTokens", + "outputs": [ + { + "internalType": "address", + "name": "baseToken", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_stateTransitionManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_baseToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "createNewChain", + "outputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + } + ], + "name": "getHyperchain", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "hyperchains", + "outputs": [ + { + "internalType": "address", + "name": "hyperChain", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "l2TransactionBaseCost", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "enum TxStatus", + "name": "", + "type": "uint8" + } + ], + "name": "proveL1ToL2TransactionStatus", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "l2ShardId", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "isService", + "type": "bool" + }, + { + "internalType": "uint16", + "name": "txNumberInBatch", + "type": "uint16" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + } + ], + "internalType": "struct L2Log", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "name": "proveL2LogInclusion", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint16", + "name": "txNumberInBatch", + "type": "uint16" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct L2Message", + "name": "", + "type": "tuple" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "name": "proveL2MessageInclusion", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "stateTransitionManager", + "type": "address" + } + ], + "name": "registeredStateTransitionManagers", + "outputs": [ + { + "internalType": "bool", + "name": "stateTransitionManagerIsRegistered", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "baseToken", + "type": "address" + } + ], + "name": "registeredTokens", + "outputs": [ + { + "internalType": "bool", + "name": "tokenIsRegistered", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_stateTransitionManager", + "type": "address" + } + ], + "name": "removeStateTransitionManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintValue", + "type": "uint256" + }, + { + "internalType": "address", + "name": "l2Contract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "l2Value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "l2Calldata", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "l2GasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2GasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "factoryDeps", + "type": "bytes[]" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + } + ], + "internalType": "struct L2TransactionRequestDirect", + "name": "txRequest", + "type": "tuple" + } + ], + "name": "requestL2TransactionDirect", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2Value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2GasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "l2GasPerPubdataByteLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + }, + { + "internalType": "address", + "name": "secondBridgeAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "secondBridgeValue", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "secondBridgeCalldata", + "type": "bytes" + } + ], + "internalType": "struct L2TransactionRequestTwoBridgesOuter", + "name": "", + "type": "tuple" + } + ], + "name": "requestL2TransactionTwoBridges", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newPendingAdmin", + "type": "address" + } + ], + "name": "setPendingAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sharedBridgeAddr", + "type": "address" + } + ], + "name": "setSharedBridge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sharedBridge", + "outputs": [ + { + "internalType": "contract IL1SharedBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sharedBridgeAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_chainId", + "type": "uint256" + } + ], + "name": "stateTransitionManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_stateTransitionManager", + "type": "address" + } + ], + "name": "stateTransitionManagerIsRegistered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainId", + "type": "uint256" + } + ], + "name": "stateTransitionManagers", + "outputs": [ + { + "internalType": "address", + "name": "stateTransitionManagerAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_baseToken", + "type": "address" + } + ], + "name": "tokenIsRegistered", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json new file mode 100644 index 0000000..dafee02 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json @@ -0,0 +1,137 @@ +[ + { + "inputs": [ + { + "internalType": "int256", + "name": "_answer", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "answer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json new file mode 100644 index 0000000..760d0fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json @@ -0,0 +1,150 @@ +[ + { + "inputs": [ + { + "internalType": "int256", + "name": "_answer", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "answer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_blockTimestampDeduction", + "type": "uint256" + } + ], + "name": "setBlockTimestampDeduction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json new file mode 100644 index 0000000..65f9a26 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json @@ -0,0 +1,36 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "TransactionFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "gasAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "gasBoundCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json new file mode 100644 index 0000000..36750f8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json @@ -0,0 +1,138 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "updateCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json new file mode 100644 index 0000000..1b914f1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json @@ -0,0 +1,322 @@ +[ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "holdNative", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFinalizationAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [], + "name": "NativeSendFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "NonceAlreadyUsed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "NonceNotProven", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "provider", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LiquidityRemoved", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "internalType": "struct MockL1BridgeAdapter.FinalizePayload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodeFinalizePayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "enum MockL1BridgeAdapter.FinalizationAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct MockL1BridgeAdapter.Payload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodePayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "internalType": "struct MockL1BridgeAdapter.ProvePayload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodeProvePayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "localReceiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "bridgeSpecificPayload", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "provideLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLiquidity", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json new file mode 100644 index 0000000..8df42ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json @@ -0,0 +1,131 @@ +[ + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json new file mode 100644 index 0000000..87147a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json @@ -0,0 +1,135 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "setBalance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "totalTokensIssued", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json new file mode 100644 index 0000000..01ef6d2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json @@ -0,0 +1,101 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "_setMockMessageSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json new file mode 100644 index 0000000..b4532b3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json @@ -0,0 +1,40 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "getL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getL1FeeUpperBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json new file mode 100644 index 0000000..3b7e646 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json @@ -0,0 +1,41 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + } + ], + "name": "RoundIdUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "requestNewRound", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roundId", + "outputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json new file mode 100644 index 0000000..f2612dc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json @@ -0,0 +1,238 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_messageNonce", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "batchIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "batchRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "batchSize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "prevTotalElements", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "internalType": "struct Lib_OVMCodec.ChainBatchHeader", + "name": "stateRootBatchHeader", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "siblings", + "type": "bytes32[]" + } + ], + "internalType": "struct Lib_OVMCodec.ChainInclusionProof", + "name": "stateRootProof", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "stateTrieWitness", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "storageTrieWitness", + "type": "bytes" + } + ], + "internalType": "struct IL1CrossDomainMessenger.L2MessageInclusionProof", + "name": "_proof", + "type": "tuple" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_queueIndex", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "_oldGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_newGasLimit", + "type": "uint32" + } + ], + "name": "replayMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "_gasLimit", + "type": "uint32" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json new file mode 100644 index 0000000..eaf980a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json @@ -0,0 +1,146 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_messageNonce", + "type": "uint256" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "_gasLimit", + "type": "uint32" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newSender", + "type": "address" + } + ], + "name": "setSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json new file mode 100644 index 0000000..e8f355d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json @@ -0,0 +1,35 @@ +[ + { + "inputs": [], + "name": "getValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "receiveData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revertMessage", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json new file mode 100644 index 0000000..3a579fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json @@ -0,0 +1,169 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "_setMockMessageSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json new file mode 100644 index 0000000..e220cef --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json @@ -0,0 +1,284 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxReplayTimes", + "type": "uint256" + } + ], + "name": "UpdateMaxReplayTimes", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "dropMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "batchIndex", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "merkleProof", + "type": "bytes" + } + ], + "internalType": "struct IL1ScrollMessenger.L2MessageProof", + "name": "proof", + "type": "tuple" + } + ], + "name": "relayMessageWithProof", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "newGasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "refundAddress", + "type": "address" + } + ], + "name": "replayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json new file mode 100644 index 0000000..bab0cce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json @@ -0,0 +1,302 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "skippedBitmap", + "type": "uint256" + } + ], + "name": "DequeueTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "DropTransaction", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "queueIndex", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "QueueTransaction", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "appendCrossDomainMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "appendEnforcedTransaction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "calculateIntrinsicGasFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "computeTransactionHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "dropCrossDomainMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "estimateCrossDomainMessageFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getCrossDomainMessage", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "nextCrossDomainMessageIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "pendingQueueIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "skippedBitmap", + "type": "uint256" + } + ], + "name": "popCrossDomainMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json new file mode 100644 index 0000000..4dab44f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json @@ -0,0 +1,195 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "messageNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_gasLimit", + "type": "uint256" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newSender", + "type": "address" + } + ], + "name": "setSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json new file mode 100644 index 0000000..d3fc208 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json @@ -0,0 +1,218 @@ +[ + { + "inputs": [], + "name": "CheckRevert", + "type": "error" + }, + { + "inputs": [], + "name": "PerformRevert", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "upkeepData", + "type": "bytes" + } + ], + "name": "UpkeepPerformedWith", + "type": "event" + }, + { + "inputs": [], + "name": "checkGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkResult", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "callable", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "executedata", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setCheckGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setCheckResult", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setPerformData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldCheckRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldPerformRevert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shouldCheckRevert", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "shouldPerformRevert", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json new file mode 100644 index 0000000..bd452b6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json @@ -0,0 +1,297 @@ +[ + { + "inputs": [ + { + "internalType": "uint8", + "name": "_decimals", + "type": "uint8" + }, + { + "internalType": "int256", + "name": "_initialAnswer", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "_answer", + "type": "int256" + } + ], + "name": "updateAnswer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "_answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "_timestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startedAt", + "type": "uint256" + } + ], + "name": "updateRoundData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json new file mode 100644 index 0000000..b8a632e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json @@ -0,0 +1,41 @@ +[ + { + "inputs": [], + "name": "gasPerPubdataByte", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPubdataSpent", + "outputs": [ + { + "internalType": "uint256", + "name": "currentPubdataSpent", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json new file mode 100644 index 0000000..89d3ba5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "transactions", + "type": "bytes" + } + ], + "name": "multiSend", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json new file mode 100644 index 0000000..bf30425 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json @@ -0,0 +1,432 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_specId", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "id", + "type": "bytes32" + } + ], + "name": "ChainlinkRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes", + "name": "price", + "type": "bytes" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "usd", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "eur", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "jpy", + "type": "bytes32" + } + ], + "name": "RequestMultipleFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "usd", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "eur", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "jpy", + "type": "uint256" + } + ], + "name": "RequestMultipleFulfilledWithCustomURLs", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + } + ], + "name": "addExternalRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_oracle", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "_callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "_expiration", + "type": "uint256" + } + ], + "name": "cancelRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "eur", + "outputs": [ + { + "internalType": "bytes32", + "name": "_value", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "_price", + "type": "bytes" + } + ], + "name": "fulfillBytes", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_usd", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_eur", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_jpy", + "type": "bytes32" + } + ], + "name": "fulfillMultipleParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_usd", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_eur", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_jpy", + "type": "uint256" + } + ], + "name": "fulfillMultipleParametersWithCustomURLs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPrice", + "outputs": [ + { + "internalType": "bytes", + "name": "_value", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "jpy", + "outputs": [ + { + "internalType": "bytes32", + "name": "_value", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "publicGetNextRequestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestEthereumPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestMultipleParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_urlUSD", + "type": "string" + }, + { + "internalType": "string", + "name": "_pathUSD", + "type": "string" + }, + { + "internalType": "string", + "name": "_urlEUR", + "type": "string" + }, + { + "internalType": "string", + "name": "_pathEUR", + "type": "string" + }, + { + "internalType": "string", + "name": "_urlJPY", + "type": "string" + }, + { + "internalType": "string", + "name": "_pathJPY", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_payment", + "type": "uint256" + } + ], + "name": "requestMultipleParametersWithCustomURLs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_specId", + "type": "bytes32" + } + ], + "name": "setSpecID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usd", + "outputs": [ + { + "internalType": "bytes32", + "name": "_value", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json new file mode 100644 index 0000000..58bd2e2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json @@ -0,0 +1,396 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "expected", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actual", + "type": "bytes32" + } + ], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ForkedChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestSequenceNumber", + "type": "uint64" + } + ], + "name": "NonIncreasingSequenceNumber", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "OracleCannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "SignaturesOutOfRegistration", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongMessageLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongNumberOfSignatures", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestSequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json new file mode 100644 index 0000000..ebbdd3d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json @@ -0,0 +1,212 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "signers", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "signers", + "type": "bytes[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json new file mode 100644 index 0000000..8089c1b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json @@ -0,0 +1,318 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "ReportInvalid", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "transmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json new file mode 100644 index 0000000..25d717e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json @@ -0,0 +1,189 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json new file mode 100644 index 0000000..6ce23e3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json @@ -0,0 +1,391 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "expected", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actual", + "type": "bytes32" + } + ], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ForkedChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestSequenceNumber", + "type": "uint64" + } + ], + "name": "NonIncreasingSequenceNumber", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "OracleCannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "SignaturesOutOfRegistration", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongMessageLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongNumberOfSignatures", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestSequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json new file mode 100644 index 0000000..3e46109 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json @@ -0,0 +1,299 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [], + "name": "ReportingUnsupported", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "signers", + "type": "bytes[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "_signers", + "type": "bytes[]" + }, + { + "internalType": "address[]", + "name": "_transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "_f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "_onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "_offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "_offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json new file mode 100644 index 0000000..e2d24b2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json @@ -0,0 +1,463 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "expected", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "actual", + "type": "bytes32" + } + ], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ForkedChain", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "latestSequenceNumber", + "type": "uint64" + } + ], + "name": "NonIncreasingSequenceNumber", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "OracleCannotBeZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "SignaturesOutOfRegistration", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongMessageLength", + "type": "error" + }, + { + "inputs": [], + "name": "WrongNumberOfSignatures", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "chainSelector", + "type": "uint256" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "configDigestFromConfigData", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmitters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestSequenceNumber", + "outputs": [ + { + "internalType": "uint64", + "name": "sequenceNumber", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "newSeqNum", + "type": "uint64" + } + ], + "name": "setLatestSeqNum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setOCR3Config", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "report", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json new file mode 100644 index 0000000..735c1b6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json @@ -0,0 +1,298 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "DecimalsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "GasPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "L1BaseFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "OverheadUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ScalarUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "getL1GasUsed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1BaseFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "overhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "scalar", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_decimals", + "type": "uint256" + } + ], + "name": "setDecimals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_gasPrice", + "type": "uint256" + } + ], + "name": "setGasPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_baseFee", + "type": "uint256" + } + ], + "name": "setL1BaseFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_overhead", + "type": "uint256" + } + ], + "name": "setOverhead", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_scalar", + "type": "uint256" + } + ], + "name": "setScalar", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json new file mode 100644 index 0000000..f995689 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json @@ -0,0 +1,820 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "maxSupply_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "l2Bridge", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "supplyAfterMint", + "type": "uint256" + } + ], + "name": "MaxSupplyExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotBurner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotMinter", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "BurnAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "MintAccessRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBurners", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinters", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "grantBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAndMinter", + "type": "address" + } + ], + "name": "grantMintAndBurnRoles", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "isBurner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "remoteToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burner", + "type": "address" + } + ], + "name": "revokeBurnRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "revokeMintRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "transferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json new file mode 100644 index 0000000..fb0892e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json @@ -0,0 +1,738 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "CancelOracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "specId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "callbackAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "cancelExpiration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "OracleRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + } + ], + "name": "OracleResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "acceptedContract", + "type": "address" + } + ], + "name": "OwnableContractAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "TargetsUpdatedAuthorizedSenders", + "type": "event" + }, + { + "inputs": [], + "name": "EXPIRYTIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "acceptAuthorizedReceivers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "ownable", + "type": "address[]" + } + ], + "name": "acceptOwnableContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "callbackFunc", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "cancelOracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "callbackFunc", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "cancelOracleRequestByRequester", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "distributeFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "data", + "type": "bytes32" + } + ], + "name": "fulfillOracleRequest", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "fulfillOracleRequest2", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChainlinkToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isAuthorizedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "specId", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "operatorRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "specId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "oracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ownerForward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ownerTransferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSenders", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "targets", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSendersOn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "ownable", + "type": "address[]" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnableContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json new file mode 100644 index 0000000..ea31a35 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json @@ -0,0 +1,176 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "AuthorizedForwarderCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "OperatorCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "created", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deployNewForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "deployNewForwarderAndTransferOwnership", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployNewOperator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deployNewOperatorAndForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json new file mode 100644 index 0000000..b5d92c0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json @@ -0,0 +1,287 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "cancelOracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable[]", + "name": "receivers", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "distributeFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "data", + "type": "bytes32" + } + ], + "name": "fulfillOracleRequest", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "fulfillOracleRequest2", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "specId", + "type": "bytes32" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "operatorRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "requestPrice", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "serviceAgreementID", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "dataVersion", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "oracleRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ownerTransferAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json new file mode 100644 index 0000000..ca8ded3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json @@ -0,0 +1,204 @@ +[ + { + "inputs": [ + { + "internalType": "contract iOVM_CrossDomainMessenger", + "name": "crossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json new file mode 100644 index 0000000..5840680 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json @@ -0,0 +1,222 @@ +[ + { + "inputs": [ + { + "internalType": "contract iOVM_CrossDomainMessenger", + "name": "crossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json new file mode 100644 index 0000000..599c939 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json @@ -0,0 +1,200 @@ +[ + { + "inputs": [ + { + "internalType": "contract IL1StandardBridge", + "name": "l1Bridge", + "type": "address" + }, + { + "internalType": "contract IWrappedNative", + "name": "wrappedNative", + "type": "address" + }, + { + "internalType": "contract IOptimismPortal", + "name": "optimismPortal", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFinalizationAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getL1Bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOptimismPortal", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNative", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json new file mode 100644 index 0000000..4322d1e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json @@ -0,0 +1,168 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "enum OptimismL1BridgeAdapter.FinalizationAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodeFinalizeWithdrawalERC20Payload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Types.WithdrawalTransaction", + "name": "withdrawalTransaction", + "type": "tuple" + } + ], + "internalType": "struct OptimismL1BridgeAdapter.OptimismFinalizationPayload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodeOptimismFinalizationPayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Types.WithdrawalTransaction", + "name": "withdrawalTransaction", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "l2OutputIndex", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "version", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "stateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "messagePasserStorageRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "latestBlockhash", + "type": "bytes32" + } + ], + "internalType": "struct Types.OutputRootProof", + "name": "outputRootProof", + "type": "tuple" + }, + { + "internalType": "bytes[]", + "name": "withdrawalProof", + "type": "bytes[]" + } + ], + "internalType": "struct OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload", + "name": "payload", + "type": "tuple" + } + ], + "name": "encodeOptimismProveWithdrawalPayload", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json new file mode 100644 index 0000000..142c04f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json @@ -0,0 +1,158 @@ +[ + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCalculationMode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCalculationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCalculationMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCoefficient", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json new file mode 100644 index 0000000..9c13a13 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json @@ -0,0 +1,172 @@ +[ + { + "inputs": [ + { + "internalType": "contract IWrappedNative", + "name": "wrappedNative", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BridgeAddressCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wanted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "got", + "type": "uint256" + } + ], + "name": "InsufficientEthValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "MsgShouldNotContainValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "msgValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MsgValueDoesNotMatchAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "finalizeWithdrawERC20", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getBridgeFeeInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getL2Bridge", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNative", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "localToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "sendERC20", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json new file mode 100644 index 0000000..a94b46f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json new file mode 100644 index 0000000..57b3556 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json @@ -0,0 +1,216 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCoefficientSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getL1FeeCoefficient", + "outputs": [ + { + "internalType": "uint256", + "name": "coefficient", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json new file mode 100644 index 0000000..730bea0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json @@ -0,0 +1,583 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1SenderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l2CrossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "bool", + "name": "initialStatus", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "NoDataPresent", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1SenderTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int256", + "name": "status", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "updatedAt", + "type": "uint64" + } + ], + "name": "RoundUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "latestStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "latestTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bool", + "name": "incomingStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "incomingTimestamp", + "type": "uint64" + } + ], + "name": "UpdateIgnored", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Sender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json new file mode 100644 index 0000000..e6131b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json @@ -0,0 +1,335 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1CrossDomainMessengerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l2UptimeFeedAddr", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "L1CrossDomainMessengerAddressZero", + "type": "error" + }, + { + "inputs": [], + "name": "L2UptimeFeedAddrZero", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "GasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_UPTIME_FEED_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json new file mode 100644 index 0000000..d74508e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json @@ -0,0 +1,77 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "payment", + "type": "uint256" + }, + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "callbackFunctionId", + "type": "bytes4" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "data", + "type": "bytes32" + } + ], + "name": "fulfillOracleRequest", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json new file mode 100644 index 0000000..890a79d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json @@ -0,0 +1,78 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json new file mode 100644 index 0000000..8b939e6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json @@ -0,0 +1,51 @@ +[ + { + "inputs": [], + "name": "EnforcedPause", + "type": "error" + }, + { + "inputs": [], + "name": "ExpectedPause", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json new file mode 100644 index 0000000..71e27ff --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json @@ -0,0 +1,359 @@ +[ + { + "inputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "linkToken", + "type": "address" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "linkEthFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "entryPoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "juelsNeeded", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "subscriptionBalance", + "type": "uint256" + } + ], + "name": "InsufficientFunds", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + } + ], + "name": "UserOperationAlreadyTried", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "i_entryPoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkEthFeed", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum IPaymaster.PostOpMode", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "actualGasCost", + "type": "uint256" + } + ], + "name": "postOp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "maxCost", + "type": "uint256" + } + ], + "name": "validatePaymasterUserOp", + "outputs": [ + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json new file mode 100644 index 0000000..8c976c3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json @@ -0,0 +1,89 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "expectedData", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_expectedData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "expectedData", + "type": "bytes" + } + ], + "name": "setExpectedData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json new file mode 100644 index 0000000..2e61e1e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json @@ -0,0 +1,183 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "PermissionNotSet", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "PermissionRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "PermissionSet", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "handler", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "getPermission", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "removePermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "setPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json new file mode 100644 index 0000000..5f3bb0b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "getPoRAddressList", + "outputs": [ + { + "internalType": "string[]", + "name": "", + "type": "string[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPoRAddressListLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json new file mode 100644 index 0000000..c5ae2c8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "getAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json new file mode 100644 index 0000000..c1dd512 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json @@ -0,0 +1,10 @@ +[ + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json new file mode 100644 index 0000000..6a75bdb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json @@ -0,0 +1,25 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "FundsReceived", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json new file mode 100644 index 0000000..7c7fdcf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json @@ -0,0 +1,25 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "FundsReceived", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json new file mode 100644 index 0000000..d48d964 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json @@ -0,0 +1,6 @@ +[ + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json new file mode 100644 index 0000000..3f30efb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json @@ -0,0 +1,76 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes[]", + "name": "mercuryReports", + "type": "bytes[]" + } + ], + "name": "MessageReceived", + "type": "event" + }, + { + "inputs": [], + "name": "latestReport", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + } + ], + "name": "onReport", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json new file mode 100644 index 0000000..3afbe73 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json @@ -0,0 +1,124 @@ +[ + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nativeBridgeFee", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "bridgeData", + "type": "bytes" + } + ], + "internalType": "struct ILiquidityManager.SendLiquidityParams[]", + "name": "sendLiquidityParams", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "shouldWrapNative", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "bridgeData", + "type": "bytes" + } + ], + "internalType": "struct ILiquidityManager.ReceiveLiquidityParams[]", + "name": "receiveLiquidityParams", + "type": "tuple[]" + } + ], + "internalType": "struct ILiquidityManager.LiquidityInstructions", + "name": "instructions", + "type": "tuple" + } + ], + "name": "exposeForEncoding", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getAllCrossChainRebalancers", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "remoteRebalancer", + "type": "address" + }, + { + "internalType": "contract IBridgeAdapter", + "name": "localBridge", + "type": "address" + }, + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "internalType": "uint64", + "name": "remoteChainSelector", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "currentLiquidity", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json new file mode 100644 index 0000000..bbe09c3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json @@ -0,0 +1,535 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPoolId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPoolLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWeights", + "type": "error" + }, + { + "inputs": [], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newFeeManagerAddress", + "type": "address" + } + ], + "name": "FeeManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "indexed": false, + "internalType": "struct IRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "FeePaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "RewardRecipientsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint192", + "name": "quantity", + "type": "uint192" + } + ], + "name": "RewardsClaimed", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "poolIds", + "type": "bytes32[]" + } + ], + "name": "claimRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "getAvailableRewardPoolIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_linkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "uint192", + "name": "amount", + "type": "uint192" + } + ], + "internalType": "struct IRewardManager.FeePayment[]", + "name": "payments", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + } + ], + "name": "onFeePaid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "recipients", + "type": "address[]" + } + ], + "name": "payRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManagerAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_registeredPoolIds", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_rewardRecipientWeights", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_rewardRecipientWeightsSet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_totalRewardRecipientFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_totalRewardRecipientFeesLastClaimedAmounts", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newFeeManagerAddress", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "rewardRecipientAndWeights", + "type": "tuple[]" + } + ], + "name": "setRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "poolId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "newRewardRecipients", + "type": "tuple[]" + } + ], + "name": "updateRewardRecipients", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json new file mode 100644 index 0000000..35733b2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json @@ -0,0 +1,30 @@ +[ + { + "inputs": [], + "name": "OnlyCallableByRouter", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByRouterOwner", + "type": "error" + }, + { + "inputs": [], + "name": "RouterMustBeSet", + "type": "error" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json new file mode 100644 index 0000000..e16ec27 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json @@ -0,0 +1,235 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "entryPoint", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BadFormatOrOOG", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentNonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "nonceGiven", + "type": "uint256" + } + ], + "name": "IncorrectNonce", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "operationHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "NotAuthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentTimestamp", + "type": "uint256" + } + ], + "name": "TransactionExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint48", + "name": "deadline", + "type": "uint48" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "executeTransactionFromEntryPoint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "i_entryPoint", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_nonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "callGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "verificationGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preVerificationGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxFeePerGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPriorityFeePerGas", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "paymasterAndData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "internalType": "struct UserOperation", + "name": "userOp", + "type": "tuple" + }, + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "validateUserOp", + "outputs": [ + { + "internalType": "uint256", + "name": "validationData", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json new file mode 100644 index 0000000..6627861 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json @@ -0,0 +1,56 @@ +[ + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "int256", + "name": "value", + "type": "int256" + } + ], + "name": "SafeCastOverflowedIntDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "value", + "type": "int256" + } + ], + "name": "SafeCastOverflowedIntToUint", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "bits", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintDowncast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "SafeCastOverflowedUintToInt", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json new file mode 100644 index 0000000..ef89440 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json @@ -0,0 +1,34 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentAllowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestedDecrease", + "type": "uint256" + } + ], + "name": "SafeERC20FailedDecreaseAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json new file mode 100644 index 0000000..8fb5c53 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json @@ -0,0 +1,204 @@ +[ + { + "inputs": [ + { + "internalType": "contract IScrollMessenger", + "name": "crossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json new file mode 100644 index 0000000..bf50b2b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json @@ -0,0 +1,222 @@ +[ + { + "inputs": [ + { + "internalType": "contract IScrollMessenger", + "name": "crossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l1OwnerAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "crossDomainMessenger", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Ownership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json new file mode 100644 index 0000000..df53c59 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json @@ -0,0 +1,216 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCoefficientSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "blockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getCurrentL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "chainModuleFixedOverhead", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chainModulePerByteOverhead", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL1FeeCoefficient", + "outputs": [ + { + "internalType": "uint256", + "name": "coefficient", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "dataSize", + "type": "uint256" + } + ], + "name": "getMaxL1Fee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json new file mode 100644 index 0000000..0177ef2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json @@ -0,0 +1,588 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1SenderAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l2CrossDomainMessengerAddr", + "type": "address" + }, + { + "internalType": "bool", + "name": "initialStatus", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "NoDataPresent", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1SenderTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int256", + "name": "status", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "updatedAt", + "type": "uint64" + } + ], + "name": "RoundUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "latestStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "latestTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bool", + "name": "incomingStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "incomingTimestamp", + "type": "uint64" + } + ], + "name": "UpdateIgnored", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Sender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json new file mode 100644 index 0000000..bee27a4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json @@ -0,0 +1,353 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1CrossDomainMessengerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l2UptimeFeedAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "l1MessageQueueAddr", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "L1CrossDomainMessengerAddressZero", + "type": "error" + }, + { + "inputs": [], + "name": "L2UptimeFeedAddrZero", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "GasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L1_MSG_QUEUE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_UPTIME_FEED_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json new file mode 100644 index 0000000..55febb5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json @@ -0,0 +1,21 @@ +[ + { + "inputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "name": "createSender", + "outputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json new file mode 100644 index 0000000..24589f2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json @@ -0,0 +1,18 @@ +[ + { + "inputs": [], + "name": "InvalidShortString", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "str", + "type": "string" + } + ], + "name": "StringTooLong", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json new file mode 100644 index 0000000..803b2a4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json @@ -0,0 +1,445 @@ +[ + { + "inputs": [ + { + "internalType": "bool", + "name": "_isStreamsLookup", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lastBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "counter", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timeToPerform", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isRecovered", + "type": "bool" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "checkBurnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "performBurnAmount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "eventSig", + "type": "bytes32" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + } + ], + "internalType": "struct CheckData", + "name": "", + "type": "tuple" + } + ], + "name": "_checkDataConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "log", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkLog", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isStreamsLookup", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "previousPerformBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParam", + "type": "string" + } + ], + "name": "setFeedParamKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldRetryOnErrorBool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "timeParam", + "type": "string" + } + ], + "name": "setTimeParamKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shouldRetryOnError", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeToPerform", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json new file mode 100644 index 0000000..e7a38bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json @@ -0,0 +1,188 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json new file mode 100644 index 0000000..ecc2ca0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json @@ -0,0 +1,193 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json new file mode 100644 index 0000000..5297f37 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json @@ -0,0 +1,44 @@ +[ + { + "inputs": [], + "name": "DeploymentFailed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "scaAddress", + "type": "address" + } + ], + "name": "ContractCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "abiEncodedOwnerAddress", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "name": "deploySmartContractAccount", + "outputs": [ + { + "internalType": "address", + "name": "scaAddress", + "type": "address" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json new file mode 100644 index 0000000..6f37fb6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json @@ -0,0 +1,171 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "entryPoint", + "type": "address" + }, + { + "internalType": "address", + "name": "factory", + "type": "address" + } + ], + "name": "calculateSmartContractAccountAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "topupThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "topupAmount", + "type": "uint256" + } + ], + "name": "getAbiEncodedDirectRequestData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "endContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "getFullEndTxEncoding", + "outputs": [ + { + "internalType": "bytes", + "name": "encoding", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "userOpHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "scaAddress", + "type": "address" + } + ], + "name": "getFullHashForSigning", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "factory", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "entryPoint", + "type": "address" + } + ], + "name": "getInitCode", + "outputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "entryPoint", + "type": "address" + } + ], + "name": "getSCAInitCodeWithConstructor", + "outputs": [ + { + "internalType": "bytes", + "name": "initCode", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json new file mode 100644 index 0000000..aaabb15 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json @@ -0,0 +1,34 @@ +[ + { + "inputs": [], + "name": "EmptySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "set", + "type": "bytes32[]" + } + ], + "name": "NotASortedSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "subset", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "superset", + "type": "bytes32[]" + } + ], + "name": "NotASubset", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json new file mode 100644 index 0000000..187fe7f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json @@ -0,0 +1,287 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDeposit", + "type": "uint256" + } + ], + "name": "Deposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalStaked", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "unstakeDelaySec", + "type": "uint256" + } + ], + "name": "StakeLocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawTime", + "type": "uint256" + } + ], + "name": "StakeUnlocked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "StakeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + } + ], + "name": "addStake", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "depositTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "deposits", + "outputs": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getDepositInfo", + "outputs": [ + { + "components": [ + { + "internalType": "uint112", + "name": "deposit", + "type": "uint112" + }, + { + "internalType": "bool", + "name": "staked", + "type": "bool" + }, + { + "internalType": "uint112", + "name": "stake", + "type": "uint112" + }, + { + "internalType": "uint32", + "name": "unstakeDelaySec", + "type": "uint32" + }, + { + "internalType": "uint48", + "name": "withdrawTime", + "type": "uint48" + } + ], + "internalType": "struct IStakeManager.DepositInfo", + "name": "info", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unlockStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + } + ], + "name": "withdrawStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "withdrawAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "withdrawAmount", + "type": "uint256" + } + ], + "name": "withdrawTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json new file mode 100644 index 0000000..2605410 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json @@ -0,0 +1,91 @@ +[ + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json new file mode 100644 index 0000000..20b22ce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json @@ -0,0 +1,448 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "_useArbBlock", + "type": "bool" + }, + { + "internalType": "bool", + "name": "_staging", + "type": "bool" + }, + { + "internalType": "bool", + "name": "_verify", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "v0", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "verifiedV0", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "ed", + "type": "bytes" + } + ], + "name": "MercuryPerformEvent", + "type": "event" + }, + { + "inputs": [], + "name": "callbackReturnBool", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feeds", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "interval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "previousPerformBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setCallbackReturnBool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_feeds", + "type": "string[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedParamKey", + "type": "string" + }, + { + "internalType": "string", + "name": "_timeParamKey", + "type": "string" + } + ], + "name": "setParamKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldRevertCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shouldRevertCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "staging", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbBlock", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json new file mode 100644 index 0000000..4793f6a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json @@ -0,0 +1,18 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "StringsInsufficientHexLength", + "type": "error" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json new file mode 100644 index 0000000..1c262bc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json @@ -0,0 +1,843 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json new file mode 100644 index 0000000..af511ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json @@ -0,0 +1,466 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "signerPublicKey", + "type": "address" + } + ], + "internalType": "struct TermsOfServiceAllowListConfig", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "initialAllowedSenders", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "initialBlockedSenders", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidUsage", + "type": "error" + }, + { + "inputs": [], + "name": "RecipientIsBlocked", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "BlockedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "signerPublicKey", + "type": "address" + } + ], + "indexed": false, + "internalType": "struct TermsOfServiceAllowListConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "UnblockedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "acceptor", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + } + ], + "name": "acceptTermsOfService", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "blockSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllAllowedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedSendersCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "allowedSenderIdxStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "allowedSenderIdxEnd", + "type": "uint64" + } + ], + "name": "getAllowedSendersInRange", + "outputs": [ + { + "internalType": "address[]", + "name": "allowedSenders", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockedSendersCount", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "blockedSenderIdxStart", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "blockedSenderIdxEnd", + "type": "uint64" + } + ], + "name": "getBlockedSendersInRange", + "outputs": [ + { + "internalType": "address[]", + "name": "blockedSenders", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "signerPublicKey", + "type": "address" + } + ], + "internalType": "struct TermsOfServiceAllowListConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "acceptor", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "getMessage", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isBlockedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "unblockSender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "address", + "name": "signerPublicKey", + "type": "address" + } + ], + "internalType": "struct TermsOfServiceAllowListConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "updateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json new file mode 100644 index 0000000..04a0302 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json @@ -0,0 +1,235 @@ +[ + { + "inputs": [ + { + "internalType": "address[]", + "name": "whitelist", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidRecentBlockhash", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrustedBlockhashes", + "type": "error" + }, + { + "inputs": [], + "name": "NotInWhitelist", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getBlockhash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_whitelist", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "s_whitelistStatus", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "whitelist", + "type": "address[]" + } + ], + "name": "setWhitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "storeEarliest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "blockNums", + "type": "uint256[]" + }, + { + "internalType": "bytes32[]", + "name": "blockhashes", + "type": "bytes32[]" + }, + { + "internalType": "uint256", + "name": "recentBlockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "recentBlockhash", + "type": "bytes32" + } + ], + "name": "storeTrusted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "header", + "type": "bytes" + } + ], + "name": "storeVerifyHeader", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json new file mode 100644 index 0000000..99725a5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json new file mode 100644 index 0000000..a680f22 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json @@ -0,0 +1,261 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "registryAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "callable", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "executedata", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_autoFundLink", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_isEligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_keeperRegistry", + "outputs": [ + { + "internalType": "contract AutomationRegistryBaseInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_shouldCancel", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_upkeepId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "value", + "type": "uint96" + } + ], + "name": "setAutoFundLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setIsEligible", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldCancel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setUpkeepId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json new file mode 100644 index 0000000..d636bfb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json @@ -0,0 +1,524 @@ +[ + { + "inputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "linkToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "maxBatchSize", + "type": "uint8" + }, + { + "internalType": "uint24", + "name": "minPercentage", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "targetPercentage", + "type": "uint24" + }, + { + "internalType": "uint96", + "name": "maxTopUpAmount", + "type": "uint96" + } + ], + "internalType": "struct UpkeepBalanceMonitor.Config", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidConfig", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTopUpData", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyForwarderOrOwner", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "maxBatchSize", + "type": "uint8" + }, + { + "internalType": "uint24", + "name": "minPercentage", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "targetPercentage", + "type": "uint24" + }, + { + "internalType": "uint96", + "name": "maxTopUpAmount", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct UpkeepBalanceMonitor.Config", + "name": "config", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "forwarderAddress", + "type": "address" + } + ], + "name": "ForwarderSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "registryAddress", + "type": "address" + } + ], + "name": "WatchListSet", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "maxBatchSize", + "type": "uint8" + }, + { + "internalType": "uint24", + "name": "minPercentage", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "targetPercentage", + "type": "uint24" + }, + { + "internalType": "uint96", + "name": "maxTopUpAmount", + "type": "uint96" + } + ], + "internalType": "struct UpkeepBalanceMonitor.Config", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedUpkeeps", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "", + "type": "uint96[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "uint256[][]", + "name": "", + "type": "uint256[][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint8", + "name": "maxBatchSize", + "type": "uint8" + }, + { + "internalType": "uint24", + "name": "minPercentage", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "targetPercentage", + "type": "uint24" + }, + { + "internalType": "uint96", + "name": "maxTopUpAmount", + "type": "uint96" + } + ], + "internalType": "struct UpkeepBalanceMonitor.Config", + "name": "config", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarderAddress", + "type": "address" + } + ], + "name": "setForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "registryAddress", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "watchlist", + "type": "uint256[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIDs", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "registryAddresses", + "type": "address[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmounts", + "type": "uint96[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json new file mode 100644 index 0000000..559ad80 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json @@ -0,0 +1,201 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialTimestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lastTimestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "counter", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "interval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "previousPerformBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setSpread", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json new file mode 100644 index 0000000..9f86cff --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json @@ -0,0 +1,427 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "InvalidCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialTimestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lastTimestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "counter", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [], + "name": "checkGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "counter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "data", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dataCopy", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "forwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "interval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "previousPerformBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_checkGasToBurn", + "type": "uint256" + } + ], + "name": "setCheckGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "setData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_forwarder", + "type": "address" + } + ], + "name": "setForwarder", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_performGasToBurn", + "type": "uint256" + } + ], + "name": "setPerformGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setSpread", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_trickSimulation", + "type": "bool" + } + ], + "name": "setTrickSimulation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_useMoreCheckGas", + "type": "bool" + } + ], + "name": "setUseMoreCheckGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_useMorePerformData", + "type": "bool" + } + ], + "name": "setUseMorePerformData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_useMorePerformGas", + "type": "bool" + } + ], + "name": "setUseMorePerformGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trickSimulation", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useMoreCheckGas", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useMorePerformData", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useMorePerformGas", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json new file mode 100644 index 0000000..18ad60e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json @@ -0,0 +1,239 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "upkeepData", + "type": "bytes" + } + ], + "name": "UpkeepPerformedWith", + "type": "event" + }, + { + "inputs": [], + "name": "canCheck", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "canPerform", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkRevertReason", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "callable", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "executedata", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "performData", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setCanCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setCanPerform", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setCheckGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "value", + "type": "string" + } + ], + "name": "setCheckRevertReason", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "setPerformData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "value", + "type": "bool" + } + ], + "name": "setShouldRevertCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shouldRevertCheck", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json new file mode 100644 index 0000000..a6d3e16 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json @@ -0,0 +1,266 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_testRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_averageEligibilityCadence", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "eligible", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialCall", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nextEligible", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "PerformingUpkeep", + "type": "event" + }, + { + "inputs": [], + "name": "averageEligibilityCadence", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkEligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "checkGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCountPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialCall", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextEligible", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "performGasToBurn", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setCheckGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformGasToBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newTestRange", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newAverageEligibilityCadence", + "type": "uint256" + } + ], + "name": "setSpread", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "testRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json new file mode 100644 index 0000000..dd3c3e3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json @@ -0,0 +1,44 @@ +[ + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "callable", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "executedata", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json new file mode 100644 index 0000000..977aa03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json @@ -0,0 +1,49 @@ +[ + { + "inputs": [], + "name": "InvalidTranscoding", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "enum UpkeepFormat", + "name": "toVersion", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json new file mode 100644 index 0000000..18259c1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json @@ -0,0 +1,49 @@ +[ + { + "inputs": [], + "name": "InvalidTranscoding", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "enum UpkeepFormat", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json new file mode 100644 index 0000000..7f6f286 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json @@ -0,0 +1,49 @@ +[ + { + "inputs": [], + "name": "InvalidTranscoding", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json new file mode 100644 index 0000000..2f7d062 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json @@ -0,0 +1,49 @@ +[ + { + "inputs": [], + "name": "InvalidTranscoding", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "toVersion", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json new file mode 100644 index 0000000..83cadad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json @@ -0,0 +1,31 @@ +[ + { + "inputs": [ + { + "internalType": "enum UpkeepFormat", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "enum UpkeepFormat", + "name": "toVersion", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json new file mode 100644 index 0000000..a58a7ca --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json @@ -0,0 +1,31 @@ +[ + { + "inputs": [ + { + "internalType": "uint8", + "name": "fromVersion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "toVersion", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "transcodeUpkeeps", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json new file mode 100644 index 0000000..1ad6a94 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json @@ -0,0 +1,86 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "doRequestRandomness", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "randomnessOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "name": "rawFulfillRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "requestId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json new file mode 100644 index 0000000..2f5c323 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "name": "rawFulfillRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json new file mode 100644 index 0000000..413f472 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json @@ -0,0 +1,36 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json new file mode 100644 index 0000000..991702f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json @@ -0,0 +1,172 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json new file mode 100644 index 0000000..d135614 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json @@ -0,0 +1,49 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json new file mode 100644 index 0000000..797e98d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json @@ -0,0 +1,188 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minReqConfs", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json new file mode 100644 index 0000000..4a35c51 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json @@ -0,0 +1,336 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json new file mode 100644 index 0000000..ba7515c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json @@ -0,0 +1,229 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "minReqConfs", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json new file mode 100644 index 0000000..0288525 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json @@ -0,0 +1,229 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minReqConfs", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json new file mode 100644 index 0000000..7cde48d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json @@ -0,0 +1,103 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "RandomnessRequest", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumerContract", + "type": "address" + } + ], + "name": "callBackWithRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json new file mode 100644 index 0000000..d010a7f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json @@ -0,0 +1,1463 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + }, + { + "internalType": "address", + "name": "linkEthFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "want", + "type": "uint256" + } + ], + "name": "InsufficientGasForConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct VRFCoordinatorTestV2.FeeConfig", + "name": "feeConfig", + "type": "tuple" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oracle", + "type": "address" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "oracle", + "type": "address" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "internalType": "struct VRFCoordinatorTestV2.RequestCommitment", + "name": "rc", + "type": "tuple" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "getCommitment", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentSubId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeConfig", + "outputs": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + } + ], + "name": "getFeeTier", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRequestConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "oracleWithdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "internalType": "struct VRFCoordinatorTestV2.FeeConfig", + "name": "feeConfig", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json new file mode 100644 index 0000000..a858f4e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json @@ -0,0 +1,1750 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFOld.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json new file mode 100644 index 0000000..bc6eb08 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json @@ -0,0 +1,100 @@ +[ + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "internalType": "struct VRFTypes.RequestCommitment", + "name": "rc", + "type": "tuple" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json new file mode 100644 index 0000000..1b16915 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json @@ -0,0 +1,215 @@ +[ + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getRequestConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json new file mode 100644 index 0000000..74c606b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json @@ -0,0 +1,765 @@ +[ + { + "inputs": [ + { + "internalType": "uint96", + "name": "_baseFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "_gasPriceLink", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRandomWords", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "ConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "ConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_FEE", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GAS_PRICE_LINK", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "consumerIsAdded", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_words", + "type": "uint256[]" + } + ], + "name": "fulfillRandomWordsWithOverride", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "uint96", + "name": "_amount", + "type": "uint96" + } + ], + "name": "fundSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getFeeConfig", + "outputs": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getRequestConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "_minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json new file mode 100644 index 0000000..6bb444b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json @@ -0,0 +1,1778 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "transferredValue", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "expectedValue", + "type": "uint96" + } + ], + "name": "InvalidNativeBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "requestVersion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "expectedVersion", + "type": "uint8" + } + ], + "name": "InvalidVersion", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "SubscriptionIDCollisionFound", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRequestConfig", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "migrationVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedData", + "type": "bytes" + } + ], + "name": "onMigration", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json new file mode 100644 index 0000000..0c76d73 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json @@ -0,0 +1,329 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "prevCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "transferredValue", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "expectedValue", + "type": "uint96" + } + ], + "name": "InvalidNativeBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "requestVersion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "expectedVersion", + "type": "uint8" + } + ], + "name": "InvalidVersion", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "previousCoordinator", + "type": "address" + } + ], + "name": "MustBePreviousCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "SubscriptionIDCollisionFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestID", + "type": "uint256" + } + ], + "name": "generateFakeRandomness", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "linkBalance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedData", + "type": "bytes" + } + ], + "name": "onMigration", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_link", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_prevCoordinator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestConsumerMapping", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_subscriptions", + "outputs": [ + { + "internalType": "uint96", + "name": "linkBalance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalLinkBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json new file mode 100644 index 0000000..cc81e63 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json @@ -0,0 +1,78 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkEthFeed", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasAfterPaymentCalculation", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPM", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "weiPerUnitGas", + "type": "uint256" + } + ], + "name": "calculatePaymentAmountTest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getPaymentAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json new file mode 100644 index 0000000..60f7254 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json @@ -0,0 +1,1763 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json new file mode 100644 index 0000000..a409893 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json @@ -0,0 +1,1180 @@ +[ + { + "inputs": [ + { + "internalType": "uint96", + "name": "_baseFee", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "_gasPrice", + "type": "uint96" + }, + { + "internalType": "int256", + "name": "_weiPerUnitLink", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRandomWords", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequest", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotImplemented", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "consumerIsAdded", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "_words", + "type": "uint256[]" + } + ], + "name": "fulfillRandomWordsWithOverride", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "fundSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_base_fee", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_gas_price", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_wei_per_unit_link", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "_req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json new file mode 100644 index 0000000..60f7254 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json @@ -0,0 +1,1763 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json new file mode 100644 index 0000000..30c3d71 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json @@ -0,0 +1,1848 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "blockhashStore", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "internalBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "externalBalance", + "type": "uint256" + } + ], + "name": "BalanceInvariantViolated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "BlockhashNotInStore", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorAlreadyRegistered", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToSendNative", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "GasLimitTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxGas", + "type": "uint256" + } + ], + "name": "GasPriceExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectCommitment", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCalldata", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "InvalidConsumer", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExtraArgsTag", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCalculationMode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "linkWei", + "type": "int256" + } + ], + "name": "InvalidLinkWeiPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "have", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "min", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "max", + "type": "uint16" + } + ], + "name": "InvalidRequestConfirmations", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSubscription", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "LinkNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "have", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "max", + "type": "uint32" + } + ], + "name": "MsgDataTooBig", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposedOwner", + "type": "address" + } + ], + "name": "MustBeRequestedOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "MustBeSubOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NoCorrespondingRequest", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "NoSuchProvingKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "have", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "want", + "type": "uint32" + } + ], + "name": "NumWordsTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [], + "name": "PaymentTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "PendingRequestExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "ProvingKeyAlreadyRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "Reentrant", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyConsumers", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "CoordinatorRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCalculationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "L1GasFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newCoordinator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "MigrationCompleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeFundsRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyDeregistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "ProvingKeyRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountLink", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountNative", + "type": "uint256" + } + ], + "name": "SubscriptionCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "SubscriptionConsumerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "SubscriptionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFunded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldNativeBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newNativeBalance", + "type": "uint256" + } + ], + "name": "SubscriptionFundedWithNative", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "SubscriptionOwnerTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "BLOCKHASH_STORE", + "outputs": [ + { + "internalType": "contract BlockhashStoreInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_NATIVE_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_CONSUMERS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_WORDS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REQUEST_CONFIRMATIONS", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "acceptSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "addConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "cancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscription", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "deregisterMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFTypes.RequestCommitmentV2Plus", + "name": "rc", + "type": "tuple" + }, + { + "internalType": "bool", + "name": "onlyPremium", + "type": "bool" + } + ], + "name": "fulfillRandomWords", + "outputs": [ + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "fundSubscriptionWithNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveSubscriptionIds", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "getSubscription", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeBalance", + "type": "uint96" + }, + { + "internalType": "uint64", + "name": "reqCount", + "type": "uint64" + }, + { + "internalType": "address", + "name": "subOwner", + "type": "address" + }, + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicKey", + "type": "uint256[2]" + } + ], + "name": "hashOfKey", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newCoordinator", + "type": "address" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "pendingRequestExists", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + } + ], + "name": "recoverNativeFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "registerMigratableCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "removeConsumer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "internalType": "struct VRFV2PlusClient.RandomWordsRequest", + "name": "req", + "type": "tuple" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "requestSubscriptionOwnerTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_config", + "outputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "reentrancyLock", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_currentSubNonce", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fallbackWeiPerUnitLink", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCalculationMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCoefficient", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_provingKeyHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "s_provingKeys", + "outputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "maxGas", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestCommitments", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_totalNativeBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "nativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "linkPremiumPercentage", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkNativeFeed", + "type": "address" + } + ], + "name": "setLINKAndLINKNativeFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json new file mode 100644 index 0000000..eb693d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json @@ -0,0 +1,130 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json new file mode 100644 index 0000000..82084df --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json @@ -0,0 +1,190 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json new file mode 100644 index 0000000..babe0d6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_price", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "name": "rawFulfillRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json new file mode 100644 index 0000000..5efdfc9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json @@ -0,0 +1,164 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "RandomWordsFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsRequested", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "outputSeed", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "payment", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "emitRandomWordsFulfilled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "preSeed", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "emitRandomWordsRequested", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json new file mode 100644 index 0000000..63f3188 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json @@ -0,0 +1,155 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json new file mode 100644 index 0000000..fbd1f4f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json @@ -0,0 +1,278 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json new file mode 100644 index 0000000..760d0fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json @@ -0,0 +1,150 @@ +[ + { + "inputs": [ + { + "internalType": "int256", + "name": "_answer", + "type": "int256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "answer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "ans", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_blockTimestampDeduction", + "type": "uint256" + } + ], + "name": "setBlockTimestampDeduction", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json new file mode 100644 index 0000000..3ebf34b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json @@ -0,0 +1,455 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "EmptySendersList", + "type": "error" + }, + { + "inputs": [], + "name": "NotAllowedToSetSenders", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedSender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "changedBy", + "type": "address" + } + ], + "name": "AuthorizedSendersChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RandomWordsForced", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "acceptVRFOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "deregisterProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRFTypes.Proof", + "name": "proof", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint64", + "name": "blockNum", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "internalType": "struct VRFTypes.RequestCommitment", + "name": "rc", + "type": "tuple" + } + ], + "name": "fulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizedSenders", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVRFCoordinator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isAuthorizedSender", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + } + ], + "name": "ownerCancelSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "recoverFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "publicProvingKey", + "type": "uint256[2]" + } + ], + "name": "registerProvingKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + } + ], + "name": "setAuthorizedSenders", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "minimumRequestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "maxGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "gasAfterPaymentCalculation", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier1", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier2", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier3", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier4", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPMTier5", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "reqsForTier2", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier3", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier4", + "type": "uint24" + }, + { + "internalType": "uint24", + "name": "reqsForTier5", + "type": "uint24" + } + ], + "internalType": "struct FeeConfig", + "name": "feeConfig", + "type": "tuple" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferVRFOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json new file mode 100644 index 0000000..9254332 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json @@ -0,0 +1,90 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OnlyCallableFromLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "requestId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "randomness", + "type": "uint256" + } + ], + "name": "rawFulfillRandomness", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_randomnessOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json new file mode 100644 index 0000000..53bb38b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json @@ -0,0 +1,60 @@ +[ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_vRFInputSeed", + "type": "uint256" + } + ], + "name": "makeRequestId_", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "_userSeed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_requester", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "makeVRFInputSeed_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json new file mode 100644 index 0000000..5a4eb85 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json @@ -0,0 +1,208 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "fundAndRequestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestConfig", + "outputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subscribe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "unsubscribe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json new file mode 100644 index 0000000..d39bb01 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json @@ -0,0 +1,606 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duplicate", + "type": "uint64" + } + ], + "name": "DuplicateSubcriptionId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "LinkTokenAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "lastId", + "type": "uint256" + } + ], + "name": "OutOfGas", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VRFCoordinatorV2AddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscriptionInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalanceJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpAmountJuels", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedSubscriptions", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_keeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_minWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_watchList", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "linkTokenAddress", + "type": "address" + } + ], + "name": "setLinkTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "setVRFCoordinatorV2Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64[]", + "name": "subscriptionIds", + "type": "uint64[]" + }, + { + "internalType": "uint96[]", + "name": "minBalancesJuels", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmountsJuels", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64[]", + "name": "needsFunding", + "type": "uint64[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json new file mode 100644 index 0000000..35a83f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json @@ -0,0 +1,624 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "linkTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "minWaitPeriodSeconds", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "duplicate", + "type": "uint64" + } + ], + "name": "DuplicateSubcriptionId", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidWatchList", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyKeeperRegistry", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amountWithdrawn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "KeeperRegistryAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "LinkTokenAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinWaitPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinWaitPeriod", + "type": "uint256" + } + ], + "name": "MinWaitPeriodUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "lastId", + "type": "uint256" + } + ], + "name": "OutOfGas", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "TopUpFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "TopUpSucceeded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "VRFCoordinatorV2AddressUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subscriptionId", + "type": "uint64" + } + ], + "name": "getSubscriptionInfo", + "outputs": [ + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "uint96", + "name": "minBalanceJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "topUpAmountJuels", + "type": "uint96" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getUnderfundedSubscriptions", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWatchList", + "outputs": [ + { + "internalType": "uint64[]", + "name": "", + "type": "uint64[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_keeperRegistryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_minWaitPeriodSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_watchList", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeperRegistryAddress", + "type": "address" + } + ], + "name": "setKeeperRegistryAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "target", + "type": "uint64" + }, + { + "internalType": "uint56", + "name": "lastTopUpTimestamp", + "type": "uint56" + } + ], + "name": "setLastTopUpXXXTestOnly", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "linkTokenAddress", + "type": "address" + } + ], + "name": "setLinkTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setMinWaitPeriodSeconds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "coordinatorAddress", + "type": "address" + } + ], + "name": "setVRFCoordinatorV2Address", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64[]", + "name": "subscriptionIds", + "type": "uint64[]" + }, + { + "internalType": "uint96[]", + "name": "minBalancesJuels", + "type": "uint96[]" + }, + { + "internalType": "uint96[]", + "name": "topUpAmountsJuels", + "type": "uint96[]" + } + ], + "name": "setWatchList", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64[]", + "name": "needsFunding", + "type": "uint64[]" + } + ], + "name": "topUp", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address payable", + "name": "payee", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json new file mode 100644 index 0000000..0c2fe93 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json @@ -0,0 +1,474 @@ +[ + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "p1", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "p2", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "invZ", + "type": "uint256" + } + ], + "name": "affineECAdd_", + "outputs": [ + { + "internalType": "uint256[2]", + "name": "", + "type": "uint256[2]" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "base", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exponent", + "type": "uint256" + } + ], + "name": "bigModExp_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "x", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "scalar", + "type": "uint256" + }, + { + "internalType": "uint256[2]", + "name": "q", + "type": "uint256[2]" + } + ], + "name": "ecmulVerify_", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "b", + "type": "bytes" + } + ], + "name": "fieldHash_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "name": "hashToCurve_", + "outputs": [ + { + "internalType": "uint256[2]", + "name": "", + "type": "uint256[2]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "p", + "type": "uint256[2]" + } + ], + "name": "isOnCurve_", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256[2]", + "name": "p1", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "cp1Witness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256[2]", + "name": "p2", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sp2Witness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "name": "linearCombination_", + "outputs": [ + { + "internalType": "uint256[2]", + "name": "", + "type": "uint256[2]" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "px", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "py", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qx", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "qy", + "type": "uint256" + } + ], + "name": "projectiveECAdd_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "internalType": "struct VRF.Proof", + "name": "proof", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + } + ], + "name": "randomValueFromVRFProof_", + "outputs": [ + { + "internalType": "uint256", + "name": "output", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "hash", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "v", + "type": "uint256[2]" + } + ], + "name": "scalarFromCurvePoints_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "name": "squareRoot_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256[2]", + "name": "p", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "address", + "name": "lcWitness", + "type": "address" + } + ], + "name": "verifyLinearCombinationWithGenerator_", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[2]", + "name": "pk", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "gamma", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "s", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seed", + "type": "uint256" + }, + { + "internalType": "address", + "name": "uWitness", + "type": "address" + }, + { + "internalType": "uint256[2]", + "name": "cGammaWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256[2]", + "name": "sHashWitness", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "zInv", + "type": "uint256" + } + ], + "name": "verifyVRFProof_", + "outputs": [], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "x", + "type": "uint256" + } + ], + "name": "ySquared_", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json new file mode 100644 index 0000000..70ec704 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json @@ -0,0 +1,370 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SubscriptionCreatedFundedAndConsumerAdded", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "_subTopUpAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "name": "requestRandomWordsWithForceFulfill", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageFulfillmentInMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "_subId", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json new file mode 100644 index 0000000..c4b3fa3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json @@ -0,0 +1,406 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "_link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address", + "name": "consumer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SubscriptionCreatedFundedAndConsumerAdded", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract VRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINKTOKEN", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "_subTopUpAmount", + "type": "uint256" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageFulfillmentInMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "subId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json new file mode 100644 index 0000000..34569b2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "EXTRA_ARGS_V1_TAG", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json new file mode 100644 index 0000000..250215d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json @@ -0,0 +1,392 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "createSubscriptionAndFundNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "idx", + "type": "uint256" + } + ], + "name": "getRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "randomWord", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_recentRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinatorApiV1", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + } + ], + "name": "setSubId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "topUpSubscriptionNative", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json new file mode 100644 index 0000000..e923907 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json @@ -0,0 +1,258 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json new file mode 100644 index 0000000..6301bab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json @@ -0,0 +1,476 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quantity", + "type": "uint256" + } + ], + "name": "getRequestBlockTimes", + "outputs": [ + { + "internalType": "uint32[]", + "name": "", + "type": "uint32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "_nativePayment", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageResponseTimeInBlocksMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageResponseTimeInSecondsMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestResponseTimeInBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestResponseTimeInSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestBlockTimes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestResponseTimeInBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestResponseTimeInSeconds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json new file mode 100644 index 0000000..87eabea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json new file mode 100644 index 0000000..a91774a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json @@ -0,0 +1,324 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "minReqConfs", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json new file mode 100644 index 0000000..4051083 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json @@ -0,0 +1,354 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "fundAndRequestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "requestRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestConfig", + "outputs": [ + { + "internalType": "uint256", + "name": "subId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "nativePayment", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "subscribe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "unsubscribe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json new file mode 100644 index 0000000..f830554 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json @@ -0,0 +1,954 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "_coordinator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "expectedMinimumLength", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "actualLength", + "type": "uint16" + } + ], + "name": "IncorrectExtraArgsLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [], + "name": "LINKPaymentInRequestRandomWordsInNative", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "NativePaymentInOnTokenTransfer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "SubscriptionIdMissing", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Disabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Enabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "size", + "type": "uint32" + } + ], + "name": "FulfillmentTxSizeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "WrapperFulfillmentFailed", + "type": "event" + }, + { + "inputs": [], + "name": "SUBSCRIPTION_ID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isLinkMode", + "type": "bool" + } + ], + "name": "checkPaymentMode", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "wrapperNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "wrapperLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "link", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkNativeFeed", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "name": "requestRandomWordsInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_callbacks", + "outputs": [ + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "requestGasPrice", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_configured", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_disabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fulfillmentTxSizeBytes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "_coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_maxNumWords", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "_stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "_fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_size", + "type": "uint32" + } + ], + "name": "setFulfillmentTxSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json new file mode 100644 index 0000000..f5a54bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json @@ -0,0 +1,75 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyVRFWrapperCanFulfill", + "type": "error" + }, + { + "inputs": [], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_vrfV2PlusWrapper", + "outputs": [ + { + "internalType": "contract IVRFV2PlusWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json new file mode 100644 index 0000000..a8782ed --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json @@ -0,0 +1,366 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyVRFWrapperCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "Received", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "WrappedRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid", + "type": "uint256" + } + ], + "name": "WrapperRequestMade", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_vrfV2PlusWrapper", + "outputs": [ + { + "internalType": "contract IVRFV2PlusWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequestNative", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "native", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json new file mode 100644 index 0000000..3ba6702 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json @@ -0,0 +1,513 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfV2PlusWrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyVRFWrapperCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "WrappedRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid", + "type": "uint256" + } + ], + "name": "WrapperRequestMade", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "quantity", + "type": "uint256" + } + ], + "name": "getRequestBlockTimes", + "outputs": [ + { + "internalType": "uint32[]", + "name": "", + "type": "uint32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_vrfV2PlusWrapper", + "outputs": [ + { + "internalType": "contract IVRFV2PlusWrapper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "makeRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "makeRequestsNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageFulfillmentInMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requestBlockTimes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "native", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json new file mode 100644 index 0000000..f830554 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json @@ -0,0 +1,954 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "_coordinator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "expectedMinimumLength", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "actualLength", + "type": "uint16" + } + ], + "name": "IncorrectExtraArgsLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [], + "name": "LINKPaymentInRequestRandomWordsInNative", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "NativePaymentInOnTokenTransfer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "SubscriptionIdMissing", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Disabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Enabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "size", + "type": "uint32" + } + ], + "name": "FulfillmentTxSizeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "WrapperFulfillmentFailed", + "type": "event" + }, + { + "inputs": [], + "name": "SUBSCRIPTION_ID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isLinkMode", + "type": "bool" + } + ], + "name": "checkPaymentMode", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "wrapperNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "wrapperLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "link", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkNativeFeed", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "name": "requestRandomWordsInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_callbacks", + "outputs": [ + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "requestGasPrice", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_configured", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_disabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fulfillmentTxSizeBytes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "_coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_maxNumWords", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "_stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "_fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_size", + "type": "uint32" + } + ], + "name": "setFulfillmentTxSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json new file mode 100644 index 0000000..83a8c30 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json @@ -0,0 +1,1050 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_linkNativeFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "_coordinator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_subId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "FailedToTransferLink", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "expectedMinimumLength", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "actualLength", + "type": "uint16" + } + ], + "name": "IncorrectExtraArgsLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCalculationMode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "InvalidL1FeeCoefficient", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "premiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "max", + "type": "uint8" + } + ], + "name": "InvalidPremiumPercentage", + "type": "error" + }, + { + "inputs": [], + "name": "LINKPaymentInRequestRandomWordsInNative", + "type": "error" + }, + { + "inputs": [], + "name": "LinkAlreadySet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "flatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeNativePPM", + "type": "uint32" + } + ], + "name": "LinkDiscountTooHigh", + "type": "error" + }, + { + "inputs": [], + "name": "NativePaymentInOnTokenTransfer", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "coordinator", + "type": "address" + } + ], + "name": "OnlyOwnerOrCoordinator", + "type": "error" + }, + { + "inputs": [], + "name": "SubscriptionIdMissing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + } + ], + "name": "UnsupportedL1FeeCalculationMode", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "name": "CoordinatorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Disabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "Enabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + } + ], + "name": "FallbackWeiPerUnitLinkUsed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "size", + "type": "uint32" + } + ], + "name": "FulfillmentTxSizeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "L1FeeCalculationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NativeWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "WrapperFulfillmentFailed", + "type": "event" + }, + { + "inputs": [], + "name": "SUBSCRIPTION_ID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "calculateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "isLinkMode", + "type": "bool" + } + ], + "name": "checkPaymentMode", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPriceNative", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "wrapperNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "wrapperLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "link", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkNativeFeed", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "extraArgs", + "type": "bytes" + } + ], + "name": "requestRandomWordsInNative", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_callbacks", + "outputs": [ + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "requestGasPrice", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_configured", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_disabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fulfillmentTxSizeBytes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCalculationMode", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_l1FeeCoefficient", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_vrfCoordinator", + "outputs": [ + { + "internalType": "contract IVRFCoordinatorV2Plus", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadNative", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverheadLink", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_coordinatorGasOverheadPerWord", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "_coordinatorNativePremiumPercentage", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "_coordinatorLinkPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_maxNumWords", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "_stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "int256", + "name": "_fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeNativePPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_fulfillmentFlatFeeLinkDiscountPPM", + "type": "uint32" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_vrfCoordinator", + "type": "address" + } + ], + "name": "setCoordinator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_size", + "type": "uint32" + } + ], + "name": "setFulfillmentTxSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "mode", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "coefficient", + "type": "uint8" + } + ], + "name": "setL1FeeCalculation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + } + ], + "name": "withdrawNative", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json new file mode 100644 index 0000000..7793e0d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json @@ -0,0 +1,151 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ITransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json new file mode 100644 index 0000000..797e98d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json @@ -0,0 +1,188 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + }, + { + "internalType": "address", + "name": "link", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "createSubscriptionAndFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint16", + "name": "minReqConfs", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "requestRandomness", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_gasAvailable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_randomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_subId", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "topUpSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "consumers", + "type": "address[]" + } + ], + "name": "updateSubscription", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json new file mode 100644 index 0000000..27423cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json @@ -0,0 +1,76 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json new file mode 100644 index 0000000..893edb6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json @@ -0,0 +1,495 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_linkEthFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "_coordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "consumer", + "type": "address" + } + ], + "name": "WrapperFulfillmentFailed", + "type": "event" + }, + { + "inputs": [], + "name": "COORDINATOR", + "outputs": [ + { + "internalType": "contract ExtendedVRFCoordinatorV2Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_ETH_FEED", + "outputs": [ + { + "internalType": "contract AggregatorV3Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUBSCRIPTION_ID", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enable", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "internalType": "int256", + "name": "fallbackWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint32", + "name": "stalenessSeconds", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "fulfillmentFlatFeeLinkPPM", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "coordinatorGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "wrapperPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "maxNumWords", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_callbacks", + "outputs": [ + { + "internalType": "address", + "name": "callbackAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "requestGasPrice", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "requestWeiPerUnitLink", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "juelsPaid", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_configured", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_disabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fulfillmentTxSizeBytes", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_wrapperGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_coordinatorGasOverhead", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "_wrapperPremiumPercentage", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "_keyHash", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_maxNumWords", + "type": "uint8" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "size", + "type": "uint32" + } + ], + "name": "setFulfillmentTxSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json new file mode 100644 index 0000000..797e6f6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json @@ -0,0 +1,20 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json new file mode 100644 index 0000000..1c7a980 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json @@ -0,0 +1,246 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "WrappedRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid", + "type": "uint256" + } + ], + "name": "WrapperRequestMade", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json new file mode 100644 index 0000000..6618881 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json @@ -0,0 +1,58 @@ +[ + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + } + ], + "name": "calculateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "_requestGasPriceWei", + "type": "uint256" + } + ], + "name": "estimateRequestPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json new file mode 100644 index 0000000..ec71ede --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json @@ -0,0 +1,387 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "payment", + "type": "uint256" + } + ], + "name": "WrappedRequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paid", + "type": "uint256" + } + ], + "name": "WrapperRequestMade", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "i_vrfV2Wrapper", + "outputs": [ + { + "internalType": "contract VRFV2WrapperInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestCount", + "type": "uint16" + } + ], + "name": "makeRequests", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "s_averageFulfillmentInMillions", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_fastestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_requestCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "uint256", + "name": "paid", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "requestTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestBlockNumber", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fulfilmentBlockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_responseCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_slowestFulfillment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json new file mode 100644 index 0000000..b4333ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json @@ -0,0 +1,136 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json new file mode 100644 index 0000000..b4333ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json @@ -0,0 +1,136 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequest", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json new file mode 100644 index 0000000..c2dee64 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json @@ -0,0 +1,112 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_link", + "type": "address" + }, + { + "internalType": "address", + "name": "_vrfV2Wrapper", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "_requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "_numWords", + "type": "uint32" + } + ], + "name": "makeRequest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json new file mode 100644 index 0000000..698d6d0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json @@ -0,0 +1,275 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "vrfCoordinator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "have", + "type": "address" + }, + { + "internalType": "address", + "name": "want", + "type": "address" + } + ], + "name": "OnlyCoordinatorCanFulfill", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "RequestFulfilled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + } + ], + "name": "RequestSent", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_requestId", + "type": "uint256" + } + ], + "name": "getRequestStatus", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRequestId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "randomWords", + "type": "uint256[]" + } + ], + "name": "rawFulfillRandomWords", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "requestIds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "subId", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "callbackGasLimit", + "type": "uint32" + }, + { + "internalType": "uint16", + "name": "requestConfirmations", + "type": "uint16" + }, + { + "internalType": "uint32", + "name": "numWords", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "keyHash", + "type": "bytes32" + } + ], + "name": "requestRandomWords", + "outputs": [ + { + "internalType": "uint256", + "name": "requestId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "s_requests", + "outputs": [ + { + "internalType": "bool", + "name": "fulfilled", + "type": "bool" + }, + { + "internalType": "bool", + "name": "exists", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json new file mode 100644 index 0000000..e570c0e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json @@ -0,0 +1,323 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "aggregator", + "type": "address" + }, + { + "internalType": "contract AggregatorValidatorInterface", + "name": "validator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "aggregator", + "type": "address" + } + ], + "name": "AggregatorProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previous", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "current", + "type": "address" + } + ], + "name": "AggregatorUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proposed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "ProposedAggregatorValidateCall", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract AggregatorValidatorInterface", + "name": "validator", + "type": "address" + } + ], + "name": "ValidatorProposed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract AggregatorValidatorInterface", + "name": "previous", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract AggregatorValidatorInterface", + "name": "current", + "type": "address" + } + ], + "name": "ValidatorUpgraded", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAggregators", + "outputs": [ + { + "internalType": "address", + "name": "current", + "type": "address" + }, + { + "internalType": "bool", + "name": "hasProposal", + "type": "bool" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidators", + "outputs": [ + { + "internalType": "contract AggregatorValidatorInterface", + "name": "current", + "type": "address" + }, + { + "internalType": "bool", + "name": "hasProposal", + "type": "bool" + }, + { + "internalType": "contract AggregatorValidatorInterface", + "name": "proposed", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "proposeNewAggregator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AggregatorValidatorInterface", + "name": "proposed", + "type": "address" + } + ], + "name": "proposeNewValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "upgradeAggregator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upgradeValidator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "previousRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "previousAnswer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "currentRoundId", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json new file mode 100644 index 0000000..df73015 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json @@ -0,0 +1,1524 @@ +[ + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmittedAgain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "UpkeepTopUp", + "type": "event" + }, + { + "inputs": [], + "name": "BUCKET_SIZE", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addLinkAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchCancelUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "batchPreparingUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + } + ], + "name": "batchPreparingUpkeepsSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "number", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "checkGasToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "performGasToBurn", + "type": "uint256" + } + ], + "name": "batchRegisterUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "batchSendLogs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint32", + "name": "interval", + "type": "uint32" + } + ], + "name": "batchSetIntervals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchUpdatePipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchWithdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "bucketedDelays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "buckets", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "burnPerformGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "checkGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "counters", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "delays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedAgainSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feedsHex", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "firstPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDsDeployedByThisContract", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getAllActiveUpkeepIDsOnRegistry", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getBucketedDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getBucketedDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "getLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "p", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getPxDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getSumDelayInBucket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getSumDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "intervals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastTopUpBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minBalanceThresholdMultiplier", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performDataSizes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "previousPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registrar", + "outputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract IKeeperRegistryMaster", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "sendLog", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "newRegistrar", + "type": "address" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_feeds", + "type": "string[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedParamKey", + "type": "string" + }, + { + "internalType": "string", + "name": "_timeParamKey", + "type": "string" + } + ], + "name": "setParamKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformDataSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "topUpFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "updateLogTriggerConfig1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "updateLogTriggerConfig2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pipelineData", + "type": "bytes" + } + ], + "name": "updateUpkeepPipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTopUpCheckInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbitrumBlockNum", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json new file mode 100644 index 0000000..9968337 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json @@ -0,0 +1,1757 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "_registrar", + "type": "address" + }, + { + "internalType": "bool", + "name": "_useArb", + "type": "bool" + }, + { + "internalType": "bool", + "name": "_useMercury", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmittedAgain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "UpkeepTopUp", + "type": "event" + }, + { + "inputs": [], + "name": "BUCKET_SIZE", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addLinkAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchCancelUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "batchPreparingUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + } + ], + "name": "batchPreparingUpkeepsSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "number", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "checkGasToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "performGasToBurn", + "type": "uint256" + } + ], + "name": "batchRegisterUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "batchSendLogs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint32", + "name": "interval", + "type": "uint32" + } + ], + "name": "batchSetIntervals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchUpdatePipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchWithdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "bucketedDelays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "buckets", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "burnPerformGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "checkGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "source", + "type": "address" + }, + { + "internalType": "bytes32[]", + "name": "topics", + "type": "bytes32[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Log", + "name": "log", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkLog", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "counters", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "delays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedAgainSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feedsHex", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "firstPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDsDeployedByThisContract", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getAllActiveUpkeepIDsOnRegistry", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getBucketedDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getBucketedDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "getLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "p", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getPxDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getSumDelayInBucket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getSumDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "intervals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastTopUpBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "logNum", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minBalanceThresholdMultiplier", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performDataSizes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "previousPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registrar", + "outputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract IKeeperRegistryMaster", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "sendLog", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "newRegistrar", + "type": "address" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_feeds", + "type": "string[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "_log", + "type": "uint8" + } + ], + "name": "setLog", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedParamKey", + "type": "string" + }, + { + "internalType": "string", + "name": "_timeParamKey", + "type": "string" + } + ], + "name": "setParamKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformDataSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "topUpFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "updateLogTriggerConfig1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "updateLogTriggerConfig2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pipelineData", + "type": "bytes" + } + ], + "name": "updateUpkeepPipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTopUpCheckInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbitrumBlockNum", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useMercury", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json new file mode 100644 index 0000000..fab8627 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json @@ -0,0 +1,1666 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "_registrar", + "type": "address" + }, + { + "internalType": "bool", + "name": "_useArb", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "feedParamKey", + "type": "string" + }, + { + "internalType": "string[]", + "name": "feeds", + "type": "string[]" + }, + { + "internalType": "string", + "name": "timeParamKey", + "type": "string" + }, + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "StreamsLookup", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmittedAgain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "UpkeepTopUp", + "type": "event" + }, + { + "inputs": [], + "name": "BUCKET_SIZE", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addLinkAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchCancelUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "batchPreparingUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + } + ], + "name": "batchPreparingUpkeepsSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "number", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "checkGasToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "performGasToBurn", + "type": "uint256" + } + ], + "name": "batchRegisterUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "batchSendLogs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint32", + "name": "interval", + "type": "uint32" + } + ], + "name": "batchSetIntervals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchUpdatePipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchWithdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "bucketedDelays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "buckets", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "burnPerformGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkErrorHandler", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "checkGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "counters", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "delays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedAgainSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feedsHex", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "firstPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDsDeployedByThisContract", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getAllActiveUpkeepIDsOnRegistry", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getBucketedDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getBucketedDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "getLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "p", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getPxDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getSumDelayInBucket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getSumDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "intervals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastTopUpBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minBalanceThresholdMultiplier", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performDataSizes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "previousPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registrar", + "outputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract IKeeperRegistryMaster", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "sendLog", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "newRegistrar", + "type": "address" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_feeds", + "type": "string[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedParamKey", + "type": "string" + }, + { + "internalType": "string", + "name": "_timeParamKey", + "type": "string" + } + ], + "name": "setParamKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformDataSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "topUpFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "updateLogTriggerConfig1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "updateLogTriggerConfig2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pipelineData", + "type": "bytes" + } + ], + "name": "updateUpkeepPipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTopUpCheckInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbitrumBlockNum", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json new file mode 100644 index 0000000..e9abeb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json @@ -0,0 +1,1577 @@ +[ + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "_registrar", + "type": "address" + }, + { + "internalType": "bool", + "name": "_useArb", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "LogEmittedAgain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "UpkeepTopUp", + "type": "event" + }, + { + "inputs": [], + "name": "BUCKET_SIZE", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "addLinkAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchCancelUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "batchPreparingUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + } + ], + "name": "batchPreparingUpkeepsSimple", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "number", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "checkGasToBurn", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "performGasToBurn", + "type": "uint256" + } + ], + "name": "batchRegisterUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "batchSendLogs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + }, + { + "internalType": "uint32", + "name": "interval", + "type": "uint32" + } + ], + "name": "batchSetIntervals", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchUpdatePipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "upkeepIds", + "type": "uint256[]" + } + ], + "name": "batchWithdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "bucketedDelays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "buckets", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "burnPerformGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "checkGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "counters", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "delays", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "dummyMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "eligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedAgainSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "emittedSig", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feedParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "feedsHex", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "firstPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "gasLimits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDsDeployedByThisContract", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getAllActiveUpkeepIDsOnRegistry", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getBucketedDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getBucketedDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelays", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getDelaysLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "getLogTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "logTrigger", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "p", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getPxDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "bucket", + "type": "uint16" + } + ], + "name": "getSumDelayInBucket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "n", + "type": "uint256" + } + ], + "name": "getSumDelayLastNPerforms", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepInfo", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "intervals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "lastTopUpBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkToken", + "outputs": [ + { + "internalType": "contract LinkTokenInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minBalanceThresholdMultiplier", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performDataSizes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "performGasToBurns", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "performUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "previousPerformBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registrar", + "outputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "contract IKeeperRegistryMaster", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "log", + "type": "uint8" + } + ], + "name": "sendLog", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AutomationRegistrar2_1", + "name": "newRegistrar", + "type": "address" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_feeds", + "type": "string[]" + } + ], + "name": "setFeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_interval", + "type": "uint256" + } + ], + "name": "setInterval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_feedParamKey", + "type": "string" + }, + { + "internalType": "string", + "name": "_timeParamKey", + "type": "string" + } + ], + "name": "setParamKeys", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "setPerformDataSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "timeParamKey", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockNum", + "type": "uint256" + } + ], + "name": "topUpFund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint8", + "name": "selector", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "topic0", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic1", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "topic3", + "type": "bytes32" + } + ], + "name": "updateLogTriggerConfig1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "cfg", + "type": "bytes" + } + ], + "name": "updateLogTriggerConfig2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "pipelineData", + "type": "bytes" + } + ], + "name": "updateUpkeepPipelineData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepTopUpCheckInterval", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "useArbitrumBlockNum", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "withdrawLinks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json new file mode 100644 index 0000000..5c6de23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json @@ -0,0 +1,714 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "verifierProxyAddr", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessForbidden", + "type": "error" + }, + { + "inputs": [], + "name": "BadVerification", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "CannotDeactivateLatestConfig", + "type": "error" + }, + { + "inputs": [], + "name": "DigestEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "DigestInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "DigestNotSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSigners", + "type": "uint256" + } + ], + "name": "ExcessSigners", + "type": "error" + }, + { + "inputs": [], + "name": "FaultToleranceMustBePositive", + "type": "error" + }, + { + "inputs": [], + "name": "FeedIdEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "InactiveFeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expectedNumSigners", + "type": "uint256" + } + ], + "name": "IncorrectSignatureCount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "numSigners", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minSigners", + "type": "uint256" + } + ], + "name": "InsufficientSigners", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rsLength", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ssLength", + "type": "uint256" + } + ], + "name": "MismatchedSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "NonUniqueSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "ConfigActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "ConfigDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "FeedActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "FeedDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "requester", + "type": "address" + } + ], + "name": "ReportVerified", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "activateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "activateFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "deactivateConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "deactivateFeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + } + ], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "feedId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "sourceChainId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "sourceAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newConfigCount", + "type": "uint32" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "offchainTransmitters", + "type": "bytes32[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "recipientAddressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setConfigFromSource", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "isVerifier", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "signedReport", + "type": "bytes" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "verifierResponse", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json new file mode 100644 index 0000000..625860a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json @@ -0,0 +1,435 @@ +[ + { + "inputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "accessController", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessForbidden", + "type": "error" + }, + { + "inputs": [], + "name": "BadVerification", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "ConfigDigestAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "FeeManagerInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "VerifierAlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "VerifierInvalid", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "VerifierNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessController", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessController", + "type": "address" + } + ], + "name": "AccessControllerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldFeeManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newFeeManager", + "type": "address" + } + ], + "name": "FeeManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "VerifierInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "oldConfigDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "newConfigDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "VerifierSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "VerifierUnset", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "getVerifier", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + } + ], + "name": "initializeVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_accessController", + "outputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "s_feeManager", + "outputs": [ + { + "internalType": "contract IVerifierFeeManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract AccessControllerInterface", + "name": "accessController", + "type": "address" + } + ], + "name": "setAccessController", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVerifierFeeManager", + "name": "feeManager", + "type": "address" + } + ], + "name": "setFeeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "currentConfigDigest", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newConfigDigest", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "weight", + "type": "uint64" + } + ], + "internalType": "struct Common.AddressAndWeight[]", + "name": "addressesAndWeights", + "type": "tuple[]" + } + ], + "name": "setVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "name": "unsetVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "payloads", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "parameterPayload", + "type": "bytes" + } + ], + "name": "verifyBulk", + "outputs": [ + { + "internalType": "bytes[]", + "name": "verifiedReports", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json new file mode 100644 index 0000000..16b7b02 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json @@ -0,0 +1,375 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json new file mode 100644 index 0000000..9cf2ec7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json @@ -0,0 +1,309 @@ +[ + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "guy", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "wad", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json new file mode 100644 index 0000000..a62c6f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json @@ -0,0 +1,80 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "address", + "name": "registry", + "type": "address" + }, + { + "internalType": "address", + "name": "logic", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "InvalidCaller", + "type": "error" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gasAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forward", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json new file mode 100644 index 0000000..fd901fc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json @@ -0,0 +1,1580 @@ +[ + { + "inputs": [ + { + "internalType": "contract ZKSyncAutomationRegistryLogicA2_3", + "name": "logicA", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "previousConfigBlockNumber", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "configCount", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "onchainConfig", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "ConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "name": "Transmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestConfigDigestAndEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "scanLogs", + "type": "bool" + }, + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "onchainConfigBytes", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", + "name": "onchainConfig", + "type": "tuple" + }, + { + "internalType": "uint64", + "name": "offchainConfigVersion", + "type": "uint64" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + }, + { + "internalType": "contract IERC20Metadata[]", + "name": "billingTokens", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]", + "name": "billingConfigs", + "type": "tuple[]" + } + ], + "name": "setConfigTypeSafe", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[3]", + "name": "reportContext", + "type": "bytes32[3]" + }, + { + "internalType": "bytes", + "name": "rawReport", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "rs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "ss", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "rawVs", + "type": "bytes32" + } + ], + "name": "transmit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json new file mode 100644 index 0000000..a94b41b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json @@ -0,0 +1,1180 @@ +[ + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json new file mode 100644 index 0000000..2e92ecc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json @@ -0,0 +1,1329 @@ +[ + { + "inputs": [ + { + "internalType": "contract ZKSyncAutomationRegistryLogicB2_3", + "name": "logicB", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "cancelUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "migrateUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "encodedUpkeeps", + "type": "bytes" + } + ], + "name": "receiveUpkeeps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "registerUpkeep", + "outputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json new file mode 100644 index 0000000..0fd9316 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json @@ -0,0 +1,1672 @@ +[ + { + "inputs": [ + { + "internalType": "contract ZKSyncAutomationRegistryLogicC2_3", + "name": "logicC", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "acceptUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "addFunds", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "values", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "checkCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerData", + "type": "bytes" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "checkUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "gasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fastGasWei", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "linkUSD", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "executeCallback", + "outputs": [ + { + "internalType": "bool", + "name": "upkeepNeeded", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", + "name": "upkeepFailureReason", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "fallbackTo", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "pauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "removeBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "billingOverrides", + "type": "tuple" + } + ], + "name": "setBillingOverrides", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "setUpkeepCheckData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setUpkeepGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "config", + "type": "bytes" + } + ], + "name": "setUpkeepOffchainConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "setUpkeepTriggerConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "performData", + "type": "bytes" + } + ], + "name": "simulatePerformUpkeep", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferUpkeepAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "unpauseUpkeep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawERC20Fees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawLink", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json new file mode 100644 index 0000000..87ae905 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json @@ -0,0 +1,2639 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "link", + "type": "address" + }, + { + "internalType": "address", + "name": "linkUSDFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeUSDFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "fastGasFeed", + "type": "address" + }, + { + "internalType": "address", + "name": "automationForwarderLogic", + "type": "address" + }, + { + "internalType": "address", + "name": "allowedReadOnlyAddress", + "type": "address" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.PayoutMode", + "name": "payoutMode", + "type": "uint8" + }, + { + "internalType": "address", + "name": "wrappedNativeTokenAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ArrayHasNoEntries", + "type": "error" + }, + { + "inputs": [], + "name": "CannotCancel", + "type": "error" + }, + { + "inputs": [], + "name": "CheckDataExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "ConfigDigestMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateEntry", + "type": "error" + }, + { + "inputs": [], + "name": "DuplicateSigners", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitCanOnlyIncrease", + "type": "error" + }, + { + "inputs": [], + "name": "GasLimitOutsideRange", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfFaultyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSignatures", + "type": "error" + }, + { + "inputs": [], + "name": "IncorrectNumberOfSigners", + "type": "error" + }, + { + "inputs": [], + "name": "IndexOutOfRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "available", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + } + ], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLinkLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidDataLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFeed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidPayee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRecipient", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidReport", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSigner", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidToken", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTransmitter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTrigger", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTriggerType", + "type": "error" + }, + { + "inputs": [], + "name": "MigrationNotPermitted", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOffchain", + "type": "error" + }, + { + "inputs": [], + "name": "MustSettleOnchain", + "type": "error" + }, + { + "inputs": [], + "name": "NotAContract", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveSigners", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyActiveTransmitters", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByLINKToken", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByOwnerOrRegistrar", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByProposedPayee", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyCallableByUpkeepPrivilegeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyFinanceAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "OnlySimulatedBackend", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyUnpausedUpkeep", + "type": "error" + }, + { + "inputs": [], + "name": "ParameterLengthError", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrantCall", + "type": "error" + }, + { + "inputs": [], + "name": "RegistryPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedSigner", + "type": "error" + }, + { + "inputs": [], + "name": "RepeatedTransmitter", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "TargetCheckReverted", + "type": "error" + }, + { + "inputs": [], + "name": "TooManyOracles", + "type": "error" + }, + { + "inputs": [], + "name": "TranscoderNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepCancelled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotCanceled", + "type": "error" + }, + { + "inputs": [], + "name": "UpkeepNotNeeded", + "type": "error" + }, + { + "inputs": [], + "name": "ValueNotChanged", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "AdminPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "overrides", + "type": "tuple" + } + ], + "name": "BillingConfigOverridden", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BillingConfigOverrideRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "BillingConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "CancelledUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newModule", + "type": "address" + } + ], + "name": "ChainSpecificModuleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "DedupKeyAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "assetAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "FundsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "FundsWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "InsufficientFundsUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "payments", + "type": "uint256[]" + } + ], + "name": "NOPsSettledOffchain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "PayeesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "PayeeshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "name": "PaymentWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "ReorgedUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "StaleUpkeepReport", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "UpkeepAdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "atBlockHeight", + "type": "uint64" + } + ], + "name": "UpkeepCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint96", + "name": "gasChargeInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInBillingToken", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "gasReimbursementInJuels", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "premiumInJuels", + "type": "uint96" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + }, + { + "internalType": "uint96", + "name": "linkUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "nativeUSD", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "billingUSD", + "type": "uint96" + } + ], + "indexed": false, + "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", + "name": "receipt", + "type": "tuple" + } + ], + "name": "UpkeepCharged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "newCheckData", + "type": "bytes" + } + ], + "name": "UpkeepCheckDataSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "gasLimit", + "type": "uint96" + } + ], + "name": "UpkeepGasLimitSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "destination", + "type": "address" + } + ], + "name": "UpkeepMigrated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "name": "UpkeepOffchainConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "totalPayment", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasUsed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gasOverhead", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "trigger", + "type": "bytes" + } + ], + "name": "UpkeepPerformed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "privilegeConfig", + "type": "bytes" + } + ], + "name": "UpkeepPrivilegeConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startingBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "importedFrom", + "type": "address" + } + ], + "name": "UpkeepReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "UpkeepRegistered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "triggerConfig", + "type": "bytes" + } + ], + "name": "UpkeepTriggerConfigSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "UpkeepUnpaused", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + } + ], + "name": "acceptPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "disableOffchainPayments", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxCount", + "type": "uint256" + } + ], + "name": "getActiveUpkeepIDs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "getAdminPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllowedReadOnlyAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAutomationForwarderLogic", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getAvailableERC20ForPayment", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getBillingConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverrides", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingOverridesEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getBillingToken", + "outputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + } + ], + "name": "getBillingTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "gasFeePPB", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "flatFeeMilliCents", + "type": "uint24" + }, + { + "internalType": "contract AggregatorV3Interface", + "name": "priceFeed", + "type": "address" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "fallbackPrice", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "minSpend", + "type": "uint96" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBillingTokens", + "outputs": [ + { + "internalType": "contract IERC20Metadata[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCancellationDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getChainModule", + "outputs": [ + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConditionalGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getConfig", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackNativePrice", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFallbackNativePrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFastGasFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepID", + "type": "uint256" + } + ], + "name": "getForwarder", + "outputs": [ + { + "internalType": "contract IAutomationForwarder", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getHotVars", + "outputs": [ + { + "components": [ + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reentrancyGuard", + "type": "bool" + }, + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + }, + { + "internalType": "contract IChainModule", + "name": "chainModule", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.HotVars", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLinkUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLogGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", + "name": "triggerType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getMaxPaymentForGas", + "outputs": [ + { + "internalType": "uint96", + "name": "maxPayment", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinBalanceForUpkeep", + "outputs": [ + { + "internalType": "uint96", + "name": "minBalance", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNativeUSDFeedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNumUpkeeps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPayoutMode", + "outputs": [ + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.PayoutMode", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + } + ], + "name": "getPeerRegistryMigrationPermission", + "outputs": [ + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.MigrationPermission", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPerSignerGasOverhead", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getReorgProtectionEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "reorgProtectionEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "billingToken", + "type": "address" + } + ], + "name": "getReserveAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getSignerInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getState", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "ownerLinkBalance", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "expectedLinkBalance", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "totalPremium", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "numUpkeeps", + "type": "uint256" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "latestConfigDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "latestEpoch", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "internalType": "struct IAutomationV21PlusCommon.StateLegacy", + "name": "state", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "paymentPremiumPPB", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "flatFeeMicroLink", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint24", + "name": "stalenessSeconds", + "type": "uint24" + }, + { + "internalType": "uint16", + "name": "gasCeilingMultiplier", + "type": "uint16" + }, + { + "internalType": "uint96", + "name": "minUpkeepSpend", + "type": "uint96" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fallbackGasPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fallbackLinkPrice", + "type": "uint256" + }, + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "address[]", + "name": "registrars", + "type": "address[]" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + } + ], + "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", + "name": "config", + "type": "tuple" + }, + { + "internalType": "address[]", + "name": "signers", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "transmitters", + "type": "address[]" + }, + { + "internalType": "uint8", + "name": "f", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStorage", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transcoder", + "type": "address" + }, + { + "internalType": "uint32", + "name": "checkGasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxPerformGas", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nonce", + "type": "uint32" + }, + { + "internalType": "address", + "name": "upkeepPrivilegeManager", + "type": "address" + }, + { + "internalType": "uint32", + "name": "configCount", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "latestConfigBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxCheckDataSize", + "type": "uint32" + }, + { + "internalType": "address", + "name": "financeAdmin", + "type": "address" + }, + { + "internalType": "uint32", + "name": "maxPerformDataSize", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "maxRevertDataSize", + "type": "uint32" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.Storage", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "query", + "type": "address" + } + ], + "name": "getTransmitterInfo", + "outputs": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "uint8", + "name": "index", + "type": "uint8" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "lastCollected", + "type": "uint96" + }, + { + "internalType": "address", + "name": "payee", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTransmittersWithPayees", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "transmitterAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "payeeAddress", + "type": "address" + } + ], + "internalType": "struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getTriggerType", + "outputs": [ + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getUpkeep", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint32", + "name": "performGas", + "type": "uint32" + }, + { + "internalType": "bytes", + "name": "checkData", + "type": "bytes" + }, + { + "internalType": "uint96", + "name": "balance", + "type": "uint96" + }, + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "uint64", + "name": "maxValidBlocknumber", + "type": "uint64" + }, + { + "internalType": "uint32", + "name": "lastPerformedBlockNumber", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "amountSpent", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "paused", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "offchainConfig", + "type": "bytes" + } + ], + "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", + "name": "upkeepInfo", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepPrivilegeConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + } + ], + "name": "getUpkeepTriggerConfig", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getWrappedNativeTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "dedupKey", + "type": "bytes32" + } + ], + "name": "hasDedupKey", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "linkAvailableForPayment", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setAdminPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "payees", + "type": "address[]" + } + ], + "name": "setPayees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "peer", + "type": "address" + }, + { + "internalType": "enum ZKSyncAutomationRegistryBase2_3.MigrationPermission", + "name": "permission", + "type": "uint8" + } + ], + "name": "setPeerRegistryMigrationPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "upkeepId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "newPrivilegeConfig", + "type": "bytes" + } + ], + "name": "setUpkeepPrivilegeConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "settleNOPsOffchain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Metadata", + "name": "token", + "type": "address" + } + ], + "name": "supportsBillingToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transmitter", + "type": "address" + }, + { + "internalType": "address", + "name": "proposed", + "type": "address" + } + ], + "name": "transferPayeeship", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "upkeepVersion", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "withdrawPayment", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json new file mode 100644 index 0000000..44ce54a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json @@ -0,0 +1,578 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1SenderAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "initialStatus", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidSender", + "type": "error" + }, + { + "inputs": [], + "name": "NoDataPresent", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "int256", + "name": "current", + "type": "int256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + } + ], + "name": "AnswerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "L1SenderTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "startedBy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + } + ], + "name": "NewRound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int256", + "name": "status", + "type": "int256" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "updatedAt", + "type": "uint64" + } + ], + "name": "RoundUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "latestStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "latestTimestamp", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bool", + "name": "incomingStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "incomingTimestamp", + "type": "uint64" + } + ], + "name": "UpdateIgnored", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "description", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint80", + "name": "_roundId", + "type": "uint80" + } + ], + "name": "getRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "roundId", + "type": "uint256" + } + ], + "name": "getTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1Sender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestAnswer", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestRoundData", + "outputs": [ + { + "internalType": "uint80", + "name": "roundId", + "type": "uint80" + }, + { + "internalType": "int256", + "name": "answer", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "startedAt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "updatedAt", + "type": "uint256" + }, + { + "internalType": "uint80", + "name": "answeredInRound", + "type": "uint80" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferL1Sender", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "status", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "timestamp", + "type": "uint64" + } + ], + "name": "updateStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json new file mode 100644 index 0000000..425d150 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json @@ -0,0 +1,402 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "l1CrossDomainMessengerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "l2UptimeFeedAddr", + "type": "address" + }, + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "chainId", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "l2GasPerPubdataByteLimit", + "type": "uint32" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidChainID", + "type": "error" + }, + { + "inputs": [], + "name": "L1CrossDomainMessengerAddressZero", + "type": "error" + }, + { + "inputs": [], + "name": "L2UptimeFeedAddrZero", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "AddedAccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CheckAccessEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "GasLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "l2GasPerPubdataByteLimit", + "type": "uint32" + } + ], + "name": "GasPerPubdataByteLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "RemovedAccess", + "type": "event" + }, + { + "inputs": [], + "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_UPTIME_FEED_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "addAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "checkEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "disableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "enableAccessCheck", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getGasLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getL2GasPerPubdataByteLimit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "hasAccess", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "removeAccess", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "gasLimit", + "type": "uint32" + } + ], + "name": "setGasLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "l2GasPerPubdataByteLimit", + "type": "uint32" + } + ], + "name": "setL2GasPerPubdataByteLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "typeAndVersion", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "currentAnswer", + "type": "int256" + } + ], + "name": "validate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json new file mode 100644 index 0000000..7d0e9a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json @@ -0,0 +1,77 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "FailedRelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "msgHash", + "type": "bytes32" + } + ], + "name": "RelayedMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "SentMessage", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_message", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "_gasLimit", + "type": "uint32" + } + ], + "name": "sendMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "xDomainMessageSender", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/packages/foundry/lib/chainlink/contracts/package.json b/packages/foundry/lib/chainlink/contracts/package.json new file mode 100644 index 0000000..c6bb574 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/package.json @@ -0,0 +1,84 @@ +{ + "name": "@chainlink/contracts", + "version": "1.3.0", + "description": "Chainlink smart contracts", + "author": "Chainlink devs", + "license": "MIT", + "private": false, + "files": [ + "src/v0.8", + "abi/v0.8" + ], + "engines": { + "node": ">=18", + "pnpm": ">=9" + }, + "devDependencies": { + "@ethereum-waffle/mock-contract": "^3.4.4", + "@ethersproject/abi": "~5.7.0", + "@ethersproject/bignumber": "~5.7.0", + "@ethersproject/contracts": "~5.7.0", + "@ethersproject/providers": "~5.7.2", + "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", + "@nomicfoundation/hardhat-ethers": "^3.0.8", + "@nomicfoundation/hardhat-network-helpers": "^1.0.12", + "@nomicfoundation/hardhat-verify": "^2.0.11", + "@typechain/ethers-v5": "^7.2.0", + "@typechain/hardhat": "^7.0.0", + "@types/cbor": "~5.0.1", + "@types/chai": "^4.3.20", + "@types/debug": "^4.1.12", + "@types/deep-equal-in-any-order": "^1.0.3", + "@types/mocha": "^10.0.8", + "@types/node": "^20.16.10", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", + "abi-to-sol": "^0.6.6", + "cbor": "^5.2.0", + "chai": "^4.5.0", + "debug": "^4.3.7", + "deep-equal-in-any-order": "^2.0.6", + "eslint": "^8.57.1", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "ethers": "~5.7.2", + "hardhat": "~2.20.1", + "hardhat-abi-exporter": "^2.10.1", + "hardhat-ignore-warnings": "^0.2.6", + "moment": "^2.30.1", + "prettier": "^3.3.3", + "prettier-plugin-solidity": "^1.4.1", + "solhint": "^5.0.3", + "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", + "solhint-plugin-prettier": "^0.1.0", + "ts-node": "^10.9.2", + "typechain": "^8.2.1", + "typescript": "^5.6.2" + }, + "dependencies": { + "@arbitrum/nitro-contracts": "1.1.1", + "@arbitrum/token-bridge-contracts": "1.1.2", + "@changesets/changelog-github": "^0.5.0", + "@changesets/cli": "~2.27.8", + "@eth-optimism/contracts": "0.6.0", + "@openzeppelin/contracts": "4.9.3", + "@openzeppelin/contracts-upgradeable": "4.9.3", + "@scroll-tech/contracts": "0.1.0", + "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9", + "semver": "^7.6.3" + }, + "scripts": { + "test": "hardhat test --parallel", + "lint": "eslint --ext js,ts .", + "prettier:check": "prettier '**/*' --check --ignore-unknown", + "prettier:write": "prettier '**/*' --write --ignore-unknown", + "size": "hardhat size-contracts", + "clean": "hardhat clean", + "compile:native": "./scripts/native_solc_compile_all", + "compile": "hardhat compile", + "coverage": "hardhat coverage", + "publish-beta": "pnpm publish --tag beta", + "publish-prod": "pnpm publish --tag latest", + "solhint": "solhint --max-warnings 0 \"./src/v0.8/**/*.sol\"" + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol new file mode 100644 index 0000000..c5052cd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_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. +/// @dev For instance, ChainSpecificUtil.getBlockNumber() returns L2 block number in L2 chains +library ChainSpecificUtil { + // ------------ Start Arbitrum Constants ------------ + + /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); + + /// @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); + + uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; + uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; + uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; + + // ------------ 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 OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + uint256 private constant OP_MAINNET_CHAIN_ID = 10; + uint256 private constant OP_GOERLI_CHAIN_ID = 420; + uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; + + /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. + uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; + uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; + uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; + + // ------------ End Optimism Constants ------------ + + /** + * @notice Returns the blockhash for the given blockNumber. + * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. + * @notice Otherwise, it uses the blockhash opcode. + * @notice Note that the blockhash opcode will return the L2 blockhash on Optimism. + */ + function _getBlockhash(uint64 blockNumber) internal view returns (bytes32) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + if ((_getBlockNumber() - blockNumber) > 256 || blockNumber >= _getBlockNumber()) { + return ""; + } + return ARBSYS.arbBlockHash(blockNumber); + } + return blockhash(blockNumber); + } + + /** + * @notice Returns the block number of the current block. + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. + * @notice Otherwise, it uses the block.number opcode. + * @notice Note that the block.number opcode will return the L2 block number on Optimism. + */ + function _getBlockNumber() internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + return ARBSYS.arbBlockNumber(); + } + return block.number; + } + + /** + * @notice Returns the L1 fees 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, there's no need to pass the provided calldata + * @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy + * @notice and getL1Fee is called to get the fees. + */ + function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + return ARBGAS.getCurrentTxL1GasFees(); + } else if (_isOptimismChainId(chainid)) { + return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); + } + return 0; + } + + /** + * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted + * @notice to L1. + */ + function _getL1CalldataGasCost(uint256 calldataSizeBytes) internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); + // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from + // for the justification behind the 140 number. + return l1PricePerByte * (calldataSizeBytes + 140); + } else if (_isOptimismChainId(chainid)) { + return _calculateOptimismL1DataFee(calldataSizeBytes); + } + return 0; + } + + /** + * @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. + */ + function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == ARB_MAINNET_CHAIN_ID || + chainId == ARB_GOERLI_TESTNET_CHAIN_ID || + chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; + } + + /** + * @notice Return true if and only if the provided chain ID is an Optimism chain ID. + * @notice Note that optimism chain id's are also OP stack chain id's (e.g. Base). + */ + function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == OP_MAINNET_CHAIN_ID || + chainId == OP_GOERLI_CHAIN_ID || + chainId == OP_SEPOLIA_CHAIN_ID || + chainId == BASE_MAINNET_CHAIN_ID || + chainId == BASE_GOERLI_CHAIN_ID || + chainId == BASE_SEPOLIA_CHAIN_ID; + } + + function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { + // from: https://community.optimism.io/docs/developers/build/transaction-fees/#the-l1-data-fee + // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead + // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 + // note we conservatively assume all non-zero bytes. + uint256 l1BaseFeeWei = OVM_GASPRICEORACLE.l1BaseFee(); + uint256 numZeroBytes = 0; + uint256 numNonzeroBytes = calldataSizeBytes - numZeroBytes; + uint256 txDataGas = numZeroBytes * 4 + numNonzeroBytes * 16; + uint256 fixedOverhead = OVM_GASPRICEORACLE.overhead(); + + // The scalar is some value like 0.684, but is represented as + // that times 10 ^ number of scalar decimals. + // e.g scalar = 0.684 * 10^6 + // The divisor is used to divide that and have a net result of the true scalar. + uint256 scalar = OVM_GASPRICEORACLE.scalar(); + uint256 scalarDecimals = OVM_GASPRICEORACLE.decimals(); + uint256 divisor = 10 ** scalarDecimals; + + uint256 l1DataFee = (l1BaseFeeWei * (txDataGas + fixedOverhead) * scalar) / divisor; + return l1DataFee; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol new file mode 100644 index 0000000..0379dc8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_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. +/// @dev For instance, ChainSpecificUtil.getBlockNumber() returns L2 block number in L2 chains +library ChainSpecificUtil { + // ------------ Start Arbitrum Constants ------------ + + /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); + + /// @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); + + uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; + uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; + uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; + + // ------------ 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 OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + uint256 private constant OP_MAINNET_CHAIN_ID = 10; + uint256 private constant OP_GOERLI_CHAIN_ID = 420; + uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; + + /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. + uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; + uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; + uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; + + // ------------ End Optimism Constants ------------ + + /** + * @notice Returns the blockhash for the given blockNumber. + * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. + * @notice Otherwise, it uses the blockhash opcode. + * @notice Note that the blockhash opcode will return the L2 blockhash on Optimism. + */ + function _getBlockhash(uint64 blockNumber) internal view returns (bytes32) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + if ((_getBlockNumber() - blockNumber) > 256 || blockNumber >= _getBlockNumber()) { + return ""; + } + return ARBSYS.arbBlockHash(blockNumber); + } + return blockhash(blockNumber); + } + + /** + * @notice Returns the block number of the current block. + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. + * @notice Otherwise, it uses the block.number opcode. + * @notice Note that the block.number opcode will return the L2 block number on Optimism. + */ + function _getBlockNumber() internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + return ARBSYS.arbBlockNumber(); + } + return block.number; + } + + /** + * @notice Returns the L1 fees 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, there's no need to pass the provided calldata + * @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy + * @notice and getL1Fee is called to get the fees. + */ + function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + return ARBGAS.getCurrentTxL1GasFees(); + } else if (_isOptimismChainId(chainid)) { + return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); + } + return 0; + } + + /** + * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted + * @notice to L1. + */ + function _getL1CalldataGasCost(uint256 calldataSizeBytes) internal view returns (uint256) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); + // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from + // for the justification behind the 140 number. + return l1PricePerByte * (calldataSizeBytes + 140); + } else if (_isOptimismChainId(chainid)) { + return _calculateOptimismL1DataFee(calldataSizeBytes); + } + return 0; + } + + /** + * @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. + */ + function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == ARB_MAINNET_CHAIN_ID || + chainId == ARB_GOERLI_TESTNET_CHAIN_ID || + chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; + } + + /** + * @notice Return true if and only if the provided chain ID is an Optimism chain ID. + * @notice Note that optimism chain id's are also OP stack chain id's (e.g. Base). + */ + function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == OP_MAINNET_CHAIN_ID || + chainId == OP_GOERLI_CHAIN_ID || + chainId == OP_SEPOLIA_CHAIN_ID || + chainId == BASE_MAINNET_CHAIN_ID || + chainId == BASE_GOERLI_CHAIN_ID || + chainId == BASE_SEPOLIA_CHAIN_ID; + } + + function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { + // from: https://community.optimism.io/docs/developers/build/transaction-fees/#the-l1-data-fee + // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead + // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 + // note we conservatively assume all non-zero bytes. + uint256 l1BaseFeeWei = OVM_GASPRICEORACLE.l1BaseFee(); + uint256 numZeroBytes = 0; + uint256 numNonzeroBytes = calldataSizeBytes - numZeroBytes; + uint256 txDataGas = numZeroBytes * 4 + numNonzeroBytes * 16; + uint256 fixedOverhead = OVM_GASPRICEORACLE.overhead(); + + // The scalar is some value like 0.684, but is represented as + // that times 10 ^ number of scalar decimals. + // e.g scalar = 0.684 * 10^6 + // The divisor is used to divide that and have a net result of the true scalar. + uint256 scalar = OVM_GASPRICEORACLE.scalar(); + uint256 scalarDecimals = OVM_GASPRICEORACLE.decimals(); + uint256 divisor = 10 ** scalarDecimals; + + uint256 l1DataFee = (l1BaseFeeWei * (txDataGas + fixedOverhead) * scalar) / divisor; + return l1DataFee; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol new file mode 100644 index 0000000..e511cfc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {CBORChainlink} from "./vendor/CBORChainlink.sol"; +import {BufferChainlink} from "./vendor/BufferChainlink.sol"; + +/** + * @title Library for common Chainlink functions + * @dev Uses imported CBOR library for encoding to buffer + */ +library Chainlink { + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint256 internal constant defaultBufferSize = 256; + + using CBORChainlink for BufferChainlink.buffer; + + struct Request { + bytes32 id; + address callbackAddress; + bytes4 callbackFunctionId; + uint256 nonce; + BufferChainlink.buffer buf; + } + + /** + * @notice Initializes a Chainlink request + * @dev Sets the ID, callback address, and callback function signature on the request + * @param self The uninitialized request + * @param jobId The Job Specification ID + * @param callbackAddr The callback address + * @param callbackFunc The callback function signature + * @return The initialized request + */ + function _initialize( + Request memory self, + bytes32 jobId, + address callbackAddr, + bytes4 callbackFunc + ) internal pure returns (Chainlink.Request memory) { + BufferChainlink.init(self.buf, defaultBufferSize); + self.id = jobId; + self.callbackAddress = callbackAddr; + self.callbackFunctionId = callbackFunc; + return self; + } + + /** + * @notice Sets the data for the buffer without encoding CBOR on-chain + * @dev CBOR can be closed with curly-brackets {} or they can be left off + * @param self The initialized request + * @param data The CBOR data + */ + function _setBuffer(Request memory self, bytes memory data) internal pure { + BufferChainlink.init(self.buf, data.length); + BufferChainlink.append(self.buf, data); + } + + /** + * @notice Adds a string value to the request with a given key name + * @param self The initialized request + * @param key The name of the key + * @param value The string value to add + */ + function _add(Request memory self, string memory key, string memory value) internal pure { + self.buf.encodeString(key); + self.buf.encodeString(value); + } + + /** + * @notice Adds a bytes value to the request with a given key name + * @param self The initialized request + * @param key The name of the key + * @param value The bytes value to add + */ + function _addBytes(Request memory self, string memory key, bytes memory value) internal pure { + self.buf.encodeString(key); + self.buf.encodeBytes(value); + } + + /** + * @notice Adds a int256 value to the request with a given key name + * @param self The initialized request + * @param key The name of the key + * @param value The int256 value to add + */ + function _addInt(Request memory self, string memory key, int256 value) internal pure { + self.buf.encodeString(key); + self.buf.encodeInt(value); + } + + /** + * @notice Adds a uint256 value to the request with a given key name + * @param self The initialized request + * @param key The name of the key + * @param value The uint256 value to add + */ + function _addUint(Request memory self, string memory key, uint256 value) internal pure { + self.buf.encodeString(key); + self.buf.encodeUInt(value); + } + + /** + * @notice Adds an array of strings to the request with a given key name + * @param self The initialized request + * @param key The name of the key + * @param values The array of string values to add + */ + function _addStringArray(Request memory self, string memory key, string[] memory values) internal pure { + self.buf.encodeString(key); + self.buf.startArray(); + for (uint256 i = 0; i < values.length; i++) { + self.buf.encodeString(values[i]); + } + self.buf.endSequence(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol new file mode 100644 index 0000000..1d8640a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Chainlink} from "./Chainlink.sol"; +import {ENSInterface} from "./interfaces/ENSInterface.sol"; +import {LinkTokenInterface} from "./shared/interfaces/LinkTokenInterface.sol"; +import {ChainlinkRequestInterface} from "./interfaces/ChainlinkRequestInterface.sol"; +import {OperatorInterface} from "./interfaces/OperatorInterface.sol"; +import {PointerInterface} from "./interfaces/PointerInterface.sol"; +import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; + +/** + * @title The ChainlinkClient contract + * @notice Contract writers can inherit this contract in order to create requests for the + * Chainlink network + */ +// solhint-disable gas-custom-errors +abstract contract ChainlinkClient { + using Chainlink for Chainlink.Request; + + uint256 internal constant LINK_DIVISIBILITY = 10 ** 18; + uint256 private constant AMOUNT_OVERRIDE = 0; + address private constant SENDER_OVERRIDE = address(0); + uint256 private constant ORACLE_ARGS_VERSION = 1; + uint256 private constant OPERATOR_ARGS_VERSION = 2; + bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link"); + bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle"); + address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; + + ENSInterface private s_ens; + bytes32 private s_ensNode; + LinkTokenInterface private s_link; + OperatorInterface private s_oracle; + uint256 private s_requestCount = 1; + mapping(bytes32 => address) private s_pendingRequests; + + event ChainlinkRequested(bytes32 indexed id); + event ChainlinkFulfilled(bytes32 indexed id); + event ChainlinkCancelled(bytes32 indexed id); + + /** + * @notice Creates a request that can hold additional parameters + * @param specId The Job Specification ID that the request will be created for + * @param callbackAddr address to operate the callback on + * @param callbackFunctionSignature function signature to use for the callback + * @return A Chainlink Request struct in memory + */ + function _buildChainlinkRequest( + bytes32 specId, + address callbackAddr, + bytes4 callbackFunctionSignature + ) internal pure returns (Chainlink.Request memory) { + Chainlink.Request memory req; + return req._initialize(specId, callbackAddr, callbackFunctionSignature); + } + + /** + * @notice Creates a request that can hold additional parameters + * @param specId The Job Specification ID that the request will be created for + * @param callbackFunctionSignature function signature to use for the callback + * @return A Chainlink Request struct in memory + */ + function _buildOperatorRequest( + bytes32 specId, + bytes4 callbackFunctionSignature + ) internal view returns (Chainlink.Request memory) { + Chainlink.Request memory req; + return req._initialize(specId, address(this), callbackFunctionSignature); + } + + /** + * @notice Creates a Chainlink request to the stored oracle address + * @dev Calls `chainlinkRequestTo` with the stored oracle address + * @param req The initialized Chainlink Request + * @param payment The amount of LINK to send for the request + * @return requestId The request ID + */ + function _sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { + return _sendChainlinkRequestTo(address(s_oracle), req, payment); + } + + /** + * @notice Creates a Chainlink request to the specified oracle address + * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to + * send LINK which creates a request on the target oracle contract. + * Emits ChainlinkRequested event. + * @param oracleAddress The address of the oracle for the request + * @param req The initialized Chainlink Request + * @param payment The amount of LINK to send for the request + * @return requestId The request ID + */ + function _sendChainlinkRequestTo( + address oracleAddress, + Chainlink.Request memory req, + uint256 payment + ) internal returns (bytes32 requestId) { + uint256 nonce = s_requestCount; + s_requestCount = nonce + 1; + bytes memory encodedRequest = abi.encodeWithSelector( + ChainlinkRequestInterface.oracleRequest.selector, + SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address + AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent + req.id, + address(this), + req.callbackFunctionId, + nonce, + ORACLE_ARGS_VERSION, + req.buf.buf + ); + return _rawRequest(oracleAddress, nonce, payment, encodedRequest); + } + + /** + * @notice Creates a Chainlink request to the stored oracle address + * @dev This function supports multi-word response + * @dev Calls `sendOperatorRequestTo` with the stored oracle address + * @param req The initialized Chainlink Request + * @param payment The amount of LINK to send for the request + * @return requestId The request ID + */ + function _sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { + return _sendOperatorRequestTo(address(s_oracle), req, payment); + } + + /** + * @notice Creates a Chainlink request to the specified oracle address + * @dev This function supports multi-word response + * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to + * send LINK which creates a request on the target oracle contract. + * Emits ChainlinkRequested event. + * @param oracleAddress The address of the oracle for the request + * @param req The initialized Chainlink Request + * @param payment The amount of LINK to send for the request + * @return requestId The request ID + */ + function _sendOperatorRequestTo( + address oracleAddress, + Chainlink.Request memory req, + uint256 payment + ) internal returns (bytes32 requestId) { + uint256 nonce = s_requestCount; + s_requestCount = nonce + 1; + bytes memory encodedRequest = abi.encodeWithSelector( + OperatorInterface.operatorRequest.selector, + SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address + AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent + req.id, + req.callbackFunctionId, + nonce, + OPERATOR_ARGS_VERSION, + req.buf.buf + ); + return _rawRequest(oracleAddress, nonce, payment, encodedRequest); + } + + /** + * @notice Make a request to an oracle + * @param oracleAddress The address of the oracle for the request + * @param nonce used to generate the request ID + * @param payment The amount of LINK to send for the request + * @param encodedRequest data encoded for request type specific format + * @return requestId The request ID + */ + function _rawRequest( + address oracleAddress, + uint256 nonce, + uint256 payment, + bytes memory encodedRequest + ) private returns (bytes32 requestId) { + requestId = keccak256(abi.encodePacked(this, nonce)); + s_pendingRequests[requestId] = oracleAddress; + emit ChainlinkRequested(requestId); + require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle"); + return requestId; + } + + /** + * @notice Allows a request to be cancelled if it has not been fulfilled + * @dev Requires keeping track of the expiration value emitted from the oracle contract. + * Deletes the request from the `pendingRequests` mapping. + * Emits ChainlinkCancelled event. + * @param requestId The request ID + * @param payment The amount of LINK sent for the request + * @param callbackFunc The callback function specified for the request + * @param expiration The time of the expiration for the request + */ + function _cancelChainlinkRequest( + bytes32 requestId, + uint256 payment, + bytes4 callbackFunc, + uint256 expiration + ) internal { + OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]); + delete s_pendingRequests[requestId]; + emit ChainlinkCancelled(requestId); + requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); + } + + /** + * @notice the next request count to be used in generating a nonce + * @dev starts at 1 in order to ensure consistent gas cost + * @return returns the next request count to be used in a nonce + */ + function _getNextRequestCount() internal view returns (uint256) { + return s_requestCount; + } + + /** + * @notice Sets the stored oracle address + * @param oracleAddress The address of the oracle contract + */ + function _setChainlinkOracle(address oracleAddress) internal { + s_oracle = OperatorInterface(oracleAddress); + } + + /** + * @notice Sets the LINK token address + * @param linkAddress The address of the LINK token contract + */ + function _setChainlinkToken(address linkAddress) internal { + s_link = LinkTokenInterface(linkAddress); + } + + /** + * @notice Sets the Chainlink token address for the public + * network as given by the Pointer contract + */ + function _setPublicChainlinkToken() internal { + _setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); + } + + /** + * @notice Retrieves the stored address of the LINK token + * @return The address of the LINK token + */ + function _chainlinkTokenAddress() internal view returns (address) { + return address(s_link); + } + + /** + * @notice Retrieves the stored address of the oracle contract + * @return The address of the oracle contract + */ + function _chainlinkOracleAddress() internal view returns (address) { + return address(s_oracle); + } + + /** + * @notice Allows for a request which was created on another contract to be fulfilled + * on this contract + * @param oracleAddress The address of the oracle contract that will fulfill the request + * @param requestId The request ID used for the response + */ + function _addChainlinkExternalRequest( + address oracleAddress, + bytes32 requestId + ) internal notPendingRequest(requestId) { + s_pendingRequests[requestId] = oracleAddress; + } + + /** + * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS + * @dev Accounts for subnodes having different resolvers + * @param ensAddress The address of the ENS contract + * @param node The ENS node hash + */ + function _useChainlinkWithENS(address ensAddress, bytes32 node) internal { + s_ens = ENSInterface(ensAddress); + s_ensNode = node; + bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME)); + ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode)); + _setChainlinkToken(resolver.addr(linkSubnode)); + _updateChainlinkOracleWithENS(); + } + + /** + * @notice Sets the stored oracle contract with the address resolved by ENS + * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously + */ + function _updateChainlinkOracleWithENS() internal { + bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME)); + ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode)); + _setChainlinkOracle(resolver.addr(oracleSubnode)); + } + + /** + * @notice Ensures that the fulfillment is valid for this contract + * @dev Use if the contract developer prefers methods instead of modifiers for validation + * @param requestId The request ID for fulfillment + */ + function _validateChainlinkCallback( + bytes32 requestId + ) + internal + recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks + {} + + /** + * @dev Reverts if the sender is not the oracle of the request. + * Emits ChainlinkFulfilled event. + * @param requestId The request ID for fulfillment + */ + modifier recordChainlinkFulfillment(bytes32 requestId) { + require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request"); + delete s_pendingRequests[requestId]; + emit ChainlinkFulfilled(requestId); + _; + } + + /** + * @dev Reverts if the request is already pending + * @param requestId The request ID for fulfillment + */ + modifier notPendingRequest(bytes32 requestId) { + require(s_pendingRequests[requestId] == address(0), "Request is already pending"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol new file mode 100644 index 0000000..6e9aa77 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +library Denominations { + address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; + + // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217 + address public constant USD = address(840); + address public constant GBP = address(826); + address public constant EUR = address(978); + address public constant JPY = address(392); + address public constant KRW = address(410); + address public constant CNY = address(156); + address public constant AUD = address(36); + address public constant CAD = address(124); + address public constant CHF = address(756); + address public constant ARS = address(32); + address public constant PHP = address(608); + address public constant NZD = address(554); + address public constant SGD = address(702); + address public constant NGN = address(566); + address public constant ZAR = address(710); + address public constant RUB = address(643); + address public constant INR = address(356); + address public constant BRL = address(986); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol new file mode 100644 index 0000000..de14583 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SimpleReadAccessController} from "./shared/access/SimpleReadAccessController.sol"; +import {AccessControllerInterface} from "./shared/interfaces/AccessControllerInterface.sol"; +import {FlagsInterface} from "./interfaces/FlagsInterface.sol"; + +/** + * @title The Flags contract + * @notice Allows flags to signal to any reader on the access control list. + * The owner can set flags, or designate other addresses to set flags. The + * owner must turn the flags off, other setters cannot. An expected pattern is + * to allow addresses to raise flags on themselves, so if you are subscribing to + * FlagOn events you should filter for addresses you care about. + */ +// solhint-disable gas-custom-errors +contract Flags is FlagsInterface, SimpleReadAccessController { + AccessControllerInterface public raisingAccessController; + + mapping(address => bool) private s_flags; + + event FlagRaised(address indexed subject); + event FlagLowered(address indexed subject); + event RaisingAccessControllerUpdated(address indexed previous, address indexed current); + + /** + * @param racAddress address for the raising access controller. + */ + constructor(address racAddress) { + setRaisingAccessController(racAddress); + } + + /** + * @notice read the warning flag status of a contract address. + * @param subject The contract address being checked for a flag. + * @return A true value indicates that a flag was raised and a + * false value indicates that no flag was raised. + */ + function getFlag(address subject) external view override checkAccess returns (bool) { + return s_flags[subject]; + } + + /** + * @notice read the warning flag status of a contract address. + * @param subjects An array of addresses being checked for a flag. + * @return An array of bools where a true value for any flag indicates that + * a flag was raised and a false value indicates that no flag was raised. + */ + function getFlags(address[] calldata subjects) external view override checkAccess returns (bool[] memory) { + bool[] memory responses = new bool[](subjects.length); + for (uint256 i = 0; i < subjects.length; i++) { + responses[i] = s_flags[subjects[i]]; + } + return responses; + } + + /** + * @notice enable the warning flag for an address. + * Access is controlled by raisingAccessController, except for owner + * who always has access. + * @param subject The contract address whose flag is being raised + */ + function raiseFlag(address subject) external override { + require(_allowedToRaiseFlags(), "Not allowed to raise flags"); + + _tryToRaiseFlag(subject); + } + + /** + * @notice enable the warning flags for multiple addresses. + * Access is controlled by raisingAccessController, except for owner + * who always has access. + * @param subjects List of the contract addresses whose flag is being raised + */ + function raiseFlags(address[] calldata subjects) external override { + require(_allowedToRaiseFlags(), "Not allowed to raise flags"); + + for (uint256 i = 0; i < subjects.length; i++) { + _tryToRaiseFlag(subjects[i]); + } + } + + /** + * @notice allows owner to disable the warning flags for multiple addresses. + * @param subjects List of the contract addresses whose flag is being lowered + */ + function lowerFlags(address[] calldata subjects) external override onlyOwner { + for (uint256 i = 0; i < subjects.length; i++) { + address subject = subjects[i]; + + if (s_flags[subject]) { + s_flags[subject] = false; + emit FlagLowered(subject); + } + } + } + + /** + * @notice allows owner to change the access controller for raising flags. + * @param racAddress new address for the raising access controller. + */ + function setRaisingAccessController(address racAddress) public override onlyOwner { + address previous = address(raisingAccessController); + + if (previous != racAddress) { + raisingAccessController = AccessControllerInterface(racAddress); + + emit RaisingAccessControllerUpdated(previous, racAddress); + } + } + + // PRIVATE + + function _allowedToRaiseFlags() private view returns (bool) { + return msg.sender == owner() || raisingAccessController.hasAccess(msg.sender, msg.data); + } + + function _tryToRaiseFlag(address subject) private { + if (!s_flags[subject]) { + s_flags[subject] = true; + emit FlagRaised(subject); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol new file mode 100644 index 0000000..544f890 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; +import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; + +/** + * @title PermissionedForwardProxy + * @notice This proxy is used to forward calls from sender to target. It maintains + * a permission list to check which sender is allowed to call which target + */ +contract PermissionedForwardProxy is ConfirmedOwner { + using Address for address; + + error PermissionNotSet(); + + event PermissionSet(address indexed sender, address target); + event PermissionRemoved(address indexed sender); + + mapping(address => address) private s_forwardPermissionList; + + constructor() ConfirmedOwner(msg.sender) {} + + /** + * @notice Verifies if msg.sender has permission to forward to target address and then forwards the handler + * @param target address of the contract to forward the handler to + * @param handler bytes to be passed to target in call data + */ + function forward(address target, bytes calldata handler) external { + if (s_forwardPermissionList[msg.sender] != target) { + revert PermissionNotSet(); + } + target.functionCall(handler); + } + + /** + * @notice Adds permission for sender to forward calls to target via this proxy. + * Note that it allows to overwrite an existing permission + * @param sender The address who will use this proxy to forward calls + * @param target The address where sender will be allowed to forward calls + */ + function setPermission(address sender, address target) external onlyOwner { + s_forwardPermissionList[sender] = target; + + emit PermissionSet(sender, target); + } + + /** + * @notice Removes permission for sender to forward calls via this proxy + * @param sender The address who will use this proxy to forward calls + */ + function removePermission(address sender) external onlyOwner { + delete s_forwardPermissionList[sender]; + + emit PermissionRemoved(sender); + } + + /** + * @notice Returns the target address that the sender can use this proxy for + * @param sender The address to fetch the permissioned target for + */ + function getPermission(address sender) external view returns (address) { + return s_forwardPermissionList[sender]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol new file mode 100644 index 0000000..58e0e28 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; +import {AggregatorValidatorInterface} from "./shared/interfaces/AggregatorValidatorInterface.sol"; +import {TypeAndVersionInterface} from "./interfaces/TypeAndVersionInterface.sol"; + +// solhint-disable gas-custom-errors +contract ValidatorProxy is AggregatorValidatorInterface, TypeAndVersionInterface, ConfirmedOwner { + /// @notice Uses a single storage slot to store the current address + struct AggregatorConfiguration { + address target; + bool hasNewProposal; + } + + struct ValidatorConfiguration { + AggregatorValidatorInterface target; + bool hasNewProposal; + } + + // Configuration for the current aggregator + AggregatorConfiguration private s_currentAggregator; + // Proposed aggregator address + address private s_proposedAggregator; + + // Configuration for the current validator + ValidatorConfiguration private s_currentValidator; + // Proposed validator address + AggregatorValidatorInterface private s_proposedValidator; + + event AggregatorProposed(address indexed aggregator); + event AggregatorUpgraded(address indexed previous, address indexed current); + event ValidatorProposed(AggregatorValidatorInterface indexed validator); + event ValidatorUpgraded(AggregatorValidatorInterface indexed previous, AggregatorValidatorInterface indexed current); + /// @notice The proposed aggregator called validate, but the call was not passed on to any validators + event ProposedAggregatorValidateCall( + address indexed proposed, + uint256 previousRoundId, + int256 previousAnswer, + uint256 currentRoundId, + int256 currentAnswer + ); + + /** + * @notice Construct the ValidatorProxy with an aggregator and a validator + * @param aggregator address + * @param validator address + */ + constructor(address aggregator, AggregatorValidatorInterface validator) ConfirmedOwner(msg.sender) { + s_currentAggregator = AggregatorConfiguration({target: aggregator, hasNewProposal: false}); + s_currentValidator = ValidatorConfiguration({target: validator, hasNewProposal: false}); + } + + /** + * @notice Validate a transmission + * @dev Must be called by either the `s_currentAggregator.target`, or the `s_proposedAggregator`. + * If called by the `s_currentAggregator.target` this function passes the call on to the `s_currentValidator.target` + * and the `s_proposedValidator`, if it is set. + * If called by the `s_proposedAggregator` this function emits a `ProposedAggregatorValidateCall` to signal that + * the call was received. + * @dev To guard against external `validate` calls reverting, we use raw calls here. + * We favour `call` over try-catch to ensure that failures are avoided even if the validator address is incorrectly + * set as a non-contract address. + * @dev If the `aggregator` and `validator` are the same contract or collude, this could exhibit reentrancy behavior. + * However, since that contract would have to be explicitly written for reentrancy and that the `owner` would have + * to configure this contract to use that malicious contract, we refrain from using mutex or check here. + * @dev This does not perform any checks on any roundId, so it is possible that a validator receive different reports + * for the same roundId at different points in time. Validator implementations should be aware of this. + * @param previousRoundId uint256 + * @param previousAnswer int256 + * @param currentRoundId uint256 + * @param currentAnswer int256 + * @return bool + */ + function validate( + uint256 previousRoundId, + int256 previousAnswer, + uint256 currentRoundId, + int256 currentAnswer + ) external override returns (bool) { + address currentAggregator = s_currentAggregator.target; + if (msg.sender != currentAggregator) { + address proposedAggregator = s_proposedAggregator; + require(msg.sender == proposedAggregator, "Not a configured aggregator"); + // If the aggregator is still in proposed state, emit an event and don't push to any validator. + // This is to confirm that `validate` is being called prior to upgrade. + emit ProposedAggregatorValidateCall( + proposedAggregator, + previousRoundId, + previousAnswer, + currentRoundId, + currentAnswer + ); + return true; + } + + // Send the validate call to the current validator + ValidatorConfiguration memory currentValidator = s_currentValidator; + address currentValidatorAddress = address(currentValidator.target); + require(currentValidatorAddress != address(0), "No validator set"); + // solhint-disable-next-line avoid-low-level-calls + currentValidatorAddress.call( + abi.encodeWithSelector( + AggregatorValidatorInterface.validate.selector, + previousRoundId, + previousAnswer, + currentRoundId, + currentAnswer + ) + ); + // If there is a new proposed validator, send the validate call to that validator also + if (currentValidator.hasNewProposal) { + // solhint-disable-next-line avoid-low-level-calls + address(s_proposedValidator).call( + abi.encodeWithSelector( + AggregatorValidatorInterface.validate.selector, + previousRoundId, + previousAnswer, + currentRoundId, + currentAnswer + ) + ); + } + return true; + } + + /** AGGREGATOR CONFIGURATION FUNCTIONS **/ + + /** + * @notice Propose an aggregator + * @dev A zero address can be used to unset the proposed aggregator. Only owner can call. + * @param proposed address + */ + function proposeNewAggregator(address proposed) external onlyOwner { + require(s_proposedAggregator != proposed && s_currentAggregator.target != proposed, "Invalid proposal"); + s_proposedAggregator = proposed; + // If proposed is zero address, hasNewProposal = false + s_currentAggregator.hasNewProposal = (proposed != address(0)); + emit AggregatorProposed(proposed); + } + + /** + * @notice Upgrade the aggregator by setting the current aggregator as the proposed aggregator. + * @dev Must have a proposed aggregator. Only owner can call. + */ + function upgradeAggregator() external onlyOwner { + // Get configuration in memory + AggregatorConfiguration memory current = s_currentAggregator; + address previous = current.target; + address proposed = s_proposedAggregator; + + // Perform the upgrade + require(current.hasNewProposal, "No proposal"); + s_currentAggregator = AggregatorConfiguration({target: proposed, hasNewProposal: false}); + delete s_proposedAggregator; + + emit AggregatorUpgraded(previous, proposed); + } + + /** + * @notice Get aggregator details + * @return current address + * @return hasProposal bool + * @return proposed address + */ + function getAggregators() external view returns (address current, bool hasProposal, address proposed) { + current = s_currentAggregator.target; + hasProposal = s_currentAggregator.hasNewProposal; + proposed = s_proposedAggregator; + return (current, hasProposal, proposed); + } + + /** VALIDATOR CONFIGURATION FUNCTIONS **/ + + /** + * @notice Propose an validator + * @dev A zero address can be used to unset the proposed validator. Only owner can call. + * @param proposed address + */ + function proposeNewValidator(AggregatorValidatorInterface proposed) external onlyOwner { + require(s_proposedValidator != proposed && s_currentValidator.target != proposed, "Invalid proposal"); + s_proposedValidator = proposed; + // If proposed is zero address, hasNewProposal = false + s_currentValidator.hasNewProposal = (address(proposed) != address(0)); + emit ValidatorProposed(proposed); + } + + /** + * @notice Upgrade the validator by setting the current validator as the proposed validator. + * @dev Must have a proposed validator. Only owner can call. + */ + function upgradeValidator() external onlyOwner { + // Get configuration in memory + ValidatorConfiguration memory current = s_currentValidator; + AggregatorValidatorInterface previous = current.target; + AggregatorValidatorInterface proposed = s_proposedValidator; + + // Perform the upgrade + require(current.hasNewProposal, "No proposal"); + s_currentValidator = ValidatorConfiguration({target: proposed, hasNewProposal: false}); + delete s_proposedValidator; + + emit ValidatorUpgraded(previous, proposed); + } + + /** + * @notice Get validator details + * @return current address + * @return hasProposal bool + * @return proposed address + */ + function getValidators() + external + view + returns (AggregatorValidatorInterface current, bool hasProposal, AggregatorValidatorInterface proposed) + { + current = s_currentValidator.target; + hasProposal = s_currentValidator.hasNewProposal; + proposed = s_proposedValidator; + return (current, hasProposal, proposed); + } + + /** + * @notice The type and version of this contract + * @return Type and version string + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "ValidatorProxy 1.0.0"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol new file mode 100644 index 0000000..72ee8aa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract AutomationBase { + error OnlySimulatedBackend(); + + /** + * @notice method that allows it to be simulated via eth_call by checking that + * the sender is the zero address. + */ + function _preventExecution() internal view { + // solhint-disable-next-line avoid-tx-origin + if (tx.origin != address(0) && tx.origin != address(0x1111111111111111111111111111111111111111)) { + revert OnlySimulatedBackend(); + } + } + + /** + * @notice modifier that allows it to be simulated via eth_call by checking + * that the sender is the zero address. + */ + modifier cannotExecute() { + _preventExecution(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol new file mode 100644 index 0000000..6533243 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AutomationBase} from "./AutomationBase.sol"; +import {AutomationCompatibleInterface} from "./interfaces/AutomationCompatibleInterface.sol"; + +abstract contract AutomationCompatible is AutomationBase, AutomationCompatibleInterface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol new file mode 100644 index 0000000..58d68fc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {Log} from "./interfaces/ILogAutomation.sol"; +import {IAutomationV21PlusCommon} from "./interfaces/IAutomationV21PlusCommon.sol"; + +contract AutomationCompatibleUtils { + function _report(IAutomationV21PlusCommon.Report memory) external {} + + function _logTriggerConfig(IAutomationV21PlusCommon.LogTriggerConfig memory) external {} + + function _logTrigger(IAutomationV21PlusCommon.LogTrigger memory) external {} + + function _conditionalTrigger(IAutomationV21PlusCommon.ConditionalTrigger memory) external {} + + function _log(Log memory) external {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol new file mode 100644 index 0000000..58707e9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.16; + +import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; + +uint256 constant PERFORM_GAS_CUSHION = 5_000; + +/** + * @title AutomationForwarder is a relayer that sits between the registry and the customer's target contract + * @dev The purpose of the forwarder is to give customers a consistent address to authorize against, + * which stays consistent between migrations. The Forwarder also exposes the registry address, so that users who + * want to programatically interact with the registry (ie top up funds) can do so. + */ +contract AutomationForwarder { + /// @notice the user's target contract address + address private immutable i_target; + + /// @notice the shared logic address + address private immutable i_logic; + + IAutomationRegistryConsumer private s_registry; + + constructor(address target, address registry, address logic) { + s_registry = IAutomationRegistryConsumer(registry); + i_target = target; + i_logic = logic; + } + + /** + * @notice forward is called by the registry and forwards the call to the target + * @param gasAmount is the amount of gas to use in the call + * @param data is the 4 bytes function selector + arbitrary function data + * @return success indicating whether the target call succeeded or failed + */ + function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed) { + if (msg.sender != address(s_registry)) revert(); + address target = i_target; + gasUsed = gasleft(); + assembly { + let g := gas() + // Compute g -= PERFORM_GAS_CUSHION and check for underflow + if lt(g, PERFORM_GAS_CUSHION) { + revert(0, 0) + } + g := sub(g, PERFORM_GAS_CUSHION) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call with exact gas + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + gasUsed = gasUsed - gasleft(); + return (success, gasUsed); + } + + function getTarget() external view returns (address) { + return i_target; + } + + fallback() external { + // copy to memory for assembly access + address logic = i_logic; + // copied directly from OZ's Proxy contract + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), logic, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol new file mode 100644 index 0000000..d8236f3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.16; + +import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; + +contract AutomationForwarderLogic is ITypeAndVersion { + IAutomationRegistryConsumer private s_registry; + + string public constant typeAndVersion = "AutomationForwarder 1.0.0"; + + /** + * @notice updateRegistry is called by the registry during migrations + * @param newRegistry is the registry that this forwarder is being migrated to + */ + function updateRegistry(address newRegistry) external { + if (msg.sender != address(s_registry)) revert(); + s_registry = IAutomationRegistryConsumer(newRegistry); + } + + function getRegistry() external view returns (IAutomationRegistryConsumer) { + return s_registry; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol new file mode 100644 index 0000000..469ea91 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +/** + * @title Chainable - the contract size limit nullifier + * @notice Chainable is designed to link together a "chain" of contracts through fallback functions + * and delegatecalls. All code is executed in the context of the head of the chain, the "master" contract. + */ +contract Chainable { + /** + * @dev addresses of the next contract in the chain **have to be immutable/constant** or the system won't work + */ + address private immutable i_FALLBACK_ADDRESS; + + /** + * @param fallbackAddress the address of the next contract in the chain + */ + constructor(address fallbackAddress) { + i_FALLBACK_ADDRESS = fallbackAddress; + } + + /** + * @notice returns the address of the next contract in the chain + */ + function fallbackTo() external view returns (address) { + return i_FALLBACK_ADDRESS; + } + + /** + * @notice the fallback function routes the call to the next contract in the chain + * @dev most of the implementation is copied directly from OZ's Proxy contract + */ + // solhint-disable-next-line no-complex-fallback + fallback() external payable { + // copy to memory for assembly access + address next = i_FALLBACK_ADDRESS; + // copied directly from OZ's Proxy contract + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the next contract. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), next, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol new file mode 100644 index 0000000..30a823c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +abstract contract ExecutionPrevention { + error OnlySimulatedBackend(); + + /** + * @notice method that allows it to be simulated via eth_call by checking that + * the sender is the zero address. + */ + function _preventExecution() internal view { + // solhint-disable-next-line avoid-tx-origin + if (tx.origin != address(0)) { + revert OnlySimulatedBackend(); + } + } + + /** + * @notice modifier that allows it to be simulated via eth_call by checking + * that the sender is the zero address. + */ + modifier cannotExecute() { + _preventExecution(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol new file mode 100644 index 0000000..8ef7fa4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity 0.8.6; + +import {TypeAndVersionInterface} from "./../interfaces/TypeAndVersionInterface.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; + +// defines some interfaces for type safety and reduces encoding/decoding +// does not use the full interfaces intentionally because the requester only uses a fraction of them +interface IAggregatorProxy { + function aggregator() external view returns (address); +} + +interface IOffchainAggregator { + function requestNewRound() external returns (uint80); +} + +/** + * @notice The heartbeat requester will maintain a mapping from allowed callers to corresponding proxies. When requested + * by eligible caller, it will call a proxy for an aggregator address and request a new round. The aggregator + * is gated by permissions and this requester address needs to be whitelisted. + */ +contract HeartbeatRequester is TypeAndVersionInterface, ConfirmedOwner { + event HeartbeatPermitted(address indexed permittedCaller, address newProxy, address oldProxy); + event HeartbeatRemoved(address indexed permittedCaller, address removedProxy); + + error HeartbeatNotPermitted(); + + mapping(address => IAggregatorProxy) internal s_heartbeatList; + + /** + * @notice versions: + * - HeartbeatRequester 1.0.0: The requester fetches the latest aggregator address from proxy, and request a new round + * using the aggregator address. + */ + string public constant override typeAndVersion = "HeartbeatRequester 1.0.0"; + + constructor() ConfirmedOwner(msg.sender) {} + + /** + * @notice adds a permitted caller and proxy combination. + * @param permittedCaller the permitted caller + * @param proxy the proxy corresponding to this caller + */ + function permitHeartbeat(address permittedCaller, IAggregatorProxy proxy) external onlyOwner { + address oldProxy = address(s_heartbeatList[permittedCaller]); + s_heartbeatList[permittedCaller] = proxy; + emit HeartbeatPermitted(permittedCaller, address(proxy), oldProxy); + } + + /** + * @notice removes a permitted caller and proxy combination. + * @param permittedCaller the permitted caller + */ + function removeHeartbeat(address permittedCaller) external onlyOwner { + address removedProxy = address(s_heartbeatList[permittedCaller]); + delete s_heartbeatList[permittedCaller]; + emit HeartbeatRemoved(permittedCaller, removedProxy); + } + + /** + * @notice fetches aggregator address from proxy and requests a new round. + * @param proxy the proxy address + */ + function getAggregatorAndRequestHeartbeat(address proxy) external { + IAggregatorProxy proxyInterface = s_heartbeatList[msg.sender]; + if (address(proxyInterface) != proxy) revert HeartbeatNotPermitted(); + + IOffchainAggregator aggregator = IOffchainAggregator(proxyInterface.aggregator()); + aggregator.requestNewRound(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol new file mode 100644 index 0000000..0e050d4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +/** + * @notice This is a deprecated interface. Please use AutomationBase directly. + */ +pragma solidity ^0.8.0; +// solhint-disable-next-line no-unused-import +import {AutomationBase as KeeperBase} from "./AutomationBase.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol new file mode 100644 index 0000000..6379fe5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +/** + * @notice This is a deprecated interface. Please use AutomationCompatible directly. + */ +pragma solidity ^0.8.0; +// solhint-disable-next-line no-unused-import +import {AutomationCompatible as KeeperCompatible} from "./AutomationCompatible.sol"; +// solhint-disable-next-line no-unused-import +import {AutomationBase as KeeperBase} from "./AutomationBase.sol"; +// solhint-disable-next-line no-unused-import +import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./interfaces/AutomationCompatibleInterface.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md new file mode 100644 index 0000000..717e741 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md @@ -0,0 +1,43 @@ +# Automation Contract Structure + +The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. Therefore, we include this explanation of how the pieces fit together and various tradeoffs incurred. + +### Glossary + +**Root Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the on-chain entry-point into the system. The root contract uses `delegatecall` to execute code at various logic contracts. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) + +**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the root contract in order to increase our total capacity for on-chain code. + +### Overview + +We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fallback to the next, always executing the function in the scope of the root contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. + +### Diagram + +```mermaid +graph LR + Root -- delegatecall --> la[Logic A] + la -- delegatecall --> lb[Logic B] + lb -. delegatecall .-> lx[Logic Z] +``` + +### Special Considerations + +- functions on the root contract have the least gas overhead. Therefore, our most price-sensitive functions live there. We have 3 functions that we consider hot paths. Ideally, these would all live on the root contract to minimize gas overhead. + - `transmit()` - this is the most important code path + - `registerUpkeep()` + - `addFunds()` +- functions on the root contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there +- etherscan supports executing logic contract functions that are once removed from the root - therefore we give secondary preference to the first logic contract for user and debugging functions +- functions on logic B through logic Z (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically +- We use Logic A, B, C... to avoid confusion with the version ex `AutomationRegistryLogicA2_1.sol` --> Logic Contract A verion 2.1 +- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break + +### Master Interface + +The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. + +[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 +[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function +[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries +[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol new file mode 100644 index 0000000..e765327 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev this struct is only maintained for backwards compatibility with MigratableKeeperRegistryInterface + * it should be deprecated in the future in favor of MigratableKeeperRegistryInterfaceV2 + */ +enum UpkeepFormat { + V1, + V2, + V3 +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol new file mode 100644 index 0000000..03f40d8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import {UpkeepTranscoderInterface} from "./interfaces/UpkeepTranscoderInterface.sol"; +import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {UpkeepFormat} from "./UpkeepFormat.sol"; + +/** + * @notice Transcoder for converting upkeep data from one keeper + * registry version to another + */ +contract UpkeepTranscoder is UpkeepTranscoderInterface, TypeAndVersionInterface { + error InvalidTranscoding(); + + /** + * @notice versions: + * - UpkeepTranscoder 1.0.0: placeholder to allow new formats in the future + */ + string public constant override typeAndVersion = "UpkeepTranscoder 1.0.0"; + + /** + * @notice transcodeUpkeeps transforms upkeep data from the format expected by + * one registry to the format expected by another. It future-proofs migrations + * by allowing keepers team to customize migration paths and set sensible defaults + * when new fields are added + * @param fromVersion struct version the upkeep is migrating from + * @param toVersion struct version the upkeep is migrating to + * @param encodedUpkeeps encoded upkeep data + * @dev this contract & function are simple now, but should evolve as new registries + * and migration paths are added + */ + function transcodeUpkeeps( + UpkeepFormat fromVersion, + UpkeepFormat toVersion, + bytes calldata encodedUpkeeps + ) external view override returns (bytes memory) { + if (fromVersion != toVersion) { + revert InvalidTranscoding(); + } + + return encodedUpkeeps; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol new file mode 100644 index 0000000..f4616ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; +import {GAS_BOUND_CALLER, IGasBoundCaller} from "./interfaces/zksync/IGasBoundCaller.sol"; + +uint256 constant PERFORM_GAS_CUSHION = 50_000; + +/** + * @title ZKSyncAutomationForwarder is a relayer that sits between the registry and the customer's target contract + * @dev The purpose of the forwarder is to give customers a consistent address to authorize against, + * which stays consistent between migrations. The Forwarder also exposes the registry address, so that users who + * want to programmatically interact with the registry (ie top up funds) can do so. + */ +contract ZKSyncAutomationForwarder { + error InvalidCaller(address); + + /// @notice the user's target contract address + address private immutable i_target; + + /// @notice the shared logic address + address private immutable i_logic; + + IAutomationRegistryConsumer private s_registry; + + constructor(address target, address registry, address logic) { + s_registry = IAutomationRegistryConsumer(registry); + i_target = target; + i_logic = logic; + } + + /** + * @notice forward is called by the registry and forwards the call to the target + * @param gasAmount is the amount of gas to use in the call + * @param data is the 4 bytes function selector + arbitrary function data + * @return success indicating whether the target call succeeded or failed + * @return gasUsed the total gas used from this forwarding call + */ + function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed) { + if (msg.sender != address(s_registry)) revert InvalidCaller(msg.sender); + + uint256 g1 = gasleft(); + address target = i_target; + + assembly { + let g := gas() + // Compute g -= PERFORM_GAS_CUSHION and check for underflow + if lt(g, PERFORM_GAS_CUSHION) { + revert(0, 0) + } + g := sub(g, PERFORM_GAS_CUSHION) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + } + + bytes memory returnData; + // solhint-disable-next-line avoid-low-level-calls + (success, returnData) = GAS_BOUND_CALLER.delegatecall{gas: gasAmount}( + abi.encodeWithSelector(IGasBoundCaller.gasBoundCall.selector, target, gasAmount, data) + ); + uint256 pubdataGasSpent; + if (success) { + (, pubdataGasSpent) = abi.decode(returnData, (bytes, uint256)); + } + gasUsed = g1 - gasleft() + pubdataGasSpent; + return (success, gasUsed); + } + + function getTarget() external view returns (address) { + return i_target; + } + + // solhint-disable-next-line no-complex-fallback + fallback() external payable { + // copy to memory for assembly access + address logic = i_logic; + // copied directly from OZ's Proxy contract + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), logic, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol new file mode 100644 index 0000000..2ad6fdd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {ChainModuleBase} from "./ChainModuleBase.sol"; + +contract ArbitrumModule is ChainModuleBase { + /// @dev ARB_SYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARB_SYS_ADDR = 0x0000000000000000000000000000000000000064; + ArbSys private constant ARB_SYS = ArbSys(ARB_SYS_ADDR); + + /// @dev ARB_GAS_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 ARB_GAS_ADDR = 0x000000000000000000000000000000000000006C; + ArbGasInfo private constant ARB_GAS = ArbGasInfo(ARB_GAS_ADDR); + + uint256 private constant FIXED_GAS_OVERHEAD = 5000; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; + + function blockHash(uint256 n) external view override returns (bytes32) { + uint256 blockNum = ARB_SYS.arbBlockNumber(); + if (n >= blockNum || blockNum - n > 256) { + return ""; + } + return ARB_SYS.arbBlockHash(n); + } + + function blockNumber() external view override returns (uint256) { + return ARB_SYS.arbBlockNumber(); + } + + function getCurrentL1Fee(uint256) external view override returns (uint256) { + return ARB_GAS.getCurrentTxL1GasFees(); + } + + function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + (, uint256 perL1CalldataByte, , , , ) = ARB_GAS.getPricesInWei(); + return perL1CalldataByte * dataSize; + } + + function getGasOverhead() + external + view + override + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol new file mode 100644 index 0000000..c595dbd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {IChainModule} from "../interfaces/IChainModule.sol"; + +contract ChainModuleBase is IChainModule { + uint256 private constant FIXED_GAS_OVERHEAD = 300; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; + + function blockNumber() external view virtual returns (uint256) { + return block.number; + } + + function blockHash(uint256 n) external view virtual returns (bytes32) { + if (n >= block.number || block.number - n > 256) { + return ""; + } + return blockhash(n); + } + + function getCurrentL1Fee(uint256) external view virtual returns (uint256 l1Fee) { + return 0; + } + + function getMaxL1Fee(uint256) external view virtual returns (uint256 maxL1Fee) { + return 0; + } + + function getGasOverhead() + external + view + virtual + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol new file mode 100644 index 0000000..7a46429 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import {ChainModuleBase} from "./ChainModuleBase.sol"; + +/** + * @notice This contract is deprecated. Please use OptimismModuleV2 which utilizes the most recent offerings from OP + * and can estimate L1 fee with much lower cost. + */ +contract OptimismModule is ChainModuleBase { + /// @dev OP_L1_DATA_FEE_PADDING includes 80 bytes for L1 data padding for Optimism and BASE + bytes private constant OP_L1_DATA_FEE_PADDING = + hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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 = 0x420000000000000000000000000000000000000F; + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + uint256 private constant FIXED_GAS_OVERHEAD = 60_000; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 270; + + // @dev This will be updated to use the new function introduced by OP team + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @dev this function uses the getL1Fee function in OP gas price oracle. it estimates the exact L1 fee but it costs + * a lot of gas to call. + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view 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); + return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, OP_L1_DATA_FEE_PADDING)); + } + + function getGasOverhead() + external + view + override + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol new file mode 100644 index 0000000..772b66c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; +import {ChainModuleBase} from "./ChainModuleBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +/** + * @notice OptimismModuleV2 provides a cost-efficient way to get L1 fee on OP stack. + * After EIP-4844 is implemented in OP stack, the new OP upgrade includes a new function getL1FeeUpperBound to estimate + * the upper bound of current transaction's L1 fee. + */ +contract OptimismModuleV2 is ChainModuleBase, ConfirmedOwner { + error InvalidL1FeeCoefficient(uint8 coefficient); + event L1FeeCoefficientSet(uint8 coefficient); + + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + /// @dev L1 fee coefficient is used to account for the impact of data compression on the l1 fee + /// getL1FeeUpperBound returns the upper bound of l1 fee so this configurable coefficient will help + /// charge a predefined percentage of the upper bound. + uint8 private s_l1FeeCoefficient = 100; + uint256 private constant FIXED_GAS_OVERHEAD = 28_000; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; + + constructor() ConfirmedOwner(msg.sender) {} + + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; + } + + function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @dev this function uses the newly provided getL1FeeUpperBound function in OP gas price oracle. this helps + * estimate L1 fee with much lower cost + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view returns (uint256) { + return OVM_GASPRICEORACLE.getL1FeeUpperBound(dataSize); + } + + function getGasOverhead() + external + pure + override + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } + + /* @notice this function sets a new coefficient for L1 fee estimation. + * @dev this function can only be invoked by contract owner + * @param coefficient the new coefficient + */ + function setL1FeeCalculation(uint8 coefficient) external onlyOwner { + if (coefficient > 100) { + revert InvalidL1FeeCoefficient(coefficient); + } + + s_l1FeeCoefficient = coefficient; + + emit L1FeeCoefficientSet(coefficient); + } + + /* @notice this function returns the s_l1FeeCoefficient + * @return coefficient the current s_l1FeeCoefficient in effect + */ + function getL1FeeCoefficient() public view returns (uint256 coefficient) { + return s_l1FeeCoefficient; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol new file mode 100644 index 0000000..30fdc90 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {IScrollL1GasPriceOracle} from "../../vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol"; +import {ChainModuleBase} from "./ChainModuleBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +contract ScrollModule is ChainModuleBase, ConfirmedOwner { + error InvalidL1FeeCoefficient(uint8 coefficient); + event L1FeeCoefficientSet(uint8 coefficient); + + /// @dev SCROLL_L1_FEE_DATA_PADDING includes 140 bytes for L1 data padding for Scroll + /// @dev according to testing, this padding allows automation registry to properly estimates L1 data fee with 3-5% buffer + /// @dev this MAY NOT work for a different product and this may get out of date if transmit function is changed + bytes private constant SCROLL_L1_FEE_DATA_PADDING = + hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + /// @dev SCROLL_ORACLE_ADDR is the address of the ScrollL1GasPriceOracle precompile on Scroll. + /// @dev reference: https://docs.scroll.io/en/developers/transaction-fees-on-scroll/#estimating-the-l1-data-fee + address private constant SCROLL_ORACLE_ADDR = 0x5300000000000000000000000000000000000002; + IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR); + + /// @dev L1 fee coefficient can be applied to reduce possibly inflated gas cost + uint8 private s_l1FeeCoefficient = 100; + uint256 private constant FIXED_GAS_OVERHEAD = 45_000; + uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 170; + + constructor() ConfirmedOwner(msg.sender) {} + + function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { + return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; + } + + function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { + return _getL1Fee(dataSize); + } + + /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size + * @param dataSize the size of calldata + * @return l1Fee the L1 fee + */ + function _getL1Fee(uint256 dataSize) internal view returns (uint256 l1Fee) { + // 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. + 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) + { + return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); + } + + /* @notice this function sets a new coefficient for L1 fee estimation. + * @dev this function can only be invoked by contract owner + * @param coefficient the new coefficient + */ + function setL1FeeCalculation(uint8 coefficient) external onlyOwner { + if (coefficient > 100) { + revert InvalidL1FeeCoefficient(coefficient); + } + + s_l1FeeCoefficient = coefficient; + + emit L1FeeCoefficientSet(coefficient); + } + + /* @notice this function returns the s_l1FeeCoefficient + * @return coefficient the current s_l1FeeCoefficient in effect + */ + function getL1FeeCoefficient() public view returns (uint256 coefficient) { + return s_l1FeeCoefficient; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol new file mode 100644 index 0000000..247301a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol @@ -0,0 +1,320 @@ +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; + +/*--------------------------------------------------------------------------------------------------------------------+ +| Mercury + Automation | +| ________________ | +| This implementation allows for an on-chain registry of price feed data to be maintained and updated by Automation | +| nodes. The upkeep provides the following advantages: | +| - Node operator savings. The single committee of automation nodes is able to update all price feed data using | +| off-chain feed data. | +| - Fetch batches of price data. All price feed data is held on the same contract, so a contract that needs | +| multiple sets of feed data can fetch them while paying for only one external call. | +| - Scalability. Feeds can be added or removed from the contract with a single contract call, and the number of | +| feeds that the registry can store is unbounded. | +| | +| Key Contracts: | +| - `MercuryRegistry.sol` - stores price feed data and implements core logic. | +| - `MercuryRegistryBatchUpkeep.sol` - enables batching for the registry. | +| - `MercuryRegistry.t.sol` - contains foundry tests to demonstrate various flows. | +| | +| NOTE: This contract uses Mercury v0.2. Automation will likely upgrade to v0.3 eventually, which may change some | +| components such as the Report struct, verification, and the StreamsLookup revert. | +| | +| TODO: | +| - Optimize gas consumption. | +-+---------------------------------------------------------------------------------------------------------------------*/ +contract MercuryRegistry is ConfirmedOwner, AutomationCompatibleInterface, StreamsLookupCompatibleInterface { + error DuplicateFeed(string feedId); + error FeedNotActive(string feedId); + error StaleReport(string feedId, uint32 currentTimestamp, uint32 incomingTimestamp); + error InvalidFeeds(); + + // Feed object used for storing feed data. + // not included but contained in reports: + // - blocknumberUpperBound + // - upperBlockhash + // - blocknumberLowerBound + // - currentBlockTimestamp + struct Feed { + uint32 observationsTimestamp; // the timestamp of the most recent data assigned to this feed + int192 price; // the current price of the feed + int192 bid; // the current bid price of the feed + int192 ask; // the current ask price of the feed + string feedName; // the name of the feed + string feedId; // the id of the feed (hex encoded) + bool active; // true if the feed is being actively updated, otherwise false + int192 deviationPercentagePPM; // acceptable deviation threshold - 1.5% = 15_000, 100% = 1_000_000, etc.. + uint32 stalenessSeconds; // acceptable staleness threshold - 60 = 1 minute, 300 = 5 minutes, etc.. + } + + // Report object obtained from off-chain Mercury server. + struct Report { + bytes32 feedId; // the feed Id of the report + uint32 observationsTimestamp; // the timestamp of when the data was observed + int192 price; // the median value of the OCR round + int192 bid; // the median bid of the OCR round + int192 ask; // the median ask if the OCR round + uint64 blocknumberUpperBound; // the highest block observed at the time the report was generated + bytes32 upperBlockhash; // the blockhash of the highest block observed + uint64 blocknumberLowerBound; // the lowest block observed at the time the report was generated + uint64 currentBlockTimestamp; // the timestamp of the highest block observed + } + + event FeedUpdated(uint32 observationsTimestamp, int192 price, int192 bid, int192 ask, string feedId); + + uint32 private constant MIN_GAS_FOR_PERFORM = 200_000; + + string private constant FEED_PARAM_KEY = "feedIdHex"; // for Mercury v0.2 - format by which feeds are identified + string private constant TIME_PARAM_KEY = "blockNumber"; // for Mercury v0.2 - format by which feeds are filtered to be sufficiently recent + IVerifierProxy public s_verifier; // for Mercury v0.2 - verifies off-chain reports + + int192 private constant SCALE = 1_000_000; // a scalar used for measuring deviation with precision + + string[] public s_feeds; // list of feed Ids + mapping(string => Feed) public s_feedMapping; // mapping of feed Ids to stored feed data + + constructor( + string[] memory feedIds, + string[] memory feedNames, + int192[] memory deviationPercentagePPMs, + uint32[] memory stalenessSeconds, + address verifier + ) ConfirmedOwner(msg.sender) { + s_verifier = IVerifierProxy(verifier); + + // Store desired feeds. + setFeeds(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds); + } + + // Returns a user-defined batch of feed data, based on the on-chain state. + function getLatestFeedData(string[] memory feedIds) external view returns (Feed[] memory) { + Feed[] memory feeds = new Feed[](feedIds.length); + for (uint256 i = 0; i < feedIds.length; i++) { + feeds[i] = s_feedMapping[feedIds[i]]; + } + + return feeds; + } + + // Invoke a feed lookup through the checkUpkeep function. Expected to run on a cron schedule. + function checkUpkeep(bytes calldata /* data */) external view override returns (bool, bytes memory) { + string[] memory feeds = s_feeds; + return revertForFeedLookup(feeds); + } + + // Extracted from `checkUpkeep` for batching purposes. + function revertForFeedLookup(string[] memory feeds) public view returns (bool, bytes memory) { + uint256 blockNumber = ChainSpecificUtil._getBlockNumber(); + revert StreamsLookup(FEED_PARAM_KEY, feeds, TIME_PARAM_KEY, blockNumber, ""); + } + + // Filter for feeds that have deviated sufficiently from their respective on-chain values, or where + // the on-chain values are sufficiently stale. + function checkCallback( + bytes[] memory values, + bytes memory lookupData + ) external view override returns (bool, bytes memory) { + bytes[] memory filteredValues = new bytes[](values.length); + uint256 count = 0; + for (uint256 i = 0; i < values.length; i++) { + Report memory report = _getReport(values[i]); + string memory feedId = _bytes32ToHexString(abi.encodePacked(report.feedId)); + Feed memory feed = s_feedMapping[feedId]; + if ( + (report.observationsTimestamp - feed.observationsTimestamp > feed.stalenessSeconds) || + deviationExceedsThreshold(feed.price, report.price, feed.deviationPercentagePPM) + ) { + filteredValues[count] = values[i]; + count++; + } + } + + // Adjusts the length of the filteredValues array to `count` such that it + // does not have extra empty slots, in case some items were filtered. + assembly { + mstore(filteredValues, count) + } + + bytes memory performData = abi.encode(filteredValues, lookupData); + return (filteredValues.length > 0, performData); + } + + function checkErrorHandler( + uint256 /* errCode */, + bytes memory /* extraData */ + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (false, new bytes(0)); + } + + // Use deviated off-chain values to update on-chain state. + function performUpkeep(bytes calldata performData) external override { + (bytes[] memory values /* bytes memory lookupData */, ) = abi.decode(performData, (bytes[], bytes)); + for (uint256 i = 0; i < values.length; i++) { + // Verify and decode the Mercury report. + Report memory report = abi.decode(s_verifier.verify(values[i]), (Report)); + string memory feedId = _bytes32ToHexString(abi.encodePacked(report.feedId)); + + // Feeds that have been removed between checkUpkeep and performUpkeep should not be updated. + if (!s_feedMapping[feedId].active) { + revert FeedNotActive(feedId); + } + + // Ensure stale reports do not cause a regression in the registry. + if (s_feedMapping[feedId].observationsTimestamp > report.observationsTimestamp) { + revert StaleReport(feedId, s_feedMapping[feedId].observationsTimestamp, report.observationsTimestamp); + } + + // Assign new values to state. + s_feedMapping[feedId].bid = report.bid; + s_feedMapping[feedId].ask = report.ask; + s_feedMapping[feedId].price = report.price; + s_feedMapping[feedId].observationsTimestamp = report.observationsTimestamp; + + // Emit log. + emit FeedUpdated(report.observationsTimestamp, report.price, report.bid, report.ask, feedId); + + // Ensure enough gas remains for the next iteration. Otherwise, stop here. + if (gasleft() < MIN_GAS_FOR_PERFORM) { + return; + } + } + } + + // Decodes a mercury respone into an on-chain object. Thanks @mikestone!! + function _getReport(bytes memory signedReport) internal pure returns (Report memory) { + /* + * bytes32[3] memory reportContext, + * bytes memory reportData, + * bytes32[] memory rs, + * bytes32[] memory ss, + * bytes32 rawVs + **/ + (, bytes memory reportData, , , ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); + + Report memory report = abi.decode(reportData, (Report)); + return report; + } + + // Check if the off-chain value has deviated sufficiently from the on-chain value to justify an update. + // `scale` is used to ensure precision is not lost. + function deviationExceedsThreshold( + int192 onChain, + int192 offChain, + int192 deviationPercentagePPM + ) public pure returns (bool) { + // Compute absolute difference between the on-chain and off-chain values. + int192 scaledDifference = (onChain - offChain) * SCALE; + if (scaledDifference < 0) { + scaledDifference = -scaledDifference; + } + + // Compare to the allowed deviation from the on-chain value. + int192 deviationMax = ((onChain * SCALE) * deviationPercentagePPM) / SCALE; + return scaledDifference > deviationMax; + } + + // Helper function to reconcile a difference in formatting: + // - Automation passes feedId into their off-chain lookup function as a string. + // - Mercury stores feedId in their reports as a bytes32. + function _bytes32ToHexString(bytes memory buffer) internal pure returns (string memory) { + bytes memory converted = new bytes(buffer.length * 2); + bytes memory _base = "0123456789abcdef"; + for (uint256 i = 0; i < buffer.length; i++) { + converted[i * 2] = _base[uint8(buffer[i]) / _base.length]; + converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length]; + } + return string(abi.encodePacked("0x", converted)); + } + + function addFeeds( + string[] memory feedIds, + string[] memory feedNames, + int192[] memory deviationPercentagePPMs, + uint32[] memory stalenessSeconds + ) external onlyOwner feedsAreValid(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds) { + for (uint256 i = 0; i < feedIds.length; i++) { + string memory feedId = feedIds[i]; + if (s_feedMapping[feedId].active) { + revert DuplicateFeed(feedId); + } + _updateFeed(feedId, feedNames[i], deviationPercentagePPMs[i], stalenessSeconds[i]); + s_feedMapping[feedId].active = true; + + s_feeds.push(feedId); + } + } + + function setFeeds( + string[] memory feedIds, + string[] memory feedNames, + int192[] memory deviationPercentagePPMs, + uint32[] memory stalenessSeconds + ) public onlyOwner feedsAreValid(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds) { + // Clear prior feeds. + for (uint256 i = 0; i < s_feeds.length; i++) { + s_feedMapping[s_feeds[i]].active = false; + } + + // Assign new feeds. + for (uint256 i = 0; i < feedIds.length; i++) { + string memory feedId = feedIds[i]; + if (s_feedMapping[feedId].active) { + revert DuplicateFeed(feedId); + } + _updateFeed(feedId, feedNames[i], deviationPercentagePPMs[i], stalenessSeconds[i]); + s_feedMapping[feedId].active = true; + } + s_feeds = feedIds; + } + + function _updateFeed( + string memory feedId, + string memory feedName, + int192 deviationPercentagePPM, + uint32 stalnessSeconds + ) internal { + s_feedMapping[feedId].feedName = feedName; + s_feedMapping[feedId].deviationPercentagePPM = deviationPercentagePPM; + s_feedMapping[feedId].stalenessSeconds = stalnessSeconds; + s_feedMapping[feedId].feedId = feedId; + } + + function setVerifier(address verifier) external onlyOwner { + s_verifier = IVerifierProxy(verifier); + } + + modifier feedsAreValid( + string[] memory feedIds, + string[] memory feedNames, + int192[] memory deviationPercentagePPMs, + uint32[] memory stalenessSeconds + ) { + if (feedIds.length != feedNames.length) { + revert InvalidFeeds(); + } + if (feedIds.length != deviationPercentagePPMs.length) { + revert InvalidFeeds(); + } + if (feedIds.length != stalenessSeconds.length) { + revert InvalidFeeds(); + } + _; + } +} + +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payload The encoded data to be verified, including the signed + * report and any metadata for billing. + * @return verifiedReport The encoded report from the verifier. + */ + function verify(bytes calldata payload) external payable returns (bytes memory verifiedReport); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol new file mode 100644 index 0000000..2d3daea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol @@ -0,0 +1,88 @@ +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {MercuryRegistry} from "./MercuryRegistry.sol"; + +contract MercuryRegistryBatchUpkeep is ConfirmedOwner, AutomationCompatibleInterface, StreamsLookupCompatibleInterface { + error BatchSizeTooLarge(uint256 batchsize, uint256 maxBatchSize); + // Use a reasonable maximum batch size. Every Mercury report is ~750 bytes, too many reports + // passed into a single batch could exceed the calldata or transaction size limit for some blockchains. + uint256 public constant MAX_BATCH_SIZE = 50; + + MercuryRegistry public immutable i_registry; // master registry, where feed data is stored + + uint256 public s_batchStart; // starting index of upkeep batch on the MercuryRegistry's s_feeds array, inclusive + uint256 public s_batchEnd; // ending index of upkeep batch on the MercuryRegistry's s_feeds array, exclusive + + constructor(address mercuryRegistry, uint256 batchStart, uint256 batchEnd) ConfirmedOwner(msg.sender) { + i_registry = MercuryRegistry(mercuryRegistry); + + updateBatchingWindow(batchStart, batchEnd); + } + + // Invoke a feed lookup for the feeds this upkeep is responsible for. + function checkUpkeep(bytes calldata /* data */) external view override returns (bool, bytes memory) { + uint256 start = s_batchStart; + uint256 end = s_batchEnd; + string[] memory feeds = new string[](end - start); + uint256 count = 0; + for (uint256 i = start; i < end; i++) { + string memory feedId; + + // If the feed doesn't exist, then the batching window exceeds the underlying registry length. + // So, the batch will be partially empty. + try i_registry.s_feeds(i) returns (string memory f) { + feedId = f; + } catch (bytes memory /* data */) { + break; + } + + // Assign feed. + feeds[i - start] = feedId; + count++; + } + + // Adjusts the length of the batch to `count` such that it does not + // contain any empty feed Ids. + assembly { + mstore(feeds, count) + } + + return i_registry.revertForFeedLookup(feeds); + } + + // Use the master registry to assess deviations. + function checkCallback( + bytes[] memory values, + bytes memory lookupData + ) external view override returns (bool, bytes memory) { + return i_registry.checkCallback(values, lookupData); + } + + function checkErrorHandler( + uint256 /* errCode */, + bytes memory /* extraData */ + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (false, new bytes(0)); + } + + // Use the master registry to update state. + function performUpkeep(bytes calldata performData) external override { + i_registry.performUpkeep(performData); + } + + function updateBatchingWindow(uint256 batchStart, uint256 batchEnd) public onlyOwner { + // Do not allow a batched mercury registry to use an excessive batch size, as to avoid + // calldata size limits. If more feeds need to be updated than allowed by the batch size, + // deploy another `MercuryRegistryBatchUpkeep` contract and register another upkeep job. + if (batchEnd - batchStart > MAX_BATCH_SIZE) { + revert BatchSizeTooLarge(batchEnd - batchStart, MAX_BATCH_SIZE); + } + + s_batchStart = batchStart; + s_batchEnd = batchEnd; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol new file mode 100644 index 0000000..ae92082 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface AutomationCompatibleInterface { + /** + * @notice method that is simulated by the keepers to see if any work actually + * needs to be performed. This method does does not actually need to be + * executable, and since it is only ever simulated it can consume lots of gas. + * @dev To ensure that it is never called, you may want to add the + * cannotExecute modifier from KeeperBase to your implementation of this + * method. + * @param checkData specified in the upkeep registration so it is always the + * same for a registered upkeep. This can easily be broken down into specific + * arguments using `abi.decode`, so multiple upkeeps can be registered on the + * same contract and easily differentiated by the contract. + * @return upkeepNeeded boolean to indicate whether the keeper should call + * performUpkeep or not. + * @return performData bytes that the keeper should call performUpkeep with, if + * upkeep is needed. If you would like to encode data to decode later, try + * `abi.encode`. + */ + function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); + + /** + * @notice method that is actually executed by the keepers, via the registry. + * The data returned by the checkUpkeep simulation will be passed into + * this method to actually be executed. + * @dev The input to this method should not be trusted, and the caller of the + * method should not even be restricted to any single registry. Anyone should + * be able call it, and the input should be validated, there is no guarantee + * that the data passed in is the performData returned from checkUpkeep. This + * could happen due to malicious keepers, racing keepers, or simply a state + * change while the performUpkeep transaction is waiting for confirmation. + * Always validate the data passed in. + * @param performData is the data which was passed back from the checkData + * simulation. If it is encoded, it can easily be decoded into other types by + * calling `abi.decode`. This data should not be trusted, and should be + * validated against the contract's current state. + */ + function performUpkeep(bytes calldata performData) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol new file mode 100644 index 0000000..0a53de6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IAutomationRegistryConsumer} from "./IAutomationRegistryConsumer.sol"; + +interface IAutomationForwarder is ITypeAndVersion { + function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed); + + function updateRegistry(address newRegistry) external; + + function getRegistry() external view returns (IAutomationRegistryConsumer); + + function getTarget() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol new file mode 100644 index 0000000..bea3e95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/** + * @notice IAutomationRegistryConsumer defines the LTS user-facing interface that we intend to maintain for + * across upgrades. As long as users use functions from within this interface, their upkeeps will retain + * backwards compatability across migrations. + * @dev Functions can be added to this interface, but not removed. + */ +interface IAutomationRegistryConsumer { + function getBalance(uint256 id) external view returns (uint96 balance); + + function getMinBalance(uint256 id) external view returns (uint96 minBalance); + + function cancelUpkeep(uint256 id) external; + + function pauseUpkeep(uint256 id) external; + + function unpauseUpkeep(uint256 id) external; + + function addFunds(uint256 id, uint96 amount) external; + + function withdrawFunds(uint256 id, address to) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol new file mode 100644 index 0000000..6e3d0d7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; + +interface IAutomationV21PlusCommon { + // registry events + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event OwnershipTransferred(address indexed from, address indexed to); + event OwnershipTransferRequested(address indexed from, address indexed to); + event Paused(address account); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeesUpdated(address[] transmitters, address[] payees); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + + // upkeep events + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + + /** + * @notice structure of trigger for log triggers + */ + struct LogTriggerConfig { + address contractAddress; + uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply + bytes32 topic0; + bytes32 topic1; + bytes32 topic2; + bytes32 topic3; + } + + /// @dev Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkNative; + uint256[] upkeepIds; + uint256[] gasLimits; + bytes[] triggers; + bytes[] performDatas; + } + + /** + * @notice all information about an upkeep + * @dev only used in return values + * @dev this will likely be deprecated in a future version of the registry + * @member target the contract which needs to be serviced + * @member performGas the gas limit of upkeep execution + * @member checkData the checkData bytes for this upkeep + * @member balance the balance of this upkeep + * @member admin for this upkeep + * @member maxValidBlocknumber until which block this upkeep is valid + * @member lastPerformedBlockNumber the last block number when this upkeep was performed + * @member amountSpent the amount this upkeep has spent + * @member paused if this upkeep has been paused + * @member offchainConfig the off-chain config of this upkeep + */ + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } + + /** + * @notice the trigger structure conditional trigger type + */ + struct ConditionalTrigger { + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the trigger structure of log upkeeps + * @dev NOTE that blockNum / blockHash describe the block used for the callback, + * not necessarily the block number that the log was emitted in!!!! + */ + struct LogTrigger { + bytes32 logBlockHash; + bytes32 txHash; + uint32 logIndex; + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice state of the registry + * @dev only used in params and return values + * @dev this will likely be deprecated in a future version of the registry in favor of individual getters + * @member nonce used for ID generation + * @member ownerLinkBalance withdrawable balance of LINK by contract owner + * @member expectedLinkBalance the expected balance of LINK of the registry + * @member totalPremium the total premium collected on registry so far + * @member numUpkeeps total number of upkeeps on the registry + * @member configCount ordinal number of current config, out of all configs applied to this contract so far + * @member latestConfigBlockNumber last block at which this config was set + * @member latestConfigDigest domain-separation tag for current config + * @member latestEpoch for which a report was transmitted + * @member paused freeze on execution scoped to the entire registry + */ + // solhint-disable-next-line gas-struct-packing + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + /** + * @notice OnchainConfigLegacy of the registry + * @dev only used in params and return values + * @member paymentPremiumPPB payment premium rate oracles receive on top of + * being reimbursed for gas, measured in parts per billion + * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, + * priced in MicroLink; can be used in conjunction with or independently of + * paymentPremiumPPB + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling + * @member maxPerformGas max performGas allowed for an upkeep on this registry + * @member maxCheckDataSize max length of checkData bytes + * @member maxPerformDataSize max length of performData bytes + * @member maxRevertDataSize max length of revertData bytes + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrars addresses of the registrar contracts + * @member upkeepPrivilegeManager address which can set privilege for upkeeps + */ + // solhint-disable-next-line gas-struct-packing + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function typeAndVersion() external view returns (string memory); + function addFunds(uint256 id, uint96 amount) external; + function cancelUpkeep(uint256 id) external; + + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeep(uint256 id) external view returns (UpkeepInfoLegacy memory upkeepInfo); + function getMinBalance(uint256 id) external view returns (uint96); + function getState() + external + view + returns ( + StateLegacy memory state, + OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function pauseUpkeep(uint256 id) external; + function unpauseUpkeep(uint256 id) external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function pause() external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + function owner() external view returns (address); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol new file mode 100644 index 0000000..15e84f7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +interface IChainModule { + /* @notice this function provides the block number of current chain. + * @dev certain chains have its own function to retrieve block number, e.g. Arbitrum + * @return blockNumber the block number of the current chain. + */ + function blockNumber() external view returns (uint256 blockNumber); + + /* @notice this function provides the block hash of a block number. + * @dev this function can usually look back 256 blocks at most, unless otherwise specified + * @param blockNumber the block number + * @return blockHash the block hash of the input block number + */ + function blockHash(uint256 blockNumber) external view returns (bytes32 blockHash); + + /* @notice this function provides the L1 fee of current transaction. + * @dev retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should + * return 0 for L2 chains if they don't have L1 fee component. + * @param dataSize the calldata size of the current transaction + * @return l1Fee the L1 fee in wei incurred by calldata of this data size + */ + function getCurrentL1Fee(uint256 dataSize) external view returns (uint256 l1Fee); + + /* @notice this function provides the max possible L1 fee of current transaction. + * @dev retrieve the max possible L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should + * return 0 for L2 chains if they don't have L1 fee component. + * @param dataSize the calldata size of the current transaction + * @return maxL1Fee the max possible L1 fee in wei incurred by calldata of this data size + */ + function getMaxL1Fee(uint256 dataSize) external view returns (uint256 maxL1Fee); + + /* @notice this function provides the overheads of calling this chain module. + * @return chainModuleFixedOverhead the fixed overhead incurred by calling this chain module + * @return chainModulePerByteOverhead the fixed overhead per byte incurred by calling this chain module with calldata + */ + function getGasOverhead() + external + view + returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol new file mode 100644 index 0000000..20a41f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @member index the index of the log in the block. 0 for the first log + * @member timestamp the timestamp of the block containing the log + * @member txHash the hash of the transaction containing the log + * @member blockNumber the number of the block containing the log + * @member blockHash the hash of the block containing the log + * @member source the address of the contract that emitted the log + * @member topics the indexed topics of the log + * @member data the data of the log + */ +struct Log { + uint256 index; + uint256 timestamp; + bytes32 txHash; + uint256 blockNumber; + bytes32 blockHash; + address source; + bytes32[] topics; + bytes data; +} + +interface ILogAutomation { + /** + * @notice method that is simulated by the keepers to see if any work actually + * needs to be performed. This method does does not actually need to be + * executable, and since it is only ever simulated it can consume lots of gas. + * @dev To ensure that it is never called, you may want to add the + * cannotExecute modifier from KeeperBase to your implementation of this + * method. + * @param log the raw log data matching the filter that this contract has + * registered as a trigger + * @param checkData user-specified extra data to provide context to this upkeep + * @return upkeepNeeded boolean to indicate whether the keeper should call + * performUpkeep or not. + * @return performData bytes that the keeper should call performUpkeep with, if + * upkeep is needed. If you would like to encode data to decode later, try + * `abi.encode`. + */ + function checkLog( + Log calldata log, + bytes memory checkData + ) external returns (bool upkeepNeeded, bytes memory performData); + + /** + * @notice method that is actually executed by the keepers, via the registry. + * The data returned by the checkUpkeep simulation will be passed into + * this method to actually be executed. + * @dev The input to this method should not be trusted, and the caller of the + * method should not even be restricted to any single registry. Anyone should + * be able call it, and the input should be validated, there is no guarantee + * that the data passed in is the performData returned from checkUpkeep. This + * could happen due to malicious keepers, racing keepers, or simply a state + * change while the performUpkeep transaction is waiting for confirmation. + * Always validate the data passed in. + * @param performData is the data which was passed back from the checkData + * simulation. If it is encoded, it can easily be decoded into other types by + * calling `abi.decode`. This data should not be trusted, and should be + * validated against the contract's current state. + */ + function performUpkeep(bytes calldata performData) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol new file mode 100644 index 0000000..b5ba819 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +/** + * @notice This is a deprecated interface. Please use AutomationCompatibleInterface directly. + */ +pragma solidity ^0.8.0; +// solhint-disable-next-line no-unused-import +import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./AutomationCompatibleInterface.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol new file mode 100644 index 0000000..d279d93 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../UpkeepFormat.sol"; + +interface MigratableKeeperRegistryInterface { + /** + * @notice Migrates upkeeps from one registry to another, including LINK and upkeep params. + * Only callable by the upkeep admin. All upkeeps must have the same admin. Can only migrate active upkeeps. + * @param upkeepIDs ids of upkeeps to migrate + * @param destination the address of the registry to migrate to + */ + function migrateUpkeeps(uint256[] calldata upkeepIDs, address destination) external; + + /** + * @notice Called by other registries when migrating upkeeps. Only callable by other registries. + * @param encodedUpkeeps abi encoding of upkeeps to import - decoded by the transcoder + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external; + + /** + * @notice Specifies the version of upkeep data that this registry requires in order to import + */ + function upkeepTranscoderVersion() external view returns (UpkeepFormat version); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol new file mode 100644 index 0000000..d6dcc03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface MigratableKeeperRegistryInterfaceV2 { + /** + * @notice Migrates upkeeps from one registry to another, including LINK and upkeep params. + * Only callable by the upkeep admin. All upkeeps must have the same admin. Can only migrate active upkeeps. + * @param upkeepIDs ids of upkeeps to migrate + * @param destination the address of the registry to migrate to + */ + function migrateUpkeeps(uint256[] calldata upkeepIDs, address destination) external; + + /** + * @notice Called by other registries when migrating upkeeps. Only callable by other registries. + * @param encodedUpkeeps abi encoding of upkeeps to import - decoded by the transcoder + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external; + + /** + * @notice Specifies the version of upkeep data that this registry requires in order to import + */ + function upkeepVersion() external view returns (uint8 version); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol new file mode 100644 index 0000000..ed873a0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface StreamsLookupCompatibleInterface { + error StreamsLookup(string feedParamKey, string[] feeds, string timeParamKey, uint256 time, bytes extraData); + + /** + * @notice any contract which wants to utilize StreamsLookup feature needs to + * implement this interface as well as the automation compatible interface. + * @param values an array of bytes returned from data streams endpoint. + * @param extraData context data from streams lookup process. + * @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not. + * @return performData bytes that the keeper should call performUpkeep with, if + * upkeep is needed. If you would like to encode data to decode later, try `abi.encode`. + */ + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData); + + /** + * @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors. + * @param errCode an uint value that represents the streams lookup error code. + * @param extraData context data from streams lookup process. + * @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not. + * @return performData bytes that the keeper should call performUpkeep with, if + * upkeep is needed. If you would like to encode data to decode later, try `abi.encode`. + */ + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol new file mode 100644 index 0000000..59d2bb4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {UpkeepFormat} from "../UpkeepFormat.sol"; + +// solhint-disable-next-line interface-starts-with-i +interface UpkeepTranscoderInterface { + function transcodeUpkeeps( + UpkeepFormat fromVersion, + UpkeepFormat toVersion, + bytes calldata encodedUpkeeps + ) external view returns (bytes memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol new file mode 100644 index 0000000..95dc307 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface UpkeepTranscoderInterfaceV2 { + function transcodeUpkeeps( + uint8 fromVersion, + uint8 toVersion, + bytes calldata encodedUpkeeps + ) external view returns (bytes memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol new file mode 100644 index 0000000..eb35589 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @notice config of the registry + * @dev only used in params and return values + * @member paymentPremiumPPB payment premium rate oracles receive on top of + * being reimbursed for gas, measured in parts per billion + * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, + * priced in MicroLink; can be used in conjunction with or independently of + * paymentPremiumPPB + * @member blockCountPerTurn number of blocks each oracle has during their turn to + * perform upkeep before it will be the next keeper's turn to submit + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling + * @member maxPerformGas max executeGas allowed for an upkeep on this registry + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrar address of the registrar contract + */ +struct Config { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK + uint24 blockCountPerTurn; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address registrar; +} + +/** + * @notice state of the registry + * @dev only used in params and return values + * @member nonce used for ID generation + * @member ownerLinkBalance withdrawable balance of LINK by contract owner + * @member expectedLinkBalance the expected balance of LINK of the registry + * @member numUpkeeps total number of upkeeps on the registry + */ +struct State { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint256 numUpkeeps; +} + +interface AutomationRegistryBaseInterface { + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData + ) external returns (uint256 id); + + function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success); + + function cancelUpkeep(uint256 id) external; + + function addFunds(uint256 id, uint96 amount) external; + + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + + function getUpkeep( + uint256 id + ) + external + view + returns ( + address target, + uint32 executeGas, + bytes memory checkData, + uint96 balance, + address lastKeeper, + address admin, + uint64 maxValidBlocknumber, + uint96 amountSpent + ); + + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + + function getKeeperInfo(address query) external view returns (address payee, bool active, uint96 balance); + + function getState() external view returns (State memory, Config memory, address[] memory); +} + +/** + * @dev The view methods are not actually marked as view in the implementation + * but we want them to be easily queried off-chain. Solidity will not compile + * if we actually inherit from this interface, so we document it here. + */ +interface AutomationRegistryInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId, + address from + ) + external + view + returns (bytes memory performData, uint256 maxLinkPayment, uint256 gasLimit, int256 gasWei, int256 linkEth); +} + +interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId, + address from + ) + external + returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol new file mode 100644 index 0000000..01f70ae --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +/** + * @notice This is a deprecated interface. Please use AutomationRegistryInterface1_2 directly. + */ +pragma solidity ^0.8.0; +// solhint-disable-next-line no-unused-import +import {Config, State} from "./AutomationRegistryInterface1_2.sol"; +// solhint-disable-next-line no-unused-import +import {AutomationRegistryBaseInterface as KeeperRegistryBaseInterface} from "./AutomationRegistryInterface1_2.sol"; +// solhint-disable-next-line no-unused-import +import {AutomationRegistryInterface as KeeperRegistryInterface} from "./AutomationRegistryInterface1_2.sol"; +// solhint-disable-next-line no-unused-import +import {AutomationRegistryExecutableInterface as KeeperRegistryExecutableInterface} from "./AutomationRegistryInterface1_2.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol new file mode 100644 index 0000000..d41a869 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @notice config of the registry + * @dev only used in params and return values + * @member paymentPremiumPPB payment premium rate oracles receive on top of + * being reimbursed for gas, measured in parts per billion + * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, + * priced in MicroLink; can be used in conjunction with or independently of + * paymentPremiumPPB + * @member blockCountPerTurn number of blocks each oracle has during their turn to + * perform upkeep before it will be the next keeper's turn to submit + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling + * @member maxPerformGas max executeGas allowed for an upkeep on this registry + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrar address of the registrar contract + */ +struct Config { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK + uint24 blockCountPerTurn; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address registrar; +} + +/** + * @notice state of the registry + * @dev only used in params and return values + * @member nonce used for ID generation + * @member ownerLinkBalance withdrawable balance of LINK by contract owner + * @member expectedLinkBalance the expected balance of LINK of the registry + * @member numUpkeeps total number of upkeeps on the registry + */ +struct State { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint256 numUpkeeps; +} + +/** + * @notice relevant state of an upkeep + * @member balance the balance of this upkeep + * @member lastKeeper the keeper which last performs the upkeep + * @member executeGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member target the contract which needs to be serviced + * @member amountSpent the amount this upkeep has spent + * @member admin the upkeep admin + * @member paused if this upkeep has been paused + */ +struct Upkeep { + uint96 balance; + address lastKeeper; // 1 full evm word + uint96 amountSpent; + address admin; // 2 full evm words + uint32 executeGas; + uint32 maxValidBlocknumber; + address target; + bool paused; // 24 bits to 3 full evm words +} + +interface AutomationRegistryBaseInterface { + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData + ) external returns (uint256 id); + + function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success); + + function cancelUpkeep(uint256 id) external; + + function pauseUpkeep(uint256 id) external; + + function unpauseUpkeep(uint256 id) external; + + function transferUpkeepAdmin(uint256 id, address proposed) external; + + function acceptUpkeepAdmin(uint256 id) external; + + function updateCheckData(uint256 id, bytes calldata newCheckData) external; + + function addFunds(uint256 id, uint96 amount) external; + + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + + function getUpkeep( + uint256 id + ) + external + view + returns ( + address target, + uint32 executeGas, + bytes memory checkData, + uint96 balance, + address lastKeeper, + address admin, + uint64 maxValidBlocknumber, + uint96 amountSpent, + bool paused + ); + + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + + function getKeeperInfo(address query) external view returns (address payee, bool active, uint96 balance); + + function getState() external view returns (State memory, Config memory, address[] memory); +} + +/** + * @dev The view methods are not actually marked as view in the implementation + * but we want them to be easily queried off-chain. Solidity will not compile + * if we actually inherit from this interface, so we document it here. + */ +interface AutomationRegistryInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId, + address from + ) + external + view + returns (bytes memory performData, uint256 maxLinkPayment, uint256 gasLimit, int256 gasWei, int256 linkEth); +} + +interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId, + address from + ) + external + returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol new file mode 100644 index 0000000..cfc9ab8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @notice OnchainConfig of the registry + * @dev only used in params and return values + * @member paymentPremiumPPB payment premium rate oracles receive on top of + * being reimbursed for gas, measured in parts per billion + * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, + * priced in MicroLink; can be used in conjunction with or independently of + * paymentPremiumPPB + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling + * @member maxPerformGas max executeGas allowed for an upkeep on this registry + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrar address of the registrar contract + */ +struct OnchainConfig { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address registrar; +} + +/** + * @notice state of the registry + * @dev only used in params and return values + * @member nonce used for ID generation + * @member ownerLinkBalance withdrawable balance of LINK by contract owner + * @member expectedLinkBalance the expected balance of LINK of the registry + * @member totalPremium the total premium collected on registry so far + * @member numUpkeeps total number of upkeeps on the registry + * @member configCount ordinal number of current config, out of all configs applied to this contract so far + * @member latestConfigBlockNumber last block at which this config was set + * @member latestConfigDigest domain-separation tag for current config + * @member latestEpoch for which a report was transmitted + * @member paused freeze on execution scoped to the entire registry + */ +struct State { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; +} + +/** + * @notice all information about an upkeep + * @dev only used in return values + * @member target the contract which needs to be serviced + * @member executeGas the gas limit of upkeep execution + * @member checkData the checkData bytes for this upkeep + * @member balance the balance of this upkeep + * @member admin for this upkeep + * @member maxValidBlocknumber until which block this upkeep is valid + * @member lastPerformBlockNumber the last block number when this upkeep was performed + * @member amountSpent the amount this upkeep has spent + * @member paused if this upkeep has been paused + * @member skipSigVerification skip signature verification in transmit for a low security low cost model + */ +struct UpkeepInfo { + address target; + uint32 executeGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; +} + +enum UpkeepFailureReason { + NONE, + UPKEEP_CANCELLED, + UPKEEP_PAUSED, + TARGET_CHECK_REVERTED, + UPKEEP_NOT_NEEDED, + PERFORM_DATA_EXCEEDS_LIMIT, + INSUFFICIENT_BALANCE +} + +interface AutomationRegistryBaseInterface { + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData, + bytes calldata offchainConfig + ) external returns (uint256 id); + + function cancelUpkeep(uint256 id) external; + + function pauseUpkeep(uint256 id) external; + + function unpauseUpkeep(uint256 id) external; + + function transferUpkeepAdmin(uint256 id, address proposed) external; + + function acceptUpkeepAdmin(uint256 id) external; + + function updateCheckData(uint256 id, bytes calldata newCheckData) external; + + function addFunds(uint256 id, uint96 amount) external; + + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external; + + function getUpkeep(uint256 id) external view returns (UpkeepInfo memory upkeepInfo); + + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + + function getState() + external + view + returns ( + State memory state, + OnchainConfig memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); +} + +/** + * @dev The view methods are not actually marked as view in the implementation + * but we want them to be easily queried off-chain. Solidity will not compile + * if we actually inherit from this interface, so we document it here. + */ +interface AutomationRegistryInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 fastGasWei, + uint256 linkNative + ); +} + +interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { + function checkUpkeep( + uint256 upkeepId + ) + external + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 fastGasWei, + uint256 linkNative + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol new file mode 100644 index 0000000..b3f8751 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol @@ -0,0 +1,315 @@ +// abi-checksum: 0x0ed34e4b36bd7b4a5447152c2d61491e6ba7ed944b11e4dfef4fea184708975e +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! +pragma solidity ^0.8.4; + +interface IKeeperRegistryMaster { + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientFunds(); + error InvalidDataLength(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidTransmitter(); + error InvalidTrigger(); + error InvalidTriggerType(); + error MaxCheckDataSizeCanOnlyIncrease(); + error MaxPerformDataSizeCanOnlyIncrease(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event OwnerFundsWithdrawn(uint96 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + fallback() external; + function acceptOwnership() external; + function fallbackTo() external view returns (address); + function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; + function owner() external view returns (address); + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function transferOwnership(address to) external; + function transmit( + bytes32[3] memory reportContext, + bytes memory rawReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) external; + function typeAndVersion() external view returns (string memory); + + function addFunds(uint256 id, uint96 amount) external; + function cancelUpkeep(uint256 id) external; + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function migrateUpkeeps(uint256[] memory ids, address destination) external; + function receiveUpkeeps(bytes memory encodedUpkeeps) external; + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + uint8 triggerType, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) external returns (uint256 id); + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes memory checkData, + bytes memory offchainConfig + ) external returns (uint256 id); + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + + function acceptPayeeship(address transmitter) external; + function acceptUpkeepAdmin(uint256 id) external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); + function getAutomationForwarderLogic() external view returns (address); + function getBalance(uint256 id) external view returns (uint96 balance); + function getCancellationDelay() external pure returns (uint256); + function getConditionalGasOverhead() external pure returns (uint256); + function getFastGasFeedAddress() external view returns (address); + function getForwarder(uint256 upkeepID) external view returns (address); + function getLinkAddress() external view returns (address); + function getLinkNativeFeedAddress() external view returns (address); + function getLogGasOverhead() external pure returns (uint256); + function getMaxPaymentForGas(uint8 triggerType, uint32 gasLimit) external view returns (uint96 maxPayment); + function getMinBalance(uint256 id) external view returns (uint96); + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); + function getMode() external view returns (uint8); + function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); + function getPerPerformByteGasOverhead() external pure returns (uint256); + function getPerSignerGasOverhead() external pure returns (uint256); + function getSignerInfo(address query) external view returns (bool active, uint8 index); + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function pause() external; + function pauseUpkeep(uint256 id) external; + function recoverFunds() external; + function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; + function setPayees(address[] memory payees) external; + function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function transferPayeeship(address transmitter, address proposed) external; + function transferUpkeepAdmin(uint256 id, address proposed) external; + function unpause() external; + function unpauseUpkeep(uint256 id) external; + function upkeepTranscoderVersion() external pure returns (uint8); + function upkeepVersion() external pure returns (uint8); + function withdrawFunds(uint256 id, address to) external; + function withdrawOwnerFunds() external; + function withdrawPayment(address from, address to) external; +} + +interface IAutomationV21PlusCommon { + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: +/* +[{"inputs":[{"internalType":"contract KeeperRegistryLogicB2_1","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MaxCheckDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MaxPerformDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"PaymentGreaterThanAllLINK","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"OwnerFundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract KeeperRegistryLogicB2_1","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"triggerType","type":"uint8"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum KeeperRegistryBase2_1.Mode","name":"mode","type":"uint8"},{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkNativeFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkNativeFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMode","outputs":[{"internalType":"enum KeeperRegistryBase2_1.Mode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum KeeperRegistryBase2_1.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum KeeperRegistryBase2_1.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawOwnerFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol new file mode 100644 index 0000000..edd8443 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol @@ -0,0 +1,341 @@ +// abi-checksum: 0xfc319f2ddde95d2e0226c913b9e417495effc4c8c847d01fe07e3de68ea8839c +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! +pragma solidity ^0.8.4; + +interface IAutomationRegistryMaster { + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InvalidDataLength(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidTransmitter(); + error InvalidTrigger(); + error InvalidTriggerType(); + error MaxCheckDataSizeCanOnlyIncrease(); + error MaxPerformDataSizeCanOnlyIncrease(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event OwnerFundsWithdrawn(uint96 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + fallback() external; + function acceptOwnership() external; + function fallbackTo() external view returns (address); + function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; + function owner() external view returns (address); + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + AutomationRegistryBase2_2.OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function transferOwnership(address to) external; + function transmit( + bytes32[3] memory reportContext, + bytes memory rawReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) external; + function typeAndVersion() external view returns (string memory); + + function addFunds(uint256 id, uint96 amount) external; + function cancelUpkeep(uint256 id) external; + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function migrateUpkeeps(uint256[] memory ids, address destination) external; + function receiveUpkeeps(bytes memory encodedUpkeeps) external; + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + uint8 triggerType, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) external returns (uint256 id); + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes memory checkData, + bytes memory offchainConfig + ) external returns (uint256 id); + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + + function acceptPayeeship(address transmitter) external; + function acceptUpkeepAdmin(uint256 id) external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); + function getAllowedReadOnlyAddress() external view returns (address); + function getAutomationForwarderLogic() external view returns (address); + function getBalance(uint256 id) external view returns (uint96 balance); + function getCancellationDelay() external pure returns (uint256); + function getChainModule() external view returns (address chainModule); + function getConditionalGasOverhead() external pure returns (uint256); + function getFastGasFeedAddress() external view returns (address); + function getForwarder(uint256 upkeepID) external view returns (address); + function getLinkAddress() external view returns (address); + function getLinkNativeFeedAddress() external view returns (address); + function getLogGasOverhead() external pure returns (uint256); + function getMaxPaymentForGas(uint8 triggerType, uint32 gasLimit) external view returns (uint96 maxPayment); + function getMinBalance(uint256 id) external view returns (uint96); + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); + function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); + function getPerPerformByteGasOverhead() external pure returns (uint256); + function getPerSignerGasOverhead() external pure returns (uint256); + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); + function getSignerInfo(address query) external view returns (bool active, uint8 index); + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256); + function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256); + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function pause() external; + function pauseUpkeep(uint256 id) external; + function recoverFunds() external; + function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; + function setPayees(address[] memory payees) external; + function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function transferPayeeship(address transmitter, address proposed) external; + function transferUpkeepAdmin(uint256 id, address proposed) external; + function unpause() external; + function unpauseUpkeep(uint256 id) external; + function upkeepTranscoderVersion() external pure returns (uint8); + function upkeepVersion() external pure returns (uint8); + function withdrawFunds(uint256 id, address to) external; + function withdrawOwnerFunds() external; + function withdrawPayment(address from, address to) external; +} + +interface AutomationRegistryBase2_2 { + struct OnchainConfig { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + address chainModule; + bool reorgProtectionEnabled; + } +} + +interface IAutomationV21PlusCommon { + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: +/* +[{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_2","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MaxCheckDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MaxPerformDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"PaymentGreaterThanAllLINK","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"OwnerFundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"internalType":"struct AutomationRegistryBase2_2.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_2","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"triggerType","type":"uint8"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkNativeFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkNativeFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_2.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_2.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawOwnerFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol new file mode 100644 index 0000000..7477c02 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -0,0 +1,435 @@ +// abi-checksum: 0xacb9d0daec3e3bed110c8cf95bdbe7280a21ce61519d4cd496f802884bf05524 +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! +pragma solidity ^0.8.4; + +interface IAutomationRegistryMaster2_3 { + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientBalance(uint256 available, uint256 requested); + error InsufficientLinkLiquidity(); + error InvalidDataLength(); + error InvalidFeed(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidToken(); + error InvalidTransmitter(); + error InvalidTrigger(); + error InvalidTriggerType(); + error MigrationNotPermitted(); + error MustSettleOffchain(); + error MustSettleOnchain(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyFinanceAdmin(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error TransferFailed(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ZeroAddressNotAllowed(); + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + event BillingConfigSet(address indexed token, AutomationRegistryBase2_3.BillingConfig config); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCharged(uint256 indexed id, AutomationRegistryBase2_3.PaymentReceipt receipt); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + fallback() external payable; + function acceptOwnership() external; + function fallbackTo() external view returns (address); + function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + function owner() external view returns (address); + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + AutomationRegistryBase2_3.OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + address[] memory billingTokens, + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs + ) external; + function transferOwnership(address to) external; + function transmit( + bytes32[3] memory reportContext, + bytes memory rawReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) external; + function typeAndVersion() external view returns (string memory); + + function cancelUpkeep(uint256 id) external; + function migrateUpkeeps(uint256[] memory ids, address destination) external; + function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; + function receiveUpkeeps(bytes memory encodedUpkeeps) external; + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + uint8 triggerType, + address billingToken, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) external returns (uint256 id); + + function acceptUpkeepAdmin(uint256 id) external; + function addFunds(uint256 id, uint96 amount) external payable; + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function pauseUpkeep(uint256 id) external; + function removeBillingOverrides(uint256 id) external; + function setBillingOverrides(uint256 id, AutomationRegistryBase2_3.BillingOverrides memory billingOverrides) external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function transferUpkeepAdmin(uint256 id, address proposed) external; + function unpauseUpkeep(uint256 id) external; + function withdrawERC20Fees(address asset, address to, uint256 amount) external; + function withdrawFunds(uint256 id, address to) external; + function withdrawLink(address to, uint256 amount) external; + + function acceptPayeeship(address transmitter) external; + function disableOffchainPayments() external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); + function getAllowedReadOnlyAddress() external view returns (address); + function getAutomationForwarderLogic() external view returns (address); + function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); + function getBalance(uint256 id) external view returns (uint96 balance); + function getBillingConfig( + address billingToken + ) external view returns (AutomationRegistryBase2_3.BillingConfig memory); + function getBillingOverrides( + uint256 upkeepID + ) external view returns (AutomationRegistryBase2_3.BillingOverrides memory); + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); + function getBillingToken(uint256 upkeepID) external view returns (address); + function getBillingTokenConfig(address token) external view returns (AutomationRegistryBase2_3.BillingConfig memory); + function getBillingTokens() external view returns (address[] memory); + function getCancellationDelay() external pure returns (uint256); + function getChainModule() external view returns (address chainModule); + function getConditionalGasOverhead() external pure returns (uint256); + function getConfig() external view returns (AutomationRegistryBase2_3.OnchainConfig memory); + function getFallbackNativePrice() external view returns (uint256); + function getFastGasFeedAddress() external view returns (address); + function getForwarder(uint256 upkeepID) external view returns (address); + function getHotVars() external view returns (AutomationRegistryBase2_3.HotVars memory); + function getLinkAddress() external view returns (address); + function getLinkUSDFeedAddress() external view returns (address); + function getLogGasOverhead() external pure returns (uint256); + function getMaxPaymentForGas( + uint256 id, + uint8 triggerType, + uint32 gasLimit, + address billingToken + ) external view returns (uint96 maxPayment); + function getMinBalance(uint256 id) external view returns (uint96); + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); + function getNativeUSDFeedAddress() external view returns (address); + function getNumUpkeeps() external view returns (uint256); + function getPayoutMode() external view returns (uint8); + function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); + function getPerPerformByteGasOverhead() external pure returns (uint256); + function getPerSignerGasOverhead() external pure returns (uint256); + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); + function getReserveAmount(address billingToken) external view returns (uint256); + function getSignerInfo(address query) external view returns (bool active, uint8 index); + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function getStorage() external view returns (AutomationRegistryBase2_3.Storage memory); + function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256); + function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256); + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTransmittersWithPayees() external view returns (AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function getWrappedNativeTokenAddress() external view returns (address); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function linkAvailableForPayment() external view returns (int256); + function pause() external; + function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; + function setPayees(address[] memory payees) external; + function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function settleNOPsOffchain() external; + function supportsBillingToken(address token) external view returns (bool); + function transferPayeeship(address transmitter, address proposed) external; + function unpause() external; + function upkeepVersion() external pure returns (uint8); + function withdrawPayment(address from, address to) external; +} + +interface AutomationRegistryBase2_3 { + struct BillingOverrides { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + } + + struct BillingConfig { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + address priceFeed; + uint8 decimals; + uint256 fallbackPrice; + uint96 minSpend; + } + + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + address billingToken; + uint96 linkUSD; + uint96 nativeUSD; + uint96 billingUSD; + } + + struct OnchainConfig { + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + address transcoder; + bool reorgProtectionEnabled; + uint24 stalenessSeconds; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + address upkeepPrivilegeManager; + uint16 gasCeilingMultiplier; + address financeAdmin; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + uint256 fallbackNativePrice; + address[] registrars; + address chainModule; + } + + struct HotVars { + uint96 totalPremium; + uint32 latestEpoch; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint8 f; + bool paused; + bool reentrancyGuard; + bool reorgProtectionEnabled; + address chainModule; + } + + struct Storage { + address transcoder; + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 nonce; + address upkeepPrivilegeManager; + uint32 configCount; + uint32 latestConfigBlockNumber; + uint32 maxCheckDataSize; + address financeAdmin; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } +} + +interface IAutomationV21PlusCommon { + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: +/* +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol new file mode 100644 index 0000000..fdbd7dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +interface IWrappedNative is IERC20 { + function deposit() external payable; + + function withdraw(uint256 wad) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol new file mode 100644 index 0000000..9edb541 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +address constant GAS_BOUND_CALLER = address(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5); + +interface IGasBoundCaller { + function gasBoundCall(address _to, uint256 _maxTotalGas, bytes calldata _data) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol new file mode 100644 index 0000000..c8f4800 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(address(0x800b)); + +interface ISystemContext { + function gasPrice() external view returns (uint256); + function gasPerPubdataByte() external view returns (uint256 gasPerPubdataByte); + function getCurrentPubdataSpent() external view returns (uint256 currentPubdataSpent); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol new file mode 100644 index 0000000..8943721 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol @@ -0,0 +1,441 @@ +// solhint-disable +// abi-checksum: 0x5857a77a981fcb60dbdac0700e68420cbe544249b20d9326d51c5ef8584c5dd7 +// SPDX-License-Identifier: MIT +// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! +pragma solidity ^0.8.19; + +interface IZKSyncAutomationRegistryMaster2_3 { + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientBalance(uint256 available, uint256 requested); + error InsufficientLinkLiquidity(); + error InvalidDataLength(); + error InvalidFeed(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidToken(); + error InvalidTransmitter(); + error InvalidTrigger(); + error InvalidTriggerType(); + error MigrationNotPermitted(); + error MustSettleOffchain(); + error MustSettleOnchain(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyFinanceAdmin(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error TransferFailed(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ZeroAddressNotAllowed(); + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event BillingConfigOverridden(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + event BillingConfigSet(address indexed token, ZKSyncAutomationRegistryBase2_3.BillingConfig config); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event Transmitted(bytes32 configDigest, uint32 epoch); + event Unpaused(address account); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCharged(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.PaymentReceipt receipt); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + fallback() external payable; + function acceptOwnership() external; + function fallbackTo() external view returns (address); + function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + function owner() external view returns (address); + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + ZKSyncAutomationRegistryBase2_3.OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + address[] memory billingTokens, + ZKSyncAutomationRegistryBase2_3.BillingConfig[] memory billingConfigs + ) external; + function transferOwnership(address to) external; + function transmit( + bytes32[3] memory reportContext, + bytes memory rawReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) external; + function typeAndVersion() external view returns (string memory); + + function cancelUpkeep(uint256 id) external; + function migrateUpkeeps(uint256[] memory ids, address destination) external; + function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; + function receiveUpkeeps(bytes memory encodedUpkeeps) external; + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + uint8 triggerType, + address billingToken, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) external returns (uint256 id); + + function acceptUpkeepAdmin(uint256 id) external; + function addFunds(uint256 id, uint96 amount) external payable; + function checkCallback( + uint256 id, + bytes[] memory values, + bytes memory extraData + ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function checkUpkeep( + uint256 id + ) + external + view + returns ( + bool upkeepNeeded, + bytes memory performData, + uint8 upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ); + function executeCallback( + uint256 id, + bytes memory payload + ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); + function pauseUpkeep(uint256 id) external; + function removeBillingOverrides(uint256 id) external; + function setBillingOverrides( + uint256 id, + ZKSyncAutomationRegistryBase2_3.BillingOverrides memory billingOverrides + ) external; + function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; + function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; + function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; + function simulatePerformUpkeep( + uint256 id, + bytes memory performData + ) external view returns (bool success, uint256 gasUsed); + function transferUpkeepAdmin(uint256 id, address proposed) external; + function unpauseUpkeep(uint256 id) external; + function withdrawERC20Fees(address asset, address to, uint256 amount) external; + function withdrawFunds(uint256 id, address to) external; + function withdrawLink(address to, uint256 amount) external; + + function acceptPayeeship(address transmitter) external; + function disableOffchainPayments() external; + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); + function getAllowedReadOnlyAddress() external view returns (address); + function getAutomationForwarderLogic() external view returns (address); + function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); + function getBalance(uint256 id) external view returns (uint96 balance); + function getBillingConfig( + address billingToken + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); + function getBillingOverrides( + uint256 upkeepID + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingOverrides memory); + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); + function getBillingToken(uint256 upkeepID) external view returns (address); + function getBillingTokenConfig( + address token + ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); + function getBillingTokens() external view returns (address[] memory); + function getCancellationDelay() external pure returns (uint256); + function getChainModule() external view returns (address chainModule); + function getConditionalGasOverhead() external pure returns (uint256); + function getConfig() external view returns (ZKSyncAutomationRegistryBase2_3.OnchainConfig memory); + function getFallbackNativePrice() external view returns (uint256); + function getFastGasFeedAddress() external view returns (address); + function getForwarder(uint256 upkeepID) external view returns (address); + function getHotVars() external view returns (ZKSyncAutomationRegistryBase2_3.HotVars memory); + function getLinkAddress() external view returns (address); + function getLinkUSDFeedAddress() external view returns (address); + function getLogGasOverhead() external pure returns (uint256); + function getMaxPaymentForGas( + uint256 id, + uint8 triggerType, + uint32 gasLimit, + address billingToken + ) external view returns (uint96 maxPayment); + function getMinBalance(uint256 id) external view returns (uint96); + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); + function getNativeUSDFeedAddress() external view returns (address); + function getNumUpkeeps() external view returns (uint256); + function getPayoutMode() external view returns (uint8); + function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); + function getPerSignerGasOverhead() external pure returns (uint256); + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); + function getReserveAmount(address billingToken) external view returns (uint256); + function getSignerInfo(address query) external view returns (bool active, uint8 index); + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ); + function getStorage() external view returns (ZKSyncAutomationRegistryBase2_3.Storage memory); + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); + function getTransmittersWithPayees() + external + view + returns (ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); + function getTriggerType(uint256 upkeepId) external pure returns (uint8); + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); + function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); + function getWrappedNativeTokenAddress() external view returns (address); + function hasDedupKey(bytes32 dedupKey) external view returns (bool); + function linkAvailableForPayment() external view returns (int256); + function pause() external; + function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; + function setPayees(address[] memory payees) external; + function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; + function settleNOPsOffchain() external; + function supportsBillingToken(address token) external view returns (bool); + function transferPayeeship(address transmitter, address proposed) external; + function unpause() external; + function upkeepVersion() external pure returns (uint8); + function withdrawPayment(address from, address to) external; +} + +interface ZKSyncAutomationRegistryBase2_3 { + struct BillingOverrides { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + } + + struct BillingConfig { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + address priceFeed; + uint8 decimals; + uint256 fallbackPrice; + uint96 minSpend; + } + + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + address billingToken; + uint96 linkUSD; + uint96 nativeUSD; + uint96 billingUSD; + } + + struct OnchainConfig { + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + address transcoder; + bool reorgProtectionEnabled; + uint24 stalenessSeconds; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + address upkeepPrivilegeManager; + uint16 gasCeilingMultiplier; + address financeAdmin; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + uint256 fallbackNativePrice; + address[] registrars; + address chainModule; + } + + struct HotVars { + uint96 totalPremium; + uint32 latestEpoch; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint8 f; + bool paused; + bool reentrancyGuard; + bool reorgProtectionEnabled; + address chainModule; + } + + struct Storage { + address transcoder; + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 nonce; + address upkeepPrivilegeManager; + uint32 configCount; + uint32 latestConfigBlockNumber; + uint32 maxCheckDataSize; + address financeAdmin; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } +} + +interface IAutomationV21PlusCommon { + struct StateLegacy { + uint32 nonce; + uint96 ownerLinkBalance; + uint256 expectedLinkBalance; + uint96 totalPremium; + uint256 numUpkeeps; + uint32 configCount; + uint32 latestConfigBlockNumber; + bytes32 latestConfigDigest; + uint32 latestEpoch; + bool paused; + } + + struct OnchainConfigLegacy { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + } + + struct UpkeepInfoLegacy { + address target; + uint32 performGas; + bytes checkData; + uint96 balance; + address admin; + uint64 maxValidBlocknumber; + uint32 lastPerformedBlockNumber; + uint96 amountSpent; + bool paused; + bytes offchainConfig; + } +} + +// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: +/* +[{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol new file mode 100644 index 0000000..0c93c19 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol @@ -0,0 +1,78 @@ +pragma solidity 0.8.6; + +import {Cron as CronInternal, Spec} from "../internal/Cron.sol"; + +/** + * @title The Cron library + * @notice A utility contract for encoding/decoding cron strings (ex: 0 0 * * *) into an + * abstraction called a Spec. The library also includes a spec function, nextTick(), which + * determines the next time a cron job should fire based on the current block timestamp. + * @dev this is the external version of the library, which relies on the internal library + * by the same name. + */ +library Cron { + using CronInternal for Spec; + using CronInternal for string; + + /** + * @notice nextTick calculates the next datetime that a spec "ticks", starting + * from the current block timestamp. This is gas-intensive and therefore should + * only be called off-chain. + * @param spec the spec to evaluate + * @return the next tick + */ + function nextTick(Spec calldata spec) public view returns (uint256) { + return spec.nextTick(); + } + + /** + * @notice lastTick calculates the previous datetime that a spec "ticks", starting + * from the current block timestamp. This is gas-intensive and therefore should + * only be called off-chain. + * @param spec the spec to evaluate + * @return the next tick + */ + function lastTick(Spec calldata spec) public view returns (uint256) { + return spec.lastTick(); + } + + /** + * @notice matches evaluates whether or not a spec "ticks" at a given timestamp + * @param spec the spec to evaluate + * @param timestamp the timestamp to compare against + * @return true / false if they match + */ + function matches(Spec calldata spec, uint256 timestamp) public view returns (bool) { + return spec.matches(timestamp); + } + + /** + * @notice toSpec converts a cron string to a spec struct. This is gas-intensive + * and therefore should only be called off-chain. + * @param cronString the cron string + * @return the spec struct + */ + function toSpec(string calldata cronString) public pure returns (Spec memory) { + return cronString.toSpec(); + } + + /** + * @notice toEncodedSpec converts a cron string to an abi-encoded spec. This is gas-intensive + * and therefore should only be called off-chain. + * @param cronString the cron string + * @return the abi-encoded spec + */ + function toEncodedSpec(string calldata cronString) public pure returns (bytes memory) { + return cronString.toEncodedSpec(); + } + + /** + * @notice toCronString converts a cron spec to a human-readable cron string. This is gas-intensive + * and therefore should only be called off-chain. + * @param spec the cron spec + * @return the corresponding cron string + */ + function toCronString(Spec calldata spec) public pure returns (string memory) { + return spec.toCronString(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol new file mode 100644 index 0000000..ae4f90d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol @@ -0,0 +1,544 @@ +// SPDX-License-Identifier: MIT + +/* + The Cron contract serves two primary functions: + * parsing cron-formatted strings like "0 0 * * *" into + structs called "Specs" + * computing the "next tick" of a cron spec + + Because manipulating strings is gas-expensive in solidity, + the intended use of this contract is for users to first convert + their cron strings to encoded Spec structs via toEncodedSpec(). + Then, the user stores the Spec on chain. Finally, users use the nextTick(), + function to determine the datetime of the next cron job run. + + Cron jobs are interpreted according to this format: + + ┌───────────── minute (0 - 59) + │ ┌───────────── hour (0 - 23) + │ │ ┌───────────── day of the month (1 - 31) + │ │ │ ┌───────────── month (1 - 12) + │ │ │ │ ┌───────────── day of the week (0 - 6) (Monday to Sunday) + │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + * * * * * + + Special limitations: + * there is no year field + * no special characters: ? L W # + * lists can have a max length of 26 + * no words like JAN / FEB or MON / TUES +*/ + +pragma solidity 0.8.6; + +import "../../../vendor/Strings.sol"; +import "../../../vendor/DateTime.sol"; + +// The fields of a cron spec, by name +string constant MINUTE = "minute"; +string constant HOUR = "hour"; +string constant DAY = "day"; +string constant MONTH = "month"; +string constant DAY_OF_WEEK = "day of week"; + +error UnknownFieldType(); +error InvalidSpec(string reason); +error InvalidField(string field, string reason); +error ListTooLarge(); + +// Set of enums representing a cron field type +enum FieldType { + WILD, + EXACT, + INTERVAL, + RANGE, + LIST +} + +// A spec represents a cron job by decomposing it into 5 fields +struct Spec { + Field minute; + Field hour; + Field day; + Field month; + Field dayOfWeek; +} + +// A field represents a single element in a cron spec. There are 5 types +// of fields (see above). Not all properties of this struct are present at once. +struct Field { + FieldType fieldType; + uint8 singleValue; + uint8 interval; + uint8 rangeStart; + uint8 rangeEnd; + uint8 listLength; + uint8[26] list; +} + +/** + * @title The Cron library + * @notice A utility contract for encoding/decoding cron strings (ex: 0 0 * * *) into an + * abstraction called a Spec. The library also includes a spec function, nextTick(), which + * determines the next time a cron job should fire based on the current block timestamp. + */ +// solhint-disable chainlink-solidity/prefix-internal-functions-with-underscore, no-global-import +library Cron { + using strings for *; + + /** + * @notice nextTick calculates the next datetime that a spec "ticks", starting + * from the current block timestamp. This is gas-intensive and therefore should + * only be called off-chain. + * @param spec the spec to evaluate + * @return the next tick + * @dev this is the internal version of the library. There is also an external version. + */ + function nextTick(Spec memory spec) internal view returns (uint256) { + uint16 year = DateTime.getYear(block.timestamp); + uint8 month = DateTime.getMonth(block.timestamp); + uint8 day = DateTime.getDay(block.timestamp); + uint8 hour = DateTime.getHour(block.timestamp); + uint8 minute = DateTime.getMinute(block.timestamp); + uint8 dayOfWeek; + for (; true; year++) { + for (; month <= 12; month++) { + if (!matches(spec.month, month)) { + day = 1; + hour = 0; + minute = 0; + continue; + } + uint8 maxDay = DateTime.getDaysInMonth(month, year); + for (; day <= maxDay; day++) { + if (!matches(spec.day, day)) { + hour = 0; + minute = 0; + continue; + } + dayOfWeek = DateTime.getWeekday(DateTime.toTimestamp(year, month, day)); + if (!matches(spec.dayOfWeek, dayOfWeek)) { + hour = 0; + minute = 0; + continue; + } + for (; hour < 24; hour++) { + if (!matches(spec.hour, hour)) { + minute = 0; + continue; + } + for (; minute < 60; minute++) { + if (!matches(spec.minute, minute)) { + continue; + } + return DateTime.toTimestamp(year, month, day, hour, minute); + } + minute = 0; + } + hour = 0; + } + day = 1; + } + month = 1; + } + } + + /** + * @notice lastTick calculates the previous datetime that a spec "ticks", starting + * from the current block timestamp. This is gas-intensive and therefore should + * only be called off-chain. + * @param spec the spec to evaluate + * @return the next tick + */ + function lastTick(Spec memory spec) internal view returns (uint256) { + uint16 year = DateTime.getYear(block.timestamp); + uint8 month = DateTime.getMonth(block.timestamp); + uint8 day = DateTime.getDay(block.timestamp); + uint8 hour = DateTime.getHour(block.timestamp); + uint8 minute = DateTime.getMinute(block.timestamp); + uint8 dayOfWeek; + bool resetDay; + for (; true; year--) { + for (; month > 0; month--) { + if (!matches(spec.month, month)) { + resetDay = true; + hour = 23; + minute = 59; + continue; + } + if (resetDay) { + day = DateTime.getDaysInMonth(month, year); + } + for (; day > 0; day--) { + if (!matches(spec.day, day)) { + hour = 23; + minute = 59; + continue; + } + dayOfWeek = DateTime.getWeekday(DateTime.toTimestamp(year, month, day)); + if (!matches(spec.dayOfWeek, dayOfWeek)) { + hour = 23; + minute = 59; + continue; + } + for (; hour >= 0; hour--) { + if (!matches(spec.hour, hour)) { + minute = 59; + if (hour == 0) { + break; + } + continue; + } + for (; minute >= 0; minute--) { + if (!matches(spec.minute, minute)) { + if (minute == 0) { + break; + } + continue; + } + return DateTime.toTimestamp(year, month, day, hour, minute); + } + minute = 59; + if (hour == 0) { + break; + } + } + hour = 23; + } + resetDay = true; + } + month = 12; + } + } + + /** + * @notice matches evaluates whether or not a spec "ticks" at a given timestamp + * @param spec the spec to evaluate + * @param timestamp the timestamp to compare against + * @return true / false if they match + */ + function matches(Spec memory spec, uint256 timestamp) internal view returns (bool) { + DateTime._DateTime memory dt = DateTime.parseTimestamp(timestamp); + return + matches(spec.month, dt.month) && + matches(spec.day, dt.day) && + matches(spec.hour, dt.hour) && + matches(spec.minute, dt.minute); + } + + /** + * @notice toSpec converts a cron string to a spec struct. This is gas-intensive + * and therefore should only be called off-chain. + * @param cronString the cron string + * @return the spec struct + */ + function toSpec(string memory cronString) internal pure returns (Spec memory) { + strings.slice memory space = strings.toSlice(" "); + strings.slice memory cronSlice = strings.toSlice(cronString); + if (cronSlice.count(space) != 4) { + revert InvalidSpec("4 spaces required"); + } + strings.slice memory minuteSlice = cronSlice.split(space); + strings.slice memory hourSlice = cronSlice.split(space); + strings.slice memory daySlice = cronSlice.split(space); + strings.slice memory monthSlice = cronSlice.split(space); + // DEV: dayOfWeekSlice = cronSlice + // The cronSlice now contains the last section of the cron job, + // which corresponds to the day of week + if ( + minuteSlice.len() == 0 || + hourSlice.len() == 0 || + daySlice.len() == 0 || + monthSlice.len() == 0 || + cronSlice.len() == 0 + ) { + revert InvalidSpec("some fields missing"); + } + return + validate( + Spec({ + minute: sliceToField(minuteSlice), + hour: sliceToField(hourSlice), + day: sliceToField(daySlice), + month: sliceToField(monthSlice), + dayOfWeek: sliceToField(cronSlice) + }) + ); + } + + /** + * @notice toEncodedSpec converts a cron string to an abi-encoded spec. This is gas-intensive + * and therefore should only be called off-chain. + * @param cronString the cron string + * @return the abi-encoded spec + */ + function toEncodedSpec(string memory cronString) internal pure returns (bytes memory) { + return abi.encode(toSpec(cronString)); + } + + /** + * @notice toCronString converts a cron spec to a human-readable cron string. This is gas-intensive + * and therefore should only be called off-chain. + * @param spec the cron spec + * @return the corresponding cron string + */ + function toCronString(Spec memory spec) internal pure returns (string memory) { + return + string( + bytes.concat( + fieldToBstring(spec.minute), + " ", + fieldToBstring(spec.hour), + " ", + fieldToBstring(spec.day), + " ", + fieldToBstring(spec.month), + " ", + fieldToBstring(spec.dayOfWeek) + ) + ); + } + + /** + * @notice matches evaluates if a values matches a field. + * ex: 3 matches *, 3 matches 0-5, 3 does not match 0,2,4 + * @param field the field struct to match against + * @param value the value of a field + * @return true / false if they match + */ + function matches(Field memory field, uint8 value) private pure returns (bool) { + if (field.fieldType == FieldType.WILD) { + return true; + } else if (field.fieldType == FieldType.INTERVAL) { + return value % field.interval == 0; + } else if (field.fieldType == FieldType.EXACT) { + return value == field.singleValue; + } else if (field.fieldType == FieldType.RANGE) { + return value >= field.rangeStart && value <= field.rangeEnd; + } else if (field.fieldType == FieldType.LIST) { + for (uint256 idx = 0; idx < field.listLength; idx++) { + if (value == field.list[idx]) { + return true; + } + } + return false; + } + revert UnknownFieldType(); + } + + // VALIDATIONS + + /** + * @notice validate validates a spec, reverting if any errors are found + * @param spec the spec to validate + * @return the original spec + */ + function validate(Spec memory spec) private pure returns (Spec memory) { + validateField(spec.dayOfWeek, DAY_OF_WEEK, 0, 6); + validateField(spec.month, MONTH, 1, 12); + uint8 maxDay = maxDayForMonthField(spec.month); + validateField(spec.day, DAY, 1, maxDay); + validateField(spec.hour, HOUR, 0, 23); + validateField(spec.minute, MINUTE, 0, 59); + return spec; + } + + /** + * @notice validateField validates the value of a field. It reverts if an error is found. + * @param field the field to validate + * @param fieldName the name of the field ex "minute" or "hour" + * @param min the minimum value a field can have (usually 1 or 0) + * @param max the maximum value a field can have (ex minute = 59, hour = 23) + */ + function validateField(Field memory field, string memory fieldName, uint8 min, uint8 max) private pure { + if (field.fieldType == FieldType.WILD) { + return; + } else if (field.fieldType == FieldType.EXACT) { + if (field.singleValue < min || field.singleValue > max) { + string memory reason = string( + bytes.concat("value must be >=,", uintToBString(min), " and <=", uintToBString(max)) + ); + revert InvalidField(fieldName, reason); + } + } else if (field.fieldType == FieldType.INTERVAL) { + if (field.interval < 1 || field.interval > max) { + string memory reason = string( + bytes.concat("inverval must be */(", uintToBString(1), "-", uintToBString(max), ")") + ); + revert InvalidField(fieldName, reason); + } + } else if (field.fieldType == FieldType.RANGE) { + if (field.rangeEnd > max || field.rangeEnd <= field.rangeStart) { + string memory reason = string( + bytes.concat("inverval must be within ", uintToBString(min), "-", uintToBString(max)) + ); + revert InvalidField(fieldName, reason); + } + } else if (field.fieldType == FieldType.LIST) { + if (field.listLength < 2) { + revert InvalidField(fieldName, "lists must have at least 2 items"); + } + string memory reason = string( + bytes.concat("items in list must be within ", uintToBString(min), "-", uintToBString(max)) + ); + uint8 listItem; + for (uint256 idx = 0; idx < field.listLength; idx++) { + listItem = field.list[idx]; + if (listItem < min || listItem > max) { + revert InvalidField(fieldName, reason); + } + } + } else { + revert UnknownFieldType(); + } + } + + /** + * @notice maxDayForMonthField returns the maximum valid day given the month field + * @param month the month field + * @return the max day + */ + function maxDayForMonthField(Field memory month) private pure returns (uint8) { + // DEV: ranges are always safe because any two consecutive months will always + // contain a month with 31 days + if (month.fieldType == FieldType.WILD || month.fieldType == FieldType.RANGE) { + return 31; + } else if (month.fieldType == FieldType.EXACT) { + // DEV: assume leap year in order to get max value + return DateTime.getDaysInMonth(month.singleValue, 4); + } else if (month.fieldType == FieldType.INTERVAL) { + if (month.interval == 9 || month.interval == 11) { + return 30; + } else { + return 31; + } + } else if (month.fieldType == FieldType.LIST) { + uint8 result; + for (uint256 idx = 0; idx < month.listLength; idx++) { + // DEV: assume leap year in order to get max value + uint8 daysInMonth = DateTime.getDaysInMonth(month.list[idx], 4); + if (daysInMonth == 31) { + return daysInMonth; + } + if (daysInMonth > result) { + result = daysInMonth; + } + } + return result; + } else { + revert UnknownFieldType(); + } + } + + /** + * @notice sliceToField converts a strings.slice to a field struct + * @param fieldSlice the slice of a string representing the field of a cron job + * @return the field + */ + function sliceToField(strings.slice memory fieldSlice) private pure returns (Field memory) { + strings.slice memory star = strings.toSlice("*"); + strings.slice memory dash = strings.toSlice("-"); + strings.slice memory slash = strings.toSlice("/"); + strings.slice memory comma = strings.toSlice(","); + Field memory field; + if (fieldSlice.equals(star)) { + field.fieldType = FieldType.WILD; + } else if (fieldSlice.contains(dash)) { + field.fieldType = FieldType.RANGE; + strings.slice memory start = fieldSlice.split(dash); + field.rangeStart = sliceToUint8(start); + field.rangeEnd = sliceToUint8(fieldSlice); + } else if (fieldSlice.contains(slash)) { + field.fieldType = FieldType.INTERVAL; + fieldSlice.split(slash); + field.interval = sliceToUint8(fieldSlice); + } else if (fieldSlice.contains(comma)) { + field.fieldType = FieldType.LIST; + strings.slice memory token; + while (fieldSlice.len() > 0) { + if (field.listLength > 25) { + revert ListTooLarge(); + } + token = fieldSlice.split(comma); + field.list[field.listLength] = sliceToUint8(token); + field.listLength++; + } + } else { + // needs input validation + field.fieldType = FieldType.EXACT; + field.singleValue = sliceToUint8(fieldSlice); + } + return field; + } + + /** + * @notice fieldToBstring converts a field to the bytes representation of that field string + * @param field the field to stringify + * @return bytes representing the string, ex: bytes("*") + */ + function fieldToBstring(Field memory field) private pure returns (bytes memory) { + if (field.fieldType == FieldType.WILD) { + return "*"; + } else if (field.fieldType == FieldType.EXACT) { + return uintToBString(uint256(field.singleValue)); + } else if (field.fieldType == FieldType.RANGE) { + return bytes.concat(uintToBString(field.rangeStart), "-", uintToBString(field.rangeEnd)); + } else if (field.fieldType == FieldType.INTERVAL) { + return bytes.concat("*/", uintToBString(uint256(field.interval))); + } else if (field.fieldType == FieldType.LIST) { + bytes memory result = uintToBString(field.list[0]); + for (uint256 idx = 1; idx < field.listLength; idx++) { + result = bytes.concat(result, ",", uintToBString(field.list[idx])); + } + return result; + } + revert UnknownFieldType(); + } + + /** + * @notice uintToBString converts a uint256 to a bytes representation of that uint as a string + * @param n the number to stringify + * @return bytes representing the string, ex: bytes("1") + */ + function uintToBString(uint256 n) private pure returns (bytes memory) { + if (n == 0) { + return "0"; + } + uint256 j = n; + uint256 len; + while (j != 0) { + len++; + j /= 10; + } + bytes memory bstr = new bytes(len); + uint256 k = len; + while (n != 0) { + k = k - 1; + uint8 temp = (48 + uint8(n - (n / 10) * 10)); + bytes1 b1 = bytes1(temp); + bstr[k] = b1; + n /= 10; + } + return bstr; + } + + /** + * @notice sliceToUint8 converts a strings.slice to uint8 + * @param slice the string slice to convert to a uint8 + * @return the number that the string represents ex: "20" --> 20 + */ + function sliceToUint8(strings.slice memory slice) private pure returns (uint8) { + bytes memory b = bytes(slice.toString()); + uint8 i; + uint8 result = 0; + for (i = 0; i < b.length; i++) { + uint8 c = uint8(b[i]); + if (c >= 48 && c <= 57) { + result = result * 10 + (c - 48); + } + } + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol new file mode 100644 index 0000000..63a6181 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +import {ERC20Mock} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; + +// mock ERC20 with 6 decimals +contract ERC20Mock6Decimals is ERC20Mock { + constructor( + string memory name, + string memory symbol, + address initialAccount, + uint256 initialBalance + ) payable ERC20Mock(name, symbol, initialAccount, initialBalance) {} + + function decimals() public view virtual override returns (uint8) { + return 6; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol new file mode 100644 index 0000000..b147c98 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +contract KeeperRegistrar1_2Mock { + event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); + event ConfigChanged( + uint8 autoApproveConfigType, + uint32 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); + event RegistrationRejected(bytes32 indexed hash); + event RegistrationRequested( + bytes32 indexed hash, + string name, + bytes encryptedEmail, + address indexed upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes checkData, + uint96 amount, + uint8 indexed source + ); + + function emitAutoApproveAllowedSenderSet(address senderAddress, bool allowed) public { + emit AutoApproveAllowedSenderSet(senderAddress, allowed); + } + + function emitConfigChanged( + uint8 autoApproveConfigType, + uint32 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ) public { + emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); + } + + function emitOwnershipTransferRequested(address from, address to) public { + emit OwnershipTransferRequested(from, to); + } + + function emitOwnershipTransferred(address from, address to) public { + emit OwnershipTransferred(from, to); + } + + function emitRegistrationApproved(bytes32 hash, string memory displayName, uint256 upkeepId) public { + emit RegistrationApproved(hash, displayName, upkeepId); + } + + function emitRegistrationRejected(bytes32 hash) public { + emit RegistrationRejected(hash); + } + + function emitRegistrationRequested( + bytes32 hash, + string memory name, + bytes memory encryptedEmail, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes memory checkData, + uint96 amount, + uint8 source + ) public { + emit RegistrationRequested( + hash, + name, + encryptedEmail, + upkeepContract, + gasLimit, + adminAddress, + checkData, + amount, + source + ); + } + + enum AutoApproveType { + DISABLED, + ENABLED_SENDER_ALLOWLIST, + ENABLED_ALL + } + + AutoApproveType public s_autoApproveConfigType; + uint32 public s_autoApproveMaxAllowed; + uint32 public s_approvedCount; + address public s_keeperRegistry; + uint256 public s_minLINKJuels; + + // Function to set mock return data for the getRegistrationConfig function + function setRegistrationConfig( + AutoApproveType _autoApproveConfigType, + uint32 _autoApproveMaxAllowed, + uint32 _approvedCount, + address _keeperRegistry, + uint256 _minLINKJuels + ) external { + s_autoApproveConfigType = _autoApproveConfigType; + s_autoApproveMaxAllowed = _autoApproveMaxAllowed; + s_approvedCount = _approvedCount; + s_keeperRegistry = _keeperRegistry; + s_minLINKJuels = _minLINKJuels; + } + + // Mock getRegistrationConfig function + function getRegistrationConfig() + external + view + returns ( + AutoApproveType autoApproveConfigType, + uint32 autoApproveMaxAllowed, + uint32 approvedCount, + address keeperRegistry, + uint256 minLINKJuels + ) + { + return (s_autoApproveConfigType, s_autoApproveMaxAllowed, s_approvedCount, s_keeperRegistry, s_minLINKJuels); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol new file mode 100644 index 0000000..87e93c6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.6; + +contract KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock { + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + + function emitOwnershipTransferRequested(address from, address to) public { + emit OwnershipTransferRequested(from, to); + } + + function emitOwnershipTransferred(address from, address to) public { + emit OwnershipTransferred(from, to); + } + + bool public s_mockResult; + bytes public s_mockPayload; + uint256 public s_mockGas; + + // Function to set mock return data for the measureCheckGas function + function setMeasureCheckGasResult(bool result, bytes memory payload, uint256 gas) external { + s_mockResult = result; + s_mockPayload = payload; + s_mockGas = gas; + } + + // Mock measureCheckGas function + function measureCheckGas(uint256 id, address from) external returns (bool, bytes memory, uint256) { + return (s_mockResult, s_mockPayload, s_mockGas); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol new file mode 100644 index 0000000..8efca03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {IOffchainAggregator} from "../HeartbeatRequester.sol"; + +contract MockAggregator is IOffchainAggregator { + int256 public s_answer; + bool public newRoundCalled; + + function setLatestAnswer(int256 answer) public { + s_answer = answer; + } + + function latestAnswer() public view returns (int256) { + return s_answer; + } + + function requestNewRound() external override returns (uint80) { + newRoundCalled = true; + return 1; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol new file mode 100644 index 0000000..c48f028 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {IAggregatorProxy} from "../HeartbeatRequester.sol"; + +contract MockAggregatorProxy is IAggregatorProxy { + address internal s_aggregator; + + constructor(address _aggregator) { + s_aggregator = _aggregator; + } + + function updateAggregator(address _aggregator) external { + s_aggregator = _aggregator; + } + + function aggregator() external view override returns (address) { + return s_aggregator; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol new file mode 100644 index 0000000..2f21780 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import "../interfaces/IAutomationRegistryConsumer.sol"; + +contract MockKeeperRegistry2_1 is IAutomationRegistryConsumer { + uint96 balance; + uint96 minBalance; + + constructor() {} + + function getBalance(uint256 id) external view override returns (uint96) { + return balance; + } + + function getMinBalance(uint256 id) external view override returns (uint96) { + return minBalance; + } + + function cancelUpkeep(uint256 id) external override {} + + function pauseUpkeep(uint256 id) external override {} + + function unpauseUpkeep(uint256 id) external override {} + + function updateCheckData(uint256 id, bytes calldata newCheckData) external {} + + function addFunds(uint256 id, uint96 amount) external override {} + + function withdrawFunds(uint256 id, address to) external override {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol new file mode 100644 index 0000000..17899f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract MockUpkeep { + bool public shouldCheckRevert; + bool public shouldPerformRevert; + bool public checkResult = true; + bytes public performData; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + + event UpkeepPerformedWith(bytes upkeepData); + error CheckRevert(); + error PerformRevert(); + + function setShouldCheckRevert(bool value) public { + shouldCheckRevert = value; + } + + function setShouldPerformRevert(bool value) public { + shouldPerformRevert = value; + } + + function setCheckResult(bool value) public { + checkResult = value; + } + + function setPerformData(bytes calldata data) public { + performData = data; + } + + function setCheckGasToBurn(uint256 value) public { + checkGasToBurn = value; + } + + function setPerformGasToBurn(uint256 value) public { + performGasToBurn = value; + } + + function checkUpkeep(bytes calldata) external view returns (bool callable, bytes memory executedata) { + if (shouldCheckRevert) revert CheckRevert(); + uint256 startGas = gasleft(); + while (startGas - gasleft() < checkGasToBurn) {} // burn gas + return (checkResult, performData); + } + + function performUpkeep(bytes calldata data) external { + if (shouldPerformRevert) revert PerformRevert(); + uint256 startGas = gasleft(); + while (startGas - gasleft() < performGasToBurn) {} // burn gas + emit UpkeepPerformedWith(data); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol new file mode 100644 index 0000000..d9a8c3b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {AutomationForwarder} from "../AutomationForwarder.sol"; +import {AutomationForwarderLogic} from "../AutomationForwarderLogic.sol"; +import "forge-std/Test.sol"; + +// in contracts directory, run +// forge test --match-path src/v0.8/automation/test/AutomationForwarder.t.sol + +contract Target { + function handler() external pure {} + + function handlerRevert() external pure { + revert("revert"); + } +} + +contract AutomationForwarderTestSetUp is Test { + address internal constant REGISTRY = 0x3e19ef5Aaa2606655f5A677A97E085cf3811067c; + address internal constant STRANGER = 0x618fae5d04963B2CEf533F247Eb2C46Bf1801D3b; + + IAutomationForwarder internal forwarder; + address internal TARGET; + + function setUp() public { + TARGET = address(new Target()); + AutomationForwarderLogic logicContract = new AutomationForwarderLogic(); + forwarder = IAutomationForwarder(address(new AutomationForwarder(TARGET, REGISTRY, address(logicContract)))); + } +} + +contract AutomationForwarderTest_constructor is AutomationForwarderTestSetUp { + function testInitialValues() external { + assertEq(address(forwarder.getRegistry()), REGISTRY); + assertEq(forwarder.getTarget(), TARGET); + } + + function testTypeAndVersion() external { + assertEq(forwarder.typeAndVersion(), "AutomationForwarder 1.0.0"); + } +} + +contract AutomationForwarderTest_forward is AutomationForwarderTestSetUp { + function testOnlyCallableByTheRegistry() external { + vm.prank(REGISTRY); + forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); + vm.prank(STRANGER); + vm.expectRevert(); + forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); + } + + function testReturnsSuccessValueAndGasUsed() external { + vm.startPrank(REGISTRY); + (bool success, uint256 gasUsed) = forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); + assertTrue(success); + assertGt(gasUsed, 0); + (success, gasUsed) = forwarder.forward(100000, abi.encodeWithSelector(Target.handlerRevert.selector)); + assertFalse(success); + assertGt(gasUsed, 0); + } +} + +contract AutomationForwarderTest_updateRegistry is AutomationForwarderTestSetUp { + function testOnlyCallableByTheActiveRegistry() external { + address newRegistry = address(1); + vm.startPrank(REGISTRY); + forwarder.updateRegistry(newRegistry); + assertEq(address(forwarder.getRegistry()), newRegistry); + vm.expectRevert(); + forwarder.updateRegistry(REGISTRY); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol new file mode 100644 index 0000000..f3eafc0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationForwarderLogic} from "../AutomationForwarderLogic.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {AutomationRegistry2_2} from "../v2_2/AutomationRegistry2_2.sol"; +import {AutomationRegistryBase2_2} from "../v2_2/AutomationRegistryBase2_2.sol"; +import {AutomationRegistryLogicA2_2} from "../v2_2/AutomationRegistryLogicA2_2.sol"; +import {AutomationRegistryLogicB2_2} from "../v2_2/AutomationRegistryLogicB2_2.sol"; +import {IAutomationRegistryMaster} from "../interfaces/v2_2/IAutomationRegistryMaster.sol"; +import {ChainModuleBase} from "../chains/ChainModuleBase.sol"; + +contract AutomationRegistry2_2_SetUp is BaseTest { + address internal constant LINK_ETH_FEED = 0x1111111111111111111111111111111111111110; + address internal constant FAST_GAS_FEED = 0x1111111111111111111111111111111111111112; + address internal constant LINK_TOKEN = 0x1111111111111111111111111111111111111113; + address internal constant ZERO_ADDRESS = address(0); + + // Signer private keys used for these test + uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; + uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; + uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; + + uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 + uint8 internal constant F = 1; + + address[] internal s_valid_signers; + address[] internal s_valid_transmitters; + address[] internal s_registrars; + + IAutomationRegistryMaster internal registryMaster; + + function setUp() public override { + s_valid_transmitters = new address[](4); + for (uint160 i = 0; i < 4; ++i) { + s_valid_transmitters[i] = address(4 + i); + } + + s_valid_signers = new address[](4); + s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 + s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 + s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b + s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 + + s_registrars = new address[](1); + s_registrars[0] = 0x3a0eDE26aa188BFE00b9A0C9A431A1a0CA5f7966; + + AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); + AutomationRegistryLogicB2_2 logicB2_2 = new AutomationRegistryLogicB2_2( + LINK_TOKEN, + LINK_ETH_FEED, + FAST_GAS_FEED, + address(forwarderLogic), + ZERO_ADDRESS + ); + AutomationRegistryLogicA2_2 logicA2_2 = new AutomationRegistryLogicA2_2(logicB2_2); + registryMaster = IAutomationRegistryMaster( + address(new AutomationRegistry2_2(AutomationRegistryLogicB2_2(address(logicA2_2)))) + ); + } +} + +contract AutomationRegistry2_2_LatestConfigDetails is AutomationRegistry2_2_SetUp { + function testGet() public { + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registryMaster.latestConfigDetails(); + assertEq(configCount, 0); + assertEq(blockNumber, 0); + assertEq(configDigest, ""); + } +} + +contract AutomationRegistry2_2_CheckUpkeep is AutomationRegistry2_2_SetUp { + function testPreventExecutionOnCheckUpkeep() public { + uint256 id = 1; + bytes memory triggerData = abi.encodePacked("trigger_data"); + + // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry + // Expecting a revert since the tx.origin is not address(0) + vm.expectRevert(abi.encodeWithSelector(IAutomationRegistryMaster.OnlySimulatedBackend.selector)); + registryMaster.checkUpkeep(id, triggerData); + } +} + +contract AutomationRegistry2_2_SetConfig is AutomationRegistry2_2_SetUp { + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + function testSetConfigSuccess() public { + (uint32 configCount, , ) = registryMaster.latestConfigDetails(); + assertEq(configCount, 0); + ChainModuleBase module = new ChainModuleBase(); + + AutomationRegistryBase2_2.OnchainConfig memory cfg = AutomationRegistryBase2_2.OnchainConfig({ + paymentPremiumPPB: 10_000, + flatFeeMicroLink: 40_000, + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + minUpkeepSpend: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 200_000_000_000, + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: s_registrars, + upkeepPrivilegeManager: 0xD9c855F08A7e460691F41bBDDe6eC310bc0593D8, + chainModule: module, + reorgProtectionEnabled: true + }); + bytes memory onchainConfigBytes = abi.encode(cfg); + + uint256 a = 1234; + address b = address(0); + bytes memory offchainConfigBytes = abi.encode(a, b); + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registryMaster), + ++configCount, + s_valid_signers, + s_valid_transmitters, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + 0, + configDigest, + configCount, + s_valid_signers, + s_valid_transmitters, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registryMaster.setConfig( + s_valid_signers, + s_valid_transmitters, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registryMaster.getState(); + + assertEq(signers, s_valid_signers); + assertEq(transmitters, s_valid_transmitters); + assertEq(f, F); + } + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol new file mode 100644 index 0000000..ecba652 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; + +contract BaseTest is Test { + address internal OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + address internal constant STRANGER = address(999); + + function setUp() public virtual { + vm.startPrank(OWNER); + deal(OWNER, 1e20); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol new file mode 100644 index 0000000..caac639 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {HeartbeatRequester, IAggregatorProxy} from "../HeartbeatRequester.sol"; +import {MockAggregator} from "../mocks/MockAggregator.sol"; +import {MockAggregatorProxy} from "../mocks/MockAggregatorProxy.sol"; +import {BaseTest} from "./BaseTest.t.sol"; + +// from contracts directory, +// forge test --match-path src/v0.8/automation/test/HeartbeatRequester.t.sol + +contract HeartbeatRequesterSetUp is BaseTest { + HeartbeatRequester internal heartbeatRequester; + MockAggregator internal aggregator; + IAggregatorProxy internal aggregatorProxy; + MockAggregator internal aggregator2; + IAggregatorProxy internal aggregatorProxy2; + + event HeartbeatPermitted(address indexed permittedCaller, address newProxy, address oldProxy); + event HeartbeatRemoved(address indexed permittedCaller, address removedProxy); + error HeartbeatNotPermitted(); + + function setUp() public override { + BaseTest.setUp(); + heartbeatRequester = new HeartbeatRequester(); + aggregator = new MockAggregator(); + aggregatorProxy = IAggregatorProxy(new MockAggregatorProxy(address(aggregator))); + aggregator2 = new MockAggregator(); + aggregatorProxy2 = IAggregatorProxy(new MockAggregatorProxy(address(aggregator2))); + } +} + +contract HeartbeatRequester_permitHeartbeat is HeartbeatRequesterSetUp { + function testBasicSuccess() public { + vm.expectEmit(); + emit HeartbeatPermitted(STRANGER, address(aggregatorProxy), address(0)); + heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); + + vm.expectEmit(); + emit HeartbeatPermitted(STRANGER, address(aggregatorProxy2), address(aggregatorProxy)); + heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy2); + } + + function testBasicDeployerSuccess() public { + vm.expectEmit(); + emit HeartbeatPermitted(OWNER, address(aggregatorProxy), address(0)); + heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy); + + vm.expectEmit(); + emit HeartbeatPermitted(OWNER, address(aggregatorProxy2), address(aggregatorProxy)); + heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy2); + } + + function testOnlyCallableByOwnerReverts() public { + vm.expectRevert(bytes("Only callable by owner")); + changePrank(STRANGER); + heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); + } +} + +contract HeartbeatRequester_removeHeartbeat is HeartbeatRequesterSetUp { + function testBasicSuccess() public { + vm.expectEmit(); + emit HeartbeatPermitted(STRANGER, address(aggregatorProxy), address(0)); + heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); + + vm.expectEmit(); + emit HeartbeatRemoved(STRANGER, address(aggregatorProxy)); + heartbeatRequester.removeHeartbeat(STRANGER); + } + + function testRemoveNoPermitsSuccess() public { + vm.expectEmit(); + emit HeartbeatRemoved(STRANGER, address(0)); + heartbeatRequester.removeHeartbeat(STRANGER); + } + + function testOnlyCallableByOwnerReverts() public { + vm.expectRevert(bytes("Only callable by owner")); + changePrank(STRANGER); + heartbeatRequester.removeHeartbeat(address(this)); + } +} + +contract HeartbeatRequester_getAggregatorRequestHeartbeat is HeartbeatRequesterSetUp { + function testBasicSuccess() public { + vm.expectEmit(); + emit HeartbeatPermitted(OWNER, address(aggregatorProxy), address(0)); + heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy); + heartbeatRequester.getAggregatorAndRequestHeartbeat(address(aggregatorProxy)); + // getter for newRoundCalled value + bool val = aggregator.newRoundCalled(); + assertEq(val, true); + } + + function testHeartbeatNotPermittedReverts() public { + bytes32 hashedReason = keccak256(abi.encodePacked("HeartbeatNotPermitted()")); + bytes memory revertMessage = bytes32ToBytes(hashedReason); + vm.expectRevert(revertMessage); + heartbeatRequester.getAggregatorAndRequestHeartbeat(address(aggregatorProxy)); + bool val = aggregator.newRoundCalled(); + assertFalse(val); + } + + function bytes32ToBytes(bytes32 _bytes32) public pure returns (bytes memory) { + bytes memory bytesArray = new bytes(4); + for (uint256 i; i < 4; ++i) { + bytesArray[i] = _bytes32[i]; + } + return bytesArray; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol new file mode 100644 index 0000000..4018c76 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol @@ -0,0 +1,336 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; +import "../dev/MercuryRegistry.sol"; +import "../dev/MercuryRegistryBatchUpkeep.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; + +contract MercuryRegistryTest is Test { + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + int192 internal constant DEVIATION_THRESHOLD = 10_000; // 1% + uint32 internal constant STALENESS_SECONDS = 3600; // 1 hour + + address s_verifier = 0x60448B880c9f3B501af3f343DA9284148BD7D77C; + + string[] feedIds; + string s_BTCUSDFeedId = "0x6962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb2"; + string s_ETHUSDFeedId = "0xf753e1201d54ac94dfd9334c542562ff7e42993419a661261d010af0cbfd4e34"; + MercuryRegistry s_testRegistry; + + // Feed: BTC/USD + // Date: Tuesday, August 22, 2023 7:29:28 PM + // Price: $25,857.11126720 + bytes s_august22BTCUSDMercuryReport = + hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad00000000000000000000000000000000000000000000000000000000014cb94e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e50c980000000000000000000000000000000000000000000000000000025a0864a8c00000000000000000000000000000000000000000000000000000025a063481720000000000000000000000000000000000000000000000000000025a0a94d00f000000000000000000000000000000000000000000000000000000000226181f4733a6d98892d1821771c041d5d69298210fdca9d643ad74477423b6a3045647000000000000000000000000000000000000000000000000000000000226181f0000000000000000000000000000000000000000000000000000000064e50c9700000000000000000000000000000000000000000000000000000000000000027f3056b1b71dd516037afd2e636f8afb39853f5cb3ccaa4b02d6f9a2a64622534e94aa1f794f6a72478deb7e0eb2942864b7fac76d6e120bd809530b1b74a32b00000000000000000000000000000000000000000000000000000000000000027bd3b385c0812dfcad2652d225410a014a0b836cd9635a6e7fb404f65f7a912f0b193db57e5c4f38ce71f29170f7eadfa94d972338858bacd59ab224245206db"; + + // Feed: BTC/USD + // Date: Wednesday, August 23, 2023 7:55:02 PM + // Price: $26,720.37346975 + bytes s_august23BTCUSDMercuryReport = + hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad000000000000000000000000000000000000000000000000000000000159a630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e664160000000000000000000000000000000000000000000000000000026e21d63e9f0000000000000000000000000000000000000000000000000000026e2147576a0000000000000000000000000000000000000000000000000000026e226525d30000000000000000000000000000000000000000000000000000000002286ce7c44fa27f67f6dd0a8bb40c12f0f050231845789f022a82aa5f4b3fe5bf2068fb0000000000000000000000000000000000000000000000000000000002286ce70000000000000000000000000000000000000000000000000000000064e664150000000000000000000000000000000000000000000000000000000000000002e9c5857631172082a47a20aa2fd9f580c1c48275d030c17a2dff77da04f88708ce776ef74c04b9ef6ba87c56d8f8c57e80ddd5298b477d60dd49fb8120f1b9ce000000000000000000000000000000000000000000000000000000000000000248624e0e2341cdaf989098f8b3dee2660b792b24e5251d6e48e3abe0a879c0683163a3a199969010e15353a99926d113f6d4cbab9d82ae90a159af9f74f8c157"; + + // Feed: BTC/USD + // Date: Wednesday, August 23, 2023 8:13:28 PM + // Price: $26,559.67100000 + bytes s_august23BTCUSDMercuryReport_2 = + hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad000000000000000000000000000000000000000000000000000000000159d009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e668690000000000000000000000000000000000000000000000000000026a63f9bc600000000000000000000000000000000000000000000000000000026a635984c00000000000000000000000000000000000000000000000000000026a67bb929d00000000000000000000000000000000000000000000000000000000022873e999d3ff9b644bba530af933dfaa6c59e31c3e232fcaa1e5f7304e2e79d939da1900000000000000000000000000000000000000000000000000000000022873e80000000000000000000000000000000000000000000000000000000064e66868000000000000000000000000000000000000000000000000000000000000000247c21657a6c2795986e95081876bf8b5f24bf72abd2dc4c601e7c96d654bcf543b5bb730e3d4736a308095e4531e7c03f581ac364f0889922ba3ae24b7cf968000000000000000000000000000000000000000000000000000000000000000020d3037d9f55256a001a2aa79ea746526c7cb36747e1deb4c804311394b4027667e5b711bcecfe60632e86cf8e83c28d1465e2d8d90bc0638dad8347f55488e8e"; + + // Feed: ETH/USD + // Date: Wednesday, August 23, 2023 7:55:01 PM + // Price: $1,690.76482169 + bytes s_august23ETHUSDMercuryReport = + hex"0006c41ec94138ae62cce3f1a2b852e42fe70359502fa7b6bdbf81207970d88e00000000000000000000000000000000000000000000000000000000016d874d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120f753e1201d54ac94dfd9334c542562ff7e42993419a661261d010af0cbfd4e340000000000000000000000000000000000000000000000000000000064e66415000000000000000000000000000000000000000000000000000000275dbe6079000000000000000000000000000000000000000000000000000000275c905eba000000000000000000000000000000000000000000000000000000275e5693080000000000000000000000000000000000000000000000000000000002286ce7c44fa27f67f6dd0a8bb40c12f0f050231845789f022a82aa5f4b3fe5bf2068fb0000000000000000000000000000000000000000000000000000000002286ce70000000000000000000000000000000000000000000000000000000064e664150000000000000000000000000000000000000000000000000000000000000002a2b01f7741563cfe305efaec43e56cd85731e3a8e2396f7c625bd16adca7b39c97805b6170adc84d065f9d68c87104c3509aeefef42c0d1711e028ace633888000000000000000000000000000000000000000000000000000000000000000025d984ad476bda9547cf0f90d32732dc5a0d84b0e2fe9795149b786fb05332d4c092e278b4dddeef45c070b818c6e221db2633b573d616ef923c755a145ea099c"; + + // Feed: USDC/USD + // Date: Wednesday, August 30, 2023 5:05:01 PM + // Price: $1.00035464 + bytes s_august30USDCUSDMercuryReport = + hex"0006970c13551e2a390246f5eccb62b9be26848e72026830f4688f49201b5a050000000000000000000000000000000000000000000000000000000001c89843000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120a5b07943b89e2c278fc8a2754e2854316e03cb959f6d323c2d5da218fb6b0ff80000000000000000000000000000000000000000000000000000000064ef69fa0000000000000000000000000000000000000000000000000000000005f5da000000000000000000000000000000000000000000000000000000000005f5b0f80000000000000000000000000000000000000000000000000000000005f5f8b0000000000000000000000000000000000000000000000000000000000240057307d0a0421d25328cb6dcfc5d0e211ff0580baaaf104e9877fc52cf2e8ec0aa7d00000000000000000000000000000000000000000000000000000000024005730000000000000000000000000000000000000000000000000000000064ef69fa0000000000000000000000000000000000000000000000000000000000000002b9e7fb46f1e9d22a1156024dc2bbf2bc6d337e0a2d78aaa3fb6e43b880217e5897732b516e39074ef4dcda488733bfee80c0a10714b94621cd93df6842373cf5000000000000000000000000000000000000000000000000000000000000000205ca5f8da9d6ae01ec6d85c681e536043323405b3b8a15e4d2a288e02dac32f10b2294593e270a4bbf53b0c4978b725293e85e49685f1d3ce915ff670ab6612f"; + + function setUp() public virtual { + // Set owner, and fork Arbitrum Goerli Testnet (chain ID 421613). + // The fork is only used with the `FORK_TEST` flag enabeld, as to not disrupt CI. For CI, a mock verifier is used instead. + vm.startPrank(OWNER); + try vm.envBool("FORK_TEST") returns (bool /* fork testing enabled */) { + vm.selectFork(vm.createFork("https://goerli-rollup.arbitrum.io/rpc")); + } catch { + s_verifier = address(new MockVerifierProxy()); + } + vm.chainId(31337); // restore chain Id + + // Use a BTC feed and ETH feed. + feedIds = new string[](2); + feedIds[0] = s_BTCUSDFeedId; + feedIds[1] = s_ETHUSDFeedId; + + // Deviation threshold and staleness are the same for all feeds. + int192[] memory thresholds = new int192[](1); + thresholds[0] = DEVIATION_THRESHOLD; + uint32[] memory stalenessSeconds = new uint32[](1); + stalenessSeconds[0] = STALENESS_SECONDS; + + // Initialize with BTC feed. + string[] memory initialFeedIds = new string[](1); + initialFeedIds[0] = feedIds[0]; + string[] memory initialFeedNames = new string[](1); + initialFeedNames[0] = "BTC/USD"; + s_testRegistry = new MercuryRegistry( + initialFeedIds, + initialFeedNames, + thresholds, + stalenessSeconds, + address(0) // verifier unset + ); + s_testRegistry.setVerifier(s_verifier); // set verifier + + // Add ETH feed. + string[] memory addedFeedIds = new string[](1); + addedFeedIds[0] = feedIds[1]; + string[] memory addedFeedNames = new string[](1); + addedFeedNames[0] = "ETH/USD"; + s_testRegistry.addFeeds(addedFeedIds, addedFeedNames, thresholds, stalenessSeconds); + } + + function testMercuryRegistry() public { + // Check upkeep, receive Mercury revert. + uint256 blockNumber = block.number; + vm.expectRevert( + abi.encodeWithSelector( + StreamsLookupCompatibleInterface.StreamsLookup.selector, + "feedIdHex", // feedParamKey + feedIds, // feed Ids + "blockNumber", // timeParamKey + blockNumber, // block number on which request is occuring + "" // extra data + ) + ); + s_testRegistry.checkUpkeep(""); + + // Obtain mercury report off-chain (for August 22 BTC/USD price) + bytes[] memory values = new bytes[](1); + values[0] = s_august22BTCUSDMercuryReport; + + // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. + (bool shouldPerformUpkeep, bytes memory performData) = s_testRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, true); + + // Perform upkeep to update on-chain state. + s_testRegistry.performUpkeep(performData); + + // Check state of BTC/USD feed to ensure update was propagated. + bytes memory oldPerformData; + uint32 oldObservationsTimestamp; + { + // scoped to prevent stack-too-deep error + ( + uint32 observationsTimestamp, + int192 price, + int192 bid, + int192 ask, + string memory feedName, + string memory localFeedId, + bool active, + int192 deviationPercentagePPM, + uint32 stalenessSeconds + ) = s_testRegistry.s_feedMapping(s_BTCUSDFeedId); + assertEq(observationsTimestamp, 1692732568); // Tuesday, August 22, 2023 7:29:28 PM + assertEq(bid, 2585674416498); // $25,856.74416498 + assertEq(price, 2585711126720); // $25,857.11126720 + assertEq(ask, 2585747836943); // $25,857.47836943 + assertEq(feedName, "BTC/USD"); + assertEq(localFeedId, s_BTCUSDFeedId); + assertEq(active, true); + assertEq(deviationPercentagePPM, DEVIATION_THRESHOLD); + assertEq(stalenessSeconds, STALENESS_SECONDS); + + // Save this for later in the test. + oldPerformData = performData; + oldObservationsTimestamp = observationsTimestamp; + } + // Obtain mercury report off-chain (for August 23 BTC/USD price & ETH/USD price) + values = new bytes[](2); + values[0] = s_august23BTCUSDMercuryReport; + values[1] = s_august23ETHUSDMercuryReport; + + // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. + (shouldPerformUpkeep, performData) = s_testRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, true); + + // Perform upkeep to update on-chain state. + s_testRegistry.performUpkeep(performData); + + // Make a batch request for both the BTC/USD feed data and the ETH/USD feed data. + MercuryRegistry.Feed[] memory feeds = s_testRegistry.getLatestFeedData(feedIds); + + // Check state of BTC/USD feed to ensure update was propagated. + assertEq(feeds[0].observationsTimestamp, 1692820502); // Wednesday, August 23, 2023 7:55:02 PM + assertEq(feeds[0].bid, 2672027981674); // $26,720.27981674 + assertEq(feeds[0].price, 2672037346975); // $26,720.37346975 + assertEq(feeds[0].ask, 2672046712275); // $26,720.46712275 + assertEq(feeds[0].feedName, "BTC/USD"); + assertEq(feeds[0].feedId, s_BTCUSDFeedId); + + // Check state of ETH/USD feed to ensure update was propagated. + assertEq(feeds[1].observationsTimestamp, 1692820501); // Wednesday, August 23, 2023 7:55:01 PM + assertEq(feeds[1].bid, 169056689850); // $1,690.56689850 + assertEq(feeds[1].price, 169076482169); // $1,690.76482169 + assertEq(feeds[1].ask, 169086456584); // $16,90.86456584 + assertEq(feeds[1].feedName, "ETH/USD"); + assertEq(feeds[1].feedId, s_ETHUSDFeedId); + assertEq(feeds[1].active, true); + assertEq(feeds[1].deviationPercentagePPM, DEVIATION_THRESHOLD); + assertEq(feeds[1].stalenessSeconds, STALENESS_SECONDS); + + // Obtain mercury report off-chain for August 23 BTC/USD price (second report of the day). + // The price of this incoming report will not deviate enough from the on-chain value to trigger an update, + // nor is the on-chain data stale enough. + values = new bytes[](1); + values[0] = s_august23BTCUSDMercuryReport_2; + + // Pass the obtained mercury report into checkCallback, to assert that an update is not warranted. + (shouldPerformUpkeep, performData) = s_testRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, false); + + // Ensure stale reports cannot be included. + vm.expectRevert( + abi.encodeWithSelector( + MercuryRegistry.StaleReport.selector, + feedIds[0], + feeds[0].observationsTimestamp, + oldObservationsTimestamp + ) + ); + s_testRegistry.performUpkeep(oldPerformData); + + // Ensure reports for inactive feeds cannot be included. + bytes[] memory inactiveFeedReports = new bytes[](1); + inactiveFeedReports[0] = s_august30USDCUSDMercuryReport; + bytes memory lookupData = ""; + vm.expectRevert( + abi.encodeWithSelector( + MercuryRegistry.FeedNotActive.selector, + "0xa5b07943b89e2c278fc8a2754e2854316e03cb959f6d323c2d5da218fb6b0ff8" // USDC/USD feed id + ) + ); + s_testRegistry.performUpkeep(abi.encode(inactiveFeedReports, lookupData)); + } + + // Below are the same tests as `testMercuryRegistry`, except done via a batching Mercury registry that + // consumes the test registry. This is to assert that batching can be accomplished by multiple different + // upkeep jobs, which can populate the same + function testMercuryRegistryBatchUpkeep() public { + MercuryRegistryBatchUpkeep batchedRegistry = new MercuryRegistryBatchUpkeep( + address(s_testRegistry), // use the test registry as master registry + 0, // start batch at index 0. + 50 // end batch beyond length of feed Ids (take responsibility for all feeds) + ); + // Check upkeep, receive Mercury revert. + uint256 blockNumber = block.number; + vm.expectRevert( + abi.encodeWithSelector( + StreamsLookupCompatibleInterface.StreamsLookup.selector, + "feedIdHex", // feedParamKey + feedIds, // feed Ids + "blockNumber", // timeParamKey + blockNumber, // block number on which request is occuring + "" // extra data + ) + ); + batchedRegistry.checkUpkeep(""); + + // Obtain mercury report off-chain (for August 22 BTC/USD price) + bytes[] memory values = new bytes[](1); + values[0] = s_august22BTCUSDMercuryReport; + + // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. + (bool shouldPerformUpkeep, bytes memory performData) = batchedRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, true); + + // Perform upkeep to update on-chain state. + batchedRegistry.performUpkeep(performData); + + // Check state of BTC/USD feed to ensure update was propagated. + ( + uint32 observationsTimestamp, + int192 price, + int192 bid, + int192 ask, + string memory feedName, + string memory localFeedId, + bool active, + int192 deviationPercentagePPM, + uint32 stalenessSeconds + ) = s_testRegistry.s_feedMapping(s_BTCUSDFeedId); + assertEq(observationsTimestamp, 1692732568); // Tuesday, August 22, 2023 7:29:28 PM + assertEq(bid, 2585674416498); // $25,856.74416498 + assertEq(price, 2585711126720); // $25,857.11126720 + assertEq(ask, 2585747836943); // $25,857.47836943 + assertEq(feedName, "BTC/USD"); + assertEq(localFeedId, s_BTCUSDFeedId); + assertEq(active, true); + assertEq(deviationPercentagePPM, DEVIATION_THRESHOLD); + assertEq(stalenessSeconds, STALENESS_SECONDS); + + // Obtain mercury report off-chain (for August 23 BTC/USD price & ETH/USD price) + values = new bytes[](2); + values[0] = s_august23BTCUSDMercuryReport; + values[1] = s_august23ETHUSDMercuryReport; + + // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. + (shouldPerformUpkeep, performData) = batchedRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, true); + + // Perform upkeep to update on-chain state, but with not enough gas to update both feeds. + batchedRegistry.performUpkeep{gas: 250_000}(performData); + + // Make a batch request for both the BTC/USD feed data and the ETH/USD feed data. + MercuryRegistry.Feed[] memory feeds = s_testRegistry.getLatestFeedData(feedIds); + + // Check state of BTC/USD feed to ensure update was propagated. + assertEq(feeds[0].observationsTimestamp, 1692820502); // Wednesday, August 23, 2023 7:55:02 PM + assertEq(feeds[0].bid, 2672027981674); // $26,720.27981674 + assertEq(feeds[0].price, 2672037346975); // $26,720.37346975 + assertEq(feeds[0].ask, 2672046712275); // $26,720.46712275 + assertEq(feeds[0].feedName, "BTC/USD"); + assertEq(feeds[0].feedId, s_BTCUSDFeedId); + + // Check state of ETH/USD feed to observe that the update was not propagated. + assertEq(feeds[1].observationsTimestamp, 0); + assertEq(feeds[1].bid, 0); + assertEq(feeds[1].price, 0); + assertEq(feeds[1].ask, 0); + assertEq(feeds[1].feedName, "ETH/USD"); + assertEq(feeds[1].feedId, s_ETHUSDFeedId); + assertEq(feeds[1].active, true); + assertEq(feeds[1].deviationPercentagePPM, DEVIATION_THRESHOLD); + assertEq(feeds[1].stalenessSeconds, STALENESS_SECONDS); + + // Try again, with sufficient gas to update both feeds. + batchedRegistry.performUpkeep{gas: 2_500_000}(performData); + feeds = s_testRegistry.getLatestFeedData(feedIds); + + // Check state of ETH/USD feed to ensure update was propagated. + assertEq(feeds[1].observationsTimestamp, 1692820501); // Wednesday, August 23, 2023 7:55:01 PM + assertEq(feeds[1].bid, 169056689850); // $1,690.56689850 + assertEq(feeds[1].price, 169076482169); // $1,690.76482169 + assertEq(feeds[1].ask, 169086456584); // $16,90.86456584 + assertEq(feeds[1].feedName, "ETH/USD"); + assertEq(feeds[1].feedId, s_ETHUSDFeedId); + + // Obtain mercury report off-chain for August 23 BTC/USD price (second report of the day). + // The price of this incoming report will not deviate enough from the on-chain value to trigger an update. + values = new bytes[](1); + values[0] = s_august23BTCUSDMercuryReport_2; + + // Pass the obtained mercury report into checkCallback, to assert that an update is not warranted. + (shouldPerformUpkeep, performData) = batchedRegistry.checkCallback(values, bytes("")); + assertEq(shouldPerformUpkeep, false); + } +} + +contract MockVerifierProxy is IVerifierProxy { + function verify(bytes calldata payload) external payable override returns (bytes memory) { + (, bytes memory reportData, , , ) = abi.decode(payload, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); + return reportData; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol new file mode 100644 index 0000000..1225e6e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol @@ -0,0 +1,93 @@ +// Submitted for verification at Etherscan.io on 2017-12-12 + +// Copyright (C) 2015, 2016, 2017 Dapphub + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +pragma solidity 0.8.19; + +contract WETH9 { + string public name = "Wrapped Ether"; + string public symbol = "WETH"; + uint8 public decimals = 18; + + event Approval(address indexed src, address indexed guy, uint256 wad); + event Transfer(address indexed src, address indexed dst, uint256 wad); + event Deposit(address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + + error InsufficientBalance(); + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + receive() external payable { + _deposit(); + } + + function _deposit() internal { + balanceOf[msg.sender] += msg.value; + emit Deposit(msg.sender, msg.value); + } + + function deposit() external payable { + _deposit(); + } + + function mint(address account, uint256 amount) public { + balanceOf[account] += amount; + } + + function withdraw(uint256 wad) external { + if (balanceOf[msg.sender] < wad) { + revert InsufficientBalance(); + } + balanceOf[msg.sender] -= wad; + payable(msg.sender).call{value: wad}(""); + emit Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint256) { + return address(this).balance; + } + + function approve(address guy, uint256 wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + emit Approval(msg.sender, guy, wad); + return true; + } + + function transfer(address dst, uint256 wad) public returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + function transferFrom(address src, address dst, uint256 wad) public returns (bool) { + if (balanceOf[src] < wad) { + revert InsufficientBalance(); + } + + if (src != msg.sender && allowance[src][msg.sender] != type(uint128).max) { + if (allowance[src][msg.sender] < wad) { + revert InsufficientBalance(); + } + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + emit Transfer(src, dst, wad); + + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol new file mode 100644 index 0000000..171e4e3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {IAutomationRegistryMaster2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; + +// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol + +contract SetUp is BaseTest { + IAutomationRegistryMaster2_3 internal registry; + AutomationRegistrar2_3 internal registrar; + + function setUp() public override { + super.setUp(); + vm.startPrank(OWNER); + (registry, registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + vm.stopPrank(); // reset identity at the start of each test + } +} + +contract CancelUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + // cancel the upkeep + vm.startPrank(OWNER); + bytes32 hash = keccak256(abi.encode(registrationParams)); + registrar.cancel(hash); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startUpkeepAdminBalance + amount, endUpkeepAdminBalance); + } +} + +contract ApproveUpkeep is SetUp { + function testUSDToken_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // default is auto approve off + registrar.registerUpkeep(registrationParams); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 startRegistryBalance = usdToken18.balanceOf(address(registry)); + + // approve the upkeep + vm.startPrank(OWNER); + registrar.approve(registrationParams); + + uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); + uint256 endRegistryBalance = usdToken18.balanceOf(address(registry)); + + assertEq(startRegistrarBalance - amount, endRegistrarBalance); + assertEq(startRegistryBalance + amount, endRegistryBalance); + } +} + +contract RegisterUpkeep is SetUp { + function testLink_autoApproveOff_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount); + + registrar.registerUpkeep( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(linkToken.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + } + + function testUSDToken_autoApproveOff_happy() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + registrar.registerUpkeep( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(usdToken18.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + } + + function testLink_autoApproveOn_happy() external { + vm.startPrank(OWNER); + registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); + + vm.startPrank(UPKEEP_ADMIN); + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount); + + registrar.registerUpkeep( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(linkToken.balanceOf(address(registrar)), 0); + assertEq(linkToken.balanceOf(address(registry)), amount); + assertEq(registry.getNumUpkeeps(), 1); + } + + function testUSDToken_autoApproveOn_happy() external { + vm.startPrank(OWNER); + registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); + + vm.startPrank(UPKEEP_ADMIN); + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); + + registrar.registerUpkeep( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: usdToken18, + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(usdToken18.balanceOf(address(registrar)), 0); + assertEq(usdToken18.balanceOf(address(registry)), amount); + assertEq(registry.getNumUpkeeps(), 1); + } + + function testNative_autoApproveOn_happy() external { + vm.startPrank(OWNER); + registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); + + vm.startPrank(UPKEEP_ADMIN); + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); + IWrappedNative(address(weth)).approve(address(registrar), amount); + + registrar.registerUpkeep{value: amount}( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: 0, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(weth)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(weth.balanceOf(address(registrar)), 0); + assertEq(weth.balanceOf(address(registry)), amount); + assertEq(registry.getNumUpkeeps(), 1); + } + + // when msg.value is 0, it uses the ERC20 payment path + function testNative_autoApproveOff_msgValue0() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); + IWrappedNative(address(weth)).approve(address(registrar), amount); + + registrar.registerUpkeep( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(weth)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(weth.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + } + + // when msg.value is not 0, it uses the native payment path + function testNative_autoApproveOff_msgValueNot0() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); + IWrappedNative(address(weth)).approve(address(registrar), amount); + + registrar.registerUpkeep{value: amount}( + AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: 0, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(weth)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }) + ); + + assertEq(weth.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + } + + function testLink_autoApproveOff_revertOnDuplicateEntry() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount * 2); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + registrar.registerUpkeep(params); + + assertEq(linkToken.balanceOf(address(registrar)), amount); + assertEq(registry.getNumUpkeeps(), 0); + + // attempt to register the same upkeep again + vm.expectRevert(AutomationRegistrar2_3.DuplicateEntry.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInsufficientPayment() external { + vm.startPrank(UPKEEP_ADMIN); + + // slightly less than the minimum amount + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))) - 1); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of insufficient payment + vm.expectRevert(AutomationRegistrar2_3.InsufficientPayment.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidAdminAddress() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); + linkToken.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: ZERO_ADDRESS, // zero address is invalid + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(linkToken)), + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidAdminAddress.selector); + registrar.registerUpkeep(params); + } + + function test_revertOnInvalidBillingToken() external { + vm.startPrank(UPKEEP_ADMIN); + + uint96 amount = 1; + usdToken18_2.approve(address(registrar), amount); + + AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ + upkeepContract: address(TARGET1), + amount: amount, + adminAddress: UPKEEP_ADMIN, + gasLimit: 10_000, + triggerType: 0, + billingToken: IERC20(address(usdToken18_2)), // unsupported billing token + name: "foobar", + encryptedEmail: "", + checkData: bytes("check data"), + triggerConfig: "", + offchainConfig: "" + }); + + // attempt to register but revert bc of invalid admin address + vm.expectRevert(AutomationRegistrar2_3.InvalidBillingToken.selector); + registrar.registerUpkeep(params); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol new file mode 100644 index 0000000..41aabf1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol @@ -0,0 +1,2753 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {Vm} from "forge-std/Test.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; + +// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol + +enum Trigger { + CONDITION, + LOG +} + +contract SetUp is BaseTest { + Registry internal registry; + AutomationRegistryBase2_3.OnchainConfig internal config; + bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); + + uint256 internal linkUpkeepID; + uint256 internal linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario + uint256 internal usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals + uint256 internal usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals + uint256 internal nativeUpkeepID; + + function setUp() public virtual override { + super.setUp(); + (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + config = registry.getConfig(); + + vm.startPrank(OWNER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(UPKEEP_ADMIN); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(STRANGER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.stopPrank(); + + linkUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + linkUpkeepID2 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + usdUpkeepID18 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken18), + "", + "", + "" + ); + + usdUpkeepID6 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken6), + "", + "", + "" + ); + + nativeUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(weth), + "", + "", + "" + ); + + vm.startPrank(OWNER); + registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); + registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); + registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); + registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); + registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); + vm.stopPrank(); + } +} + +contract LatestConfigDetails is SetUp { + function testGet() public { + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails(); + assertEq(configCount, 1); + assertTrue(blockNumber > 0); + assertNotEq(configDigest, ""); + } +} + +contract CheckUpkeep is SetUp { + function testPreventExecutionOnCheckUpkeep() public { + uint256 id = 1; + bytes memory triggerData = abi.encodePacked("trigger_data"); + + // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry + // Expecting a revert since the tx.origin is not address(0) + vm.expectRevert(abi.encodeWithSelector(Registry.OnlySimulatedBackend.selector)); + registry.checkUpkeep(id, triggerData); + } +} + +contract WithdrawFunds is SetUp { + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.withdrawFunds(linkUpkeepID, STRANGER); + } + + function test_RevertsWhen_InvalidRecipient() external { + vm.expectRevert(Registry.InvalidRecipient.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); + } + + function test_RevertsWhen_UpkeepNotCanceled() external { + vm.expectRevert(Registry.UpkeepNotCanceled.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_Happy_Link() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); + uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); + + uint256 upkeepBalance = registry.getBalance(linkUpkeepID); + vm.expectEmit(); + emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); + } + + function test_Happy_USDToken() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(usdUpkeepID6); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); + uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); + + uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); + vm.expectEmit(); + emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); + + assertEq(registry.getBalance(usdUpkeepID6), 0); + assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); + } +} + +contract AddFunds is SetUp { + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + + // when msg.value is 0, it uses the ERC20 payment path + function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { + vm.startPrank(OWNER); + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds(nativeUpkeepID, 1); + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // when msg.value is not 0, it uses the native payment path + function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // it fails when the billing token is not native, but trying to pay with native + function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.addFunds{value: 1}(linkUpkeepID, 0); + } + + function test_RevertsWhen_UpkeepDoesNotExist() public { + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(randomNumber(), 1); + } + + function test_RevertsWhen_UpkeepIsCanceled() public { + registry.cancelUpkeep(linkUpkeepID); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(linkUpkeepID, 1); + } + + function test_anyoneCanAddFunds() public { + uint256 startAmount = registry.getBalance(linkUpkeepID); + vm.prank(UPKEEP_ADMIN); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); + vm.prank(STRANGER); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); + } + + function test_movesFundFromCorrectToken() public { + vm.startPrank(UPKEEP_ADMIN); + + uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); + uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); + uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); + uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); + + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); + + registry.addFunds(usdUpkeepID18, 2); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); + } + + function test_emitsAnEvent() public { + vm.startPrank(UPKEEP_ADMIN); + vm.expectEmit(); + emit FundsAdded(linkUpkeepID, address(UPKEEP_ADMIN), 100); + registry.addFunds(linkUpkeepID, 100); + } +} + +contract Withdraw is SetUp { + address internal aMockAddress = randomAddress(); + + function testLinkAvailableForPaymentReturnsLinkBalance() public { + uint256 startBalance = linkToken.balanceOf(address(registry)); + int256 startLinkAvailable = registry.linkAvailableForPayment(); + + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + + //check there's a balance + assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); + + //check the link available has increased by the same amount + assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); + } + + function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.withdrawLink(aMockAddress, 1); + } + + function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); + registry.withdrawLink(ZERO_ADDRESS, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkSuccess() public { + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + uint256 startBalance = linkToken.balanceOf(address(registry)); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is a ton of link available + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + + assertEq(linkToken.balanceOf(address(aMockAddress)), 1); + assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); + } + + function test_WithdrawERC20Fees_RespectsReserveAmount() public { + assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); + } + + function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { + _mintLink(address(registry), 1e10); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(Registry.InvalidToken.selector); + registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert + registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds + } + + // default is ON_CHAIN mode + function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { + _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert + _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw + } + + function test_WithdrawERC20Fees_InOffChainMode_Happy() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw + + // recipient should get the funds + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + } + + function testWithdrawERC20FeeSuccess() public { + // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) + uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); + uint256 startAmount = usdToken18.balanceOf(address(registry)); + _mintERC20_18Decimals(address(registry), 1e10); + + // depositing shouldn't change reserve amount + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 USDToken + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); + + vm.stopPrank(); + + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + } +} + +contract SetConfig is SetUp { + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + address module = address(new ChainModuleBase()); + + AutomationRegistryBase2_3.OnchainConfig cfg = + AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: _getRegistrars(), + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + function testSetConfigSuccess() public { + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); + assertEq(config.gasFeePPB, 5_000); + assertEq(config.flatFeeMilliCents, 20_000); + assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config.minSpend, 100_000); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigMultipleBillingConfigsSuccess() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); + assertEq(config1.gasFeePPB, 5_001); + assertEq(config1.flatFeeMilliCents, 20_001); + assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config1.fallbackPrice, 100); + assertEq(config1.minSpend, 100); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 2); + } + + function testSetConfigTwiceAndLastSetOverwrites() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + // BillingConfig1 + address billingTokenAddress1 = address(usdToken18); + address[] memory billingTokens1 = new address[](1); + billingTokens1[0] = billingTokenAddress1; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs1 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + + // the first time uses the default onchain config with 2 registrars + bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); + + // set config once + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling1, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig1, , , ) = registry.getState(); + assertEq(onchainConfig1.registrars.length, 2); + + // BillingConfig2 + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens2 = new address[](1); + billingTokens2[0] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs2 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + address[] memory newRegistrars = new address[](3); + newRegistrars[0] = address(uint160(uint256(keccak256("newRegistrar1")))); + newRegistrars[1] = address(uint160(uint256(keccak256("newRegistrar2")))); + newRegistrars[2] = address(uint160(uint256(keccak256("newRegistrar3")))); + + // new onchain config with 3 new registrars, all other fields stay the same as the default + AutomationRegistryBase2_3.OnchainConfig memory cfg2 = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: newRegistrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + // the second time uses the new onchain config with 3 new registrars and also new billing tokens/configs + bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg2, billingTokens2, billingConfigs2); + + // set config twice + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling2, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + ( + , + IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig2, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) = registry.getState(); + + assertEq(onchainConfig2.registrars.length, 3); + for (uint256 i = 0; i < newRegistrars.length; i++) { + assertEq(newRegistrars[i], onchainConfig2.registrars[i]); + } + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigDuplicateBillingConfigFailure() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(linkToken); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + // expect revert because of duplicate tokens + vm.expectRevert(abi.encodeWithSelector(Registry.DuplicateEntry.selector)); + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + } + + function testSetConfigRevertDueToInvalidToken() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + // deploy registry with OFF_CHAIN payout mode + registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigRevertDueToInvalidDecimals() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 6 // link token should have 18 decimals + }); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigOnTransmittersAndPayees() public { + registry.setPayees(PAYEES); + AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry + .getTransmittersWithPayees(); + assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); + + for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { + address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; + address payeeAddress = transmitterPayeeInfos[i].payeeAddress; + + address expectedTransmitter = TRANSMITTERS[i]; + address expectedPayee = PAYEES[i]; + + assertEq(transmitterAddress, expectedTransmitter); + assertEq(payeeAddress, expectedPayee); + } + } + + function testSetConfigWithNewTransmittersSuccess() public { + registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 0); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + + (configCount, blockNumber, ) = registry.latestConfigDetails(); + configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , signers, transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, NEW_TRANSMITTERS); + } + + function _getRegistrars() private pure returns (address[] memory) { + address[] memory registrars = new address[](2); + registrars[0] = address(uint160(uint256(keccak256("registrar1")))); + registrars[1] = address(uint160(uint256(keccak256("registrar2")))); + return registrars; + } + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } +} + +contract NOPsSettlement is SetUp { + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + + function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainRevertDueToOffchainSettlementDisabled() public { + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + vm.prank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOnchain.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + payments[i] = 0; + } + + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + } + + // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same + function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + // verify transmitters have positive balances + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertTrue(balance > 0); + assertEq(0, lastCollected); + + payments[i] = balance; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + + // verify that transmitters balance has been zeroed out + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + // should have some ERC20s in registry after transmit + uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); + + vm.startPrank(UPKEEP_ADMIN); + vm.roll(100 + block.number); + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); + + // finance admin comes to withdraw all available ERC20s + vm.startPrank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); + + uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); + + uint256 reservedLink = registry.getReserveAmount(address(linkToken)); + require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); + + // owner comes to disable offchain mode + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity + vm.startPrank(FINANCE_ADMIN); + uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); + + // reserved link amount to NOPs should stay the same after switching to onchain mode + assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); + // available ERC20 for payment should be 0 since finance admin withdrew all already + assertEq(erc20ForPayment4, 0); + } + + function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, Registrar registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so TRANSMITTERS earn some rewards + _transmit(id, registry); + + // TRANSMITTERS have positive balance now + // configure the registry to use NEW_TRANSMITTERS + _configureWithNewTransmitters(registry, registrar); + + _transmit(id, registry); + + // verify all transmitters have positive balances + address[] memory expectedPayees = new address[](6); + uint256[] memory expectedPayments = new uint256[](6); + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + NEW_TRANSMITTERS[i] + ); + assertTrue(active); + assertEq(i, index); + assertTrue(lastCollected > 0); + expectedPayments[i] = balance; + expectedPayees[i] = payee; + } + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + TRANSMITTERS[i] + ); + assertFalse(active); + assertEq(i, index); + assertTrue(balance > 0); + assertTrue(lastCollected > 0); + expectedPayments[2 + i] = balance; + expectedPayees[2 + i] = payee; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + + // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these + // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. + vm.recordLogs(); + registry.settleNOPsOffchain(); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + Vm.Log memory l = entries[0]; + assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); + (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); + assertEq(actualPayees.length, 6); + assertEq(actualPayments.length, 6); + + // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + assertEq(actualPayees[i], expectedPayees[i]); + assertEq(actualPayments[i], expectedPayments[i]); + } + + // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered + assertTrue( + (actualPayments[5] == expectedPayments[5] && + actualPayees[5] == expectedPayees[5] && + actualPayments[4] == expectedPayments[4] && + actualPayees[4] == expectedPayees[4]) || + (actualPayments[5] == expectedPayments[4] && + actualPayees[5] == expectedPayees[4] && + actualPayments[4] == expectedPayments[5] && + actualPayees[4] == expectedPayees[5]) + ); + + // verify that new transmitters balance has been zeroed out + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertFalse(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + } + + function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(bytes("Only callable by owner")); + registry.disableOffchainPayments(); + } + + function testDisableOffchainPaymentsSuccess() public { + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); + } + + function testSinglePerformAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + vm.expectEmit(); + // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value + emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function testMultiplePerformsAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually call transmit so transmitters earn some rewards + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry); + } + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // manually call transmit after offchain payment is disabled + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry); + } + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + uint256 balance = registry.getBalance(id); + vm.expectEmit(); + emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { + IERC20[] memory billingTokens = new IERC20[](1); + billingTokens[0] = IERC20(address(usdToken18)); + + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 10_000_000, // 15% + flatFeeMilliCents: 2_000, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + + address[] memory registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + + registry.setPayees(NEW_PAYEES); + } +} + +contract WithdrawPayment is SetUp { + function testWithdrawPaymentRevertDueToOffchainPayoutMode() public { + registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOffchain.selector)); + vm.prank(TRANSMITTERS[0]); + registry.withdrawPayment(TRANSMITTERS[0], TRANSMITTERS[0]); + } +} + +contract RegisterUpkeep is SetUp { + function test_RevertsWhen_Paused() public { + registry.pause(); + vm.expectRevert(Registry.RegistryPaused.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TargetIsNotAContract() public { + vm.expectRevert(Registry.NotAContract.selector); + registry.registerUpkeep( + randomAddress(), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_CalledByNonOwner() public { + vm.prank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrRegistrar.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooLow() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + 2299, // 1 less than min + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooHigh() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas + 1, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { + vm.expectRevert(Registry.InvalidToken.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + randomAddress(), + "", + "", + "" + ); + } + + function test_RevertsWhen_CheckDataIsTooLarge() public { + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + randomBytes(config.maxCheckDataSize + 1), + "", + "" + ); + } + + function test_Happy() public { + bytes memory checkData = randomBytes(config.maxCheckDataSize); + bytes memory trigggerConfig = randomBytes(100); + bytes memory offchainConfig = randomBytes(100); + + uint256 upkeepCount = registry.getNumUpkeeps(); + + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.LOG), + address(linkToken), + checkData, + trigggerConfig, + offchainConfig + ); + + assertEq(registry.getNumUpkeeps(), upkeepCount + 1); + assertEq(registry.getUpkeep(upkeepID).target, address(TARGET1)); + assertEq(registry.getUpkeep(upkeepID).performGas, config.maxPerformGas); + assertEq(registry.getUpkeep(upkeepID).checkData, checkData); + assertEq(registry.getUpkeep(upkeepID).balance, 0); + assertEq(registry.getUpkeep(upkeepID).admin, UPKEEP_ADMIN); + assertEq(registry.getUpkeep(upkeepID).offchainConfig, offchainConfig); + assertEq(registry.getUpkeepTriggerConfig(upkeepID), trigggerConfig); + assertEq(uint8(registry.getTriggerType(upkeepID)), uint8(Trigger.LOG)); + } +} + +contract OnTokenTransfer is SetUp { + function test_RevertsWhen_NotCalledByTheLinkToken() public { + vm.expectRevert(Registry.OnlyCallableByLINKToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + } + + function test_RevertsWhen_NotCalledWithExactly32Bytes() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(31)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(33)); + } + + function test_RevertsWhen_TheUpkeepIsCancelledOrDNE() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(randomNumber())); + } + + function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); + } + + function test_Happy() public { + vm.startPrank(address(linkToken)); + uint256 beforeBalance = registry.getBalance(linkUpkeepID); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + assertEq(registry.getBalance(linkUpkeepID), beforeBalance + 100); + } +} + +contract GetMinBalanceForUpkeep is SetUp { + function test_accountsForFlatFee_with18Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } + + function test_accountsForFlatFee_with6Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } +} + +contract BillingOverrides is SetUp { + event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + + function test_RevertsWhen_NotPrivilegeManager() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_RevertsWhen_UpkeepCancelled() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(PRIVILEGE_MANAGER); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_SetBillingOverrides() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverridden(linkUpkeepID, billingOverrides); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_RemoveBillingOverrides() public { + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverrideRemoved(linkUpkeepID); + registry.removeBillingOverrides(linkUpkeepID); + } + + function test_Happy_MaxGasPayment_WithBillingOverrides() public { + uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + + // Double the two billing values + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + + // maxPayment2 should be greater than maxPayment1 after the overrides + // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium + // We do not apply the exact equation since we couldn't get the receipt.premium value + uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + assertGt(maxPayment2, maxPayment1); + } +} + +contract Transmit is SetUp { + function test_transmitRevertWithExtraBytes() external { + bytes32[3] memory exampleReportContext = [ + bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef), + bytes32(0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890), + bytes32(0x7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456) + ]; + + bytes memory exampleRawReport = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + + bytes32[] memory exampleRs = new bytes32[](3); + exampleRs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[2] = bytes32(0x7890789078907890789078907890789078907890789078907890789078907890); + + bytes32[] memory exampleSs = new bytes32[](3); + exampleSs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[2] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes32 exampleRawVs = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes memory transmitData = abi.encodeWithSelector( + registry.transmit.selector, + exampleReportContext, + exampleRawReport, + exampleRs, + exampleSs, + exampleRawVs + ); + bytes memory badTransmitData = bytes.concat(transmitData, bytes1(0x00)); // add extra data + vm.startPrank(TRANSMITTERS[0]); + (bool success, bytes memory returnData) = address(registry).call(badTransmitData); // send the bogus transmit + assertFalse(success, "Call did not revert as expected"); + assertEq(returnData, abi.encodePacked(Registry.InvalidDataLength.selector)); + vm.stopPrank(); + } + + function test_handlesMixedBatchOfBillingTokens() external { + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = linkUpkeepID; + upkeepIDs[1] = usdUpkeepID18; + upkeepIDs[2] = nativeUpkeepID; + + // withdraw-able by finance team should be 0 + require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); + require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); + + // do the thing + _transmit(upkeepIDs, registry); + + // withdraw-able by the finance team should be positive + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); + + // assert upkeep balances have decreased + require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); + require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); + require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], usdToken18.balanceOf(address(registry))); + assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), + "usd reserve amount should have increased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), + "usd reserve amount should have decreased" + ); + require( + prevReserveBalances[2] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); + } + + function test_handlesInsufficientBalanceWithUSDToken18() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken18), + "", + "", + "" + ); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 1); // smaller than gasCharge + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(gasChargeInBillingToken, balance); + assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD); + assertEq(premiumInJuels, 0); + assertEq(premiumInBillingToken, 0); + } + + function test_handlesInsufficientBalanceWithUSDToken6() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken6), + "", + "", + "" + ); + vm.prank(OWNER); + usdToken6.mint(UPKEEP_ADMIN, 1e20); + + vm.startPrank(UPKEEP_ADMIN); + usdToken6.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium) + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals + assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12)); + } +} + +contract MigrateReceive is SetUp { + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + + Registry newRegistry; + uint256[] idsToMigrate; + + function setUp() public override { + super.setUp(); + (newRegistry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + idsToMigrate.push(linkUpkeepID); + idsToMigrate.push(linkUpkeepID2); + idsToMigrate.push(usdUpkeepID18); + idsToMigrate.push(nativeUpkeepID); + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + } + + function test_RevertsWhen_PermissionsNotSet() external { + // no permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only outgoing permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only incoming permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // permissions opposite direction + registry.setPeerRegistryMigrationPermission(address(newRegistry), 2); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 1); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_RevertsWhen_ReceivingRegistryDoesNotSupportToken() external { + _removeBillingTokenConfig(newRegistry, address(weth)); + vm.expectRevert(Registry.InvalidToken.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + idsToMigrate.pop(); // remove native upkeep id + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); // should succeed now + } + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_Success() external { + vm.startPrank(UPKEEP_ADMIN); + + // add some changes in upkeep data to the mix + registry.pauseUpkeep(usdUpkeepID18); + registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); + registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); + + // record previous state + uint256[] memory prevUpkeepBalances = new uint256[](4); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); + prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + bytes[] memory prevUpkeepData = new bytes[](4); + prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); + prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); + prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); + prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); + bytes[] memory prevUpkeepTriggerData = new bytes[](4); + prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); + prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); + prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); + prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); + + // event expectations + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID, prevUpkeepBalances[0], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID, prevUpkeepBalances[0], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); + + // do the thing + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // assert upkeep balances have been migrated + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(registry.getBalance(linkUpkeepID2), 0); + assertEq(registry.getBalance(usdUpkeepID18), 0); + assertEq(registry.getBalance(nativeUpkeepID), 0); + assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); + assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); + assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); + assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); + + // assert reserve balances have been adjusted + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) + ); + assertEq( + newRegistry.getReserveAmount(address(usdToken18)), + prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) + ); + assertEq( + newRegistry.getReserveAmount(address(weth)), + prevReserveBalances[2] - registry.getReserveAmount(address(weth)) + ); + + // assert token have been transferred + assertEq( + linkToken.balanceOf(address(newRegistry)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); + assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); + assertEq( + usdToken18.balanceOf(address(registry)), + prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) + ); + assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); + + // assert upkeep data matches + assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); + assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); + assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); + assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); + assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); + assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); + assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); + assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); + + vm.stopPrank(); + } +} + +contract Pause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.expectRevert(bytes("Only callable by owner")); + vm.prank(STRANGER); + registry.pause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + + (IAutomationV21PlusCommon.StateLegacy memory state, , , , ) = registry.getState(); + assertTrue(state.paused); + } + + function test_revertsWhen_transmitInPausedRegistry() external { + vm.startPrank(registry.owner()); + registry.pause(); + + _transmitAndExpectRevert(usdUpkeepID18, registry, Registry.RegistryPaused.selector); + } +} + +contract Unpause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.startPrank(registry.owner()); + registry.pause(); + + vm.expectRevert(bytes("Only callable by owner")); + vm.startPrank(STRANGER); + registry.unpause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + (IAutomationV21PlusCommon.StateLegacy memory state1, , , , ) = registry.getState(); + assertTrue(state1.paused); + + registry.unpause(); + (IAutomationV21PlusCommon.StateLegacy memory state2, , , , ) = registry.getState(); + assertFalse(state2.paused); + } +} + +contract CancelUpkeep is SetUp { + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + + function test_RevertsWhen_IdIsInvalid_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_IdIsInvalid_CalledByOwner() external { + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_NotCalledByOwnerOrAdmin() external { + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrAdmin.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // 50 is the cancellation delay + assertEq(bn + 50, maxValidBlocknumber); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // cancellation by registry owner is immediate and no cancellation delay is applied + assertEq(bn, maxValidBlocknumber); + } + + function test_CancelUpkeep_EmitEvent_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn + 50)); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_EmitEvent_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn)); + registry.cancelUpkeep(linkUpkeepID); + } +} + +contract SetPeerRegistryMigrationPermission is SetUp { + function test_SetPeerRegistryMigrationPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + uint8 permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + + registry.setPeerRegistryMigrationPermission(peer, 1); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(1, permission); + + registry.setPeerRegistryMigrationPermission(peer, 2); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(2, permission); + + registry.setPeerRegistryMigrationPermission(peer, 0); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + } + + function test_RevertsWhen_InvalidPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + vm.expectRevert(); + registry.setPeerRegistryMigrationPermission(peer, 100); + } + + function test_RevertsWhen_CalledByNonOwner() external { + address peer = randomAddress(); + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPeerRegistryMigrationPermission(peer, 1); + } +} + +contract SetUpkeepPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, bytes("")); + } + + function test_SetUpkeepPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, hex"1233"); + } +} + +contract SetAdminPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setAdminPrivilegeConfig(randomAddress(), hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getAdminPrivilegeConfig(randomAddress()); + assertEq(cfg, bytes("")); + } + + function test_SetAdminPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + address admin = randomAddress(); + + registry.setAdminPrivilegeConfig(admin, hex"1233"); + + bytes memory cfg = registry.getAdminPrivilegeConfig(admin); + assertEq(cfg, hex"1233"); + } +} + +contract TransferUpkeepAdmin is SetUp { + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferUpkeepAdmin(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_DoesNotChangeUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + + assertEq(registry.getUpkeep(linkUpkeepID).admin, UPKEEP_ADMIN); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + // transferring to the same propose admin won't yield another event + vm.recordLogs(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } + + function test_CancelTransfer_ByTransferToEmptyAddress() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, address(0)); + registry.transferUpkeepAdmin(linkUpkeepID, address(0)); + } +} + +contract AcceptUpkeepAdmin is SetUp { + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedAdmin.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(newAdmin); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_UpkeepAdminChanged() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(newAdmin); + vm.expectEmit(); + emit UpkeepAdminTransferred(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.acceptUpkeepAdmin(linkUpkeepID); + + assertEq(newAdmin, registry.getUpkeep(linkUpkeepID).admin); + } +} + +contract PauseUpkeep is SetUp { + event UpkeepPaused(uint256 indexed id); + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyPaused() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.OnlyUnpausedUpkeep.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepPaused(linkUpkeepID); + registry.pauseUpkeep(linkUpkeepID); + } +} + +contract UnpauseUpkeep is SetUp { + event UpkeepUnpaused(uint256 indexed id); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepIsNotPaused() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyPausedUpkeep.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_UnpauseUpkeep_CalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + uint256[] memory ids1 = registry.getActiveUpkeepIDs(0, 0); + + vm.expectEmit(); + emit UpkeepUnpaused(linkUpkeepID); + registry.unpauseUpkeep(linkUpkeepID); + + uint256[] memory ids2 = registry.getActiveUpkeepIDs(0, 0); + assertEq(ids1.length + 1, ids2.length); + } +} + +contract SetUpkeepCheckData is SetUp { + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID + 1, hex"1234"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NewCheckDataTooLarge() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.setUpkeepCheckData(linkUpkeepID, new bytes(10_000)); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } + + function test_UpdateOffchainConfigOnPausedUpkeep_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.pauseUpkeep(linkUpkeepID); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertTrue(registry.getUpkeep(linkUpkeepID).paused); + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } +} + +contract SetUpkeepGasLimit is SetUp { + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID + 1, 1230000); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_RevertsWhen_NewGasLimitOutOfRange() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 300); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 3000000000); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_UpdateGasLimit_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepGasLimitSet(linkUpkeepID, 1230000); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + + assertEq(registry.getUpkeep(linkUpkeepID).performGas, 1230000); + } +} + +contract SetUpkeepOffchainConfig is SetUp { + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepOffchainConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).offchainConfig, hex"1234"); + } +} + +contract SetUpkeepTriggerConfig is SetUp { + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateTriggerConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepTriggerConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeepTriggerConfig(linkUpkeepID), hex"1234"); + } +} + +contract TransferPayeeship is SetUp { + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByPayee() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByPayee.selector); + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + registry.setPayees(PAYEES); + vm.startPrank(PAYEES[0]); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferPayeeship(TRANSMITTERS[0], PAYEES[0]); + } + + function test_Transfer_DoesNotChangePayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(PAYEES[0], payee); + } + + function test_EmitEvent_CalledByPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + + vm.expectEmit(); + emit PayeeshipTransferRequested(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + // transferring to the same propose payee won't yield another event + vm.recordLogs(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } +} + +contract AcceptPayeeship is SetUp { + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedPayee.selector); + registry.acceptPayeeship(TRANSMITTERS[0]); + } + + function test_PayeeChanged() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(newPayee); + vm.expectEmit(); + emit PayeeshipTransferred(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.acceptPayeeship(TRANSMITTERS[0]); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(newPayee, payee); + } +} + +contract SetPayees is SetUp { + event PayeesUpdated(address[] transmitters, address[] payees); + + function test_RevertsWhen_NotCalledByOwner() external { + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPayees(NEW_PAYEES); + } + + function test_RevertsWhen_PayeesLengthError() external { + vm.startPrank(registry.owner()); + + address[] memory payees = new address[](5); + vm.expectRevert(Registry.ParameterLengthError.selector); + registry.setPayees(payees); + } + + function test_RevertsWhen_InvalidPayee() external { + vm.startPrank(registry.owner()); + + NEW_PAYEES[0] = address(0); + vm.expectRevert(Registry.InvalidPayee.selector); + registry.setPayees(NEW_PAYEES); + } + + function test_SetPayees_WhenExistingPayeesAreEmpty() external { + (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertEq(address(0), payee); + } + + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit PayeesUpdated(TRANSMITTERS, PAYEES); + registry.setPayees(PAYEES); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(PAYEES[i], payee); + } + } + + function test_DotNotSetPayeesToIgnoredAddress() external { + address IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + PAYEES[0] = IGNORE_ADDRESS; + + registry.setPayees(PAYEES); + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertTrue(active); + assertEq(address(0), payee); + + (active, , , , payee) = registry.getTransmitterInfo(TRANSMITTERS[1]); + assertTrue(active); + assertEq(PAYEES[1], payee); + } +} + +contract GetActiveUpkeepIDs is SetUp { + function test_RevertsWhen_IndexOutOfRange() external { + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(5, 0); + + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(6, 0); + } + + function test_ReturnsAllUpkeeps_WhenMaxCountIsZero() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(0, 0); + assertEq(5, uids.length); + + uids = registry.getActiveUpkeepIDs(2, 0); + assertEq(3, uids.length); + } + + function test_ReturnsAllRemainingUpkeeps_WhenMaxCountIsTooLarge() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(2, 20); + assertEq(3, uids.length); + } + + function test_ReturnsUpkeeps_BoundByMaxCount() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(1, 2); + assertEq(2, uids.length); + assertEq(uids[0], linkUpkeepID2); + assertEq(uids[1], usdUpkeepID18); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol new file mode 100644 index 0000000..e0d15da --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol @@ -0,0 +1,503 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; + +import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; +import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; +import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; +import {AutomationRegistry2_3} from "../../v2_3/AutomationRegistry2_3.sol"; +import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; +import {AutomationRegistryLogicA2_3} from "../../v2_3/AutomationRegistryLogicA2_3.sol"; +import {AutomationRegistryLogicB2_3} from "../../v2_3/AutomationRegistryLogicB2_3.sol"; +import {AutomationRegistryLogicC2_3} from "../../v2_3/AutomationRegistryLogicC2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; +import {WETH9} from "../WETH9.sol"; + +/** + * @title BaseTest provides basic test setup procedures and dependencies for use by other + * unit tests + */ +contract BaseTest is Test { + // test state (not exposed to derived tests) + uint256 private nonce; + + // constants + address internal constant ZERO_ADDRESS = address(0); + uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; + uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; + + // config + uint8 internal constant F = 1; // number of faulty nodes + uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 + + // contracts + LinkToken internal linkToken; + ERC20Mock6Decimals internal usdToken6; + ERC20Mock internal usdToken18; + ERC20Mock internal usdToken18_2; + WETH9 internal weth; + MockV3Aggregator internal LINK_USD_FEED; + MockV3Aggregator internal NATIVE_USD_FEED; + MockV3Aggregator internal USDTOKEN_USD_FEED; + MockV3Aggregator internal FAST_GAS_FEED; + MockUpkeep internal TARGET1; + MockUpkeep internal TARGET2; + Transcoder internal TRANSCODER; + + // roles + address internal constant OWNER = address(uint160(uint256(keccak256("OWNER")))); + address internal constant UPKEEP_ADMIN = address(uint160(uint256(keccak256("UPKEEP_ADMIN")))); + address internal constant FINANCE_ADMIN = address(uint160(uint256(keccak256("FINANCE_ADMIN")))); + address internal constant STRANGER = address(uint160(uint256(keccak256("STRANGER")))); + address internal constant BROKE_USER = address(uint160(uint256(keccak256("BROKE_USER")))); // do not mint to this address + address internal constant PRIVILEGE_MANAGER = address(uint160(uint256(keccak256("PRIVILEGE_MANAGER")))); + + // nodes + uint256 internal constant SIGNING_KEY0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + uint256 internal constant SIGNING_KEY1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; + uint256 internal constant SIGNING_KEY2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; + uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; + address[] internal SIGNERS = new address[](4); + address[] internal TRANSMITTERS = new address[](4); + address[] internal NEW_TRANSMITTERS = new address[](4); + address[] internal PAYEES = new address[](4); + address[] internal NEW_PAYEES = new address[](4); + + function setUp() public virtual { + vm.startPrank(OWNER); + linkToken = new LinkToken(); + linkToken.grantMintRole(OWNER); + usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); + usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); + weth = new WETH9(); + + LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 + NATIVE_USD_FEED = new MockV3Aggregator(8, 400_000_000_000); // $4,000 + USDTOKEN_USD_FEED = new MockV3Aggregator(8, 100_000_000); // $1 + FAST_GAS_FEED = new MockV3Aggregator(0, 1_000_000_000); // 1 gwei + + TARGET1 = new MockUpkeep(); + TARGET2 = new MockUpkeep(); + + TRANSCODER = new Transcoder(); + + SIGNERS[0] = vm.addr(SIGNING_KEY0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 + SIGNERS[1] = vm.addr(SIGNING_KEY1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 + SIGNERS[2] = vm.addr(SIGNING_KEY2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b + SIGNERS[3] = vm.addr(SIGNING_KEY3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 + + TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); + TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); + NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); + NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); + + PAYEES[0] = address(100); + PAYEES[1] = address(101); + PAYEES[2] = address(102); + PAYEES[3] = address(103); + NEW_PAYEES[0] = address(100); + NEW_PAYEES[1] = address(101); + NEW_PAYEES[2] = address(106); + NEW_PAYEES[3] = address(107); + + // mint funds + vm.deal(OWNER, 100 ether); + vm.deal(UPKEEP_ADMIN, 100 ether); + vm.deal(FINANCE_ADMIN, 100 ether); + vm.deal(STRANGER, 100 ether); + + linkToken.mint(OWNER, 1000e18); + linkToken.mint(UPKEEP_ADMIN, 1000e18); + linkToken.mint(FINANCE_ADMIN, 1000e18); + linkToken.mint(STRANGER, 1000e18); + + usdToken18.mint(OWNER, 1000e18); + usdToken18.mint(UPKEEP_ADMIN, 1000e18); + usdToken18.mint(FINANCE_ADMIN, 1000e18); + usdToken18.mint(STRANGER, 1000e18); + + usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); + + usdToken6.mint(OWNER, 1000e6); + usdToken6.mint(UPKEEP_ADMIN, 1000e6); + usdToken6.mint(FINANCE_ADMIN, 1000e6); + usdToken6.mint(STRANGER, 1000e6); + + weth.mint(OWNER, 1000e18); + weth.mint(UPKEEP_ADMIN, 1000e18); + weth.mint(FINANCE_ADMIN, 1000e18); + weth.mint(STRANGER, 1000e18); + + vm.stopPrank(); + } + + /// @notice deploys the component parts of a registry, but nothing more + function deployRegistry(AutoBase.PayoutMode payoutMode) internal returns (Registry) { + AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); + AutomationRegistryLogicC2_3 logicC2_3 = new AutomationRegistryLogicC2_3( + address(linkToken), + address(LINK_USD_FEED), + address(NATIVE_USD_FEED), + address(FAST_GAS_FEED), + address(forwarderLogic), + ZERO_ADDRESS, + payoutMode, + address(weth) + ); + AutomationRegistryLogicB2_3 logicB2_3 = new AutomationRegistryLogicB2_3(logicC2_3); + AutomationRegistryLogicA2_3 logicA2_3 = new AutomationRegistryLogicA2_3(logicB2_3); + return Registry(payable(address(new AutomationRegistry2_3(logicA2_3)))); + } + + /// @notice deploys and configures a registry, registrar, and everything needed for most tests + function deployAndConfigureRegistryAndRegistrar( + AutoBase.PayoutMode payoutMode + ) internal returns (Registry, AutomationRegistrar2_3) { + Registry registry = deployRegistry(payoutMode); + + IERC20[] memory billingTokens = new IERC20[](4); + billingTokens[0] = IERC20(address(usdToken18)); + billingTokens[1] = IERC20(address(weth)); + billingTokens[2] = IERC20(address(linkToken)); + billingTokens[3] = IERC20(address(usdToken6)); + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + minRegistrationFees[1] = 5e18; // 5 Native + minRegistrationFees[2] = 5e18; // 5 LINK + minRegistrationFees[3] = 100e6; // 100 USD + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(NATIVE_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 5e18, // 5 Native + decimals: 18 + }); + billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(LINK_USD_FEED), + fallbackPrice: 1_000_000_000, // $10 + minSpend: 1e18, // 1 LINK + decimals: 18 + }); + billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e6, // 1 USD + decimals: 6 + }); + + if (payoutMode == AutoBase.PayoutMode.OFF_CHAIN) { + // remove LINK as a payment method if we are settling offchain + assembly { + mstore(billingTokens, 2) + mstore(minRegistrationFees, 2) + mstore(billingTokenAddresses, 2) + mstore(billingTokenConfigs, 2) + } + } + + // deploy registrar + AutomationRegistrar2_3.InitialTriggerConfig[] + memory triggerConfigs = new AutomationRegistrar2_3.InitialTriggerConfig[](2); + triggerConfigs[0] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 0, // condition + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + triggerConfigs[1] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 1, // log + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + AutomationRegistrar2_3 registrar = new AutomationRegistrar2_3( + address(linkToken), + registry, + triggerConfigs, + billingTokens, + minRegistrationFees, + IWrappedNative(address(weth)) + ); + + address[] memory registrars; + registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: address(TRANSCODER), + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + return (registry, registrar); + } + + /// @notice this function updates the billing config for the provided token on the provided registry, + /// and throws an error if the token is not found + function _updateBillingTokenConfig( + Registry registry, + address billingToken, + AutomationRegistryBase2_3.BillingConfig memory newConfig + ) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + + bool found = false; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] == billingToken) { + found = true; + billingTokenConfigs[i] = newConfig; + } else { + billingTokenConfigs[i] = registry.getBillingTokenConfig(billingTokens[i]); + } + } + require(found, "could not find billing token provided on registry"); + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokens, + billingTokenConfigs + ); + } + + /// @notice this function removes a billing token from the registry + function _removeBillingTokenConfig(Registry registry, address billingToken) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + address[] memory newBillingTokens = new address[](billingTokens.length - 1); + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length - 1); + + uint256 j = 0; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] != billingToken) { + if (j == newBillingTokens.length) revert("could not find billing token provided on registry"); + newBillingTokens[j] = billingTokens[i]; + billingTokenConfigs[j] = registry.getBillingTokenConfig(billingTokens[i]); + j++; + } + } + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + newBillingTokens, + billingTokenConfigs + ); + } + + // tests single upkeep, expects success + function _transmit(uint256 id, Registry registry) internal { + uint256[] memory ids = new uint256[](1); + ids[0] = id; + _handleTransmit(ids, registry, bytes4(0)); + } + + // tests multiple upkeeps, expects success + function _transmit(uint256[] memory ids, Registry registry) internal { + _handleTransmit(ids, registry, bytes4(0)); + } + + // tests single upkeep, expects revert + function _transmitAndExpectRevert(uint256 id, Registry registry, bytes4 selector) internal { + uint256[] memory ids = new uint256[](1); + ids[0] = id; + _handleTransmit(ids, registry, selector); + } + + // private function not exposed to actual testing contract + function _handleTransmit(uint256[] memory ids, Registry registry, bytes4 selector) private { + bytes memory reportBytes; + { + uint256[] memory upkeepIds = new uint256[](ids.length); + uint256[] memory gasLimits = new uint256[](ids.length); + bytes[] memory performDatas = new bytes[](ids.length); + bytes[] memory triggers = new bytes[](ids.length); + for (uint256 i = 0; i < ids.length; i++) { + upkeepIds[i] = ids[i]; + gasLimits[i] = registry.getUpkeep(ids[i]).performGas; + performDatas[i] = new bytes(0); + uint8 triggerType = registry.getTriggerType(ids[i]); + if (triggerType == 0) { + triggers[i] = _encodeConditionalTrigger( + AutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) + ); + } else { + revert("not implemented"); + } + } + + AutoBase.Report memory report = AutoBase.Report( + uint256(1000000000), + uint256(2000000000), + upkeepIds, + gasLimits, + triggers, + performDatas + ); + + reportBytes = _encodeReport(report); + } + (, , bytes32 configDigest) = registry.latestConfigDetails(); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + uint256[] memory signerPKs = new uint256[](2); + signerPKs[0] = SIGNING_KEY0; + signerPKs[1] = SIGNING_KEY1; + (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); + + vm.startPrank(TRANSMITTERS[0]); + if (selector != bytes4(0)) { + vm.expectRevert(selector); + } + registry.transmit(reportContext, reportBytes, rs, ss, vs); + vm.stopPrank(); + } + + /// @notice Gather signatures on report data + /// @param report - Report bytes generated from `_buildReport` + /// @param reportContext - Report context bytes32 generated from `_buildReport` + /// @param signerPrivateKeys - One or more addresses that will sign the report data + /// @return rawRs - Signature rs + /// @return rawSs - Signature ss + /// @return rawVs - Signature vs + function _signReport( + bytes memory report, + bytes32[3] memory reportContext, + uint256[] memory signerPrivateKeys + ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { + bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); + bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); + bytes memory vs = new bytes(signerPrivateKeys.length); + + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signerPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + + return (rs, ss, bytes32(vs)); + } + + function _encodeReport(AutoBase.Report memory report) internal pure returns (bytes memory reportBytes) { + return abi.encode(report); + } + + function _encodeConditionalTrigger( + AutoBase.ConditionalTrigger memory trigger + ) internal pure returns (bytes memory triggerBytes) { + return abi.encode(trigger.blockNum, trigger.blockHash); + } + + /// @dev mints LINK to the recipient + function _mintLink(address recipient, uint256 amount) internal { + vm.prank(OWNER); + linkToken.mint(recipient, amount); + } + + /// @dev mints USDToken with 18 decimals to the recipient + function _mintERC20_18Decimals(address recipient, uint256 amount) internal { + vm.prank(OWNER); + usdToken18.mint(recipient, amount); + } + + /// @dev returns a pseudo-random 32 bytes + function _random() private returns (bytes32) { + nonce++; + return keccak256(abi.encode(block.timestamp, nonce)); + } + + /// @dev returns a pseudo-random number + function randomNumber() internal returns (uint256) { + return uint256(_random()); + } + + /// @dev returns a pseudo-random address + function randomAddress() internal returns (address) { + return address(uint160(randomNumber())); + } + + /// @dev returns a pseudo-random byte array + function randomBytes(uint256 length) internal returns (bytes memory) { + bytes memory result = new bytes(length); + bytes32 entropy; + for (uint256 i = 0; i < length; i++) { + if (i % 32 == 0) { + entropy = _random(); + } + result[i] = entropy[i % 32]; + } + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol new file mode 100644 index 0000000..cde05ab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; + +import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; +import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; +import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; +import {ZKSyncAutomationRegistry2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistry2_3.sol"; +import {ZKSyncAutomationRegistryLogicA2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol"; +import {ZKSyncAutomationRegistryLogicB2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol"; +import {ZKSyncAutomationRegistryLogicC2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol"; +import {ZKSyncAutomationRegistryBase2_3 as ZKSyncAutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; +import {WETH9} from "../WETH9.sol"; +import {MockGasBoundCaller} from "../../../tests/MockGasBoundCaller.sol"; +import {MockZKSyncSystemContext} from "../../../tests/MockZKSyncSystemContext.sol"; + +/** + * @title BaseTest provides basic test setup procedures and dependencies for use by other + * unit tests + */ +contract BaseTest is Test { + // test state (not exposed to derived tests) + uint256 private nonce; + + // constants + address internal constant ZERO_ADDRESS = address(0); + uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; + uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; + + // config + uint8 internal constant F = 1; // number of faulty nodes + uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 + + // contracts + LinkToken internal linkToken; + ERC20Mock6Decimals internal usdToken6; + ERC20Mock internal usdToken18; + ERC20Mock internal usdToken18_2; + WETH9 internal weth; + MockV3Aggregator internal LINK_USD_FEED; + MockV3Aggregator internal NATIVE_USD_FEED; + MockV3Aggregator internal USDTOKEN_USD_FEED; + MockV3Aggregator internal FAST_GAS_FEED; + MockUpkeep internal TARGET1; + MockUpkeep internal TARGET2; + Transcoder internal TRANSCODER; + MockGasBoundCaller internal GAS_BOUND_CALLER; + MockZKSyncSystemContext internal SYSTEM_CONTEXT; + + // roles + address internal constant OWNER = address(uint160(uint256(keccak256("OWNER")))); + address internal constant UPKEEP_ADMIN = address(uint160(uint256(keccak256("UPKEEP_ADMIN")))); + address internal constant FINANCE_ADMIN = address(uint160(uint256(keccak256("FINANCE_ADMIN")))); + address internal constant STRANGER = address(uint160(uint256(keccak256("STRANGER")))); + address internal constant BROKE_USER = address(uint160(uint256(keccak256("BROKE_USER")))); // do not mint to this address + address internal constant PRIVILEGE_MANAGER = address(uint160(uint256(keccak256("PRIVILEGE_MANAGER")))); + + // nodes + uint256 internal constant SIGNING_KEY0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + uint256 internal constant SIGNING_KEY1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; + uint256 internal constant SIGNING_KEY2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; + uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; + address[] internal SIGNERS = new address[](4); + address[] internal TRANSMITTERS = new address[](4); + address[] internal NEW_TRANSMITTERS = new address[](4); + address[] internal PAYEES = new address[](4); + address[] internal NEW_PAYEES = new address[](4); + + function setUp() public virtual { + vm.startPrank(OWNER); + linkToken = new LinkToken(); + linkToken.grantMintRole(OWNER); + usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); + usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); + weth = new WETH9(); + + LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 + NATIVE_USD_FEED = new MockV3Aggregator(8, 400_000_000_000); // $4,000 + USDTOKEN_USD_FEED = new MockV3Aggregator(8, 100_000_000); // $1 + FAST_GAS_FEED = new MockV3Aggregator(0, 1_000_000_000); // 1 gwei + + TARGET1 = new MockUpkeep(); + TARGET2 = new MockUpkeep(); + + TRANSCODER = new Transcoder(); + GAS_BOUND_CALLER = new MockGasBoundCaller(); + SYSTEM_CONTEXT = new MockZKSyncSystemContext(); + + bytes memory callerCode = address(GAS_BOUND_CALLER).code; + vm.etch(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5, callerCode); + + bytes memory contextCode = address(SYSTEM_CONTEXT).code; + vm.etch(0x000000000000000000000000000000000000800B, contextCode); + + SIGNERS[0] = vm.addr(SIGNING_KEY0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 + SIGNERS[1] = vm.addr(SIGNING_KEY1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 + SIGNERS[2] = vm.addr(SIGNING_KEY2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b + SIGNERS[3] = vm.addr(SIGNING_KEY3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 + + TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); + TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); + NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); + NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); + + PAYEES[0] = address(100); + PAYEES[1] = address(101); + PAYEES[2] = address(102); + PAYEES[3] = address(103); + NEW_PAYEES[0] = address(100); + NEW_PAYEES[1] = address(101); + NEW_PAYEES[2] = address(106); + NEW_PAYEES[3] = address(107); + + // mint funds + vm.deal(OWNER, 100 ether); + vm.deal(UPKEEP_ADMIN, 100 ether); + vm.deal(FINANCE_ADMIN, 100 ether); + vm.deal(STRANGER, 100 ether); + + linkToken.mint(OWNER, 1000e18); + linkToken.mint(UPKEEP_ADMIN, 1000e18); + linkToken.mint(FINANCE_ADMIN, 1000e18); + linkToken.mint(STRANGER, 1000e18); + + usdToken18.mint(OWNER, 1000e18); + usdToken18.mint(UPKEEP_ADMIN, 1000e18); + usdToken18.mint(FINANCE_ADMIN, 1000e18); + usdToken18.mint(STRANGER, 1000e18); + + usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); + + usdToken6.mint(OWNER, 1000e6); + usdToken6.mint(UPKEEP_ADMIN, 1000e6); + usdToken6.mint(FINANCE_ADMIN, 1000e6); + usdToken6.mint(STRANGER, 1000e6); + + weth.mint(OWNER, 1000e18); + weth.mint(UPKEEP_ADMIN, 1000e18); + weth.mint(FINANCE_ADMIN, 1000e18); + weth.mint(STRANGER, 1000e18); + + vm.stopPrank(); + } + + /// @notice deploys the component parts of a registry, but nothing more + function deployZKSyncRegistry(ZKSyncAutoBase.PayoutMode payoutMode) internal returns (Registry) { + AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); + ZKSyncAutomationRegistryLogicC2_3 logicC2_3 = new ZKSyncAutomationRegistryLogicC2_3( + address(linkToken), + address(LINK_USD_FEED), + address(NATIVE_USD_FEED), + address(FAST_GAS_FEED), + address(forwarderLogic), + ZERO_ADDRESS, + payoutMode, + address(weth) + ); + ZKSyncAutomationRegistryLogicB2_3 logicB2_3 = new ZKSyncAutomationRegistryLogicB2_3(logicC2_3); + ZKSyncAutomationRegistryLogicA2_3 logicA2_3 = new ZKSyncAutomationRegistryLogicA2_3(logicB2_3); + return Registry(payable(address(new ZKSyncAutomationRegistry2_3(logicA2_3)))); + } + + /// @notice deploys and configures a registry, registrar, and everything needed for most tests + function deployAndConfigureZKSyncRegistryAndRegistrar( + ZKSyncAutoBase.PayoutMode payoutMode + ) internal returns (Registry, AutomationRegistrar2_3) { + Registry registry = deployZKSyncRegistry(payoutMode); + + IERC20[] memory billingTokens = new IERC20[](4); + billingTokens[0] = IERC20(address(usdToken18)); + billingTokens[1] = IERC20(address(weth)); + billingTokens[2] = IERC20(address(linkToken)); + billingTokens[3] = IERC20(address(usdToken6)); + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + minRegistrationFees[1] = 5e18; // 5 Native + minRegistrationFees[2] = 5e18; // 5 LINK + minRegistrationFees[3] = 100e6; // 100 USD + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(NATIVE_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 5e18, // 5 Native + decimals: 18 + }); + billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(LINK_USD_FEED), + fallbackPrice: 1_000_000_000, // $10 + minSpend: 1e18, // 1 LINK + decimals: 18 + }); + billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e6, // 1 USD + decimals: 6 + }); + + if (payoutMode == ZKSyncAutoBase.PayoutMode.OFF_CHAIN) { + // remove LINK as a payment method if we are settling offchain + assembly { + mstore(billingTokens, 2) + mstore(minRegistrationFees, 2) + mstore(billingTokenAddresses, 2) + mstore(billingTokenConfigs, 2) + } + } + + // deploy registrar + AutomationRegistrar2_3.InitialTriggerConfig[] + memory triggerConfigs = new AutomationRegistrar2_3.InitialTriggerConfig[](2); + triggerConfigs[0] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 0, // condition + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + triggerConfigs[1] = AutomationRegistrar2_3.InitialTriggerConfig({ + triggerType: 1, // log + autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, + autoApproveMaxAllowed: 0 + }); + AutomationRegistrar2_3 registrar = new AutomationRegistrar2_3( + address(linkToken), + registry, + triggerConfigs, + billingTokens, + minRegistrationFees, + IWrappedNative(address(weth)) + ); + + address[] memory registrars; + registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: address(TRANSCODER), + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + return (registry, registrar); + } + + /// @notice this function updates the billing config for the provided token on the provided registry, + /// and throws an error if the token is not found + function _updateBillingTokenConfig( + Registry registry, + address billingToken, + AutomationRegistryBase2_3.BillingConfig memory newConfig + ) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + + bool found = false; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] == billingToken) { + found = true; + billingTokenConfigs[i] = newConfig; + } else { + billingTokenConfigs[i] = registry.getBillingTokenConfig(billingTokens[i]); + } + } + require(found, "could not find billing token provided on registry"); + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokens, + billingTokenConfigs + ); + } + + /// @notice this function removes a billing token from the registry + function _removeBillingTokenConfig(Registry registry, address billingToken) internal { + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); + address[] memory billingTokens = registry.getBillingTokens(); + + address[] memory newBillingTokens = new address[](billingTokens.length - 1); + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length - 1); + + uint256 j = 0; + for (uint256 i = 0; i < billingTokens.length; i++) { + if (billingTokens[i] != billingToken) { + if (j == newBillingTokens.length) revert("could not find billing token provided on registry"); + newBillingTokens[j] = billingTokens[i]; + billingTokenConfigs[j] = registry.getBillingTokenConfig(billingTokens[i]); + j++; + } + } + + registry.setConfigTypeSafe( + signers, + transmitters, + f, + config, + OFFCHAIN_CONFIG_VERSION, + "", + newBillingTokens, + billingTokenConfigs + ); + } + + function _transmit(uint256 id, Registry registry, bytes4 selector) internal { + uint256[] memory ids = new uint256[](1); + ids[0] = id; + _transmit(ids, registry, selector); + } + + function _transmit(uint256[] memory ids, Registry registry, bytes4 selector) internal { + bytes memory reportBytes; + { + uint256[] memory upkeepIds = new uint256[](ids.length); + uint256[] memory gasLimits = new uint256[](ids.length); + bytes[] memory performDatas = new bytes[](ids.length); + bytes[] memory triggers = new bytes[](ids.length); + for (uint256 i = 0; i < ids.length; i++) { + upkeepIds[i] = ids[i]; + gasLimits[i] = registry.getUpkeep(ids[i]).performGas; + performDatas[i] = new bytes(0); + uint8 triggerType = registry.getTriggerType(ids[i]); + if (triggerType == 0) { + triggers[i] = _encodeConditionalTrigger( + ZKSyncAutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) + ); + } else { + revert("not implemented"); + } + } + ZKSyncAutoBase.Report memory report = ZKSyncAutoBase.Report( + uint256(1000000000), + uint256(2000000000), + upkeepIds, + gasLimits, + triggers, + performDatas + ); + + reportBytes = _encodeReport(report); + } + (, , bytes32 configDigest) = registry.latestConfigDetails(); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + uint256[] memory signerPKs = new uint256[](2); + signerPKs[0] = SIGNING_KEY0; + signerPKs[1] = SIGNING_KEY1; + (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); + + vm.startPrank(TRANSMITTERS[0]); + if (selector != bytes4(0)) { + vm.expectRevert(selector); + } + registry.transmit(reportContext, reportBytes, rs, ss, vs); + vm.stopPrank(); + } + + /// @notice Gather signatures on report data + /// @param report - Report bytes generated from `_buildReport` + /// @param reportContext - Report context bytes32 generated from `_buildReport` + /// @param signerPrivateKeys - One or more addresses that will sign the report data + /// @return rawRs - Signature rs + /// @return rawSs - Signature ss + /// @return rawVs - Signature vs + function _signReport( + bytes memory report, + bytes32[3] memory reportContext, + uint256[] memory signerPrivateKeys + ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { + bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); + bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); + bytes memory vs = new bytes(signerPrivateKeys.length); + + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signerPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + + return (rs, ss, bytes32(vs)); + } + + function _encodeReport(ZKSyncAutoBase.Report memory report) internal pure returns (bytes memory reportBytes) { + return abi.encode(report); + } + + function _encodeConditionalTrigger( + ZKSyncAutoBase.ConditionalTrigger memory trigger + ) internal pure returns (bytes memory triggerBytes) { + return abi.encode(trigger.blockNum, trigger.blockHash); + } + + /// @dev mints LINK to the recipient + function _mintLink(address recipient, uint256 amount) internal { + vm.prank(OWNER); + linkToken.mint(recipient, amount); + } + + /// @dev mints USDToken with 18 decimals to the recipient + function _mintERC20_18Decimals(address recipient, uint256 amount) internal { + vm.prank(OWNER); + usdToken18.mint(recipient, amount); + } + + /// @dev returns a pseudo-random 32 bytes + function _random() private returns (bytes32) { + nonce++; + return keccak256(abi.encode(block.timestamp, nonce)); + } + + /// @dev returns a pseudo-random number + function randomNumber() internal returns (uint256) { + return uint256(_random()); + } + + /// @dev returns a pseudo-random address + function randomAddress() internal returns (address) { + return address(uint160(randomNumber())); + } + + /// @dev returns a pseudo-random byte array + function randomBytes(uint256 length) internal returns (bytes memory) { + bytes memory result = new bytes(length); + bytes32 entropy; + for (uint256 i = 0; i < length; i++) { + if (i % 32 == 0) { + entropy = _random(); + } + result[i] = entropy[i % 32]; + } + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol new file mode 100644 index 0000000..7098d9f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol @@ -0,0 +1,2772 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {Vm} from "forge-std/Test.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {ZKSyncAutomationRegistryBase2_3 as AutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; +import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; +import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; + +// forge test --match-path src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol --match-test + +enum Trigger { + CONDITION, + LOG +} + +contract SetUp is BaseTest { + Registry internal registry; + AutomationRegistryBase2_3.OnchainConfig internal config; + bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); + + uint256 linkUpkeepID; + uint256 linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario + uint256 usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals + uint256 usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals + uint256 nativeUpkeepID; + + function setUp() public virtual override { + super.setUp(); + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + config = registry.getConfig(); + + vm.startPrank(OWNER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(UPKEEP_ADMIN); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.startPrank(STRANGER); + linkToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); + weth.approve(address(registry), type(uint256).max); + vm.stopPrank(); + + linkUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + linkUpkeepID2 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + + usdUpkeepID18 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken18), + "", + "", + "" + ); + + usdUpkeepID6 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken6), + "", + "", + "" + ); + + nativeUpkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(weth), + "", + "", + "" + ); + + vm.startPrank(OWNER); + registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); + registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); + registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); + registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); + registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); + vm.stopPrank(); + } +} + +contract LatestConfigDetails is SetUp { + function testGet() public { + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails(); + assertEq(configCount, 1); + assertTrue(blockNumber > 0); + assertNotEq(configDigest, ""); + } +} + +contract CheckUpkeep is SetUp { + function testPreventExecutionOnCheckUpkeep() public { + uint256 id = 1; + bytes memory triggerData = abi.encodePacked("trigger_data"); + + // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry + // Expecting a revert since the tx.origin is not address(0) + vm.expectRevert(abi.encodeWithSelector(Registry.OnlySimulatedBackend.selector)); + registry.checkUpkeep(id, triggerData); + } +} + +contract WithdrawFunds is SetUp { + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.withdrawFunds(linkUpkeepID, STRANGER); + } + + function test_RevertsWhen_InvalidRecipient() external { + vm.expectRevert(Registry.InvalidRecipient.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); + } + + function test_RevertsWhen_UpkeepNotCanceled() external { + vm.expectRevert(Registry.UpkeepNotCanceled.selector); + vm.prank(UPKEEP_ADMIN); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_Happy_Link() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); + uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); + + uint256 upkeepBalance = registry.getBalance(linkUpkeepID); + vm.expectEmit(); + emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); + + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); + } + + function test_Happy_USDToken() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(usdUpkeepID6); + vm.roll(100 + block.number); + + uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); + uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); + + uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); + vm.expectEmit(); + emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); + registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); + + assertEq(registry.getBalance(usdUpkeepID6), 0); + assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); + assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); + } +} + +contract AddFunds is SetUp { + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + + // when msg.value is 0, it uses the ERC20 payment path + function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { + vm.startPrank(OWNER); + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds(nativeUpkeepID, 1); + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // when msg.value is not 0, it uses the native payment path + function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { + uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); + uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); + registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored + assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); + assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); + assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); + } + + // it fails when the billing token is not native, but trying to pay with native + function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.addFunds{value: 1}(linkUpkeepID, 0); + } + + function test_RevertsWhen_UpkeepDoesNotExist() public { + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(randomNumber(), 1); + } + + function test_RevertsWhen_UpkeepIsCanceled() public { + registry.cancelUpkeep(linkUpkeepID); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.addFunds(linkUpkeepID, 1); + } + + function test_anyoneCanAddFunds() public { + uint256 startAmount = registry.getBalance(linkUpkeepID); + vm.prank(UPKEEP_ADMIN); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); + vm.prank(STRANGER); + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); + } + + function test_movesFundFromCorrectToken() public { + vm.startPrank(UPKEEP_ADMIN); + + uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); + uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); + uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); + uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); + + registry.addFunds(linkUpkeepID, 1); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); + + registry.addFunds(usdUpkeepID18, 2); + assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); + assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); + } + + function test_emitsAnEvent() public { + vm.startPrank(UPKEEP_ADMIN); + vm.expectEmit(); + emit FundsAdded(linkUpkeepID, address(UPKEEP_ADMIN), 100); + registry.addFunds(linkUpkeepID, 100); + } +} + +contract Withdraw is SetUp { + address internal aMockAddress = randomAddress(); + + function testLinkAvailableForPaymentReturnsLinkBalance() public { + uint256 startBalance = linkToken.balanceOf(address(registry)); + int256 startLinkAvailable = registry.linkAvailableForPayment(); + + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + + //check there's a balance + assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); + + //check the link available has increased by the same amount + assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); + } + + function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.withdrawLink(aMockAddress, 1); + } + + function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is 0 balance + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); + registry.withdrawLink(ZERO_ADDRESS, 1); + + vm.stopPrank(); + } + + function testWithdrawLinkSuccess() public { + //simulate a deposit of link to the liquidity pool + _mintLink(address(registry), 1e10); + uint256 startBalance = linkToken.balanceOf(address(registry)); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 link while there is a ton of link available + registry.withdrawLink(aMockAddress, 1); + + vm.stopPrank(); + + assertEq(linkToken.balanceOf(address(aMockAddress)), 1); + assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); + } + + function test_WithdrawERC20Fees_RespectsReserveAmount() public { + assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); + } + + function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { + _mintLink(address(registry), 1e10); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(Registry.InvalidToken.selector); + registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert + registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds + } + + // default is ON_CHAIN mode + function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { + _transmit(usdUpkeepID18, registry, bytes4(0)); // adds USD token to finance withdrawable, and gives NOPs a LINK balance + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert + _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw + } + + function test_WithdrawERC20Fees_InOffChainMode_Happy() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); + vm.prank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw + + // recipient should get the funds + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + } + + function testWithdrawERC20FeeSuccess() public { + // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) + uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); + uint256 startAmount = usdToken18.balanceOf(address(registry)); + _mintERC20_18Decimals(address(registry), 1e10); + + // depositing shouldn't change reserve amount + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + + vm.startPrank(FINANCE_ADMIN); + + // try to withdraw 1 USDToken + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); + + vm.stopPrank(); + + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); + } +} + +contract SetConfig is SetUp { + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + address module = address(new ChainModuleBase()); + + AutomationRegistryBase2_3.OnchainConfig cfg = + AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: _getRegistrars(), + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + function testSetConfigSuccess() public { + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); + assertEq(config.gasFeePPB, 5_000); + assertEq(config.flatFeeMilliCents, 20_000); + assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config.minSpend, 100_000); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigMultipleBillingConfigsSuccess() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); + + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); + assertEq(config1.gasFeePPB, 5_001); + assertEq(config1.flatFeeMilliCents, 20_001); + assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config1.fallbackPrice, 100); + assertEq(config1.minSpend, 100); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 2); + } + + function testSetConfigTwiceAndLastSetOverwrites() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + // BillingConfig1 + address billingTokenAddress1 = address(usdToken18); + address[] memory billingTokens1 = new address[](1); + billingTokens1[0] = billingTokenAddress1; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs1 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + + // the first time uses the default onchain config with 2 registrars + bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); + + // set config once + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling1, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + (, IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig1, , , ) = registry.getState(); + assertEq(onchainConfig1.registrars.length, 2); + + // BillingConfig2 + address billingTokenAddress2 = address(usdToken18); + address[] memory billingTokens2 = new address[](1); + billingTokens2[0] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs2 = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + address[] memory newRegistrars = new address[](3); + newRegistrars[0] = address(uint160(uint256(keccak256("newRegistrar1")))); + newRegistrars[1] = address(uint160(uint256(keccak256("newRegistrar2")))); + newRegistrars[2] = address(uint160(uint256(keccak256("newRegistrar3")))); + + // new onchain config with 3 new registrars, all other fields stay the same as the default + AutomationRegistryBase2_3.OnchainConfig memory cfg2 = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 0, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: newRegistrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: module, + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + // the second time uses the new onchain config with 3 new registrars and also new billing tokens/configs + bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg2, billingTokens2, billingConfigs2); + + // set config twice + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling2, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + ( + , + IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig2, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) = registry.getState(); + + assertEq(onchainConfig2.registrars.length, 3); + for (uint256 i = 0; i < newRegistrars.length; i++) { + assertEq(newRegistrars[i], onchainConfig2.registrars[i]); + } + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + assertEq(f, F); + + AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); + assertEq(config2.gasFeePPB, 5_002); + assertEq(config2.flatFeeMilliCents, 20_002); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); + assertEq(config2.fallbackPrice, 200); + assertEq(config2.minSpend, 200); + + address[] memory tokens = registry.getBillingTokens(); + assertEq(tokens.length, 1); + } + + function testSetConfigDuplicateBillingConfigFailure() public { + (uint32 configCount, , ) = registry.latestConfigDetails(); + assertEq(configCount, 1); + + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(linkToken); + address[] memory billingTokens = new address[](2); + billingTokens[0] = billingTokenAddress1; + billingTokens[1] = billingTokenAddress2; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_001, + flatFeeMilliCents: 20_001, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100, + minSpend: 100, + decimals: 18 + }); + billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_002, + flatFeeMilliCents: 20_002, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 200, + minSpend: 200, + decimals: 18 + }); + + bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); + + // expect revert because of duplicate tokens + vm.expectRevert(abi.encodeWithSelector(Registry.DuplicateEntry.selector)); + registry.setConfig( + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytesWithBilling, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + } + + function testSetConfigRevertDueToInvalidToken() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + // deploy registry with OFF_CHAIN payout mode + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigRevertDueToInvalidDecimals() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 6 // link token should have 18 decimals + }); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + + function testSetConfigOnTransmittersAndPayees() public { + registry.setPayees(PAYEES); + AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry + .getTransmittersWithPayees(); + assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); + + for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { + address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; + address payeeAddress = transmitterPayeeInfos[i].payeeAddress; + + address expectedTransmitter = TRANSMITTERS[i]; + address expectedPayee = PAYEES[i]; + + assertEq(transmitterAddress, expectedTransmitter); + assertEq(payeeAddress, expectedPayee); + } + } + + function testSetConfigWithNewTransmittersSuccess() public { + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 0); + + address billingTokenAddress = address(usdToken18); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 18 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + + (configCount, blockNumber, ) = registry.latestConfigDetails(); + configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , signers, transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, NEW_TRANSMITTERS); + } + + function _getRegistrars() private pure returns (address[] memory) { + address[] memory registrars = new address[](2); + registrars[0] = address(uint160(uint256(keccak256("registrar1")))); + registrars[1] = address(uint160(uint256(keccak256("registrar2")))); + return registrars; + } + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } +} + +contract NOPsSettlement is SetUp { + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + + function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainRevertDueToOffchainSettlementDisabled() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + vm.prank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOnchain.selector)); + registry.settleNOPsOffchain(); + } + + function testSettleNOPsOffchainSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + payments[i] = 0; + } + + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + } + + // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same + function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + // verify transmitters have positive balances + uint256[] memory payments = new uint256[](TRANSMITTERS.length); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertTrue(balance > 0); + assertEq(0, lastCollected); + + payments[i] = balance; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + vm.expectEmit(); + emit NOPsSettledOffchain(PAYEES, payments); + registry.settleNOPsOffchain(); + + // verify that transmitters balance has been zeroed out + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + // should have some ERC20s in registry after transmit + uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); + + vm.startPrank(UPKEEP_ADMIN); + vm.roll(100 + block.number); + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); + + // finance admin comes to withdraw all available ERC20s + vm.startPrank(FINANCE_ADMIN); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); + + uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); + require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); + + uint256 reservedLink = registry.getReserveAmount(address(linkToken)); + require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); + + // owner comes to disable offchain mode + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity + vm.startPrank(FINANCE_ADMIN); + uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); + + // reserved link amount to NOPs should stay the same after switching to onchain mode + assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); + // available ERC20 for payment should be 0 since finance admin withdrew all already + assertEq(erc20ForPayment4, 0); + } + + function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, Registrar registrar) = deployAndConfigureZKSyncRegistryAndRegistrar( + AutoBase.PayoutMode.OFF_CHAIN + ); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so TRANSMITTERS earn some rewards + _transmit(id, registry, bytes4(0)); + + // TRANSMITTERS have positive balance now + // configure the registry to use NEW_TRANSMITTERS + _configureWithNewTransmitters(registry, registrar); + + _transmit(id, registry, bytes4(0)); + + // verify all transmitters have positive balances + address[] memory expectedPayees = new address[](6); + uint256[] memory expectedPayments = new uint256[](6); + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + NEW_TRANSMITTERS[i] + ); + assertTrue(active); + assertEq(i, index); + assertTrue(lastCollected > 0); + expectedPayments[i] = balance; + expectedPayees[i] = payee; + } + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + TRANSMITTERS[i] + ); + assertFalse(active); + assertEq(i, index); + assertTrue(balance > 0); + assertTrue(lastCollected > 0); + expectedPayments[2 + i] = balance; + expectedPayees[2 + i] = payee; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + + // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these + // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. + vm.recordLogs(); + registry.settleNOPsOffchain(); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + Vm.Log memory l = entries[0]; + assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); + (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); + assertEq(actualPayees.length, 6); + assertEq(actualPayments.length, 6); + + // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + assertEq(actualPayees[i], expectedPayees[i]); + assertEq(actualPayments[i], expectedPayments[i]); + } + + // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered + assertTrue( + (actualPayments[5] == expectedPayments[5] && + actualPayees[5] == expectedPayees[5] && + actualPayments[4] == expectedPayments[4] && + actualPayees[4] == expectedPayees[4]) || + (actualPayments[5] == expectedPayments[4] && + actualPayees[5] == expectedPayees[4] && + actualPayments[4] == expectedPayments[5] && + actualPayees[4] == expectedPayees[5]) + ); + + // verify that new transmitters balance has been zeroed out + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertFalse(active); + assertEq(i, index); + assertEq(0, balance); + } + + // after the offchain settlement, the total reserve amount of LINK should be 0 + assertEq(registry.getReserveAmount(address(linkToken)), 0); + } + + function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(bytes("Only callable by owner")); + registry.disableOffchainPayments(); + } + + function testDisableOffchainPaymentsSuccess() public { + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + + vm.startPrank(registry.owner()); + registry.disableOffchainPayments(); + + assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); + } + + function testSinglePerformAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry, bytes4(0)); + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + vm.expectEmit(); + // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value + emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function testMultiplePerformsAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); + registry.setPayees(PAYEES); + + // register an upkeep and add funds + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually call transmit so transmitters earn some rewards + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry, bytes4(0)); + } + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // manually call transmit after offchain payment is disabled + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry, bytes4(0)); + } + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + uint256 balance = registry.getBalance(id); + vm.expectEmit(); + emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { + IERC20[] memory billingTokens = new IERC20[](1); + billingTokens[0] = IERC20(address(usdToken18)); + + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100e18; // 100 USD + + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 10_000_000, // 15% + flatFeeMilliCents: 2_000, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 + }); + + address[] memory registrars = new address[](1); + registrars[0] = address(registrar); + + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + + registry.setPayees(NEW_PAYEES); + } +} + +contract WithdrawPayment is SetUp { + function testWithdrawPaymentRevertDueToOffchainPayoutMode() public { + registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); + vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOffchain.selector)); + vm.prank(TRANSMITTERS[0]); + registry.withdrawPayment(TRANSMITTERS[0], TRANSMITTERS[0]); + } +} + +contract RegisterUpkeep is SetUp { + function test_RevertsWhen_Paused() public { + registry.pause(); + vm.expectRevert(Registry.RegistryPaused.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TargetIsNotAContract() public { + vm.expectRevert(Registry.NotAContract.selector); + registry.registerUpkeep( + randomAddress(), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_CalledByNonOwner() public { + vm.prank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrRegistrar.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooLow() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + 2299, // 1 less than min + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_ExecuteGasIsTooHigh() public { + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas + 1, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { + vm.expectRevert(Registry.InvalidToken.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + randomAddress(), + "", + "", + "" + ); + } + + function test_RevertsWhen_CheckDataIsTooLarge() public { + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + randomBytes(config.maxCheckDataSize + 1), + "", + "" + ); + } + + function test_Happy() public { + bytes memory checkData = randomBytes(config.maxCheckDataSize); + bytes memory trigggerConfig = randomBytes(100); + bytes memory offchainConfig = randomBytes(100); + + uint256 upkeepCount = registry.getNumUpkeeps(); + + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.LOG), + address(linkToken), + checkData, + trigggerConfig, + offchainConfig + ); + + assertEq(registry.getNumUpkeeps(), upkeepCount + 1); + assertEq(registry.getUpkeep(upkeepID).target, address(TARGET1)); + assertEq(registry.getUpkeep(upkeepID).performGas, config.maxPerformGas); + assertEq(registry.getUpkeep(upkeepID).checkData, checkData); + assertEq(registry.getUpkeep(upkeepID).balance, 0); + assertEq(registry.getUpkeep(upkeepID).admin, UPKEEP_ADMIN); + assertEq(registry.getUpkeep(upkeepID).offchainConfig, offchainConfig); + assertEq(registry.getUpkeepTriggerConfig(upkeepID), trigggerConfig); + assertEq(uint8(registry.getTriggerType(upkeepID)), uint8(Trigger.LOG)); + } +} + +contract OnTokenTransfer is SetUp { + function test_RevertsWhen_NotCalledByTheLinkToken() public { + vm.expectRevert(Registry.OnlyCallableByLINKToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + } + + function test_RevertsWhen_NotCalledWithExactly32Bytes() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(31)); + vm.expectRevert(Registry.InvalidDataLength.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(33)); + } + + function test_RevertsWhen_TheUpkeepIsCancelledOrDNE() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(randomNumber())); + } + + function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { + vm.startPrank(address(linkToken)); + vm.expectRevert(Registry.InvalidToken.selector); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); + } + + function test_Happy() public { + vm.startPrank(address(linkToken)); + uint256 beforeBalance = registry.getBalance(linkUpkeepID); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); + assertEq(registry.getBalance(linkUpkeepID), beforeBalance + 100); + } +} + +contract GetMinBalanceForUpkeep is SetUp { + function test_accountsForFlatFee_with18Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } + + function test_accountsForFlatFee_with6Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } +} + +contract BillingOverrides is SetUp { + event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + + function test_RevertsWhen_NotPrivilegeManager() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_RevertsWhen_UpkeepCancelled() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(PRIVILEGE_MANAGER); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_SetBillingOverrides() public { + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverridden(linkUpkeepID, billingOverrides); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + } + + function test_Happy_RemoveBillingOverrides() public { + vm.startPrank(PRIVILEGE_MANAGER); + + vm.expectEmit(); + emit BillingConfigOverrideRemoved(linkUpkeepID); + registry.removeBillingOverrides(linkUpkeepID); + } + + function test_Happy_MaxGasPayment_WithBillingOverrides() public { + uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + + // Double the two billing values + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + + // maxPayment2 should be greater than maxPayment1 after the overrides + // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium + // We do not apply the exact equation since we couldn't get the receipt.premium value + uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + assertGt(maxPayment2, maxPayment1); + } +} + +contract Transmit is SetUp { + function test_transmitRevertWithExtraBytes() external { + bytes32[3] memory exampleReportContext = [ + bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef), + bytes32(0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890), + bytes32(0x7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456) + ]; + + bytes memory exampleRawReport = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; + + bytes32[] memory exampleRs = new bytes32[](3); + exampleRs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleRs[2] = bytes32(0x7890789078907890789078907890789078907890789078907890789078907890); + + bytes32[] memory exampleSs = new bytes32[](3); + exampleSs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + exampleSs[2] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes32 exampleRawVs = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); + + bytes memory transmitData = abi.encodeWithSelector( + registry.transmit.selector, + exampleReportContext, + exampleRawReport, + exampleRs, + exampleSs, + exampleRawVs + ); + bytes memory badTransmitData = bytes.concat(transmitData, bytes1(0x00)); // add extra data + vm.startPrank(TRANSMITTERS[0]); + (bool success, bytes memory returnData) = address(registry).call(badTransmitData); // send the bogus transmit + assertFalse(success, "Call did not revert as expected"); + assertEq(returnData, abi.encodePacked(Registry.InvalidDataLength.selector)); + vm.stopPrank(); + } + + function test_handlesMixedBatchOfBillingTokens() external { + uint256[] memory prevUpkeepBalances = new uint256[](3); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory upkeepIDs = new uint256[](3); + upkeepIDs[0] = linkUpkeepID; + upkeepIDs[1] = usdUpkeepID18; + upkeepIDs[2] = nativeUpkeepID; + + // withdraw-able by finance team should be 0 + require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); + require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); + + // do the thing + _transmit(upkeepIDs, registry, bytes4(0)); + + // withdraw-able by the finance team should be positive + require( + registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, + "ERC20AvailableForPayment should be positive" + ); + require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); + + // assert upkeep balances have decreased + require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); + require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); + require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); + // assert token balances have not changed + assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], usdToken18.balanceOf(address(registry))); + assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); + // assert reserve amounts have adjusted accordingly + require( + prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), + "usd reserve amount should have increased" + ); // link reserve amount increases in value equal to the decrease of the other reserve amounts + require( + prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), + "usd reserve amount should have decreased" + ); + require( + prevReserveBalances[2] > registry.getReserveAmount(address(weth)), + "native reserve amount should have decreased" + ); + } + + function test_handlesInsufficientBalanceWithUSDToken18() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken18), + "", + "", + "" + ); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); + vm.startPrank(UPKEEP_ADMIN); + usdToken18.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 1); // smaller than gasCharge + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry, bytes4(0)); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(gasChargeInBillingToken, balance); + assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD); + assertEq(premiumInJuels, 0); + assertEq(premiumInBillingToken, 0); + } + + function test_handlesInsufficientBalanceWithUSDToken6() external { + // deploy and configure a registry with ON_CHAIN payout + (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + // register an upkeep and add funds + uint256 upkeepID = registry.registerUpkeep( + address(TARGET1), + 1000000, + UPKEEP_ADMIN, + 0, + address(usdToken6), + "", + "", + "" + ); + vm.prank(OWNER); + usdToken6.mint(UPKEEP_ADMIN, 1e20); + + vm.startPrank(UPKEEP_ADMIN); + usdToken6.approve(address(registry), 1e20); + registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium) + uint256 balance = registry.getBalance(upkeepID); + + // manually create a transmit + vm.recordLogs(); + _transmit(upkeepID, registry, bytes4(0)); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 3); + Vm.Log memory l1 = entries[1]; + assertEq( + l1.topics[0], + keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") + ); + ( + uint96 gasChargeInBillingToken, + uint96 premiumInBillingToken, + uint96 gasReimbursementInJuels, + uint96 premiumInJuels, + address billingToken, + uint96 linkUSD, + uint96 nativeUSD, + uint96 billingUSD + ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); + + assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals + assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12)); + } +} + +contract MigrateReceive is SetUp { + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + + Registry newRegistry; + uint256[] idsToMigrate; + + function setUp() public override { + super.setUp(); + (newRegistry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + idsToMigrate.push(linkUpkeepID); + idsToMigrate.push(linkUpkeepID2); + idsToMigrate.push(usdUpkeepID18); + idsToMigrate.push(nativeUpkeepID); + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + } + + function test_RevertsWhen_PermissionsNotSet() external { + // no permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only outgoing permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // only incoming permissions + registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // permissions opposite direction + registry.setPeerRegistryMigrationPermission(address(newRegistry), 2); + newRegistry.setPeerRegistryMigrationPermission(address(registry), 1); + vm.expectRevert(Registry.MigrationNotPermitted.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_RevertsWhen_ReceivingRegistryDoesNotSupportToken() external { + _removeBillingTokenConfig(newRegistry, address(weth)); + vm.expectRevert(Registry.InvalidToken.selector); + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + idsToMigrate.pop(); // remove native upkeep id + vm.prank(UPKEEP_ADMIN); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); // should succeed now + } + + function test_RevertsWhen_CalledByNonAdmin() external { + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + vm.prank(STRANGER); + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + } + + function test_Success() external { + vm.startPrank(UPKEEP_ADMIN); + + // add some changes in upkeep data to the mix + registry.pauseUpkeep(usdUpkeepID18); + registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); + registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); + + // record previous state + uint256[] memory prevUpkeepBalances = new uint256[](4); + prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); + prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); + prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); + uint256[] memory prevReserveBalances = new uint256[](3); + prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); + prevReserveBalances[2] = registry.getReserveAmount(address(weth)); + uint256[] memory prevTokenBalances = new uint256[](3); + prevTokenBalances[0] = linkToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); + prevTokenBalances[2] = weth.balanceOf(address(registry)); + bytes[] memory prevUpkeepData = new bytes[](4); + prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); + prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); + prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); + prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); + bytes[] memory prevUpkeepTriggerData = new bytes[](4); + prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); + prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); + prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); + prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); + + // event expectations + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID, prevUpkeepBalances[0], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); + vm.expectEmit(address(registry)); + emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID, prevUpkeepBalances[0], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); + vm.expectEmit(address(newRegistry)); + emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); + + // do the thing + registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); + + // assert upkeep balances have been migrated + assertEq(registry.getBalance(linkUpkeepID), 0); + assertEq(registry.getBalance(linkUpkeepID2), 0); + assertEq(registry.getBalance(usdUpkeepID18), 0); + assertEq(registry.getBalance(nativeUpkeepID), 0); + assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); + assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); + assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); + assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); + + // assert reserve balances have been adjusted + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); + assertEq( + newRegistry.getReserveAmount(address(linkToken)), + prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) + ); + assertEq( + newRegistry.getReserveAmount(address(usdToken18)), + prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) + ); + assertEq( + newRegistry.getReserveAmount(address(weth)), + prevReserveBalances[2] - registry.getReserveAmount(address(weth)) + ); + + // assert token have been transferred + assertEq( + linkToken.balanceOf(address(newRegistry)), + newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) + ); + assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); + assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); + assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); + assertEq( + usdToken18.balanceOf(address(registry)), + prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) + ); + assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); + + // assert upkeep data matches + assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); + assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); + assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); + assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); + assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); + assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); + assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); + assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); + + vm.stopPrank(); + } +} + +contract Pause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.expectRevert(bytes("Only callable by owner")); + vm.prank(STRANGER); + registry.pause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + + (IAutomationV21PlusCommon.StateLegacy memory state, , , , ) = registry.getState(); + assertTrue(state.paused); + } + + function test_revertsWhen_registerUpkeepInPausedRegistry() external { + vm.startPrank(registry.owner()); + registry.pause(); + + vm.expectRevert(Registry.RegistryPaused.selector); + uint256 id = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(linkToken), + "", + "", + "" + ); + } + + function test_revertsWhen_transmitInPausedRegistry() external { + vm.startPrank(registry.owner()); + registry.pause(); + + _transmit(usdUpkeepID18, registry, Registry.RegistryPaused.selector); + } +} + +contract Unpause is SetUp { + function test_RevertsWhen_CalledByNonOwner() external { + vm.startPrank(registry.owner()); + registry.pause(); + + vm.expectRevert(bytes("Only callable by owner")); + vm.startPrank(STRANGER); + registry.unpause(); + } + + function test_CalledByOwner_success() external { + vm.startPrank(registry.owner()); + registry.pause(); + (IAutomationV21PlusCommon.StateLegacy memory state1, , , , ) = registry.getState(); + assertTrue(state1.paused); + + registry.unpause(); + (IAutomationV21PlusCommon.StateLegacy memory state2, , , , ) = registry.getState(); + assertFalse(state2.paused); + } +} + +contract CancelUpkeep is SetUp { + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + + function test_RevertsWhen_IdIsInvalid_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_IdIsInvalid_CalledByOwner() external { + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.CannotCancel.selector); + registry.cancelUpkeep(1111111); + } + + function test_RevertsWhen_NotCalledByOwnerOrAdmin() external { + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByOwnerOrAdmin.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(registry.owner()); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(UPKEEP_ADMIN); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // 50 is the cancellation delay + assertEq(bn + 50, maxValidBlocknumber); + } + + function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + registry.cancelUpkeep(linkUpkeepID); + + uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); + + // cancellation by registry owner is immediate and no cancellation delay is applied + assertEq(bn, maxValidBlocknumber); + } + + function test_CancelUpkeep_EmitEvent_CalledByAdmin() external { + uint256 bn = block.number; + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn + 50)); + registry.cancelUpkeep(linkUpkeepID); + } + + function test_CancelUpkeep_EmitEvent_CalledByOwner() external { + uint256 bn = block.number; + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit UpkeepCanceled(linkUpkeepID, uint64(bn)); + registry.cancelUpkeep(linkUpkeepID); + } +} + +contract SetPeerRegistryMigrationPermission is SetUp { + function test_SetPeerRegistryMigrationPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + uint8 permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + + registry.setPeerRegistryMigrationPermission(peer, 1); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(1, permission); + + registry.setPeerRegistryMigrationPermission(peer, 2); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(2, permission); + + registry.setPeerRegistryMigrationPermission(peer, 0); + permission = registry.getPeerRegistryMigrationPermission(peer); + assertEq(0, permission); + } + + function test_RevertsWhen_InvalidPermission_CalledByOwner() external { + address peer = randomAddress(); + vm.startPrank(registry.owner()); + + vm.expectRevert(); + registry.setPeerRegistryMigrationPermission(peer, 100); + } + + function test_RevertsWhen_CalledByNonOwner() external { + address peer = randomAddress(); + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPeerRegistryMigrationPermission(peer, 1); + } +} + +contract SetUpkeepPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, bytes("")); + } + + function test_SetUpkeepPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + + registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); + + bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); + assertEq(cfg, hex"1233"); + } +} + +contract SetAdminPrivilegeConfig is SetUp { + function test_RevertsWhen_CalledByNonManager() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); + registry.setAdminPrivilegeConfig(randomAddress(), hex"1233"); + } + + function test_UpkeepHasEmptyConfig() external { + bytes memory cfg = registry.getAdminPrivilegeConfig(randomAddress()); + assertEq(cfg, bytes("")); + } + + function test_SetAdminPrivilegeConfig_CalledByManager() external { + vm.startPrank(PRIVILEGE_MANAGER); + address admin = randomAddress(); + + registry.setAdminPrivilegeConfig(admin, hex"1233"); + + bytes memory cfg = registry.getAdminPrivilegeConfig(admin); + assertEq(cfg, hex"1233"); + } +} + +contract TransferUpkeepAdmin is SetUp { + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferUpkeepAdmin(linkUpkeepID, UPKEEP_ADMIN); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + } + + function test_DoesNotChangeUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); + + assertEq(registry.getUpkeep(linkUpkeepID).admin, UPKEEP_ADMIN); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + // transferring to the same propose admin won't yield another event + vm.recordLogs(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } + + function test_CancelTransfer_ByTransferToEmptyAddress() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.expectEmit(); + emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, address(0)); + registry.transferUpkeepAdmin(linkUpkeepID, address(0)); + } +} + +contract AcceptUpkeepAdmin is SetUp { + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedAdmin.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + registry.cancelUpkeep(linkUpkeepID); + + vm.startPrank(newAdmin); + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.acceptUpkeepAdmin(linkUpkeepID); + } + + function test_UpkeepAdminChanged() external { + vm.startPrank(UPKEEP_ADMIN); + address newAdmin = randomAddress(); + registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); + + vm.startPrank(newAdmin); + vm.expectEmit(); + emit UpkeepAdminTransferred(linkUpkeepID, UPKEEP_ADMIN, newAdmin); + registry.acceptUpkeepAdmin(linkUpkeepID); + + assertEq(newAdmin, registry.getUpkeep(linkUpkeepID).admin); + } +} + +contract PauseUpkeep is SetUp { + event UpkeepPaused(uint256 indexed id); + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.pauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyPaused() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.OnlyUnpausedUpkeep.selector); + registry.pauseUpkeep(linkUpkeepID); + } + + function test_EmitEvent_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepPaused(linkUpkeepID); + registry.pauseUpkeep(linkUpkeepID); + } +} + +contract UnpauseUpkeep is SetUp { + event UpkeepUnpaused(uint256 indexed id); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID + 1); + } + + function test_RevertsWhen_UpkeepIsNotPaused() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyPausedUpkeep.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_RevertsWhen_NotCalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.unpauseUpkeep(linkUpkeepID); + } + + function test_UnpauseUpkeep_CalledByUpkeepAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + registry.pauseUpkeep(linkUpkeepID); + + uint256[] memory ids1 = registry.getActiveUpkeepIDs(0, 0); + + vm.expectEmit(); + emit UpkeepUnpaused(linkUpkeepID); + registry.unpauseUpkeep(linkUpkeepID); + + uint256[] memory ids2 = registry.getActiveUpkeepIDs(0, 0); + assertEq(ids1.length + 1, ids2.length); + } +} + +contract SetUpkeepCheckData is SetUp { + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID + 1, hex"1234"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NewCheckDataTooLarge() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.CheckDataExceedsLimit.selector); + registry.setUpkeepCheckData(linkUpkeepID, new bytes(10_000)); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } + + function test_UpdateOffchainConfigOnPausedUpkeep_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + registry.pauseUpkeep(linkUpkeepID); + + vm.expectEmit(); + emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); + registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); + + assertTrue(registry.getUpkeep(linkUpkeepID).paused); + assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); + } +} + +contract SetUpkeepGasLimit is SetUp { + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID + 1, 1230000); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_RevertsWhen_NewGasLimitOutOfRange() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 300); + + vm.expectRevert(Registry.GasLimitOutsideRange.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 3000000000); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + } + + function test_UpdateGasLimit_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepGasLimitSet(linkUpkeepID, 1230000); + registry.setUpkeepGasLimit(linkUpkeepID, 1230000); + + assertEq(registry.getUpkeep(linkUpkeepID).performGas, 1230000); + } +} + +contract SetUpkeepOffchainConfig is SetUp { + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateOffchainConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepOffchainConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeep(linkUpkeepID).offchainConfig, hex"1234"); + } +} + +contract SetUpkeepTriggerConfig is SetUp { + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + + function test_RevertsWhen_InvalidUpkeepId() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID + 1, hex"1233"); + } + + function test_RevertsWhen_UpkeepAlreadyCanceled() external { + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(linkUpkeepID); + + vm.expectRevert(Registry.UpkeepCancelled.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_RevertsWhen_NotCalledByAdmin() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByAdmin.selector); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + } + + function test_UpdateTriggerConfig_CalledByAdmin() external { + vm.startPrank(UPKEEP_ADMIN); + + vm.expectEmit(); + emit UpkeepTriggerConfigSet(linkUpkeepID, hex"1234"); + registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); + + assertEq(registry.getUpkeepTriggerConfig(linkUpkeepID), hex"1234"); + } +} + +contract TransferPayeeship is SetUp { + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByPayee() external { + vm.startPrank(STRANGER); + + vm.expectRevert(Registry.OnlyCallableByPayee.selector); + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + } + + function test_RevertsWhen_TransferToSelf() external { + registry.setPayees(PAYEES); + vm.startPrank(PAYEES[0]); + + vm.expectRevert(Registry.ValueNotChanged.selector); + registry.transferPayeeship(TRANSMITTERS[0], PAYEES[0]); + } + + function test_Transfer_DoesNotChangePayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + + registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(PAYEES[0], payee); + } + + function test_EmitEvent_CalledByPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + + vm.expectEmit(); + emit PayeeshipTransferRequested(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + // transferring to the same propose payee won't yield another event + vm.recordLogs(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(0, entries.length); + } +} + +contract AcceptPayeeship is SetUp { + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + + function test_RevertsWhen_NotCalledByProposedPayee() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(STRANGER); + vm.expectRevert(Registry.OnlyCallableByProposedPayee.selector); + registry.acceptPayeeship(TRANSMITTERS[0]); + } + + function test_PayeeChanged() external { + registry.setPayees(PAYEES); + + vm.startPrank(PAYEES[0]); + address newPayee = randomAddress(); + registry.transferPayeeship(TRANSMITTERS[0], newPayee); + + vm.startPrank(newPayee); + vm.expectEmit(); + emit PayeeshipTransferred(TRANSMITTERS[0], PAYEES[0], newPayee); + registry.acceptPayeeship(TRANSMITTERS[0]); + + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertEq(newPayee, payee); + } +} + +contract SetPayees is SetUp { + event PayeesUpdated(address[] transmitters, address[] payees); + + function test_RevertsWhen_NotCalledByOwner() external { + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + registry.setPayees(NEW_PAYEES); + } + + function test_RevertsWhen_PayeesLengthError() external { + vm.startPrank(registry.owner()); + + address[] memory payees = new address[](5); + vm.expectRevert(Registry.ParameterLengthError.selector); + registry.setPayees(payees); + } + + function test_RevertsWhen_InvalidPayee() external { + vm.startPrank(registry.owner()); + + NEW_PAYEES[0] = address(0); + vm.expectRevert(Registry.InvalidPayee.selector); + registry.setPayees(NEW_PAYEES); + } + + function test_SetPayees_WhenExistingPayeesAreEmpty() external { + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertEq(address(0), payee); + } + + vm.startPrank(registry.owner()); + + vm.expectEmit(); + emit PayeesUpdated(TRANSMITTERS, PAYEES); + registry.setPayees(PAYEES); + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertTrue(active); + assertEq(PAYEES[i], payee); + } + } + + function test_DotNotSetPayeesToIgnoredAddress() external { + address IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); + PAYEES[0] = IGNORE_ADDRESS; + + registry.setPayees(PAYEES); + (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); + assertTrue(active); + assertEq(address(0), payee); + + (active, , , , payee) = registry.getTransmitterInfo(TRANSMITTERS[1]); + assertTrue(active); + assertEq(PAYEES[1], payee); + } +} + +contract GetActiveUpkeepIDs is SetUp { + function test_RevertsWhen_IndexOutOfRange() external { + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(5, 0); + + vm.expectRevert(Registry.IndexOutOfRange.selector); + registry.getActiveUpkeepIDs(6, 0); + } + + function test_ReturnsAllUpkeeps_WhenMaxCountIsZero() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(0, 0); + assertEq(5, uids.length); + + uids = registry.getActiveUpkeepIDs(2, 0); + assertEq(3, uids.length); + } + + function test_ReturnsAllRemainingUpkeeps_WhenMaxCountIsTooLarge() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(2, 20); + assertEq(3, uids.length); + } + + function test_ReturnsUpkeeps_BoundByMaxCount() external { + uint256[] memory uids = registry.getActiveUpkeepIDs(1, 2); + assertEq(2, uids.length); + assertEq(uids[0], linkUpkeepID2); + assertEq(uids[1], usdUpkeepID18); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol new file mode 100644 index 0000000..f500547 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {Cron as CronInternal, Spec} from "../libraries/internal/Cron.sol"; +import {Cron as CronExternal} from "../libraries/external/Cron.sol"; + +/** + * @title The CronInternalTestHelper contract + * @notice This contract exposes core functionality of the internal/Cron library. + * It is only intended for use in tests. + */ +contract CronInternalTestHelper { + /** + * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to convert and encode + * @return the abi encoding of the Spec struct representing the cron string + */ + function encodeCronString(string memory cronString) external pure returns (bytes memory) { + return CronInternal.toEncodedSpec(cronString); + } + + /** + * @notice encodedSpecToString is a helper function for turning an + * encoded spec back into a string. There is limited or no use for this outside + * of tests. + */ + function encodedSpecToString(bytes memory encodedSpec) public pure returns (string memory) { + Spec memory spec = abi.decode(encodedSpec, (Spec)); + return CronInternal.toCronString(spec); + } + + /** + * @notice calculateNextTick calculates the next time a cron job should "tick". + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to consider + * @return the timestamp in UTC of the next "tick" + */ + function calculateNextTick(string memory cronString) external view returns (uint256) { + return CronInternal.nextTick(CronInternal.toSpec(cronString)); + } + + /** + * @notice calculateLastTick calculates the last time a cron job "ticked". + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to consider + * @return the timestamp in UTC of the last "tick" + */ + function calculateLastTick(string memory cronString) external view returns (uint256) { + return CronInternal.lastTick(CronInternal.toSpec(cronString)); + } +} + +/** + * @title The CronExternalTestHelper contract + * @notice This contract exposes core functionality of the external/Cron library. + * It is only intended for use in tests. + */ +contract CronExternalTestHelper { + /** + * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to convert and encode + * @return the abi encoding of the Spec struct representing the cron string + */ + function encodeCronString(string memory cronString) external pure returns (bytes memory) { + return CronExternal.toEncodedSpec(cronString); + } + + /** + * @notice encodedSpecToString is a helper function for turning an + * encoded spec back into a string. There is limited or no use for this outside + * of tests. + */ + function encodedSpecToString(bytes memory encodedSpec) public pure returns (string memory) { + Spec memory spec = abi.decode(encodedSpec, (Spec)); + return CronExternal.toCronString(spec); + } + + /** + * @notice calculateNextTick calculates the next time a cron job should "tick". + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to consider + * @return the timestamp in UTC of the next "tick" + */ + function calculateNextTick(string memory cronString) external view returns (uint256) { + return CronExternal.nextTick(CronExternal.toSpec(cronString)); + } + + /** + * @notice calculateLastTick calculates the last time a cron job "ticked". + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to consider + * @return the timestamp in UTC of the last "tick" + */ + function calculateLastTick(string memory cronString) external view returns (uint256) { + return CronExternal.lastTick(CronExternal.toSpec(cronString)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol new file mode 100644 index 0000000..8ede4ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import "../upkeeps/CronUpkeep.sol"; +import {Cron, Spec} from "../libraries/internal/Cron.sol"; + +/** + * @title The CronUpkeepTestHelper contract + * @notice This contract exposes core functionality of the CronUpkeep contract. + * It is only intended for use in tests. + */ +contract CronUpkeepTestHelper is CronUpkeep { + using Cron for Spec; + using Cron for string; + + constructor( + address owner, + address delegate, + uint256 maxJobs, + bytes memory firstJob + ) CronUpkeep(owner, delegate, maxJobs, firstJob) {} + + /** + * @notice createCronJobFromString is a helper function for creating cron jobs + * directly from strings. This is gas-intensive and shouldn't be done outside + * of testing environments. + */ + function createCronJobFromString(address target, bytes memory handler, string memory cronString) external { + Spec memory spec = cronString.toSpec(); + createCronJobFromSpec(target, handler, spec); + } + + /** + * @notice txCheckUpkeep is a helper function for sending real txs to the + * checkUpkeep function. This allows us to do gas analysis on it. + */ + function txCheckUpkeep(bytes calldata checkData) external { + address(this).call(abi.encodeWithSelector(bytes4(keccak256("checkUpkeep(bytes)")), checkData)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol new file mode 100644 index 0000000..4e86ec2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +// this struct is the same as LogTriggerConfig defined in KeeperRegistryLogicA2_1 contract +struct LogTriggerConfig { + address contractAddress; + uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply + bytes32 topic0; + bytes32 topic1; + bytes32 topic2; + bytes32 topic3; +} + +contract DummyProtocol { + event LimitOrderSent(uint256 indexed amount, uint256 indexed price, address indexed to); // keccak256(LimitOrderSent(uint256,uint256,address)) => 0x3e9c37b3143f2eb7e9a2a0f8091b6de097b62efcfe48e1f68847a832e521750a + event LimitOrderWithdrawn(uint256 indexed amount, uint256 indexed price, address indexed from); // keccak256(LimitOrderWithdrawn(uint256,uint256,address)) => 0x0a71b8ed921ff64d49e4d39449f8a21094f38a0aeae489c3051aedd63f2c229f + event LimitOrderExecuted(uint256 indexed orderId, uint256 indexed amount, address indexed exchange); // keccak(LimitOrderExecuted(uint256,uint256,address)) => 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd + + function sendLimitedOrder(uint256 amount, uint256 price, address to) public { + // send an order to an exchange + emit LimitOrderSent(amount, price, to); + } + + function withdrawLimit(uint256 amount, uint256 price, address from) public { + // withdraw an order from an exchange + emit LimitOrderSent(amount, price, from); + } + + function executeLimitOrder(uint256 orderId, uint256 amount, address exchange) public { + // execute a limit order + emit LimitOrderExecuted(orderId, amount, exchange); + } + + /** + * @notice this function generates bytes for a basic log trigger config with no filter selector. + * @param targetContract the address of contract where events will be emitted from + * @param t0 the signature of the event to listen to + */ + function getBasicLogTriggerConfig( + address targetContract, + bytes32 t0 + ) external view returns (bytes memory logTrigger) { + LogTriggerConfig memory cfg = LogTriggerConfig({ + contractAddress: targetContract, + filterSelector: 0, + topic0: t0, + topic1: 0x000000000000000000000000000000000000000000000000000000000000000, + topic2: 0x000000000000000000000000000000000000000000000000000000000000000, + topic3: 0x000000000000000000000000000000000000000000000000000000000000000 + }); + return abi.encode(cfg); + } + + /** + * @notice this function generates bytes for a customizable log trigger config. + * @param targetContract the address of contract where events will be emitted from + * @param selector the filter selector. this denotes which topics apply to filter ex 000, 101, 111....only last 3 bits apply + * if 0, it won't filter based on topic 1, 2, 3. + * if 1, it will filter based on topic 1, + * if 2, it will filter based on topic 2, + * if 3, it will filter based on topic 1 and topic 2, + * if 4, it will filter based on topic 3, + * if 5, it will filter based on topic 1 and topic 3.... + * @param t0 the signature of the event to listen to. + * @param t1 the topic 1 of the event. + * @param t2 the topic 2 of the event. + * @param t3 the topic 2 of the event. + */ + function getAdvancedLogTriggerConfig( + address targetContract, + uint8 selector, + bytes32 t0, + bytes32 t1, + bytes32 t2, + bytes32 t3 + ) external view returns (bytes memory logTrigger) { + LogTriggerConfig memory cfg = LogTriggerConfig({ + contractAddress: targetContract, + filterSelector: selector, + topic0: t0, + topic1: t1, + topic2: t2, + topic3: t3 + }); + return abi.encode(cfg); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol new file mode 100644 index 0000000..fb492f3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol @@ -0,0 +1,26 @@ +pragma solidity 0.8.16; + +import "../interfaces/KeeperCompatibleInterface.sol"; +import "../KeeperBase.sol"; + +contract KeeperConsumer is KeeperCompatibleInterface, KeeperBase { + uint public counter; + uint public immutable interval; + uint public lastTimeStamp; + + constructor(uint updateInterval) public { + interval = updateInterval; + lastTimeStamp = block.timestamp; + counter = 0; + } + + function checkUpkeep( + bytes calldata checkData + ) external view override cannotExecute returns (bool upkeepNeeded, bytes memory performData) { + return (true, checkData); + } + + function performUpkeep(bytes calldata performData) external override { + counter = counter + 1; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol new file mode 100644 index 0000000..5b7f57e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol @@ -0,0 +1,88 @@ +pragma solidity 0.8.16; + +contract KeeperConsumerPerformance { + event PerformingUpkeep(bool eligible, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); + + uint256 public initialCall = 0; + uint256 public nextEligible = 0; + uint256 public testRange; + uint256 public averageEligibilityCadence; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup + + uint256 public count = 0; + + constructor( + uint256 _testRange, + uint256 _averageEligibilityCadence, + uint256 _checkGasToBurn, + uint256 _performGasToBurn + ) { + testRange = _testRange; + averageEligibilityCadence = _averageEligibilityCadence; + checkGasToBurn = _checkGasToBurn; + performGasToBurn = _performGasToBurn; + } + + function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { + uint256 startGas = gasleft(); + bool dummy; + // burn gas + while (startGas - gasleft() < checkGasToBurn) { + dummy = dummy && dummyMap[blockhash(block.number)]; // arbitrary state reads + } + return (eligible(), abi.encode(dummy)); + } + + function performUpkeep(bytes calldata data) external { + uint256 startGas = gasleft(); + bool eligible = eligible(); + uint256 blockNum = block.number; + emit PerformingUpkeep(eligible, tx.origin, initialCall, nextEligible, blockNum); + require(eligible); + if (initialCall == 0) { + initialCall = blockNum; + } + nextEligible = (blockNum + (rand() % (averageEligibilityCadence * 2))) + 1; + count++; + // burn gas + while (startGas - gasleft() < performGasToBurn) { + dummyMap[blockhash(block.number)] = false; + } + } + + function setCheckGasToBurn(uint256 value) public { + checkGasToBurn = value; + } + + function setPerformGasToBurn(uint256 value) public { + performGasToBurn = value; + } + + function getCountPerforms() public view returns (uint256) { + return count; + } + + function eligible() internal view returns (bool) { + return initialCall == 0 || (block.number - initialCall < testRange && block.number > nextEligible); + } + + function checkEligible() public view returns (bool) { + return eligible(); + } + + function reset() external { + initialCall = 0; + count = 0; + } + + function setSpread(uint256 _newTestRange, uint256 _newAverageEligibilityCadence) external { + testRange = _newTestRange; + averageEligibilityCadence = _newAverageEligibilityCadence; + } + + function rand() private view returns (uint256) { + return uint256(keccak256(abi.encode(blockhash(block.number - 1), address(this)))); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol new file mode 100644 index 0000000..d0b89b3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; + +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier. + * @param signedReport The encoded data to be verified. + * @return verifierResponse The encoded response from the verifier. + */ + function verify(bytes memory signedReport) external returns (bytes memory verifierResponse); +} + +contract LogTriggeredStreamsLookup is ILogAutomation, StreamsLookupCompatibleInterface { + event PerformingLogTriggerUpkeep( + address indexed from, + uint256 orderId, + uint256 amount, + address exchange, + uint256 blockNumber, + bytes blob, + bytes verified + ); + event LimitOrderExecuted(uint256 indexed orderId, uint256 indexed amount, address indexed exchange); // keccak(LimitOrderExecuted(uint256,uint256,address)) => 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd + event IgnoringErrorHandlerData(); + + ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); + IVerifierProxy internal constant VERIFIER = IVerifierProxy(0x09DFf56A4fF44e0f4436260A04F5CFa65636A481); + + // for log trigger + bytes32 constant sentSig = 0x3e9c37b3143f2eb7e9a2a0f8091b6de097b62efcfe48e1f68847a832e521750a; + bytes32 constant withdrawnSig = 0x0a71b8ed921ff64d49e4d39449f8a21094f38a0aeae489c3051aedd63f2c229f; + bytes32 constant executedSig = 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd; + + // for mercury config + bool public useArbitrumBlockNum; + bool public verify; + string[] public feedsHex = ["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]; + string public feedParamKey = "feedIdHex"; + string public timeParamKey = "blockNumber"; + uint256 public counter; + bool public checkErrReturnBool; + + constructor(bool _useArbitrumBlockNum, bool _verify, bool _checkErrReturnBool) { + useArbitrumBlockNum = _useArbitrumBlockNum; + verify = _verify; + checkErrReturnBool = _checkErrReturnBool; + counter = 0; + } + + function start() public { + // need an initial event to begin the cycle + emit LimitOrderExecuted(1, 100, address(0x0)); + } + + function setTimeParamKey(string memory timeParam) external { + timeParamKey = timeParam; + } + + function setFeedParamKey(string memory feedParam) external { + feedParamKey = feedParam; + } + + function setFeedsHex(string[] memory newFeeds) external { + feedsHex = newFeeds; + } + + function checkLog( + Log calldata log, + bytes memory + ) external override returns (bool upkeepNeeded, bytes memory performData) { + uint256 blockNum = getBlockNumber(); + + // filter by event signature + if (log.topics[0] == executedSig) { + // filter by indexed parameters + bytes memory t1 = abi.encodePacked(log.topics[1]); // bytes32 to bytes + uint256 orderId = abi.decode(t1, (uint256)); + bytes memory t2 = abi.encodePacked(log.topics[2]); + uint256 amount = abi.decode(t2, (uint256)); + bytes memory t3 = abi.encodePacked(log.topics[3]); + address exchange = abi.decode(t3, (address)); + + revert StreamsLookup( + feedParamKey, + feedsHex, + timeParamKey, + blockNum, + abi.encode(orderId, amount, exchange, executedSig) + ); + } + revert("could not find matching event sig"); + } + + function performUpkeep(bytes calldata performData) external override { + if (performData.length == 0) { + emit IgnoringErrorHandlerData(); + return; + } + (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + (uint256 orderId, uint256 amount, address exchange, bytes32 logTopic0) = abi.decode( + extraData, + (uint256, uint256, address, bytes32) + ); + + bytes memory verifiedResponse = ""; + if (verify) { + verifiedResponse = VERIFIER.verify(values[0]); + } + + counter = counter + 1; + if (logTopic0 == executedSig) { + emit LimitOrderExecuted(1, 100, address(0x0)); + } + + emit PerformingLogTriggerUpkeep( + tx.origin, + orderId, + amount, + exchange, + getBlockNumber(), + values[0], + verifiedResponse + ); + } + + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external view override returns (bool, bytes memory) { + // do sth about the chainlinkBlob data in values and extraData + bytes memory performData = abi.encode(values, extraData); + return (true, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (checkErrReturnBool, new bytes(0)); + } + + function getBlockNumber() internal view returns (uint256) { + if (useArbitrumBlockNum) { + return ARB_SYS.arbBlockNumber(); + } else { + return block.number; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol new file mode 100644 index 0000000..8f7fa46 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; + +contract LogUpkeepCounter is ILogAutomation { + bytes32 sig1 = 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d; + bytes32 sig2 = 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da; + bytes32 sig3 = 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8; + bytes32 sig4 = 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71; + + event PerformingUpkeep( + address indexed from, + uint256 initialBlock, + uint256 lastBlock, + uint256 previousBlock, + uint256 counter + ); + + /** + * @dev we include multiple event types for testing various filters, signatures, etc + */ + event Trigger(); // 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d + event Trigger(uint256 a); // 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da + event Trigger(uint256 a, uint256 b); // 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8 + event Trigger(uint256 a, uint256 b, uint256 c); // 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71 + + uint256 public testRange; + uint256 public lastBlock; + uint256 public previousPerformBlock; + uint256 public initialBlock; + uint256 public counter; + bool public autoExecution; + + constructor(uint256 _testRange) { + testRange = _testRange; + previousPerformBlock = 0; + lastBlock = block.number; + initialBlock = 0; + counter = 0; + autoExecution = true; + } + + function start() public { + // need an initial event to begin the cycle + emit Trigger(); + emit Trigger(1); + emit Trigger(1, 2); + emit Trigger(1, 2, 3); + } + + function checkLog(Log calldata log, bytes memory) external view override returns (bool, bytes memory) { + require(eligible(), "not eligible"); + if (log.topics[0] == sig1 || log.topics[0] == sig2 || log.topics[0] == sig3 || log.topics[0] == sig4) { + return (true, abi.encode(log)); + } else { + revert("could not find matching event sig"); + } + } + + function performUpkeep(bytes calldata performData) external override { + if (initialBlock == 0) { + initialBlock = block.number; + } + lastBlock = block.number; + counter = counter + 1; + previousPerformBlock = lastBlock; + Log memory log = abi.decode(performData, (Log)); + if (autoExecution) { + if (log.topics[0] == sig1) { + emit Trigger(); + } else if (log.topics[0] == sig2) { + emit Trigger(1); + } else if (log.topics[0] == sig3) { + emit Trigger(1, 2); + } else if (log.topics[0] == sig4) { + emit Trigger(1, 2, 3); + } else { + revert("could not find matching sig"); + } + } + emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter); + } + + function eligible() public view returns (bool) { + if (initialBlock == 0) { + return true; + } + + return (block.number - initialBlock) < testRange; + } + + function setSpread(uint256 _testRange) external { + testRange = _testRange; + initialBlock = 0; + counter = 0; + } + + function setAuto(bool _auto) external { + autoExecution = _auto; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol new file mode 100644 index 0000000..10f6732 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "../../shared/interfaces/AggregatorV3Interface.sol"; + +contract MockETHUSDAggregator is AggregatorV3Interface { + int256 public answer; + uint256 private blockTimestampDeduction = 0; + + constructor(int256 _answer) { + answer = _answer; + } + + function decimals() external pure override returns (uint8) { + return 8; + } + + function description() external pure override returns (string memory) { + return "MockETHUSDAggregator"; + } + + function version() external pure override returns (uint256) { + return 1; + } + + function getRoundData( + uint80 /*_roundId*/ + ) + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function latestRoundData() + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function getDeductedBlockTimestamp() internal view returns (uint256) { + return block.timestamp - blockTimestampDeduction; + } + + function setBlockTimestampDeduction(uint256 _blockTimestampDeduction) external { + blockTimestampDeduction = _blockTimestampDeduction; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol new file mode 100644 index 0000000..268942f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import "../interfaces/KeeperCompatibleInterface.sol"; + +contract PerformDataChecker is KeeperCompatibleInterface { + uint256 public counter; + bytes public s_expectedData; + + constructor(bytes memory expectedData) { + s_expectedData = expectedData; + } + + function setExpectedData(bytes calldata expectedData) external { + s_expectedData = expectedData; + } + + function checkUpkeep( + bytes calldata checkData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + return (keccak256(checkData) == keccak256(s_expectedData), checkData); + } + + function performUpkeep(bytes calldata performData) external override { + if (keccak256(performData) == keccak256(s_expectedData)) { + counter++; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol new file mode 100644 index 0000000..c4d5771 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; + +struct CheckData { + uint256 checkBurnAmount; + uint256 performBurnAmount; + bytes32 eventSig; + string[] feeds; +} + +contract SimpleLogUpkeepCounter is ILogAutomation, StreamsLookupCompatibleInterface { + event PerformingUpkeep( + address indexed from, + uint256 initialBlock, + uint256 lastBlock, + uint256 previousBlock, + uint256 counter, + uint256 timeToPerform, + bool isRecovered + ); + + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup + uint256 public lastBlock; + uint256 public previousPerformBlock; + uint256 public initialBlock; + uint256 public counter; + uint256 public timeToPerform; + bool internal isRecovered; + bool public isStreamsLookup; + bool public shouldRetryOnError; + string public feedParamKey = "feedIDs"; + string public timeParamKey = "timestamp"; + + constructor(bool _isStreamsLookup) { + previousPerformBlock = 0; + lastBlock = block.number; + initialBlock = 0; + counter = 0; + isStreamsLookup = _isStreamsLookup; + } + + function _checkDataConfig(CheckData memory) external {} + + function setTimeParamKey(string memory timeParam) external { + timeParamKey = timeParam; + } + + function setFeedParamKey(string memory feedParam) external { + feedParamKey = feedParam; + } + + function setShouldRetryOnErrorBool(bool value) public { + shouldRetryOnError = value; + } + + function checkLog(Log calldata log, bytes calldata checkData) external view override returns (bool, bytes memory) { + CheckData memory _checkData = abi.decode(checkData, (CheckData)); + uint256 startGas = gasleft(); + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + // burn gas + if (_checkData.checkBurnAmount > 0) { + while (startGas - gasleft() < _checkData.checkBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + bytes[] memory values = new bytes[](2); + values[0] = abi.encode(0x00); + values[1] = abi.encode(0x00); + bytes memory extraData = abi.encode(log, block.number, checkData); + if (log.topics[2] == _checkData.eventSig) { + if (isStreamsLookup) { + revert StreamsLookup(feedParamKey, _checkData.feeds, timeParamKey, block.timestamp, extraData); + } + return (true, abi.encode(values, extraData)); + } + return (false, abi.encode(values, extraData)); + } + + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external view override returns (bool, bytes memory) { + // do sth about the chainlinkBlob data in values and extraData + bytes memory performData = abi.encode(values, extraData); + return (true, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + bytes[] memory values = new bytes[](2); + values[0] = abi.encode(errCode); + values[1] = abi.encode(extraData); + bytes memory returnData = abi.encode(values, extraData); + return (shouldRetryOnError, returnData); + } + + function performUpkeep(bytes calldata performData) external override { + if (initialBlock == 0) { + initialBlock = block.number; + } + lastBlock = block.number; + counter = counter + 1; + previousPerformBlock = lastBlock; + (, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + (Log memory log, uint256 checkBlock, bytes memory checkData) = abi.decode(extraData, (Log, uint256, bytes)); + timeToPerform = block.timestamp - log.timestamp; + isRecovered = false; + if (checkBlock != log.blockNumber) { + isRecovered = true; + } + CheckData memory _checkData = abi.decode(checkData, (CheckData)); + uint256 startGas = gasleft(); + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + if (log.topics[2] != _checkData.eventSig) { + revert("Invalid event signature"); + } + // burn gas + if (_checkData.performBurnAmount > 0) { + while (startGas - gasleft() < _checkData.performBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + emit PerformingUpkeep( + tx.origin, + initialBlock, + lastBlock, + previousPerformBlock, + counter, + timeToPerform, + isRecovered + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol new file mode 100644 index 0000000..263aad5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AutomationCompatible} from "../AutomationCompatible.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AutomationRegistryBaseInterface} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; + +contract UpkeepAutoFunder is AutomationCompatible, ConfirmedOwner { + bool public s_isEligible; + bool public s_shouldCancel; + uint256 public s_upkeepId; + uint96 public s_autoFundLink; + LinkTokenInterface public immutable LINK; + AutomationRegistryBaseInterface public immutable s_keeperRegistry; + + constructor(address linkAddress, address registryAddress) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(linkAddress); + s_keeperRegistry = AutomationRegistryBaseInterface(registryAddress); + + s_isEligible = false; + s_shouldCancel = false; + s_upkeepId = 0; + s_autoFundLink = 0; + } + + function setShouldCancel(bool value) external onlyOwner { + s_shouldCancel = value; + } + + function setIsEligible(bool value) external onlyOwner { + s_isEligible = value; + } + + function setAutoFundLink(uint96 value) external onlyOwner { + s_autoFundLink = value; + } + + function setUpkeepId(uint256 value) external onlyOwner { + s_upkeepId = value; + } + + function checkUpkeep( + bytes calldata data + ) external override cannotExecute returns (bool callable, bytes calldata executedata) { + return (s_isEligible, data); + } + + function performUpkeep(bytes calldata data) external override { + require(s_isEligible, "Upkeep should be eligible"); + s_isEligible = false; // Allow upkeep only once until it is set again + + // Topup upkeep so it can be called again + LINK.transferAndCall(address(s_keeperRegistry), s_autoFundLink, abi.encode(s_upkeepId)); + + if (s_shouldCancel) { + s_keeperRegistry.cancelUpkeep(s_upkeepId); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol new file mode 100644 index 0000000..24a8b1f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +contract UpkeepCounter { + event PerformingUpkeep( + address indexed from, + uint256 initialTimestamp, + uint256 lastTimestamp, + uint256 previousBlock, + uint256 counter + ); + + uint256 public testRange; + uint256 public interval; + uint256 public lastTimestamp; + uint256 public previousPerformBlock; + uint256 public initialTimestamp; + uint256 public counter; + + constructor(uint256 _testRange, uint256 _interval) { + testRange = _testRange; + interval = _interval; + previousPerformBlock = 0; + lastTimestamp = block.timestamp; + initialTimestamp = 0; + counter = 0; + } + + function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { + return (eligible(), data); + } + + function performUpkeep(bytes calldata performData) external { + if (initialTimestamp == 0) { + initialTimestamp = block.timestamp; + } + lastTimestamp = block.timestamp; + counter = counter + 1; + performData; + emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); + previousPerformBlock = lastTimestamp; + } + + function eligible() public view returns (bool) { + if (initialTimestamp == 0) { + return true; + } + + return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; + } + + function setSpread(uint256 _testRange, uint256 _interval) external { + testRange = _testRange; + interval = _interval; + initialTimestamp = 0; + counter = 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol new file mode 100644 index 0000000..76b3877 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +contract UpkeepCounterNew { + event PerformingUpkeep( + address indexed from, + uint256 initialTimestamp, + uint256 lastTimestamp, + uint256 previousBlock, + uint256 counter + ); + error InvalidCaller(address caller, address forwarder); + + uint256 public testRange; + uint256 public interval; + uint256 public lastTimestamp; + uint256 public previousPerformBlock; + uint256 public initialTimestamp; + uint256 public counter; + bool public useMoreCheckGas; + bool public useMorePerformGas; + bool public useMorePerformData; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + bytes public data; + bytes public dataCopy; + bool public trickSimulation = false; + address public forwarder; + + constructor() { + testRange = 1000000; + interval = 40; + previousPerformBlock = 0; + lastTimestamp = block.timestamp; + initialTimestamp = 0; + counter = 0; + useMoreCheckGas = false; + useMorePerformData = false; + useMorePerformGas = false; + checkGasToBurn = 9700000; + performGasToBurn = 7700000; + } + + function setPerformGasToBurn(uint256 _performGasToBurn) external { + performGasToBurn = _performGasToBurn; + } + + function setCheckGasToBurn(uint256 _checkGasToBurn) external { + checkGasToBurn = _checkGasToBurn; + } + + function setUseMoreCheckGas(bool _useMoreCheckGas) external { + useMoreCheckGas = _useMoreCheckGas; + } + + function setUseMorePerformGas(bool _useMorePerformGas) external { + useMorePerformGas = _useMorePerformGas; + } + + function setUseMorePerformData(bool _useMorePerformData) external { + useMorePerformData = _useMorePerformData; + } + + function setData(bytes calldata _data) external { + data = _data; + } + + function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { + if (useMoreCheckGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < checkGasToBurn) {} // burn gas + } + + if (useMorePerformData) { + return (eligible(), data); + } + return (eligible(), ""); + } + + function setTrickSimulation(bool _trickSimulation) external { + trickSimulation = _trickSimulation; + } + + function performUpkeep(bytes calldata performData) external { + if (trickSimulation && tx.origin == address(0)) { + return; + } + + if (msg.sender != forwarder) { + revert InvalidCaller(msg.sender, forwarder); + } + + if (useMorePerformGas) { + uint256 startGas = gasleft(); + while (startGas - gasleft() < performGasToBurn) {} // burn gas + } + + if (initialTimestamp == 0) { + initialTimestamp = block.timestamp; + } + lastTimestamp = block.timestamp; + counter = counter + 1; + dataCopy = performData; + emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); + previousPerformBlock = lastTimestamp; + } + + function eligible() public view returns (bool) { + if (initialTimestamp == 0) { + return true; + } + + return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; + } + + function setSpread(uint256 _testRange, uint256 _interval) external { + testRange = _testRange; + interval = _interval; + initialTimestamp = 0; + counter = 0; + } + + function setForwarder(address _forwarder) external { + forwarder = _forwarder; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol new file mode 100644 index 0000000..392700e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AutomationCompatible} from "../AutomationCompatible.sol"; + +contract UpkeepMock is AutomationCompatible { + bool public shouldRevertCheck; + bool public canCheck; + bool public canPerform; + bytes public performData; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + string public checkRevertReason; + + uint256 constant checkGasBuffer = 6000; // use all but this amount in gas burn loops + uint256 constant performGasBuffer = 1000; // use all but this amount in gas burn loops + + event UpkeepPerformedWith(bytes upkeepData); + + function setShouldRevertCheck(bool value) public { + shouldRevertCheck = value; + } + + function setPerformData(bytes calldata data) public { + performData = data; + } + + function setCanCheck(bool value) public { + canCheck = value; + } + + function setCanPerform(bool value) public { + canPerform = value; + } + + function setCheckRevertReason(string calldata value) public { + checkRevertReason = value; + } + + function setCheckGasToBurn(uint256 value) public { + require(value > checkGasBuffer || value == 0, "checkGasToBurn must be 0 (disabled) or greater than buffer"); + if (value > 0) { + checkGasToBurn = value - checkGasBuffer; + } else { + checkGasToBurn = 0; + } + } + + function setPerformGasToBurn(uint256 value) public { + require(value > performGasBuffer || value == 0, "performGasToBurn must be 0 (disabled) or greater than buffer"); + if (value > 0) { + performGasToBurn = value - performGasBuffer; + } else { + performGasToBurn = 0; + } + } + + function checkUpkeep( + bytes calldata + ) external override cannotExecute returns (bool callable, bytes memory executedata) { + require(!shouldRevertCheck, checkRevertReason); + uint256 startGas = gasleft(); + bool couldCheck = canCheck; + + setCanCheck(false); // test that state modifications don't stick + + while (startGas - gasleft() < checkGasToBurn) {} // burn gas + + return (couldCheck, performData); + } + + function performUpkeep(bytes calldata data) external override { + uint256 startGas = gasleft(); + + require(canPerform, "Cannot perform"); + + emit UpkeepPerformedWith(data); + + while (startGas - gasleft() < performGasToBurn) {} // burn gas + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol new file mode 100644 index 0000000..3aa345a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol @@ -0,0 +1,85 @@ +pragma solidity 0.8.16; + +contract UpkeepPerformCounterRestrictive { + event PerformingUpkeep(bool eligible, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); + + uint256 public initialCall = 0; + uint256 public nextEligible = 0; + uint256 public testRange; + uint256 public averageEligibilityCadence; + uint256 public checkGasToBurn; + uint256 public performGasToBurn; + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup + + uint256 private count = 0; + + constructor(uint256 _testRange, uint256 _averageEligibilityCadence) { + testRange = _testRange; + averageEligibilityCadence = _averageEligibilityCadence; + } + + function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { + uint256 startGas = gasleft(); + uint256 blockNum = block.number - 1; + bool dummy; + // burn gas + while (startGas - gasleft() < checkGasToBurn) { + dummy = dummy && dummyMap[blockhash(blockNum)]; // arbitrary storage reads + blockNum--; + } + return (eligible(), abi.encode(dummy)); + } + + function performUpkeep(bytes calldata) external { + uint256 startGas = gasleft(); + bool eligible = eligible(); + uint256 blockNum = block.number; + emit PerformingUpkeep(eligible, tx.origin, initialCall, nextEligible, blockNum); + require(eligible); + if (initialCall == 0) { + initialCall = blockNum; + } + nextEligible = (blockNum + (rand() % (averageEligibilityCadence * 2))) + 1; + count++; + // burn gas + blockNum--; + while (startGas - gasleft() < performGasToBurn) { + dummyMap[blockhash(blockNum)] = false; // arbitrary storage writes + blockNum--; + } + } + + function setCheckGasToBurn(uint256 value) public { + checkGasToBurn = value; + } + + function setPerformGasToBurn(uint256 value) public { + performGasToBurn = value; + } + + function getCountPerforms() public view returns (uint256) { + return count; + } + + function eligible() internal view returns (bool) { + return initialCall == 0 || (block.number - initialCall < testRange && block.number > nextEligible); + } + + function checkEligible() public view returns (bool) { + return eligible(); + } + + function reset() external { + initialCall = 0; + count = 0; + } + + function setSpread(uint256 _newTestRange, uint256 _newAverageEligibilityCadence) external { + testRange = _newTestRange; + averageEligibilityCadence = _newAverageEligibilityCadence; + } + + function rand() private view returns (uint256) { + return uint256(keccak256(abi.encode(blockhash(block.number - 1), address(this)))); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol new file mode 100644 index 0000000..1d140cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AutomationCompatible} from "../AutomationCompatible.sol"; + +contract UpkeepReverter is AutomationCompatible { + function checkUpkeep( + bytes calldata data + ) public view override cannotExecute returns (bool callable, bytes calldata executedata) { + require(false, "!working"); + return (true, data); + } + + function performUpkeep(bytes calldata) external pure override { + require(false, "!working"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol new file mode 100644 index 0000000..b9eda1f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: MIT + +/** + The Cron contract is a chainlink keepers-powered cron job runner for smart contracts. + The contract enables developers to trigger actions on various targets using cron + strings to specify the cadence. For example, a user may have 3 tasks that require + regular service in their dapp ecosystem: + 1) 0xAB..CD, update(1), "0 0 * * *" --> runs update(1) on 0xAB..CD daily at midnight + 2) 0xAB..CD, update(2), "30 12 * * 0-4" --> runs update(2) on 0xAB..CD weekdays at 12:30 + 3) 0x12..34, trigger(), "0 * * * *" --> runs trigger() on 0x12..34 hourly + + To use this contract, a user first deploys this contract and registers it on the chainlink + keeper registry. Then the user adds cron jobs by following these steps: + 1) Convert a cron string to an encoded cron spec by calling encodeCronString() + 2) Take the encoding, target, and handler, and create a job by sending a tx to createCronJob() + 3) Cron job is running :) +*/ + +pragma solidity 0.8.6; + +import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; +import {Proxy} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {KeeperBase as KeeperBase} from "../KeeperBase.sol"; +import {KeeperCompatibleInterface as KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {Cron as CronInternal, Spec} from "../libraries/internal/Cron.sol"; +import {Cron as CronExternal} from "../libraries/external/Cron.sol"; + +/** + * @title The CronUpkeep contract + * @notice A keeper-compatible contract that runs various tasks on cron schedules. + * Users must use the encodeCronString() function to encode their cron jobs before + * setting them. This keeps all the string manipulation off chain and reduces gas costs. + */ +contract CronUpkeep is KeeperCompatibleInterface, KeeperBase, ConfirmedOwner, Pausable, Proxy { + using EnumerableSet for EnumerableSet.UintSet; + + event CronJobExecuted(uint256 indexed id, bool success); + event CronJobCreated(uint256 indexed id, address target, bytes handler); + event CronJobUpdated(uint256 indexed id, address target, bytes handler); + event CronJobDeleted(uint256 indexed id); + + error CronJobIDNotFound(uint256 id); + error ExceedsMaxJobs(); + error InvalidHandler(); + error TickInFuture(); + error TickTooOld(); + error TickDoesntMatchSpec(); + + address immutable s_delegate; + uint256 public immutable s_maxJobs; + uint256 private s_nextCronJobID = 1; + EnumerableSet.UintSet private s_activeCronJobIDs; + + mapping(uint256 => uint256) private s_lastRuns; + mapping(uint256 => Spec) private s_specs; + mapping(uint256 => address) private s_targets; + mapping(uint256 => bytes) private s_handlers; + mapping(uint256 => bytes32) private s_handlerSignatures; + + /** + * @param owner the initial owner of the contract + * @param delegate the contract to delegate checkUpkeep calls to + * @param maxJobs the max number of cron jobs this contract will support + * @param firstJob an optional encoding of the first cron job + */ + constructor(address owner, address delegate, uint256 maxJobs, bytes memory firstJob) ConfirmedOwner(owner) { + s_delegate = delegate; + s_maxJobs = maxJobs; + if (firstJob.length > 0) { + (address target, bytes memory handler, Spec memory spec) = abi.decode(firstJob, (address, bytes, Spec)); + createCronJobFromSpec(target, handler, spec); + } + } + + /** + * @notice Executes the cron job with id encoded in performData + * @param performData abi encoding of cron job ID and the cron job's next run-at datetime + */ + function performUpkeep(bytes calldata performData) external override whenNotPaused { + (uint256 id, uint256 tickTime, address target, bytes memory handler) = abi.decode( + performData, + (uint256, uint256, address, bytes) + ); + validate(id, tickTime, target, handler); + s_lastRuns[id] = block.timestamp; + (bool success, ) = target.call(handler); + emit CronJobExecuted(id, success); + } + + /** + * @notice Creates a cron job from the given encoded spec + * @param target the destination contract of a cron job + * @param handler the function signature on the target contract to call + * @param encodedCronSpec abi encoding of a cron spec + */ + function createCronJobFromEncodedSpec( + address target, + bytes memory handler, + bytes memory encodedCronSpec + ) external onlyOwner { + if (s_activeCronJobIDs.length() >= s_maxJobs) { + revert ExceedsMaxJobs(); + } + Spec memory spec = abi.decode(encodedCronSpec, (Spec)); + createCronJobFromSpec(target, handler, spec); + } + + /** + * @notice Updates a cron job from the given encoded spec + * @param id the id of the cron job to update + * @param newTarget the destination contract of a cron job + * @param newHandler the function signature on the target contract to call + * @param newEncodedCronSpec abi encoding of a cron spec + */ + function updateCronJob( + uint256 id, + address newTarget, + bytes memory newHandler, + bytes memory newEncodedCronSpec + ) external onlyOwner onlyValidCronID(id) { + Spec memory newSpec = abi.decode(newEncodedCronSpec, (Spec)); + s_targets[id] = newTarget; + s_handlers[id] = newHandler; + s_specs[id] = newSpec; + s_handlerSignatures[id] = handlerSig(newTarget, newHandler); + emit CronJobUpdated(id, newTarget, newHandler); + } + + /** + * @notice Deletes the cron job matching the provided id. Reverts if + * the id is not found. + * @param id the id of the cron job to delete + */ + function deleteCronJob(uint256 id) external onlyOwner onlyValidCronID(id) { + delete s_lastRuns[id]; + delete s_specs[id]; + delete s_targets[id]; + delete s_handlers[id]; + delete s_handlerSignatures[id]; + s_activeCronJobIDs.remove(id); + emit CronJobDeleted(id); + } + + /** + * @notice Pauses the contract, which prevents executing performUpkeep + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpauses the contract + */ + function unpause() external onlyOwner { + _unpause(); + } + + /** + * @notice Get the id of an eligible cron job + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding + * of the id and "next tick" of the elligible cron job + */ + function checkUpkeep(bytes calldata) external override whenNotPaused cannotExecute returns (bool, bytes memory) { + _delegate(s_delegate); + } + + /** + * @notice gets a list of active cron job IDs + * @return list of active cron job IDs + */ + function getActiveCronJobIDs() external view returns (uint256[] memory) { + uint256 length = s_activeCronJobIDs.length(); + uint256[] memory jobIDs = new uint256[](length); + for (uint256 idx = 0; idx < length; idx++) { + jobIDs[idx] = s_activeCronJobIDs.at(idx); + } + return jobIDs; + } + + /** + * @notice gets a cron job + * @param id the cron job ID + * @return target - the address a cron job forwards the eth tx to + handler - the encoded function sig to execute when forwarding a tx + cronString - the string representing the cron job + nextTick - the timestamp of the next time the cron job will run + */ + function getCronJob( + uint256 id + ) + external + view + onlyValidCronID(id) + returns (address target, bytes memory handler, string memory cronString, uint256 nextTick) + { + Spec memory spec = s_specs[id]; + return (s_targets[id], s_handlers[id], CronExternal.toCronString(spec), CronExternal.nextTick(spec)); + } + + /** + * @notice Adds a cron spec to storage and the ID to the list of jobs + * @param target the destination contract of a cron job + * @param handler the function signature on the target contract to call + * @param spec the cron spec to create + */ + function createCronJobFromSpec(address target, bytes memory handler, Spec memory spec) internal { + uint256 newID = s_nextCronJobID; + s_activeCronJobIDs.add(newID); + s_targets[newID] = target; + s_handlers[newID] = handler; + s_specs[newID] = spec; + s_lastRuns[newID] = block.timestamp; + s_handlerSignatures[newID] = handlerSig(target, handler); + s_nextCronJobID++; + emit CronJobCreated(newID, target, handler); + } + + function _implementation() internal view override returns (address) { + return s_delegate; + } + + /** + * @notice validates the input to performUpkeep + * @param id the id of the cron job + * @param tickTime the observed tick time + * @param target the contract to forward the tx to + * @param handler the handler of the contract receiving the forwarded tx + */ + function validate(uint256 id, uint256 tickTime, address target, bytes memory handler) private { + tickTime = tickTime - (tickTime % 60); // remove seconds from tick time + if (block.timestamp < tickTime) { + revert TickInFuture(); + } + if (tickTime <= s_lastRuns[id]) { + revert TickTooOld(); + } + if (!CronInternal.matches(s_specs[id], tickTime)) { + revert TickDoesntMatchSpec(); + } + if (handlerSig(target, handler) != s_handlerSignatures[id]) { + revert InvalidHandler(); + } + } + + /** + * @notice returns a unique identifier for target/handler pairs + * @param target the contract to forward the tx to + * @param handler the handler of the contract receiving the forwarded tx + * @return a hash of the inputs + */ + function handlerSig(address target, bytes memory handler) private pure returns (bytes32) { + return keccak256(abi.encodePacked(target, handler)); + } + + modifier onlyValidCronID(uint256 id) { + if (!s_activeCronJobIDs.contains(id)) { + revert CronJobIDNotFound(id); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol new file mode 100644 index 0000000..ed8d031 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Cron, Spec} from "../libraries/internal/Cron.sol"; + +/** + * @title The CronUpkeepDelegate contract + * @notice This contract serves as a delegate for all instances of CronUpkeep. Those contracts + * delegate their checkUpkeep calls onto this contract. Utilizing this pattern reduces the size + * of the CronUpkeep contracts. + */ +contract CronUpkeepDelegate { + using EnumerableSet for EnumerableSet.UintSet; + using Cron for Spec; + + address private s_owner; // from ConfirmedOwner + address private s_delegate; + uint256 private s_nextCronJobID; + EnumerableSet.UintSet private s_activeCronJobIDs; + mapping(uint256 => uint256) private s_lastRuns; + mapping(uint256 => Spec) private s_specs; + mapping(uint256 => address) private s_targets; + mapping(uint256 => bytes) private s_handlers; + + /** + * @notice Get the id of an eligible cron job + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding + * of the id and "next tick" of the eligible cron job + */ + function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { + // DEV: start at a random spot in the list so that checks are + // spread evenly among cron jobs + uint256 numCrons = s_activeCronJobIDs.length(); + if (numCrons == 0) { + return (false, bytes("")); + } + uint256 startIdx = block.number % numCrons; + bool result; + bytes memory payload; + (result, payload) = checkInRange(startIdx, numCrons); + if (result) { + return (result, payload); + } + (result, payload) = checkInRange(0, startIdx); + if (result) { + return (result, payload); + } + return (false, bytes("")); + } + + /** + * @notice checks the cron jobs in a given range + * @param start the starting id to check (inclusive) + * @param end the ending id to check (exclusive) + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding + * of the id and "next tick" of the eligible cron job + */ + function checkInRange(uint256 start, uint256 end) private view returns (bool, bytes memory) { + uint256 id; + uint256 lastTick; + for (uint256 idx = start; idx < end; idx++) { + id = s_activeCronJobIDs.at(idx); + lastTick = s_specs[id].lastTick(); + if (lastTick > s_lastRuns[id]) { + return (true, abi.encode(id, lastTick, s_targets[id], s_handlers[id])); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol new file mode 100644 index 0000000..2b6e97e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {CronUpkeep} from "./CronUpkeep.sol"; +import {CronUpkeepDelegate} from "./CronUpkeepDelegate.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {Spec, Cron as CronExternal} from "../libraries/external/Cron.sol"; + +/** + * @title The CronUpkeepFactory contract + * @notice This contract serves as a delegate for all instances of CronUpkeep. Those contracts + * delegate their checkUpkeep calls onto this contract. Utilizing this pattern reduces the size + * of the CronUpkeep contracts. + */ +contract CronUpkeepFactory is ConfirmedOwner { + event NewCronUpkeepCreated(address upkeep, address owner); + + address private immutable s_cronDelegate; + uint256 public s_maxJobs = 5; + + constructor() ConfirmedOwner(msg.sender) { + s_cronDelegate = address(new CronUpkeepDelegate()); + } + + /** + * @notice Creates a new CronUpkeep contract, with msg.sender as the owner + */ + function newCronUpkeep() external { + newCronUpkeepWithJob(bytes("")); + } + + /** + * @notice Creates a new CronUpkeep contract, with msg.sender as the owner, and registers a cron job + */ + function newCronUpkeepWithJob(bytes memory encodedJob) public { + emit NewCronUpkeepCreated(address(new CronUpkeep(msg.sender, s_cronDelegate, s_maxJobs, encodedJob)), msg.sender); + } + + /** + * @notice Sets the max job limit on new cron upkeeps + */ + function setMaxJobs(uint256 maxJobs) external onlyOwner { + s_maxJobs = maxJobs; + } + + /** + * @notice Gets the address of the delegate contract + * @return the address of the delegate contract + */ + function cronDelegateAddress() external view returns (address) { + return s_cronDelegate; + } + + /** + * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. + * This should only be called off-chain, as it is gas expensive! + * @param cronString the cron string to convert and encode + * @return the abi encoding of the Spec struct representing the cron string + */ + function encodeCronString(string memory cronString) external pure returns (bytes memory) { + return CronExternal.toEncodedSpec(cronString); + } + + /** + * @notice Converts, validates, and encodes a full cron spec. This payload is then passed to newCronUpkeepWithJob. + * @param target the destination contract of a cron job + * @param handler the function signature on the target contract to call + * @param cronString the cron string to convert and encode + * @return the abi encoding of the entire cron job + */ + function encodeCronJob( + address target, + bytes memory handler, + string memory cronString + ) external pure returns (bytes memory) { + Spec memory spec = CronExternal.toSpec(cronString); + return abi.encode(target, handler, spec); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol new file mode 100644 index 0000000..d2a7adc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.4; + +import "../../shared/access/ConfirmedOwner.sol"; +import "../interfaces/KeeperCompatibleInterface.sol"; +import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; +import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title The ERC20BalanceMonitor contract. + * @notice A keeper-compatible contract that monitors and funds ERC20 tokens. + */ +contract ERC20BalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { + uint16 private constant MAX_WATCHLIST_SIZE = 300; + uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; + + event FundsWithdrawn(uint256 amountWithdrawn, address payee); + event TopUpSucceeded(address indexed topUpAddress); + event WatchlistUpdated(address[] oldWatchlist, address[] newWatchlist); + event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); + event ERC20TokenAddressUpdated(address oldAddress, address newAddress); + event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); + + error InvalidWatchList(); + error OnlyKeeperRegistry(); + error DuplicateAddress(address duplicate); + + struct Target { + bool isActive; + uint96 minBalance; + uint96 topUpLevel; + uint56 lastTopUpTimestamp; + } + + IERC20 private s_erc20Token; + address private s_keeperRegistryAddress; + uint256 private s_minWaitPeriodSeconds; + address[] private s_watchList; + mapping(address => Target) internal s_targets; + + /** + * @param erc20TokenAddress the ERC20 token address + * @param keeperRegistryAddress the address of the keeper registry contract + * @param minWaitPeriodSeconds the minimum wait period for addresses between funding + */ + constructor( + address erc20TokenAddress, + address keeperRegistryAddress, + uint256 minWaitPeriodSeconds + ) ConfirmedOwner(msg.sender) { + setERC20TokenAddress(erc20TokenAddress); + setKeeperRegistryAddress(keeperRegistryAddress); + setMinWaitPeriodSeconds(minWaitPeriodSeconds); + } + + /** + * @notice Sets the list of subscriptions to watch and their funding parameters. + * @param addresses the list of subscription ids to watch + * @param minBalances the minimum balances for each subscription + * @param topUpLevels the amount to top up to for each subscription + */ + function setWatchList( + address[] calldata addresses, + uint96[] calldata minBalances, + uint96[] calldata topUpLevels + ) external onlyOwner { + if ( + addresses.length != minBalances.length || + addresses.length != topUpLevels.length || + addresses.length > MAX_WATCHLIST_SIZE + ) { + revert InvalidWatchList(); + } + address[] memory oldWatchList = s_watchList; + for (uint256 idx = 0; idx < oldWatchList.length; idx++) { + s_targets[oldWatchList[idx]].isActive = false; + } + for (uint256 idx = 0; idx < addresses.length; idx++) { + if (s_targets[addresses[idx]].isActive) { + revert DuplicateAddress(addresses[idx]); + } + if (addresses[idx] == address(0)) { + revert InvalidWatchList(); + } + if (topUpLevels[idx] <= minBalances[idx]) { + revert InvalidWatchList(); + } + s_targets[addresses[idx]] = Target({ + isActive: true, + minBalance: minBalances[idx], + topUpLevel: topUpLevels[idx], + lastTopUpTimestamp: 0 + }); + } + s_watchList = addresses; + emit WatchlistUpdated(oldWatchList, addresses); + } + + /** + * @notice Gets a list of subscriptions that are underfunded. + * @return list of subscriptions that are underfunded + */ + function getUnderfundedAddresses() public view returns (address[] memory) { + address[] memory watchList = s_watchList; + address[] memory needsFunding = new address[](watchList.length); + uint256 count = 0; + uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; + uint256 contractBalance = s_erc20Token.balanceOf(address(this)); + Target memory target; + for (uint256 idx = 0; idx < watchList.length; idx++) { + target = s_targets[watchList[idx]]; + uint256 targetTokenBalance = s_erc20Token.balanceOf(watchList[idx]); + if ( + target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && + targetTokenBalance < target.minBalance && + contractBalance >= (target.topUpLevel - targetTokenBalance) + ) { + uint256 topUpAmount = target.topUpLevel - targetTokenBalance; + needsFunding[count] = watchList[idx]; + count++; + contractBalance -= topUpAmount; + } + } + if (count != watchList.length) { + assembly { + mstore(needsFunding, count) // resize array to number of valid targets + } + } + return needsFunding; + } + + /** + * @notice Send funds to the subscriptions provided. + * @param needsFunding the list of subscriptions to fund + */ + function topUp(address[] memory needsFunding) public whenNotPaused { + uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; + Target memory target; + uint256 contractBalance = s_erc20Token.balanceOf(address(this)); + for (uint256 idx = 0; idx < needsFunding.length; idx++) { + target = s_targets[needsFunding[idx]]; + uint256 targetTokenBalance = s_erc20Token.balanceOf(needsFunding[idx]); + if ( + target.isActive && + target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && + targetTokenBalance < target.minBalance && + contractBalance >= (target.topUpLevel - targetTokenBalance) + ) { + uint256 topUpAmount = target.topUpLevel - targetTokenBalance; + s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); + contractBalance -= topUpAmount; + SafeERC20.safeTransfer(s_erc20Token, needsFunding[idx], topUpAmount); + emit TopUpSucceeded(needsFunding[idx]); + } + if (gasleft() < MIN_GAS_FOR_TRANSFER) { + return; + } + } + } + + /** + * @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds + */ + function checkUpkeep( + bytes calldata + ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { + address[] memory needsFunding = getUnderfundedAddresses(); + upkeepNeeded = needsFunding.length > 0; + performData = abi.encode(needsFunding); + return (upkeepNeeded, performData); + } + + /** + * @notice Called by the keeper to send funds to underfunded addresses. + * @param performData the abi encoded list of addresses to fund + */ + function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { + address[] memory needsFunding = abi.decode(performData, (address[])); + topUp(needsFunding); + } + + /** + * @notice Withdraws the contract balance in the ERC20 token. + * @param amount the amount of the ERC20 to withdraw + * @param payee the address to pay + */ + function withdraw(uint256 amount, address payable payee) external onlyOwner { + require(payee != address(0)); + SafeERC20.safeTransfer(s_erc20Token, payee, amount); + emit FundsWithdrawn(amount, payee); + } + + /** + * @notice Sets the ERC20 token address. + */ + function setERC20TokenAddress(address erc20TokenAddress) public onlyOwner { + require(erc20TokenAddress != address(0)); + emit ERC20TokenAddressUpdated(address(s_erc20Token), erc20TokenAddress); + s_erc20Token = IERC20(erc20TokenAddress); + } + + /** + * @notice Sets the keeper registry address. + */ + function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { + require(keeperRegistryAddress != address(0)); + emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); + s_keeperRegistryAddress = keeperRegistryAddress; + } + + /** + * @notice Sets the minimum wait period (in seconds) for subscription ids between funding. + */ + function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { + emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); + s_minWaitPeriodSeconds = period; + } + + /** + * @notice Gets the ERC20 token address. + */ + function getERC20TokenAddress() external view returns (address) { + return address(s_erc20Token); + } + + /** + * @notice Gets the keeper registry address. + */ + function getKeeperRegistryAddress() external view returns (address) { + return s_keeperRegistryAddress; + } + + /** + * @notice Gets the minimum wait period. + */ + function getMinWaitPeriodSeconds() external view returns (uint256) { + return s_minWaitPeriodSeconds; + } + + /** + * @notice Gets the list of subscription ids being watched. + */ + function getWatchList() external view returns (address[] memory) { + return s_watchList; + } + + /** + * @notice Gets configuration information for an address on the watchlist + */ + function getAccountInfo( + address targetAddress + ) external view returns (bool isActive, uint96 minBalance, uint96 topUpLevel, uint56 lastTopUpTimestamp) { + Target memory target = s_targets[targetAddress]; + return (target.isActive, target.minBalance, target.topUpLevel, target.lastTopUpTimestamp); + } + + /** + * @notice Pause the contract, which prevents executing performUpkeep. + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpause the contract. + */ + function unpause() external onlyOwner { + _unpause(); + } + + modifier onlyKeeperRegistry() { + if (msg.sender != s_keeperRegistryAddress) { + revert OnlyKeeperRegistry(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol new file mode 100644 index 0000000..c7d8a30 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import "../../shared/access/ConfirmedOwner.sol"; +import "../interfaces/KeeperCompatibleInterface.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; + +/** + * @title The EthBalanceMonitor contract + * @notice A keeper-compatible contract that monitors and funds eth addresses + */ +contract EthBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { + // observed limit of 45K + 10k buffer + uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; + + event FundsAdded(uint256 amountAdded, uint256 newBalance, address sender); + event FundsWithdrawn(uint256 amountWithdrawn, address payee); + event TopUpSucceeded(address indexed recipient); + event TopUpFailed(address indexed recipient); + event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); + event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); + + error InvalidWatchList(); + error OnlyKeeperRegistry(); + error DuplicateAddress(address duplicate); + + struct Target { + bool isActive; + uint96 minBalanceWei; + uint96 topUpAmountWei; + uint56 lastTopUpTimestamp; // enough space for 2 trillion years + } + + address private s_keeperRegistryAddress; + uint256 private s_minWaitPeriodSeconds; + address[] private s_watchList; + mapping(address => Target) internal s_targets; + + /** + * @param keeperRegistryAddress The address of the keeper registry contract + * @param minWaitPeriodSeconds The minimum wait period for addresses between funding + */ + constructor(address keeperRegistryAddress, uint256 minWaitPeriodSeconds) ConfirmedOwner(msg.sender) { + setKeeperRegistryAddress(keeperRegistryAddress); + setMinWaitPeriodSeconds(minWaitPeriodSeconds); + } + + /** + * @notice Sets the list of addresses to watch and their funding parameters + * @param addresses the list of addresses to watch + * @param minBalancesWei the minimum balances for each address + * @param topUpAmountsWei the amount to top up each address + */ + function setWatchList( + address[] calldata addresses, + uint96[] calldata minBalancesWei, + uint96[] calldata topUpAmountsWei + ) external onlyOwner { + if (addresses.length != minBalancesWei.length || addresses.length != topUpAmountsWei.length) { + revert InvalidWatchList(); + } + address[] memory oldWatchList = s_watchList; + for (uint256 idx = 0; idx < oldWatchList.length; idx++) { + s_targets[oldWatchList[idx]].isActive = false; + } + for (uint256 idx = 0; idx < addresses.length; idx++) { + if (s_targets[addresses[idx]].isActive) { + revert DuplicateAddress(addresses[idx]); + } + if (addresses[idx] == address(0)) { + revert InvalidWatchList(); + } + if (topUpAmountsWei[idx] == 0) { + revert InvalidWatchList(); + } + s_targets[addresses[idx]] = Target({ + isActive: true, + minBalanceWei: minBalancesWei[idx], + topUpAmountWei: topUpAmountsWei[idx], + lastTopUpTimestamp: 0 + }); + } + s_watchList = addresses; + } + + /** + * @notice Gets a list of addresses that are under funded + * @return list of addresses that are underfunded + */ + function getUnderfundedAddresses() public view returns (address[] memory) { + address[] memory watchList = s_watchList; + address[] memory needsFunding = new address[](watchList.length); + uint256 count = 0; + uint256 minWaitPeriod = s_minWaitPeriodSeconds; + uint256 balance = address(this).balance; + Target memory target; + for (uint256 idx = 0; idx < watchList.length; idx++) { + target = s_targets[watchList[idx]]; + if ( + target.lastTopUpTimestamp + minWaitPeriod <= block.timestamp && + balance >= target.topUpAmountWei && + watchList[idx].balance < target.minBalanceWei + ) { + needsFunding[count] = watchList[idx]; + count++; + balance -= target.topUpAmountWei; + } + } + if (count != watchList.length) { + assembly { + mstore(needsFunding, count) + } + } + return needsFunding; + } + + /** + * @notice Send funds to the addresses provided + * @param needsFunding the list of addresses to fund (addresses must be pre-approved) + */ + function topUp(address[] memory needsFunding) public whenNotPaused { + uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; + Target memory target; + for (uint256 idx = 0; idx < needsFunding.length; idx++) { + target = s_targets[needsFunding[idx]]; + if ( + target.isActive && + target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && + needsFunding[idx].balance < target.minBalanceWei + ) { + bool success = payable(needsFunding[idx]).send(target.topUpAmountWei); + if (success) { + s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); + emit TopUpSucceeded(needsFunding[idx]); + } else { + emit TopUpFailed(needsFunding[idx]); + } + } + if (gasleft() < MIN_GAS_FOR_TRANSFER) { + return; + } + } + } + + /** + * @notice Get list of addresses that are underfunded and return keeper-compatible payload + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of addresses that need funds + */ + function checkUpkeep( + bytes calldata + ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { + address[] memory needsFunding = getUnderfundedAddresses(); + upkeepNeeded = needsFunding.length > 0; + performData = abi.encode(needsFunding); + return (upkeepNeeded, performData); + } + + /** + * @notice Called by keeper to send funds to underfunded addresses + * @param performData The abi encoded list of addresses to fund + */ + function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { + address[] memory needsFunding = abi.decode(performData, (address[])); + topUp(needsFunding); + } + + /** + * @notice Withdraws the contract balance + * @param amount The amount of eth (in wei) to withdraw + * @param payee The address to pay + */ + function withdraw(uint256 amount, address payable payee) external onlyOwner { + require(payee != address(0)); + emit FundsWithdrawn(amount, payee); + payee.transfer(amount); + } + + /** + * @notice Receive funds + */ + receive() external payable { + emit FundsAdded(msg.value, address(this).balance, msg.sender); + } + + /** + * @notice Sets the keeper registry address + */ + function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { + require(keeperRegistryAddress != address(0)); + emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); + s_keeperRegistryAddress = keeperRegistryAddress; + } + + /** + * @notice Sets the minimum wait period (in seconds) for addresses between funding + */ + function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { + emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); + s_minWaitPeriodSeconds = period; + } + + /** + * @notice Gets the keeper registry address + */ + function getKeeperRegistryAddress() external view returns (address keeperRegistryAddress) { + return s_keeperRegistryAddress; + } + + /** + * @notice Gets the minimum wait period + */ + function getMinWaitPeriodSeconds() external view returns (uint256) { + return s_minWaitPeriodSeconds; + } + + /** + * @notice Gets the list of addresses being watched + */ + function getWatchList() external view returns (address[] memory) { + return s_watchList; + } + + /** + * @notice Gets configuration information for an address on the watchlist + */ + function getAccountInfo( + address targetAddress + ) external view returns (bool isActive, uint96 minBalanceWei, uint96 topUpAmountWei, uint56 lastTopUpTimestamp) { + Target memory target = s_targets[targetAddress]; + return (target.isActive, target.minBalanceWei, target.topUpAmountWei, target.lastTopUpTimestamp); + } + + /** + * @notice Pauses the contract, which prevents executing performUpkeep + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpauses the contract + */ + function unpause() external onlyOwner { + _unpause(); + } + + modifier onlyKeeperRegistry() { + if (msg.sender != s_keeperRegistryAddress) { + revert OnlyKeeperRegistry(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol new file mode 100644 index 0000000..9bf68fc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol @@ -0,0 +1,480 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; +import {AccessControl} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol"; +import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; + +interface IAggregatorProxy { + function aggregator() external view returns (address); +} + +interface ILinkAvailable { + function linkAvailableForPayment() external view returns (int256 availableBalance); +} + +/// @title The LinkAvailableBalanceMonitor contract. +/// @notice A keeper-compatible contract that monitors target contracts for balance from a custom +/// function linkAvailableForPayment() and funds them with LINK if it falls below a defined +/// threshold. Also supports aggregator proxy contracts monitoring which require fetching the actual +/// target contract through a predefined interface. +/// @dev with 30 addresses as the s_maxPerform, the measured max gas usage of performUpkeep is around 2M +/// therefore, we recommend an upkeep gas limit of 3M (this has a 33% margin of safety). Although, nothing +/// prevents us from using 5M gas and increasing s_maxPerform, 30 seems like a reasonable batch size that +/// is probably plenty for most needs. +/// @dev with 130 addresses as the s_maxCheck, the measured max gas usage of checkUpkeep is around 3.5M, +/// which is 30% below the 5M limit. +/// Note that testing conditions DO NOT match live chain gas usage, hence the margins. Change +/// at your own risk!!! +/// @dev some areas for improvement / acknowledgement of limitations: +/// validate that all addresses conform to interface when adding them to the watchlist +/// this is a "trustless" upkeep, meaning it does not trust the caller of performUpkeep; +/// we could save a fair amount of gas and re-write this upkeep for use with Automation v2.0+, +/// which has significantly different trust assumptions +contract LinkAvailableBalanceMonitor is AccessControl, AutomationCompatibleInterface, Pausable { + using EnumerableMap for EnumerableMap.UintToAddressMap; + using EnumerableSet for EnumerableSet.AddressSet; + + event BalanceUpdated(address indexed addr, uint256 oldBalance, uint256 newBalance); + event FundsWithdrawn(uint256 amountWithdrawn, address payee); + event UpkeepIntervalSet(uint256 oldUpkeepInterval, uint256 newUpkeepInterval); + event MaxCheckSet(uint256 oldMaxCheck, uint256 newMaxCheck); + event MaxPerformSet(uint256 oldMaxPerform, uint256 newMaxPerform); + event MinWaitPeriodSet(uint256 s_minWaitPeriodSeconds, uint256 minWaitPeriodSeconds); + event TopUpBlocked(address indexed topUpAddress); + event TopUpFailed(address indexed recipient); + event TopUpSucceeded(address indexed topUpAddress, uint256 amount); + event TopUpUpdated(address indexed addr, uint256 oldTopUpAmount, uint256 newTopUpAmount); + event WatchlistUpdated(); + + error InvalidAddress(address target); + error InvalidMaxCheck(uint16 maxCheck); + error InvalixMaxPerform(uint16 maxPerform); + error InvalidMinBalance(uint96 minBalance); + error InvalidTopUpAmount(uint96 topUpAmount); + error InvalidUpkeepInterval(uint8 upkeepInterval); + error InvalidLinkTokenAddress(address lt); + error InvalidWatchList(); + error InvalidChainSelector(); + error DuplicateAddress(address duplicate); + error ReentrantCall(); + + struct MonitoredAddress { + uint96 minBalance; + uint96 topUpAmount; + uint56 lastTopUpTimestamp; + bool isActive; + } + + bytes32 private constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); + bytes32 private constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + uint96 private constant DEFAULT_TOP_UP_AMOUNT_JUELS = 3000000000000000000; + uint96 private constant DEFAULT_MIN_BALANCE_JUELS = 1000000000000000000; + IERC20 private immutable i_linkToken; + + uint256 private s_minWaitPeriodSeconds; + uint16 private s_maxPerform; + uint16 private s_maxCheck; + uint8 private s_upkeepInterval; + + /// @notice s_watchList contains all the addresses watched by this monitor + /// @dev It mainly provides the length() function + EnumerableSet.AddressSet private s_watchList; + + /// @notice s_targets contains all the addresses watched by this monitor + /// Each key points to a MonitoredAddress with all the needed metadata + mapping(address targetAddress => MonitoredAddress targetProperties) private s_targets; + + /// @notice s_onRampAddresses represents a list of CCIP onRamp addresses watched on this contract + /// There has to be only one onRamp per dstChainSelector. + /// dstChainSelector is needed as we have to track the live onRamp, and delete the onRamp + /// whenever a new one is deployed with the same dstChainSelector. + EnumerableMap.UintToAddressMap private s_onRampAddresses; + + bool private reentrancyGuard; + + /// @param admin is the administrator address of this contract + /// @param linkToken the LINK token address + /// @param minWaitPeriodSeconds represents the amount of time that has to wait a contract to be funded + /// @param maxPerform maximum amount of contracts to fund + /// @param maxCheck maximum amount of contracts to check + /// @param upkeepInterval randomizes the check for underfunded contracts + constructor( + address admin, + IERC20 linkToken, + uint256 minWaitPeriodSeconds, + uint16 maxPerform, + uint16 maxCheck, + uint8 upkeepInterval + ) { + _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); + _setRoleAdmin(EXECUTOR_ROLE, ADMIN_ROLE); + _grantRole(ADMIN_ROLE, admin); + i_linkToken = linkToken; + setMinWaitPeriodSeconds(minWaitPeriodSeconds); + setMaxPerform(maxPerform); + setMaxCheck(maxCheck); + setUpkeepInterval(upkeepInterval); + reentrancyGuard = false; + } + + /// @notice Sets the list of subscriptions to watch and their funding parameters + /// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy) + /// @param minBalances the list of corresponding minBalance for the target address + /// @param topUpAmounts the list of corresponding minTopUp for the target address + function setWatchList( + address[] calldata addresses, + uint96[] calldata minBalances, + uint96[] calldata topUpAmounts, + uint64[] calldata dstChainSelectors + ) external onlyAdminOrExecutor { + if ( + addresses.length != minBalances.length || + addresses.length != topUpAmounts.length || + addresses.length != dstChainSelectors.length + ) { + revert InvalidWatchList(); + } + for (uint256 idx = s_watchList.length(); idx > 0; idx--) { + address member = s_watchList.at(idx - 1); + s_watchList.remove(member); + delete s_targets[member]; + } + // s_onRampAddresses is not the same length as s_watchList, so it has + // to be clean in a separate loop + for (uint256 idx = s_onRampAddresses.length(); idx > 0; idx--) { + (uint256 key, ) = s_onRampAddresses.at(idx - 1); + s_onRampAddresses.remove(key); + } + for (uint256 idx = 0; idx < addresses.length; idx++) { + address targetAddress = addresses[idx]; + if (s_targets[targetAddress].isActive) revert DuplicateAddress(targetAddress); + if (targetAddress == address(0)) revert InvalidWatchList(); + if (minBalances[idx] == 0) revert InvalidWatchList(); + if (topUpAmounts[idx] == 0) revert InvalidWatchList(); + s_targets[targetAddress] = MonitoredAddress({ + isActive: true, + minBalance: minBalances[idx], + topUpAmount: topUpAmounts[idx], + lastTopUpTimestamp: 0 + }); + if (dstChainSelectors[idx] > 0) { + s_onRampAddresses.set(dstChainSelectors[idx], targetAddress); + } + s_watchList.add(targetAddress); + } + emit WatchlistUpdated(); + } + + /// @notice Adds a new address to the watchlist + /// @param targetAddress the address to be added to the watchlist + /// @param dstChainSelector carries a non-zero value in case the targetAddress is an onRamp, otherwise it carries a 0 + /// @dev this function has to be compatible with the event onRampSet(address, dstChainSelector) emitted by + /// the CCIP router. Important detail to know is this event is also emitted when an onRamp is decommissioned, + /// in which case it will carry the proper dstChainSelector along with the 0x0 address + function addToWatchListOrDecommission(address targetAddress, uint64 dstChainSelector) public onlyAdminOrExecutor { + if (s_targets[targetAddress].isActive) revert DuplicateAddress(targetAddress); + if (targetAddress == address(0) && dstChainSelector == 0) revert InvalidAddress(targetAddress); + bool onRampExists = s_onRampAddresses.contains(dstChainSelector); + // if targetAddress is an existing onRamp, there's a need of cleaning the previous onRamp associated to this dstChainSelector + // there's no need to remove any other address that's not an onRamp + if (dstChainSelector > 0 && onRampExists) { + address oldAddress = s_onRampAddresses.get(dstChainSelector); + removeFromWatchList(oldAddress); + } + // only add the new address if it's not 0x0 + if (targetAddress != address(0)) { + s_targets[targetAddress] = MonitoredAddress({ + isActive: true, + minBalance: DEFAULT_MIN_BALANCE_JUELS, + topUpAmount: DEFAULT_TOP_UP_AMOUNT_JUELS, + lastTopUpTimestamp: 0 + }); + s_watchList.add(targetAddress); + // add the contract to onRampAddresses if it carries a valid dstChainSelector + if (dstChainSelector > 0) { + s_onRampAddresses.set(dstChainSelector, targetAddress); + } + // else if is redundant as this is the only corner case left, maintaining it for legibility + } else if (targetAddress == address(0) && dstChainSelector > 0) { + s_onRampAddresses.remove(dstChainSelector); + } + } + + /// @notice Delete an address from the watchlist and sets the target to inactive + /// @param targetAddress the address to be deleted + function removeFromWatchList(address targetAddress) public onlyAdminOrExecutor returns (bool) { + if (s_watchList.remove(targetAddress)) { + delete s_targets[targetAddress]; + return true; + } + return false; + } + + /// @notice Gets a list of proxies that are underfunded, up to the s_maxPerform size + /// @dev the function starts at a random index in the list to avoid biasing the first + /// addresses in the list over latter ones. + /// @dev the function will check at most s_maxCheck proxies in a single call + /// @dev the function returns a list with a max length of s_maxPerform + /// @return list of target addresses which are underfunded + function sampleUnderfundedAddresses() public view returns (address[] memory) { + uint16 maxPerform = s_maxPerform; + uint16 maxCheck = s_maxCheck; + uint256 numTargets = s_watchList.length(); + uint256 idx = uint256(blockhash(block.number - (block.number % s_upkeepInterval) - 1)) % numTargets; + uint256 numToCheck = numTargets < maxCheck ? numTargets : maxCheck; + uint256 numFound = 0; + uint256 minWaitPeriod = s_minWaitPeriodSeconds; + address[] memory targetsToFund = new address[](maxPerform); + MonitoredAddress memory contractToFund; + address targetAddress; + for ( + uint256 numChecked = 0; + numChecked < numToCheck; + (idx, numChecked) = ((idx + 1) % numTargets, numChecked + 1) + ) { + targetAddress = s_watchList.at(idx); + contractToFund = s_targets[targetAddress]; + (bool fundingNeeded, ) = _needsFunding( + targetAddress, + contractToFund.lastTopUpTimestamp + minWaitPeriod, + contractToFund.minBalance, + contractToFund.isActive + ); + if (fundingNeeded) { + targetsToFund[numFound] = targetAddress; + numFound++; + if (numFound == maxPerform) { + break; // max number of addresses in batch reached + } + } + } + if (numFound != maxPerform) { + assembly { + mstore(targetsToFund, numFound) // resize array to number of valid targets + } + } + return targetsToFund; + } + + /// @notice tries to fund an array of target addresses, checking if they're underfunded in the process + /// @param targetAddresses is an array of contract addresses to be funded in case they're underfunded + function topUp(address[] memory targetAddresses) public whenNotPaused nonReentrant { + MonitoredAddress memory contractToFund; + uint256 minWaitPeriod = s_minWaitPeriodSeconds; + uint256 localBalance = i_linkToken.balanceOf(address(this)); + for (uint256 idx = 0; idx < targetAddresses.length; idx++) { + address targetAddress = targetAddresses[idx]; + contractToFund = s_targets[targetAddress]; + + (bool fundingNeeded, address target) = _needsFunding( + targetAddress, + contractToFund.lastTopUpTimestamp + minWaitPeriod, + contractToFund.minBalance, + contractToFund.isActive + ); + if (localBalance >= contractToFund.topUpAmount && fundingNeeded) { + bool success = i_linkToken.transfer(target, contractToFund.topUpAmount); + if (success) { + localBalance -= contractToFund.topUpAmount; + s_targets[targetAddress].lastTopUpTimestamp = uint56(block.timestamp); + emit TopUpSucceeded(target, contractToFund.topUpAmount); + } else { + emit TopUpFailed(targetAddress); + } + } else { + emit TopUpBlocked(targetAddress); + } + } + } + + /// @notice checks the target (could be direct target or IAggregatorProxy), and determines + /// if it is eligible for funding + /// @param targetAddress the target to check + /// @param minBalance minimum balance required for the target + /// @param minWaitPeriodPassed the minimum wait period (target lastTopUpTimestamp + minWaitPeriod) + /// @return bool whether the target needs funding or not + /// @return address the address to fund. for DF, this is the aggregator address behind the proxy address. + /// for other products, it's the original target address + function _needsFunding( + address targetAddress, + uint256 minWaitPeriodPassed, + uint256 minBalance, + bool contractIsActive + ) private view returns (bool, address) { + // Explicitly check if the targetAddress is the zero address + // or if it's not a contract. In both cases return with false, + // to prevent target.linkAvailableForPayment from running, + // which would revert the operation. + if (targetAddress == address(0) || targetAddress.code.length == 0) { + return (false, address(0)); + } + ILinkAvailable target; + IAggregatorProxy proxy = IAggregatorProxy(targetAddress); + try proxy.aggregator() returns (address aggregatorAddress) { + // proxy.aggregator() can return a 0 address if the address is not an aggregator + if (aggregatorAddress == address(0)) return (false, address(0)); + target = ILinkAvailable(aggregatorAddress); + } catch { + target = ILinkAvailable(targetAddress); + } + try target.linkAvailableForPayment() returns (int256 balance) { + if (balance < int256(minBalance) && minWaitPeriodPassed <= block.timestamp && contractIsActive) { + return (true, address(target)); + } + } catch {} + return (false, address(0)); + } + + /// @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. + /// @return upkeepNeeded signals if upkeep is needed + /// @return performData is an abi encoded list of subscription ids that need funds + function checkUpkeep( + bytes calldata + ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { + address[] memory needsFunding = sampleUnderfundedAddresses(); + if (needsFunding.length == 0) { + return (false, ""); + } + uint96 total_batch_balance; + for (uint256 idx = 0; idx < needsFunding.length; idx++) { + address targetAddress = needsFunding[idx]; + total_batch_balance = total_batch_balance + s_targets[targetAddress].topUpAmount; + } + if (i_linkToken.balanceOf(address(this)) >= total_batch_balance) { + return (true, abi.encode(needsFunding)); + } + return (false, ""); + } + + /// @notice Called by the keeper to send funds to underfunded addresses. + /// @param performData the abi encoded list of addresses to fund + function performUpkeep(bytes calldata performData) external override { + address[] memory needsFunding = abi.decode(performData, (address[])); + topUp(needsFunding); + } + + /// @notice Withdraws the contract balance in the LINK token. + /// @param amount the amount of the LINK to withdraw + /// @param payee the address to pay + function withdraw(uint256 amount, address payable payee) external onlyAdminOrExecutor { + if (payee == address(0)) revert InvalidAddress(payee); + i_linkToken.transfer(payee, amount); + emit FundsWithdrawn(amount, payee); + } + + /// @notice Sets the minimum balance for the given target address + function setMinBalance(address target, uint96 minBalance) external onlyRole(ADMIN_ROLE) { + if (target == address(0)) revert InvalidAddress(target); + if (minBalance == 0) revert InvalidMinBalance(minBalance); + if (!s_targets[target].isActive) revert InvalidWatchList(); + uint256 oldBalance = s_targets[target].minBalance; + s_targets[target].minBalance = minBalance; + emit BalanceUpdated(target, oldBalance, minBalance); + } + + /// @notice Sets the minimum balance for the given target address + function setTopUpAmount(address target, uint96 topUpAmount) external onlyRole(ADMIN_ROLE) { + if (target == address(0)) revert InvalidAddress(target); + if (topUpAmount == 0) revert InvalidTopUpAmount(topUpAmount); + if (!s_targets[target].isActive) revert InvalidWatchList(); + uint256 oldTopUpAmount = s_targets[target].topUpAmount; + s_targets[target].topUpAmount = topUpAmount; + emit BalanceUpdated(target, oldTopUpAmount, topUpAmount); + } + + /// @notice Update s_maxPerform + function setMaxPerform(uint16 maxPerform) public onlyRole(ADMIN_ROLE) { + emit MaxPerformSet(s_maxPerform, maxPerform); + s_maxPerform = maxPerform; + } + + /// @notice Update s_maxCheck + function setMaxCheck(uint16 maxCheck) public onlyRole(ADMIN_ROLE) { + emit MaxCheckSet(s_maxCheck, maxCheck); + s_maxCheck = maxCheck; + } + + /// @notice Sets the minimum wait period (in seconds) for addresses between funding + function setMinWaitPeriodSeconds(uint256 minWaitPeriodSeconds) public onlyRole(ADMIN_ROLE) { + emit MinWaitPeriodSet(s_minWaitPeriodSeconds, minWaitPeriodSeconds); + s_minWaitPeriodSeconds = minWaitPeriodSeconds; + } + + /// @notice Update s_upkeepInterval + function setUpkeepInterval(uint8 upkeepInterval) public onlyRole(ADMIN_ROLE) { + if (upkeepInterval > 255) revert InvalidUpkeepInterval(upkeepInterval); + emit UpkeepIntervalSet(s_upkeepInterval, upkeepInterval); + s_upkeepInterval = upkeepInterval; + } + + /// @notice Gets maxPerform + function getMaxPerform() external view returns (uint16) { + return s_maxPerform; + } + + /// @notice Gets maxCheck + function getMaxCheck() external view returns (uint16) { + return s_maxCheck; + } + + /// @notice Gets the minimum wait period + function getMinWaitPeriodSeconds() external view returns (uint256) { + return s_minWaitPeriodSeconds; + } + + /// @notice Gets upkeepInterval + function getUpkeepInterval() external view returns (uint8) { + return s_upkeepInterval; + } + + /// @notice Gets the list of subscription ids being watched + function getWatchList() external view returns (address[] memory) { + return s_watchList.values(); + } + + /// @notice Gets the onRamp address with the specified dstChainSelector + function getOnRampAddressAtChainSelector(uint64 dstChainSelector) external view returns (address) { + if (dstChainSelector == 0) revert InvalidChainSelector(); + return s_onRampAddresses.get(dstChainSelector); + } + + /// @notice Gets configuration information for an address on the watchlist + function getAccountInfo( + address targetAddress + ) external view returns (bool isActive, uint96 minBalance, uint96 topUpAmount, uint56 lastTopUpTimestamp) { + MonitoredAddress memory target = s_targets[targetAddress]; + return (target.isActive, target.minBalance, target.topUpAmount, target.lastTopUpTimestamp); + } + + /// @dev Modifier to make a function callable only by executor role or the + /// admin role. + modifier onlyAdminOrExecutor() { + address sender = _msgSender(); + if (!hasRole(ADMIN_ROLE, sender)) { + _checkRole(EXECUTOR_ROLE, sender); + } + _; + } + + modifier nonReentrant() { + if (reentrancyGuard) revert ReentrantCall(); + reentrancyGuard = true; + _; + reentrancyGuard = false; + } + + /// @notice Pause the contract, which prevents executing performUpkeep + function pause() external onlyRole(ADMIN_ROLE) { + _pause(); + } + + /// @notice Unpause the contract + function unpause() external onlyRole(ADMIN_ROLE) { + _unpause(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol new file mode 100644 index 0000000..dae17da --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IAutomationRegistryConsumer} from "../interfaces/IAutomationRegistryConsumer.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; + +/// @title The UpkeepBalanceMonitor contract +/// @notice A keeper-compatible contract that monitors and funds Chainlink Automation upkeeps. +contract UpkeepBalanceMonitor is ConfirmedOwner, Pausable { + using EnumerableSet for EnumerableSet.AddressSet; + + event ConfigSet(Config config); + event ForwarderSet(address forwarderAddress); + event FundsWithdrawn(uint256 amountWithdrawn, address payee); + event TopUpFailed(uint256 indexed upkeepId); + event TopUpSucceeded(uint256 indexed upkeepId, uint96 amount); + event WatchListSet(address registryAddress); + + error InvalidConfig(); + error InvalidTopUpData(); + error OnlyForwarderOrOwner(); + + /// @member maxBatchSize is the maximum number of upkeeps to fund in a single transaction + /// @member minPercentage is the percentage of the upkeep's minBalance at which top-up occurs + /// @member targetPercentage is the percentage of the upkeep's minBalance to top-up to + /// @member maxTopUpAmount is the maximum amount of LINK to top-up an upkeep with + struct Config { + uint8 maxBatchSize; + uint24 minPercentage; + uint24 targetPercentage; + uint96 maxTopUpAmount; + } + + // ================================================================ + // | STORAGE | + // ================================================================ + + LinkTokenInterface private immutable LINK_TOKEN; + + mapping(address => uint256[]) s_registryWatchLists; + EnumerableSet.AddressSet s_registries; + Config private s_config; + address private s_forwarderAddress; + + // ================================================================ + // | CONSTRUCTOR | + // ================================================================ + + /// @param linkToken the Link token address + /// @param config the initial config for the contract + constructor(LinkTokenInterface linkToken, Config memory config) ConfirmedOwner(msg.sender) { + require(address(linkToken) != address(0)); + LINK_TOKEN = linkToken; + setConfig(config); + } + + // ================================================================ + // | CORE FUNCTIONALITY | + // ================================================================ + + /// @notice Gets a list of upkeeps that are underfunded + /// @return needsFunding list of underfunded upkeepIDs + /// @return registryAddresses list of registries that the upkeepIDs belong to + /// @return topUpAmounts amount to top up each upkeep + function getUnderfundedUpkeeps() public view returns (uint256[] memory, address[] memory, uint96[] memory) { + Config memory config = s_config; + uint256[] memory needsFunding = new uint256[](config.maxBatchSize); + address[] memory registryAddresses = new address[](config.maxBatchSize); + uint96[] memory topUpAmounts = new uint96[](config.maxBatchSize); + uint256 availableFunds = LINK_TOKEN.balanceOf(address(this)); + uint256 count; + for (uint256 i = 0; i < s_registries.length(); i++) { + IAutomationRegistryConsumer registry = IAutomationRegistryConsumer(s_registries.at(i)); + for (uint256 j = 0; j < s_registryWatchLists[address(registry)].length; j++) { + uint256 upkeepID = s_registryWatchLists[address(registry)][j]; + uint96 upkeepBalance = registry.getBalance(upkeepID); + uint96 minBalance = registry.getMinBalance(upkeepID); + uint96 topUpThreshold = (minBalance * config.minPercentage) / 100; + uint96 topUpAmount = ((minBalance * config.targetPercentage) / 100) - upkeepBalance; + if (topUpAmount > config.maxTopUpAmount) { + topUpAmount = config.maxTopUpAmount; + } + if (upkeepBalance <= topUpThreshold && availableFunds >= topUpAmount) { + needsFunding[count] = upkeepID; + topUpAmounts[count] = topUpAmount; + registryAddresses[count] = address(registry); + count++; + availableFunds -= topUpAmount; + } + if (count == config.maxBatchSize) { + break; + } + } + if (count == config.maxBatchSize) { + break; + } + } + if (count < config.maxBatchSize) { + assembly { + mstore(needsFunding, count) + mstore(registryAddresses, count) + mstore(topUpAmounts, count) + } + } + return (needsFunding, registryAddresses, topUpAmounts); + } + + /// @notice Called by the keeper/owner to send funds to underfunded upkeeps + /// @param upkeepIDs the list of upkeep ids to fund + /// @param registryAddresses the list of registries that the upkeepIDs belong to + /// @param topUpAmounts the list of amounts to fund each upkeep with + /// @dev We explicitly choose not to verify that input upkeepIDs are included in the watchlist. We also + /// explicity permit any amount to be sent via topUpAmounts; it does not have to meet the criteria + /// specified in getUnderfundedUpkeeps(). Here, we are relying on the security of automation's OCR to + /// secure the output of getUnderfundedUpkeeps() as the input to topUp(), and we are treating the owner + /// as a privileged user that can perform arbitrary top-ups to any upkeepID. + function topUp( + uint256[] memory upkeepIDs, + address[] memory registryAddresses, + uint96[] memory topUpAmounts + ) public whenNotPaused { + if (msg.sender != address(s_forwarderAddress) && msg.sender != owner()) revert OnlyForwarderOrOwner(); + if (upkeepIDs.length != registryAddresses.length || upkeepIDs.length != topUpAmounts.length) + revert InvalidTopUpData(); + for (uint256 i = 0; i < upkeepIDs.length; i++) { + try LINK_TOKEN.transferAndCall(registryAddresses[i], topUpAmounts[i], abi.encode(upkeepIDs[i])) returns ( + bool success + ) { + if (success) { + emit TopUpSucceeded(upkeepIDs[i], topUpAmounts[i]); + continue; + } + } catch {} + emit TopUpFailed(upkeepIDs[i]); + } + } + + // ================================================================ + // | AUTOMATION COMPATIBLE | + // ================================================================ + + /// @notice Gets list of upkeeps ids that are underfunded and returns a keeper-compatible payload. + /// @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds + function checkUpkeep(bytes calldata) external view returns (bool upkeepNeeded, bytes memory performData) { + ( + uint256[] memory needsFunding, + address[] memory registryAddresses, + uint96[] memory topUpAmounts + ) = getUnderfundedUpkeeps(); + upkeepNeeded = needsFunding.length > 0; + if (upkeepNeeded) { + performData = abi.encode(needsFunding, registryAddresses, topUpAmounts); + } + return (upkeepNeeded, performData); + } + + /// @notice Called by the keeper to send funds to underfunded addresses. + /// @param performData the abi encoded list of addresses to fund + function performUpkeep(bytes calldata performData) external { + (uint256[] memory upkeepIDs, address[] memory registryAddresses, uint96[] memory topUpAmounts) = abi.decode( + performData, + (uint256[], address[], uint96[]) + ); + topUp(upkeepIDs, registryAddresses, topUpAmounts); + } + + // ================================================================ + // | ADMIN | + // ================================================================ + + /// @notice Withdraws the contract balance in LINK. + /// @param amount the amount of LINK (in juels) to withdraw + /// @param payee the address to pay + function withdraw(uint256 amount, address payee) external onlyOwner { + require(payee != address(0)); + LINK_TOKEN.transfer(payee, amount); + emit FundsWithdrawn(amount, payee); + } + + /// @notice Pause the contract, which prevents executing performUpkeep. + function pause() external onlyOwner { + _pause(); + } + + /// @notice Unpause the contract. + function unpause() external onlyOwner { + _unpause(); + } + + // ================================================================ + // | SETTERS | + // ================================================================ + + /// @notice Sets the list of upkeeps to watch + /// @param registryAddress the registry that this watchlist applies to + /// @param watchlist the list of UpkeepIDs to watch + function setWatchList(address registryAddress, uint256[] calldata watchlist) external onlyOwner { + if (watchlist.length == 0) { + s_registries.remove(registryAddress); + delete s_registryWatchLists[registryAddress]; + } else { + s_registries.add(registryAddress); + s_registryWatchLists[registryAddress] = watchlist; + } + emit WatchListSet(registryAddress); + } + + /// @notice Sets the contract config + /// @param config the new config + function setConfig(Config memory config) public onlyOwner { + if ( + config.maxBatchSize == 0 || + config.minPercentage < 100 || + config.targetPercentage <= config.minPercentage || + config.maxTopUpAmount == 0 + ) { + revert InvalidConfig(); + } + s_config = config; + emit ConfigSet(config); + } + + /// @notice Sets the upkeep's forwarder contract + /// @param forwarderAddress the new forwarder + /// @dev this should only need to be called once, after registering the contract with the registry + function setForwarder(address forwarderAddress) external onlyOwner { + s_forwarderAddress = forwarderAddress; + emit ForwarderSet(forwarderAddress); + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + /// @notice Gets the list of upkeeps ids being monitored + function getWatchList() external view returns (address[] memory, uint256[][] memory) { + address[] memory registryAddresses = s_registries.values(); + uint256[][] memory upkeepIDs = new uint256[][](registryAddresses.length); + for (uint256 i = 0; i < registryAddresses.length; i++) { + upkeepIDs[i] = s_registryWatchLists[registryAddresses[i]]; + } + return (registryAddresses, upkeepIDs); + } + + /// @notice Gets the contract config + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice Gets the upkeep's forwarder contract + function getForwarder() external view returns (address) { + return s_forwarderAddress; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol new file mode 100644 index 0000000..f455d56 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; +import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/LinkTokenInterface.sol"; +import "../../shared/access/ConfirmedOwner.sol"; +import "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Contract to accept requests for upkeep registrations + * @dev There are 2 registration workflows in this contract + * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually + * calls `approve` to register upkeep and emit events to inform UI and others interested. + * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on + * keeper registry and then emits approved event to finish the flow automatically without manual intervention. + * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. + * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. + */ +contract KeeperRegistrar is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { + /** + * DISABLED: No auto approvals, all new upkeeps should be approved manually. + * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. + * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. + */ + enum AutoApproveType { + DISABLED, + ENABLED_SENDER_ALLOWLIST, + ENABLED_ALL + } + + bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; + + mapping(bytes32 => PendingRequest) private s_pendingRequests; + + LinkTokenInterface public immutable LINK; + + /** + * @notice versions: + * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve + * : Remove rate limit and add max allowed for auto approve + * - KeeperRegistrar 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistrar 1.1.0"; + + struct Config { + AutoApproveType autoApproveConfigType; + uint32 autoApproveMaxAllowed; + uint32 approvedCount; + KeeperRegistryBaseInterface keeperRegistry; + uint96 minLINKJuels; + } + + struct PendingRequest { + address admin; + uint96 balance; + } + + Config private s_config; + // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST + mapping(address => bool) private s_autoApproveAllowedSenders; + + event RegistrationRequested( + bytes32 indexed hash, + string name, + bytes encryptedEmail, + address indexed upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes checkData, + uint96 amount, + uint8 indexed source + ); + + event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); + + event RegistrationRejected(bytes32 indexed hash); + + event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); + + event ConfigChanged( + AutoApproveType autoApproveConfigType, + uint32 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ); + + error InvalidAdminAddress(); + error RequestNotFound(); + error HashMismatch(); + error OnlyAdminOrOwner(); + error InsufficientPayment(); + error RegistrationRequestFailed(); + error OnlyLink(); + error AmountMismatch(); + error SenderMismatch(); + error FunctionNotPermitted(); + error LinkTransferFailed(address to); + error InvalidDataLength(); + + /* + * @param LINKAddress Address of Link token + * @param autoApproveConfigType setting for auto-approve registrations + * @param autoApproveMaxAllowed max number of registrations that can be auto approved + * @param keeperRegistry keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + */ + constructor( + address LINKAddress, + AutoApproveType autoApproveConfigType, + uint16 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(LINKAddress); + setRegistrationConfig(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); + } + + //EXTERNAL + + /** + * @notice register can only be called through transferAndCall on LINK contract + * @param name string of the upkeep to be registered + * @param encryptedEmail email address of upkeep contact + * @param upkeepContract address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when performing upkeep + * @param adminAddress address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + * @param amount quantity of LINK upkeep is funded with (specified in Juels) + * @param source application sending this request + * @param sender address of the sender making the request + */ + function register( + string memory name, + bytes calldata encryptedEmail, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes calldata checkData, + uint96 amount, + uint8 source, + address sender + ) external onlyLINK { + if (adminAddress == address(0)) { + revert InvalidAdminAddress(); + } + bytes32 hash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); + + emit RegistrationRequested( + hash, + name, + encryptedEmail, + upkeepContract, + gasLimit, + adminAddress, + checkData, + amount, + source + ); + + Config memory config = s_config; + if (_shouldAutoApprove(config, sender)) { + s_config.approvedCount = config.approvedCount + 1; + + _approve(name, upkeepContract, gasLimit, adminAddress, checkData, amount, hash); + } else { + uint96 newBalance = s_pendingRequests[hash].balance + amount; + s_pendingRequests[hash] = PendingRequest({admin: adminAddress, balance: newBalance}); + } + } + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function approve( + string memory name, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes calldata checkData, + bytes32 hash + ) external onlyOwner { + PendingRequest memory request = s_pendingRequests[hash]; + if (request.admin == address(0)) { + revert RequestNotFound(); + } + bytes32 expectedHash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); + if (hash != expectedHash) { + revert HashMismatch(); + } + delete s_pendingRequests[hash]; + _approve(name, upkeepContract, gasLimit, adminAddress, checkData, request.balance, hash); + } + + /** + * @notice cancel will remove a registration request and return the refunds to the msg.sender + * @param hash the request hash + */ + function cancel(bytes32 hash) external { + PendingRequest memory request = s_pendingRequests[hash]; + if (!(msg.sender == request.admin || msg.sender == owner())) { + revert OnlyAdminOrOwner(); + } + if (request.admin == address(0)) { + revert RequestNotFound(); + } + delete s_pendingRequests[hash]; + bool success = LINK.transfer(msg.sender, request.balance); + if (!success) { + revert LinkTransferFailed(msg.sender); + } + emit RegistrationRejected(hash); + } + + /** + * @notice owner calls this function to set if registration requests should be sent directly to the Keeper Registry + * @param autoApproveConfigType setting for auto-approve registrations + * note: autoApproveAllowedSenders list persists across config changes irrespective of type + * @param autoApproveMaxAllowed max number of registrations that can be auto approved + * @param keeperRegistry new keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + */ + function setRegistrationConfig( + AutoApproveType autoApproveConfigType, + uint16 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ) public onlyOwner { + uint32 approvedCount = s_config.approvedCount; + s_config = Config({ + autoApproveConfigType: autoApproveConfigType, + autoApproveMaxAllowed: autoApproveMaxAllowed, + approvedCount: approvedCount, + minLINKJuels: minLINKJuels, + keeperRegistry: KeeperRegistryBaseInterface(keeperRegistry) + }); + + emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); + } + + /** + * @notice owner calls this function to set allowlist status for senderAddress + * @param senderAddress senderAddress to set the allowlist status for + * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed + */ + function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { + s_autoApproveAllowedSenders[senderAddress] = allowed; + + emit AutoApproveAllowedSenderSet(senderAddress, allowed); + } + + /** + * @notice read the allowlist status of senderAddress + * @param senderAddress address to read the allowlist status for + */ + function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { + return s_autoApproveAllowedSenders[senderAddress]; + } + + /** + * @notice read the current registration configuration + */ + function getRegistrationConfig() + external + view + returns ( + AutoApproveType autoApproveConfigType, + uint32 autoApproveMaxAllowed, + uint32 approvedCount, + address keeperRegistry, + uint256 minLINKJuels + ) + { + Config memory config = s_config; + return ( + config.autoApproveConfigType, + config.autoApproveMaxAllowed, + config.approvedCount, + address(config.keeperRegistry), + config.minLINKJuels + ); + } + + /** + * @notice gets the admin address and the current balance of a registration request + */ + function getPendingRequest(bytes32 hash) external view returns (address, uint96) { + PendingRequest memory request = s_pendingRequests[hash]; + return (request.admin, request.balance); + } + + /** + * @notice Called when LINK is sent to the contract via `transferAndCall` + * @param sender Address of the sender transfering LINK + * @param amount Amount of LINK sent (specified in Juels) + * @param data Payload of the transaction + */ + function onTokenTransfer( + address sender, + uint256 amount, + bytes calldata data + ) + external + override + onlyLINK + permittedFunctionsForLINK(data) + isActualAmount(amount, data) + isActualSender(sender, data) + { + if (data.length < 292) revert InvalidDataLength(); + if (amount < s_config.minLINKJuels) { + revert InsufficientPayment(); + } + (bool success, ) = address(this).delegatecall(data); + // calls register + if (!success) { + revert RegistrationRequestFailed(); + } + } + + //PRIVATE + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function _approve( + string memory name, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes calldata checkData, + uint96 amount, + bytes32 hash + ) private { + KeeperRegistryBaseInterface keeperRegistry = s_config.keeperRegistry; + + // register upkeep + uint256 upkeepId = keeperRegistry.registerUpkeep(upkeepContract, gasLimit, adminAddress, checkData); + // fund upkeep + bool success = LINK.transferAndCall(address(keeperRegistry), amount, abi.encode(upkeepId)); + if (!success) { + revert LinkTransferFailed(address(keeperRegistry)); + } + + emit RegistrationApproved(hash, name, upkeepId); + } + + /** + * @dev verify sender allowlist if needed and check max limit + */ + function _shouldAutoApprove(Config memory config, address sender) private returns (bool) { + if (config.autoApproveConfigType == AutoApproveType.DISABLED) { + return false; + } + if ( + config.autoApproveConfigType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender]) + ) { + return false; + } + if (config.approvedCount < config.autoApproveMaxAllowed) { + return true; + } + return false; + } + + //MODIFIERS + + /** + * @dev Reverts if not sent from the LINK token + */ + modifier onlyLINK() { + if (msg.sender != address(LINK)) { + revert OnlyLink(); + } + _; + } + + /** + * @dev Reverts if the given data does not begin with the `register` function selector + * @param _data The data payload of the request + */ + modifier permittedFunctionsForLINK(bytes memory _data) { + bytes4 funcSelector; + assembly { + // solhint-disable-next-line avoid-low-level-calls + funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data + } + if (funcSelector != REGISTER_REQUEST_SELECTOR) { + revert FunctionNotPermitted(); + } + _; + } + + /** + * @dev Reverts if the actual amount passed does not match the expected amount + * @param expected amount that should match the actual amount + * @param data bytes + */ + modifier isActualAmount(uint256 expected, bytes memory data) { + uint256 actual; + assembly { + actual := mload(add(data, 228)) + } + if (expected != actual) { + revert AmountMismatch(); + } + _; + } + + /** + * @dev Reverts if the actual sender address does not match the expected sender address + * @param expected address that should match the actual sender address + * @param data bytes + */ + modifier isActualSender(address expected, bytes memory data) { + address actual; + assembly { + actual := mload(add(data, 292)) + } + if (expected != actual) { + revert SenderMismatch(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol new file mode 100644 index 0000000..2fa1ee6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol @@ -0,0 +1,909 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/security/Pausable.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import "../KeeperBase.sol"; +import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/AggregatorV3Interface.sol"; +import "../interfaces/KeeperCompatibleInterface.sol"; +import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; +import "../interfaces/MigratableKeeperRegistryInterface.sol"; +import "../interfaces/UpkeepTranscoderInterface.sol"; +import "../../shared/interfaces/IERC677Receiver.sol"; +import "../../shared/interfaces/LinkTokenInterface.sol"; +import "../../shared/access/ConfirmedOwner.sol"; + +struct Upkeep { + uint96 balance; + address lastKeeper; // 1 storage slot full + uint32 executeGas; + uint64 maxValidBlocknumber; + address target; // 2 storage slots full + uint96 amountSpent; + address admin; // 3 storage slots full +} + +/** + * @notice Registry for adding work for Chainlink Keepers to perform on client + * contracts. Clients must support the Upkeep interface. + */ +contract KeeperRegistry1_2 is + TypeAndVersionInterface, + ConfirmedOwner, + KeeperBase, + ReentrancyGuard, + Pausable, + KeeperRegistryExecutableInterface, + MigratableKeeperRegistryInterface, + IERC677Receiver +{ + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + + address private constant ZERO_ADDRESS = address(0); + address private constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 private constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 private constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + uint256 private constant PERFORM_GAS_MIN = 2_300; + uint256 private constant CANCELATION_DELAY = 50; + uint256 private constant PERFORM_GAS_CUSHION = 5_000; + uint256 private constant REGISTRY_GAS_OVERHEAD = 80_000; + uint256 private constant PPB_BASE = 1_000_000_000; + uint64 private constant UINT64_MAX = 2 ** 64 - 1; + uint96 private constant LINK_TOTAL_SUPPLY = 1e27; + + address[] private s_keeperList; + EnumerableSet.UintSet private s_upkeepIDs; + mapping(uint256 => Upkeep) private s_upkeep; + mapping(address => KeeperInfo) private s_keeperInfo; + mapping(address => address) private s_proposedPayee; + mapping(uint256 => bytes) private s_checkData; + mapping(address => MigrationPermission) private s_peerRegistryMigrationPermission; + Storage private s_storage; + uint256 private s_fallbackGasPrice; // not in config object for gas savings + uint256 private s_fallbackLinkPrice; // not in config object for gas savings + uint96 private s_ownerLinkBalance; + uint256 private s_expectedLinkBalance; + address private s_transcoder; + address private s_registrar; + + LinkTokenInterface public immutable LINK; + AggregatorV3Interface public immutable LINK_ETH_FEED; + AggregatorV3Interface public immutable FAST_GAS_FEED; + + /** + * @notice versions: + * - KeeperRegistry 1.2.0: allow funding within performUpkeep + * : allow configurable registry maxPerformGas + * : add function to let admin change upkeep gas limit + * : add minUpkeepSpend requirement + : upgrade to solidity v0.8 + * - KeeperRegistry 1.1.0: added flatFeeMicroLink + * - KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistry 1.2.0"; + + error CannotCancel(); + error UpkeepNotActive(); + error MigrationNotPermitted(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error NotAContract(); + error PaymentGreaterThanAllLINK(); + error OnlyActiveKeepers(); + error InsufficientFunds(); + error KeepersMustTakeTurns(); + error ParameterLengthError(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByLINKToken(); + error InvalidPayee(); + error DuplicateEntry(); + error ValueNotChanged(); + error IndexOutOfRange(); + error TranscoderNotSet(); + error ArrayHasNoEntries(); + error GasLimitOutsideRange(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedPayee(); + error GasLimitCanOnlyIncrease(); + error OnlyCallableByAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error InvalidRecipient(); + error InvalidDataLength(); + error TargetCheckReverted(bytes reason); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + /** + * @notice storage of the registry, contains a mix of config and state data + */ + struct Storage { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint24 blockCountPerTurn; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; // 1 evm word + uint32 maxPerformGas; + uint32 nonce; // 2 evm words + } + + struct KeeperInfo { + address payee; + uint96 balance; + bool active; + } + + struct PerformParams { + address from; + uint256 id; + bytes performData; + uint256 maxLinkPayment; + uint256 gasLimit; + uint256 adjustedGasWei; + uint256 linkEth; + } + + event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + address indexed from, + uint96 payment, + bytes performData + ); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event OwnerFundsWithdrawn(uint96 amount); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event ConfigSet(Config config); + event KeepersUpdated(address[] keepers, address[] payees); + event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); + event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + + /** + * @param link address of the LINK Token + * @param linkEthFeed address of the LINK/ETH price feed + * @param fastGasFeed address of the Fast Gas price feed + * @param config registry config settings + */ + constructor(address link, address linkEthFeed, address fastGasFeed, Config memory config) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(link); + LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); + FAST_GAS_FEED = AggregatorV3Interface(fastGasFeed); + setConfig(config); + } + + // ACTIONS + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData + ) external override onlyOwnerOrRegistrar returns (uint256 id) { + id = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), s_storage.nonce))); + _createUpkeep(id, target, gasLimit, admin, 0, checkData); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + return id; + } + + /** + * @notice simulated by keepers via eth_call to see if the upkeep needs to be + * performed. If upkeep is needed, the call then simulates performUpkeep + * to make sure it succeeds. Finally, it returns the success status along with + * payment information and the perform data payload. + * @param id identifier of the upkeep to check + * @param from the address to simulate performing the upkeep from + */ + function checkUpkeep( + uint256 id, + address from + ) + external + override + cannotExecute + returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ) + { + Upkeep memory upkeep = s_upkeep[id]; + + bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); + (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); + + if (!success) revert TargetCheckReverted(result); + + (success, performData) = abi.decode(result, (bool, bytes)); + if (!success) revert UpkeepNotNeeded(); + + PerformParams memory params = _generatePerformParams(from, id, performData, false); + _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); + + return (performData, params.maxLinkPayment, params.gasLimit, params.adjustedGasWei, params.linkEth); + } + + /** + * @notice executes the upkeep with the perform data returned from + * checkUpkeep, validates the keeper's permissions, and pays the keeper. + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + */ + function performUpkeep( + uint256 id, + bytes calldata performData + ) external override whenNotPaused returns (bool success) { + return _performUpkeepWithParams(_generatePerformParams(msg.sender, id, performData, true)); + } + + /** + * @notice prevent an upkeep from being performed in the future + * @param id upkeep to be canceled + */ + function cancelUpkeep(uint256 id) external override { + uint64 maxValid = s_upkeep[id].maxValidBlocknumber; + bool canceled = maxValid != UINT64_MAX; + bool isOwner = msg.sender == owner(); + + if (canceled && !(isOwner && maxValid > block.number)) revert CannotCancel(); + if (!isOwner && msg.sender != s_upkeep[id].admin) revert OnlyCallableByOwnerOrAdmin(); + + uint256 height = block.number; + if (!isOwner) { + height = height + CANCELATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint64(height); + s_upkeepIDs.remove(id); + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @notice adds LINK funding for an upkeep by transferring from the sender's + * LINK balance + * @param id upkeep to fund + * @param amount number of LINK to transfer + */ + function addFunds(uint256 id, uint96 amount) external override onlyActiveUpkeep(id) { + s_upkeep[id].balance = s_upkeep[id].balance + amount; + s_expectedLinkBalance = s_expectedLinkBalance + amount; + LINK.transferFrom(msg.sender, address(this), amount); + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(LINK)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); + + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_expectedLinkBalance = s_expectedLinkBalance + amount; + + emit FundsAdded(id, sender, uint96(amount)); + } + + /** + * @notice removes funding from a canceled upkeep + * @param id upkeep to withdraw funds from + * @param to destination address for sending remaining funds + */ + function withdrawFunds(uint256 id, address to) external validRecipient(to) onlyUpkeepAdmin(id) { + if (s_upkeep[id].maxValidBlocknumber > block.number) revert UpkeepNotCanceled(); + + uint96 minUpkeepSpend = s_storage.minUpkeepSpend; + uint96 amountLeft = s_upkeep[id].balance; + uint96 amountSpent = s_upkeep[id].amountSpent; + + uint96 cancellationFee = 0; + // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) + if (amountSpent < minUpkeepSpend) { + cancellationFee = minUpkeepSpend - amountSpent; + if (cancellationFee > amountLeft) { + cancellationFee = amountLeft; + } + } + uint96 amountToWithdraw = amountLeft - cancellationFee; + + s_upkeep[id].balance = 0; + s_ownerLinkBalance = s_ownerLinkBalance + cancellationFee; + + s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; + emit FundsWithdrawn(id, amountToWithdraw, to); + + LINK.transfer(to, amountToWithdraw); + } + + /** + * @notice withdraws LINK funds collected through cancellation fees + */ + function withdrawOwnerFunds() external onlyOwner { + uint96 amount = s_ownerLinkBalance; + + s_expectedLinkBalance = s_expectedLinkBalance - amount; + s_ownerLinkBalance = 0; + + emit OwnerFundsWithdrawn(amount); + LINK.transfer(msg.sender, amount); + } + + /** + * @notice allows the admin of an upkeep to modify gas limit + * @param id upkeep to be change the gas limit for + * @param gasLimit new gas limit for the upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override onlyActiveUpkeep(id) onlyUpkeepAdmin(id) { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + + s_upkeep[id].executeGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @notice recovers LINK funds improperly transferred to the registry + * @dev In principle this function’s execution cost could exceed block + * gas limit. However, in our anticipated deployment, the number of upkeeps and + * keepers will be low enough to avoid this problem. + */ + function recoverFunds() external onlyOwner { + uint256 total = LINK.balanceOf(address(this)); + LINK.transfer(msg.sender, total - s_expectedLinkBalance); + } + + /** + * @notice withdraws a keeper's payment, callable only by the keeper's payee + * @param from keeper address + * @param to address to send the payment to + */ + function withdrawPayment(address from, address to) external validRecipient(to) { + KeeperInfo memory keeper = s_keeperInfo[from]; + if (keeper.payee != msg.sender) revert OnlyCallableByPayee(); + + s_keeperInfo[from].balance = 0; + s_expectedLinkBalance = s_expectedLinkBalance - keeper.balance; + emit PaymentWithdrawn(from, keeper.balance, to, msg.sender); + + LINK.transfer(to, keeper.balance); + } + + /** + * @notice proposes the safe transfer of a keeper's payee to another address + * @param keeper address of the keeper to transfer payee role + * @param proposed address to nominate for next payeeship + */ + function transferPayeeship(address keeper, address proposed) external { + if (s_keeperInfo[keeper].payee != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[keeper] != proposed) { + s_proposedPayee[keeper] = proposed; + emit PayeeshipTransferRequested(keeper, msg.sender, proposed); + } + } + + /** + * @notice accepts the safe transfer of payee role for a keeper + * @param keeper address to accept the payee role for + */ + function acceptPayeeship(address keeper) external { + if (s_proposedPayee[keeper] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_keeperInfo[keeper].payee; + s_keeperInfo[keeper].payee = msg.sender; + s_proposedPayee[keeper] = ZERO_ADDRESS; + + emit PayeeshipTransferred(keeper, past, msg.sender); + } + + /** + * @notice signals to keepers that they should not perform upkeeps until the + * contract has been unpaused + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice signals to keepers that they can perform upkeeps once again after + * having been paused + */ + function unpause() external onlyOwner { + _unpause(); + } + + // SETTERS + + /** + * @notice updates the configuration of the registry + * @param config registry config fields + */ + function setConfig(Config memory config) public onlyOwner { + if (config.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); + s_storage = Storage({ + paymentPremiumPPB: config.paymentPremiumPPB, + flatFeeMicroLink: config.flatFeeMicroLink, + blockCountPerTurn: config.blockCountPerTurn, + checkGasLimit: config.checkGasLimit, + stalenessSeconds: config.stalenessSeconds, + gasCeilingMultiplier: config.gasCeilingMultiplier, + minUpkeepSpend: config.minUpkeepSpend, + maxPerformGas: config.maxPerformGas, + nonce: s_storage.nonce + }); + s_fallbackGasPrice = config.fallbackGasPrice; + s_fallbackLinkPrice = config.fallbackLinkPrice; + s_transcoder = config.transcoder; + s_registrar = config.registrar; + emit ConfigSet(config); + } + + /** + * @notice update the list of keepers allowed to perform upkeep + * @param keepers list of addresses allowed to perform upkeep + * @param payees addresses corresponding to keepers who are allowed to + * move payments which have been accrued + */ + function setKeepers(address[] calldata keepers, address[] calldata payees) external onlyOwner { + if (keepers.length != payees.length || keepers.length < 2) revert ParameterLengthError(); + for (uint256 i = 0; i < s_keeperList.length; i++) { + address keeper = s_keeperList[i]; + s_keeperInfo[keeper].active = false; + } + for (uint256 i = 0; i < keepers.length; i++) { + address keeper = keepers[i]; + KeeperInfo storage s_keeper = s_keeperInfo[keeper]; + address oldPayee = s_keeper.payee; + address newPayee = payees[i]; + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) revert InvalidPayee(); + if (s_keeper.active) revert DuplicateEntry(); + s_keeper.active = true; + if (newPayee != IGNORE_ADDRESS) { + s_keeper.payee = newPayee; + } + } + s_keeperList = keepers; + emit KeepersUpdated(keepers, payees); + } + + // GETTERS + + /** + * @notice read all of the details about an upkeep + */ + function getUpkeep( + uint256 id + ) + external + view + override + returns ( + address target, + uint32 executeGas, + bytes memory checkData, + uint96 balance, + address lastKeeper, + address admin, + uint64 maxValidBlocknumber, + uint96 amountSpent + ) + { + Upkeep memory reg = s_upkeep[id]; + return ( + reg.target, + reg.executeGas, + s_checkData[id], + reg.balance, + reg.lastKeeper, + reg.admin, + reg.maxValidBlocknumber, + reg.amountSpent + ); + } + + /** + * @notice retrieve active upkeep IDs + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a wholistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { + uint256 maxIdx = s_upkeepIDs.length(); + if (startIndex >= maxIdx) revert IndexOutOfRange(); + if (maxCount == 0) { + maxCount = maxIdx - startIndex; + } + uint256[] memory ids = new uint256[](maxCount); + for (uint256 idx = 0; idx < maxCount; idx++) { + ids[idx] = s_upkeepIDs.at(startIndex + idx); + } + return ids; + } + + /** + * @notice read the current info about any keeper address + */ + function getKeeperInfo(address query) external view override returns (address payee, bool active, uint96 balance) { + KeeperInfo memory keeper = s_keeperInfo[query]; + return (keeper.payee, keeper.active, keeper.balance); + } + + /** + * @notice read the current state of the registry + */ + function getState() + external + view + override + returns (State memory state, Config memory config, address[] memory keepers) + { + Storage memory store = s_storage; + state.nonce = store.nonce; + state.ownerLinkBalance = s_ownerLinkBalance; + state.expectedLinkBalance = s_expectedLinkBalance; + state.numUpkeeps = s_upkeepIDs.length(); + config.paymentPremiumPPB = store.paymentPremiumPPB; + config.flatFeeMicroLink = store.flatFeeMicroLink; + config.blockCountPerTurn = store.blockCountPerTurn; + config.checkGasLimit = store.checkGasLimit; + config.stalenessSeconds = store.stalenessSeconds; + config.gasCeilingMultiplier = store.gasCeilingMultiplier; + config.minUpkeepSpend = store.minUpkeepSpend; + config.maxPerformGas = store.maxPerformGas; + config.fallbackGasPrice = s_fallbackGasPrice; + config.fallbackLinkPrice = s_fallbackLinkPrice; + config.transcoder = s_transcoder; + config.registrar = s_registrar; + return (state, config, s_keeperList); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { + return getMaxPaymentForGas(s_upkeep[id].executeGas); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas(uint256 gasLimit) public view returns (uint96 maxPayment) { + (uint256 gasWei, uint256 linkEth) = _getFeedData(); + uint256 adjustedGasWei = _adjustGasPrice(gasWei, false); + return _calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice sets the peer registry migration permission + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external override { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + uint256 id; + Upkeep memory upkeep; + uint256 totalBalanceRemaining; + bytes[] memory checkDatas = new bytes[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); + upkeeps[idx] = upkeep; + checkDatas[idx] = s_checkData[id]; + totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; + delete s_upkeep[id]; + delete s_checkData[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; + bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas); + MigratableKeeperRegistryInterface(destination).receiveUpkeeps( + UpkeepTranscoderInterface(s_transcoder).transcodeUpkeeps( + UpkeepFormat.V1, + MigratableKeeperRegistryInterface(destination).upkeepTranscoderVersion(), + encodedUpkeeps + ) + ); + LINK.transfer(destination, totalBalanceRemaining); + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + UpkeepFormat public constant override upkeepTranscoderVersion = UpkeepFormat.V1; + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external override { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], Upkeep[], bytes[]) + ); + for (uint256 idx = 0; idx < ids.length; idx++) { + _createUpkeep( + ids[idx], + upkeeps[idx].target, + upkeeps[idx].executeGas, + upkeeps[idx].admin, + upkeeps[idx].balance, + checkDatas[idx] + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } + + /** + * @notice creates a new upkeep with the given fields + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + */ + function _createUpkeep( + uint256 id, + address target, + uint32 gasLimit, + address admin, + uint96 balance, + bytes memory checkData + ) internal whenNotPaused { + if (!target.isContract()) revert NotAContract(); + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + s_upkeep[id] = Upkeep({ + target: target, + executeGas: gasLimit, + balance: balance, + admin: admin, + maxValidBlocknumber: UINT64_MAX, + lastKeeper: ZERO_ADDRESS, + amountSpent: 0 + }); + s_expectedLinkBalance = s_expectedLinkBalance + balance; + s_checkData[id] = checkData; + s_upkeepIDs.add(id); + } + + /** + * @dev retrieves feed data for fast gas/eth and link/eth prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData() private view returns (uint256 gasWei, uint256 linkEth) { + uint32 stalenessSeconds = s_storage.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = FAST_GAS_FEED.latestRoundData(); + if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { + linkEth = s_fallbackLinkPrice; + } else { + linkEth = uint256(feedValue); + } + return (gasWei, linkEth); + } + + /** + * @dev calculates LINK paid for gas spent plus a configure premium percentage + */ + function _calculatePaymentAmount( + uint256 gasLimit, + uint256 gasWei, + uint256 linkEth + ) private view returns (uint96 payment) { + uint256 weiForGas = gasWei * (gasLimit + REGISTRY_GAS_OVERHEAD); + uint256 premium = PPB_BASE + s_storage.paymentPremiumPPB; + uint256 total = ((weiForGas * (1e9) * (premium)) / (linkEth)) + (uint256(s_storage.flatFeeMicroLink) * (1e12)); + if (total > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); + return uint96(total); // LINK_TOTAL_SUPPLY < UINT96_MAX + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= PERFORM_GAS_CUSHION and check for underflow + if lt(g, PERFORM_GAS_CUSHION) { + revert(0, 0) + } + g := sub(g, PERFORM_GAS_CUSHION) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * keeper and the exact gas required by the Upkeep + */ + function _performUpkeepWithParams( + PerformParams memory params + ) private nonReentrant validUpkeep(params.id) returns (bool success) { + Upkeep memory upkeep = s_upkeep[params.id]; + _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); + + uint256 gasUsed = gasleft(); + bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, params.performData); + success = _callWithExactGas(params.gasLimit, upkeep.target, callData); + gasUsed = gasUsed - gasleft(); + + uint96 payment = _calculatePaymentAmount(gasUsed, params.adjustedGasWei, params.linkEth); + + s_upkeep[params.id].balance = s_upkeep[params.id].balance - payment; + s_upkeep[params.id].amountSpent = s_upkeep[params.id].amountSpent + payment; + s_upkeep[params.id].lastKeeper = params.from; + s_keeperInfo[params.from].balance = s_keeperInfo[params.from].balance + payment; + + emit UpkeepPerformed(params.id, success, params.from, payment, params.performData); + return success; + } + + /** + * @dev ensures all required checks are passed before an upkeep is performed + */ + function _prePerformUpkeep(Upkeep memory upkeep, address from, uint256 maxLinkPayment) private view { + if (!s_keeperInfo[from].active) revert OnlyActiveKeepers(); + if (upkeep.balance < maxLinkPayment) revert InsufficientFunds(); + if (upkeep.lastKeeper == from) revert KeepersMustTakeTurns(); + } + + /** + * @dev adjusts the gas price to min(ceiling, tx.gasprice) or just uses the ceiling if tx.gasprice is disabled + */ + function _adjustGasPrice(uint256 gasWei, bool useTxGasPrice) private view returns (uint256 adjustedPrice) { + adjustedPrice = gasWei * s_storage.gasCeilingMultiplier; + if (useTxGasPrice && tx.gasprice < adjustedPrice) { + adjustedPrice = tx.gasprice; + } + } + + /** + * @dev generates a PerformParams struct for use in _performUpkeepWithParams() + */ + function _generatePerformParams( + address from, + uint256 id, + bytes memory performData, + bool useTxGasPrice + ) private view returns (PerformParams memory) { + uint256 gasLimit = s_upkeep[id].executeGas; + (uint256 gasWei, uint256 linkEth) = _getFeedData(); + uint256 adjustedGasWei = _adjustGasPrice(gasWei, useTxGasPrice); + uint96 maxLinkPayment = _calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); + + return + PerformParams({ + from: from, + id: id, + performData: performData, + maxLinkPayment: maxLinkPayment, + gasLimit: gasLimit, + adjustedGasWei: adjustedGasWei, + linkEth: linkEth + }); + } + + // MODIFIERS + + /** + * @dev ensures a upkeep is valid + */ + modifier validUpkeep(uint256 id) { + if (s_upkeep[id].maxValidBlocknumber <= block.number) revert UpkeepNotActive(); + _; + } + + /** + * @dev Reverts if called by anyone other than the admin of upkeep #id + */ + modifier onlyUpkeepAdmin(uint256 id) { + if (msg.sender != s_upkeep[id].admin) revert OnlyCallableByAdmin(); + _; + } + + /** + * @dev Reverts if called on a cancelled upkeep + */ + modifier onlyActiveUpkeep(uint256 id) { + if (s_upkeep[id].maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); + _; + } + + /** + * @dev ensures that burns don't accidentally happen by sending to the zero + * address + */ + modifier validRecipient(address to) { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + _; + } + + /** + * @dev Reverts if called by anyone other than the contract owner or registrar. + */ + modifier onlyOwnerOrRegistrar() { + if (msg.sender != owner() && msg.sender != s_registrar) revert OnlyCallableByOwnerOrRegistrar(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol new file mode 100644 index 0000000..253a421 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import {AutomationRegistryExecutableInterface} from "../interfaces/v1_2/AutomationRegistryInterface1_2.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +/** + * @notice This contract serves as a wrapper around a keeper registry's checkUpkeep function. + */ +contract KeeperRegistryCheckUpkeepGasUsageWrapper1_2 is ConfirmedOwner { + AutomationRegistryExecutableInterface private immutable i_keeperRegistry; + + /** + * @param keeperRegistry address of a keeper registry + */ + constructor(AutomationRegistryExecutableInterface keeperRegistry) ConfirmedOwner(msg.sender) { + i_keeperRegistry = keeperRegistry; + } + + /** + * @return the keeper registry + */ + function getKeeperRegistry() external view returns (AutomationRegistryExecutableInterface) { + return i_keeperRegistry; + } + + /** + * @notice This function is called by monitoring service to estimate how much gas checkUpkeep functions will consume. + * @param id identifier of the upkeep to check + * @param from the address to simulate performing the upkeep from + */ + function measureCheckGas(uint256 id, address from) external returns (bool, bytes memory, uint256) { + uint256 startGas = gasleft(); + try i_keeperRegistry.checkUpkeep(id, from) returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ) { + uint256 gasUsed = startGas - gasleft(); + return (true, performData, gasUsed); + } catch { + uint256 gasUsed = startGas - gasleft(); + return (false, "", gasUsed); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol new file mode 100644 index 0000000..dbef8d7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol @@ -0,0 +1,548 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "@openzeppelin/contracts/proxy/Proxy.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "./KeeperRegistryBase1_3.sol"; +import "./KeeperRegistryLogic1_3.sol"; +import {AutomationRegistryExecutableInterface, State} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol"; +import "../interfaces/MigratableKeeperRegistryInterface.sol"; +import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Registry for adding work for Chainlink Keepers to perform on client + * contracts. Clients must support the Upkeep interface. + */ +contract KeeperRegistry1_3 is + KeeperRegistryBase1_3, + Proxy, + TypeAndVersionInterface, + AutomationRegistryExecutableInterface, + MigratableKeeperRegistryInterface, + IERC677Receiver +{ + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + + address public immutable KEEPER_REGISTRY_LOGIC; + + /** + * @notice versions: + * - KeeperRegistry 1.3.0: split contract into Proxy and Logic + * : account for Arbitrum and Optimism L1 gas fee + * : allow users to configure upkeeps + * - KeeperRegistry 1.2.0: allow funding within performUpkeep + * : allow configurable registry maxPerformGas + * : add function to let admin change upkeep gas limit + * : add minUpkeepSpend requirement + : upgrade to solidity v0.8 + * - KeeperRegistry 1.1.0: added flatFeeMicroLink + * - KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistry 1.3.0"; + + /** + * @param keeperRegistryLogic the address of keeper registry logic + * @param config registry config settings + */ + constructor( + KeeperRegistryLogic1_3 keeperRegistryLogic, + Config memory config + ) + KeeperRegistryBase1_3( + keeperRegistryLogic.PAYMENT_MODEL(), + keeperRegistryLogic.REGISTRY_GAS_OVERHEAD(), + address(keeperRegistryLogic.LINK()), + address(keeperRegistryLogic.LINK_ETH_FEED()), + address(keeperRegistryLogic.FAST_GAS_FEED()) + ) + { + KEEPER_REGISTRY_LOGIC = address(keeperRegistryLogic); + setConfig(config); + } + + // ACTIONS + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData + ) external override returns (uint256 id) { + // Executed through logic contract + _fallback(); + } + + /** + * @notice simulated by keepers via eth_call to see if the upkeep needs to be + * performed. If upkeep is needed, the call then simulates performUpkeep + * to make sure it succeeds. Finally, it returns the success status along with + * payment information and the perform data payload. + * @param id identifier of the upkeep to check + * @param from the address to simulate performing the upkeep from + */ + function checkUpkeep( + uint256 id, + address from + ) + external + override + cannotExecute + returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ) + { + // Executed through logic contract + _fallback(); + } + + /** + * @notice executes the upkeep with the perform data returned from + * checkUpkeep, validates the keeper's permissions, and pays the keeper. + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + */ + function performUpkeep( + uint256 id, + bytes calldata performData + ) external override whenNotPaused returns (bool success) { + return _performUpkeepWithParams(_generatePerformParams(msg.sender, id, performData, true)); + } + + /** + * @notice prevent an upkeep from being performed in the future + * @param id upkeep to be canceled + */ + function cancelUpkeep(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice pause an upkeep + * @param id upkeep to be paused + */ + function pauseUpkeep(uint256 id) external override { + Upkeep memory upkeep = s_upkeep[id]; + requireAdminAndNotCancelled(upkeep); + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @notice unpause an upkeep + * @param id upkeep to be resumed + */ + function unpauseUpkeep(uint256 id) external override { + Upkeep memory upkeep = s_upkeep[id]; + requireAdminAndNotCancelled(upkeep); + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @notice update the check data of an upkeep + * @param id the id of the upkeep whose check data needs to be updated + * @param newCheckData the new check data + */ + function updateCheckData(uint256 id, bytes calldata newCheckData) external override { + Upkeep memory upkeep = s_upkeep[id]; + requireAdminAndNotCancelled(upkeep); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataUpdated(id, newCheckData); + } + + /** + * @notice adds LINK funding for an upkeep by transferring from the sender's + * LINK balance + * @param id upkeep to fund + * @param amount number of LINK to transfer + */ + function addFunds(uint256 id, uint96 amount) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(LINK)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_expectedLinkBalance = s_expectedLinkBalance + amount; + + emit FundsAdded(id, sender, uint96(amount)); + } + + /** + * @notice removes funding from a canceled upkeep + * @param id upkeep to withdraw funds from + * @param to destination address for sending remaining funds + */ + function withdrawFunds(uint256 id, address to) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice withdraws LINK funds collected through cancellation fees + */ + function withdrawOwnerFunds() external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice allows the admin of an upkeep to modify gas limit + * @param id upkeep to be change the gas limit for + * @param gasLimit new gas limit for the upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice recovers LINK funds improperly transferred to the registry + * @dev In principle this function’s execution cost could exceed block + * gas limit. However, in our anticipated deployment, the number of upkeeps and + * keepers will be low enough to avoid this problem. + */ + function recoverFunds() external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice withdraws a keeper's payment, callable only by the keeper's payee + * @param from keeper address + * @param to address to send the payment to + */ + function withdrawPayment(address from, address to) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice proposes the safe transfer of a keeper's payee to another address + * @param keeper address of the keeper to transfer payee role + * @param proposed address to nominate for next payeeship + */ + function transferPayeeship(address keeper, address proposed) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice accepts the safe transfer of payee role for a keeper + * @param keeper address to accept the payee role for + */ + function acceptPayeeship(address keeper) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice proposes the safe transfer of an upkeep's admin role to another address + * @param id the upkeep id to transfer admin + * @param proposed address to nominate for the new upkeep admin + */ + function transferUpkeepAdmin(uint256 id, address proposed) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice accepts the safe transfer of admin role for an upkeep + * @param id the upkeep id + */ + function acceptUpkeepAdmin(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice signals to keepers that they should not perform upkeeps until the + * contract has been unpaused + */ + function pause() external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice signals to keepers that they can perform upkeeps once again after + * having been paused + */ + function unpause() external { + // Executed through logic contract + _fallback(); + } + + // SETTERS + + /** + * @notice updates the configuration of the registry + * @param config registry config fields + */ + function setConfig(Config memory config) public onlyOwner { + if (config.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); + s_storage = Storage({ + paymentPremiumPPB: config.paymentPremiumPPB, + flatFeeMicroLink: config.flatFeeMicroLink, + blockCountPerTurn: config.blockCountPerTurn, + checkGasLimit: config.checkGasLimit, + stalenessSeconds: config.stalenessSeconds, + gasCeilingMultiplier: config.gasCeilingMultiplier, + minUpkeepSpend: config.minUpkeepSpend, + maxPerformGas: config.maxPerformGas, + nonce: s_storage.nonce + }); + s_fallbackGasPrice = config.fallbackGasPrice; + s_fallbackLinkPrice = config.fallbackLinkPrice; + s_transcoder = config.transcoder; + s_registrar = config.registrar; + emit ConfigSet(config); + } + + /** + * @notice update the list of keepers allowed to perform upkeep + * @param keepers list of addresses allowed to perform upkeep + * @param payees addresses corresponding to keepers who are allowed to + * move payments which have been accrued + */ + function setKeepers(address[] calldata keepers, address[] calldata payees) external { + // Executed through logic contract + _fallback(); + } + + // GETTERS + + /** + * @notice read all of the details about an upkeep + */ + function getUpkeep( + uint256 id + ) + external + view + override + returns ( + address target, + uint32 executeGas, + bytes memory checkData, + uint96 balance, + address lastKeeper, + address admin, + uint64 maxValidBlocknumber, + uint96 amountSpent, + bool paused + ) + { + Upkeep memory reg = s_upkeep[id]; + return ( + reg.target, + reg.executeGas, + s_checkData[id], + reg.balance, + reg.lastKeeper, + reg.admin, + reg.maxValidBlocknumber, + reg.amountSpent, + reg.paused + ); + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { + uint256 maxIdx = s_upkeepIDs.length(); + if (startIndex >= maxIdx) revert IndexOutOfRange(); + if (maxCount == 0) { + maxCount = maxIdx - startIndex; + } + uint256[] memory ids = new uint256[](maxCount); + for (uint256 idx = 0; idx < maxCount; idx++) { + ids[idx] = s_upkeepIDs.at(startIndex + idx); + } + return ids; + } + + /** + * @notice read the current info about any keeper address + */ + function getKeeperInfo(address query) external view override returns (address payee, bool active, uint96 balance) { + KeeperInfo memory keeper = s_keeperInfo[query]; + return (keeper.payee, keeper.active, keeper.balance); + } + + /** + * @notice read the current state of the registry + */ + function getState() + external + view + override + returns (State memory state, Config memory config, address[] memory keepers) + { + Storage memory store = s_storage; + state.nonce = store.nonce; + state.ownerLinkBalance = s_ownerLinkBalance; + state.expectedLinkBalance = s_expectedLinkBalance; + state.numUpkeeps = s_upkeepIDs.length(); + config.paymentPremiumPPB = store.paymentPremiumPPB; + config.flatFeeMicroLink = store.flatFeeMicroLink; + config.blockCountPerTurn = store.blockCountPerTurn; + config.checkGasLimit = store.checkGasLimit; + config.stalenessSeconds = store.stalenessSeconds; + config.gasCeilingMultiplier = store.gasCeilingMultiplier; + config.minUpkeepSpend = store.minUpkeepSpend; + config.maxPerformGas = store.maxPerformGas; + config.fallbackGasPrice = s_fallbackGasPrice; + config.fallbackLinkPrice = s_fallbackLinkPrice; + config.transcoder = s_transcoder; + config.registrar = s_registrar; + return (state, config, s_keeperList); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { + return getMaxPaymentForGas(s_upkeep[id].executeGas); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas(uint256 gasLimit) public view returns (uint96 maxPayment) { + (uint256 fastGasWei, uint256 linkEth) = _getFeedData(); + return _calculatePaymentAmount(gasLimit, fastGasWei, linkEth, false); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice sets the peer registry migration permission + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external { + // Executed through logic contract + _fallback(); + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + UpkeepFormat public constant override upkeepTranscoderVersion = UPKEEP_TRANSCODER_VERSION_BASE; + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @dev This is the address to which proxy functions are delegated to + */ + function _implementation() internal view override returns (address) { + return KEEPER_REGISTRY_LOGIC; + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= PERFORM_GAS_CUSHION and check for underflow + if lt(g, PERFORM_GAS_CUSHION) { + revert(0, 0) + } + g := sub(g, PERFORM_GAS_CUSHION) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * keeper and the exact gas required by the Upkeep + */ + function _performUpkeepWithParams(PerformParams memory params) private nonReentrant returns (bool success) { + Upkeep memory upkeep = s_upkeep[params.id]; + if (upkeep.maxValidBlocknumber <= block.number) revert UpkeepCancelled(); + _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); + + uint256 gasUsed = gasleft(); + bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, params.performData); + success = _callWithExactGas(params.gasLimit, upkeep.target, callData); + gasUsed = gasUsed - gasleft(); + uint96 payment = _calculatePaymentAmount(gasUsed, params.fastGasWei, params.linkEth, true); + + s_upkeep[params.id].balance = s_upkeep[params.id].balance - payment; + s_upkeep[params.id].amountSpent = s_upkeep[params.id].amountSpent + payment; + s_upkeep[params.id].lastKeeper = params.from; + s_keeperInfo[params.from].balance = s_keeperInfo[params.from].balance + payment; + + emit UpkeepPerformed(params.id, success, params.from, payment, params.performData); + return success; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol new file mode 100644 index 0000000..c21f3a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol @@ -0,0 +1,304 @@ +pragma solidity 0.8.6; + +import "@openzeppelin/contracts/security/Pausable.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import "../ExecutionPrevention.sol"; +import {Config, Upkeep} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol"; +import "../../shared/access/ConfirmedOwner.sol"; +import "../../shared/interfaces/AggregatorV3Interface.sol"; +import "../../shared/interfaces/LinkTokenInterface.sol"; +import "../interfaces/KeeperCompatibleInterface.sol"; +import "../interfaces/UpkeepTranscoderInterface.sol"; + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * KeeperRegistry and KeeperRegistryLogic + */ +abstract contract KeeperRegistryBase1_3 is ConfirmedOwner, ExecutionPrevention, ReentrancyGuard, Pausable { + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint256 internal constant PERFORM_GAS_CUSHION = 5_000; + uint256 internal constant PPB_BASE = 1_000_000_000; + uint32 internal constant UINT32_MAX = type(uint32).max; + uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; + UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V2; + // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism + bytes internal constant L1_FEE_DATA_PADDING = + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + // MAX_INPUT_DATA represents the estimated max size of the sum of L1 data padding and msg.data in performUpkeep + // function, which includes 4 bytes for function selector, 32 bytes for upkeep id, 35 bytes for data padding, and + // 64 bytes for estimated perform data + bytes internal constant MAX_INPUT_DATA = + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + address[] internal s_keeperList; + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; + mapping(address => KeeperInfo) internal s_keeperInfo; + mapping(address => address) internal s_proposedPayee; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; + Storage internal s_storage; + uint256 internal s_fallbackGasPrice; // not in config object for gas savings + uint256 internal s_fallbackLinkPrice; // not in config object for gas savings + uint96 internal s_ownerLinkBalance; + uint256 internal s_expectedLinkBalance; + address internal s_transcoder; + address internal s_registrar; + + LinkTokenInterface public immutable LINK; + AggregatorV3Interface public immutable LINK_ETH_FEED; + AggregatorV3Interface public immutable FAST_GAS_FEED; + OVM_GasPriceOracle public immutable OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); + ArbGasInfo public immutable ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); + PaymentModel public immutable PAYMENT_MODEL; + uint256 public immutable REGISTRY_GAS_OVERHEAD; + + error ArrayHasNoEntries(); + error CannotCancel(); + error DuplicateEntry(); + error EmptyAddress(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IndexOutOfRange(); + error InsufficientFunds(); + error InvalidDataLength(); + error InvalidPayee(); + error InvalidRecipient(); + error KeepersMustTakeTurns(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveKeepers(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyPausedUpkeep(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error TargetCheckReverted(bytes reason); + error TranscoderNotSet(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum PaymentModel { + DEFAULT, + ARBITRUM, + OPTIMISM + } + + /** + * @notice storage of the registry, contains a mix of config and state data + */ + struct Storage { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; + uint24 blockCountPerTurn; + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; // 1 full evm word + uint32 maxPerformGas; + uint32 nonce; + } + + struct KeeperInfo { + address payee; + uint96 balance; + bool active; + } + + struct PerformParams { + address from; + uint256 id; + bytes performData; + uint256 maxLinkPayment; + uint256 gasLimit; + uint256 fastGasWei; + uint256 linkEth; + } + + event ConfigSet(Config config); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event KeepersUpdated(address[] keepers, address[] payees); + event OwnerFundsWithdrawn(uint96 amount); + event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataUpdated(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + address indexed from, + uint96 payment, + bytes performData + ); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepUnpaused(uint256 indexed id); + event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); + + /** + * @param paymentModel the payment model of default, Arbitrum, or Optimism + * @param registryGasOverhead the gas overhead used by registry in performUpkeep + * @param link address of the LINK Token + * @param linkEthFeed address of the LINK/ETH price feed + * @param fastGasFeed address of the Fast Gas price feed + */ + constructor( + PaymentModel paymentModel, + uint256 registryGasOverhead, + address link, + address linkEthFeed, + address fastGasFeed + ) ConfirmedOwner(msg.sender) { + PAYMENT_MODEL = paymentModel; + REGISTRY_GAS_OVERHEAD = registryGasOverhead; + if (ZERO_ADDRESS == link || ZERO_ADDRESS == linkEthFeed || ZERO_ADDRESS == fastGasFeed) { + revert EmptyAddress(); + } + LINK = LinkTokenInterface(link); + LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); + FAST_GAS_FEED = AggregatorV3Interface(fastGasFeed); + } + + /** + * @dev retrieves feed data for fast gas/eth and link/eth prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData() internal view returns (uint256 gasWei, uint256 linkEth) { + uint32 stalenessSeconds = s_storage.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = FAST_GAS_FEED.latestRoundData(); + if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { + linkEth = s_fallbackLinkPrice; + } else { + linkEth = uint256(feedValue); + } + return (gasWei, linkEth); + } + + /** + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @param gasLimit the amount of gas used + * @param fastGasWei the fast gas price + * @param linkEth the exchange ratio between LINK and ETH + * @param isExecution if this is triggered by a perform upkeep function + */ + function _calculatePaymentAmount( + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkEth, + bool isExecution + ) internal view returns (uint96 payment) { + Storage memory store = s_storage; + uint256 gasWei = fastGasWei * store.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (isExecution && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + + uint256 weiForGas = gasWei * (gasLimit + REGISTRY_GAS_OVERHEAD); + uint256 premium = PPB_BASE + store.paymentPremiumPPB; + uint256 l1CostWei = 0; + if (PAYMENT_MODEL == PaymentModel.OPTIMISM) { + bytes memory txCallData = new bytes(0); + if (isExecution) { + txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); + } else { + txCallData = MAX_INPUT_DATA; + } + l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); + } else if (PAYMENT_MODEL == PaymentModel.ARBITRUM) { + l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); + } + // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound + if (!isExecution) { + l1CostWei = store.gasCeilingMultiplier * l1CostWei; + } + + uint256 total = ((weiForGas + l1CostWei) * 1e9 * premium) / linkEth + uint256(store.flatFeeMicroLink) * 1e12; + if (total > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); + return uint96(total); // LINK_TOTAL_SUPPLY < UINT96_MAX + } + + /** + * @dev ensures all required checks are passed before an upkeep is performed + */ + function _prePerformUpkeep(Upkeep memory upkeep, address from, uint256 maxLinkPayment) internal view { + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + if (!s_keeperInfo[from].active) revert OnlyActiveKeepers(); + if (upkeep.balance < maxLinkPayment) revert InsufficientFunds(); + if (upkeep.lastKeeper == from) revert KeepersMustTakeTurns(); + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function requireAdminAndNotCancelled(Upkeep memory upkeep) internal view { + if (msg.sender != upkeep.admin) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } + + /** + * @dev generates a PerformParams struct for use in _performUpkeepWithParams() + */ + function _generatePerformParams( + address from, + uint256 id, + bytes memory performData, + bool isExecution + ) internal view returns (PerformParams memory) { + uint256 gasLimit = s_upkeep[id].executeGas; + (uint256 fastGasWei, uint256 linkEth) = _getFeedData(); + uint96 maxLinkPayment = _calculatePaymentAmount(gasLimit, fastGasWei, linkEth, isExecution); + + return + PerformParams({ + from: from, + id: id, + performData: performData, + maxLinkPayment: maxLinkPayment, + gasLimit: gasLimit, + fastGasWei: fastGasWei, + linkEth: linkEth + }); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol new file mode 100644 index 0000000..fd7c3af --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "./KeeperRegistryBase1_3.sol"; +import "../interfaces/MigratableKeeperRegistryInterface.sol"; +import "../interfaces/UpkeepTranscoderInterface.sol"; + +/** + * @notice Logic contract, works in tandem with KeeperRegistry as a proxy + */ +contract KeeperRegistryLogic1_3 is KeeperRegistryBase1_3 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + + /** + * @param paymentModel one of Default, Arbitrum, Optimism + * @param registryGasOverhead the gas overhead used by registry in performUpkeep + * @param link address of the LINK Token + * @param linkEthFeed address of the LINK/ETH price feed + * @param fastGasFeed address of the Fast Gas price feed + */ + constructor( + PaymentModel paymentModel, + uint256 registryGasOverhead, + address link, + address linkEthFeed, + address fastGasFeed + ) KeeperRegistryBase1_3(paymentModel, registryGasOverhead, link, linkEthFeed, fastGasFeed) {} + + function checkUpkeep( + uint256 id, + address from + ) + external + cannotExecute + returns ( + bytes memory performData, + uint256 maxLinkPayment, + uint256 gasLimit, + uint256 adjustedGasWei, + uint256 linkEth + ) + { + Upkeep memory upkeep = s_upkeep[id]; + + bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); + (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); + + if (!success) revert TargetCheckReverted(result); + + (success, performData) = abi.decode(result, (bool, bytes)); + if (!success) revert UpkeepNotNeeded(); + + PerformParams memory params = _generatePerformParams(from, id, performData, false); + _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); + + return ( + performData, + params.maxLinkPayment, + params.gasLimit, + // adjustedGasWei equals fastGasWei multiplies gasCeilingMultiplier in non-execution cases + params.fastGasWei * s_storage.gasCeilingMultiplier, + params.linkEth + ); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawOwnerFunds() external onlyOwner { + uint96 amount = s_ownerLinkBalance; + + s_expectedLinkBalance = s_expectedLinkBalance - amount; + s_ownerLinkBalance = 0; + + emit OwnerFundsWithdrawn(amount); + LINK.transfer(msg.sender, amount); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function recoverFunds() external onlyOwner { + uint256 total = LINK.balanceOf(address(this)); + LINK.transfer(msg.sender, total - s_expectedLinkBalance); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setKeepers(address[] calldata keepers, address[] calldata payees) external onlyOwner { + if (keepers.length != payees.length || keepers.length < 2) revert ParameterLengthError(); + for (uint256 i = 0; i < s_keeperList.length; i++) { + address keeper = s_keeperList[i]; + s_keeperInfo[keeper].active = false; + } + for (uint256 i = 0; i < keepers.length; i++) { + address keeper = keepers[i]; + KeeperInfo storage s_keeper = s_keeperInfo[keeper]; + address oldPayee = s_keeper.payee; + address newPayee = payees[i]; + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) revert InvalidPayee(); + if (s_keeper.active) revert DuplicateEntry(); + s_keeper.active = true; + if (newPayee != IGNORE_ADDRESS) { + s_keeper.payee = newPayee; + } + } + s_keeperList = keepers; + emit KeepersUpdated(keepers, payees); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function unpause() external onlyOwner { + _unpause(); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData + ) external returns (uint256 id) { + if (msg.sender != owner() && msg.sender != s_registrar) revert OnlyCallableByOwnerOrRegistrar(); + + id = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), s_storage.nonce))); + _createUpkeep(id, target, gasLimit, admin, 0, checkData, false); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + return id; + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; + bool isOwner = msg.sender == owner(); + + if (canceled && !(isOwner && upkeep.maxValidBlocknumber > block.number)) revert CannotCancel(); + if (!isOwner && msg.sender != upkeep.admin) revert OnlyCallableByOwnerOrAdmin(); + + uint256 height = block.number; + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minUpkeepSpend is not met + uint96 minUpkeepSpend = s_storage.minUpkeepSpend; + uint96 cancellationFee = 0; + // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) + if (upkeep.amountSpent < minUpkeepSpend) { + cancellationFee = minUpkeepSpend - upkeep.amountSpent; + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_ownerLinkBalance = s_ownerLinkBalance + cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function addFunds(uint256 id, uint96 amount) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].balance = upkeep.balance + amount; + s_expectedLinkBalance = s_expectedLinkBalance + amount; + LINK.transferFrom(msg.sender, address(this), amount); + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawFunds(uint256 id, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > block.number) revert UpkeepNotCanceled(); + + uint96 amountToWithdraw = s_upkeep[id].balance; + s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; + s_upkeep[id].balance = 0; + emit FundsWithdrawn(id, amountToWithdraw, to); + + LINK.transfer(to, amountToWithdraw); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); + + s_upkeep[id].executeGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + KeeperInfo memory keeper = s_keeperInfo[from]; + if (keeper.payee != msg.sender) revert OnlyCallableByPayee(); + + s_keeperInfo[from].balance = 0; + s_expectedLinkBalance = s_expectedLinkBalance - keeper.balance; + emit PaymentWithdrawn(from, keeper.balance, to, msg.sender); + + LINK.transfer(to, keeper.balance); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function transferPayeeship(address keeper, address proposed) external { + if (s_keeperInfo[keeper].payee != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[keeper] != proposed) { + s_proposedPayee[keeper] = proposed; + emit PayeeshipTransferRequested(keeper, msg.sender, proposed); + } + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function acceptPayeeship(address keeper) external { + if (s_proposedPayee[keeper] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_keeperInfo[keeper].payee; + s_keeperInfo[keeper].payee = msg.sender; + s_proposedPayee[keeper] = ZERO_ADDRESS; + + emit PayeeshipTransferred(keeper, past, msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + Upkeep memory upkeep = s_upkeep[id]; + requireAdminAndNotCancelled(upkeep); + if (proposed == msg.sender) revert ValueNotChanged(); + if (proposed == ZERO_ADDRESS) revert InvalidRecipient(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = upkeep.admin; + s_upkeep[id].admin = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + uint256 id; + Upkeep memory upkeep; + uint256 totalBalanceRemaining; + bytes[] memory checkDatas = new bytes[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + requireAdminAndNotCancelled(upkeep); + upkeeps[idx] = upkeep; + checkDatas[idx] = s_checkData[id]; + totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; + delete s_upkeep[id]; + delete s_checkData[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; + bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas); + MigratableKeeperRegistryInterface(destination).receiveUpkeeps( + UpkeepTranscoderInterface(s_transcoder).transcodeUpkeeps( + UPKEEP_TRANSCODER_VERSION_BASE, + MigratableKeeperRegistryInterface(destination).upkeepTranscoderVersion(), + encodedUpkeeps + ) + ); + LINK.transfer(destination, totalBalanceRemaining); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], Upkeep[], bytes[]) + ); + for (uint256 idx = 0; idx < ids.length; idx++) { + _createUpkeep( + ids[idx], + upkeeps[idx].target, + upkeeps[idx].executeGas, + upkeeps[idx].admin, + upkeeps[idx].balance, + checkDatas[idx], + upkeeps[idx].paused + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } + + /** + * @notice creates a new upkeep with the given fields + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + * @param paused if this upkeep is paused + */ + function _createUpkeep( + uint256 id, + address target, + uint32 gasLimit, + address admin, + uint96 balance, + bytes memory checkData, + bool paused + ) internal whenNotPaused { + if (!target.isContract()) revert NotAContract(); + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + s_upkeep[id] = Upkeep({ + target: target, + executeGas: gasLimit, + balance: balance, + admin: admin, + maxValidBlocknumber: UINT32_MAX, + lastKeeper: ZERO_ADDRESS, + amountSpent: 0, + paused: paused + }); + s_expectedLinkBalance = s_expectedLinkBalance + balance; + s_checkData[id] = checkData; + s_upkeepIDs.add(id); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol new file mode 100644 index 0000000..c1b7e45 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol @@ -0,0 +1,489 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "../../shared/interfaces/LinkTokenInterface.sol"; +import "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; +import "../../interfaces/TypeAndVersionInterface.sol"; +import "../../shared/access/ConfirmedOwner.sol"; +import "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Contract to accept requests for upkeep registrations + * @dev There are 2 registration workflows in this contract + * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually + * calls `approve` to register upkeep and emit events to inform UI and others interested. + * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on + * keeper registry and then emits approved event to finish the flow automatically without manual intervention. + * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. + * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. + */ +contract KeeperRegistrar2_0 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { + /** + * DISABLED: No auto approvals, all new upkeeps should be approved manually. + * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. + * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. + */ + enum AutoApproveType { + DISABLED, + ENABLED_SENDER_ALLOWLIST, + ENABLED_ALL + } + + bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; + + mapping(bytes32 => PendingRequest) private s_pendingRequests; + + LinkTokenInterface public immutable LINK; + + /** + * @notice versions: + * - KeeperRegistrar 2.0.0: Remove source from register + * Breaks our example of "Register an Upkeep using your own deployed contract" + * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve + * : Remove rate limit and add max allowed for auto approve + * - KeeperRegistrar 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistrar 2.0.0"; + + struct RegistrarConfig { + AutoApproveType autoApproveConfigType; + uint32 autoApproveMaxAllowed; + uint32 approvedCount; + AutomationRegistryBaseInterface keeperRegistry; + uint96 minLINKJuels; + } + + struct PendingRequest { + address admin; + uint96 balance; + } + + struct RegistrationParams { + string name; + bytes encryptedEmail; + address upkeepContract; + uint32 gasLimit; + address adminAddress; + bytes checkData; + bytes offchainConfig; + uint96 amount; + } + + RegistrarConfig private s_config; + // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST + mapping(address => bool) private s_autoApproveAllowedSenders; + + event RegistrationRequested( + bytes32 indexed hash, + string name, + bytes encryptedEmail, + address indexed upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes checkData, + uint96 amount + ); + + event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); + + event RegistrationRejected(bytes32 indexed hash); + + event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); + + event ConfigChanged( + AutoApproveType autoApproveConfigType, + uint32 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ); + + error InvalidAdminAddress(); + error RequestNotFound(); + error HashMismatch(); + error OnlyAdminOrOwner(); + error InsufficientPayment(); + error RegistrationRequestFailed(); + error OnlyLink(); + error AmountMismatch(); + error SenderMismatch(); + error FunctionNotPermitted(); + error LinkTransferFailed(address to); + error InvalidDataLength(); + + /* + * @param LINKAddress Address of Link token + * @param autoApproveConfigType setting for auto-approve registrations + * @param autoApproveMaxAllowed max number of registrations that can be auto approved + * @param keeperRegistry keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + */ + constructor( + address LINKAddress, + AutoApproveType autoApproveConfigType, + uint16 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(LINKAddress); + setRegistrationConfig(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); + } + + //EXTERNAL + + /** + * @notice register can only be called through transferAndCall on LINK contract + * @param name string of the upkeep to be registered + * @param encryptedEmail email address of upkeep contact + * @param upkeepContract address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when performing upkeep + * @param adminAddress address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + * @param amount quantity of LINK upkeep is funded with (specified in Juels) + * @param offchainConfig offchainConfig for upkeep in bytes + * @param sender address of the sender making the request + */ + function register( + string memory name, + bytes calldata encryptedEmail, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes calldata checkData, + bytes calldata offchainConfig, + uint96 amount, + address sender + ) external onlyLINK { + _register( + RegistrationParams({ + name: name, + encryptedEmail: encryptedEmail, + upkeepContract: upkeepContract, + gasLimit: gasLimit, + adminAddress: adminAddress, + checkData: checkData, + offchainConfig: offchainConfig, + amount: amount + }), + sender + ); + } + + /** + * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract + * @param requestParams struct of all possible registration parameters + */ + function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256) { + if (requestParams.amount < s_config.minLINKJuels) { + revert InsufficientPayment(); + } + + LINK.transferFrom(msg.sender, address(this), requestParams.amount); + + return _register(requestParams, msg.sender); + } + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function approve( + string memory name, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + bytes calldata checkData, + bytes calldata offchainConfig, + bytes32 hash + ) external onlyOwner { + PendingRequest memory request = s_pendingRequests[hash]; + if (request.admin == address(0)) { + revert RequestNotFound(); + } + bytes32 expectedHash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData, offchainConfig)); + if (hash != expectedHash) { + revert HashMismatch(); + } + delete s_pendingRequests[hash]; + _approve( + RegistrationParams({ + name: name, + encryptedEmail: "", + upkeepContract: upkeepContract, + gasLimit: gasLimit, + adminAddress: adminAddress, + checkData: checkData, + offchainConfig: offchainConfig, + amount: request.balance + }), + expectedHash + ); + } + + /** + * @notice cancel will remove a registration request and return the refunds to the request.admin + * @param hash the request hash + */ + function cancel(bytes32 hash) external { + PendingRequest memory request = s_pendingRequests[hash]; + if (!(msg.sender == request.admin || msg.sender == owner())) { + revert OnlyAdminOrOwner(); + } + if (request.admin == address(0)) { + revert RequestNotFound(); + } + delete s_pendingRequests[hash]; + bool success = LINK.transfer(request.admin, request.balance); + if (!success) { + revert LinkTransferFailed(request.admin); + } + emit RegistrationRejected(hash); + } + + /** + * @notice owner calls this function to set if registration requests should be sent directly to the Keeper Registry + * @param autoApproveConfigType setting for auto-approve registrations + * note: autoApproveAllowedSenders list persists across config changes irrespective of type + * @param autoApproveMaxAllowed max number of registrations that can be auto approved + * @param keeperRegistry new keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + */ + function setRegistrationConfig( + AutoApproveType autoApproveConfigType, + uint16 autoApproveMaxAllowed, + address keeperRegistry, + uint96 minLINKJuels + ) public onlyOwner { + uint32 approvedCount = s_config.approvedCount; + s_config = RegistrarConfig({ + autoApproveConfigType: autoApproveConfigType, + autoApproveMaxAllowed: autoApproveMaxAllowed, + approvedCount: approvedCount, + minLINKJuels: minLINKJuels, + keeperRegistry: AutomationRegistryBaseInterface(keeperRegistry) + }); + + emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); + } + + /** + * @notice owner calls this function to set allowlist status for senderAddress + * @param senderAddress senderAddress to set the allowlist status for + * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed + */ + function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { + s_autoApproveAllowedSenders[senderAddress] = allowed; + + emit AutoApproveAllowedSenderSet(senderAddress, allowed); + } + + /** + * @notice read the allowlist status of senderAddress + * @param senderAddress address to read the allowlist status for + */ + function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { + return s_autoApproveAllowedSenders[senderAddress]; + } + + /** + * @notice read the current registration configuration + */ + function getRegistrationConfig() + external + view + returns ( + AutoApproveType autoApproveConfigType, + uint32 autoApproveMaxAllowed, + uint32 approvedCount, + address keeperRegistry, + uint256 minLINKJuels + ) + { + RegistrarConfig memory config = s_config; + return ( + config.autoApproveConfigType, + config.autoApproveMaxAllowed, + config.approvedCount, + address(config.keeperRegistry), + config.minLINKJuels + ); + } + + /** + * @notice gets the admin address and the current balance of a registration request + */ + function getPendingRequest(bytes32 hash) external view returns (address, uint96) { + PendingRequest memory request = s_pendingRequests[hash]; + return (request.admin, request.balance); + } + + /** + * @notice Called when LINK is sent to the contract via `transferAndCall` + * @param sender Address of the sender transfering LINK + * @param amount Amount of LINK sent (specified in Juels) + * @param data Payload of the transaction + */ + function onTokenTransfer( + address sender, + uint256 amount, + bytes calldata data + ) + external + override + onlyLINK + permittedFunctionsForLINK(data) + isActualAmount(amount, data) + isActualSender(sender, data) + { + if (data.length < 292) revert InvalidDataLength(); + if (amount < s_config.minLINKJuels) { + revert InsufficientPayment(); + } + (bool success, ) = address(this).delegatecall(data); + // calls register + if (!success) { + revert RegistrationRequestFailed(); + } + } + + //PRIVATE + + /** + * @dev verify registration request and emit RegistrationRequested event + */ + function _register(RegistrationParams memory params, address sender) private returns (uint256) { + if (params.adminAddress == address(0)) { + revert InvalidAdminAddress(); + } + bytes32 hash = keccak256( + abi.encode(params.upkeepContract, params.gasLimit, params.adminAddress, params.checkData, params.offchainConfig) + ); + + emit RegistrationRequested( + hash, + params.name, + params.encryptedEmail, + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.checkData, + params.amount + ); + + uint256 upkeepId; + RegistrarConfig memory config = s_config; + if (_shouldAutoApprove(config, sender)) { + s_config.approvedCount = config.approvedCount + 1; + + upkeepId = _approve(params, hash); + } else { + uint96 newBalance = s_pendingRequests[hash].balance + params.amount; + s_pendingRequests[hash] = PendingRequest({admin: params.adminAddress, balance: newBalance}); + } + + return upkeepId; + } + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { + AutomationRegistryBaseInterface keeperRegistry = s_config.keeperRegistry; + + // register upkeep + uint256 upkeepId = keeperRegistry.registerUpkeep( + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.checkData, + params.offchainConfig + ); + // fund upkeep + bool success = LINK.transferAndCall(address(keeperRegistry), params.amount, abi.encode(upkeepId)); + if (!success) { + revert LinkTransferFailed(address(keeperRegistry)); + } + + emit RegistrationApproved(hash, params.name, upkeepId); + + return upkeepId; + } + + /** + * @dev verify sender allowlist if needed and check max limit + */ + function _shouldAutoApprove(RegistrarConfig memory config, address sender) private view returns (bool) { + if (config.autoApproveConfigType == AutoApproveType.DISABLED) { + return false; + } + if ( + config.autoApproveConfigType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender]) + ) { + return false; + } + if (config.approvedCount < config.autoApproveMaxAllowed) { + return true; + } + return false; + } + + //MODIFIERS + + /** + * @dev Reverts if not sent from the LINK token + */ + modifier onlyLINK() { + if (msg.sender != address(LINK)) { + revert OnlyLink(); + } + _; + } + + /** + * @dev Reverts if the given data does not begin with the `register` function selector + * @param _data The data payload of the request + */ + modifier permittedFunctionsForLINK(bytes memory _data) { + bytes4 funcSelector; + assembly { + // solhint-disable-next-line avoid-low-level-calls + funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data + } + if (funcSelector != REGISTER_REQUEST_SELECTOR) { + revert FunctionNotPermitted(); + } + _; + } + + /** + * @dev Reverts if the actual amount passed does not match the expected amount + * @param expected amount that should match the actual amount + * @param data bytes + */ + modifier isActualAmount(uint256 expected, bytes calldata data) { + // decode register function arguments to get actual amount + (, , , , , , , uint96 amount, ) = abi.decode( + data[4:], + (string, bytes, address, uint32, address, bytes, bytes, uint96, address) + ); + if (expected != amount) { + revert AmountMismatch(); + } + _; + } + + /** + * @dev Reverts if the actual sender address does not match the expected sender address + * @param expected address that should match the actual sender address + * @param data bytes + */ + modifier isActualSender(address expected, bytes calldata data) { + // decode register function arguments to get actual sender + (, , , , , , , , address sender) = abi.decode( + data[4:], + (string, bytes, address, uint32, address, bytes, bytes, uint96, address) + ); + if (expected != sender) { + revert SenderMismatch(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol new file mode 100644 index 0000000..bd3c78e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol @@ -0,0 +1,1012 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol"; +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import "./KeeperRegistryBase2_0.sol"; +import {AutomationRegistryExecutableInterface, UpkeepInfo, State, OnchainConfig, UpkeepFailureReason} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; +import "../interfaces/MigratableKeeperRegistryInterface.sol"; +import "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; +import "../../shared/interfaces/IERC677Receiver.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; + +/** + _. _|_ _ ._ _ _._|_o _ ._ o _ _ ._ _| _ __|_o._ +(_||_||_(_)| | |(_| |_|(_)| | |_> (_)|_|| (_|(/__> |_|| |\/ + / + */ +/** + * @notice Registry for adding work for Chainlink Keepers to perform on client + * contracts. Clients must support the Upkeep interface. + */ +contract KeeperRegistry2_0 is + KeeperRegistryBase2_0, + Proxy, + OCR2Abstract, + AutomationRegistryExecutableInterface, + MigratableKeeperRegistryInterface, + MigratableKeeperRegistryInterfaceV2, + IERC677Receiver +{ + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + + // Immutable address of logic contract where some functionality is delegated to + address private immutable i_keeperRegistryLogic; + + /** + * @notice versions: + * - KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts + * : fixes issue with arbitrum block number + * : does an early return in case of stale report instead of revert + * - KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X + * - KeeperRegistry 2.0.0: implement OCR interface + * - KeeperRegistry 1.3.0: split contract into Proxy and Logic + * : account for Arbitrum and Optimism L1 gas fee + * : allow users to configure upkeeps + * - KeeperRegistry 1.2.0: allow funding within performUpkeep + * : allow configurable registry maxPerformGas + * : add function to let admin change upkeep gas limit + * : add minUpkeepSpend requirement + * : upgrade to solidity v0.8 + * - KeeperRegistry 1.1.0: added flatFeeMicroLink + * - KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistry 2.0.2"; + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + + UpkeepFormat public constant override upkeepTranscoderVersion = UPKEEP_TRANSCODER_VERSION_BASE; + + /** + * @inheritdoc MigratableKeeperRegistryInterfaceV2 + */ + uint8 public constant override upkeepVersion = UPKEEP_VERSION_BASE; + + /** + * @param keeperRegistryLogic address of the logic contract + */ + constructor( + KeeperRegistryBase2_0 keeperRegistryLogic + ) + KeeperRegistryBase2_0( + keeperRegistryLogic.getMode(), + keeperRegistryLogic.getLinkAddress(), + keeperRegistryLogic.getLinkNativeFeedAddress(), + keeperRegistryLogic.getFastGasFeedAddress() + ) + { + i_keeperRegistryLogic = address(keeperRegistryLogic); + } + + //////// + // ACTIONS + //////// + + /** + * @dev This struct is used to maintain run time information about an upkeep in transmit function + * @member upkeep the upkeep struct + * @member earlyChecksPassed whether the upkeep passed early checks before perform + * @member paymentParams the paymentParams for this upkeep + * @member performSuccess whether the perform was successful + * @member gasUsed gasUsed by this upkeep in perform + */ + struct UpkeepTransmitInfo { + Upkeep upkeep; + bool earlyChecksPassed; + uint96 maxLinkPayment; + bool performSuccess; + uint256 gasUsed; + uint256 gasOverhead; + } + + /** + * @inheritdoc OCR2Abstract + */ + function transmit( + bytes32[3] calldata reportContext, + bytes calldata rawReport, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external override { + uint256 gasOverhead = gasleft(); + HotVars memory hotVars = s_hotVars; + + if (hotVars.paused) revert RegistryPaused(); + if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); + + Report memory report = _decodeReport(rawReport); + UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); + uint16 numUpkeepsPassedChecks; + + for (uint256 i = 0; i < report.upkeepIds.length; i++) { + upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]]; + + upkeepTransmitInfo[i].maxLinkPayment = _getMaxLinkPayment( + hotVars, + upkeepTransmitInfo[i].upkeep.executeGas, + uint32(report.wrappedPerformDatas[i].performData.length), + report.fastGasWei, + report.linkNative, + true + ); + upkeepTransmitInfo[i].earlyChecksPassed = _prePerformChecks( + report.upkeepIds[i], + report.wrappedPerformDatas[i], + upkeepTransmitInfo[i].upkeep, + upkeepTransmitInfo[i].maxLinkPayment + ); + + if (upkeepTransmitInfo[i].earlyChecksPassed) { + numUpkeepsPassedChecks += 1; + } + } + // No upkeeps to be performed in this report + if (numUpkeepsPassedChecks == 0) { + return; + } + + // Verify signatures + if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); + if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); + _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); + + // Actually perform upkeeps + for (uint256 i = 0; i < report.upkeepIds.length; i++) { + if (upkeepTransmitInfo[i].earlyChecksPassed) { + // Check if this upkeep was already performed in this report + if (s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber == uint32(_blockNum())) { + revert InvalidReport(); + } + + // Actually perform the target upkeep + (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( + upkeepTransmitInfo[i].upkeep, + report.wrappedPerformDatas[i].performData + ); + + // Deduct that gasUsed by upkeep from our running counter + gasOverhead -= upkeepTransmitInfo[i].gasUsed; + + // Store last perform block number for upkeep + s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber = uint32(_blockNum()); + } + } + + // 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 + gasOverhead = + (gasOverhead - gasleft() + 16 * rawReport.length) + + ACCOUNTING_FIXED_GAS_OVERHEAD + + (ACCOUNTING_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); + gasOverhead = gasOverhead / 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, + uint32(report.wrappedPerformDatas[i].performData.length), + hotVars.f + ); + + (reimbursement, premium) = _postPerformPayment( + hotVars, + report.upkeepIds[i], + upkeepTransmitInfo[i], + report.fastGasWei, + report.linkNative, + numUpkeepsPassedChecks + ); + totalPremium += premium; + totalReimbursement += reimbursement; + + emit UpkeepPerformed( + report.upkeepIds[i], + upkeepTransmitInfo[i].performSuccess, + report.wrappedPerformDatas[i].checkBlockNumber, + upkeepTransmitInfo[i].gasUsed, + upkeepTransmitInfo[i].gasOverhead, + reimbursement + premium + ); + } + } + } + // record payments + s_transmitters[msg.sender].balance += totalReimbursement; + s_hotVars.totalPremium += totalPremium; + + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + if (epoch > hotVars.latestEpoch) { + s_hotVars.latestEpoch = epoch; + } + } + + /** + * @notice simulates the upkeep with the perform data returned from + * checkUpkeep + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + */ + function simulatePerformUpkeep( + uint256 id, + bytes calldata performData + ) external cannotExecute returns (bool success, uint256 gasUsed) { + if (s_hotVars.paused) revert RegistryPaused(); + + Upkeep memory upkeep = s_upkeep[id]; + return _performUpkeep(upkeep, performData); + } + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_expectedLinkBalance = s_expectedLinkBalance + amount; + + emit FundsAdded(id, sender, uint96(amount)); + } + + //////// + // SETTERS + //////// + + /** + * @inheritdoc OCR2Abstract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override onlyOwner { + if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); + if (f == 0) revert IncorrectNumberOfFaultyOracles(); + if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); + + // move all pooled payments out of the pool to each transmitter's balance + uint96 totalPremium = s_hotVars.totalPremium; + uint96 oldLength = uint96(s_transmittersList.length); + for (uint256 i = 0; i < oldLength; i++) { + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); + } + + // remove any old signer/transmitter addresses + address signerAddress; + address transmitterAddress; + for (uint256 i = 0; i < oldLength; i++) { + signerAddress = s_signersList[i]; + transmitterAddress = s_transmittersList[i]; + delete s_signers[signerAddress]; + // Do not delete the whole transmitter struct as it has balance information stored + s_transmitters[transmitterAddress].active = false; + } + delete s_signersList; + delete s_transmittersList; + + // add new signer/transmitter addresses + { + Transmitter memory transmitter; + address temp; + for (uint256 i = 0; i < signers.length; i++) { + if (s_signers[signers[i]].active) revert RepeatedSigner(); + s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); + + temp = transmitters[i]; + transmitter = s_transmitters[temp]; + if (transmitter.active) revert RepeatedTransmitter(); + transmitter.active = true; + transmitter.index = uint8(i); + transmitter.lastCollected = totalPremium; + s_transmitters[temp] = transmitter; + } + } + s_signersList = signers; + s_transmittersList = transmitters; + + // Set the onchain config + OnchainConfig memory onchainConfigStruct = abi.decode(onchainConfig, (OnchainConfig)); + if (onchainConfigStruct.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); + if (onchainConfigStruct.maxCheckDataSize < s_storage.maxCheckDataSize) revert MaxCheckDataSizeCanOnlyIncrease(); + if (onchainConfigStruct.maxPerformDataSize < s_storage.maxPerformDataSize) + revert MaxPerformDataSizeCanOnlyIncrease(); + + s_hotVars = HotVars({ + f: f, + paymentPremiumPPB: onchainConfigStruct.paymentPremiumPPB, + flatFeeMicroLink: onchainConfigStruct.flatFeeMicroLink, + stalenessSeconds: onchainConfigStruct.stalenessSeconds, + gasCeilingMultiplier: onchainConfigStruct.gasCeilingMultiplier, + paused: false, + reentrancyGuard: false, + totalPremium: totalPremium, + latestEpoch: 0 + }); + + s_storage = Storage({ + checkGasLimit: onchainConfigStruct.checkGasLimit, + minUpkeepSpend: onchainConfigStruct.minUpkeepSpend, + maxPerformGas: onchainConfigStruct.maxPerformGas, + transcoder: onchainConfigStruct.transcoder, + registrar: onchainConfigStruct.registrar, + maxCheckDataSize: onchainConfigStruct.maxCheckDataSize, + maxPerformDataSize: onchainConfigStruct.maxPerformDataSize, + nonce: s_storage.nonce, + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + ownerLinkBalance: s_storage.ownerLinkBalance + }); + s_fallbackGasPrice = onchainConfigStruct.fallbackGasPrice; + s_fallbackLinkPrice = onchainConfigStruct.fallbackLinkPrice; + + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + s_storage.latestConfigBlockNumber = uint32(_blockNum()); + s_storage.configCount += 1; + + s_latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_storage.configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + emit ConfigSet( + previousConfigBlockNumber, + s_latestConfigDigest, + s_storage.configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + } + + //////// + // GETTERS + //////// + + /** + * @notice read all of the details about an upkeep + */ + function getUpkeep(uint256 id) external view override returns (UpkeepInfo memory upkeepInfo) { + Upkeep memory reg = s_upkeep[id]; + upkeepInfo = UpkeepInfo({ + target: reg.target, + executeGas: reg.executeGas, + checkData: s_checkData[id], + balance: reg.balance, + admin: s_upkeepAdmin[id], + maxValidBlocknumber: reg.maxValidBlocknumber, + lastPerformBlockNumber: reg.lastPerformBlockNumber, + amountSpent: reg.amountSpent, + paused: reg.paused, + offchainConfig: s_upkeepOffchainConfig[id] + }); + return upkeepInfo; + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { + uint256 maxIdx = s_upkeepIDs.length(); + if (startIndex >= maxIdx) revert IndexOutOfRange(); + if (maxCount == 0) { + maxCount = maxIdx - startIndex; + } + uint256[] memory ids = new uint256[](maxCount); + for (uint256 idx = 0; idx < maxCount; idx++) { + ids[idx] = s_upkeepIDs.at(startIndex + idx); + } + return ids; + } + + /** + * @notice read the current info about any transmitter address + */ + function getTransmitterInfo( + address query + ) external view override returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { + Transmitter memory transmitter = s_transmitters[query]; + uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; + uint96 pooledShare = totalDifference / uint96(s_transmittersList.length); + + return ( + transmitter.active, + transmitter.index, + (transmitter.balance + pooledShare), + transmitter.lastCollected, + s_transmitterPayees[query] + ); + } + + /** + * @notice read the current info about any signer address + */ + function getSignerInfo(address query) external view returns (bool active, uint8 index) { + Signer memory signer = s_signers[query]; + return (signer.active, signer.index); + } + + /** + * @notice read the current state of the registry + */ + function getState() + external + view + override + returns ( + State memory state, + OnchainConfig memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) + { + state = State({ + nonce: s_storage.nonce, + ownerLinkBalance: s_storage.ownerLinkBalance, + expectedLinkBalance: s_expectedLinkBalance, + totalPremium: s_hotVars.totalPremium, + numUpkeeps: s_upkeepIDs.length(), + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + latestConfigDigest: s_latestConfigDigest, + latestEpoch: s_hotVars.latestEpoch, + paused: s_hotVars.paused + }); + + config = OnchainConfig({ + paymentPremiumPPB: s_hotVars.paymentPremiumPPB, + flatFeeMicroLink: s_hotVars.flatFeeMicroLink, + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + minUpkeepSpend: s_storage.minUpkeepSpend, + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + transcoder: s_storage.transcoder, + registrar: s_storage.registrar + }); + + return (state, config, s_signersList, s_transmittersList, s_hotVars.f); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { + return getMaxPaymentForGas(s_upkeep[id].executeGas); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas(uint32 gasLimit) public view returns (uint96 maxPayment) { + HotVars memory hotVars = s_hotVars; + (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); + return _getMaxLinkPayment(hotVars, gasLimit, s_storage.maxPerformDataSize, fastGasWei, linkNative, false); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice retrieves the address of the logic address + */ + function getKeeperRegistryLogicAddress() external view returns (address) { + return i_keeperRegistryLogic; + } + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); + } + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDigestAndEpoch() + external + view + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (false, s_latestConfigDigest, s_hotVars.latestEpoch); + } + + //////// + // INTERNAL FUNCTIONS + //////// + + /** + * @dev This is the address to which proxy functions are delegated to + */ + function _implementation() internal view override returns (address) { + return i_keeperRegistryLogic; + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= PERFORM_GAS_CUSHION and check for underflow + if lt(g, PERFORM_GAS_CUSHION) { + revert(0, 0) + } + g := sub(g, PERFORM_GAS_CUSHION) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + /** + * @dev _decodeReport decodes a serialized report into a Report struct + */ + function _decodeReport(bytes memory rawReport) internal pure returns (Report memory) { + ( + uint256 fastGasWei, + uint256 linkNative, + uint256[] memory upkeepIds, + PerformDataWrapper[] memory wrappedPerformDatas + ) = abi.decode(rawReport, (uint256, uint256, uint256[], PerformDataWrapper[])); + if (upkeepIds.length != wrappedPerformDatas.length) revert InvalidReport(); + + return + Report({ + fastGasWei: fastGasWei, + linkNative: linkNative, + upkeepIds: upkeepIds, + wrappedPerformDatas: wrappedPerformDatas + }); + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + */ + function _prePerformChecks( + uint256 upkeepId, + PerformDataWrapper memory wrappedPerformData, + Upkeep memory upkeep, + uint96 maxLinkPayment + ) internal returns (bool) { + if (wrappedPerformData.checkBlockNumber < upkeep.lastPerformBlockNumber) { + // Can happen when another report performed this upkeep after this report was generated + emit StaleUpkeepReport(upkeepId); + return false; + } + + if (_blockHash(wrappedPerformData.checkBlockNumber) != wrappedPerformData.checkBlockhash) { + // Can happen when the block on which report was generated got reorged + // We will also revert if checkBlockNumber is older than 256 blocks. In this case we rely on a new transmission + // with the latest checkBlockNumber + emit ReorgedUpkeepReport(upkeepId); + return false; + } + + if (upkeep.maxValidBlocknumber <= _blockNum()) { + // Can happen when an upkeep got cancelled after report was generated. + // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice + emit CancelledUpkeepReport(upkeepId); + return false; + } + + if (upkeep.balance < maxLinkPayment) { + // Can happen due to flucutations in gas / link prices + emit InsufficientFundsUpkeepReport(upkeepId); + return false; + } + + return true; + } + + /** + * @dev Verify signatures attached to report + */ + function _verifyReportSignature( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) internal view { + bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount = 0; + + Signer memory signer; + address signerAddress; + for (uint256 i = 0; i < rs.length; i++) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + signer = s_signers[signerAddress]; + if (!signer.active) revert OnlyActiveSigners(); + unchecked { + signedCount += 1 << (8 * signer.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * transmitter and the exact gas required by the Upkeep + */ + function _performUpkeep( + Upkeep memory upkeep, + bytes memory performData + ) private nonReentrant returns (bool success, uint256 gasUsed) { + gasUsed = gasleft(); + bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); + success = _callWithExactGas(upkeep.executeGas, upkeep.target, callData); + gasUsed = gasUsed - gasleft(); + + return (success, gasUsed); + } + + /** + * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases + * amount spent. + */ + function _postPerformPayment( + HotVars memory hotVars, + uint256 upkeepId, + UpkeepTransmitInfo memory upkeepTransmitInfo, + uint256 fastGasWei, + uint256 linkNative, + uint16 numBatchedUpkeeps + ) internal returns (uint96 gasReimbursement, uint96 premium) { + (gasReimbursement, premium) = _calculatePaymentAmount( + hotVars, + upkeepTransmitInfo.gasUsed, + upkeepTransmitInfo.gasOverhead, + fastGasWei, + linkNative, + numBatchedUpkeeps, + true + ); + + uint96 payment = gasReimbursement + premium; + s_upkeep[upkeepId].balance -= payment; + s_upkeep[upkeepId].amountSpent += payment; + + return (gasReimbursement, premium); + } + + /** + * @dev Caps the gas overhead by the constant overhead used within initial payment checks in order to + * prevent a revert in payment processing. + */ + function _getCappedGasOverhead( + uint256 calculatedGasOverhead, + uint32 performDataLength, + uint8 f + ) private pure returns (uint256 cappedGasOverhead) { + cappedGasOverhead = _getMaxGasOverhead(performDataLength, f); + if (calculatedGasOverhead < cappedGasOverhead) { + return calculatedGasOverhead; + } + return cappedGasOverhead; + } + + //////// + // PROXY FUNCTIONS - EXECUTED THROUGH FALLBACK + //////// + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData, + bytes calldata offchainConfig + ) external override returns (uint256 id) { + // Executed through logic contract + _fallback(); + } + + /** + * @notice simulated by keepers via eth_call to see if the upkeep needs to be + * performed. It returns the success status / failure reason along with the perform data payload. + * @param id identifier of the upkeep to check + */ + function checkUpkeep( + uint256 id + ) + external + override + cannotExecute + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 fastGasWei, + uint256 linkNative + ) + { + // Executed through logic contract + _fallback(); + } + + /** + * @notice prevent an upkeep from being performed in the future + * @param id upkeep to be canceled + */ + function cancelUpkeep(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice pause an upkeep + * @param id upkeep to be paused + */ + function pauseUpkeep(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice unpause an upkeep + * @param id upkeep to be resumed + */ + function unpauseUpkeep(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice update the check data of an upkeep + * @param id the id of the upkeep whose check data needs to be updated + * @param newCheckData the new check data + */ + function updateCheckData(uint256 id, bytes calldata newCheckData) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice adds LINK funding for an upkeep by transferring from the sender's + * LINK balance + * @param id upkeep to fund + * @param amount number of LINK to transfer + */ + function addFunds(uint256 id, uint96 amount) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice removes funding from a canceled upkeep + * @param id upkeep to withdraw funds from + * @param to destination address for sending remaining funds + */ + function withdrawFunds(uint256 id, address to) external { + // Executed through logic contract + // Restricted to nonRentrant in logic contract as this is not callable from a user's performUpkeep + _fallback(); + } + + /** + * @notice allows the admin of an upkeep to modify gas limit + * @param id upkeep to be change the gas limit for + * @param gasLimit new gas limit for the upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice allows the admin of an upkeep to modify the offchain config + * @param id upkeep to be change the gas limit for + * @param config instructs oracles of offchain config preferences + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice withdraws a transmitter's payment, callable only by the transmitter's payee + * @param from transmitter address + * @param to address to send the payment to + */ + function withdrawPayment(address from, address to) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice proposes the safe transfer of a transmitter's payee to another address + * @param transmitter address of the transmitter to transfer payee role + * @param proposed address to nominate for next payeeship + */ + function transferPayeeship(address transmitter, address proposed) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice accepts the safe transfer of payee role for a transmitter + * @param transmitter address to accept the payee role for + */ + function acceptPayeeship(address transmitter) external { + // Executed through logic contract + _fallback(); + } + + /** + * @notice proposes the safe transfer of an upkeep's admin role to another address + * @param id the upkeep id to transfer admin + * @param proposed address to nominate for the new upkeep admin + */ + function transferUpkeepAdmin(uint256 id, address proposed) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @notice accepts the safe transfer of admin role for an upkeep + * @param id the upkeep id + */ + function acceptUpkeepAdmin(uint256 id) external override { + // Executed through logic contract + _fallback(); + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function migrateUpkeeps( + uint256[] calldata ids, + address destination + ) external override(MigratableKeeperRegistryInterface, MigratableKeeperRegistryInterfaceV2) { + // Executed through logic contract + _fallback(); + } + + /** + * @inheritdoc MigratableKeeperRegistryInterface + */ + function receiveUpkeeps( + bytes calldata encodedUpkeeps + ) external override(MigratableKeeperRegistryInterface, MigratableKeeperRegistryInterfaceV2) { + // Executed through logic contract + _fallback(); + } + + //////// + // OWNER RESTRICTED FUNCTIONS + //////// + + /** + * @notice recovers LINK funds improperly transferred to the registry + * @dev In principle this function’s execution cost could exceed block + * gas limit. However, in our anticipated deployment, the number of upkeeps and + * transmitters will be low enough to avoid this problem. + */ + function recoverFunds() external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } + + /** + * @notice withdraws LINK funds collected through cancellation fees + */ + function withdrawOwnerFunds() external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } + + /** + * @notice update the list of payees corresponding to the transmitters + * @param payees addresses corresponding to transmitters who are allowed to + * move payments which have been accrued + */ + function setPayees(address[] calldata payees) external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } + + /** + * @notice signals to transmitters that they should not perform upkeeps until the + * contract has been unpaused + */ + function pause() external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } + + /** + * @notice signals to transmitters that they can perform upkeeps once again after + * having been paused + */ + function unpause() external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } + + /** + * @notice sets the peer registry migration permission + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external { + // Executed through logic contract + // Restricted to onlyOwner in logic contract + _fallback(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol new file mode 100644 index 0000000..9b78e58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol @@ -0,0 +1,479 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import "../ExecutionPrevention.sol"; +import "../../shared/access/ConfirmedOwner.sol"; +import "../../shared/interfaces/AggregatorV3Interface.sol"; +import "../../shared/interfaces/LinkTokenInterface.sol"; +import "../interfaces/KeeperCompatibleInterface.sol"; +import "../interfaces/UpkeepTranscoderInterface.sol"; + +/** + * @notice relevant state of an upkeep which is used in transmit function + * @member executeGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member paused if this upkeep has been paused + * @member target the contract which needs to be serviced + * @member amountSpent the amount this upkeep has spent + * @member balance the balance of this upkeep + * @member lastPerformBlockNumber the last block number when this upkeep was performed + */ +struct Upkeep { + uint32 executeGas; + uint32 maxValidBlocknumber; + bool paused; + address target; + // 3 bytes left in 1st EVM word - not written to in transmit + uint96 amountSpent; + uint96 balance; + uint32 lastPerformBlockNumber; + // 4 bytes left in 2nd EVM word - written in transmit path +} + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * KeeperRegistry and KeeperRegistryLogic + */ +abstract contract KeeperRegistryBase2_0 is ConfirmedOwner, ExecutionPrevention { + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint256 internal constant PERFORM_GAS_CUSHION = 5_000; + uint256 internal constant PPB_BASE = 1_000_000_000; + uint32 internal constant UINT32_MAX = type(uint32).max; + uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + /** + * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with + * MigratableKeeperRegistryInterfaceV1 - it should be removed in future versions in favor of + * UPKEEP_VERSION_BASE and MigratableKeeperRegistryInterfaceV2 + */ + UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; + uint8 internal constant UPKEEP_VERSION_BASE = uint8(UpkeepFormat.V3); + // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism + bytes internal constant L1_FEE_DATA_PADDING = + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + uint256 internal constant REGISTRY_GAS_OVERHEAD = 70_000; // Used only in maxPayment estimation, not in actual payment + uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 20; // Used only in maxPayment estimation, not in actual payment. Value scales with performData length. + uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 7_500; // Used only in maxPayment estimation, not in actual payment. Value scales with f. + + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 26_900; // Used in actual payment. Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_SIGNER_GAS_OVERHEAD = 1_100; // Used in actual payment. overhead per signer + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 5_800; // Used in actual payment. overhead per upkeep performed + + OVM_GasPriceOracle internal constant OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); + ArbGasInfo internal constant ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); + ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); + + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_linkNativeFeed; + AggregatorV3Interface internal immutable i_fastGasFeed; + Mode internal immutable i_mode; + + // @dev - The storage is gas optimised for one and only function - transmit. All the storage accessed in transmit + // is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path + // Upkeep storage + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit + mapping(uint256 => address) internal s_upkeepAdmin; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + // Registry config and state + mapping(address => Transmitter) internal s_transmitters; + mapping(address => Signer) internal s_signers; + address[] internal s_signersList; // s_signersList contains the signing address of each oracle + address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle + mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. + mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter + bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification + HotVars internal s_hotVars; // Mixture of config and state, used in transmit + Storage internal s_storage; // Mixture of config and state, not used in transmit + uint256 internal s_fallbackGasPrice; + uint256 internal s_fallbackLinkPrice; + uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro + mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general configuration preferences + + error ArrayHasNoEntries(); + error CannotCancel(); + error DuplicateEntry(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IndexOutOfRange(); + error InsufficientFunds(); + error InvalidDataLength(); + error InvalidPayee(); + error InvalidRecipient(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyPausedUpkeep(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error TargetCheckReverted(bytes reason); + error TranscoderNotSet(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ConfigDigestMismatch(); + error IncorrectNumberOfSignatures(); + error OnlyActiveSigners(); + error DuplicateSigners(); + error TooManyOracles(); + error IncorrectNumberOfSigners(); + error IncorrectNumberOfFaultyOracles(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error OnchainConfigNonEmpty(); + error CheckDataExceedsLimit(); + error MaxCheckDataSizeCanOnlyIncrease(); + error MaxPerformDataSizeCanOnlyIncrease(); + error InvalidReport(); + error RegistryPaused(); + error ReentrantCall(); + error UpkeepAlreadyExists(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum Mode { + DEFAULT, + ARBITRUM, + OPTIMISM + } + + // Config + State storage struct which is on hot transmit path + struct HotVars { + uint8 f; // maximum number of faulty oracles + uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost + uint32 flatFeeMicroLink; // flat fee charged to user for every perform + uint24 stalenessSeconds; // Staleness tolerance for feeds + uint16 gasCeilingMultiplier; // multiplier on top of fast gas feed for upper bound + bool paused; // pause switch for all upkeeps in the registry + bool reentrancyGuard; // guard against reentrancy + uint96 totalPremium; // total historical payment to oracles for premium + uint32 latestEpoch; // latest epoch for which a report was transmitted + // 1 EVM word full + } + + // Config + State storage struct which is not on hot transmit path + struct Storage { + uint96 minUpkeepSpend; // Minimum amount an upkeep must spend + address transcoder; // Address of transcoder contract used in migrations + // 1 EVM word full + uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent + address registrar; // Address of registrar used to register upkeeps + // 2 EVM word full + uint32 checkGasLimit; // Gas limit allowed in checkUpkeep + uint32 maxPerformGas; // Max gas an upkeep can use on this registry + uint32 nonce; // Nonce for each upkeep created + uint32 configCount; // incremented each time a new config is posted, The count + // is incorporated into the config digest to prevent replay attacks. + uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs + uint32 maxCheckDataSize; // max length of checkData bytes + uint32 maxPerformDataSize; // max length of performData bytes + // 4 bytes to 3rd EVM word + } + + struct Transmitter { + bool active; + uint8 index; // Index of oracle in s_signersList/s_transmittersList + uint96 balance; + uint96 lastCollected; + } + + struct Signer { + bool active; + // Index of oracle in s_signersList/s_transmittersList + uint8 index; + } + + // This struct is used to pack information about the user's check function + struct PerformDataWrapper { + uint32 checkBlockNumber; // Block number-1 on which check was simulated + bytes32 checkBlockhash; // blockhash of checkBlockNumber. Used for reorg protection + bytes performData; // actual performData that user's check returned + } + + // Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkNative; + uint256[] upkeepIds; // Ids of upkeeps + PerformDataWrapper[] wrappedPerformDatas; // Contains checkInfo and performData for the corresponding upkeeps + } + + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event OwnerFundsWithdrawn(uint96 amount); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataUpdated(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint32 checkBlockNumber, + uint256 gasUsed, + uint256 gasOverhead, + uint96 totalPayment + ); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepUnpaused(uint256 indexed id); + event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); + event StaleUpkeepReport(uint256 indexed id); + event ReorgedUpkeepReport(uint256 indexed id); + event InsufficientFundsUpkeepReport(uint256 indexed id); + event CancelledUpkeepReport(uint256 indexed id); + event Paused(address account); + event Unpaused(address account); + + /** + * @param mode the contract mode of default, Arbitrum, or Optimism + * @param link address of the LINK Token + * @param linkNativeFeed address of the LINK/Native price feed + * @param fastGasFeed address of the Fast Gas price feed + */ + constructor(Mode mode, address link, address linkNativeFeed, address fastGasFeed) ConfirmedOwner(msg.sender) { + i_mode = mode; + i_link = LinkTokenInterface(link); + i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); + i_fastGasFeed = AggregatorV3Interface(fastGasFeed); + } + + //////// + // GETTERS + //////// + + function getMode() external view returns (Mode) { + return i_mode; + } + + function getLinkAddress() external view returns (address) { + return address(i_link); + } + + function getLinkNativeFeedAddress() external view returns (address) { + return address(i_linkNativeFeed); + } + + function getFastGasFeedAddress() external view returns (address) { + return address(i_fastGasFeed); + } + + //////// + // INTERNAL + //////// + + /** + * @dev retrieves feed data for fast gas/native and link/native prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { + uint32 stalenessSeconds = hotVars.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + linkNative = s_fallbackLinkPrice; + } else { + linkNative = uint256(feedValue); + } + return (gasWei, linkNative); + } + + /** + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @param gasLimit the amount of gas used + * @param gasOverhead the amount of gas overhead + * @param fastGasWei the fast gas price + * @param linkNative the exchange ratio between LINK and Native token + * @param numBatchedUpkeeps the number of upkeeps in this batch. Used to divide the L1 cost + * @param isExecution if this is triggered by a perform upkeep function + */ + function _calculatePaymentAmount( + HotVars memory hotVars, + uint256 gasLimit, + uint256 gasOverhead, + uint256 fastGasWei, + uint256 linkNative, + uint16 numBatchedUpkeeps, + bool isExecution + ) internal view returns (uint96, uint96) { + uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (isExecution && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + + uint256 l1CostWei = 0; + if (i_mode == Mode.OPTIMISM) { + bytes memory txCallData = new bytes(0); + if (isExecution) { + txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); + } else { + // @dev fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have + // s_storage.maxPerformDataSize non zero-bytes. Instead of setting bytes to non-zero + // we initialize 'new bytes' of length 4*maxPerformDataSize to cover for zero bytes. + txCallData = new bytes(4 * s_storage.maxPerformDataSize); + } + l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); + } else if (i_mode == Mode.ARBITRUM) { + l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); + } + // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound + if (!isExecution) { + l1CostWei = hotVars.gasCeilingMultiplier * l1CostWei; + } + // Divide l1CostWei among all batched upkeeps. Spare change from division is not charged + l1CostWei = l1CostWei / numBatchedUpkeeps; + + uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; + uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / + linkNative + + uint256(hotVars.flatFeeMicroLink) * + 1e12; + // LINK_TOTAL_SUPPLY < UINT96_MAX + if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); + return (uint96(gasPayment), uint96(premium)); + } + + /** + * @dev generates the max link payment for an upkeep + */ + function _getMaxLinkPayment( + HotVars memory hotVars, + uint32 executeGas, + uint32 performDataLength, + uint256 fastGasWei, + uint256 linkNative, + bool isExecution // Whether this is an actual perform execution or just a simulation + ) internal view returns (uint96) { + uint256 gasOverhead = _getMaxGasOverhead(performDataLength, hotVars.f); + (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( + hotVars, + executeGas, + gasOverhead, + fastGasWei, + linkNative, + 1, // Consider only 1 upkeep in batch to get maxPayment + isExecution + ); + + return reimbursement + premium; + } + + /** + * @dev returns the max gas overhead that can be charged for an upkeep + */ + function _getMaxGasOverhead(uint32 performDataLength, uint8 f) internal pure returns (uint256) { + // performData causes additional overhead in report length and memory operations + return + REGISTRY_GAS_OVERHEAD + + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (f + 1)) + + (REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD * performDataLength); + } + + /** + * @dev move a transmitter's balance from total pool to withdrawable balance + */ + function _updateTransmitterBalanceFromPool( + address transmitterAddress, + uint96 totalPremium, + uint96 payeeCount + ) internal returns (uint96) { + Transmitter memory transmitter = s_transmitters[transmitterAddress]; + + uint96 uncollected = totalPremium - transmitter.lastCollected; + uint96 due = uncollected / payeeCount; + transmitter.balance += due; + transmitter.lastCollected = totalPremium; + + // Transfer spare change to owner + s_storage.ownerLinkBalance += (uncollected - due * payeeCount); + s_transmitters[transmitterAddress] = transmitter; + + return transmitter.balance; + } + + /** + * @notice returns the current block number in a chain agnostic manner + */ + function _blockNum() internal view returns (uint256) { + if (i_mode == Mode.ARBITRUM) { + return ARB_SYS.arbBlockNumber(); + } else { + return block.number; + } + } + + /** + * @notice returns the blockhash of the provided block number in a chain agnostic manner + * @param n the blocknumber to retrieve the blockhash for + * @return blockhash the blockhash of block number n, or 0 if n is out queryable of range + */ + function _blockHash(uint256 n) internal view returns (bytes32) { + if (i_mode == Mode.ARBITRUM) { + uint256 blockNum = ARB_SYS.arbBlockNumber(); + if (n >= blockNum || blockNum - n > 256) { + return ""; + } + return ARB_SYS.arbBlockHash(n); + } else { + return blockhash(n); + } + } + + /** + * @notice replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage + */ + modifier nonReentrant() { + if (s_hotVars.reentrancyGuard) revert ReentrantCall(); + s_hotVars.reentrancyGuard = true; + _; + s_hotVars.reentrancyGuard = false; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol new file mode 100644 index 0000000..7eacc3c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import "./KeeperRegistryBase2_0.sol"; +import {UpkeepFailureReason} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; +import "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; +import "../interfaces/UpkeepTranscoderInterfaceV2.sol"; + +/** + * @notice Logic contract, works in tandem with KeeperRegistry as a proxy + */ +contract KeeperRegistryLogic2_0 is KeeperRegistryBase2_0 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + + /** + * @param mode one of Default, Arbitrum, Optimism + * @param link address of the LINK Token + * @param linkNativeFeed address of the LINK/Native price feed + * @param fastGasFeed address of the Fast Gas price feed + */ + constructor( + Mode mode, + address link, + address linkNativeFeed, + address fastGasFeed + ) KeeperRegistryBase2_0(mode, link, linkNativeFeed, fastGasFeed) {} + + function checkUpkeep( + uint256 id + ) + external + cannotExecute + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 fastGasWei, + uint256 linkNative + ) + { + HotVars memory hotVars = s_hotVars; + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, gasUsed, 0, 0); + if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, gasUsed, 0, 0); + + (fastGasWei, linkNative) = _getFeedData(hotVars); + uint96 maxLinkPayment = _getMaxLinkPayment( + hotVars, + upkeep.executeGas, + s_storage.maxPerformDataSize, + fastGasWei, + linkNative, + false + ); + if (upkeep.balance < maxLinkPayment) + return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, gasUsed, fastGasWei, linkNative); + + gasUsed = gasleft(); + bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); + (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); + gasUsed = gasUsed - gasleft(); + + if (!success) { + upkeepFailureReason = UpkeepFailureReason.TARGET_CHECK_REVERTED; + } else { + (upkeepNeeded, result) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, fastGasWei, linkNative); + if (result.length > s_storage.maxPerformDataSize) + return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed, fastGasWei, linkNative); + } + + performData = abi.encode( + PerformDataWrapper({ + checkBlockNumber: uint32(_blockNum() - 1), + checkBlockhash: _blockHash(_blockNum() - 1), + performData: result + }) + ); + + return (success, performData, upkeepFailureReason, gasUsed, fastGasWei, linkNative); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawOwnerFunds() external onlyOwner { + uint96 amount = s_storage.ownerLinkBalance; + + s_expectedLinkBalance = s_expectedLinkBalance - amount; + s_storage.ownerLinkBalance = 0; + + emit OwnerFundsWithdrawn(amount); + i_link.transfer(msg.sender, amount); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function recoverFunds() external onlyOwner { + uint256 total = i_link.balanceOf(address(this)); + i_link.transfer(msg.sender, total - s_expectedLinkBalance); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setPayees(address[] calldata payees) external onlyOwner { + if (s_transmittersList.length != payees.length) revert ParameterLengthError(); + for (uint256 i = 0; i < s_transmittersList.length; i++) { + address transmitter = s_transmittersList[i]; + address oldPayee = s_transmitterPayees[transmitter]; + address newPayee = payees[i]; + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) revert InvalidPayee(); + if (newPayee != IGNORE_ADDRESS) { + s_transmitterPayees[transmitter] = newPayee; + } + } + emit PayeesUpdated(s_transmittersList, payees); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function pause() external onlyOwner { + s_hotVars.paused = true; + + emit Paused(msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function unpause() external onlyOwner { + s_hotVars.paused = false; + + emit Unpaused(msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData, + bytes calldata offchainConfig + ) external returns (uint256 id) { + if (msg.sender != owner() && msg.sender != s_storage.registrar) revert OnlyCallableByOwnerOrRegistrar(); + + id = uint256(keccak256(abi.encode(_blockHash(_blockNum() - 1), address(this), s_storage.nonce))); + _createUpkeep(id, target, gasLimit, admin, 0, checkData, false); + s_storage.nonce++; + s_upkeepOffchainConfig[id] = offchainConfig; + emit UpkeepRegistered(id, gasLimit, admin); + return id; + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; + bool isOwner = msg.sender == owner(); + + if (canceled && !(isOwner && upkeep.maxValidBlocknumber > _blockNum())) revert CannotCancel(); + if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); + + uint256 height = _blockNum(); + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minUpkeepSpend is not met + uint96 minUpkeepSpend = s_storage.minUpkeepSpend; + uint96 cancellationFee = 0; + // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) + if (upkeep.amountSpent < minUpkeepSpend) { + cancellationFee = minUpkeepSpend - upkeep.amountSpent; + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function addFunds(uint256 id, uint96 amount) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].balance = upkeep.balance + amount; + s_expectedLinkBalance = s_expectedLinkBalance + amount; + i_link.transferFrom(msg.sender, address(this), amount); + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawFunds(uint256 id, address to) external nonReentrant { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > _blockNum()) revert UpkeepNotCanceled(); + + uint96 amountToWithdraw = s_upkeep[id].balance; + s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; + s_upkeep[id].balance = 0; + i_link.transfer(to, amountToWithdraw); + emit FundsWithdrawn(id, amountToWithdraw, to); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + _requireAdminAndNotCancelled(id); + s_upkeep[id].executeGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { + _requireAdminAndNotCancelled(id); + + s_upkeepOffchainConfig[id] = config; + + emit UpkeepOffchainConfigSet(id, config); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); + + uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); + s_transmitters[from].balance = 0; + s_expectedLinkBalance = s_expectedLinkBalance - balance; + + i_link.transfer(to, balance); + + emit PaymentWithdrawn(from, balance, to, msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function transferPayeeship(address transmitter, address proposed) external { + if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[transmitter] != proposed) { + s_proposedPayee[transmitter] = proposed; + emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); + } + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function acceptPayeeship(address transmitter) external { + if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_transmitterPayees[transmitter]; + s_transmitterPayees[transmitter] = msg.sender; + s_proposedPayee[transmitter] = ZERO_ADDRESS; + + emit PayeeshipTransferred(transmitter, past, msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + _requireAdminAndNotCancelled(id); + if (proposed == msg.sender) revert ValueNotChanged(); + if (proposed == ZERO_ADDRESS) revert InvalidRecipient(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = s_upkeepAdmin[id]; + s_upkeepAdmin[id] = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function pauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function unpauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function updateCheckData(uint256 id, bytes calldata newCheckData) external { + _requireAdminAndNotCancelled(id); + if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataUpdated(id, newCheckData); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + uint256 id; + Upkeep memory upkeep; + uint256 totalBalanceRemaining; + bytes[] memory checkDatas = new bytes[](ids.length); + address[] memory admins = new address[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + _requireAdminAndNotCancelled(id); + upkeeps[idx] = upkeep; + checkDatas[idx] = s_checkData[id]; + admins[idx] = s_upkeepAdmin[id]; + totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; + delete s_upkeep[id]; + delete s_checkData[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; + bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas, admins); + MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( + UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( + UPKEEP_VERSION_BASE, + MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), + encodedUpkeeps + ) + ); + i_link.transfer(destination, totalBalanceRemaining); + } + + /** + * @dev Called through KeeperRegistry main contract + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas, address[] memory upkeepAdmins) = abi + .decode(encodedUpkeeps, (uint256[], Upkeep[], bytes[], address[])); + for (uint256 idx = 0; idx < ids.length; idx++) { + _createUpkeep( + ids[idx], + upkeeps[idx].target, + upkeeps[idx].executeGas, + upkeepAdmins[idx], + upkeeps[idx].balance, + checkDatas[idx], + upkeeps[idx].paused + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } + + /** + * @notice creates a new upkeep with the given fields + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data passed to the contract when checking for upkeep + * @param paused if this upkeep is paused + */ + function _createUpkeep( + uint256 id, + address target, + uint32 gasLimit, + address admin, + uint96 balance, + bytes memory checkData, + bool paused + ) internal { + if (s_hotVars.paused) revert RegistryPaused(); + if (!target.isContract()) revert NotAContract(); + if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + if (s_upkeep[id].target != address(0)) revert UpkeepAlreadyExists(); + s_upkeep[id] = Upkeep({ + target: target, + executeGas: gasLimit, + balance: balance, + maxValidBlocknumber: UINT32_MAX, + lastPerformBlockNumber: 0, + amountSpent: 0, + paused: paused + }); + s_upkeepAdmin[id] = admin; + s_expectedLinkBalance = s_expectedLinkBalance + balance; + s_checkData[id] = checkData; + s_upkeepIDs.add(id); + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { + if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); + if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol new file mode 100644 index 0000000..0a56f20 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import "../../automation/interfaces/UpkeepTranscoderInterface.sol"; +import "../../interfaces/TypeAndVersionInterface.sol"; +import {Upkeep as UpkeepV1} from "../../automation/v1_2/KeeperRegistry1_2.sol"; +import {Upkeep as UpkeepV2} from "../../automation/v1_3/KeeperRegistryBase1_3.sol"; +import {Upkeep as UpkeepV3} from "../../automation/v2_0/KeeperRegistryBase2_0.sol"; +import "../../automation/UpkeepFormat.sol"; + +/** + * @notice UpkeepTranscoder 3_0 allows converting upkeep data from previous keeper registry versions 1.2 and 1.3 to + * registry 2.0 + */ +contract UpkeepTranscoder3_0 is UpkeepTranscoderInterface, TypeAndVersionInterface { + error InvalidTranscoding(); + + /** + * @notice versions: + * - UpkeepTranscoder 3.0.0: version 3.0.0 works with registry 2.0; adds temporary workaround for UpkeepFormat enum bug + */ + string public constant override typeAndVersion = "UpkeepTranscoder 3.0.0"; + uint32 internal constant UINT32_MAX = type(uint32).max; + + /** + * @notice transcodeUpkeeps transforms upkeep data from the format expected by + * one registry to the format expected by another. It future-proofs migrations + * by allowing keepers team to customize migration paths and set sensible defaults + * when new fields are added + * @param fromVersion struct version the upkeep is migrating from + * @param encodedUpkeeps encoded upkeep data + * @dev this transcoder should ONLY be use for V1/V2 --> V3 migrations + * @dev this transcoder **ignores** the toVersion param, as it assumes all migrations are + * for the V3 version. Therefore, it is the responsibility of the deployer of this contract + * to ensure it is not used in any other migration paths. + */ + function transcodeUpkeeps( + UpkeepFormat fromVersion, + UpkeepFormat, + bytes calldata encodedUpkeeps + ) external view override returns (bytes memory) { + // this transcoder only handles upkeep V1/V2 to V3, all other formats are invalid. + if (fromVersion == UpkeepFormat.V1) { + (uint256[] memory ids, UpkeepV1[] memory upkeepsV1, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], UpkeepV1[], bytes[]) + ); + + if (ids.length != upkeepsV1.length || ids.length != checkDatas.length) { + revert InvalidTranscoding(); + } + + address[] memory admins = new address[](ids.length); + UpkeepV3[] memory newUpkeeps = new UpkeepV3[](ids.length); + UpkeepV1 memory upkeepV1; + for (uint256 idx = 0; idx < ids.length; idx++) { + upkeepV1 = upkeepsV1[idx]; + newUpkeeps[idx] = UpkeepV3({ + executeGas: upkeepV1.executeGas, + maxValidBlocknumber: UINT32_MAX, // maxValidBlocknumber is uint64 in V1, hence a new default value is provided + paused: false, // migrated upkeeps are not paused by default + target: upkeepV1.target, + amountSpent: upkeepV1.amountSpent, + balance: upkeepV1.balance, + lastPerformBlockNumber: 0 + }); + admins[idx] = upkeepV1.admin; + } + return abi.encode(ids, newUpkeeps, checkDatas, admins); + } + + if (fromVersion == UpkeepFormat.V2) { + (uint256[] memory ids, UpkeepV2[] memory upkeepsV2, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], UpkeepV2[], bytes[]) + ); + + if (ids.length != upkeepsV2.length || ids.length != checkDatas.length) { + revert InvalidTranscoding(); + } + + address[] memory admins = new address[](ids.length); + UpkeepV3[] memory newUpkeeps = new UpkeepV3[](ids.length); + UpkeepV2 memory upkeepV2; + for (uint256 idx = 0; idx < ids.length; idx++) { + upkeepV2 = upkeepsV2[idx]; + newUpkeeps[idx] = UpkeepV3({ + executeGas: upkeepV2.executeGas, + maxValidBlocknumber: upkeepV2.maxValidBlocknumber, + paused: upkeepV2.paused, + target: upkeepV2.target, + amountSpent: upkeepV2.amountSpent, + balance: upkeepV2.balance, + lastPerformBlockNumber: 0 + }); + admins[idx] = upkeepV2.admin; + } + return abi.encode(ids, newUpkeeps, checkDatas, admins); + } + + revert InvalidTranscoding(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol new file mode 100644 index 0000000..407dda2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol @@ -0,0 +1,532 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {IKeeperRegistryMaster} from "../interfaces/v2_1/IKeeperRegistryMaster.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Contract to accept requests for upkeep registrations + * @dev There are 2 registration workflows in this contract + * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually + * calls `approve` to register upkeep and emit events to inform UI and others interested. + * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on + * keeper registry and then emits approved event to finish the flow automatically without manual intervention. + * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. + * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. + */ +contract AutomationRegistrar2_1 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { + /** + * DISABLED: No auto approvals, all new upkeeps should be approved manually. + * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. + * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. + */ + enum AutoApproveType { + DISABLED, + ENABLED_SENDER_ALLOWLIST, + ENABLED_ALL + } + + bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; + + mapping(bytes32 => PendingRequest) private s_pendingRequests; + mapping(uint8 => TriggerRegistrationStorage) private s_triggerRegistrations; + + LinkTokenInterface public immutable LINK; + + /** + * @notice versions: + * - KeeperRegistrar 2.1.0: Update for compatability with registry 2.1.0 + * Add auto approval levels by type + * - KeeperRegistrar 2.0.0: Remove source from register + * Breaks our example of "Register an Upkeep using your own deployed contract" + * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve + * : Remove rate limit and add max allowed for auto approve + * - KeeperRegistrar 1.0.0: initial release + */ + string public constant override typeAndVersion = "AutomationRegistrar 2.1.0"; + + /** + * @notice TriggerRegistrationStorage stores the auto-approval levels for upkeeps by type + * @member autoApproveType the auto approval setting (see enum) + * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + * @member approvedCount the count of upkeeps auto approved of this type + */ + struct TriggerRegistrationStorage { + AutoApproveType autoApproveType; + uint32 autoApproveMaxAllowed; + uint32 approvedCount; + } + + /** + * @notice InitialTriggerConfig configures the auto-approval levels for upkeeps by trigger type + * @dev this struct is only used in the constructor to set the initial values for various trigger configs + * @member triggerType the upkeep type to configure + * @member autoApproveType the auto approval setting (see enum) + * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + */ + struct InitialTriggerConfig { + uint8 triggerType; + AutoApproveType autoApproveType; + uint32 autoApproveMaxAllowed; + } + + struct RegistrarConfig { + IKeeperRegistryMaster keeperRegistry; + uint96 minLINKJuels; + } + + struct PendingRequest { + address admin; + uint96 balance; + } + + struct RegistrationParams { + string name; + bytes encryptedEmail; + address upkeepContract; + uint32 gasLimit; + address adminAddress; + uint8 triggerType; + bytes checkData; + bytes triggerConfig; + bytes offchainConfig; + uint96 amount; + } + + RegistrarConfig private s_config; + // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST + mapping(address => bool) private s_autoApproveAllowedSenders; + + event RegistrationRequested( + bytes32 indexed hash, + string name, + bytes encryptedEmail, + address indexed upkeepContract, + uint32 gasLimit, + address adminAddress, + uint8 triggerType, + bytes triggerConfig, + bytes offchainConfig, + bytes checkData, + uint96 amount + ); + + event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); + + event RegistrationRejected(bytes32 indexed hash); + + event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); + + event ConfigChanged(address keeperRegistry, uint96 minLINKJuels); + + event TriggerConfigSet(uint8 triggerType, AutoApproveType autoApproveType, uint32 autoApproveMaxAllowed); + + error InvalidAdminAddress(); + error RequestNotFound(); + error HashMismatch(); + error OnlyAdminOrOwner(); + error InsufficientPayment(); + error RegistrationRequestFailed(); + error OnlyLink(); + error AmountMismatch(); + error SenderMismatch(); + error FunctionNotPermitted(); + error LinkTransferFailed(address to); + error InvalidDataLength(); + + /** + * @param LINKAddress Address of Link token + * @param keeperRegistry keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + * @param triggerConfigs the initial config for individual triggers + */ + constructor( + address LINKAddress, + address keeperRegistry, + uint96 minLINKJuels, + InitialTriggerConfig[] memory triggerConfigs + ) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(LINKAddress); + setConfig(keeperRegistry, minLINKJuels); + for (uint256 idx = 0; idx < triggerConfigs.length; idx++) { + setTriggerConfig( + triggerConfigs[idx].triggerType, + triggerConfigs[idx].autoApproveType, + triggerConfigs[idx].autoApproveMaxAllowed + ); + } + } + + //EXTERNAL + + /** + * @notice register can only be called through transferAndCall on LINK contract + * @param name string of the upkeep to be registered + * @param encryptedEmail email address of upkeep contact + * @param upkeepContract address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when performing upkeep + * @param adminAddress address to cancel upkeep and withdraw remaining funds + * @param triggerType the type of trigger for the upkeep + * @param checkData data passed to the contract when checking for upkeep + * @param triggerConfig the config for the trigger + * @param offchainConfig offchainConfig for upkeep in bytes + * @param amount quantity of LINK upkeep is funded with (specified in Juels) + * @param sender address of the sender making the request + */ + function register( + string memory name, + bytes calldata encryptedEmail, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + uint8 triggerType, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig, + uint96 amount, + address sender + ) external onlyLINK { + _register( + RegistrationParams({ + name: name, + encryptedEmail: encryptedEmail, + upkeepContract: upkeepContract, + gasLimit: gasLimit, + adminAddress: adminAddress, + triggerType: triggerType, + checkData: checkData, + triggerConfig: triggerConfig, + offchainConfig: offchainConfig, + amount: amount + }), + sender + ); + } + + /** + * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract + * @param requestParams struct of all possible registration parameters + */ + function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256) { + if (requestParams.amount < s_config.minLINKJuels) { + revert InsufficientPayment(); + } + + LINK.transferFrom(msg.sender, address(this), requestParams.amount); + + return _register(requestParams, msg.sender); + } + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function approve( + string memory name, + address upkeepContract, + uint32 gasLimit, + address adminAddress, + uint8 triggerType, + bytes calldata checkData, + bytes memory triggerConfig, + bytes calldata offchainConfig, + bytes32 hash + ) external onlyOwner { + PendingRequest memory request = s_pendingRequests[hash]; + if (request.admin == address(0)) { + revert RequestNotFound(); + } + bytes32 expectedHash = keccak256( + abi.encode(upkeepContract, gasLimit, adminAddress, triggerType, checkData, triggerConfig, offchainConfig) + ); + if (hash != expectedHash) { + revert HashMismatch(); + } + delete s_pendingRequests[hash]; + _approve( + RegistrationParams({ + name: name, + encryptedEmail: "", + upkeepContract: upkeepContract, + gasLimit: gasLimit, + adminAddress: adminAddress, + triggerType: triggerType, + checkData: checkData, + triggerConfig: triggerConfig, + offchainConfig: offchainConfig, + amount: request.balance + }), + expectedHash + ); + } + + /** + * @notice cancel will remove a registration request and return the refunds to the request.admin + * @param hash the request hash + */ + function cancel(bytes32 hash) external { + PendingRequest memory request = s_pendingRequests[hash]; + if (!(msg.sender == request.admin || msg.sender == owner())) { + revert OnlyAdminOrOwner(); + } + if (request.admin == address(0)) { + revert RequestNotFound(); + } + delete s_pendingRequests[hash]; + bool success = LINK.transfer(request.admin, request.balance); + if (!success) { + revert LinkTransferFailed(request.admin); + } + emit RegistrationRejected(hash); + } + + /** + * @notice owner calls this function to set contract config + * @param keeperRegistry new keeper registry address + * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with + */ + function setConfig(address keeperRegistry, uint96 minLINKJuels) public onlyOwner { + s_config = RegistrarConfig({minLINKJuels: minLINKJuels, keeperRegistry: IKeeperRegistryMaster(keeperRegistry)}); + emit ConfigChanged(keeperRegistry, minLINKJuels); + } + + /** + * @notice owner calls to set the config for this upkeep type + * @param triggerType the upkeep type to configure + * @param autoApproveType the auto approval setting (see enum) + * @param autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + */ + function setTriggerConfig( + uint8 triggerType, + AutoApproveType autoApproveType, + uint32 autoApproveMaxAllowed + ) public onlyOwner { + s_triggerRegistrations[triggerType].autoApproveType = autoApproveType; + s_triggerRegistrations[triggerType].autoApproveMaxAllowed = autoApproveMaxAllowed; + emit TriggerConfigSet(triggerType, autoApproveType, autoApproveMaxAllowed); + } + + /** + * @notice owner calls this function to set allowlist status for senderAddress + * @param senderAddress senderAddress to set the allowlist status for + * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed + */ + function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { + s_autoApproveAllowedSenders[senderAddress] = allowed; + + emit AutoApproveAllowedSenderSet(senderAddress, allowed); + } + + /** + * @notice read the allowlist status of senderAddress + * @param senderAddress address to read the allowlist status for + */ + function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { + return s_autoApproveAllowedSenders[senderAddress]; + } + + /** + * @notice read the current registration configuration + */ + function getConfig() external view returns (address keeperRegistry, uint256 minLINKJuels) { + RegistrarConfig memory config = s_config; + return (address(config.keeperRegistry), config.minLINKJuels); + } + + /** + * @notice read the config for this upkeep type + * @param triggerType upkeep type to read config for + */ + function getTriggerRegistrationDetails(uint8 triggerType) external view returns (TriggerRegistrationStorage memory) { + return s_triggerRegistrations[triggerType]; + } + + /** + * @notice gets the admin address and the current balance of a registration request + */ + function getPendingRequest(bytes32 hash) external view returns (address, uint96) { + PendingRequest memory request = s_pendingRequests[hash]; + return (request.admin, request.balance); + } + + /** + * @notice Called when LINK is sent to the contract via `transferAndCall` + * @param sender Address of the sender transfering LINK + * @param amount Amount of LINK sent (specified in Juels) + * @param data Payload of the transaction + */ + function onTokenTransfer( + address sender, + uint256 amount, + bytes calldata data + ) + external + override + onlyLINK + permittedFunctionsForLINK(data) + isActualAmount(amount, data) + isActualSender(sender, data) + { + if (amount < s_config.minLINKJuels) { + revert InsufficientPayment(); + } + (bool success, ) = address(this).delegatecall(data); + // calls register + if (!success) { + revert RegistrationRequestFailed(); + } + } + + // ================================================================ + // | PRIVATE | + // ================================================================ + + /** + * @dev verify registration request and emit RegistrationRequested event + */ + function _register(RegistrationParams memory params, address sender) private returns (uint256) { + if (params.adminAddress == address(0)) { + revert InvalidAdminAddress(); + } + bytes32 hash = keccak256( + abi.encode( + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.triggerType, + params.checkData, + params.triggerConfig, + params.offchainConfig + ) + ); + + emit RegistrationRequested( + hash, + params.name, + params.encryptedEmail, + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.triggerType, + params.triggerConfig, + params.offchainConfig, + params.checkData, + params.amount + ); + + uint256 upkeepId; + if (_shouldAutoApprove(s_triggerRegistrations[params.triggerType], sender)) { + s_triggerRegistrations[params.triggerType].approvedCount++; + upkeepId = _approve(params, hash); + } else { + uint96 newBalance = s_pendingRequests[hash].balance + params.amount; + s_pendingRequests[hash] = PendingRequest({admin: params.adminAddress, balance: newBalance}); + } + + return upkeepId; + } + + /** + * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event + */ + function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { + IKeeperRegistryMaster keeperRegistry = s_config.keeperRegistry; + uint256 upkeepId = keeperRegistry.registerUpkeep( + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.triggerType, + params.checkData, + params.triggerConfig, + params.offchainConfig + ); + bool success = LINK.transferAndCall(address(keeperRegistry), params.amount, abi.encode(upkeepId)); + if (!success) { + revert LinkTransferFailed(address(keeperRegistry)); + } + emit RegistrationApproved(hash, params.name, upkeepId); + return upkeepId; + } + + /** + * @dev verify sender allowlist if needed and check max limit + */ + function _shouldAutoApprove(TriggerRegistrationStorage memory config, address sender) private view returns (bool) { + if (config.autoApproveType == AutoApproveType.DISABLED) { + return false; + } + if (config.autoApproveType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender])) { + return false; + } + if (config.approvedCount < config.autoApproveMaxAllowed) { + return true; + } + return false; + } + + // ================================================================ + // | MODIFIERS | + // ================================================================ + + /** + * @dev Reverts if not sent from the LINK token + */ + modifier onlyLINK() { + if (msg.sender != address(LINK)) { + revert OnlyLink(); + } + _; + } + + /** + * @dev Reverts if the given data does not begin with the `register` function selector + * @param _data The data payload of the request + */ + modifier permittedFunctionsForLINK(bytes memory _data) { + bytes4 funcSelector; + assembly { + // solhint-disable-next-line avoid-low-level-calls + funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data + } + if (funcSelector != REGISTER_REQUEST_SELECTOR) { + revert FunctionNotPermitted(); + } + _; + } + + /** + * @dev Reverts if the actual amount passed does not match the expected amount + * @param expected amount that should match the actual amount + * @param data bytes + */ + modifier isActualAmount(uint256 expected, bytes calldata data) { + // decode register function arguments to get actual amount + (, , , , , , , , , uint96 amount, ) = abi.decode( + data[4:], + (string, bytes, address, uint32, address, uint8, bytes, bytes, bytes, uint96, address) + ); + if (expected != amount) { + revert AmountMismatch(); + } + _; + } + + /** + * @dev Reverts if the actual sender address does not match the expected sender address + * @param expected address that should match the actual sender address + * @param data bytes + */ + modifier isActualSender(address expected, bytes calldata data) { + // decode register function arguments to get actual sender + (, , , , , , , , , , address sender) = abi.decode( + data[4:], + (string, bytes, address, uint32, address, uint8, bytes, bytes, bytes, uint96, address) + ); + if (expected != sender) { + revert SenderMismatch(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol new file mode 100644 index 0000000..76483c8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; +import {Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +/** + * @notice this file exposes structs that are otherwise internal to the automation registry + * doing this allows those structs to be encoded and decoded with type safety in offchain code + * and tests because generated wrappers are made available + */ + +/** + * @notice structure of trigger for log triggers + */ +struct LogTriggerConfig { + address contractAddress; + uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply + bytes32 topic0; + bytes32 topic1; + bytes32 topic2; + bytes32 topic3; +} + +contract AutomationUtils2_1 { + /** + * @dev this can be removed as OnchainConfig is now exposed directly from the registry + */ + function _onChainConfig(IAutomationV21PlusCommon.OnchainConfigLegacy memory) external {} // 0x2ff92a81 + + function _report(KeeperRegistryBase2_1.Report memory) external {} // 0xe65d6546 + + function _logTriggerConfig(LogTriggerConfig memory) external {} // 0x21f373d7 + + function _logTrigger(KeeperRegistryBase2_1.LogTrigger memory) external {} // 0x1c8d8260 + + function _conditionalTrigger(KeeperRegistryBase2_1.ConditionalTrigger memory) external {} // 0x4b6df294 + + function _log(Log memory) external {} // 0xe9720a49 +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol new file mode 100644 index 0000000..25028e6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; +import {KeeperRegistryLogicB2_1} from "./KeeperRegistryLogicB2_1.sol"; +import {Chainable} from "../Chainable.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +/** + * @notice Registry for adding work for Chainlink Keepers to perform on client + * contracts. Clients must support the Upkeep interface. + */ +contract KeeperRegistry2_1 is KeeperRegistryBase2_1, OCR2Abstract, Chainable, IERC677Receiver { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @notice versions: + * - KeeperRegistry 2.1.0: introduces support for log, cron, and ready triggers + : removes the need for "wrapped perform data" + * - KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts + * : fixes issue with arbitrum block number + * : does an early return in case of stale report instead of revert + * - KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X + * - KeeperRegistry 2.0.0: implement OCR interface + * - KeeperRegistry 1.3.0: split contract into Proxy and Logic + * : account for Arbitrum and Optimism L1 gas fee + * : allow users to configure upkeeps + * - KeeperRegistry 1.2.0: allow funding within performUpkeep + * : allow configurable registry maxPerformGas + * : add function to let admin change upkeep gas limit + * : add minUpkeepSpend requirement + * : upgrade to solidity v0.8 + * - KeeperRegistry 1.1.0: added flatFeeMicroLink + * - KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "KeeperRegistry 2.1.0"; + + /** + * @param logicA the address of the first logic contract, but cast as logicB in order to call logicB functions + */ + constructor( + KeeperRegistryLogicB2_1 logicA + ) + KeeperRegistryBase2_1( + logicA.getMode(), + logicA.getLinkAddress(), + logicA.getLinkNativeFeedAddress(), + logicA.getFastGasFeedAddress(), + logicA.getAutomationForwarderLogic() + ) + Chainable(address(logicA)) + {} + + // ================================================================ + // | ACTIONS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function transmit( + bytes32[3] calldata reportContext, + bytes calldata rawReport, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external override { + uint256 gasOverhead = gasleft(); + HotVars memory hotVars = s_hotVars; + + if (hotVars.paused) revert RegistryPaused(); + if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); + + // Verify signatures + if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); + if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); + _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); + + Report memory report = _decodeReport(rawReport); + UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); + uint16 numUpkeepsPassedChecks; + + 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], + report.triggers[i], + upkeepTransmitInfo[i] + ); + + if (upkeepTransmitInfo[i].earlyChecksPassed) { + numUpkeepsPassedChecks += 1; + } else { + continue; + } + + // Actually perform the target upkeep + (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( + upkeepTransmitInfo[i].upkeep.forwarder, + report.gasLimits[i], + report.performDatas[i] + ); + + // 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], upkeepTransmitInfo[i]); + } + // No upkeeps to be performed in this report + if (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 + gasOverhead = + (gasOverhead - gasleft() + 16 * rawReport.length) + + ACCOUNTING_FIXED_GAS_OVERHEAD + + (ACCOUNTING_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); + gasOverhead = gasOverhead / 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], + report.fastGasWei, + report.linkNative, + numUpkeepsPassedChecks + ); + totalPremium += premium; + totalReimbursement += reimbursement; + + emit UpkeepPerformed( + report.upkeepIds[i], + upkeepTransmitInfo[i].performSuccess, + reimbursement + premium, + upkeepTransmitInfo[i].gasUsed, + upkeepTransmitInfo[i].gasOverhead, + report.triggers[i] + ); + } + } + } + // record payments + s_transmitters[msg.sender].balance += totalReimbursement; + s_hotVars.totalPremium += totalPremium; + + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + if (epoch > hotVars.latestEpoch) { + s_hotVars.latestEpoch = epoch; + } + } + + /** + * @notice simulates the upkeep with the perform data returned from checkUpkeep + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + * @return success whether the call reverted or not + * @return gasUsed the amount of gas the target contract consumed + */ + function simulatePerformUpkeep( + uint256 id, + bytes calldata performData + ) external cannotExecute returns (bool success, uint256 gasUsed) { + if (s_hotVars.paused) revert RegistryPaused(); + Upkeep memory upkeep = s_upkeep[id]; + (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); + return (success, gasUsed); + } + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_expectedLinkBalance = s_expectedLinkBalance + amount; + emit FundsAdded(id, sender, uint96(amount)); + } + + // ================================================================ + // | SETTERS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + * @dev prefer the type-safe version of setConfig (below) whenever possible + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override { + setConfigTypeSafe( + signers, + transmitters, + f, + abi.decode(onchainConfigBytes, (IAutomationV21PlusCommon.OnchainConfigLegacy)), + offchainConfigVersion, + offchainConfig + ); + } + + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) public onlyOwner { + if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); + if (f == 0) revert IncorrectNumberOfFaultyOracles(); + if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); + + // move all pooled payments out of the pool to each transmitter's balance + uint96 totalPremium = s_hotVars.totalPremium; + uint96 oldLength = uint96(s_transmittersList.length); + for (uint256 i = 0; i < oldLength; i++) { + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); + } + + // remove any old signer/transmitter addresses + address signerAddress; + address transmitterAddress; + for (uint256 i = 0; i < oldLength; i++) { + signerAddress = s_signersList[i]; + transmitterAddress = s_transmittersList[i]; + delete s_signers[signerAddress]; + // Do not delete the whole transmitter struct as it has balance information stored + s_transmitters[transmitterAddress].active = false; + } + delete s_signersList; + delete s_transmittersList; + + // add new signer/transmitter addresses + { + Transmitter memory transmitter; + address temp; + for (uint256 i = 0; i < signers.length; i++) { + if (s_signers[signers[i]].active) revert RepeatedSigner(); + if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); + s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); + + temp = transmitters[i]; + if (temp == ZERO_ADDRESS) revert InvalidTransmitter(); + transmitter = s_transmitters[temp]; + if (transmitter.active) revert RepeatedTransmitter(); + transmitter.active = true; + transmitter.index = uint8(i); + // new transmitters start afresh from current totalPremium + // some spare change of premium from previous pool will be forfeited + transmitter.lastCollected = totalPremium; + s_transmitters[temp] = transmitter; + } + } + s_signersList = signers; + s_transmittersList = transmitters; + + s_hotVars = HotVars({ + f: f, + paymentPremiumPPB: onchainConfig.paymentPremiumPPB, + flatFeeMicroLink: onchainConfig.flatFeeMicroLink, + stalenessSeconds: onchainConfig.stalenessSeconds, + gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, + paused: s_hotVars.paused, + reentrancyGuard: s_hotVars.reentrancyGuard, + totalPremium: totalPremium, + latestEpoch: 0 // DON restarts epoch + }); + + s_storage = Storage({ + checkGasLimit: onchainConfig.checkGasLimit, + minUpkeepSpend: onchainConfig.minUpkeepSpend, + maxPerformGas: onchainConfig.maxPerformGas, + transcoder: onchainConfig.transcoder, + maxCheckDataSize: onchainConfig.maxCheckDataSize, + maxPerformDataSize: onchainConfig.maxPerformDataSize, + maxRevertDataSize: onchainConfig.maxRevertDataSize, + upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, + nonce: s_storage.nonce, + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + ownerLinkBalance: s_storage.ownerLinkBalance + }); + s_fallbackGasPrice = onchainConfig.fallbackGasPrice; + s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; + + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + s_storage.latestConfigBlockNumber = uint32(_blockNum()); + s_storage.configCount += 1; + + bytes memory onchainConfigBytes = abi.encode(onchainConfig); + + s_latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + + for (uint256 idx = 0; idx < s_registrars.length(); idx++) { + s_registrars.remove(s_registrars.at(idx)); + } + + for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { + s_registrars.add(onchainConfig.registrars[idx]); + } + + emit ConfigSet( + previousConfigBlockNumber, + s_latestConfigDigest, + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); + } + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDigestAndEpoch() + external + view + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (false, s_latestConfigDigest, s_hotVars.latestEpoch); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol new file mode 100644 index 0000000..fe73894 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol @@ -0,0 +1,861 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import {ExecutionPrevention} from "../ExecutionPrevention.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * KeeperRegistry and KeeperRegistryLogic + * @dev all errors, events, and internal functions should live here + */ +abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; + bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint256 internal constant PERFORM_GAS_CUSHION = 5_000; + uint256 internal constant PPB_BASE = 1_000_000_000; + uint32 internal constant UINT32_MAX = type(uint32).max; + uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + /** + * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with + * MigratableKeeperRegistryInterfaceV1 - it should be removed in future versions in favor of + * UPKEEP_VERSION_BASE and MigratableKeeperRegistryInterfaceV2 + */ + UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; + uint8 internal constant UPKEEP_VERSION_BASE = 3; + // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism + bytes internal constant L1_FEE_DATA_PADDING = + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 90_000; // Used in maxPayment estimation, and in capping overheads during actual payment + uint256 internal constant REGISTRY_LOG_OVERHEAD = 110_000; // Used only in maxPayment estimation, and in capping overheads during actual payment. + uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 20; // Used only in maxPayment estimation, and in capping overheads during actual payment. Value scales with performData length. + uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 7_500; // Used only in maxPayment estimation, and in capping overheads during actual payment. Value scales with f. + + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 27_500; // Used in actual payment. Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_SIGNER_GAS_OVERHEAD = 1_100; // Used in actual payment. overhead per signer + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 7_000; // Used in actual payment. overhead per upkeep performed + + OVM_GasPriceOracle internal constant OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); + ArbGasInfo internal constant ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); + ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); + + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_linkNativeFeed; + AggregatorV3Interface internal immutable i_fastGasFeed; + Mode internal immutable i_mode; + address internal immutable i_automationForwarderLogic; + + /** + * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit + * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path + */ + + // Upkeep storage + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit + mapping(uint256 => address) internal s_upkeepAdmin; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + mapping(bytes32 => bool) internal s_dedupKeys; + // Registry config and state + EnumerableSet.AddressSet internal s_registrars; + mapping(address => Transmitter) internal s_transmitters; + mapping(address => Signer) internal s_signers; + address[] internal s_signersList; // s_signersList contains the signing address of each oracle + address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle + mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. + mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter + bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification + HotVars internal s_hotVars; // Mixture of config and state, used in transmit + Storage internal s_storage; // Mixture of config and state, not used in transmit + uint256 internal s_fallbackGasPrice; + uint256 internal s_fallbackLinkPrice; + uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro + mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers + mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep + mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep + mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin + + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientFunds(); + error InvalidDataLength(); + error InvalidTrigger(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidTransmitter(); + error InvalidTriggerType(); + error MaxCheckDataSizeCanOnlyIncrease(); + error MaxPerformDataSizeCanOnlyIncrease(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyPausedUpkeep(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum Mode { + DEFAULT, + ARBITRUM, + OPTIMISM + } + + enum Trigger { + CONDITION, + LOG + } + + enum UpkeepFailureReason { + NONE, + UPKEEP_CANCELLED, + UPKEEP_PAUSED, + TARGET_CHECK_REVERTED, + UPKEEP_NOT_NEEDED, + PERFORM_DATA_EXCEEDS_LIMIT, + INSUFFICIENT_BALANCE, + CALLBACK_REVERTED, + REVERT_DATA_EXCEEDS_LIMIT, + REGISTRY_PAUSED + } + + /** + * @notice relevant state of an upkeep which is used in transmit function + * @member paused if this upkeep has been paused + * @member performGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member forwarder the forwarder contract to use for this upkeep + * @member amountSpent the amount this upkeep has spent + * @member balance the balance of this upkeep + * @member lastPerformedBlockNumber the last block number when this upkeep was performed + */ + struct Upkeep { + bool paused; + uint32 performGas; + uint32 maxValidBlocknumber; + IAutomationForwarder forwarder; + // 0 bytes left in 1st EVM word - not written to in transmit + uint96 amountSpent; + uint96 balance; + uint32 lastPerformedBlockNumber; + // 2 bytes left in 2nd EVM word - written in transmit path + } + + /// @dev Config + State storage struct which is on hot transmit path + struct HotVars { + uint8 f; // maximum number of faulty oracles + uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost + uint32 flatFeeMicroLink; // flat fee charged to user for every perform + uint24 stalenessSeconds; // Staleness tolerance for feeds + uint16 gasCeilingMultiplier; // multiplier on top of fast gas feed for upper bound + bool paused; // pause switch for all upkeeps in the registry + bool reentrancyGuard; // guard against reentrancy + uint96 totalPremium; // total historical payment to oracles for premium + uint32 latestEpoch; // latest epoch for which a report was transmitted + // 1 EVM word full + } + + /// @dev Config + State storage struct which is not on hot transmit path + struct Storage { + uint96 minUpkeepSpend; // Minimum amount an upkeep must spend + address transcoder; // Address of transcoder contract used in migrations + // 1 EVM word full + uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent + uint32 checkGasLimit; // Gas limit allowed in checkUpkeep + uint32 maxPerformGas; // Max gas an upkeep can use on this registry + uint32 nonce; // Nonce for each upkeep created + uint32 configCount; // incremented each time a new config is posted, The count + // is incorporated into the config digest to prevent replay attacks. + uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs + // 2 EVM word full + uint32 maxCheckDataSize; // max length of checkData bytes + uint32 maxPerformDataSize; // max length of performData bytes + uint32 maxRevertDataSize; // max length of revertData bytes + address upkeepPrivilegeManager; // address which can set privilege for upkeeps + // 3 EVM word full + } + + /// @dev Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkNative; + uint256[] upkeepIds; + uint256[] gasLimits; + bytes[] triggers; + bytes[] performDatas; + } + + /** + * @dev This struct is used to maintain run time information about an upkeep in transmit function + * @member upkeep the upkeep struct + * @member earlyChecksPassed whether the upkeep passed early checks before perform + * @member maxLinkPayment the max amount this upkeep could pay for work + * @member performSuccess whether the perform was successful + * @member triggerType the type of trigger + * @member gasUsed gasUsed by this upkeep in perform + * @member gasOverhead gasOverhead for this upkeep + * @member dedupID unique ID used to dedup an upkeep/trigger combo + */ + struct UpkeepTransmitInfo { + Upkeep upkeep; + bool earlyChecksPassed; + uint96 maxLinkPayment; + bool performSuccess; + Trigger triggerType; + uint256 gasUsed; + uint256 gasOverhead; + bytes32 dedupID; + } + + struct Transmitter { + bool active; + uint8 index; // Index of oracle in s_signersList/s_transmittersList + uint96 balance; + uint96 lastCollected; + } + + struct Signer { + bool active; + // Index of oracle in s_signersList/s_transmittersList + uint8 index; + } + + /** + * @notice the trigger structure conditional trigger type + */ + struct ConditionalTrigger { + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the trigger structure of log upkeeps + * @dev NOTE that blockNum / blockHash describe the block used for the callback, + * not necessarily the block number that the log was emitted in!!!! + */ + struct LogTrigger { + bytes32 logBlockHash; + bytes32 txHash; + uint32 logIndex; + uint32 blockNum; + bytes32 blockHash; + } + + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event OwnerFundsWithdrawn(uint96 amount); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + event Unpaused(address account); + + /** + * @param mode the contract mode of default, Arbitrum, or Optimism + * @param link address of the LINK Token + * @param linkNativeFeed address of the LINK/Native price feed + * @param fastGasFeed address of the Fast Gas price feed + */ + constructor( + Mode mode, + address link, + address linkNativeFeed, + address fastGasFeed, + address automationForwarderLogic + ) ConfirmedOwner(msg.sender) { + i_mode = mode; + i_link = LinkTokenInterface(link); + i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); + i_fastGasFeed = AggregatorV3Interface(fastGasFeed); + i_automationForwarderLogic = automationForwarderLogic; + } + + // ================================================================ + // | INTERNAL FUNCTIONS ONLY | + // ================================================================ + + /** + * @dev creates a new upkeep with the given fields + * @param id the id of the upkeep + * @param upkeep the upkeep to create + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data which is passed to user's checkUpkeep + * @param triggerConfig the trigger config for this upkeep + * @param offchainConfig the off-chain config of this upkeep + */ + function _createUpkeep( + uint256 id, + Upkeep memory upkeep, + address admin, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) internal { + if (s_hotVars.paused) revert RegistryPaused(); + if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) + revert GasLimitOutsideRange(); + if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); + s_upkeep[id] = upkeep; + s_upkeepAdmin[id] = admin; + s_checkData[id] = checkData; + s_expectedLinkBalance = s_expectedLinkBalance + upkeep.balance; + s_upkeepTriggerConfig[id] = triggerConfig; + s_upkeepOffchainConfig[id] = offchainConfig; + s_upkeepIDs.add(id); + } + + /** + * @dev creates an ID for the upkeep based on the upkeep's type + * @dev the format of the ID looks like this: + * ****00000000000X**************** + * 4 bytes of entropy + * 11 bytes of zeros + * 1 identifying byte for the trigger type + * 16 bytes of entropy + * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique + * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only + * see the first 4 and last 4 hex values ex 0x1234...ABCD + */ + function _createID(Trigger triggerType) internal view returns (uint256) { + bytes1 empty; + bytes memory idBytes = abi.encodePacked( + keccak256(abi.encode(_blockHash(_blockNum() - 1), address(this), s_storage.nonce)) + ); + for (uint256 idx = 4; idx < 15; idx++) { + idBytes[idx] = empty; + } + idBytes[15] = bytes1(uint8(triggerType)); + return uint256(bytes32(idBytes)); + } + + /** + * @dev retrieves feed data for fast gas/native and link/native prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { + uint32 stalenessSeconds = hotVars.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + linkNative = s_fallbackLinkPrice; + } else { + linkNative = uint256(feedValue); + } + return (gasWei, linkNative); + } + + /** + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @param gasLimit the amount of gas used + * @param gasOverhead the amount of gas overhead + * @param fastGasWei the fast gas price + * @param linkNative the exchange ratio between LINK and Native token + * @param numBatchedUpkeeps the number of upkeeps in this batch. Used to divide the L1 cost + * @param isExecution if this is triggered by a perform upkeep function + */ + function _calculatePaymentAmount( + HotVars memory hotVars, + uint256 gasLimit, + uint256 gasOverhead, + uint256 fastGasWei, + uint256 linkNative, + uint16 numBatchedUpkeeps, + bool isExecution + ) internal view returns (uint96, uint96) { + uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (isExecution && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + + uint256 l1CostWei = 0; + if (i_mode == Mode.OPTIMISM) { + bytes memory txCallData = new bytes(0); + if (isExecution) { + txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); + } else { + // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have + // s_storage.maxPerformDataSize non zero-bytes. Instead of setting bytes to non-zero + // we initialize 'new bytes' of length 4*maxPerformDataSize to cover for zero bytes. + txCallData = new bytes(4 * s_storage.maxPerformDataSize); + } + l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); + } else if (i_mode == Mode.ARBITRUM) { + if (isExecution) { + l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); + } else { + // fee is 4 per 0 byte, 16 per non-zero byte - we assume all non-zero and + // max data size to calculate max payment + (, uint256 perL1CalldataUnit, , , , ) = ARB_NITRO_ORACLE.getPricesInWei(); + l1CostWei = perL1CalldataUnit * s_storage.maxPerformDataSize * 16; + } + } + // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound + if (!isExecution) { + l1CostWei = hotVars.gasCeilingMultiplier * l1CostWei; + } + // Divide l1CostWei among all batched upkeeps. Spare change from division is not charged + l1CostWei = l1CostWei / numBatchedUpkeeps; + + uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; + uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / + linkNative + + uint256(hotVars.flatFeeMicroLink) * + 1e12; + // LINK_TOTAL_SUPPLY < UINT96_MAX + if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); + return (uint96(gasPayment), uint96(premium)); + } + + /** + * @dev calculates the max LINK payment for an upkeep + */ + function _getMaxLinkPayment( + HotVars memory hotVars, + Trigger triggerType, + uint32 performGas, + uint32 performDataLength, + uint256 fastGasWei, + uint256 linkNative, + bool isExecution // Whether this is an actual perform execution or just a simulation + ) internal view returns (uint96) { + uint256 gasOverhead = _getMaxGasOverhead(triggerType, performDataLength, hotVars.f); + (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( + hotVars, + performGas, + gasOverhead, + fastGasWei, + linkNative, + 1, // Consider only 1 upkeep in batch to get maxPayment + isExecution + ); + + return reimbursement + premium; + } + + /** + * @dev returns the max gas overhead that can be charged for an upkeep + */ + function _getMaxGasOverhead(Trigger triggerType, uint32 performDataLength, uint8 f) internal pure returns (uint256) { + // performData causes additional overhead in report length and memory operations + uint256 baseOverhead; + if (triggerType == Trigger.CONDITION) { + baseOverhead = REGISTRY_CONDITIONAL_OVERHEAD; + } else if (triggerType == Trigger.LOG) { + baseOverhead = REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } + return + baseOverhead + + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (f + 1)) + + (REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD * performDataLength); + } + + /** + * @dev move a transmitter's balance from total pool to withdrawable balance + */ + function _updateTransmitterBalanceFromPool( + address transmitterAddress, + uint96 totalPremium, + uint96 payeeCount + ) internal returns (uint96) { + Transmitter memory transmitter = s_transmitters[transmitterAddress]; + + if (transmitter.active) { + uint96 uncollected = totalPremium - transmitter.lastCollected; + uint96 due = uncollected / payeeCount; + transmitter.balance += due; + transmitter.lastCollected += due * payeeCount; + s_transmitters[transmitterAddress] = transmitter; + } + + return transmitter.balance; + } + + /** + * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) + */ + function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { + bytes32 rawID = bytes32(upkeepId); + bytes1 empty = bytes1(0); + for (uint256 idx = 4; idx < 15; idx++) { + if (rawID[idx] != empty) { + // old IDs that were created before this standard and migrated to this registry + return Trigger.CONDITION; + } + } + return Trigger(uint8(rawID[15])); + } + + function _checkPayload( + uint256 upkeepId, + Trigger triggerType, + bytes memory triggerData + ) internal view returns (bytes memory) { + if (triggerType == Trigger.CONDITION) { + return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); + } else if (triggerType == Trigger.LOG) { + Log memory log = abi.decode(triggerData, (Log)); + return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); + } + revert InvalidTriggerType(); + } + + /** + * @dev _decodeReport decodes a serialized report into a Report struct + */ + function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { + Report memory report = abi.decode(rawReport, (Report)); + uint256 expectedLength = report.upkeepIds.length; + if ( + report.gasLimits.length != expectedLength || + report.triggers.length != expectedLength || + report.performDatas.length != expectedLength + ) { + revert InvalidReport(); + } + return report; + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + * @return bool whether the upkeep should be performed + * @return bytes32 dedupID for preventing duplicate performances of this trigger + */ + function _prePerformChecks( + uint256 upkeepId, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo + ) internal returns (bool, bytes32) { + bytes32 dedupID; + if (transmitInfo.triggerType == Trigger.CONDITION) { + if (!_validateConditionalTrigger(upkeepId, rawTrigger, transmitInfo)) return (false, dedupID); + } else if (transmitInfo.triggerType == Trigger.LOG) { + bool valid; + (valid, dedupID) = _validateLogTrigger(upkeepId, rawTrigger, transmitInfo); + if (!valid) return (false, dedupID); + } else { + revert InvalidTriggerType(); + } + if (transmitInfo.upkeep.maxValidBlocknumber <= _blockNum()) { + // Can happen when an upkeep got cancelled after report was generated. + // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice + emit CancelledUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + if (transmitInfo.upkeep.balance < transmitInfo.maxLinkPayment) { + // Can happen due to fluctuations in gas / link prices + emit InsufficientFundsUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + */ + function _validateConditionalTrigger( + uint256 upkeepId, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo + ) internal returns (bool) { + ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); + if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { + // Can happen when another report performed this upkeep after this report was generated + emit StaleUpkeepReport(upkeepId, rawTrigger); + return false; + } + if ( + (trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) || + trigger.blockNum >= _blockNum() + ) { + // There are two cases of reorged report + // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain + // which is always protected against + // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is + // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain + // when it is sent + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return false; + } + return true; + } + + function _validateLogTrigger( + uint256 upkeepId, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo + ) internal returns (bool, bytes32) { + LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); + bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); + if ( + (trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) || + trigger.blockNum >= _blockNum() + ) { + // Reorg protection is same as conditional trigger upkeeps + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + if (s_dedupKeys[dedupID]) { + emit StaleUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Verify signatures attached to report + */ + function _verifyReportSignature( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) internal view { + bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount = 0; + + Signer memory signer; + address signerAddress; + for (uint256 i = 0; i < rs.length; i++) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + signer = s_signers[signerAddress]; + if (!signer.active) revert OnlyActiveSigners(); + unchecked { + signedCount += 1 << (8 * signer.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); + } + + /** + * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances + * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID + */ + function _updateTriggerMarker(uint256 upkeepID, UpkeepTransmitInfo memory upkeepTransmitInfo) internal { + if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { + s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(_blockNum()); + } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { + s_dedupKeys[upkeepTransmitInfo.dedupID] = true; + emit DedupKeyAdded(upkeepTransmitInfo.dedupID); + } + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * transmitter and the exact gas required by the Upkeep + */ + function _performUpkeep( + IAutomationForwarder forwarder, + uint256 performGas, + bytes memory performData + ) internal nonReentrant returns (bool success, uint256 gasUsed) { + performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); + return forwarder.forward(performGas, performData); + } + + /** + * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases + * amount spent. + */ + function _postPerformPayment( + HotVars memory hotVars, + uint256 upkeepId, + UpkeepTransmitInfo memory upkeepTransmitInfo, + uint256 fastGasWei, + uint256 linkNative, + uint16 numBatchedUpkeeps + ) internal returns (uint96 gasReimbursement, uint96 premium) { + (gasReimbursement, premium) = _calculatePaymentAmount( + hotVars, + upkeepTransmitInfo.gasUsed, + upkeepTransmitInfo.gasOverhead, + fastGasWei, + linkNative, + numBatchedUpkeeps, + true + ); + + uint96 payment = gasReimbursement + premium; + s_upkeep[upkeepId].balance -= payment; + s_upkeep[upkeepId].amountSpent += payment; + + return (gasReimbursement, premium); + } + + /** + * @dev Caps the gas overhead by the constant overhead used within initial payment checks in order to + * prevent a revert in payment processing. + */ + function _getCappedGasOverhead( + uint256 calculatedGasOverhead, + Trigger triggerType, + uint32 performDataLength, + uint8 f + ) internal pure returns (uint256 cappedGasOverhead) { + cappedGasOverhead = _getMaxGasOverhead(triggerType, performDataLength, f); + if (calculatedGasOverhead < cappedGasOverhead) { + return calculatedGasOverhead; + } + return cappedGasOverhead; + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { + if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); + if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } + + /** + * @dev returns the current block number in a chain agnostic manner + */ + function _blockNum() internal view returns (uint256) { + if (i_mode == Mode.ARBITRUM) { + return ARB_SYS.arbBlockNumber(); + } else { + return block.number; + } + } + + /** + * @dev returns the blockhash of the provided block number in a chain agnostic manner + * @param n the blocknumber to retrieve the blockhash for + * @return blockhash the blockhash of block number n, or 0 if n is out queryable of range + */ + function _blockHash(uint256 n) internal view returns (bytes32) { + if (i_mode == Mode.ARBITRUM) { + uint256 blockNum = ARB_SYS.arbBlockNumber(); + if (n >= blockNum || blockNum - n > 256) { + return ""; + } + return ARB_SYS.arbBlockHash(n); + } else { + return blockhash(n); + } + } + + /** + * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage + */ + modifier nonReentrant() { + if (s_hotVars.reentrancyGuard) revert ReentrantCall(); + s_hotVars.reentrancyGuard = true; + _; + s_hotVars.reentrancyGuard = false; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol new file mode 100644 index 0000000..517d14d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; +import {KeeperRegistryLogicB2_1} from "./KeeperRegistryLogicB2_1.sol"; +import {Chainable} from "../Chainable.sol"; +import {AutomationForwarder} from "../AutomationForwarder.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; + +/** + * @notice Logic contract, works in tandem with KeeperRegistry as a proxy + */ +contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @param logicB the address of the second logic contract + */ + constructor( + KeeperRegistryLogicB2_1 logicB + ) + KeeperRegistryBase2_1( + logicB.getMode(), + logicB.getLinkAddress(), + logicB.getLinkNativeFeedAddress(), + logicB.getFastGasFeedAddress(), + logicB.getAutomationForwarderLogic() + ) + Chainable(address(logicB)) + {} + + /** + * @notice called by the automation DON to check if work is needed + * @param id the upkeep ID to check for work needed + * @param triggerData extra contextual data about the trigger (not used in all code paths) + * @dev this one of the core functions called in the hot path + * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility + * @dev there is an incongruency on what gets returned during failure modes + * ex sometimes we include price data, sometimes we omit it depending on the failure + */ + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + public + cannotExecute + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ) + { + Trigger triggerType = _getTriggerType(id); + HotVars memory hotVars = s_hotVars; + Upkeep memory upkeep = s_upkeep[id]; + + if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); + if (upkeep.maxValidBlocknumber != UINT32_MAX) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); + if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); + + (fastGasWei, linkNative) = _getFeedData(hotVars); + uint96 maxLinkPayment = _getMaxLinkPayment( + hotVars, + triggerType, + upkeep.performGas, + s_storage.maxPerformDataSize, + fastGasWei, + linkNative, + false + ); + if (upkeep.balance < maxLinkPayment) { + return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); + } + + bytes memory callData = _checkPayload(id, triggerType, triggerData); + + gasUsed = gasleft(); + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); + gasUsed = gasUsed - gasleft(); + + if (!success) { + // User's target check reverted. We capture the revert data here and pass it within performData + if (result.length > s_storage.maxRevertDataSize) { + return ( + false, + bytes(""), + UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + } + return ( + upkeepNeeded, + result, + UpkeepFailureReason.TARGET_CHECK_REVERTED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + } + + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) + return ( + false, + bytes(""), + UpkeepFailureReason.UPKEEP_NOT_NEEDED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + + if (performData.length > s_storage.maxPerformDataSize) + return ( + false, + bytes(""), + UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkNative); + } + + /** + * @notice see other checkUpkeep function for description + * @dev this function may be deprecated in a future version of chainlink automation + */ + function checkUpkeep( + uint256 id + ) + external + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ) + { + return checkUpkeep(id, bytes("")); + } + + /** + * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) + * @param id the upkeepID to execute a callback for + * @param values the values returned from the data streams lookup + * @param extraData the user-provided extra context data + */ + function checkCallback( + uint256 id, + bytes[] memory values, + bytes calldata extraData + ) + external + cannotExecute + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); + return executeCallback(id, payload); + } + + /** + * @notice this is a generic callback executor that forwards a call to a user's contract with the configured + * gas limit + * @param id the upkeepID to execute a callback for + * @param payload the data (including function selector) to call on the upkeep target contract + */ + function executeCallback( + uint256 id, + bytes memory payload + ) + public + cannotExecute + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + Upkeep memory upkeep = s_upkeep[id]; + gasUsed = gasleft(); + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); + gasUsed = gasUsed - gasleft(); + if (!success) { + return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); + } + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) { + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); + } + if (performData.length > s_storage.maxPerformDataSize) { + return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); + } + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); + } + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param triggerType the trigger for the upkeep + * @param checkData data passed to the contract when checking for upkeep + * @param triggerConfig the config for the trigger + * @param offchainConfig arbitrary offchain config for the upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + Trigger triggerType, + bytes calldata checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) public returns (uint256 id) { + if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); + if (!target.isContract()) revert NotAContract(); + id = _createID(triggerType); + IAutomationForwarder forwarder = IAutomationForwarder( + address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) + ); + _createUpkeep( + id, + Upkeep({ + performGas: gasLimit, + balance: 0, + maxValidBlocknumber: UINT32_MAX, + lastPerformedBlockNumber: 0, + amountSpent: 0, + paused: false, + forwarder: forwarder + }), + admin, + checkData, + triggerConfig, + offchainConfig + ); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + emit UpkeepCheckDataSet(id, checkData); + emit UpkeepTriggerConfigSet(id, triggerConfig); + emit UpkeepOffchainConfigSet(id, offchainConfig); + return (id); + } + + /** + * @notice this function registers a conditional upkeep, using a backwards compatible function signature + * @dev this function is backwards compatible with versions <=2.0, but may be removed in a future version + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData, + bytes calldata offchainConfig + ) external returns (uint256 id) { + return registerUpkeep(target, gasLimit, admin, Trigger.CONDITION, checkData, bytes(""), offchainConfig); + } + + /** + * @notice cancels an upkeep + * @param id the upkeepID to cancel + * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to + * allow any pending performUpkeep txs time to get confirmed + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; + bool isOwner = msg.sender == owner(); + + if (canceled && !(isOwner && upkeep.maxValidBlocknumber > _blockNum())) revert CannotCancel(); + if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); + + uint256 height = _blockNum(); + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minUpkeepSpend is not met + uint96 minUpkeepSpend = s_storage.minUpkeepSpend; + uint96 cancellationFee = 0; + // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) + if (upkeep.amountSpent < minUpkeepSpend) { + cancellationFee = minUpkeepSpend - upkeep.amountSpent; + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @notice adds fund to an upkeep + * @param id the upkeepID + * @param amount the amount of LINK to fund, in jules (jules = "wei" of LINK) + */ + function addFunds(uint256 id, uint96 amount) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + s_upkeep[id].balance = upkeep.balance + amount; + s_expectedLinkBalance = s_expectedLinkBalance + amount; + i_link.transferFrom(msg.sender, address(this), amount); + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @notice migrates upkeeps from one registry to another + * @param ids the upkeepIDs to migrate + * @param destination the destination registry address + * @dev a transcoder must be set in order to enable migration + * @dev migration permissions must be set on *both* sending and receiving registries + * @dev only an upkeep admin can migrate their upkeeps + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + uint256 id; + Upkeep memory upkeep; + uint256 totalBalanceRemaining; + address[] memory admins = new address[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + bytes[] memory checkDatas = new bytes[](ids.length); + bytes[] memory triggerConfigs = new bytes[](ids.length); + bytes[] memory offchainConfigs = new bytes[](ids.length); + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + _requireAdminAndNotCancelled(id); + upkeep.forwarder.updateRegistry(destination); + upkeeps[idx] = upkeep; + admins[idx] = s_upkeepAdmin[id]; + checkDatas[idx] = s_checkData[id]; + triggerConfigs[idx] = s_upkeepTriggerConfig[id]; + offchainConfigs[idx] = s_upkeepOffchainConfig[id]; + totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; + delete s_upkeep[id]; + delete s_checkData[id]; + delete s_upkeepTriggerConfig[id]; + delete s_upkeepOffchainConfig[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; + bytes memory encodedUpkeeps = abi.encode( + ids, + upkeeps, + new address[](ids.length), + admins, + checkDatas, + triggerConfigs, + offchainConfigs + ); + MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( + UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( + UPKEEP_VERSION_BASE, + MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), + encodedUpkeeps + ) + ); + i_link.transfer(destination, totalBalanceRemaining); + } + + /** + * @notice received upkeeps migrated from another registry + * @param encodedUpkeeps the raw upkeep data to import + * @dev this function is never called directly, it is only called by another registry's migrate function + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + ( + uint256[] memory ids, + Upkeep[] memory upkeeps, + address[] memory targets, + address[] memory upkeepAdmins, + bytes[] memory checkDatas, + bytes[] memory triggerConfigs, + bytes[] memory offchainConfigs + ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); + for (uint256 idx = 0; idx < ids.length; idx++) { + if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { + upkeeps[idx].forwarder = IAutomationForwarder( + address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) + ); + } + _createUpkeep( + ids[idx], + upkeeps[idx], + upkeepAdmins[idx], + checkDatas[idx], + triggerConfigs[idx], + offchainConfigs[idx] + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } + + /** + * @notice sets the upkeep trigger config + * @param id the upkeepID to change the trigger for + * @param triggerConfig the new trigger config + */ + function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { + _requireAdminAndNotCancelled(id); + s_upkeepTriggerConfig[id] = triggerConfig; + emit UpkeepTriggerConfigSet(id, triggerConfig); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol new file mode 100644 index 0000000..243d0ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol @@ -0,0 +1,517 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.16; + +import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +contract KeeperRegistryLogicB2_1 is KeeperRegistryBase2_1 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @dev see KeeperRegistry master contract for constructor description + */ + constructor( + Mode mode, + address link, + address linkNativeFeed, + address fastGasFeed, + address automationForwarderLogic + ) KeeperRegistryBase2_1(mode, link, linkNativeFeed, fastGasFeed, automationForwarderLogic) {} + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice transfers the address of an admin for an upkeep + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + _requireAdminAndNotCancelled(id); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of an upkeep admin + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = s_upkeepAdmin[id]; + s_upkeepAdmin[id] = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused + */ + function pauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @notice unpauses an upkeep + */ + function unpauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @notice updates the checkData for an upkeep + */ + function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { + _requireAdminAndNotCancelled(id); + if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataSet(id, newCheckData); + } + + /** + * @notice updates the gas limit for an upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + _requireAdminAndNotCancelled(id); + s_upkeep[id].performGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @notice updates the offchain config for an upkeep + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { + _requireAdminAndNotCancelled(id); + s_upkeepOffchainConfig[id] = config; + emit UpkeepOffchainConfigSet(id, config); + } + + /** + * @notice withdraws LINK funds from an upkeep + * @dev note that an upkeep must be cancelled first!! + */ + function withdrawFunds(uint256 id, address to) external nonReentrant { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > _blockNum()) revert UpkeepNotCanceled(); + uint96 amountToWithdraw = s_upkeep[id].balance; + s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; + s_upkeep[id].balance = 0; + i_link.transfer(to, amountToWithdraw); + emit FundsWithdrawn(id, amountToWithdraw, to); + } + + // ================================================================ + // | NODE MANAGEMENT | + // ================================================================ + + /** + * @notice transfers the address of payee for a transmitter + */ + function transferPayeeship(address transmitter, address proposed) external { + if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[transmitter] != proposed) { + s_proposedPayee[transmitter] = proposed; + emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of the payee + */ + function acceptPayeeship(address transmitter) external { + if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_transmitterPayees[transmitter]; + s_transmitterPayees[transmitter] = msg.sender; + s_proposedPayee[transmitter] = ZERO_ADDRESS; + + emit PayeeshipTransferred(transmitter, past, msg.sender); + } + + /** + * @notice withdraws LINK received as payment for work performed + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); + uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); + s_transmitters[from].balance = 0; + s_expectedLinkBalance = s_expectedLinkBalance - balance; + i_link.transfer(to, balance); + emit PaymentWithdrawn(from, balance, to, msg.sender); + } + + // ================================================================ + // | OWNER / MANAGER ACTIONS | + // ================================================================ + + /** + * @notice sets the privilege config for an upkeep + */ + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; + emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); + } + + /** + * @notice withdraws the owner's LINK balance + */ + function withdrawOwnerFunds() external onlyOwner { + uint96 amount = s_storage.ownerLinkBalance; + s_expectedLinkBalance = s_expectedLinkBalance - amount; + s_storage.ownerLinkBalance = 0; + emit OwnerFundsWithdrawn(amount); + i_link.transfer(msg.sender, amount); + } + + /** + * @notice allows the owner to withdraw any LINK accidentally sent to the contract + */ + function recoverFunds() external onlyOwner { + uint256 total = i_link.balanceOf(address(this)); + i_link.transfer(msg.sender, total - s_expectedLinkBalance); + } + + /** + * @notice sets the payees for the transmitters + */ + function setPayees(address[] calldata payees) external onlyOwner { + if (s_transmittersList.length != payees.length) revert ParameterLengthError(); + for (uint256 i = 0; i < s_transmittersList.length; i++) { + address transmitter = s_transmittersList[i]; + address oldPayee = s_transmitterPayees[transmitter]; + address newPayee = payees[i]; + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) revert InvalidPayee(); + if (newPayee != IGNORE_ADDRESS) { + s_transmitterPayees[transmitter] = newPayee; + } + } + emit PayeesUpdated(s_transmittersList, payees); + } + + /** + * @notice sets the migration permission for a peer registry + * @dev this must be done before upkeeps can be migrated to/from another registry + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @notice pauses the entire registry + */ + function pause() external onlyOwner { + s_hotVars.paused = true; + emit Paused(msg.sender); + } + + /** + * @notice unpauses the entire registry + */ + function unpause() external onlyOwner { + s_hotVars.paused = false; + emit Unpaused(msg.sender); + } + + /** + * @notice sets a generic bytes field used to indicate the privilege that this admin address had + * @param admin the address to set privilege for + * @param newPrivilegeConfig the privileges that this admin has + */ + function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + s_adminPrivilegeConfig[admin] = newPrivilegeConfig; + emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + function getConditionalGasOverhead() external pure returns (uint256) { + return REGISTRY_CONDITIONAL_OVERHEAD; + } + + function getLogGasOverhead() external pure returns (uint256) { + return REGISTRY_LOG_OVERHEAD; + } + + function getPerPerformByteGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; + } + + function getPerSignerGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_SIGNER_GAS_OVERHEAD; + } + + function getCancellationDelay() external pure returns (uint256) { + return CANCELLATION_DELAY; + } + + function getMode() external view returns (Mode) { + return i_mode; + } + + function getLinkAddress() external view returns (address) { + return address(i_link); + } + + function getLinkNativeFeedAddress() external view returns (address) { + return address(i_linkNativeFeed); + } + + function getFastGasFeedAddress() external view returns (address) { + return address(i_fastGasFeed); + } + + function getAutomationForwarderLogic() external view returns (address) { + return i_automationForwarderLogic; + } + + function upkeepTranscoderVersion() public pure returns (UpkeepFormat) { + return UPKEEP_TRANSCODER_VERSION_BASE; + } + + function upkeepVersion() public pure returns (uint8) { + return UPKEEP_VERSION_BASE; + } + + /** + * @notice read all of the details about an upkeep + * @dev this function may be deprecated in a future version of automation in favor of individual + * getters for each field + */ + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { + Upkeep memory reg = s_upkeep[id]; + address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); + upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ + target: target, + performGas: reg.performGas, + checkData: s_checkData[id], + balance: reg.balance, + admin: s_upkeepAdmin[id], + maxValidBlocknumber: reg.maxValidBlocknumber, + lastPerformedBlockNumber: reg.lastPerformedBlockNumber, + amountSpent: reg.amountSpent, + paused: reg.paused, + offchainConfig: s_upkeepOffchainConfig[id] + }); + return upkeepInfo; + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { + uint256 numUpkeeps = s_upkeepIDs.length(); + if (startIndex >= numUpkeeps) revert IndexOutOfRange(); + uint256 endIndex = startIndex + maxCount; + endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; + uint256[] memory ids = new uint256[](endIndex - startIndex); + for (uint256 idx = 0; idx < ids.length; idx++) { + ids[idx] = s_upkeepIDs.at(idx + startIndex); + } + return ids; + } + + /** + * @notice returns the upkeep's trigger type + */ + function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { + return _getTriggerType(upkeepId); + } + + /** + * @notice returns the trigger config for an upkeeep + */ + function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { + return s_upkeepTriggerConfig[upkeepId]; + } + + /** + * @notice read the current info about any transmitter address + */ + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { + Transmitter memory transmitter = s_transmitters[query]; + + uint96 pooledShare = 0; + if (transmitter.active) { + uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; + pooledShare = totalDifference / uint96(s_transmittersList.length); + } + + return ( + transmitter.active, + transmitter.index, + (transmitter.balance + pooledShare), + transmitter.lastCollected, + s_transmitterPayees[query] + ); + } + + /** + * @notice read the current info about any signer address + */ + function getSignerInfo(address query) external view returns (bool active, uint8 index) { + Signer memory signer = s_signers[query]; + return (signer.active, signer.index); + } + + /** + * @notice read the current state of the registry + */ + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) + { + state = IAutomationV21PlusCommon.StateLegacy({ + nonce: s_storage.nonce, + ownerLinkBalance: s_storage.ownerLinkBalance, + expectedLinkBalance: s_expectedLinkBalance, + totalPremium: s_hotVars.totalPremium, + numUpkeeps: s_upkeepIDs.length(), + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + latestConfigDigest: s_latestConfigDigest, + latestEpoch: s_hotVars.latestEpoch, + paused: s_hotVars.paused + }); + + config = IAutomationV21PlusCommon.OnchainConfigLegacy({ + paymentPremiumPPB: s_hotVars.paymentPremiumPPB, + flatFeeMicroLink: s_hotVars.flatFeeMicroLink, + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + minUpkeepSpend: s_storage.minUpkeepSpend, + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager + }); + + return (state, config, s_signersList, s_transmittersList, s_hotVars.f); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getBalance(uint256 id) external view returns (uint96 balance) { + return s_upkeep[id].balance; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalance(uint256 id) external view returns (uint96) { + return getMinBalanceForUpkeep(id); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + * @dev this will be deprecated in a future version in favor of getMinBalance + */ + function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { + return getMaxPaymentForGas(_getTriggerType(id), s_upkeep[id].performGas); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas(Trigger triggerType, uint32 gasLimit) public view returns (uint96 maxPayment) { + HotVars memory hotVars = s_hotVars; + (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); + return + _getMaxLinkPayment(hotVars, triggerType, gasLimit, s_storage.maxPerformDataSize, fastGasWei, linkNative, false); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { + return s_upkeepPrivilegeConfig[upkeepId]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { + return s_adminPrivilegeConfig[admin]; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { + return s_upkeep[upkeepID].forwarder; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function hasDedupKey(bytes32 dedupKey) external view returns (bool) { + return s_dedupKeys[dedupKey]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE new file mode 100644 index 0000000..f60ab65 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE @@ -0,0 +1,56 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +--- + +Parameters + +Licensor: SmartContract Chainlink Limited SEZC + +Licensed Work: Automation v2.1 +The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC + +Additional Use Grant: Any uses listed and defined at https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md + + +Change Date: September 12, 2027 + +Change License: MIT + +--- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. + +If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. + +MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. + +--- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. + +2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md new file mode 100644 index 0000000..43c71da --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md @@ -0,0 +1,40 @@ +# Automation Contract Structure + +The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. It is also too large to fit into 2 contracts, a solution that works for most large projects. Therefore, we included this explanation of how the pieces fit together and various tradeoffs incurred. + +### Glossary + +**Master Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the entry-point into the chain of delegatecalls. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) + +**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the master contract in order to increase our total capacity for on-chain code. + +### Overview + +We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fall back to the next, always executing the function in the scope of the master contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. + +### Diagram + +```mermaid +graph LR + Master -- delegatecall --> la[Logic A] + la -- delegatecall --> lb[Logic B] + lb -. delegatecall .-> lx[Logic X] +``` + +### Special Considerations + +- functions on the master contract have the least gas overhead, therefore, our most price-sensitive functions live there +- functions on the master contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there +- etherscan supports executing logic contract functions that are once removed from the master - therefore we give secondary preference to the first logic contract for user and debugging functions +- functions on logic A through logic X (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically +- We use Logic A, B, C... to avoid confusion with the version ex `KeeperRegistryLogicA2_1.sol` --> Logic Contract A verion 2.1 +- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break + +### Master Interface + +The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. This process is not a hardened one. Users of this script should take great care to ensure it's efficacy. + +[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 +[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function +[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries +[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol new file mode 100644 index 0000000..53b681d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.16; + +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {KeeperRegistryBase2_1 as R21} from "./KeeperRegistryBase2_1.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; + +enum RegistryVersion { + V12, + V13, + V20, + V21 +} + +/** + * @dev structs copied directly from source (can't import without changing the contract version) + */ +struct UpkeepV12 { + uint96 balance; + address lastKeeper; + uint32 executeGas; + uint64 maxValidBlocknumber; + address target; + uint96 amountSpent; + address admin; +} + +struct UpkeepV13 { + uint96 balance; + address lastKeeper; + uint96 amountSpent; + address admin; + uint32 executeGas; + uint32 maxValidBlocknumber; + address target; + bool paused; +} + +struct UpkeepV20 { + uint32 executeGas; + uint32 maxValidBlocknumber; + bool paused; + address target; + uint96 amountSpent; + uint96 balance; + uint32 lastPerformedBlockNumber; +} + +/** + * @notice UpkeepTranscoder allows converting upkeep data from previous keeper registry versions 1.2, 1.3, and + * 2.0 to registry 2.1 + */ +contract UpkeepTranscoder4_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { + error InvalidTranscoding(); + + /** + * @notice versions: + * - UpkeepTranscoder 4.0.0: adds support for registry 2.1; adds support for offchainConfigs + * - UpkeepTranscoder 3.0.0: works with registry 2.0; adds temporary workaround for UpkeepFormat enum bug + */ + string public constant override typeAndVersion = "UpkeepTranscoder 4.0.0"; + uint32 internal constant UINT32_MAX = type(uint32).max; + IAutomationForwarder internal constant ZERO_FORWARDER = IAutomationForwarder(address(0)); + + /** + * @notice transcodeUpkeeps transforms upkeep data from the format expected by + * one registry to the format expected by another. It future-proofs migrations + * by allowing keepers team to customize migration paths and set sensible defaults + * when new fields are added + * @param fromVersion struct version the upkeep is migrating from + * @param encodedUpkeeps encoded upkeep data + * @dev this transcoder should ONLY be use for V1/V2 --> V3 migrations + * @dev this transcoder **ignores** the toVersion param, as it assumes all migrations are + * for the V3 version. Therefore, it is the responsibility of the deployer of this contract + * to ensure it is not used in any other migration paths. + */ + function transcodeUpkeeps( + uint8 fromVersion, + uint8, + bytes calldata encodedUpkeeps + ) external view override returns (bytes memory) { + // v1.2 => v2.1 + if (fromVersion == uint8(RegistryVersion.V12)) { + (uint256[] memory ids, UpkeepV12[] memory upkeepsV12, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], UpkeepV12[], bytes[]) + ); + if (ids.length != upkeepsV12.length || ids.length != checkDatas.length) { + revert InvalidTranscoding(); + } + address[] memory targets = new address[](ids.length); + address[] memory admins = new address[](ids.length); + R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); + UpkeepV12 memory upkeepV12; + for (uint256 idx = 0; idx < ids.length; idx++) { + upkeepV12 = upkeepsV12[idx]; + newUpkeeps[idx] = R21.Upkeep({ + performGas: upkeepV12.executeGas, + maxValidBlocknumber: UINT32_MAX, // maxValidBlocknumber is uint64 in V1, hence a new default value is provided + paused: false, // migrated upkeeps are not paused by default + forwarder: ZERO_FORWARDER, + amountSpent: upkeepV12.amountSpent, + balance: upkeepV12.balance, + lastPerformedBlockNumber: 0 + }); + targets[idx] = upkeepV12.target; + admins[idx] = upkeepV12.admin; + } + return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, new bytes[](ids.length), new bytes[](ids.length)); + } + // v1.3 => v2.1 + if (fromVersion == uint8(RegistryVersion.V13)) { + (uint256[] memory ids, UpkeepV13[] memory upkeepsV13, bytes[] memory checkDatas) = abi.decode( + encodedUpkeeps, + (uint256[], UpkeepV13[], bytes[]) + ); + if (ids.length != upkeepsV13.length || ids.length != checkDatas.length) { + revert InvalidTranscoding(); + } + address[] memory targets = new address[](ids.length); + address[] memory admins = new address[](ids.length); + R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); + UpkeepV13 memory upkeepV13; + for (uint256 idx = 0; idx < ids.length; idx++) { + upkeepV13 = upkeepsV13[idx]; + newUpkeeps[idx] = R21.Upkeep({ + performGas: upkeepV13.executeGas, + maxValidBlocknumber: upkeepV13.maxValidBlocknumber, + paused: upkeepV13.paused, + forwarder: ZERO_FORWARDER, + amountSpent: upkeepV13.amountSpent, + balance: upkeepV13.balance, + lastPerformedBlockNumber: 0 + }); + targets[idx] = upkeepV13.target; + admins[idx] = upkeepV13.admin; + } + return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, new bytes[](ids.length), new bytes[](ids.length)); + } + // v2.0 => v2.1 + if (fromVersion == uint8(RegistryVersion.V20)) { + (uint256[] memory ids, UpkeepV20[] memory upkeepsV20, bytes[] memory checkDatas, address[] memory admins) = abi + .decode(encodedUpkeeps, (uint256[], UpkeepV20[], bytes[], address[])); + if (ids.length != upkeepsV20.length || ids.length != checkDatas.length) { + revert InvalidTranscoding(); + } + // bit of a hack - transcodeUpkeeps should be a pure function + R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); + bytes[] memory emptyBytes = new bytes[](ids.length); + address[] memory targets = new address[](ids.length); + UpkeepV20 memory upkeepV20; + for (uint256 idx = 0; idx < ids.length; idx++) { + upkeepV20 = upkeepsV20[idx]; + newUpkeeps[idx] = R21.Upkeep({ + performGas: upkeepV20.executeGas, + maxValidBlocknumber: upkeepV20.maxValidBlocknumber, + paused: upkeepV20.paused, + forwarder: ZERO_FORWARDER, + amountSpent: upkeepV20.amountSpent, + balance: upkeepV20.balance, + lastPerformedBlockNumber: 0 + }); + targets[idx] = upkeepV20.target; + } + return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, emptyBytes, emptyBytes); + } + // v2.1 => v2.1 + if (fromVersion == uint8(RegistryVersion.V21)) { + return encodedUpkeeps; + } + + revert InvalidTranscoding(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol new file mode 100644 index 0000000..464e874 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; +import {AutomationRegistryLogicB2_2} from "./AutomationRegistryLogicB2_2.sol"; +import {Chainable} from "../Chainable.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; + +/** + * @notice Registry for adding work for Chainlink nodes to perform on client + * contracts. Clients must support the AutomationCompatibleInterface interface. + */ +contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chainable, IERC677Receiver { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @notice versions: + * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module + * KeeperRegistry 2.1.0: introduces support for log triggers + * removes the need for "wrapped perform data" + * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts + * fixes issue with arbitrum block number + * does an early return in case of stale report instead of revert + * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X + * KeeperRegistry 2.0.0: implement OCR interface + * KeeperRegistry 1.3.0: split contract into Proxy and Logic + * account for Arbitrum and Optimism L1 gas fee + * allow users to configure upkeeps + * KeeperRegistry 1.2.0: allow funding within performUpkeep + * allow configurable registry maxPerformGas + * add function to let admin change upkeep gas limit + * add minUpkeepSpend requirement + * upgrade to solidity v0.8 + * KeeperRegistry 1.1.0: added flatFeeMicroLink + * KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "AutomationRegistry 2.2.0"; + + /** + * @param logicA the address of the first logic contract, but cast as logicB in order to call logicB functions + */ + constructor( + AutomationRegistryLogicB2_2 logicA + ) + AutomationRegistryBase2_2( + logicA.getLinkAddress(), + logicA.getLinkNativeFeedAddress(), + logicA.getFastGasFeedAddress(), + logicA.getAutomationForwarderLogic(), + logicA.getAllowedReadOnlyAddress() + ) + Chainable(address(logicA)) + {} + + /** + * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors + */ + // solhint-disable-next-line gas-struct-packing + struct TransmitVars { + uint16 numUpkeepsPassedChecks; + uint256 totalCalldataWeight; + uint96 totalReimbursement; + uint96 totalPremium; + } + + // ================================================================ + // | ACTIONS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function transmit( + bytes32[3] calldata reportContext, + bytes calldata rawReport, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external override { + uint256 gasOverhead = gasleft(); + HotVars memory hotVars = s_hotVars; + + if (hotVars.paused) revert RegistryPaused(); + if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); + + // Verify signatures + if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); + if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); + _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); + + Report memory report = _decodeReport(rawReport); + + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + + _handleReport(hotVars, report, gasOverhead); + + if (epoch > hotVars.latestEpoch) { + s_hotVars.latestEpoch = epoch; + } + } + + function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private { + UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); + TransmitVars memory transmitVars = TransmitVars({ + numUpkeepsPassedChecks: 0, + totalCalldataWeight: 0, + totalReimbursement: 0, + totalPremium: 0 + }); + + uint256 blocknumber = hotVars.chainModule.blockNumber(); + uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); + + 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( + report.upkeepIds[i], + blocknumber, + report.triggers[i], + upkeepTransmitInfo[i], + hotVars + ); + + if (upkeepTransmitInfo[i].earlyChecksPassed) { + transmitVars.numUpkeepsPassedChecks += 1; + } else { + continue; + } + + // Actually perform the target upkeep + (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( + upkeepTransmitInfo[i].upkeep.forwarder, + report.gasLimits[i], + 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 (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 + gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD; + gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; + + { + uint96 reimbursement; + uint96 premium; + for (uint256 i = 0; i < report.upkeepIds.length; i++) { + if (upkeepTransmitInfo[i].earlyChecksPassed) { + (reimbursement, premium) = _postPerformPayment( + hotVars, + report.upkeepIds[i], + upkeepTransmitInfo[i].gasUsed, + report.fastGasWei, + report.linkNative, + gasOverhead, + (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight + ); + transmitVars.totalPremium += premium; + transmitVars.totalReimbursement += reimbursement; + + emit UpkeepPerformed( + report.upkeepIds[i], + upkeepTransmitInfo[i].performSuccess, + reimbursement + premium, + upkeepTransmitInfo[i].gasUsed, + gasOverhead, + report.triggers[i] + ); + } + } + } + // record payments + s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; + s_hotVars.totalPremium += transmitVars.totalPremium; + } + + /** + * @notice simulates the upkeep with the perform data returned from checkUpkeep + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + * @return success whether the call reverted or not + * @return gasUsed the amount of gas the target contract consumed + */ + function simulatePerformUpkeep( + uint256 id, + bytes calldata performData + ) external returns (bool success, uint256 gasUsed) { + _preventExecution(); + + if (s_hotVars.paused) revert RegistryPaused(); + Upkeep memory upkeep = s_upkeep[id]; + (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); + return (success, gasUsed); + } + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_expectedLinkBalance = s_expectedLinkBalance + amount; + emit FundsAdded(id, sender, uint96(amount)); + } + + // ================================================================ + // | SETTERS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override { + setConfigTypeSafe( + signers, + transmitters, + f, + abi.decode(onchainConfigBytes, (OnchainConfig)), + offchainConfigVersion, + offchainConfig + ); + } + + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) public onlyOwner { + if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); + if (f == 0) revert IncorrectNumberOfFaultyOracles(); + if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); + + // move all pooled payments out of the pool to each transmitter's balance + uint96 totalPremium = s_hotVars.totalPremium; + uint96 oldLength = uint96(s_transmittersList.length); + for (uint256 i = 0; i < oldLength; i++) { + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); + } + + // remove any old signer/transmitter addresses + address signerAddress; + address transmitterAddress; + for (uint256 i = 0; i < oldLength; i++) { + signerAddress = s_signersList[i]; + transmitterAddress = s_transmittersList[i]; + delete s_signers[signerAddress]; + // Do not delete the whole transmitter struct as it has balance information stored + s_transmitters[transmitterAddress].active = false; + } + delete s_signersList; + delete s_transmittersList; + + // add new signer/transmitter addresses + { + Transmitter memory transmitter; + address temp; + for (uint256 i = 0; i < signers.length; i++) { + if (s_signers[signers[i]].active) revert RepeatedSigner(); + if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); + s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); + + temp = transmitters[i]; + if (temp == ZERO_ADDRESS) revert InvalidTransmitter(); + transmitter = s_transmitters[temp]; + if (transmitter.active) revert RepeatedTransmitter(); + transmitter.active = true; + transmitter.index = uint8(i); + // new transmitters start afresh from current totalPremium + // some spare change of premium from previous pool will be forfeited + transmitter.lastCollected = totalPremium; + s_transmitters[temp] = transmitter; + } + } + s_signersList = signers; + s_transmittersList = transmitters; + + s_hotVars = HotVars({ + f: f, + paymentPremiumPPB: onchainConfig.paymentPremiumPPB, + flatFeeMicroLink: onchainConfig.flatFeeMicroLink, + stalenessSeconds: onchainConfig.stalenessSeconds, + gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, + paused: s_hotVars.paused, + reentrancyGuard: s_hotVars.reentrancyGuard, + totalPremium: totalPremium, + latestEpoch: 0, // DON restarts epoch + reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, + chainModule: onchainConfig.chainModule + }); + + s_storage = Storage({ + checkGasLimit: onchainConfig.checkGasLimit, + minUpkeepSpend: onchainConfig.minUpkeepSpend, + maxPerformGas: onchainConfig.maxPerformGas, + transcoder: onchainConfig.transcoder, + maxCheckDataSize: onchainConfig.maxCheckDataSize, + maxPerformDataSize: onchainConfig.maxPerformDataSize, + maxRevertDataSize: onchainConfig.maxRevertDataSize, + upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, + nonce: s_storage.nonce, + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + ownerLinkBalance: s_storage.ownerLinkBalance + }); + s_fallbackGasPrice = onchainConfig.fallbackGasPrice; + s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; + + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + s_storage.latestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); + s_storage.configCount += 1; + + bytes memory onchainConfigBytes = abi.encode(onchainConfig); + + s_latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + + for (uint256 idx = 0; idx < s_registrars.length(); idx++) { + s_registrars.remove(s_registrars.at(idx)); + } + + for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { + s_registrars.add(onchainConfig.registrars[idx]); + } + + emit ConfigSet( + previousConfigBlockNumber, + s_latestConfigDigest, + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); + } + + /** + * @inheritdoc OCR2Abstract + */ + function latestConfigDigestAndEpoch() + external + view + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (false, s_latestConfigDigest, s_hotVars.latestEpoch); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol new file mode 100644 index 0000000..6903f55 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol @@ -0,0 +1,861 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * AutomationRegistry and AutomationRegistryLogic + * @dev all errors, events, and internal functions should live here + */ +// solhint-disable-next-line max-states-count +abstract contract AutomationRegistryBase2_2 is ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; + bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint256 internal constant PERFORM_GAS_CUSHION = 5_000; + uint256 internal constant PPB_BASE = 1_000_000_000; + uint32 internal constant UINT32_MAX = type(uint32).max; + uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + /** + * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with + * MigratableAutomationRegistryInterfaceV1 - it should be removed in future versions in favor of + * UPKEEP_VERSION_BASE and MigratableAutomationRegistryInterfaceV2 + */ + UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; + uint8 internal constant UPKEEP_VERSION_BASE = 3; + + // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation + // These values are calibrated using hardhat tests which simulates various cases and verifies that + // the variables result in accurate estimation + uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 60_000; // Fixed gas overhead for conditional upkeeps + uint256 internal constant REGISTRY_LOG_OVERHEAD = 85_000; // Fixed gas overhead for log upkeeps + uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f + uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead + + // The overhead (in bytes) in addition to perform data for upkeep sent in calldata + // This includes overhead for all struct encoding as well as report signatures + // There is a fixed component and a per signer component. This is calculated exactly by doing abi encoding + uint256 internal constant TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD = 932; + uint256 internal constant TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD = 64; + + // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the + // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants + // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that + // the variables result in accurate estimation + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 22_000; // Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 7_000; // Overhead per upkeep performed in batch + + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_linkNativeFeed; + AggregatorV3Interface internal immutable i_fastGasFeed; + address internal immutable i_automationForwarderLogic; + address internal immutable i_allowedReadOnlyAddress; + + /** + * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit + * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path + */ + + // Upkeep storage + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit + mapping(uint256 => address) internal s_upkeepAdmin; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + mapping(bytes32 => bool) internal s_dedupKeys; + // Registry config and state + EnumerableSet.AddressSet internal s_registrars; + mapping(address => Transmitter) internal s_transmitters; + mapping(address => Signer) internal s_signers; + address[] internal s_signersList; // s_signersList contains the signing address of each oracle + address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle + mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. + mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter + bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification + HotVars internal s_hotVars; // Mixture of config and state, used in transmit + Storage internal s_storage; // Mixture of config and state, not used in transmit + uint256 internal s_fallbackGasPrice; + uint256 internal s_fallbackLinkPrice; + uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro + mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers + mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep + mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep + mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin + + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InvalidDataLength(); + error InvalidTrigger(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidTransmitter(); + error InvalidTriggerType(); + error MaxCheckDataSizeCanOnlyIncrease(); + error MaxPerformDataSizeCanOnlyIncrease(); + error MigrationNotPermitted(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error PaymentGreaterThanAllLINK(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum Trigger { + CONDITION, + LOG + } + + enum UpkeepFailureReason { + NONE, + UPKEEP_CANCELLED, + UPKEEP_PAUSED, + TARGET_CHECK_REVERTED, + UPKEEP_NOT_NEEDED, + PERFORM_DATA_EXCEEDS_LIMIT, + INSUFFICIENT_BALANCE, + CALLBACK_REVERTED, + REVERT_DATA_EXCEEDS_LIMIT, + REGISTRY_PAUSED + } + + /** + * @notice OnchainConfig of the registry + * @dev used only in setConfig() + * @member paymentPremiumPPB payment premium rate oracles receive on top of + * being reimbursed for gas, measured in parts per billion + * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, + * priced in MicroLink; can be used in conjunction with or independently of + * paymentPremiumPPB + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling + * @member maxPerformGas max performGas allowed for an upkeep on this registry + * @member maxCheckDataSize max length of checkData bytes + * @member maxPerformDataSize max length of performData bytes + * @member maxRevertDataSize max length of revertData bytes + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrars addresses of the registrar contracts + * @member upkeepPrivilegeManager address which can set privilege for upkeeps + * @member reorgProtectionEnabled if this registry enables re-org protection checks + * @member chainModule the chain specific module + */ + // solhint-disable-next-line gas-struct-packing + struct OnchainConfig { + uint32 paymentPremiumPPB; + uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK + uint32 checkGasLimit; + uint24 stalenessSeconds; + uint16 gasCeilingMultiplier; + uint96 minUpkeepSpend; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + address transcoder; + address[] registrars; + address upkeepPrivilegeManager; + IChainModule chainModule; + bool reorgProtectionEnabled; + } + + /** + * @notice relevant state of an upkeep which is used in transmit function + * @member paused if this upkeep has been paused + * @member performGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member forwarder the forwarder contract to use for this upkeep + * @member amountSpent the amount this upkeep has spent + * @member balance the balance of this upkeep + * @member lastPerformedBlockNumber the last block number when this upkeep was performed + */ + struct Upkeep { + bool paused; + uint32 performGas; + uint32 maxValidBlocknumber; + IAutomationForwarder forwarder; + // 0 bytes left in 1st EVM word - not written to in transmit + uint96 amountSpent; + uint96 balance; + uint32 lastPerformedBlockNumber; + // 2 bytes left in 2nd EVM word - written in transmit path + } + + /// @dev Config + State storage struct which is on hot transmit path + struct HotVars { + uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium + uint32 paymentPremiumPPB; // │ premium percentage charged to user over tx cost + uint32 flatFeeMicroLink; // │ flat fee charged to user for every perform + uint32 latestEpoch; // │ latest epoch for which a report was transmitted + uint24 stalenessSeconds; // │ Staleness tolerance for feeds + uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound + uint8 f; // │ maximum number of faulty oracles + bool paused; // │ pause switch for all upkeeps in the registry + bool reentrancyGuard; // ────────╯ guard against reentrancy + bool reorgProtectionEnabled; // if this registry should enable re-org protection mechanism + IChainModule chainModule; // the interface of chain specific module + } + + /// @dev Config + State storage struct which is not on hot transmit path + struct Storage { + uint96 minUpkeepSpend; // Minimum amount an upkeep must spend + address transcoder; // Address of transcoder contract used in migrations + // 1 EVM word full + uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent + uint32 checkGasLimit; // Gas limit allowed in checkUpkeep + uint32 maxPerformGas; // Max gas an upkeep can use on this registry + uint32 nonce; // Nonce for each upkeep created + uint32 configCount; // incremented each time a new config is posted, The count + // is incorporated into the config digest to prevent replay attacks. + uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs + // 2 EVM word full + uint32 maxCheckDataSize; // max length of checkData bytes + uint32 maxPerformDataSize; // max length of performData bytes + uint32 maxRevertDataSize; // max length of revertData bytes + address upkeepPrivilegeManager; // address which can set privilege for upkeeps + // 3 EVM word full + } + + /// @dev Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkNative; + uint256[] upkeepIds; + uint256[] gasLimits; + bytes[] triggers; + bytes[] performDatas; + } + + /** + * @dev This struct is used to maintain run time information about an upkeep in transmit function + * @member upkeep the upkeep struct + * @member earlyChecksPassed whether the upkeep passed early checks before perform + * @member performSuccess whether the perform was successful + * @member triggerType the type of trigger + * @member gasUsed gasUsed by this upkeep in perform + * @member calldataWeight weight assigned to this upkeep for its contribution to calldata. It is used to split L1 fee + * @member dedupID unique ID used to dedup an upkeep/trigger combo + */ + struct UpkeepTransmitInfo { + Upkeep upkeep; + bool earlyChecksPassed; + bool performSuccess; + Trigger triggerType; + uint256 gasUsed; + uint256 calldataWeight; + bytes32 dedupID; + } + + struct Transmitter { + bool active; + uint8 index; // Index of oracle in s_signersList/s_transmittersList + uint96 balance; + uint96 lastCollected; + } + + struct Signer { + bool active; + // Index of oracle in s_signersList/s_transmittersList + uint8 index; + } + + /** + * @notice the trigger structure conditional trigger type + */ + struct ConditionalTrigger { + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the trigger structure of log upkeeps + * @dev NOTE that blockNum / blockHash describe the block used for the callback, + * not necessarily the block number that the log was emitted in!!!! + */ + struct LogTrigger { + bytes32 logBlockHash; + bytes32 txHash; + uint32 logIndex; + uint32 blockNum; + bytes32 blockHash; + } + + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event OwnerFundsWithdrawn(uint96 amount); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + event Unpaused(address account); + + /** + * @param link address of the LINK Token + * @param linkNativeFeed address of the LINK/Native price feed + * @param fastGasFeed address of the Fast Gas price feed + * @param automationForwarderLogic the address of automation forwarder logic + * @param allowedReadOnlyAddress the address of the allowed read only address + */ + constructor( + address link, + address linkNativeFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress + ) ConfirmedOwner(msg.sender) { + i_link = LinkTokenInterface(link); + i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); + i_fastGasFeed = AggregatorV3Interface(fastGasFeed); + i_automationForwarderLogic = automationForwarderLogic; + i_allowedReadOnlyAddress = allowedReadOnlyAddress; + } + + // ================================================================ + // | INTERNAL FUNCTIONS ONLY | + // ================================================================ + + /** + * @dev creates a new upkeep with the given fields + * @param id the id of the upkeep + * @param upkeep the upkeep to create + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data which is passed to user's checkUpkeep + * @param triggerConfig the trigger config for this upkeep + * @param offchainConfig the off-chain config of this upkeep + */ + function _createUpkeep( + uint256 id, + Upkeep memory upkeep, + address admin, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) internal { + if (s_hotVars.paused) revert RegistryPaused(); + if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) + revert GasLimitOutsideRange(); + if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); + s_upkeep[id] = upkeep; + s_upkeepAdmin[id] = admin; + s_checkData[id] = checkData; + s_expectedLinkBalance = s_expectedLinkBalance + upkeep.balance; + s_upkeepTriggerConfig[id] = triggerConfig; + s_upkeepOffchainConfig[id] = offchainConfig; + s_upkeepIDs.add(id); + } + + /** + * @dev creates an ID for the upkeep based on the upkeep's type + * @dev the format of the ID looks like this: + * ****00000000000X**************** + * 4 bytes of entropy + * 11 bytes of zeros + * 1 identifying byte for the trigger type + * 16 bytes of entropy + * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique + * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only + * see the first 4 and last 4 hex values ex 0x1234...ABCD + */ + function _createID(Trigger triggerType) internal view returns (uint256) { + bytes1 empty; + IChainModule chainModule = s_hotVars.chainModule; + bytes memory idBytes = abi.encodePacked( + keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) + ); + for (uint256 idx = 4; idx < 15; idx++) { + idBytes[idx] = empty; + } + idBytes[15] = bytes1(uint8(triggerType)); + return uint256(bytes32(idBytes)); + } + + /** + * @dev retrieves feed data for fast gas/native and link/native prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { + uint32 stalenessSeconds = hotVars.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + linkNative = s_fallbackLinkPrice; + } else { + linkNative = uint256(feedValue); + } + return (gasWei, linkNative); + } + + /** + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @param gasLimit the amount of gas used + * @param gasOverhead the amount of gas overhead + * @param l1CostWei the amount to be charged for L1 fee in wei + * @param fastGasWei the fast gas price + * @param linkNative the exchange ratio between LINK and Native token + * @param isExecution if this is triggered by a perform upkeep function + */ + function _calculatePaymentAmount( + HotVars memory hotVars, + uint256 gasLimit, + uint256 gasOverhead, + uint256 l1CostWei, + uint256 fastGasWei, + uint256 linkNative, + bool isExecution + ) internal view returns (uint96, uint96) { + uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (isExecution && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; + uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / + linkNative + + uint256(hotVars.flatFeeMicroLink) * + 1e12; + // LINK_TOTAL_SUPPLY < UINT96_MAX + if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); + return (uint96(gasPayment), uint96(premium)); + } + + /** + * @dev calculates the max LINK payment for an upkeep. Called during checkUpkeep simulation and assumes + * maximum gas overhead, L1 fee + */ + function _getMaxLinkPayment( + HotVars memory hotVars, + Trigger triggerType, + uint32 performGas, + uint256 fastGasWei, + uint256 linkNative + ) internal view returns (uint96) { + uint256 maxGasOverhead; + if (triggerType == Trigger.CONDITION) { + maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; + } else if (triggerType == Trigger.LOG) { + maxGasOverhead = REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } + uint256 maxCalldataSize = s_storage.maxPerformDataSize + + TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + + (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); + (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) = s_hotVars.chainModule.getGasOverhead(); + maxGasOverhead += + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + + ((REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD + chainModulePerByteOverhead) * maxCalldataSize) + + chainModuleFixedOverhead; + + uint256 maxL1Fee = hotVars.gasCeilingMultiplier * hotVars.chainModule.getMaxL1Fee(maxCalldataSize); + + (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( + hotVars, + performGas, + maxGasOverhead, + maxL1Fee, + fastGasWei, + linkNative, + false //isExecution + ); + + return reimbursement + premium; + } + + /** + * @dev move a transmitter's balance from total pool to withdrawable balance + */ + function _updateTransmitterBalanceFromPool( + address transmitterAddress, + uint96 totalPremium, + uint96 payeeCount + ) internal returns (uint96) { + Transmitter memory transmitter = s_transmitters[transmitterAddress]; + + if (transmitter.active) { + uint96 uncollected = totalPremium - transmitter.lastCollected; + uint96 due = uncollected / payeeCount; + transmitter.balance += due; + transmitter.lastCollected += due * payeeCount; + s_transmitters[transmitterAddress] = transmitter; + } + + return transmitter.balance; + } + + /** + * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) + */ + function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { + bytes32 rawID = bytes32(upkeepId); + bytes1 empty = bytes1(0); + for (uint256 idx = 4; idx < 15; idx++) { + if (rawID[idx] != empty) { + // old IDs that were created before this standard and migrated to this registry + return Trigger.CONDITION; + } + } + return Trigger(uint8(rawID[15])); + } + + function _checkPayload( + uint256 upkeepId, + Trigger triggerType, + bytes memory triggerData + ) internal view returns (bytes memory) { + if (triggerType == Trigger.CONDITION) { + return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); + } else if (triggerType == Trigger.LOG) { + Log memory log = abi.decode(triggerData, (Log)); + return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); + } + revert InvalidTriggerType(); + } + + /** + * @dev _decodeReport decodes a serialized report into a Report struct + */ + function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { + Report memory report = abi.decode(rawReport, (Report)); + uint256 expectedLength = report.upkeepIds.length; + if ( + report.gasLimits.length != expectedLength || + report.triggers.length != expectedLength || + report.performDatas.length != expectedLength + ) { + revert InvalidReport(); + } + return report; + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + * @return bool whether the upkeep should be performed + * @return bytes32 dedupID for preventing duplicate performances of this trigger + */ + function _prePerformChecks( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + bytes32 dedupID; + if (transmitInfo.triggerType == Trigger.CONDITION) { + if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) + return (false, dedupID); + } else if (transmitInfo.triggerType == Trigger.LOG) { + bool valid; + (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); + if (!valid) return (false, dedupID); + } else { + revert InvalidTriggerType(); + } + if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { + // Can happen when an upkeep got cancelled after report was generated. + // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice + emit CancelledUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + */ + function _validateConditionalTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool) { + ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); + if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { + // Can happen when another report performed this upkeep after this report was generated + emit StaleUpkeepReport(upkeepId, rawTrigger); + return false; + } + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // There are two cases of reorged report + // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain + // which is always protected against + // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is + // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain + // when it is sent + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return false; + } + return true; + } + + function _validateLogTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); + bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // Reorg protection is same as conditional trigger upkeeps + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + if (s_dedupKeys[dedupID]) { + emit StaleUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Verify signatures attached to report + */ + function _verifyReportSignature( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) internal view { + bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount = 0; + + Signer memory signer; + address signerAddress; + for (uint256 i = 0; i < rs.length; i++) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + signer = s_signers[signerAddress]; + if (!signer.active) revert OnlyActiveSigners(); + unchecked { + signedCount += 1 << (8 * signer.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); + } + + /** + * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances + * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID + */ + function _updateTriggerMarker( + uint256 upkeepID, + uint256 blocknumber, + UpkeepTransmitInfo memory upkeepTransmitInfo + ) internal { + if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { + s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); + } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { + s_dedupKeys[upkeepTransmitInfo.dedupID] = true; + emit DedupKeyAdded(upkeepTransmitInfo.dedupID); + } + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * transmitter and the exact gas required by the Upkeep + */ + function _performUpkeep( + IAutomationForwarder forwarder, + uint256 performGas, + bytes memory performData + ) internal nonReentrant returns (bool success, uint256 gasUsed) { + performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); + return forwarder.forward(performGas, performData); + } + + /** + * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases + * amount spent. + */ + function _postPerformPayment( + HotVars memory hotVars, + uint256 upkeepId, + uint256 gasUsed, + uint256 fastGasWei, + uint256 linkNative, + uint256 gasOverhead, + uint256 l1Fee + ) internal returns (uint96 gasReimbursement, uint96 premium) { + (gasReimbursement, premium) = _calculatePaymentAmount( + hotVars, + gasUsed, + gasOverhead, + l1Fee, + fastGasWei, + linkNative, + true // isExecution + ); + + uint96 balance = s_upkeep[upkeepId].balance; + uint96 payment = gasReimbursement + premium; + + // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user + // can't cover the amount owed + if (balance < gasReimbursement) { + payment = balance; + gasReimbursement = balance; + premium = 0; + } else if (balance < payment) { + payment = balance; + premium = payment - gasReimbursement; + } + + s_upkeep[upkeepId].balance -= payment; + s_upkeep[upkeepId].amountSpent += payment; + + return (gasReimbursement, premium); + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { + if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); + if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } + + /** + * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage + */ + modifier nonReentrant() { + if (s_hotVars.reentrancyGuard) revert ReentrantCall(); + s_hotVars.reentrancyGuard = true; + _; + s_hotVars.reentrancyGuard = false; + } + + /** + * @notice only allows a pre-configured address to initiate offchain read + */ + function _preventExecution() internal view { + // solhint-disable-next-line avoid-tx-origin + if (tx.origin != i_allowedReadOnlyAddress) { + revert OnlySimulatedBackend(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol new file mode 100644 index 0000000..b176843 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol @@ -0,0 +1,433 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; +import {AutomationRegistryLogicB2_2} from "./AutomationRegistryLogicB2_2.sol"; +import {Chainable} from "../Chainable.sol"; +import {AutomationForwarder} from "../AutomationForwarder.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; + +/** + * @notice Logic contract, works in tandem with AutomationRegistry as a proxy + */ +contract AutomationRegistryLogicA2_2 is AutomationRegistryBase2_2, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @param logicB the address of the second logic contract + */ + constructor( + AutomationRegistryLogicB2_2 logicB + ) + AutomationRegistryBase2_2( + logicB.getLinkAddress(), + logicB.getLinkNativeFeedAddress(), + logicB.getFastGasFeedAddress(), + logicB.getAutomationForwarderLogic(), + logicB.getAllowedReadOnlyAddress() + ) + Chainable(address(logicB)) + {} + + /** + * @notice called by the automation DON to check if work is needed + * @param id the upkeep ID to check for work needed + * @param triggerData extra contextual data about the trigger (not used in all code paths) + * @dev this one of the core functions called in the hot path + * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility + * @dev there is an incongruency on what gets returned during failure modes + * ex sometimes we include price data, sometimes we omit it depending on the failure + */ + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + public + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ) + { + _preventExecution(); + + Trigger triggerType = _getTriggerType(id); + HotVars memory hotVars = s_hotVars; + Upkeep memory upkeep = s_upkeep[id]; + + if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); + if (upkeep.maxValidBlocknumber != UINT32_MAX) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); + if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); + + (fastGasWei, linkNative) = _getFeedData(hotVars); + uint96 maxLinkPayment = _getMaxLinkPayment(hotVars, triggerType, upkeep.performGas, fastGasWei, linkNative); + if (upkeep.balance < maxLinkPayment) { + return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); + } + + bytes memory callData = _checkPayload(id, triggerType, triggerData); + + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); + gasUsed = gasUsed - gasleft(); + + if (!success) { + // User's target check reverted. We capture the revert data here and pass it within performData + if (result.length > s_storage.maxRevertDataSize) { + return ( + false, + bytes(""), + UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + } + return ( + upkeepNeeded, + result, + UpkeepFailureReason.TARGET_CHECK_REVERTED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + } + + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) + return ( + false, + bytes(""), + UpkeepFailureReason.UPKEEP_NOT_NEEDED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + + if (performData.length > s_storage.maxPerformDataSize) + return ( + false, + bytes(""), + UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkNative + ); + + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkNative); + } + + /** + * @notice see other checkUpkeep function for description + * @dev this function may be deprecated in a future version of chainlink automation + */ + function checkUpkeep( + uint256 id + ) + external + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkNative + ) + { + return checkUpkeep(id, bytes("")); + } + + /** + * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) + * @param id the upkeepID to execute a callback for + * @param values the values returned from the data streams lookup + * @param extraData the user-provided extra context data + */ + function checkCallback( + uint256 id, + bytes[] memory values, + bytes calldata extraData + ) + external + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); + return executeCallback(id, payload); + } + + /** + * @notice this is a generic callback executor that forwards a call to a user's contract with the configured + * gas limit + * @param id the upkeepID to execute a callback for + * @param payload the data (including function selector) to call on the upkeep target contract + */ + function executeCallback( + uint256 id, + bytes memory payload + ) + public + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + _preventExecution(); + + Upkeep memory upkeep = s_upkeep[id]; + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); + gasUsed = gasUsed - gasleft(); + if (!success) { + return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); + } + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) { + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); + } + if (performData.length > s_storage.maxPerformDataSize) { + return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); + } + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); + } + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param triggerType the trigger for the upkeep + * @param checkData data passed to the contract when checking for upkeep + * @param triggerConfig the config for the trigger + * @param offchainConfig arbitrary offchain config for the upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + Trigger triggerType, + bytes calldata checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) public returns (uint256 id) { + if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); + if (!target.isContract()) revert NotAContract(); + id = _createID(triggerType); + IAutomationForwarder forwarder = IAutomationForwarder( + address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) + ); + _createUpkeep( + id, + Upkeep({ + performGas: gasLimit, + balance: 0, + maxValidBlocknumber: UINT32_MAX, + lastPerformedBlockNumber: 0, + amountSpent: 0, + paused: false, + forwarder: forwarder + }), + admin, + checkData, + triggerConfig, + offchainConfig + ); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + emit UpkeepCheckDataSet(id, checkData); + emit UpkeepTriggerConfigSet(id, triggerConfig); + emit UpkeepOffchainConfigSet(id, offchainConfig); + return (id); + } + + /** + * @notice this function registers a conditional upkeep, using a backwards compatible function signature + * @dev this function is backwards compatible with versions <=2.0, but may be removed in a future version + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + bytes calldata checkData, + bytes calldata offchainConfig + ) external returns (uint256 id) { + return registerUpkeep(target, gasLimit, admin, Trigger.CONDITION, checkData, bytes(""), offchainConfig); + } + + /** + * @notice cancels an upkeep + * @param id the upkeepID to cancel + * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to + * allow any pending performUpkeep txs time to get confirmed + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool isOwner = msg.sender == owner(); + + uint256 height = s_hotVars.chainModule.blockNumber(); + if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); + + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minUpkeepSpend is not met + uint96 minUpkeepSpend = s_storage.minUpkeepSpend; + uint96 cancellationFee = 0; + // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) + if (upkeep.amountSpent < minUpkeepSpend) { + cancellationFee = minUpkeepSpend - upkeep.amountSpent; + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @notice adds fund to an upkeep + * @param id the upkeepID + * @param amount the amount of LINK to fund, in jules (jules = "wei" of LINK) + */ + function addFunds(uint256 id, uint96 amount) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + s_upkeep[id].balance = upkeep.balance + amount; + s_expectedLinkBalance = s_expectedLinkBalance + amount; + i_link.transferFrom(msg.sender, address(this), amount); + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @notice migrates upkeeps from one registry to another + * @param ids the upkeepIDs to migrate + * @param destination the destination registry address + * @dev a transcoder must be set in order to enable migration + * @dev migration permissions must be set on *both* sending and receiving registries + * @dev only an upkeep admin can migrate their upkeeps + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + uint256 id; + Upkeep memory upkeep; + uint256 totalBalanceRemaining; + address[] memory admins = new address[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + bytes[] memory checkDatas = new bytes[](ids.length); + bytes[] memory triggerConfigs = new bytes[](ids.length); + bytes[] memory offchainConfigs = new bytes[](ids.length); + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + _requireAdminAndNotCancelled(id); + upkeep.forwarder.updateRegistry(destination); + upkeeps[idx] = upkeep; + admins[idx] = s_upkeepAdmin[id]; + checkDatas[idx] = s_checkData[id]; + triggerConfigs[idx] = s_upkeepTriggerConfig[id]; + offchainConfigs[idx] = s_upkeepOffchainConfig[id]; + totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; + delete s_upkeep[id]; + delete s_checkData[id]; + delete s_upkeepTriggerConfig[id]; + delete s_upkeepOffchainConfig[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; + bytes memory encodedUpkeeps = abi.encode( + ids, + upkeeps, + new address[](ids.length), + admins, + checkDatas, + triggerConfigs, + offchainConfigs + ); + MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( + UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( + UPKEEP_VERSION_BASE, + MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), + encodedUpkeeps + ) + ); + i_link.transfer(destination, totalBalanceRemaining); + } + + /** + * @notice received upkeeps migrated from another registry + * @param encodedUpkeeps the raw upkeep data to import + * @dev this function is never called directly, it is only called by another registry's migrate function + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + ( + uint256[] memory ids, + Upkeep[] memory upkeeps, + address[] memory targets, + address[] memory upkeepAdmins, + bytes[] memory checkDatas, + bytes[] memory triggerConfigs, + bytes[] memory offchainConfigs + ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); + for (uint256 idx = 0; idx < ids.length; idx++) { + if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { + upkeeps[idx].forwarder = IAutomationForwarder( + address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) + ); + } + _createUpkeep( + ids[idx], + upkeeps[idx], + upkeepAdmins[idx], + checkDatas[idx], + triggerConfigs[idx], + offchainConfigs[idx] + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } + + /** + * @notice sets the upkeep trigger config + * @param id the upkeepID to change the trigger for + * @param triggerConfig the new trigger config + */ + function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { + _requireAdminAndNotCancelled(id); + s_upkeepTriggerConfig[id] = triggerConfig; + emit UpkeepTriggerConfigSet(id, triggerConfig); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol new file mode 100644 index 0000000..f6d1ea8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol @@ -0,0 +1,540 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +contract AutomationRegistryLogicB2_2 is AutomationRegistryBase2_2 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @dev see AutomationRegistry master contract for constructor description + */ + constructor( + address link, + address linkNativeFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress + ) AutomationRegistryBase2_2(link, linkNativeFeed, fastGasFeed, automationForwarderLogic, allowedReadOnlyAddress) {} + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice transfers the address of an admin for an upkeep + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + _requireAdminAndNotCancelled(id); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of an upkeep admin + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = s_upkeepAdmin[id]; + s_upkeepAdmin[id] = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused + */ + function pauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @notice unpauses an upkeep + */ + function unpauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @notice updates the checkData for an upkeep + */ + function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { + _requireAdminAndNotCancelled(id); + if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataSet(id, newCheckData); + } + + /** + * @notice updates the gas limit for an upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + _requireAdminAndNotCancelled(id); + s_upkeep[id].performGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @notice updates the offchain config for an upkeep + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { + _requireAdminAndNotCancelled(id); + s_upkeepOffchainConfig[id] = config; + emit UpkeepOffchainConfigSet(id, config); + } + + /** + * @notice withdraws LINK funds from an upkeep + * @dev note that an upkeep must be cancelled first!! + */ + function withdrawFunds(uint256 id, address to) external nonReentrant { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); + uint96 amountToWithdraw = s_upkeep[id].balance; + s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; + s_upkeep[id].balance = 0; + i_link.transfer(to, amountToWithdraw); + emit FundsWithdrawn(id, amountToWithdraw, to); + } + + // ================================================================ + // | NODE MANAGEMENT | + // ================================================================ + + /** + * @notice transfers the address of payee for a transmitter + */ + function transferPayeeship(address transmitter, address proposed) external { + if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[transmitter] != proposed) { + s_proposedPayee[transmitter] = proposed; + emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of the payee + */ + function acceptPayeeship(address transmitter) external { + if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_transmitterPayees[transmitter]; + s_transmitterPayees[transmitter] = msg.sender; + s_proposedPayee[transmitter] = ZERO_ADDRESS; + + emit PayeeshipTransferred(transmitter, past, msg.sender); + } + + /** + * @notice withdraws LINK received as payment for work performed + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); + uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); + s_transmitters[from].balance = 0; + s_expectedLinkBalance = s_expectedLinkBalance - balance; + i_link.transfer(to, balance); + emit PaymentWithdrawn(from, balance, to, msg.sender); + } + + // ================================================================ + // | OWNER / MANAGER ACTIONS | + // ================================================================ + + /** + * @notice sets the privilege config for an upkeep + */ + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; + emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); + } + + /** + * @notice withdraws the owner's LINK balance + */ + function withdrawOwnerFunds() external onlyOwner { + uint96 amount = s_storage.ownerLinkBalance; + s_expectedLinkBalance = s_expectedLinkBalance - amount; + s_storage.ownerLinkBalance = 0; + emit OwnerFundsWithdrawn(amount); + i_link.transfer(msg.sender, amount); + } + + /** + * @notice allows the owner to withdraw any LINK accidentally sent to the contract + */ + function recoverFunds() external onlyOwner { + uint256 total = i_link.balanceOf(address(this)); + i_link.transfer(msg.sender, total - s_expectedLinkBalance); + } + + /** + * @notice sets the payees for the transmitters + */ + function setPayees(address[] calldata payees) external onlyOwner { + if (s_transmittersList.length != payees.length) revert ParameterLengthError(); + for (uint256 i = 0; i < s_transmittersList.length; i++) { + address transmitter = s_transmittersList[i]; + address oldPayee = s_transmitterPayees[transmitter]; + address newPayee = payees[i]; + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) revert InvalidPayee(); + if (newPayee != IGNORE_ADDRESS) { + s_transmitterPayees[transmitter] = newPayee; + } + } + emit PayeesUpdated(s_transmittersList, payees); + } + + /** + * @notice sets the migration permission for a peer registry + * @dev this must be done before upkeeps can be migrated to/from another registry + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @notice pauses the entire registry + */ + function pause() external onlyOwner { + s_hotVars.paused = true; + emit Paused(msg.sender); + } + + /** + * @notice unpauses the entire registry + */ + function unpause() external onlyOwner { + s_hotVars.paused = false; + emit Unpaused(msg.sender); + } + + /** + * @notice sets a generic bytes field used to indicate the privilege that this admin address had + * @param admin the address to set privilege for + * @param newPrivilegeConfig the privileges that this admin has + */ + function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + s_adminPrivilegeConfig[admin] = newPrivilegeConfig; + emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + function getConditionalGasOverhead() external pure returns (uint256) { + return REGISTRY_CONDITIONAL_OVERHEAD; + } + + function getLogGasOverhead() external pure returns (uint256) { + return REGISTRY_LOG_OVERHEAD; + } + + function getPerPerformByteGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; + } + + function getPerSignerGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_SIGNER_GAS_OVERHEAD; + } + + function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256) { + return TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD; + } + + function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256) { + return TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD; + } + + function getCancellationDelay() external pure returns (uint256) { + return CANCELLATION_DELAY; + } + + function getLinkAddress() external view returns (address) { + return address(i_link); + } + + function getLinkNativeFeedAddress() external view returns (address) { + return address(i_linkNativeFeed); + } + + function getFastGasFeedAddress() external view returns (address) { + return address(i_fastGasFeed); + } + + function getAutomationForwarderLogic() external view returns (address) { + return i_automationForwarderLogic; + } + + function getAllowedReadOnlyAddress() external view returns (address) { + return i_allowedReadOnlyAddress; + } + + function upkeepTranscoderVersion() public pure returns (UpkeepFormat) { + return UPKEEP_TRANSCODER_VERSION_BASE; + } + + function upkeepVersion() public pure returns (uint8) { + return UPKEEP_VERSION_BASE; + } + + /** + * @notice read all of the details about an upkeep + * @dev this function may be deprecated in a future version of automation in favor of individual + * getters for each field + */ + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { + Upkeep memory reg = s_upkeep[id]; + address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); + upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ + target: target, + performGas: reg.performGas, + checkData: s_checkData[id], + balance: reg.balance, + admin: s_upkeepAdmin[id], + maxValidBlocknumber: reg.maxValidBlocknumber, + lastPerformedBlockNumber: reg.lastPerformedBlockNumber, + amountSpent: reg.amountSpent, + paused: reg.paused, + offchainConfig: s_upkeepOffchainConfig[id] + }); + return upkeepInfo; + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { + uint256 numUpkeeps = s_upkeepIDs.length(); + if (startIndex >= numUpkeeps) revert IndexOutOfRange(); + uint256 endIndex = startIndex + maxCount; + endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; + uint256[] memory ids = new uint256[](endIndex - startIndex); + for (uint256 idx = 0; idx < ids.length; idx++) { + ids[idx] = s_upkeepIDs.at(idx + startIndex); + } + return ids; + } + + /** + * @notice returns the upkeep's trigger type + */ + function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { + return _getTriggerType(upkeepId); + } + + /** + * @notice returns the trigger config for an upkeeep + */ + function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { + return s_upkeepTriggerConfig[upkeepId]; + } + + /** + * @notice read the current info about any transmitter address + */ + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { + Transmitter memory transmitter = s_transmitters[query]; + + uint96 pooledShare = 0; + if (transmitter.active) { + uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; + pooledShare = totalDifference / uint96(s_transmittersList.length); + } + + return ( + transmitter.active, + transmitter.index, + (transmitter.balance + pooledShare), + transmitter.lastCollected, + s_transmitterPayees[query] + ); + } + + /** + * @notice read the current info about any signer address + */ + function getSignerInfo(address query) external view returns (bool active, uint8 index) { + Signer memory signer = s_signers[query]; + return (signer.active, signer.index); + } + + /** + * @notice read the current state of the registry + * @dev this function is deprecated + */ + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) + { + state = IAutomationV21PlusCommon.StateLegacy({ + nonce: s_storage.nonce, + ownerLinkBalance: s_storage.ownerLinkBalance, + expectedLinkBalance: s_expectedLinkBalance, + totalPremium: s_hotVars.totalPremium, + numUpkeeps: s_upkeepIDs.length(), + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + latestConfigDigest: s_latestConfigDigest, + latestEpoch: s_hotVars.latestEpoch, + paused: s_hotVars.paused + }); + + config = IAutomationV21PlusCommon.OnchainConfigLegacy({ + paymentPremiumPPB: s_hotVars.paymentPremiumPPB, + flatFeeMicroLink: s_hotVars.flatFeeMicroLink, + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + minUpkeepSpend: s_storage.minUpkeepSpend, + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager + }); + + return (state, config, s_signersList, s_transmittersList, s_hotVars.f); + } + + /** + * @notice get the chain module + */ + function getChainModule() external view returns (IChainModule chainModule) { + return s_hotVars.chainModule; + } + + /** + * @notice if this registry has reorg protection enabled + */ + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { + return s_hotVars.reorgProtectionEnabled; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getBalance(uint256 id) external view returns (uint96 balance) { + return s_upkeep[id].balance; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalance(uint256 id) external view returns (uint96) { + return getMinBalanceForUpkeep(id); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + * @dev this will be deprecated in a future version in favor of getMinBalance + */ + function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { + return getMaxPaymentForGas(_getTriggerType(id), s_upkeep[id].performGas); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas(Trigger triggerType, uint32 gasLimit) public view returns (uint96 maxPayment) { + HotVars memory hotVars = s_hotVars; + (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); + return _getMaxLinkPayment(hotVars, triggerType, gasLimit, fastGasWei, linkNative); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { + return s_upkeepPrivilegeConfig[upkeepId]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { + return s_adminPrivilegeConfig[admin]; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { + return s_upkeep[upkeepID].forwarder; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function hasDedupKey(bytes32 dedupKey) external view returns (bool) { + return s_dedupKeys[dedupKey]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol new file mode 100644 index 0000000..abdabeb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; +import {Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +/** + * @notice this file exposes structs that are otherwise internal to the automation registry + * doing this allows those structs to be encoded and decoded with type safety in offchain code + * and tests because generated wrappers are made available + */ + +/** + * @notice structure of trigger for log triggers + */ +struct LogTriggerConfig { + address contractAddress; + uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply + bytes32 topic0; + bytes32 topic1; + bytes32 topic2; + bytes32 topic3; +} + +contract AutomationUtils2_2 { + /** + * @dev this can be removed as OnchainConfig is now exposed directly from the registry + */ + function _onChainConfig(IAutomationV21PlusCommon.OnchainConfigLegacy memory) external {} // 0x2ff92a81 + + function _report(AutomationRegistryBase2_2.Report memory) external {} // 0xe65d6546 + + function _logTriggerConfig(LogTriggerConfig memory) external {} // 0x21f373d7 + + function _logTrigger(AutomationRegistryBase2_2.LogTrigger memory) external {} // 0x1c8d8260 + + function _conditionalTrigger(AutomationRegistryBase2_2.ConditionalTrigger memory) external {} // 0x4b6df294 + + function _log(Log memory) external {} // 0xe9720a49 +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE new file mode 100644 index 0000000..9230d39 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE @@ -0,0 +1,57 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +--- + +Parameters + +Licensor: SmartContract Chainlink Limited SEZC + +Licensed Work: Automation v2.2 +The Licensed Work is (c) 2024 SmartContract Chainlink Limited SEZC + +Additional Use Grant(s): +You may make use of Automation v2.1, v2.2 (which is available subject to the license here the “Licensed Work”) solely for purposes listed below: +https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md + +Change Date: January 22, 2028 + +Change License: MIT + +--- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. + +If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. + +MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. + +--- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. + +2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md new file mode 100644 index 0000000..abd3eb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md @@ -0,0 +1,40 @@ +# Automation Contract Structure + +The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. It is also too large to fit into 2 contracts, a solution that works for most large projects. Therefore, we included this explanation of how the pieces fit together and various tradeoffs incurred. + +### Glossary + +**Master Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the entry-point into the chain of delegatecalls. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) + +**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the master contract in order to increase our total capacity for on-chain code. + +### Overview + +We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fall back to the next, always executing the function in the scope of the master contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. + +### Diagram + +```mermaid +graph LR + Master -- delegatecall --> la[Logic A] + la -- delegatecall --> lb[Logic B] + lb -. delegatecall .-> lx[Logic X] +``` + +### Special Considerations + +- functions on the master contract have the least gas overhead, therefore, our most price-sensitive functions live there +- functions on the master contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there +- etherscan supports executing logic contract functions that are once removed from the master - therefore we give secondary preference to the first logic contract for user and debugging functions +- functions on logic A through logic X (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically +- We use Logic A, B, C... to avoid confusion with the version ex `AutomationRegistryLogicA2_2.sol` --> Logic Contract A verion 2.1 +- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break + +### Master Interface + +The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. This process is not a hardened one. Users of this script should take great care to ensure it's efficacy. + +[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 +[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function +[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries +[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol new file mode 100644 index 0000000..2effb8d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @notice Contract to accept requests for upkeep registrations + * @dev There are 2 registration workflows in this contract + * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually + * calls `approve` to register upkeep and emit events to inform UI and others interested. + * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on + * keeper registry and then emits approved event to finish the flow automatically without manual intervention. + * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. + * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. + */ +contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { + using SafeERC20 for IERC20; + + /** + * DISABLED: No auto approvals, all new upkeeps should be approved manually. + * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. + * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. + */ + enum AutoApproveType { + DISABLED, + ENABLED_SENDER_ALLOWLIST, + ENABLED_ALL + } + + /** + * @notice versions: + * - KeeperRegistrar 2.3.0: Update for compatability with registry 2.3.0 + * Add native billing and ERC20 billing support + * - KeeperRegistrar 2.1.0: Update for compatability with registry 2.1.0 + * Add auto approval levels by type + * - KeeperRegistrar 2.0.0: Remove source from register + * Breaks our example of "Register an Upkeep using your own deployed contract" + * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve + * : Remove rate limit and add max allowed for auto approve + * - KeeperRegistrar 1.0.0: initial release + */ + string public constant override typeAndVersion = "AutomationRegistrar 2.3.0"; + + /** + * @notice TriggerRegistrationStorage stores the auto-approval levels for upkeeps by type + * @member autoApproveType the auto approval setting (see enum) + * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + * @member approvedCount the count of upkeeps auto approved of this type + */ + struct TriggerRegistrationStorage { + AutoApproveType autoApproveType; + uint32 autoApproveMaxAllowed; + uint32 approvedCount; + } + + /** + * @notice InitialTriggerConfig configures the auto-approval levels for upkeeps by trigger type + * @dev this struct is only used in the constructor to set the initial values for various trigger configs + * @member triggerType the upkeep type to configure + * @member autoApproveType the auto approval setting (see enum) + * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + */ + // solhint-disable-next-line gas-struct-packing + struct InitialTriggerConfig { + uint8 triggerType; + AutoApproveType autoApproveType; + uint32 autoApproveMaxAllowed; + } + + struct PendingRequest { + address admin; + uint96 balance; + IERC20 billingToken; + } + /** + * @member upkeepContract address to perform upkeep on + * @member amount quantity of billing token upkeep is funded with (specified in the billing token's decimals) + * @member adminAddress address to cancel upkeep and withdraw remaining funds + * @member gasLimit amount of gas to provide the target contract when performing upkeep + * @member triggerType the type of trigger for the upkeep + * @member billingToken the token to pay with + * @member name string of the upkeep to be registered + * @member encryptedEmail email address of upkeep contact + * @member checkData data passed to the contract when checking for upkeep + * @member triggerConfig the config for the trigger + * @member offchainConfig offchainConfig for upkeep in bytes + */ + struct RegistrationParams { + address upkeepContract; + uint96 amount; + // 1 word full + address adminAddress; + uint32 gasLimit; + uint8 triggerType; + // 7 bytes left in 2nd word + IERC20 billingToken; + // 12 bytes left in 3rd word + string name; + bytes encryptedEmail; + bytes checkData; + bytes triggerConfig; + bytes offchainConfig; + } + + LinkTokenInterface public immutable i_LINK; + IWrappedNative public immutable i_WRAPPED_NATIVE_TOKEN; + IAutomationRegistryMaster2_3 private s_registry; + + // Only applicable if trigger config is set to ENABLED_SENDER_ALLOWLIST + mapping(address => bool) private s_autoApproveAllowedSenders; + mapping(IERC20 => uint256) private s_minRegistrationAmounts; + mapping(bytes32 => PendingRequest) private s_pendingRequests; + mapping(uint8 => TriggerRegistrationStorage) private s_triggerRegistrations; + + event RegistrationRequested( + bytes32 indexed hash, + string name, + bytes encryptedEmail, + address indexed upkeepContract, + uint32 gasLimit, + address adminAddress, + uint8 triggerType, + bytes triggerConfig, + bytes offchainConfig, + bytes checkData, + uint96 amount, + IERC20 billingToken + ); + + event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); + + event RegistrationRejected(bytes32 indexed hash); + + event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); + + event ConfigChanged(); + + event TriggerConfigSet(uint8 triggerType, AutoApproveType autoApproveType, uint32 autoApproveMaxAllowed); + + error HashMismatch(); + error InsufficientPayment(); + error InvalidAdminAddress(); + error InvalidBillingToken(); + error InvalidDataLength(); + error TransferFailed(address to); + error DuplicateEntry(); + error OnlyAdminOrOwner(); + error OnlyLink(); + error RequestNotFound(); + + /** + * @param LINKAddress Address of Link token + * @param registry keeper registry address + * @param triggerConfigs the initial config for individual triggers + * @param billingTokens the tokens allowed for billing + * @param minRegistrationFees the minimum amount for registering with each billing token + * @param wrappedNativeToken wrapped native token + */ + constructor( + address LINKAddress, + IAutomationRegistryMaster2_3 registry, + InitialTriggerConfig[] memory triggerConfigs, + IERC20[] memory billingTokens, + uint256[] memory minRegistrationFees, + IWrappedNative wrappedNativeToken + ) ConfirmedOwner(msg.sender) { + i_LINK = LinkTokenInterface(LINKAddress); + i_WRAPPED_NATIVE_TOKEN = wrappedNativeToken; + setConfig(registry, billingTokens, minRegistrationFees); + for (uint256 idx = 0; idx < triggerConfigs.length; idx++) { + setTriggerConfig( + triggerConfigs[idx].triggerType, + triggerConfigs[idx].autoApproveType, + triggerConfigs[idx].autoApproveMaxAllowed + ); + } + } + + //EXTERNAL + + /** + * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract + * @param requestParams struct of all possible registration parameters + */ + function registerUpkeep(RegistrationParams memory requestParams) external payable returns (uint256) { + if (requestParams.billingToken == IERC20(i_WRAPPED_NATIVE_TOKEN) && msg.value != 0) { + requestParams.amount = SafeCast.toUint96(msg.value); + // wrap and send native payment + i_WRAPPED_NATIVE_TOKEN.deposit{value: msg.value}(); + } else { + // send ERC20 payment, including wrapped native token + requestParams.billingToken.safeTransferFrom(msg.sender, address(this), requestParams.amount); + } + + return _register(requestParams, msg.sender); + } + + /** + * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event + * @param requestParams struct of all possible registration parameters + */ + function approve(RegistrationParams calldata requestParams) external onlyOwner { + bytes32 hash = keccak256(abi.encode(requestParams)); + + PendingRequest memory request = s_pendingRequests[hash]; + if (request.admin == address(0)) { + revert RequestNotFound(); + } + + delete s_pendingRequests[hash]; + _approve(requestParams, hash); + } + + /** + * @notice cancel will remove a registration request from the pending request queue and return the refunds to the request.admin + * @param hash the request hash + */ + function cancel(bytes32 hash) external { + PendingRequest memory request = s_pendingRequests[hash]; + + if (!(msg.sender == request.admin || msg.sender == owner())) { + revert OnlyAdminOrOwner(); + } + if (request.admin == address(0)) { + revert RequestNotFound(); + } + delete s_pendingRequests[hash]; + + request.billingToken.safeTransfer(request.admin, request.balance); + + emit RegistrationRejected(hash); + } + + /** + * @notice owner calls this function to set contract config + * @param registry new keeper registry address + * @param billingTokens the billing tokens that this registrar supports (registy must also support these) + * @param minBalances minimum balances that users must supply to register with the corresponding billing token + */ + function setConfig( + IAutomationRegistryMaster2_3 registry, + IERC20[] memory billingTokens, + uint256[] memory minBalances + ) public onlyOwner { + if (billingTokens.length != minBalances.length) revert InvalidDataLength(); + s_registry = registry; + for (uint256 i = 0; i < billingTokens.length; i++) { + s_minRegistrationAmounts[billingTokens[i]] = minBalances[i]; + } + emit ConfigChanged(); + } + + /** + * @notice owner calls to set the config for this upkeep type + * @param triggerType the upkeep type to configure + * @param autoApproveType the auto approval setting (see enum) + * @param autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type + */ + function setTriggerConfig( + uint8 triggerType, + AutoApproveType autoApproveType, + uint32 autoApproveMaxAllowed + ) public onlyOwner { + s_triggerRegistrations[triggerType].autoApproveType = autoApproveType; + s_triggerRegistrations[triggerType].autoApproveMaxAllowed = autoApproveMaxAllowed; + emit TriggerConfigSet(triggerType, autoApproveType, autoApproveMaxAllowed); + } + + /** + * @notice owner calls this function to set allowlist status for senderAddress + * @param senderAddress senderAddress to set the allowlist status for + * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed + */ + function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { + s_autoApproveAllowedSenders[senderAddress] = allowed; + + emit AutoApproveAllowedSenderSet(senderAddress, allowed); + } + + /** + * @notice read the allowlist status of senderAddress + * @param senderAddress address to read the allowlist status for + */ + function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { + return s_autoApproveAllowedSenders[senderAddress]; + } + + /** + * @notice gets the registry that this registrar is pointed to + */ + function getRegistry() external view returns (IAutomationRegistryMaster2_3) { + return s_registry; + } + + /** + * @notice get the minimum registration fee for a particular billing token + */ + function getMinimumRegistrationAmount(IERC20 billingToken) external view returns (uint256) { + return s_minRegistrationAmounts[billingToken]; + } + + /** + * @notice read the config for this upkeep type + * @param triggerType upkeep type to read config for + */ + function getTriggerRegistrationDetails(uint8 triggerType) external view returns (TriggerRegistrationStorage memory) { + return s_triggerRegistrations[triggerType]; + } + + /** + * @notice gets the admin address and the current balance of a registration request + */ + function getPendingRequest(bytes32 hash) external view returns (address, uint96) { + PendingRequest memory request = s_pendingRequests[hash]; + return (request.admin, request.balance); + } + + /** + * @notice Called when LINK is sent to the contract via `transferAndCall` + * @param sender Address of the sender transfering LINK + * @param amount Amount of LINK sent (specified in Juels) + * @param data Payload of the transaction + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_LINK)) revert OnlyLink(); + RegistrationParams memory params = abi.decode(data, (RegistrationParams)); + if (address(params.billingToken) != address(i_LINK)) revert OnlyLink(); + params.amount = uint96(amount); // ignore whatever is sent in registration params, use actual value; casting safe because max supply LINK < 2^96 + _register(params, sender); + } + + // ================================================================ + // | PRIVATE | + // ================================================================ + + /** + * @dev verify registration request and emit RegistrationRequested event + * @dev we don't allow multiple duplicate registrations by adding to the original registration's balance + * users can cancel and re-register if they want to update the registration + */ + function _register(RegistrationParams memory params, address sender) private returns (uint256) { + if (params.amount < s_minRegistrationAmounts[params.billingToken]) { + revert InsufficientPayment(); + } + if (params.adminAddress == address(0)) { + revert InvalidAdminAddress(); + } + if (!s_registry.supportsBillingToken(address(params.billingToken))) { + revert InvalidBillingToken(); + } + bytes32 hash = keccak256(abi.encode(params)); + + if (s_pendingRequests[hash].admin != address(0)) { + revert DuplicateEntry(); + } + + emit RegistrationRequested( + hash, + params.name, + params.encryptedEmail, + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.triggerType, + params.triggerConfig, + params.offchainConfig, + params.checkData, + params.amount, + params.billingToken + ); + + uint256 upkeepId; + if (_shouldAutoApprove(s_triggerRegistrations[params.triggerType], sender)) { + s_triggerRegistrations[params.triggerType].approvedCount++; + upkeepId = _approve(params, hash); + } else { + s_pendingRequests[hash] = PendingRequest({ + admin: params.adminAddress, + balance: params.amount, + billingToken: params.billingToken + }); + } + + return upkeepId; + } + + /** + * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event + * @dev safeApprove is deprecated and removed from the latest (v5) OZ release, Use safeIncreaseAllowance when we upgrade OZ (we are on v4.8) + * @dev we stick to the safeApprove because of the older version (v4.8) of safeIncreaseAllowance can't handle USDT correctly, but newer version can + */ + function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { + IAutomationRegistryMaster2_3 registry = s_registry; + uint256 upkeepId = registry.registerUpkeep( + params.upkeepContract, + params.gasLimit, + params.adminAddress, + params.triggerType, + address(params.billingToken), // have to cast as address because master interface doesn't use contract types + params.checkData, + params.triggerConfig, + params.offchainConfig + ); + + if (address(params.billingToken) == address(i_LINK)) { + bool success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); + if (!success) { + revert TransferFailed(address(registry)); + } + } else { + params.billingToken.safeApprove(address(registry), params.amount); + registry.addFunds(upkeepId, params.amount); + } + + emit RegistrationApproved(hash, params.name, upkeepId); + return upkeepId; + } + + /** + * @dev verify sender allowlist if needed and check max limit + */ + function _shouldAutoApprove(TriggerRegistrationStorage memory config, address sender) private view returns (bool) { + if (config.autoApproveType == AutoApproveType.DISABLED) { + return false; + } + if (config.autoApproveType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender])) { + return false; + } + if (config.approvedCount < config.autoApproveMaxAllowed) { + return true; + } + return false; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol new file mode 100644 index 0000000..031d7b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; +import {AutomationRegistryLogicA2_3} from "./AutomationRegistryLogicA2_3.sol"; +import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/** + * @notice Registry for adding work for Chainlink nodes to perform on client + * contracts. Clients must support the AutomationCompatibleInterface interface. + */ +contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @notice versions: + * AutomationRegistry 2.3.0: supports native and ERC20 billing + * changes flat fee to USD-denominated + * adds support for custom billing overrides + * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module + * KeeperRegistry 2.1.0: introduces support for log triggers + * removes the need for "wrapped perform data" + * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts + * fixes issue with arbitrum block number + * does an early return in case of stale report instead of revert + * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X + * KeeperRegistry 2.0.0: implement OCR interface + * KeeperRegistry 1.3.0: split contract into Proxy and Logic + * account for Arbitrum and Optimism L1 gas fee + * allow users to configure upkeeps + * KeeperRegistry 1.2.0: allow funding within performUpkeep + * allow configurable registry maxPerformGas + * add function to let admin change upkeep gas limit + * add minUpkeepSpend requirement + * upgrade to solidity v0.8 + * KeeperRegistry 1.1.0: added flatFeeMicroLink + * KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "AutomationRegistry 2.3.0"; + + /** + * @param logicA the address of the first logic contract + * @dev we cast the contract to logicC in order to call logicC functions (via fallback) + */ + constructor( + AutomationRegistryLogicA2_3 logicA + ) + AutomationRegistryBase2_3( + AutomationRegistryLogicC2_3(address(logicA)).getLinkAddress(), + AutomationRegistryLogicC2_3(address(logicA)).getLinkUSDFeedAddress(), + AutomationRegistryLogicC2_3(address(logicA)).getNativeUSDFeedAddress(), + AutomationRegistryLogicC2_3(address(logicA)).getFastGasFeedAddress(), + AutomationRegistryLogicC2_3(address(logicA)).getAutomationForwarderLogic(), + AutomationRegistryLogicC2_3(address(logicA)).getAllowedReadOnlyAddress(), + AutomationRegistryLogicC2_3(address(logicA)).getPayoutMode(), + AutomationRegistryLogicC2_3(address(logicA)).getWrappedNativeTokenAddress() + ) + Chainable(address(logicA)) + {} + + /** + * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors + */ + struct TransmitVars { + uint16 numUpkeepsPassedChecks; + uint96 totalReimbursement; + uint96 totalPremium; + uint256 totalCalldataWeight; + } + + // ================================================================ + // | HOT PATH ACTIONS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function transmit( + bytes32[3] calldata reportContext, + bytes calldata rawReport, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external override { + uint256 gasOverhead = gasleft(); + // use this msg.data length check to ensure no extra data is included in the call + // 4 is first 4 bytes of the keccak-256 hash of the function signature. ss.length == rs.length so use one of them + // 4 + (32 * 3) + (rawReport.length + 32 + 32) + (32 * rs.length + 32 + 32) + (32 * ss.length + 32 + 32) + 32 + uint256 requiredLength = 324 + rawReport.length + 64 * rs.length; + if (msg.data.length != requiredLength) revert InvalidDataLength(); + HotVars memory hotVars = s_hotVars; + + if (hotVars.paused) revert RegistryPaused(); + if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); + + // Verify signatures + if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); + if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); + _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); + + Report memory report = _decodeReport(rawReport); + + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + + _handleReport(hotVars, report, gasOverhead); + + if (epoch > hotVars.latestEpoch) { + s_hotVars.latestEpoch = epoch; + } + } + + /** + * @notice handles the report by performing the upkeeps and updating the state + * @param hotVars the hot variables of the registry + * @param report the report to be handled (already verified and decoded) + * @param gasOverhead the running tally of gas overhead to be split across the upkeeps + * @dev had to split this function from transmit() to avoid stack too deep errors + * @dev all other internal / private functions are generally defined in the Base contract + * we leave this here because it is essentially a continuation of the transmit() function, + */ + function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private { + UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); + TransmitVars memory transmitVars = TransmitVars({ + numUpkeepsPassedChecks: 0, + totalCalldataWeight: 0, + totalReimbursement: 0, + totalPremium: 0 + }); + + uint256 blocknumber = hotVars.chainModule.blockNumber(); + uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); + + 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( + report.upkeepIds[i], + blocknumber, + report.triggers[i], + upkeepTransmitInfo[i], + hotVars + ); + + if (upkeepTransmitInfo[i].earlyChecksPassed) { + transmitVars.numUpkeepsPassedChecks += 1; + } else { + continue; + } + + // Actually perform the target upkeep + (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( + upkeepTransmitInfo[i].upkeep.forwarder, + report.gasLimits[i], + 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 the gasUsed by upkeep from the overhead tally - upkeeps pay for their own gas individually + 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 (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 + gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD; + gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; + + { + BillingTokenPaymentParams memory billingTokenParams; + uint256 nativeUSD = _getNativeUSD(hotVars); + for (uint256 i = 0; i < report.upkeepIds.length; i++) { + if (upkeepTransmitInfo[i].earlyChecksPassed) { + if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { + billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); + } + PaymentReceipt memory receipt = _handlePayment( + hotVars, + PaymentParams({ + gasLimit: upkeepTransmitInfo[i].gasUsed, + gasOverhead: gasOverhead, + l1CostWei: (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight, + fastGasWei: report.fastGasWei, + linkUSD: report.linkUSD, + nativeUSD: nativeUSD, + billingToken: upkeepTransmitInfo[i].upkeep.billingToken, + billingTokenParams: billingTokenParams, + isTransaction: true + }), + report.upkeepIds[i], + upkeepTransmitInfo[i].upkeep + ); + transmitVars.totalPremium += receipt.premiumInJuels; + transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; + + emit UpkeepPerformed( + report.upkeepIds[i], + upkeepTransmitInfo[i].performSuccess, + receipt.gasChargeInBillingToken + receipt.premiumInBillingToken, + upkeepTransmitInfo[i].gasUsed, + gasOverhead, + report.triggers[i] + ); + } + } + } + // record payments to NOPs, all in LINK + s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; + s_hotVars.totalPremium += transmitVars.totalPremium; + s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium; + } + + // ================================================================ + // | OCR2ABSTRACT | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override { + (OnchainConfig memory config, IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) = abi.decode( + onchainConfigBytes, + (OnchainConfig, IERC20[], BillingConfig[]) + ); + + setConfigTypeSafe( + signers, + transmitters, + f, + config, + offchainConfigVersion, + offchainConfig, + billingTokens, + billingConfigs + ); + } + + /** + * @notice sets the configuration for the registry + * @param signers the list of permitted signers + * @param transmitters the list of permitted transmitters + * @param f the maximum tolerance for faulty nodes + * @param onchainConfig configuration values that are used on-chain + * @param offchainConfigVersion the version of the offchainConfig + * @param offchainConfig configuration values that are used off-chain + * @param billingTokens the list of valid billing tokens + * @param billingConfigs the configurations for each billing token + */ + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + IERC20[] memory billingTokens, + BillingConfig[] memory billingConfigs + ) public onlyOwner { + if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); + if (f == 0) revert IncorrectNumberOfFaultyOracles(); + if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); + if (billingTokens.length != billingConfigs.length) revert ParameterLengthError(); + // set billing config for tokens + _setBillingConfig(billingTokens, billingConfigs); + + _updateTransmitters(signers, transmitters); + + s_hotVars = HotVars({ + f: f, + stalenessSeconds: onchainConfig.stalenessSeconds, + gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, + paused: s_hotVars.paused, + reentrancyGuard: s_hotVars.reentrancyGuard, + totalPremium: s_hotVars.totalPremium, + latestEpoch: 0, // DON restarts epoch + reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, + chainModule: onchainConfig.chainModule + }); + + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); + uint32 newConfigCount = s_storage.configCount + 1; + + s_storage = Storage({ + checkGasLimit: onchainConfig.checkGasLimit, + maxPerformGas: onchainConfig.maxPerformGas, + transcoder: onchainConfig.transcoder, + maxCheckDataSize: onchainConfig.maxCheckDataSize, + maxPerformDataSize: onchainConfig.maxPerformDataSize, + maxRevertDataSize: onchainConfig.maxRevertDataSize, + upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, + financeAdmin: onchainConfig.financeAdmin, + nonce: s_storage.nonce, + configCount: newConfigCount, + latestConfigBlockNumber: newLatestConfigBlockNumber + }); + s_fallbackGasPrice = onchainConfig.fallbackGasPrice; + s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; + s_fallbackNativePrice = onchainConfig.fallbackNativePrice; + + bytes memory onchainConfigBytes = abi.encode(onchainConfig); + + s_latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + + for (uint256 idx = s_registrars.length(); idx > 0; idx--) { + s_registrars.remove(s_registrars.at(idx - 1)); + } + + for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { + s_registrars.add(onchainConfig.registrars[idx]); + } + + emit ConfigSet( + previousConfigBlockNumber, + s_latestConfigDigest, + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + } + + /** + * @inheritdoc OCR2Abstract + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); + } + + /** + * @inheritdoc OCR2Abstract + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function latestConfigDigestAndEpoch() + external + view + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (false, s_latestConfigDigest, s_hotVars.latestEpoch); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol new file mode 100644 index 0000000..354a6a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol @@ -0,0 +1,1216 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * AutomationRegistry and AutomationRegistryLogic + * @dev all errors, events, and internal functions should live here + */ +// solhint-disable-next-line max-states-count +abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; + bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint256 internal constant PERFORM_GAS_CUSHION = 5_000; + uint256 internal constant PPB_BASE = 1_000_000_000; + uint32 internal constant UINT32_MAX = type(uint32).max; + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + uint8 internal constant UPKEEP_VERSION_BASE = 4; + + // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation + // These values are calibrated using hardhat tests which simulate various cases and verify that + // the variables result in accurate estimation + uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps + uint256 internal constant REGISTRY_LOG_OVERHEAD = 123_500; // Fixed gas overhead for log upkeeps + uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f + uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead + + // The overhead (in bytes) in addition to perform data for upkeep sent in calldata + // This includes overhead for all struct encoding as well as report signatures + // There is a fixed component and a per signer component. This is calculated exactly by doing abi encoding + uint256 internal constant TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD = 932; + uint256 internal constant TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD = 64; + + // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the + // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants + // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that + // the variables result in accurate estimation + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_200; // Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 14_200; // Overhead per upkeep performed in batch + + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_linkUSDFeed; + AggregatorV3Interface internal immutable i_nativeUSDFeed; + AggregatorV3Interface internal immutable i_fastGasFeed; + address internal immutable i_automationForwarderLogic; + address internal immutable i_allowedReadOnlyAddress; + IWrappedNative internal immutable i_wrappedNativeToken; + + /** + * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit + * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path + */ + + // Upkeep storage + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit + mapping(uint256 => address) internal s_upkeepAdmin; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + mapping(bytes32 => bool) internal s_dedupKeys; + // Registry config and state + EnumerableSet.AddressSet internal s_registrars; + mapping(address => Transmitter) internal s_transmitters; + mapping(address => Signer) internal s_signers; + address[] internal s_signersList; // s_signersList contains the signing address of each oracle + address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle + EnumerableSet.AddressSet internal s_deactivatedTransmitters; + mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. + mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter + bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification + HotVars internal s_hotVars; // Mixture of config and state, used in transmit + Storage internal s_storage; // Mixture of config and state, not used in transmit + uint256 internal s_fallbackGasPrice; + uint256 internal s_fallbackLinkPrice; + uint256 internal s_fallbackNativePrice; + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro + mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers + mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep + mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep + mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin + // billing + mapping(IERC20 billingToken => uint256 reserveAmount) internal s_reserveAmounts; // unspent user deposits + unwithdrawn NOP payments + mapping(IERC20 billingToken => BillingConfig billingConfig) internal s_billingConfigs; // billing configurations for different tokens + mapping(uint256 upkeepID => BillingOverrides billingOverrides) internal s_billingOverrides; // billing overrides for specific upkeeps + IERC20[] internal s_billingTokens; // list of billing tokens + PayoutMode internal s_payoutMode; + + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientBalance(uint256 available, uint256 requested); + error InsufficientLinkLiquidity(); + error InvalidDataLength(); + error InvalidFeed(); + error InvalidTrigger(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidToken(); + error InvalidTransmitter(); + error InvalidTriggerType(); + error MigrationNotPermitted(); + error MustSettleOffchain(); + error MustSettleOnchain(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyFinanceAdmin(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error TransferFailed(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ZeroAddressNotAllowed(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum Trigger { + CONDITION, + LOG + } + + enum UpkeepFailureReason { + NONE, + UPKEEP_CANCELLED, + UPKEEP_PAUSED, + TARGET_CHECK_REVERTED, + UPKEEP_NOT_NEEDED, + PERFORM_DATA_EXCEEDS_LIMIT, + INSUFFICIENT_BALANCE, + CALLBACK_REVERTED, + REVERT_DATA_EXCEEDS_LIMIT, + REGISTRY_PAUSED + } + + enum PayoutMode { + ON_CHAIN, + OFF_CHAIN + } + + /** + * @notice OnchainConfig of the registry + * @dev used only in setConfig() + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member maxPerformGas max performGas allowed for an upkeep on this registry + * @member maxCheckDataSize max length of checkData bytes + * @member maxPerformDataSize max length of performData bytes + * @member maxRevertDataSize max length of revertData bytes + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrars addresses of the registrar contracts + * @member upkeepPrivilegeManager address which can set privilege for upkeeps + * @member reorgProtectionEnabled if this registry enables re-org protection checks + * @member chainModule the chain specific module + */ + struct OnchainConfig { + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + address transcoder; + // 1 word full + bool reorgProtectionEnabled; + uint24 stalenessSeconds; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + address upkeepPrivilegeManager; + // 2 words full + uint16 gasCeilingMultiplier; + address financeAdmin; + // 3 words + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + uint256 fallbackNativePrice; + address[] registrars; + IChainModule chainModule; + } + + /** + * @notice relevant state of an upkeep which is used in transmit function + * @member paused if this upkeep has been paused + * @member overridesEnabled if this upkeep has overrides enabled + * @member performGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member forwarder the forwarder contract to use for this upkeep + * @member amountSpent the amount this upkeep has spent, in the upkeep's billing token + * @member balance the balance of this upkeep + * @member lastPerformedBlockNumber the last block number when this upkeep was performed + */ + struct Upkeep { + bool paused; + bool overridesEnabled; + uint32 performGas; + uint32 maxValidBlocknumber; + IAutomationForwarder forwarder; + // 2 bytes left in 1st EVM word - read in transmit path + uint128 amountSpent; + uint96 balance; + uint32 lastPerformedBlockNumber; + // 0 bytes left in 2nd EVM word - written in transmit path + IERC20 billingToken; + // 12 bytes left in 3rd EVM word - read in transmit path + } + + /// @dev Config + State storage struct which is on hot transmit path + struct HotVars { + uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium + uint32 latestEpoch; // │ latest epoch for which a report was transmitted + uint24 stalenessSeconds; // │ Staleness tolerance for feeds + uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound + uint8 f; // │ maximum number of faulty oracles + bool paused; // │ pause switch for all upkeeps in the registry + bool reentrancyGuard; // | guard against reentrancy + bool reorgProtectionEnabled; // ─╯ if this registry should enable the re-org protection mechanism + IChainModule chainModule; // the interface of chain specific module + } + + /// @dev Config + State storage struct which is not on hot transmit path + struct Storage { + address transcoder; // Address of transcoder contract used in migrations + uint32 checkGasLimit; // Gas limit allowed in checkUpkeep + uint32 maxPerformGas; // Max gas an upkeep can use on this registry + uint32 nonce; // Nonce for each upkeep created + // 1 EVM word full + address upkeepPrivilegeManager; // address which can set privilege for upkeeps + uint32 configCount; // incremented each time a new config is posted, The count is incorporated into the config digest to prevent replay attacks. + uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs + uint32 maxCheckDataSize; // max length of checkData bytes + // 2 EVM word full + address financeAdmin; // address which can withdraw funds from the contract + uint32 maxPerformDataSize; // max length of performData bytes + uint32 maxRevertDataSize; // max length of revertData bytes + // 4 bytes left in 3rd EVM word + } + + /// @dev Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkUSD; + uint256[] upkeepIds; + uint256[] gasLimits; + bytes[] triggers; + bytes[] performDatas; + } + + /** + * @dev This struct is used to maintain run time information about an upkeep in transmit function + * @member upkeep the upkeep struct + * @member earlyChecksPassed whether the upkeep passed early checks before perform + * @member performSuccess whether the perform was successful + * @member triggerType the type of trigger + * @member gasUsed gasUsed by this upkeep in perform + * @member calldataWeight weight assigned to this upkeep for its contribution to calldata. It is used to split L1 fee + * @member dedupID unique ID used to dedup an upkeep/trigger combo + */ + struct UpkeepTransmitInfo { + Upkeep upkeep; + bool earlyChecksPassed; + bool performSuccess; + Trigger triggerType; + uint256 gasUsed; + uint256 calldataWeight; + bytes32 dedupID; + } + + /** + * @notice holds information about a transmiter / node in the DON + * @member active can this transmitter submit reports + * @member index of oracle in s_signersList/s_transmittersList + * @member balance a node's balance in LINK + * @member lastCollected the total balance at which the node last withdrew + * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK + */ + struct Transmitter { + bool active; + uint8 index; + uint96 balance; + uint96 lastCollected; + } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } + + struct Signer { + bool active; + // Index of oracle in s_signersList/s_transmittersList + uint8 index; + } + + /** + * @notice the trigger structure conditional trigger type + */ + struct ConditionalTrigger { + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the trigger structure of log upkeeps + * @dev NOTE that blockNum / blockHash describe the block used for the callback, + * not necessarily the block number that the log was emitted in!!!! + */ + struct LogTrigger { + bytes32 logBlockHash; + bytes32 txHash; + uint32 logIndex; + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the billing config of a token + * @dev this is a storage struct + */ + // solhint-disable-next-line gas-struct-packing + struct BillingConfig { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; // min fee is $0.00001, max fee is $167 + AggregatorV3Interface priceFeed; + uint8 decimals; + // 1st word, read in calculating BillingTokenPaymentParams + uint256 fallbackPrice; + // 2nd word only read if stale + uint96 minSpend; + // 3rd word only read during cancellation + } + + /** + * @notice override-able billing params of a billing token + */ + struct BillingOverrides { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + } + + /** + * @notice pricing params for a billing token + * @dev this is a memory-only struct, so struct packing is less important + */ + struct BillingTokenPaymentParams { + uint8 decimals; + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + uint256 priceUSD; + } + + /** + * @notice struct containing price & payment information used in calculating payment amount + * @member gasLimit the amount of gas used + * @member gasOverhead the amount of gas overhead + * @member l1CostWei the amount to be charged for L1 fee in wei + * @member fastGasWei the fast gas price + * @member linkUSD the exchange ratio between LINK and USD + * @member nativeUSD the exchange ratio between the chain's native token and USD + * @member billingToken the billing token + * @member billingTokenParams the payment params specific to a particular payment token + * @member isTransaction is this an eth_call or a transaction + */ + struct PaymentParams { + uint256 gasLimit; + uint256 gasOverhead; + uint256 l1CostWei; + uint256 fastGasWei; + uint256 linkUSD; + uint256 nativeUSD; + IERC20 billingToken; + BillingTokenPaymentParams billingTokenParams; + bool isTransaction; + } + + /** + * @notice struct containing receipt information about a payment or cost estimation + * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals + * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals + * @member gasReimbursementInJuels the amount to reimburse a node for gas spent + * @member premiumInJuels the premium paid to NOPs, shared between all nodes + */ + // solhint-disable-next-line gas-struct-packing + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + // one word ends + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + // second word ends + IERC20 billingToken; + uint96 linkUSD; + // third word ends + uint96 nativeUSD; + uint96 billingUSD; + // fourth word ends + } + + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event BillingConfigOverridden(uint256 indexed id, BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + event BillingConfigSet(IERC20 indexed token, BillingConfig config); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + event Unpaused(address account); + + /** + * @param link address of the LINK Token + * @param linkUSDFeed address of the LINK/USD price feed + * @param nativeUSDFeed address of the Native/USD price feed + * @param fastGasFeed address of the Fast Gas price feed + * @param automationForwarderLogic the address of automation forwarder logic + * @param allowedReadOnlyAddress the address of the allowed read only address + * @param payoutMode the payout mode + */ + constructor( + address link, + address linkUSDFeed, + address nativeUSDFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress, + PayoutMode payoutMode, + address wrappedNativeTokenAddress + ) ConfirmedOwner(msg.sender) { + i_link = LinkTokenInterface(link); + i_linkUSDFeed = AggregatorV3Interface(linkUSDFeed); + i_nativeUSDFeed = AggregatorV3Interface(nativeUSDFeed); + i_fastGasFeed = AggregatorV3Interface(fastGasFeed); + i_automationForwarderLogic = automationForwarderLogic; + i_allowedReadOnlyAddress = allowedReadOnlyAddress; + s_payoutMode = payoutMode; + i_wrappedNativeToken = IWrappedNative(wrappedNativeTokenAddress); + if (i_linkUSDFeed.decimals() != i_nativeUSDFeed.decimals()) { + revert InvalidFeed(); + } + } + + // ================================================================ + // | INTERNAL FUNCTIONS ONLY | + // ================================================================ + + /** + * @dev creates a new upkeep with the given fields + * @param id the id of the upkeep + * @param upkeep the upkeep to create + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data which is passed to user's checkUpkeep + * @param triggerConfig the trigger config for this upkeep + * @param offchainConfig the off-chain config of this upkeep + */ + function _createUpkeep( + uint256 id, + Upkeep memory upkeep, + address admin, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) internal { + if (s_hotVars.paused) revert RegistryPaused(); + if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) + revert GasLimitOutsideRange(); + if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); + if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidToken(); + s_upkeep[id] = upkeep; + s_upkeepAdmin[id] = admin; + s_checkData[id] = checkData; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + upkeep.balance; + s_upkeepTriggerConfig[id] = triggerConfig; + s_upkeepOffchainConfig[id] = offchainConfig; + s_upkeepIDs.add(id); + } + + /** + * @dev creates an ID for the upkeep based on the upkeep's type + * @dev the format of the ID looks like this: + * ****00000000000X**************** + * 4 bytes of entropy + * 11 bytes of zeros + * 1 identifying byte for the trigger type + * 16 bytes of entropy + * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique + * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only + * see the first 4 and last 4 hex values ex 0x1234...ABCD + */ + function _createID(Trigger triggerType) internal view returns (uint256) { + bytes1 empty; + IChainModule chainModule = s_hotVars.chainModule; + bytes memory idBytes = abi.encodePacked( + keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) + ); + for (uint256 idx = 4; idx < 15; idx++) { + idBytes[idx] = empty; + } + idBytes[15] = bytes1(uint8(triggerType)); + return uint256(bytes32(idBytes)); + } + + /** + * @dev retrieves feed data for fast gas/native and link/native prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData( + HotVars memory hotVars + ) internal view returns (uint256 gasWei, uint256 linkUSD, uint256 nativeUSD) { + uint32 stalenessSeconds = hotVars.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = i_linkUSDFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + linkUSD = s_fallbackLinkPrice; + } else { + linkUSD = uint256(feedValue); + } + return (gasWei, linkUSD, _getNativeUSD(hotVars)); + } + + /** + * @dev this price has it's own getter for use in the transmit() hot path + * in the future, all price data should be included in the report instead of + * getting read during execution + */ + function _getNativeUSD(HotVars memory hotVars) internal view returns (uint256) { + (, int256 feedValue, , uint256 timestamp, ) = i_nativeUSDFeed.latestRoundData(); + if ( + feedValue <= 0 || + block.timestamp < timestamp || + (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) + ) { + return s_fallbackNativePrice; + } else { + return uint256(feedValue); + } + } + + /** + * @dev gets the price and billing params for a specific billing token + */ + function _getBillingTokenPaymentParams( + HotVars memory hotVars, + IERC20 billingToken + ) internal view returns (BillingTokenPaymentParams memory paymentParams) { + BillingConfig storage config = s_billingConfigs[billingToken]; + paymentParams.flatFeeMilliCents = config.flatFeeMilliCents; + paymentParams.gasFeePPB = config.gasFeePPB; + paymentParams.decimals = config.decimals; + (, int256 feedValue, , uint256 timestamp, ) = config.priceFeed.latestRoundData(); + if ( + feedValue <= 0 || + block.timestamp < timestamp || + (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) + ) { + paymentParams.priceUSD = config.fallbackPrice; + } else { + paymentParams.priceUSD = uint256(feedValue); + } + return paymentParams; + } + + /** + * @param hotVars the hot path variables + * @param paymentParams the pricing data and gas usage data + * @return receipt the receipt of payment with pricing breakdown + * @dev use of PaymentParams struct is necessary to avoid stack too deep errors + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @dev 1 USD = 1e18 attoUSD + * @dev 1 USD = 1e26 hexaicosaUSD (had to borrow this prefix from geometry because there is no metric prefix for 1e-26) + * @dev 1 millicent = 1e-5 USD = 1e13 attoUSD + */ + function _calculatePaymentAmount( + HotVars memory hotVars, + PaymentParams memory paymentParams + ) internal view returns (PaymentReceipt memory receipt) { + uint256 decimals = paymentParams.billingTokenParams.decimals; + uint256 gasWei = paymentParams.fastGasWei * hotVars.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (paymentParams.isTransaction && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + + // scaling factor is based on decimals of billing token, and applies to premium and gasCharge + uint256 numeratorScalingFactor = decimals > 18 ? 10 ** (decimals - 18) : 1; + uint256 denominatorScalingFactor = decimals < 18 ? 10 ** (18 - decimals) : 1; + + // gas calculation + uint256 gasPaymentHexaicosaUSD = (gasWei * + (paymentParams.gasLimit + paymentParams.gasOverhead) + + paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed + // gasChargeInBillingToken is scaled by the billing token's decimals. Round up to ensure a minimum billing token is charged for gas + receipt.gasChargeInBillingToken = SafeCast.toUint96( + ((gasPaymentHexaicosaUSD * numeratorScalingFactor) + + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); + // 18 decimals: 26 decimals / 8 decimals + receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); + + // premium calculation + uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD + uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) * + paymentParams.billingTokenParams.gasFeePPB * + paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; + // premium is scaled by the billing token's decimals. Round up to ensure at least minimum charge + receipt.premiumInBillingToken = SafeCast.toUint96( + ((premiumHexaicosaUSD * numeratorScalingFactor) + + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); + receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); + + receipt.billingToken = paymentParams.billingToken; + receipt.linkUSD = SafeCast.toUint96(paymentParams.linkUSD); + receipt.nativeUSD = SafeCast.toUint96(paymentParams.nativeUSD); + receipt.billingUSD = SafeCast.toUint96(paymentParams.billingTokenParams.priceUSD); + + return receipt; + } + + /** + * @dev calculates the max payment for an upkeep. Called during checkUpkeep simulation and assumes + * maximum gas overhead, L1 fee + */ + function _getMaxPayment( + uint256 upkeepId, + HotVars memory hotVars, + Trigger triggerType, + uint32 performGas, + uint256 fastGasWei, + uint256 linkUSD, + uint256 nativeUSD, + IERC20 billingToken + ) internal view returns (uint96) { + uint256 maxL1Fee; + uint256 maxGasOverhead; + + { + if (triggerType == Trigger.CONDITION) { + maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; + } else if (triggerType == Trigger.LOG) { + maxGasOverhead = REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } + uint256 maxCalldataSize = s_storage.maxPerformDataSize + + TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + + (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); + (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) = s_hotVars.chainModule.getGasOverhead(); + maxGasOverhead += + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + + ((REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD + chainModulePerByteOverhead) * maxCalldataSize) + + chainModuleFixedOverhead; + maxL1Fee = hotVars.gasCeilingMultiplier * hotVars.chainModule.getMaxL1Fee(maxCalldataSize); + } + + BillingTokenPaymentParams memory paymentParams = _getBillingTokenPaymentParams(hotVars, billingToken); + if (s_upkeep[upkeepId].overridesEnabled) { + BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; + // use the overridden configs + paymentParams.gasFeePPB = billingOverrides.gasFeePPB; + paymentParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; + } + + PaymentReceipt memory receipt = _calculatePaymentAmount( + hotVars, + PaymentParams({ + gasLimit: performGas, + gasOverhead: maxGasOverhead, + l1CostWei: maxL1Fee, + fastGasWei: fastGasWei, + linkUSD: linkUSD, + nativeUSD: nativeUSD, + billingToken: billingToken, + billingTokenParams: paymentParams, + isTransaction: false + }) + ); + + return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; + } + + /** + * @dev move a transmitter's balance from total pool to withdrawable balance + */ + function _updateTransmitterBalanceFromPool( + address transmitterAddress, + uint96 totalPremium, + uint96 payeeCount + ) internal returns (uint96) { + Transmitter memory transmitter = s_transmitters[transmitterAddress]; + + if (transmitter.active) { + uint96 uncollected = totalPremium - transmitter.lastCollected; + uint96 due = uncollected / payeeCount; + transmitter.balance += due; + transmitter.lastCollected += due * payeeCount; + s_transmitters[transmitterAddress] = transmitter; + } + + return transmitter.balance; + } + + /** + * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) + */ + function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { + bytes32 rawID = bytes32(upkeepId); + bytes1 empty = bytes1(0); + for (uint256 idx = 4; idx < 15; idx++) { + if (rawID[idx] != empty) { + // old IDs that were created before this standard and migrated to this registry + return Trigger.CONDITION; + } + } + return Trigger(uint8(rawID[15])); + } + + function _checkPayload( + uint256 upkeepId, + Trigger triggerType, + bytes memory triggerData + ) internal view returns (bytes memory) { + if (triggerType == Trigger.CONDITION) { + return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); + } else if (triggerType == Trigger.LOG) { + Log memory log = abi.decode(triggerData, (Log)); + return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); + } + revert InvalidTriggerType(); + } + + /** + * @dev _decodeReport decodes a serialized report into a Report struct + */ + function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { + Report memory report = abi.decode(rawReport, (Report)); + uint256 expectedLength = report.upkeepIds.length; + if ( + report.gasLimits.length != expectedLength || + report.triggers.length != expectedLength || + report.performDatas.length != expectedLength + ) { + revert InvalidReport(); + } + return report; + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + * @return bool whether the upkeep should be performed + * @return bytes32 dedupID for preventing duplicate performances of this trigger + */ + function _prePerformChecks( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + bytes32 dedupID; + if (transmitInfo.triggerType == Trigger.CONDITION) { + if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) + return (false, dedupID); + } else if (transmitInfo.triggerType == Trigger.LOG) { + bool valid; + (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); + if (!valid) return (false, dedupID); + } else { + revert InvalidTriggerType(); + } + if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { + // Can happen when an upkeep got cancelled after report was generated. + // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice + emit CancelledUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + */ + function _validateConditionalTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool) { + ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); + if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { + // Can happen when another report performed this upkeep after this report was generated + emit StaleUpkeepReport(upkeepId, rawTrigger); + return false; + } + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // There are two cases of reorged report + // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain + // which is always protected against + // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is + // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain + // when it is sent + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return false; + } + return true; + } + + function _validateLogTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); + bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // Reorg protection is same as conditional trigger upkeeps + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + if (s_dedupKeys[dedupID]) { + emit StaleUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Verify signatures attached to report + */ + function _verifyReportSignature( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) internal view { + bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount = 0; + + Signer memory signer; + address signerAddress; + for (uint256 i = 0; i < rs.length; i++) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + signer = s_signers[signerAddress]; + if (!signer.active) revert OnlyActiveSigners(); + unchecked { + signedCount += 1 << (8 * signer.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); + } + + /** + * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances + * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID + */ + function _updateTriggerMarker( + uint256 upkeepID, + uint256 blocknumber, + UpkeepTransmitInfo memory upkeepTransmitInfo + ) internal { + if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { + s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); + } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { + s_dedupKeys[upkeepTransmitInfo.dedupID] = true; + emit DedupKeyAdded(upkeepTransmitInfo.dedupID); + } + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * transmitter and the exact gas required by the Upkeep + */ + function _performUpkeep( + IAutomationForwarder forwarder, + uint256 performGas, + bytes memory performData + ) internal nonReentrant returns (bool success, uint256 gasUsed) { + performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); + return forwarder.forward(performGas, performData); + } + + /** + * @dev handles the payment processing after an upkeep has been performed. + * Deducts an upkeep's balance and increases the amount spent. + */ + function _handlePayment( + HotVars memory hotVars, + PaymentParams memory paymentParams, + uint256 upkeepId, + Upkeep memory upkeep + ) internal returns (PaymentReceipt memory) { + if (upkeep.overridesEnabled) { + BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; + // use the overridden configs + paymentParams.billingTokenParams.gasFeePPB = billingOverrides.gasFeePPB; + paymentParams.billingTokenParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; + } + + PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); + + // balance is in the token's native decimals + uint96 balance = upkeep.balance; + // payment is in the token's native decimals + uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; + + // scaling factors to adjust decimals between billing token and LINK + uint256 decimals = paymentParams.billingTokenParams.decimals; + uint256 scalingFactor1 = decimals < 18 ? 10 ** (18 - decimals) : 1; + uint256 scalingFactor2 = decimals > 18 ? 10 ** (decimals - 18) : 1; + + // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user + // can't cover the amount owed + if (balance < receipt.gasChargeInBillingToken) { + // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON + payment = balance; + receipt.gasReimbursementInJuels = SafeCast.toUint96( + (balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / + (paymentParams.linkUSD * scalingFactor2) + ); + receipt.premiumInJuels = 0; + receipt.premiumInBillingToken = 0; + receipt.gasChargeInBillingToken = balance; + } else if (balance < payment) { + // if the user can cover the gas fee, but not the premium, then reduce the premium + payment = balance; + receipt.premiumInJuels = SafeCast.toUint96( + ((balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / + (paymentParams.linkUSD * scalingFactor2)) - receipt.gasReimbursementInJuels + ); + // round up + receipt.premiumInBillingToken = SafeCast.toUint96( + ((receipt.premiumInJuels * paymentParams.linkUSD * scalingFactor2) + + (paymentParams.billingTokenParams.priceUSD * scalingFactor1 - 1)) / + (paymentParams.billingTokenParams.priceUSD * scalingFactor1) + ); + } + + s_upkeep[upkeepId].balance -= payment; + s_upkeep[upkeepId].amountSpent += payment; + s_reserveAmounts[paymentParams.billingToken] -= payment; + + emit UpkeepCharged(upkeepId, receipt); + return receipt; + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { + if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); + if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } + + /** + * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage + */ + modifier nonReentrant() { + if (s_hotVars.reentrancyGuard) revert ReentrantCall(); + s_hotVars.reentrancyGuard = true; + _; + s_hotVars.reentrancyGuard = false; + } + + /** + * @notice only allows a pre-configured address to initiate offchain read + */ + function _preventExecution() internal view { + // solhint-disable-next-line avoid-tx-origin + if (tx.origin != i_allowedReadOnlyAddress) { + revert OnlySimulatedBackend(); + } + } + + /** + * @notice only allows finance admin to call the function + */ + function _onlyFinanceAdminAllowed() internal view { + if (msg.sender != s_storage.financeAdmin) { + revert OnlyFinanceAdmin(); + } + } + + /** + * @notice only allows privilege manager to call the function + */ + function _onlyPrivilegeManagerAllowed() internal view { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + } + + /** + * @notice sets billing configuration for a token + * @param billingTokens the addresses of tokens + * @param billingConfigs the configs for tokens + */ + function _setBillingConfig(IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) internal { + // Clear existing data + for (uint256 i = 0; i < s_billingTokens.length; i++) { + delete s_billingConfigs[s_billingTokens[i]]; + } + delete s_billingTokens; + + PayoutMode mode = s_payoutMode; + for (uint256 i = 0; i < billingTokens.length; i++) { + IERC20 token = billingTokens[i]; + BillingConfig memory config = billingConfigs[i]; + + // most ERC20 tokens are 18 decimals, priceFeed must be 8 decimals + if (config.decimals != token.decimals() || config.priceFeed.decimals() != 8) { + revert InvalidToken(); + } + + // if LINK is a billing option, payout mode must be ON_CHAIN + if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { + revert InvalidToken(); + } + if (address(token) == ZERO_ADDRESS || address(config.priceFeed) == ZERO_ADDRESS) { + revert ZeroAddressNotAllowed(); + } + + // if this is a new token, add it to tokens list. Otherwise revert + if (address(s_billingConfigs[token].priceFeed) != ZERO_ADDRESS) { + revert DuplicateEntry(); + } + s_billingTokens.push(token); + + // update the billing config for an existing token or add a new one + s_billingConfigs[token] = config; + + emit BillingConfigSet(token, config); + } + } + + /** + * @notice updates the signers and transmitters lists + */ + function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { + uint96 transmittersListLength = uint96(s_transmittersList.length); + uint96 totalPremium = s_hotVars.totalPremium; + + // move all pooled payments out of the pool to each transmitter's balance + for (uint256 i = 0; i < s_transmittersList.length; i++) { + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); + } + + // remove any old signer/transmitter addresses + address transmitterAddress; + PayoutMode mode = s_payoutMode; + for (uint256 i = 0; i < s_transmittersList.length; i++) { + transmitterAddress = s_transmittersList[i]; + delete s_signers[s_signersList[i]]; + // Do not delete the whole transmitter struct as it has balance information stored + s_transmitters[transmitterAddress].active = false; + if (mode == PayoutMode.OFF_CHAIN && s_transmitters[transmitterAddress].balance > 0) { + s_deactivatedTransmitters.add(transmitterAddress); + } + } + delete s_signersList; + delete s_transmittersList; + + // add new signer/transmitter addresses + Transmitter memory transmitter; + for (uint256 i = 0; i < signers.length; i++) { + if (s_signers[signers[i]].active) revert RepeatedSigner(); + if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); + s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); + + transmitterAddress = transmitters[i]; + if (transmitterAddress == ZERO_ADDRESS) revert InvalidTransmitter(); + transmitter = s_transmitters[transmitterAddress]; + if (transmitter.active) revert RepeatedTransmitter(); + transmitter.active = true; + transmitter.index = uint8(i); + // new transmitters start afresh from current totalPremium + // some spare change of premium from previous pool will be forfeited + transmitter.lastCollected = s_hotVars.totalPremium; + s_transmitters[transmitterAddress] = transmitter; + if (mode == PayoutMode.OFF_CHAIN) { + s_deactivatedTransmitters.remove(transmitterAddress); + } + } + + s_signersList = signers; + s_transmittersList = transmitters; + } + + /** + * @notice returns the size of the LINK liquidity pool + # @dev LINK max supply < 2^96, so casting to int256 is safe + */ + function _linkAvailableForPayment() internal view returns (int256) { + return int256(i_link.balanceOf(address(this))) - int256(s_reserveAmounts[IERC20(address(i_link))]); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol new file mode 100644 index 0000000..1ef3991 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; +import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; +import {AutomationRegistryLogicB2_3} from "./AutomationRegistryLogicB2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {AutomationForwarder} from "../AutomationForwarder.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Logic contract, works in tandem with AutomationRegistry as a proxy + */ +contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable, IERC677Receiver { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + using SafeERC20 for IERC20; + + /** + * @param logicB the address of the second logic contract + * @dev we cast the contract to logicC in order to call logicC functions (via fallback) + */ + constructor( + AutomationRegistryLogicB2_3 logicB + ) + AutomationRegistryBase2_3( + AutomationRegistryLogicC2_3(address(logicB)).getLinkAddress(), + AutomationRegistryLogicC2_3(address(logicB)).getLinkUSDFeedAddress(), + AutomationRegistryLogicC2_3(address(logicB)).getNativeUSDFeedAddress(), + AutomationRegistryLogicC2_3(address(logicB)).getFastGasFeedAddress(), + AutomationRegistryLogicC2_3(address(logicB)).getAutomationForwarderLogic(), + AutomationRegistryLogicC2_3(address(logicB)).getAllowedReadOnlyAddress(), + AutomationRegistryLogicC2_3(address(logicB)).getPayoutMode(), + AutomationRegistryLogicC2_3(address(logicB)).getWrappedNativeTokenAddress() + ) + Chainable(address(logicB)) + {} + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken(); + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount; + emit FundsAdded(id, sender, uint96(amount)); + } + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param triggerType the trigger for the upkeep + * @param billingToken the billing token for the upkeep + * @param checkData data passed to the contract when checking for upkeep + * @param triggerConfig the config for the trigger + * @param offchainConfig arbitrary offchain config for the upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + Trigger triggerType, + IERC20 billingToken, + bytes calldata checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) public returns (uint256 id) { + if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); + if (!target.isContract()) revert NotAContract(); + id = _createID(triggerType); + IAutomationForwarder forwarder = IAutomationForwarder( + address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) + ); + _createUpkeep( + id, + Upkeep({ + overridesEnabled: false, + performGas: gasLimit, + balance: 0, + maxValidBlocknumber: UINT32_MAX, + lastPerformedBlockNumber: 0, + amountSpent: 0, + paused: false, + forwarder: forwarder, + billingToken: billingToken + }), + admin, + checkData, + triggerConfig, + offchainConfig + ); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + emit UpkeepCheckDataSet(id, checkData); + emit UpkeepTriggerConfigSet(id, triggerConfig); + emit UpkeepOffchainConfigSet(id, offchainConfig); + return (id); + } + + /** + * @notice cancels an upkeep + * @param id the upkeepID to cancel + * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to + * allow any pending performUpkeep txs time to get confirmed + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool isOwner = msg.sender == owner(); + uint96 minSpend = s_billingConfigs[upkeep.billingToken].minSpend; + + uint256 height = s_hotVars.chainModule.blockNumber(); + if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); + + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minSpend is not met + uint96 cancellationFee = 0; + // cancellationFee is min(max(minSpend - amountSpent, 0), amountLeft) + if (upkeep.amountSpent < minSpend) { + cancellationFee = minSpend - uint96(upkeep.amountSpent); + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @notice migrates upkeeps from one registry to another. + * @param ids the upkeepIDs to migrate + * @param destination the destination registry address + * @dev a transcoder must be set in order to enable migration + * @dev migration permissions must be set on *both* sending and receiving registries + * @dev only an upkeep admin can migrate their upkeeps + * @dev this function is most gas-efficient if upkeepIDs are sorted by billing token + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not migrated in this function + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + + IERC20 billingToken; + uint256 balanceToTransfer; + uint256 id; + Upkeep memory upkeep; + address[] memory admins = new address[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + bytes[] memory checkDatas = new bytes[](ids.length); + bytes[] memory triggerConfigs = new bytes[](ids.length); + bytes[] memory offchainConfigs = new bytes[](ids.length); + + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + + if (idx == 0) { + billingToken = upkeep.billingToken; + balanceToTransfer = upkeep.balance; + } + + // if we encounter a new billing token, send the sum from the last billing token to the destination registry + if (upkeep.billingToken != billingToken) { + s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; + billingToken.safeTransfer(destination, balanceToTransfer); + billingToken = upkeep.billingToken; + balanceToTransfer = upkeep.balance; + } else if (idx != 0) { + balanceToTransfer += upkeep.balance; + } + + _requireAdminAndNotCancelled(id); + upkeep.forwarder.updateRegistry(destination); + + upkeeps[idx] = upkeep; + admins[idx] = s_upkeepAdmin[id]; + checkDatas[idx] = s_checkData[id]; + triggerConfigs[idx] = s_upkeepTriggerConfig[id]; + offchainConfigs[idx] = s_upkeepOffchainConfig[id]; + delete s_upkeep[id]; + delete s_checkData[id]; + delete s_upkeepTriggerConfig[id]; + delete s_upkeepOffchainConfig[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + delete s_upkeepAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + // always transfer the rolling sum in the end + s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; + billingToken.safeTransfer(destination, balanceToTransfer); + + bytes memory encodedUpkeeps = abi.encode( + ids, + upkeeps, + new address[](ids.length), + admins, + checkDatas, + triggerConfigs, + offchainConfigs + ); + MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( + UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( + UPKEEP_VERSION_BASE, + MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), + encodedUpkeeps + ) + ); + } + + /** + * @notice received upkeeps migrated from another registry + * @param encodedUpkeeps the raw upkeep data to import + * @dev this function is never called directly, it is only called by another registry's migrate function + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not handled in this function + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + ( + uint256[] memory ids, + Upkeep[] memory upkeeps, + address[] memory targets, + address[] memory upkeepAdmins, + bytes[] memory checkDatas, + bytes[] memory triggerConfigs, + bytes[] memory offchainConfigs + ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); + for (uint256 idx = 0; idx < ids.length; idx++) { + if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { + upkeeps[idx].forwarder = IAutomationForwarder( + address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) + ); + } + _createUpkeep( + ids[idx], + upkeeps[idx], + upkeepAdmins[idx], + checkDatas[idx], + triggerConfigs[idx], + offchainConfigs[idx] + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol new file mode 100644 index 0000000..d854848 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + using SafeERC20 for IERC20; + + /** + * @param logicC the address of the third logic contract + */ + constructor( + AutomationRegistryLogicC2_3 logicC + ) + AutomationRegistryBase2_3( + logicC.getLinkAddress(), + logicC.getLinkUSDFeedAddress(), + logicC.getNativeUSDFeedAddress(), + logicC.getFastGasFeedAddress(), + logicC.getAutomationForwarderLogic(), + logicC.getAllowedReadOnlyAddress(), + logicC.getPayoutMode(), + logicC.getWrappedNativeTokenAddress() + ) + Chainable(address(logicC)) + {} + + // ================================================================ + // | PIPELINE FUNCTIONS | + // ================================================================ + + /** + * @notice called by the automation DON to check if work is needed + * @param id the upkeep ID to check for work needed + * @param triggerData extra contextual data about the trigger (not used in all code paths) + * @dev this one of the core functions called in the hot path + * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility + * @dev there is an incongruency on what gets returned during failure modes + * ex sometimes we include price data, sometimes we omit it depending on the failure + */ + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + public + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ) + { + _preventExecution(); + + Trigger triggerType = _getTriggerType(id); + HotVars memory hotVars = s_hotVars; + Upkeep memory upkeep = s_upkeep[id]; + + { + uint256 nativeUSD; + uint96 maxPayment; + if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); + if (upkeep.maxValidBlocknumber != UINT32_MAX) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); + if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); + (fastGasWei, linkUSD, nativeUSD) = _getFeedData(hotVars); + maxPayment = _getMaxPayment( + id, + hotVars, + triggerType, + upkeep.performGas, + fastGasWei, + linkUSD, + nativeUSD, + upkeep.billingToken + ); + if (upkeep.balance < maxPayment) { + return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); + } + } + + bytes memory callData = _checkPayload(id, triggerType, triggerData); + + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); + gasUsed = gasUsed - gasleft(); + + if (!success) { + // User's target check reverted. We capture the revert data here and pass it within performData + if (result.length > s_storage.maxRevertDataSize) { + return ( + false, + bytes(""), + UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + } + return ( + upkeepNeeded, + result, + UpkeepFailureReason.TARGET_CHECK_REVERTED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + } + + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, upkeep.performGas, fastGasWei, linkUSD); + + if (performData.length > s_storage.maxPerformDataSize) + return ( + false, + bytes(""), + UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkUSD); + } + + /** + * @notice see other checkUpkeep function for description + * @dev this function may be deprecated in a future version of chainlink automation + */ + function checkUpkeep( + uint256 id + ) + external + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ) + { + return checkUpkeep(id, bytes("")); + } + + /** + * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) + * @param id the upkeepID to execute a callback for + * @param values the values returned from the data streams lookup + * @param extraData the user-provided extra context data + */ + function checkCallback( + uint256 id, + bytes[] memory values, + bytes calldata extraData + ) + external + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); + return executeCallback(id, payload); + } + + /** + * @notice this is a generic callback executor that forwards a call to a user's contract with the configured + * gas limit + * @param id the upkeepID to execute a callback for + * @param payload the data (including function selector) to call on the upkeep target contract + */ + function executeCallback( + uint256 id, + bytes memory payload + ) + public + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + _preventExecution(); + + Upkeep memory upkeep = s_upkeep[id]; + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); + gasUsed = gasUsed - gasleft(); + if (!success) { + return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); + } + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) { + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); + } + if (performData.length > s_storage.maxPerformDataSize) { + return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); + } + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); + } + + /** + * @notice simulates the upkeep with the perform data returned from checkUpkeep + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + * @return success whether the call reverted or not + * @return gasUsed the amount of gas the target contract consumed + */ + function simulatePerformUpkeep( + uint256 id, + bytes calldata performData + ) external returns (bool success, uint256 gasUsed) { + _preventExecution(); + + if (s_hotVars.paused) revert RegistryPaused(); + Upkeep memory upkeep = s_upkeep[id]; + (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); + return (success, gasUsed); + } + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice adds fund to an upkeep + * @param id the upkeepID + * @param amount the amount of funds to add, in the upkeep's billing token + */ + function addFunds(uint256 id, uint96 amount) external payable { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + if (msg.value != 0) { + if (upkeep.billingToken != IERC20(i_wrappedNativeToken)) { + revert InvalidToken(); + } + amount = SafeCast.toUint96(msg.value); + } + + s_upkeep[id].balance = upkeep.balance + amount; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + amount; + + if (msg.value == 0) { + // ERC20 payment + upkeep.billingToken.safeTransferFrom(msg.sender, address(this), amount); + } else { + // native payment + i_wrappedNativeToken.deposit{value: amount}(); + } + + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @notice overrides the billing config for an upkeep + * @param id the upkeepID + * @param billingOverrides the override-able billing config + */ + function setBillingOverrides(uint256 id, BillingOverrides calldata billingOverrides) external { + _onlyPrivilegeManagerAllowed(); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].overridesEnabled = true; + s_billingOverrides[id] = billingOverrides; + emit BillingConfigOverridden(id, billingOverrides); + } + + /** + * @notice remove the overridden billing config for an upkeep + * @param id the upkeepID + */ + function removeBillingOverrides(uint256 id) external { + _onlyPrivilegeManagerAllowed(); + + s_upkeep[id].overridesEnabled = false; + delete s_billingOverrides[id]; + emit BillingConfigOverrideRemoved(id); + } + + /** + * @notice transfers the address of an admin for an upkeep + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + _requireAdminAndNotCancelled(id); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of an upkeep admin + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = s_upkeepAdmin[id]; + s_upkeepAdmin[id] = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused + */ + function pauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @notice unpauses an upkeep + */ + function unpauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @notice updates the checkData for an upkeep + */ + function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { + _requireAdminAndNotCancelled(id); + if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataSet(id, newCheckData); + } + + /** + * @notice updates the gas limit for an upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + _requireAdminAndNotCancelled(id); + s_upkeep[id].performGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @notice updates the offchain config for an upkeep + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { + _requireAdminAndNotCancelled(id); + s_upkeepOffchainConfig[id] = config; + emit UpkeepOffchainConfigSet(id, config); + } + + /** + * @notice sets the upkeep trigger config + * @param id the upkeepID to change the trigger for + * @param triggerConfig the new trigger config + */ + function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { + _requireAdminAndNotCancelled(id); + s_upkeepTriggerConfig[id] = triggerConfig; + emit UpkeepTriggerConfigSet(id, triggerConfig); + } + + /** + * @notice withdraws an upkeep's funds from an upkeep + * @dev note that an upkeep must be cancelled first!! + */ + function withdrawFunds(uint256 id, address to) external nonReentrant { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); + uint96 amountToWithdraw = s_upkeep[id].balance; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - amountToWithdraw; + s_upkeep[id].balance = 0; + upkeep.billingToken.safeTransfer(to, amountToWithdraw); + emit FundsWithdrawn(id, amountToWithdraw, to); + } + + // ================================================================ + // | FINANCE ACTIONS | + // ================================================================ + + /** + * @notice withdraws excess LINK from the liquidity pool + * @param to the address to send the fees to + * @param amount the amount to withdraw + */ + function withdrawLink(address to, uint256 amount) external { + _onlyFinanceAdminAllowed(); + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + + int256 available = _linkAvailableForPayment(); + if (available < 0) { + revert InsufficientBalance(0, amount); + } else if (amount > uint256(available)) { + revert InsufficientBalance(uint256(available), amount); + } + + bool transferStatus = i_link.transfer(to, amount); + if (!transferStatus) { + revert TransferFailed(); + } + emit FeesWithdrawn(address(i_link), to, amount); + } + + /** + * @notice withdraws non-LINK fees earned by the contract + * @param asset the asset to withdraw + * @param to the address to send the fees to + * @param amount the amount to withdraw + * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity + * to cover all outstanding debts on the registry + */ + function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { + _onlyFinanceAdminAllowed(); + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (address(asset) == address(i_link)) revert InvalidToken(); + if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); + uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; + if (amount > available) revert InsufficientBalance(available, amount); + + asset.safeTransfer(to, amount); + emit FeesWithdrawn(address(asset), to, amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol new file mode 100644 index 0000000..8fc9448 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @dev see AutomationRegistry master contract for constructor description + */ + constructor( + address link, + address linkUSDFeed, + address nativeUSDFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress, + PayoutMode payoutMode, + address wrappedNativeTokenAddress + ) + AutomationRegistryBase2_3( + link, + linkUSDFeed, + nativeUSDFeed, + fastGasFeed, + automationForwarderLogic, + allowedReadOnlyAddress, + payoutMode, + wrappedNativeTokenAddress + ) + {} + + // ================================================================ + // | NODE ACTIONS | + // ================================================================ + + /** + * @notice transfers the address of payee for a transmitter + */ + function transferPayeeship(address transmitter, address proposed) external { + if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[transmitter] != proposed) { + s_proposedPayee[transmitter] = proposed; + emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of the payee + */ + function acceptPayeeship(address transmitter) external { + if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_transmitterPayees[transmitter]; + s_transmitterPayees[transmitter] = msg.sender; + s_proposedPayee[transmitter] = ZERO_ADDRESS; + + emit PayeeshipTransferred(transmitter, past, msg.sender); + } + + /** + * @notice this is for NOPs to withdraw LINK received as payment for work performed + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (s_payoutMode == PayoutMode.OFF_CHAIN) revert MustSettleOffchain(); + if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); + uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); + s_transmitters[from].balance = 0; + s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] - balance; + bool transferStatus = i_link.transfer(to, balance); + if (!transferStatus) { + revert TransferFailed(); + } + emit PaymentWithdrawn(from, balance, to, msg.sender); + } + + // ================================================================ + // | OWNER / MANAGER ACTIONS | + // ================================================================ + + /** + * @notice sets the privilege config for an upkeep + */ + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { + _onlyPrivilegeManagerAllowed(); + s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; + emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); + } + + /** + * @notice this is used by the owner to set the initial payees for newly added transmitters. The owner is not allowed to change payees for existing transmitters. + * @dev the IGNORE_ADDRESS is a "helper" that makes it easier to construct a list of payees when you only care about setting the payee for a small number of transmitters. + */ + function setPayees(address[] calldata payees) external onlyOwner { + if (s_transmittersList.length != payees.length) revert ParameterLengthError(); + for (uint256 i = 0; i < s_transmittersList.length; i++) { + address transmitter = s_transmittersList[i]; + address oldPayee = s_transmitterPayees[transmitter]; + address newPayee = payees[i]; + + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) { + revert InvalidPayee(); + } + + if (newPayee != IGNORE_ADDRESS) { + s_transmitterPayees[transmitter] = newPayee; + } + } + emit PayeesUpdated(s_transmittersList, payees); + } + + /** + * @notice sets the migration permission for a peer registry + * @dev this must be done before upkeeps can be migrated to/from another registry + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @notice pauses the entire registry + */ + function pause() external onlyOwner { + s_hotVars.paused = true; + emit Paused(msg.sender); + } + + /** + * @notice unpauses the entire registry + */ + function unpause() external onlyOwner { + s_hotVars.paused = false; + emit Unpaused(msg.sender); + } + + /** + * @notice sets a generic bytes field used to indicate the privilege that this admin address had + * @param admin the address to set privilege for + * @param newPrivilegeConfig the privileges that this admin has + */ + function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { + _onlyPrivilegeManagerAllowed(); + s_adminPrivilegeConfig[admin] = newPrivilegeConfig; + emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); + } + + /** + * @notice settles NOPs' LINK payment offchain + */ + function settleNOPsOffchain() external { + _onlyFinanceAdminAllowed(); + if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); + + uint96 totalPremium = s_hotVars.totalPremium; + uint256 activeTransmittersLength = s_transmittersList.length; + uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); + uint256 length = activeTransmittersLength + deactivatedTransmittersLength; + uint256[] memory payments = new uint256[](length); + address[] memory payees = new address[](length); + + for (uint256 i = 0; i < activeTransmittersLength; i++) { + address transmitterAddr = s_transmittersList[i]; + uint96 balance = _updateTransmitterBalanceFromPool( + transmitterAddr, + totalPremium, + uint96(activeTransmittersLength) + ); + + payments[i] = balance; + payees[i] = s_transmitterPayees[transmitterAddr]; + s_transmitters[transmitterAddr].balance = 0; + } + + for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { + address deactivatedAddr = s_deactivatedTransmitters.at(i); + Transmitter memory transmitter = s_transmitters[deactivatedAddr]; + + payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; + payments[i + activeTransmittersLength] = transmitter.balance; + s_transmitters[deactivatedAddr].balance = 0; + } + + // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode + s_reserveAmounts[IERC20(address(i_link))] = 0; + + for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { + s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); + } + + emit NOPsSettledOffchain(payees, payments); + } + + /** + * @notice disables offchain payment for NOPs + */ + function disableOffchainPayments() external onlyOwner { + s_payoutMode = PayoutMode.ON_CHAIN; + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + function getConditionalGasOverhead() external pure returns (uint256) { + return REGISTRY_CONDITIONAL_OVERHEAD; + } + + function getLogGasOverhead() external pure returns (uint256) { + return REGISTRY_LOG_OVERHEAD; + } + + function getPerPerformByteGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; + } + + function getPerSignerGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_SIGNER_GAS_OVERHEAD; + } + + function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256) { + return TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD; + } + + function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256) { + return TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD; + } + + function getCancellationDelay() external pure returns (uint256) { + return CANCELLATION_DELAY; + } + + function getLinkAddress() external view returns (address) { + return address(i_link); + } + + function getLinkUSDFeedAddress() external view returns (address) { + return address(i_linkUSDFeed); + } + + function getNativeUSDFeedAddress() external view returns (address) { + return address(i_nativeUSDFeed); + } + + function getFastGasFeedAddress() external view returns (address) { + return address(i_fastGasFeed); + } + + function getAutomationForwarderLogic() external view returns (address) { + return i_automationForwarderLogic; + } + + function getAllowedReadOnlyAddress() external view returns (address) { + return i_allowedReadOnlyAddress; + } + + function getWrappedNativeTokenAddress() external view returns (address) { + return address(i_wrappedNativeToken); + } + + function getBillingToken(uint256 upkeepID) external view returns (IERC20) { + return s_upkeep[upkeepID].billingToken; + } + + function getBillingTokens() external view returns (IERC20[] memory) { + return s_billingTokens; + } + + function supportsBillingToken(IERC20 token) external view returns (bool) { + return address(s_billingConfigs[token].priceFeed) != address(0); + } + + function getBillingTokenConfig(IERC20 token) external view returns (BillingConfig memory) { + return s_billingConfigs[token]; + } + + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool) { + return s_upkeep[upkeepID].overridesEnabled; + } + + function getPayoutMode() external view returns (PayoutMode) { + return s_payoutMode; + } + + function upkeepVersion() public pure returns (uint8) { + return UPKEEP_VERSION_BASE; + } + + /** + * @notice gets the number of upkeeps on the registry + */ + function getNumUpkeeps() external view returns (uint256) { + return s_upkeepIDs.length(); + } + + /** + * @notice read all of the details about an upkeep + * @dev this function may be deprecated in a future version of automation in favor of individual + * getters for each field + */ + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { + Upkeep memory reg = s_upkeep[id]; + address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); + upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ + target: target, + performGas: reg.performGas, + checkData: s_checkData[id], + balance: reg.balance, + admin: s_upkeepAdmin[id], + maxValidBlocknumber: reg.maxValidBlocknumber, + lastPerformedBlockNumber: reg.lastPerformedBlockNumber, + amountSpent: uint96(reg.amountSpent), // force casting to uint96 for backwards compatibility. Not an issue if it overflows. + paused: reg.paused, + offchainConfig: s_upkeepOffchainConfig[id] + }); + return upkeepInfo; + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { + uint256 numUpkeeps = s_upkeepIDs.length(); + if (startIndex >= numUpkeeps) revert IndexOutOfRange(); + uint256 endIndex = startIndex + maxCount; + endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; + uint256[] memory ids = new uint256[](endIndex - startIndex); + for (uint256 idx = 0; idx < ids.length; idx++) { + ids[idx] = s_upkeepIDs.at(idx + startIndex); + } + return ids; + } + + /** + * @notice returns the upkeep's trigger type + */ + function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { + return _getTriggerType(upkeepId); + } + + /** + * @notice returns the trigger config for an upkeeep + */ + function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { + return s_upkeepTriggerConfig[upkeepId]; + } + + /** + * @notice read the current info about any transmitter address + */ + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { + Transmitter memory transmitter = s_transmitters[query]; + + uint96 pooledShare = 0; + if (transmitter.active) { + uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; + pooledShare = totalDifference / uint96(s_transmittersList.length); + } + + return ( + transmitter.active, + transmitter.index, + (transmitter.balance + pooledShare), + transmitter.lastCollected, + s_transmitterPayees[query] + ); + } + + /** + * @notice read the current info about any signer address + */ + function getSignerInfo(address query) external view returns (bool active, uint8 index) { + Signer memory signer = s_signers[query]; + return (signer.active, signer.index); + } + + /** + * @notice read the current on-chain config of the registry + * @dev this function will change between versions, it should never be used where + * backwards compatibility matters! + */ + function getConfig() external view returns (OnchainConfig memory) { + return + OnchainConfig({ + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + fallbackNativePrice: s_fallbackNativePrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager, + chainModule: s_hotVars.chainModule, + reorgProtectionEnabled: s_hotVars.reorgProtectionEnabled, + financeAdmin: s_storage.financeAdmin + }); + } + + /** + * @notice read the current state of the registry + * @dev this function is deprecated + */ + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) + { + state = IAutomationV21PlusCommon.StateLegacy({ + nonce: s_storage.nonce, + ownerLinkBalance: 0, // deprecated + expectedLinkBalance: 0, // deprecated + totalPremium: s_hotVars.totalPremium, + numUpkeeps: s_upkeepIDs.length(), + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + latestConfigDigest: s_latestConfigDigest, + latestEpoch: s_hotVars.latestEpoch, + paused: s_hotVars.paused + }); + + config = IAutomationV21PlusCommon.OnchainConfigLegacy({ + paymentPremiumPPB: 0, // deprecated + flatFeeMicroLink: 0, // deprecated + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + minUpkeepSpend: 0, // deprecated + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager + }); + + return (state, config, s_signersList, s_transmittersList, s_hotVars.f); + } + + /** + * @notice read the Storage data + * @dev this function signature will change with each version of automation + * this should not be treated as a stable function + */ + function getStorage() external view returns (Storage memory) { + return s_storage; + } + + /** + * @notice read the HotVars data + * @dev this function signature will change with each version of automation + * this should not be treated as a stable function + */ + function getHotVars() external view returns (HotVars memory) { + return s_hotVars; + } + + /** + * @notice get the chain module + */ + function getChainModule() external view returns (IChainModule chainModule) { + return s_hotVars.chainModule; + } + + /** + * @notice if this registry has reorg protection enabled + */ + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { + return s_hotVars.reorgProtectionEnabled; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getBalance(uint256 id) external view returns (uint96 balance) { + return s_upkeep[id].balance; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalance(uint256 id) external view returns (uint96) { + return getMinBalanceForUpkeep(id); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + * @dev this will be deprecated in a future version in favor of getMinBalance + */ + function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { + Upkeep memory upkeep = s_upkeep[id]; + return getMaxPaymentForGas(id, _getTriggerType(id), upkeep.performGas, upkeep.billingToken); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas( + uint256 id, + Trigger triggerType, + uint32 gasLimit, + IERC20 billingToken + ) public view returns (uint96 maxPayment) { + HotVars memory hotVars = s_hotVars; + (uint256 fastGasWei, uint256 linkUSD, uint256 nativeUSD) = _getFeedData(hotVars); + return _getMaxPayment(id, hotVars, triggerType, gasLimit, fastGasWei, linkUSD, nativeUSD, billingToken); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { + return s_upkeepPrivilegeConfig[upkeepId]; + } + + /** + * @notice returns the admin's privilege config + */ + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { + return s_adminPrivilegeConfig[admin]; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { + return s_upkeep[upkeepID].forwarder; + } + + /** + * @notice returns if the dedupKey exists or not + */ + function hasDedupKey(bytes32 dedupKey) external view returns (bool) { + return s_dedupKeys[dedupKey]; + } + + /** + * @notice returns the fallback native price + */ + function getFallbackNativePrice() external view returns (uint256) { + return s_fallbackNativePrice; + } + + /** + * @notice returns the amount of a particular token that is reserved as + * user deposits / NOP payments + */ + function getReserveAmount(IERC20 billingToken) external view returns (uint256) { + return s_reserveAmounts[billingToken]; + } + + /** + * @notice returns the amount of a particular token that is withdraw-able by finance admin + */ + function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { + return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; + } + + /** + * @notice returns the size of the LINK liquidity pool + */ + function linkAvailableForPayment() public view returns (int256) { + return _linkAvailableForPayment(); + } + + /** + * @notice returns the BillingOverrides config for a given upkeep + */ + function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { + return s_billingOverrides[upkeepID]; + } + + /** + * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc + */ + function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { + return s_billingConfigs[billingToken]; + } + + /** + * @notice returns all active transmitters with their associated payees + */ + function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { + uint256 transmitterCount = s_transmittersList.length; + TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); + + for (uint256 i = 0; i < transmitterCount; i++) { + address transmitterAddress = s_transmittersList[i]; + address payeeAddress = s_transmitterPayees[transmitterAddress]; + + transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); + } + + return transmitters; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol new file mode 100644 index 0000000..59081b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; + +/** + * @notice this file exposes structs that are otherwise internal to the automation registry + * doing this allows those structs to be encoded and decoded with type safety in offchain code + * and tests because generated wrappers are made available + */ + +contract AutomationUtils2_3 { + /** + * @dev this uses the v2.3 Report, which uses linkUSD instead of linkNative (as in v2.2 and prior). This should be used only in typescript tests. + */ + function _report(AutomationRegistryBase2_3.Report memory) external {} // 0xe65d6546 +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE new file mode 100644 index 0000000..515985a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE @@ -0,0 +1,57 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +--- + +Parameters + +Licensor: SmartContract Chainlink Limited SEZC + +Licensed Work: Automation v2.3 +The Licensed Work is (c) 2024 SmartContract Chainlink Limited SEZC + +Additional Use Grant(s): +You may make use of Automation v2.1, v2.2, v2.3 (which is available subject to the license here the “Licensed Work”) solely for purposes listed below: +https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md + +Change Date: March 1, 2024 + +Change License: MIT + +--- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. + +If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. + +MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. + +--- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. + +2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol new file mode 100644 index 0000000..32530c7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity 0.8.19; + +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; + +enum RegistryVersion { + V12, + V13, + V20, + V21, + V23 +} + +/** + * @notice UpkeepTranscoder is a contract that allows converting upkeep data from previous registry versions to newer versions + * @dev it currently only supports 2.3 -> 2.3 migrations + */ +contract UpkeepTranscoder5_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { + error InvalidTranscoding(); + + string public constant override typeAndVersion = "UpkeepTranscoder 5.0.0"; + + /** + * @notice transcodeUpkeeps transforms upkeep data from the format expected by + * one registry to the format expected by another. It future-proofs migrations + * by allowing automation team to customize migration paths and set sensible defaults + * when new fields are added + * @param fromVersion version the upkeep is migrating from + * @param toVersion version the upkeep is migrating to + * @param encodedUpkeeps encoded upkeep data + * @dev this transcoder should ONLY be use for V23->V23 migrations for now + */ + function transcodeUpkeeps( + uint8 fromVersion, + uint8 toVersion, + bytes calldata encodedUpkeeps + ) external view override returns (bytes memory) { + if (toVersion == uint8(RegistryVersion.V23) && fromVersion == uint8(RegistryVersion.V23)) { + return encodedUpkeeps; + } + + revert InvalidTranscoding(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol new file mode 100644 index 0000000..5d5bf23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; +import {ZKSyncAutomationRegistryLogicA2_3} from "./ZKSyncAutomationRegistryLogicA2_3.sol"; +import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/** + * @notice Registry for adding work for Chainlink nodes to perform on client + * contracts. Clients must support the AutomationCompatibleInterface interface. + */ +contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abstract, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @notice versions: + * AutomationRegistry 2.3.0: supports native and ERC20 billing + * changes flat fee to USD-denominated + * adds support for custom billing overrides + * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module + * KeeperRegistry 2.1.0: introduces support for log triggers + * removes the need for "wrapped perform data" + * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts + * fixes issue with arbitrum block number + * does an early return in case of stale report instead of revert + * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X + * KeeperRegistry 2.0.0: implement OCR interface + * KeeperRegistry 1.3.0: split contract into Proxy and Logic + * account for Arbitrum and Optimism L1 gas fee + * allow users to configure upkeeps + * KeeperRegistry 1.2.0: allow funding within performUpkeep + * allow configurable registry maxPerformGas + * add function to let admin change upkeep gas limit + * add minUpkeepSpend requirement + * upgrade to solidity v0.8 + * KeeperRegistry 1.1.0: added flatFeeMicroLink + * KeeperRegistry 1.0.0: initial release + */ + string public constant override typeAndVersion = "AutomationRegistry 2.3.0"; + + /** + * @param logicA the address of the first logic contract + * @dev we cast the contract to logicC in order to call logicC functions (via fallback) + */ + constructor( + ZKSyncAutomationRegistryLogicA2_3 logicA + ) + ZKSyncAutomationRegistryBase2_3( + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getLinkAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getLinkUSDFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getNativeUSDFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getFastGasFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getAutomationForwarderLogic(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getAllowedReadOnlyAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getPayoutMode(), + ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getWrappedNativeTokenAddress() + ) + Chainable(address(logicA)) + {} + + /** + * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors + */ + struct TransmitVars { + uint16 numUpkeepsPassedChecks; + uint96 totalReimbursement; + uint96 totalPremium; + } + + // ================================================================ + // | HOT PATH ACTIONS | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + */ + function transmit( + bytes32[3] calldata reportContext, + bytes calldata rawReport, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external override { + // use this msg.data length check to ensure no extra data is included in the call + // 4 is first 4 bytes of the keccak-256 hash of the function signature. ss.length == rs.length so use one of them + // 4 + (32 * 3) + (rawReport.length + 32 + 32) + (32 * rs.length + 32 + 32) + (32 * ss.length + 32 + 32) + 32 + uint256 requiredLength = 324 + rawReport.length + 64 * rs.length; + if (msg.data.length != requiredLength) revert InvalidDataLength(); + HotVars memory hotVars = s_hotVars; + + if (hotVars.paused) revert RegistryPaused(); + if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); + + // Verify signatures + if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); + if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); + _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); + + Report memory report = _decodeReport(rawReport); + + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + + _handleReport(hotVars, report); + + if (epoch > hotVars.latestEpoch) { + s_hotVars.latestEpoch = epoch; + } + } + + /** + * @notice handles the report by performing the upkeeps and updating the state + * @param hotVars the hot variables of the registry + * @param report the report to be handled (already verified and decoded) + * @dev had to split this function from transmit() to avoid stack too deep errors + * @dev all other internal / private functions are generally defined in the Base contract + * we leave this here because it is essentially a continuation of the transmit() function, + */ + function _handleReport(HotVars memory hotVars, Report memory report) private { + UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); + TransmitVars memory transmitVars = TransmitVars({ + numUpkeepsPassedChecks: 0, + totalReimbursement: 0, + totalPremium: 0 + }); + + uint256 blocknumber = hotVars.chainModule.blockNumber(); + uint256 gasOverhead; + + 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( + report.upkeepIds[i], + blocknumber, + report.triggers[i], + upkeepTransmitInfo[i], + hotVars + ); + + if (upkeepTransmitInfo[i].earlyChecksPassed) { + transmitVars.numUpkeepsPassedChecks += 1; + } else { + continue; + } + + // Actually perform the target upkeep + (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( + upkeepTransmitInfo[i].upkeep.forwarder, + report.gasLimits[i], + report.performDatas[i] + ); + + // Store last perform block number / deduping key for upkeep + _updateTriggerMarker(report.upkeepIds[i], blocknumber, upkeepTransmitInfo[i]); + + if (upkeepTransmitInfo[i].triggerType == Trigger.CONDITION) { + gasOverhead += REGISTRY_CONDITIONAL_OVERHEAD; + } else if (upkeepTransmitInfo[i].triggerType == Trigger.LOG) { + gasOverhead += REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } + } + // No upkeeps to be performed in this report + if (transmitVars.numUpkeepsPassedChecks == 0) { + return; + } + + gasOverhead += + 16 * + msg.data.length + + ACCOUNTING_FIXED_GAS_OVERHEAD + + (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); + gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; + + { + BillingTokenPaymentParams memory billingTokenParams; + uint256 nativeUSD = _getNativeUSD(hotVars); + for (uint256 i = 0; i < report.upkeepIds.length; i++) { + if (upkeepTransmitInfo[i].earlyChecksPassed) { + if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { + billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); + } + PaymentReceipt memory receipt = _handlePayment( + hotVars, + PaymentParams({ + gasLimit: upkeepTransmitInfo[i].gasUsed, + gasOverhead: gasOverhead, + l1CostWei: 0, + fastGasWei: report.fastGasWei, + linkUSD: report.linkUSD, + nativeUSD: nativeUSD, + billingToken: upkeepTransmitInfo[i].upkeep.billingToken, + billingTokenParams: billingTokenParams, + isTransaction: true + }), + report.upkeepIds[i], + upkeepTransmitInfo[i].upkeep + ); + transmitVars.totalPremium += receipt.premiumInJuels; + transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; + + emit UpkeepPerformed( + report.upkeepIds[i], + upkeepTransmitInfo[i].performSuccess, + receipt.gasChargeInBillingToken + receipt.premiumInBillingToken, + upkeepTransmitInfo[i].gasUsed, + gasOverhead, + report.triggers[i] + ); + } + } + } + // record payments to NOPs, all in LINK + s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; + s_hotVars.totalPremium += transmitVars.totalPremium; + s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium; + } + + // ================================================================ + // | OCR2ABSTRACT | + // ================================================================ + + /** + * @inheritdoc OCR2Abstract + * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfigBytes, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override { + (OnchainConfig memory config, IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) = abi.decode( + onchainConfigBytes, + (OnchainConfig, IERC20[], BillingConfig[]) + ); + + setConfigTypeSafe( + signers, + transmitters, + f, + config, + offchainConfigVersion, + offchainConfig, + billingTokens, + billingConfigs + ); + } + + /** + * @notice sets the configuration for the registry + * @param signers the list of permitted signers + * @param transmitters the list of permitted transmitters + * @param f the maximum tolerance for faulty nodes + * @param onchainConfig configuration values that are used on-chain + * @param offchainConfigVersion the version of the offchainConfig + * @param offchainConfig configuration values that are used off-chain + * @param billingTokens the list of valid billing tokens + * @param billingConfigs the configurations for each billing token + */ + function setConfigTypeSafe( + address[] memory signers, + address[] memory transmitters, + uint8 f, + OnchainConfig memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + IERC20[] memory billingTokens, + BillingConfig[] memory billingConfigs + ) public onlyOwner { + if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); + if (f == 0) revert IncorrectNumberOfFaultyOracles(); + if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); + if (billingTokens.length != billingConfigs.length) revert ParameterLengthError(); + // set billing config for tokens + _setBillingConfig(billingTokens, billingConfigs); + + _updateTransmitters(signers, transmitters); + + s_hotVars = HotVars({ + f: f, + stalenessSeconds: onchainConfig.stalenessSeconds, + gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, + paused: s_hotVars.paused, + reentrancyGuard: s_hotVars.reentrancyGuard, + totalPremium: s_hotVars.totalPremium, + latestEpoch: 0, // DON restarts epoch + reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, + chainModule: onchainConfig.chainModule + }); + + uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; + uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); + uint32 newConfigCount = s_storage.configCount + 1; + + s_storage = Storage({ + checkGasLimit: onchainConfig.checkGasLimit, + maxPerformGas: onchainConfig.maxPerformGas, + transcoder: onchainConfig.transcoder, + maxCheckDataSize: onchainConfig.maxCheckDataSize, + maxPerformDataSize: onchainConfig.maxPerformDataSize, + maxRevertDataSize: onchainConfig.maxRevertDataSize, + upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, + financeAdmin: onchainConfig.financeAdmin, + nonce: s_storage.nonce, + configCount: newConfigCount, + latestConfigBlockNumber: newLatestConfigBlockNumber + }); + s_fallbackGasPrice = onchainConfig.fallbackGasPrice; + s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; + s_fallbackNativePrice = onchainConfig.fallbackNativePrice; + + bytes memory onchainConfigBytes = abi.encode(onchainConfig); + + s_latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + + for (uint256 idx = s_registrars.length(); idx > 0; idx--) { + s_registrars.remove(s_registrars.at(idx - 1)); + } + + for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { + s_registrars.add(onchainConfig.registrars[idx]); + } + + emit ConfigSet( + previousConfigBlockNumber, + s_latestConfigDigest, + s_storage.configCount, + signers, + transmitters, + f, + onchainConfigBytes, + offchainConfigVersion, + offchainConfig + ); + } + + /** + * @inheritdoc OCR2Abstract + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); + } + + /** + * @inheritdoc OCR2Abstract + * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface + */ + function latestConfigDigestAndEpoch() + external + view + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (false, s_latestConfigDigest, s_hotVars.latestEpoch); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol new file mode 100644 index 0000000..41097af --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol @@ -0,0 +1,1197 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; +import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; + +/** + * @notice Base Keeper Registry contract, contains shared logic between + * AutomationRegistry and AutomationRegistryLogic + * @dev all errors, events, and internal functions should live here + */ +// solhint-disable-next-line max-states-count +abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + address internal constant ZERO_ADDRESS = address(0); + address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; + bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; + bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; + bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; + uint256 internal constant PERFORM_GAS_MIN = 2_300; + uint256 internal constant CANCELLATION_DELAY = 50; + uint32 internal constant UINT32_MAX = type(uint32).max; + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + uint8 internal constant UPKEEP_VERSION_BASE = 4; + + // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation + // These values are calibrated using hardhat tests which simulate various cases and verify that + // the variables result in accurate estimation + uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps + uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // Fixed gas overhead for log upkeeps + uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f + + // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the + // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants + // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that + // the variables result in accurate estimation + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_000; // Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 20_000; // Overhead per upkeep performed in batch + + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_linkUSDFeed; + AggregatorV3Interface internal immutable i_nativeUSDFeed; + AggregatorV3Interface internal immutable i_fastGasFeed; + address internal immutable i_automationForwarderLogic; + address internal immutable i_allowedReadOnlyAddress; + IWrappedNative internal immutable i_wrappedNativeToken; + + /** + * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit + * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path + */ + + // Upkeep storage + EnumerableSet.UintSet internal s_upkeepIDs; + mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit + mapping(uint256 => address) internal s_upkeepAdmin; + mapping(uint256 => address) internal s_proposedAdmin; + mapping(uint256 => bytes) internal s_checkData; + mapping(bytes32 => bool) internal s_dedupKeys; + // Registry config and state + EnumerableSet.AddressSet internal s_registrars; + mapping(address => Transmitter) internal s_transmitters; + mapping(address => Signer) internal s_signers; + address[] internal s_signersList; // s_signersList contains the signing address of each oracle + address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle + EnumerableSet.AddressSet internal s_deactivatedTransmitters; + mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. + mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter + bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification + HotVars internal s_hotVars; // Mixture of config and state, used in transmit + Storage internal s_storage; // Mixture of config and state, not used in transmit + uint256 internal s_fallbackGasPrice; + uint256 internal s_fallbackLinkPrice; + uint256 internal s_fallbackNativePrice; + mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro + mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers + mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep + mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep + mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin + // billing + mapping(IERC20 billingToken => uint256 reserveAmount) internal s_reserveAmounts; // unspent user deposits + unwithdrawn NOP payments + mapping(IERC20 billingToken => BillingConfig billingConfig) internal s_billingConfigs; // billing configurations for different tokens + mapping(uint256 upkeepID => BillingOverrides billingOverrides) internal s_billingOverrides; // billing overrides for specific upkeeps + IERC20[] internal s_billingTokens; // list of billing tokens + PayoutMode internal s_payoutMode; + + error ArrayHasNoEntries(); + error CannotCancel(); + error CheckDataExceedsLimit(); + error ConfigDigestMismatch(); + error DuplicateEntry(); + error DuplicateSigners(); + error GasLimitCanOnlyIncrease(); + error GasLimitOutsideRange(); + error IncorrectNumberOfFaultyOracles(); + error IncorrectNumberOfSignatures(); + error IncorrectNumberOfSigners(); + error IndexOutOfRange(); + error InsufficientBalance(uint256 available, uint256 requested); + error InsufficientLinkLiquidity(); + error InvalidDataLength(); + error InvalidFeed(); + error InvalidTrigger(); + error InvalidPayee(); + error InvalidRecipient(); + error InvalidReport(); + error InvalidSigner(); + error InvalidToken(); + error InvalidTransmitter(); + error InvalidTriggerType(); + error MigrationNotPermitted(); + error MustSettleOffchain(); + error MustSettleOnchain(); + error NotAContract(); + error OnlyActiveSigners(); + error OnlyActiveTransmitters(); + error OnlyCallableByAdmin(); + error OnlyCallableByLINKToken(); + error OnlyCallableByOwnerOrAdmin(); + error OnlyCallableByOwnerOrRegistrar(); + error OnlyCallableByPayee(); + error OnlyCallableByProposedAdmin(); + error OnlyCallableByProposedPayee(); + error OnlyCallableByUpkeepPrivilegeManager(); + error OnlyFinanceAdmin(); + error OnlyPausedUpkeep(); + error OnlySimulatedBackend(); + error OnlyUnpausedUpkeep(); + error ParameterLengthError(); + error ReentrantCall(); + error RegistryPaused(); + error RepeatedSigner(); + error RepeatedTransmitter(); + error TargetCheckReverted(bytes reason); + error TooManyOracles(); + error TranscoderNotSet(); + error TransferFailed(); + error UpkeepAlreadyExists(); + error UpkeepCancelled(); + error UpkeepNotCanceled(); + error UpkeepNotNeeded(); + error ValueNotChanged(); + error ZeroAddressNotAllowed(); + + enum MigrationPermission { + NONE, + OUTGOING, + INCOMING, + BIDIRECTIONAL + } + + enum Trigger { + CONDITION, + LOG + } + + enum UpkeepFailureReason { + NONE, + UPKEEP_CANCELLED, + UPKEEP_PAUSED, + TARGET_CHECK_REVERTED, + UPKEEP_NOT_NEEDED, + PERFORM_DATA_EXCEEDS_LIMIT, + INSUFFICIENT_BALANCE, + CALLBACK_REVERTED, + REVERT_DATA_EXCEEDS_LIMIT, + REGISTRY_PAUSED + } + + enum PayoutMode { + ON_CHAIN, + OFF_CHAIN + } + + /** + * @notice OnchainConfig of the registry + * @dev used only in setConfig() + * @member checkGasLimit gas limit when checking for upkeep + * @member stalenessSeconds number of seconds that is allowed for feed data to + * be stale before switching to the fallback pricing + * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price + * when calculating the payment ceiling for keepers + * @member maxPerformGas max performGas allowed for an upkeep on this registry + * @member maxCheckDataSize max length of checkData bytes + * @member maxPerformDataSize max length of performData bytes + * @member maxRevertDataSize max length of revertData bytes + * @member fallbackGasPrice gas price used if the gas price feed is stale + * @member fallbackLinkPrice LINK price used if the LINK price feed is stale + * @member transcoder address of the transcoder contract + * @member registrars addresses of the registrar contracts + * @member upkeepPrivilegeManager address which can set privilege for upkeeps + * @member reorgProtectionEnabled if this registry enables re-org protection checks + * @member chainModule the chain specific module + */ + struct OnchainConfig { + uint32 checkGasLimit; + uint32 maxPerformGas; + uint32 maxCheckDataSize; + address transcoder; + // 1 word full + bool reorgProtectionEnabled; + uint24 stalenessSeconds; + uint32 maxPerformDataSize; + uint32 maxRevertDataSize; + address upkeepPrivilegeManager; + // 2 words full + uint16 gasCeilingMultiplier; + address financeAdmin; + // 3 words + uint256 fallbackGasPrice; + uint256 fallbackLinkPrice; + uint256 fallbackNativePrice; + address[] registrars; + IChainModule chainModule; + } + + /** + * @notice relevant state of an upkeep which is used in transmit function + * @member paused if this upkeep has been paused + * @member overridesEnabled if this upkeep has overrides enabled + * @member performGas the gas limit of upkeep execution + * @member maxValidBlocknumber until which block this upkeep is valid + * @member forwarder the forwarder contract to use for this upkeep + * @member amountSpent the amount this upkeep has spent, in the upkeep's billing token + * @member balance the balance of this upkeep + * @member lastPerformedBlockNumber the last block number when this upkeep was performed + */ + struct Upkeep { + bool paused; + bool overridesEnabled; + uint32 performGas; + uint32 maxValidBlocknumber; + IAutomationForwarder forwarder; + // 2 bytes left in 1st EVM word - read in transmit path + uint128 amountSpent; + uint96 balance; + uint32 lastPerformedBlockNumber; + // 0 bytes left in 2nd EVM word - written in transmit path + IERC20 billingToken; + // 12 bytes left in 3rd EVM word - read in transmit path + } + + /// @dev Config + State storage struct which is on hot transmit path + struct HotVars { + uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium + uint32 latestEpoch; // │ latest epoch for which a report was transmitted + uint24 stalenessSeconds; // │ Staleness tolerance for feeds + uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound + uint8 f; // │ maximum number of faulty oracles + bool paused; // │ pause switch for all upkeeps in the registry + bool reentrancyGuard; // | guard against reentrancy + bool reorgProtectionEnabled; // ─╯ if this registry should enable the re-org protection mechanism + IChainModule chainModule; // the interface of chain specific module + } + + /// @dev Config + State storage struct which is not on hot transmit path + struct Storage { + address transcoder; // Address of transcoder contract used in migrations + uint32 checkGasLimit; // Gas limit allowed in checkUpkeep + uint32 maxPerformGas; // Max gas an upkeep can use on this registry + uint32 nonce; // Nonce for each upkeep created + // 1 EVM word full + address upkeepPrivilegeManager; // address which can set privilege for upkeeps + uint32 configCount; // incremented each time a new config is posted, The count is incorporated into the config digest to prevent replay attacks. + uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs + uint32 maxCheckDataSize; // max length of checkData bytes + // 2 EVM word full + address financeAdmin; // address which can withdraw funds from the contract + uint32 maxPerformDataSize; // max length of performData bytes + uint32 maxRevertDataSize; // max length of revertData bytes + // 4 bytes left in 3rd EVM word + } + + /// @dev Report transmitted by OCR to transmit function + struct Report { + uint256 fastGasWei; + uint256 linkUSD; + uint256[] upkeepIds; + uint256[] gasLimits; + bytes[] triggers; + bytes[] performDatas; + } + + /** + * @dev This struct is used to maintain run time information about an upkeep in transmit function + * @member upkeep the upkeep struct + * @member earlyChecksPassed whether the upkeep passed early checks before perform + * @member performSuccess whether the perform was successful + * @member triggerType the type of trigger + * @member gasUsed gasUsed by this upkeep in perform + * @member dedupID unique ID used to dedup an upkeep/trigger combo + */ + struct UpkeepTransmitInfo { + Upkeep upkeep; + bool earlyChecksPassed; + bool performSuccess; + Trigger triggerType; + uint256 gasUsed; + bytes32 dedupID; + } + + /** + * @notice holds information about a transmiter / node in the DON + * @member active can this transmitter submit reports + * @member index of oracle in s_signersList/s_transmittersList + * @member balance a node's balance in LINK + * @member lastCollected the total balance at which the node last withdrew + * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK + */ + struct Transmitter { + bool active; + uint8 index; + uint96 balance; + uint96 lastCollected; + } + + struct TransmitterPayeeInfo { + address transmitterAddress; + address payeeAddress; + } + + struct Signer { + bool active; + // Index of oracle in s_signersList/s_transmittersList + uint8 index; + } + + /** + * @notice the trigger structure conditional trigger type + */ + struct ConditionalTrigger { + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the trigger structure of log upkeeps + * @dev NOTE that blockNum / blockHash describe the block used for the callback, + * not necessarily the block number that the log was emitted in!!!! + */ + struct LogTrigger { + bytes32 logBlockHash; + bytes32 txHash; + uint32 logIndex; + uint32 blockNum; + bytes32 blockHash; + } + + /** + * @notice the billing config of a token + * @dev this is a storage struct + */ + // solhint-disable-next-line gas-struct-packing + struct BillingConfig { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; // min fee is $0.00001, max fee is $167 + AggregatorV3Interface priceFeed; + uint8 decimals; + // 1st word, read in calculating BillingTokenPaymentParams + uint256 fallbackPrice; + // 2nd word only read if stale + uint96 minSpend; + // 3rd word only read during cancellation + } + + /** + * @notice override-able billing params of a billing token + */ + struct BillingOverrides { + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + } + + /** + * @notice pricing params for a billing token + * @dev this is a memory-only struct, so struct packing is less important + */ + struct BillingTokenPaymentParams { + uint8 decimals; + uint32 gasFeePPB; + uint24 flatFeeMilliCents; + uint256 priceUSD; + } + + /** + * @notice struct containing price & payment information used in calculating payment amount + * @member gasLimit the amount of gas used + * @member gasOverhead the amount of gas overhead + * @member l1CostWei the amount to be charged for L1 fee in wei + * @member fastGasWei the fast gas price + * @member linkUSD the exchange ratio between LINK and USD + * @member nativeUSD the exchange ratio between the chain's native token and USD + * @member billingToken the billing token + * @member billingTokenParams the payment params specific to a particular payment token + * @member isTransaction is this an eth_call or a transaction + */ + struct PaymentParams { + uint256 gasLimit; + uint256 gasOverhead; + uint256 l1CostWei; + uint256 fastGasWei; + uint256 linkUSD; + uint256 nativeUSD; + IERC20 billingToken; + BillingTokenPaymentParams billingTokenParams; + bool isTransaction; + } + + /** + * @notice struct containing receipt information about a payment or cost estimation + * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals + * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals + * @member gasReimbursementInJuels the amount to reimburse a node for gas spent + * @member premiumInJuels the premium paid to NOPs, shared between all nodes + */ + // solhint-disable-next-line gas-struct-packing + struct PaymentReceipt { + uint96 gasChargeInBillingToken; + uint96 premiumInBillingToken; + // one word ends + uint96 gasReimbursementInJuels; + uint96 premiumInJuels; + // second word ends + IERC20 billingToken; + uint96 linkUSD; + // third word ends + uint96 nativeUSD; + uint96 billingUSD; + // fourth word ends + } + + event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); + event BillingConfigOverridden(uint256 indexed id, BillingOverrides overrides); + event BillingConfigOverrideRemoved(uint256 indexed id); + event BillingConfigSet(IERC20 indexed token, BillingConfig config); + event CancelledUpkeepReport(uint256 indexed id, bytes trigger); + event ChainSpecificModuleUpdated(address newModule); + event DedupKeyAdded(bytes32 indexed dedupKey); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); + event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); + event NOPsSettledOffchain(address[] payees, uint256[] payments); + event Paused(address account); + event PayeesUpdated(address[] transmitters, address[] payees); + event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); + event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); + event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); + event StaleUpkeepReport(uint256 indexed id, bytes trigger); + event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); + event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); + event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); + event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); + event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); + event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); + event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); + event UpkeepPaused(uint256 indexed id); + event UpkeepPerformed( + uint256 indexed id, + bool indexed success, + uint96 totalPayment, + uint256 gasUsed, + uint256 gasOverhead, + bytes trigger + ); + event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); + event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); + event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); + event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); + event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); + event UpkeepUnpaused(uint256 indexed id); + event Unpaused(address account); + + /** + * @param link address of the LINK Token + * @param linkUSDFeed address of the LINK/USD price feed + * @param nativeUSDFeed address of the Native/USD price feed + * @param fastGasFeed address of the Fast Gas price feed + * @param automationForwarderLogic the address of automation forwarder logic + * @param allowedReadOnlyAddress the address of the allowed read only address + * @param payoutMode the payout mode + */ + constructor( + address link, + address linkUSDFeed, + address nativeUSDFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress, + PayoutMode payoutMode, + address wrappedNativeTokenAddress + ) ConfirmedOwner(msg.sender) { + i_link = LinkTokenInterface(link); + i_linkUSDFeed = AggregatorV3Interface(linkUSDFeed); + i_nativeUSDFeed = AggregatorV3Interface(nativeUSDFeed); + i_fastGasFeed = AggregatorV3Interface(fastGasFeed); + i_automationForwarderLogic = automationForwarderLogic; + i_allowedReadOnlyAddress = allowedReadOnlyAddress; + s_payoutMode = payoutMode; + i_wrappedNativeToken = IWrappedNative(wrappedNativeTokenAddress); + if (i_linkUSDFeed.decimals() != i_nativeUSDFeed.decimals()) { + revert InvalidFeed(); + } + } + + // ================================================================ + // | INTERNAL FUNCTIONS ONLY | + // ================================================================ + + /** + * @dev creates a new upkeep with the given fields + * @param id the id of the upkeep + * @param upkeep the upkeep to create + * @param admin address to cancel upkeep and withdraw remaining funds + * @param checkData data which is passed to user's checkUpkeep + * @param triggerConfig the trigger config for this upkeep + * @param offchainConfig the off-chain config of this upkeep + */ + function _createUpkeep( + uint256 id, + Upkeep memory upkeep, + address admin, + bytes memory checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) internal { + if (s_hotVars.paused) revert RegistryPaused(); + if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) + revert GasLimitOutsideRange(); + if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); + if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidToken(); + s_upkeep[id] = upkeep; + s_upkeepAdmin[id] = admin; + s_checkData[id] = checkData; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + upkeep.balance; + s_upkeepTriggerConfig[id] = triggerConfig; + s_upkeepOffchainConfig[id] = offchainConfig; + s_upkeepIDs.add(id); + } + + /** + * @dev creates an ID for the upkeep based on the upkeep's type + * @dev the format of the ID looks like this: + * ****00000000000X**************** + * 4 bytes of entropy + * 11 bytes of zeros + * 1 identifying byte for the trigger type + * 16 bytes of entropy + * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique + * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only + * see the first 4 and last 4 hex values ex 0x1234...ABCD + */ + function _createID(Trigger triggerType) internal view returns (uint256) { + bytes1 empty; + IChainModule chainModule = s_hotVars.chainModule; + bytes memory idBytes = abi.encodePacked( + keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) + ); + for (uint256 idx = 4; idx < 15; idx++) { + idBytes[idx] = empty; + } + idBytes[15] = bytes1(uint8(triggerType)); + return uint256(bytes32(idBytes)); + } + + /** + * @dev retrieves feed data for fast gas/native and link/native prices. if the feed + * data is stale it uses the configured fallback price. Once a price is picked + * for gas it takes the min of gas price in the transaction or the fast gas + * price in order to reduce costs for the upkeep clients. + */ + function _getFeedData( + HotVars memory hotVars + ) internal view returns (uint256 gasWei, uint256 linkUSD, uint256 nativeUSD) { + uint32 stalenessSeconds = hotVars.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 feedValue; + (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + gasWei = s_fallbackGasPrice; + } else { + gasWei = uint256(feedValue); + } + (, feedValue, , timestamp, ) = i_linkUSDFeed.latestRoundData(); + if ( + feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) + ) { + linkUSD = s_fallbackLinkPrice; + } else { + linkUSD = uint256(feedValue); + } + return (gasWei, linkUSD, _getNativeUSD(hotVars)); + } + + /** + * @dev this price has it's own getter for use in the transmit() hot path + * in the future, all price data should be included in the report instead of + * getting read during execution + */ + function _getNativeUSD(HotVars memory hotVars) internal view returns (uint256) { + (, int256 feedValue, , uint256 timestamp, ) = i_nativeUSDFeed.latestRoundData(); + if ( + feedValue <= 0 || + block.timestamp < timestamp || + (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) + ) { + return s_fallbackNativePrice; + } else { + return uint256(feedValue); + } + } + + /** + * @dev gets the price and billing params for a specific billing token + */ + function _getBillingTokenPaymentParams( + HotVars memory hotVars, + IERC20 billingToken + ) internal view returns (BillingTokenPaymentParams memory paymentParams) { + BillingConfig storage config = s_billingConfigs[billingToken]; + paymentParams.flatFeeMilliCents = config.flatFeeMilliCents; + paymentParams.gasFeePPB = config.gasFeePPB; + paymentParams.decimals = config.decimals; + (, int256 feedValue, , uint256 timestamp, ) = config.priceFeed.latestRoundData(); + if ( + feedValue <= 0 || + block.timestamp < timestamp || + (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) + ) { + paymentParams.priceUSD = config.fallbackPrice; + } else { + paymentParams.priceUSD = uint256(feedValue); + } + return paymentParams; + } + + /** + * @param hotVars the hot path variables + * @param paymentParams the pricing data and gas usage data + * @return receipt the receipt of payment with pricing breakdown + * @dev use of PaymentParams struct is necessary to avoid stack too deep errors + * @dev calculates LINK paid for gas spent plus a configure premium percentage + * @dev 1 USD = 1e18 attoUSD + * @dev 1 USD = 1e26 hexaicosaUSD (had to borrow this prefix from geometry because there is no metric prefix for 1e-26) + * @dev 1 millicent = 1e-5 USD = 1e13 attoUSD + */ + function _calculatePaymentAmount( + HotVars memory hotVars, + PaymentParams memory paymentParams + ) internal view returns (PaymentReceipt memory receipt) { + uint256 decimals = paymentParams.billingTokenParams.decimals; + uint256 gasWei = paymentParams.fastGasWei * hotVars.gasCeilingMultiplier; + // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier + if (paymentParams.isTransaction && tx.gasprice < gasWei) { + gasWei = tx.gasprice; + } + + // scaling factor is based on decimals of billing token, and applies to premium and gasCharge + uint256 numeratorScalingFactor = decimals > 18 ? 10 ** (decimals - 18) : 1; + uint256 denominatorScalingFactor = decimals < 18 ? 10 ** (18 - decimals) : 1; + + // gas calculation + uint256 gasPaymentHexaicosaUSD = (gasWei * + (paymentParams.gasLimit + paymentParams.gasOverhead) + + paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed + // gasChargeInBillingToken is scaled by the billing token's decimals. Round up to ensure a minimum billing token is charged for gas + receipt.gasChargeInBillingToken = SafeCast.toUint96( + ((gasPaymentHexaicosaUSD * numeratorScalingFactor) + + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); + // 18 decimals: 26 decimals / 8 decimals + receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); + + // premium calculation + uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD + uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) * + paymentParams.billingTokenParams.gasFeePPB * + paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; + // premium is scaled by the billing token's decimals. Round up to ensure at least minimum charge + receipt.premiumInBillingToken = SafeCast.toUint96( + ((premiumHexaicosaUSD * numeratorScalingFactor) + + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); + receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); + + receipt.billingToken = paymentParams.billingToken; + receipt.linkUSD = SafeCast.toUint96(paymentParams.linkUSD); + receipt.nativeUSD = SafeCast.toUint96(paymentParams.nativeUSD); + receipt.billingUSD = SafeCast.toUint96(paymentParams.billingTokenParams.priceUSD); + + return receipt; + } + + /** + * @dev calculates the max payment for an upkeep. Called during checkUpkeep simulation and assumes + * maximum gas overhead, L1 fee + */ + function _getMaxPayment( + uint256 upkeepId, + HotVars memory hotVars, + Trigger triggerType, + uint32 performGas, + uint256 fastGasWei, + uint256 linkUSD, + uint256 nativeUSD, + IERC20 billingToken + ) internal view returns (uint96) { + uint256 maxGasOverhead; + + { + if (triggerType == Trigger.CONDITION) { + maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; + } else if (triggerType == Trigger.LOG) { + maxGasOverhead = REGISTRY_LOG_OVERHEAD; + } else { + revert InvalidTriggerType(); + } + (uint256 chainModuleFixedOverhead, ) = s_hotVars.chainModule.getGasOverhead(); + maxGasOverhead += (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + chainModuleFixedOverhead; + } + + BillingTokenPaymentParams memory paymentParams = _getBillingTokenPaymentParams(hotVars, billingToken); + if (s_upkeep[upkeepId].overridesEnabled) { + BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; + // use the overridden configs + paymentParams.gasFeePPB = billingOverrides.gasFeePPB; + paymentParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; + } + + PaymentReceipt memory receipt = _calculatePaymentAmount( + hotVars, + PaymentParams({ + gasLimit: performGas, + gasOverhead: maxGasOverhead, + l1CostWei: 0, + fastGasWei: fastGasWei, + linkUSD: linkUSD, + nativeUSD: nativeUSD, + billingToken: billingToken, + billingTokenParams: paymentParams, + isTransaction: false + }) + ); + + return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; + } + + /** + * @dev move a transmitter's balance from total pool to withdrawable balance + */ + function _updateTransmitterBalanceFromPool( + address transmitterAddress, + uint96 totalPremium, + uint96 payeeCount + ) internal returns (uint96) { + Transmitter memory transmitter = s_transmitters[transmitterAddress]; + + if (transmitter.active) { + uint96 uncollected = totalPremium - transmitter.lastCollected; + uint96 due = uncollected / payeeCount; + transmitter.balance += due; + transmitter.lastCollected += due * payeeCount; + s_transmitters[transmitterAddress] = transmitter; + } + + return transmitter.balance; + } + + /** + * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) + */ + function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { + bytes32 rawID = bytes32(upkeepId); + bytes1 empty = bytes1(0); + for (uint256 idx = 4; idx < 15; idx++) { + if (rawID[idx] != empty) { + // old IDs that were created before this standard and migrated to this registry + return Trigger.CONDITION; + } + } + return Trigger(uint8(rawID[15])); + } + + function _checkPayload( + uint256 upkeepId, + Trigger triggerType, + bytes memory triggerData + ) internal view returns (bytes memory) { + if (triggerType == Trigger.CONDITION) { + return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); + } else if (triggerType == Trigger.LOG) { + Log memory log = abi.decode(triggerData, (Log)); + return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); + } + revert InvalidTriggerType(); + } + + /** + * @dev _decodeReport decodes a serialized report into a Report struct + */ + function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { + Report memory report = abi.decode(rawReport, (Report)); + uint256 expectedLength = report.upkeepIds.length; + if ( + report.gasLimits.length != expectedLength || + report.triggers.length != expectedLength || + report.performDatas.length != expectedLength + ) { + revert InvalidReport(); + } + return report; + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + * @return bool whether the upkeep should be performed + * @return bytes32 dedupID for preventing duplicate performances of this trigger + */ + function _prePerformChecks( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + bytes32 dedupID; + if (transmitInfo.triggerType == Trigger.CONDITION) { + if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) + return (false, dedupID); + } else if (transmitInfo.triggerType == Trigger.LOG) { + bool valid; + (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); + if (!valid) return (false, dedupID); + } else { + revert InvalidTriggerType(); + } + if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { + // Can happen when an upkeep got cancelled after report was generated. + // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice + emit CancelledUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Does some early sanity checks before actually performing an upkeep + */ + function _validateConditionalTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + UpkeepTransmitInfo memory transmitInfo, + HotVars memory hotVars + ) internal returns (bool) { + ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); + if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { + // Can happen when another report performed this upkeep after this report was generated + emit StaleUpkeepReport(upkeepId, rawTrigger); + return false; + } + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // There are two cases of reorged report + // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain + // which is always protected against + // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is + // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain + // when it is sent + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return false; + } + return true; + } + + function _validateLogTrigger( + uint256 upkeepId, + uint256 blocknumber, + bytes memory rawTrigger, + HotVars memory hotVars + ) internal returns (bool, bytes32) { + LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); + bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); + if ( + (hotVars.reorgProtectionEnabled && + (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || + trigger.blockNum >= blocknumber + ) { + // Reorg protection is same as conditional trigger upkeeps + emit ReorgedUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + if (s_dedupKeys[dedupID]) { + emit StaleUpkeepReport(upkeepId, rawTrigger); + return (false, dedupID); + } + return (true, dedupID); + } + + /** + * @dev Verify signatures attached to report + */ + function _verifyReportSignature( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) internal view { + bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount = 0; + + Signer memory signer; + address signerAddress; + for (uint256 i = 0; i < rs.length; i++) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + signer = s_signers[signerAddress]; + if (!signer.active) revert OnlyActiveSigners(); + unchecked { + signedCount += 1 << (8 * signer.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); + } + + /** + * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances + * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID + */ + function _updateTriggerMarker( + uint256 upkeepID, + uint256 blocknumber, + UpkeepTransmitInfo memory upkeepTransmitInfo + ) internal { + if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { + s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); + } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { + s_dedupKeys[upkeepTransmitInfo.dedupID] = true; + emit DedupKeyAdded(upkeepTransmitInfo.dedupID); + } + } + + /** + * @dev calls the Upkeep target with the performData param passed in by the + * transmitter and the exact gas required by the Upkeep + */ + function _performUpkeep( + IAutomationForwarder forwarder, + uint256 performGas, + bytes memory performData + ) internal nonReentrant returns (bool success, uint256 gasUsed) { + performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); + return forwarder.forward(performGas, performData); + } + + /** + * @dev handles the payment processing after an upkeep has been performed. + * Deducts an upkeep's balance and increases the amount spent. + */ + function _handlePayment( + HotVars memory hotVars, + PaymentParams memory paymentParams, + uint256 upkeepId, + Upkeep memory upkeep + ) internal returns (PaymentReceipt memory) { + if (upkeep.overridesEnabled) { + BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; + // use the overridden configs + paymentParams.billingTokenParams.gasFeePPB = billingOverrides.gasFeePPB; + paymentParams.billingTokenParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; + } + + PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); + + // balance is in the token's native decimals + uint96 balance = upkeep.balance; + // payment is in the token's native decimals + uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; + + // scaling factors to adjust decimals between billing token and LINK + uint256 decimals = paymentParams.billingTokenParams.decimals; + uint256 scalingFactor1 = decimals < 18 ? 10 ** (18 - decimals) : 1; + uint256 scalingFactor2 = decimals > 18 ? 10 ** (decimals - 18) : 1; + + // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user + // can't cover the amount owed + if (balance < receipt.gasChargeInBillingToken) { + // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON + payment = balance; + receipt.gasReimbursementInJuels = SafeCast.toUint96( + (balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / + (paymentParams.linkUSD * scalingFactor2) + ); + receipt.premiumInJuels = 0; + receipt.premiumInBillingToken = 0; + receipt.gasChargeInBillingToken = balance; + } else if (balance < payment) { + // if the user can cover the gas fee, but not the premium, then reduce the premium + payment = balance; + receipt.premiumInJuels = SafeCast.toUint96( + ((balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / + (paymentParams.linkUSD * scalingFactor2)) - receipt.gasReimbursementInJuels + ); + // round up + receipt.premiumInBillingToken = SafeCast.toUint96( + ((receipt.premiumInJuels * paymentParams.linkUSD * scalingFactor2) + + (paymentParams.billingTokenParams.priceUSD * scalingFactor1 - 1)) / + (paymentParams.billingTokenParams.priceUSD * scalingFactor1) + ); + } + + s_upkeep[upkeepId].balance -= payment; + s_upkeep[upkeepId].amountSpent += payment; + s_reserveAmounts[paymentParams.billingToken] -= payment; + + emit UpkeepCharged(upkeepId, receipt); + return receipt; + } + + /** + * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin + */ + function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { + if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); + if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + } + + /** + * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage + */ + modifier nonReentrant() { + if (s_hotVars.reentrancyGuard) revert ReentrantCall(); + s_hotVars.reentrancyGuard = true; + _; + s_hotVars.reentrancyGuard = false; + } + + /** + * @notice only allows a pre-configured address to initiate offchain read + */ + function _preventExecution() internal view { + // solhint-disable-next-line avoid-tx-origin + if (tx.origin != i_allowedReadOnlyAddress) { + revert OnlySimulatedBackend(); + } + } + + /** + * @notice only allows finance admin to call the function + */ + function _onlyFinanceAdminAllowed() internal view { + if (msg.sender != s_storage.financeAdmin) { + revert OnlyFinanceAdmin(); + } + } + + /** + * @notice only allows privilege manager to call the function + */ + function _onlyPrivilegeManagerAllowed() internal view { + if (msg.sender != s_storage.upkeepPrivilegeManager) { + revert OnlyCallableByUpkeepPrivilegeManager(); + } + } + + /** + * @notice sets billing configuration for a token + * @param billingTokens the addresses of tokens + * @param billingConfigs the configs for tokens + */ + function _setBillingConfig(IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) internal { + // Clear existing data + for (uint256 i = 0; i < s_billingTokens.length; i++) { + delete s_billingConfigs[s_billingTokens[i]]; + } + delete s_billingTokens; + + PayoutMode mode = s_payoutMode; + for (uint256 i = 0; i < billingTokens.length; i++) { + IERC20 token = billingTokens[i]; + BillingConfig memory config = billingConfigs[i]; + + // most ERC20 tokens are 18 decimals, priceFeed must be 8 decimals + if (config.decimals != token.decimals() || config.priceFeed.decimals() != 8) { + revert InvalidToken(); + } + + // if LINK is a billing option, payout mode must be ON_CHAIN + if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { + revert InvalidToken(); + } + if (address(token) == ZERO_ADDRESS || address(config.priceFeed) == ZERO_ADDRESS) { + revert ZeroAddressNotAllowed(); + } + + // if this is a new token, add it to tokens list. Otherwise revert + if (address(s_billingConfigs[token].priceFeed) != ZERO_ADDRESS) { + revert DuplicateEntry(); + } + s_billingTokens.push(token); + + // update the billing config for an existing token or add a new one + s_billingConfigs[token] = config; + + emit BillingConfigSet(token, config); + } + } + + /** + * @notice updates the signers and transmitters lists + */ + function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { + uint96 transmittersListLength = uint96(s_transmittersList.length); + uint96 totalPremium = s_hotVars.totalPremium; + + // move all pooled payments out of the pool to each transmitter's balance + for (uint256 i = 0; i < s_transmittersList.length; i++) { + _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); + } + + // remove any old signer/transmitter addresses + address transmitterAddress; + PayoutMode mode = s_payoutMode; + for (uint256 i = 0; i < s_transmittersList.length; i++) { + transmitterAddress = s_transmittersList[i]; + delete s_signers[s_signersList[i]]; + // Do not delete the whole transmitter struct as it has balance information stored + s_transmitters[transmitterAddress].active = false; + if (mode == PayoutMode.OFF_CHAIN && s_transmitters[transmitterAddress].balance > 0) { + s_deactivatedTransmitters.add(transmitterAddress); + } + } + delete s_signersList; + delete s_transmittersList; + + // add new signer/transmitter addresses + Transmitter memory transmitter; + for (uint256 i = 0; i < signers.length; i++) { + if (s_signers[signers[i]].active) revert RepeatedSigner(); + if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); + s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); + + transmitterAddress = transmitters[i]; + if (transmitterAddress == ZERO_ADDRESS) revert InvalidTransmitter(); + transmitter = s_transmitters[transmitterAddress]; + if (transmitter.active) revert RepeatedTransmitter(); + transmitter.active = true; + transmitter.index = uint8(i); + // new transmitters start afresh from current totalPremium + // some spare change of premium from previous pool will be forfeited + transmitter.lastCollected = s_hotVars.totalPremium; + s_transmitters[transmitterAddress] = transmitter; + if (mode == PayoutMode.OFF_CHAIN) { + s_deactivatedTransmitters.remove(transmitterAddress); + } + } + + s_signersList = signers; + s_transmittersList = transmitters; + } + + /** + * @notice returns the size of the LINK liquidity pool + # @dev LINK max supply < 2^96, so casting to int256 is safe + */ + function _linkAvailableForPayment() internal view returns (int256) { + return int256(i_link.balanceOf(address(this))) - int256(s_reserveAmounts[IERC20(address(i_link))]); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol new file mode 100644 index 0000000..64d697c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; +import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; +import {ZKSyncAutomationRegistryLogicB2_3} from "./ZKSyncAutomationRegistryLogicB2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {ZKSyncAutomationForwarder} from "../ZKSyncAutomationForwarder.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; +import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @notice Logic contract, works in tandem with AutomationRegistry as a proxy + */ +contract ZKSyncAutomationRegistryLogicA2_3 is ZKSyncAutomationRegistryBase2_3, Chainable, IERC677Receiver { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + using SafeERC20 for IERC20; + + /** + * @param logicB the address of the second logic contract + * @dev we cast the contract to logicC in order to call logicC functions (via fallback) + */ + constructor( + ZKSyncAutomationRegistryLogicB2_3 logicB + ) + ZKSyncAutomationRegistryBase2_3( + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getLinkAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getLinkUSDFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getNativeUSDFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getFastGasFeedAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getAutomationForwarderLogic(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getAllowedReadOnlyAddress(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getPayoutMode(), + ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getWrappedNativeTokenAddress() + ) + Chainable(address(logicB)) + {} + + /** + * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep + * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX + * @param sender the account which transferred the funds + * @param amount number of LINK transfer + */ + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { + if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); + if (data.length != 32) revert InvalidDataLength(); + uint256 id = abi.decode(data, (uint256)); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken(); + s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); + s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount; + emit FundsAdded(id, sender, uint96(amount)); + } + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice adds a new upkeep + * @param target address to perform upkeep on + * @param gasLimit amount of gas to provide the target contract when + * performing upkeep + * @param admin address to cancel upkeep and withdraw remaining funds + * @param triggerType the trigger for the upkeep + * @param billingToken the billing token for the upkeep + * @param checkData data passed to the contract when checking for upkeep + * @param triggerConfig the config for the trigger + * @param offchainConfig arbitrary offchain config for the upkeep + */ + function registerUpkeep( + address target, + uint32 gasLimit, + address admin, + Trigger triggerType, + IERC20 billingToken, + bytes calldata checkData, + bytes memory triggerConfig, + bytes memory offchainConfig + ) public returns (uint256 id) { + if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); + if (!target.isContract()) revert NotAContract(); + id = _createID(triggerType); + IAutomationForwarder forwarder = IAutomationForwarder( + address(new ZKSyncAutomationForwarder(target, address(this), i_automationForwarderLogic)) + ); + _createUpkeep( + id, + Upkeep({ + overridesEnabled: false, + performGas: gasLimit, + balance: 0, + maxValidBlocknumber: UINT32_MAX, + lastPerformedBlockNumber: 0, + amountSpent: 0, + paused: false, + forwarder: forwarder, + billingToken: billingToken + }), + admin, + checkData, + triggerConfig, + offchainConfig + ); + s_storage.nonce++; + emit UpkeepRegistered(id, gasLimit, admin); + emit UpkeepCheckDataSet(id, checkData); + emit UpkeepTriggerConfigSet(id, triggerConfig); + emit UpkeepOffchainConfigSet(id, offchainConfig); + return (id); + } + + /** + * @notice cancels an upkeep + * @param id the upkeepID to cancel + * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to + * allow any pending performUpkeep txs time to get confirmed + */ + function cancelUpkeep(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + bool isOwner = msg.sender == owner(); + uint96 minSpend = s_billingConfigs[upkeep.billingToken].minSpend; + + uint256 height = s_hotVars.chainModule.blockNumber(); + if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); + + if (!isOwner) { + height = height + CANCELLATION_DELAY; + } + s_upkeep[id].maxValidBlocknumber = uint32(height); + s_upkeepIDs.remove(id); + + // charge the cancellation fee if the minSpend is not met + uint96 cancellationFee = 0; + // cancellationFee is min(max(minSpend - amountSpent, 0), amountLeft) + if (upkeep.amountSpent < minSpend) { + cancellationFee = minSpend - uint96(upkeep.amountSpent); + if (cancellationFee > upkeep.balance) { + cancellationFee = upkeep.balance; + } + } + s_upkeep[id].balance = upkeep.balance - cancellationFee; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - cancellationFee; + + emit UpkeepCanceled(id, uint64(height)); + } + + /** + * @notice migrates upkeeps from one registry to another. + * @param ids the upkeepIDs to migrate + * @param destination the destination registry address + * @dev a transcoder must be set in order to enable migration + * @dev migration permissions must be set on *both* sending and receiving registries + * @dev only an upkeep admin can migrate their upkeeps + * @dev this function is most gas-efficient if upkeepIDs are sorted by billing token + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not migrated in this function + */ + function migrateUpkeeps(uint256[] calldata ids, address destination) external { + if ( + s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && + s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); + if (ids.length == 0) revert ArrayHasNoEntries(); + + IERC20 billingToken; + uint256 balanceToTransfer; + uint256 id; + Upkeep memory upkeep; + address[] memory admins = new address[](ids.length); + Upkeep[] memory upkeeps = new Upkeep[](ids.length); + bytes[] memory checkDatas = new bytes[](ids.length); + bytes[] memory triggerConfigs = new bytes[](ids.length); + bytes[] memory offchainConfigs = new bytes[](ids.length); + + for (uint256 idx = 0; idx < ids.length; idx++) { + id = ids[idx]; + upkeep = s_upkeep[id]; + + if (idx == 0) { + billingToken = upkeep.billingToken; + balanceToTransfer = upkeep.balance; + } + + // if we encounter a new billing token, send the sum from the last billing token to the destination registry + if (upkeep.billingToken != billingToken) { + s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; + billingToken.safeTransfer(destination, balanceToTransfer); + billingToken = upkeep.billingToken; + balanceToTransfer = upkeep.balance; + } else if (idx != 0) { + balanceToTransfer += upkeep.balance; + } + + _requireAdminAndNotCancelled(id); + upkeep.forwarder.updateRegistry(destination); + + upkeeps[idx] = upkeep; + admins[idx] = s_upkeepAdmin[id]; + checkDatas[idx] = s_checkData[id]; + triggerConfigs[idx] = s_upkeepTriggerConfig[id]; + offchainConfigs[idx] = s_upkeepOffchainConfig[id]; + delete s_upkeep[id]; + delete s_checkData[id]; + delete s_upkeepTriggerConfig[id]; + delete s_upkeepOffchainConfig[id]; + // nullify existing proposed admin change if an upkeep is being migrated + delete s_proposedAdmin[id]; + delete s_upkeepAdmin[id]; + s_upkeepIDs.remove(id); + emit UpkeepMigrated(id, upkeep.balance, destination); + } + // always transfer the rolling sum in the end + s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; + billingToken.safeTransfer(destination, balanceToTransfer); + + bytes memory encodedUpkeeps = abi.encode( + ids, + upkeeps, + new address[](ids.length), + admins, + checkDatas, + triggerConfigs, + offchainConfigs + ); + MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( + UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( + UPKEEP_VERSION_BASE, + MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), + encodedUpkeeps + ) + ); + } + + /** + * @notice received upkeeps migrated from another registry + * @param encodedUpkeeps the raw upkeep data to import + * @dev this function is never called directly, it is only called by another registry's migrate function + * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not handled in this function + */ + function receiveUpkeeps(bytes calldata encodedUpkeeps) external { + if ( + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && + s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL + ) revert MigrationNotPermitted(); + ( + uint256[] memory ids, + Upkeep[] memory upkeeps, + address[] memory targets, + address[] memory upkeepAdmins, + bytes[] memory checkDatas, + bytes[] memory triggerConfigs, + bytes[] memory offchainConfigs + ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); + for (uint256 idx = 0; idx < ids.length; idx++) { + if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { + upkeeps[idx].forwarder = IAutomationForwarder( + address(new ZKSyncAutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) + ); + } + _createUpkeep( + ids[idx], + upkeeps[idx], + upkeepAdmins[idx], + checkDatas[idx], + triggerConfigs[idx], + offchainConfigs[idx] + ); + emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol new file mode 100644 index 0000000..55af99f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; +import {Chainable} from "../Chainable.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +contract ZKSyncAutomationRegistryLogicB2_3 is ZKSyncAutomationRegistryBase2_3, Chainable { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + using SafeERC20 for IERC20; + + /** + * @param logicC the address of the third logic contract + */ + constructor( + ZKSyncAutomationRegistryLogicC2_3 logicC + ) + ZKSyncAutomationRegistryBase2_3( + logicC.getLinkAddress(), + logicC.getLinkUSDFeedAddress(), + logicC.getNativeUSDFeedAddress(), + logicC.getFastGasFeedAddress(), + logicC.getAutomationForwarderLogic(), + logicC.getAllowedReadOnlyAddress(), + logicC.getPayoutMode(), + logicC.getWrappedNativeTokenAddress() + ) + Chainable(address(logicC)) + {} + + // ================================================================ + // | PIPELINE FUNCTIONS | + // ================================================================ + + /** + * @notice called by the automation DON to check if work is needed + * @param id the upkeep ID to check for work needed + * @param triggerData extra contextual data about the trigger (not used in all code paths) + * @dev this one of the core functions called in the hot path + * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility + * @dev there is an incongruency on what gets returned during failure modes + * ex sometimes we include price data, sometimes we omit it depending on the failure + */ + function checkUpkeep( + uint256 id, + bytes memory triggerData + ) + public + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ) + { + _preventExecution(); + + Trigger triggerType = _getTriggerType(id); + HotVars memory hotVars = s_hotVars; + Upkeep memory upkeep = s_upkeep[id]; + + { + uint256 nativeUSD; + uint96 maxPayment; + if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); + if (upkeep.maxValidBlocknumber != UINT32_MAX) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); + if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); + (fastGasWei, linkUSD, nativeUSD) = _getFeedData(hotVars); + maxPayment = _getMaxPayment( + id, + hotVars, + triggerType, + upkeep.performGas, + fastGasWei, + linkUSD, + nativeUSD, + upkeep.billingToken + ); + if (upkeep.balance < maxPayment) { + return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); + } + } + + bytes memory callData = _checkPayload(id, triggerType, triggerData); + + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); + gasUsed = gasUsed - gasleft(); + + if (!success) { + // User's target check reverted. We capture the revert data here and pass it within performData + if (result.length > s_storage.maxRevertDataSize) { + return ( + false, + bytes(""), + UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + } + return ( + upkeepNeeded, + result, + UpkeepFailureReason.TARGET_CHECK_REVERTED, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + } + + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, upkeep.performGas, fastGasWei, linkUSD); + + if (performData.length > s_storage.maxPerformDataSize) + return ( + false, + bytes(""), + UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, + gasUsed, + upkeep.performGas, + fastGasWei, + linkUSD + ); + + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkUSD); + } + + /** + * @notice see other checkUpkeep function for description + * @dev this function may be deprecated in a future version of chainlink automation + */ + function checkUpkeep( + uint256 id + ) + external + returns ( + bool upkeepNeeded, + bytes memory performData, + UpkeepFailureReason upkeepFailureReason, + uint256 gasUsed, + uint256 gasLimit, + uint256 fastGasWei, + uint256 linkUSD + ) + { + return checkUpkeep(id, bytes("")); + } + + /** + * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) + * @param id the upkeepID to execute a callback for + * @param values the values returned from the data streams lookup + * @param extraData the user-provided extra context data + */ + function checkCallback( + uint256 id, + bytes[] memory values, + bytes calldata extraData + ) + external + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); + return executeCallback(id, payload); + } + + /** + * @notice this is a generic callback executor that forwards a call to a user's contract with the configured + * gas limit + * @param id the upkeepID to execute a callback for + * @param payload the data (including function selector) to call on the upkeep target contract + */ + function executeCallback( + uint256 id, + bytes memory payload + ) + public + returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) + { + _preventExecution(); + + Upkeep memory upkeep = s_upkeep[id]; + gasUsed = gasleft(); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); + gasUsed = gasUsed - gasleft(); + if (!success) { + return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); + } + (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); + if (!upkeepNeeded) { + return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); + } + if (performData.length > s_storage.maxPerformDataSize) { + return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); + } + return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); + } + + /** + * @notice simulates the upkeep with the perform data returned from checkUpkeep + * @param id identifier of the upkeep to execute the data with. + * @param performData calldata parameter to be passed to the target upkeep. + * @return success whether the call reverted or not + * @return gasUsed the amount of gas the target contract consumed + */ + function simulatePerformUpkeep( + uint256 id, + bytes calldata performData + ) external returns (bool success, uint256 gasUsed) { + _preventExecution(); + + if (s_hotVars.paused) revert RegistryPaused(); + Upkeep memory upkeep = s_upkeep[id]; + (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); + return (success, gasUsed); + } + + // ================================================================ + // | UPKEEP MANAGEMENT | + // ================================================================ + + /** + * @notice adds fund to an upkeep + * @param id the upkeepID + * @param amount the amount of funds to add, in the upkeep's billing token + */ + function addFunds(uint256 id, uint96 amount) external payable { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + if (msg.value != 0) { + if (upkeep.billingToken != IERC20(i_wrappedNativeToken)) { + revert InvalidToken(); + } + amount = SafeCast.toUint96(msg.value); + } + + s_upkeep[id].balance = upkeep.balance + amount; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + amount; + + if (msg.value == 0) { + // ERC20 payment + upkeep.billingToken.safeTransferFrom(msg.sender, address(this), amount); + } else { + // native payment + i_wrappedNativeToken.deposit{value: amount}(); + } + + emit FundsAdded(id, msg.sender, amount); + } + + /** + * @notice overrides the billing config for an upkeep + * @param id the upkeepID + * @param billingOverrides the override-able billing config + */ + function setBillingOverrides(uint256 id, BillingOverrides calldata billingOverrides) external { + _onlyPrivilegeManagerAllowed(); + if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + + s_upkeep[id].overridesEnabled = true; + s_billingOverrides[id] = billingOverrides; + emit BillingConfigOverridden(id, billingOverrides); + } + + /** + * @notice remove the overridden billing config for an upkeep + * @param id the upkeepID + */ + function removeBillingOverrides(uint256 id) external { + _onlyPrivilegeManagerAllowed(); + + s_upkeep[id].overridesEnabled = false; + delete s_billingOverrides[id]; + emit BillingConfigOverrideRemoved(id); + } + + /** + * @notice transfers the address of an admin for an upkeep + */ + function transferUpkeepAdmin(uint256 id, address proposed) external { + _requireAdminAndNotCancelled(id); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedAdmin[id] != proposed) { + s_proposedAdmin[id] = proposed; + emit UpkeepAdminTransferRequested(id, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of an upkeep admin + */ + function acceptUpkeepAdmin(uint256 id) external { + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); + if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); + address past = s_upkeepAdmin[id]; + s_upkeepAdmin[id] = msg.sender; + s_proposedAdmin[id] = ZERO_ADDRESS; + + emit UpkeepAdminTransferred(id, past, msg.sender); + } + + /** + * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused + */ + function pauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (upkeep.paused) revert OnlyUnpausedUpkeep(); + s_upkeep[id].paused = true; + s_upkeepIDs.remove(id); + emit UpkeepPaused(id); + } + + /** + * @notice unpauses an upkeep + */ + function unpauseUpkeep(uint256 id) external { + _requireAdminAndNotCancelled(id); + Upkeep memory upkeep = s_upkeep[id]; + if (!upkeep.paused) revert OnlyPausedUpkeep(); + s_upkeep[id].paused = false; + s_upkeepIDs.add(id); + emit UpkeepUnpaused(id); + } + + /** + * @notice updates the checkData for an upkeep + */ + function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { + _requireAdminAndNotCancelled(id); + if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); + s_checkData[id] = newCheckData; + emit UpkeepCheckDataSet(id, newCheckData); + } + + /** + * @notice updates the gas limit for an upkeep + */ + function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { + if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); + _requireAdminAndNotCancelled(id); + s_upkeep[id].performGas = gasLimit; + + emit UpkeepGasLimitSet(id, gasLimit); + } + + /** + * @notice updates the offchain config for an upkeep + */ + function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { + _requireAdminAndNotCancelled(id); + s_upkeepOffchainConfig[id] = config; + emit UpkeepOffchainConfigSet(id, config); + } + + /** + * @notice sets the upkeep trigger config + * @param id the upkeepID to change the trigger for + * @param triggerConfig the new trigger config + */ + function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { + _requireAdminAndNotCancelled(id); + s_upkeepTriggerConfig[id] = triggerConfig; + emit UpkeepTriggerConfigSet(id, triggerConfig); + } + + /** + * @notice withdraws an upkeep's funds from an upkeep + * @dev note that an upkeep must be cancelled first!! + */ + function withdrawFunds(uint256 id, address to) external nonReentrant { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + Upkeep memory upkeep = s_upkeep[id]; + if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); + if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); + uint96 amountToWithdraw = s_upkeep[id].balance; + s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - amountToWithdraw; + s_upkeep[id].balance = 0; + upkeep.billingToken.safeTransfer(to, amountToWithdraw); + emit FundsWithdrawn(id, amountToWithdraw, to); + } + + // ================================================================ + // | FINANCE ACTIONS | + // ================================================================ + + /** + * @notice withdraws excess LINK from the liquidity pool + * @param to the address to send the fees to + * @param amount the amount to withdraw + */ + function withdrawLink(address to, uint256 amount) external { + _onlyFinanceAdminAllowed(); + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + + int256 available = _linkAvailableForPayment(); + if (available < 0) { + revert InsufficientBalance(0, amount); + } else if (amount > uint256(available)) { + revert InsufficientBalance(uint256(available), amount); + } + + bool transferStatus = i_link.transfer(to, amount); + if (!transferStatus) { + revert TransferFailed(); + } + emit FeesWithdrawn(address(i_link), to, amount); + } + + /** + * @notice withdraws non-LINK fees earned by the contract + * @param asset the asset to withdraw + * @param to the address to send the fees to + * @param amount the amount to withdraw + * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity + * to cover all outstanding debts on the registry + */ + function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { + _onlyFinanceAdminAllowed(); + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (address(asset) == address(i_link)) revert InvalidToken(); + if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); + uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; + if (amount > available) revert InsufficientBalance(available, amount); + + asset.safeTransfer(to, amount); + emit FeesWithdrawn(address(asset), to, amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol new file mode 100644 index 0000000..3b4b023 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol @@ -0,0 +1,626 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; +import {IChainModule} from "../interfaces/IChainModule.sol"; +import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; + +contract ZKSyncAutomationRegistryLogicC2_3 is ZKSyncAutomationRegistryBase2_3 { + using Address for address; + using EnumerableSet for EnumerableSet.UintSet; + using EnumerableSet for EnumerableSet.AddressSet; + + /** + * @dev see AutomationRegistry master contract for constructor description + */ + constructor( + address link, + address linkUSDFeed, + address nativeUSDFeed, + address fastGasFeed, + address automationForwarderLogic, + address allowedReadOnlyAddress, + PayoutMode payoutMode, + address wrappedNativeTokenAddress + ) + ZKSyncAutomationRegistryBase2_3( + link, + linkUSDFeed, + nativeUSDFeed, + fastGasFeed, + automationForwarderLogic, + allowedReadOnlyAddress, + payoutMode, + wrappedNativeTokenAddress + ) + {} + + // ================================================================ + // | NODE ACTIONS | + // ================================================================ + + /** + * @notice transfers the address of payee for a transmitter + */ + function transferPayeeship(address transmitter, address proposed) external { + if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); + if (proposed == msg.sender) revert ValueNotChanged(); + + if (s_proposedPayee[transmitter] != proposed) { + s_proposedPayee[transmitter] = proposed; + emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); + } + } + + /** + * @notice accepts the transfer of the payee + */ + function acceptPayeeship(address transmitter) external { + if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); + address past = s_transmitterPayees[transmitter]; + s_transmitterPayees[transmitter] = msg.sender; + s_proposedPayee[transmitter] = ZERO_ADDRESS; + + emit PayeeshipTransferred(transmitter, past, msg.sender); + } + + /** + * @notice this is for NOPs to withdraw LINK received as payment for work performed + */ + function withdrawPayment(address from, address to) external { + if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (s_payoutMode == PayoutMode.OFF_CHAIN) revert MustSettleOffchain(); + if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); + uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); + s_transmitters[from].balance = 0; + s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] - balance; + bool transferStatus = i_link.transfer(to, balance); + if (!transferStatus) { + revert TransferFailed(); + } + emit PaymentWithdrawn(from, balance, to, msg.sender); + } + + // ================================================================ + // | OWNER / MANAGER ACTIONS | + // ================================================================ + + /** + * @notice sets the privilege config for an upkeep + */ + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { + _onlyPrivilegeManagerAllowed(); + s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; + emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); + } + + /** + * @notice this is used by the owner to set the initial payees for newly added transmitters. The owner is not allowed to change payees for existing transmitters. + * @dev the IGNORE_ADDRESS is a "helper" that makes it easier to construct a list of payees when you only care about setting the payee for a small number of transmitters. + */ + function setPayees(address[] calldata payees) external onlyOwner { + if (s_transmittersList.length != payees.length) revert ParameterLengthError(); + for (uint256 i = 0; i < s_transmittersList.length; i++) { + address transmitter = s_transmittersList[i]; + address oldPayee = s_transmitterPayees[transmitter]; + address newPayee = payees[i]; + + if ( + (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) + ) { + revert InvalidPayee(); + } + + if (newPayee != IGNORE_ADDRESS) { + s_transmitterPayees[transmitter] = newPayee; + } + } + emit PayeesUpdated(s_transmittersList, payees); + } + + /** + * @notice sets the migration permission for a peer registry + * @dev this must be done before upkeeps can be migrated to/from another registry + */ + function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { + s_peerRegistryMigrationPermission[peer] = permission; + } + + /** + * @notice pauses the entire registry + */ + function pause() external onlyOwner { + s_hotVars.paused = true; + emit Paused(msg.sender); + } + + /** + * @notice unpauses the entire registry + */ + function unpause() external onlyOwner { + s_hotVars.paused = false; + emit Unpaused(msg.sender); + } + + /** + * @notice sets a generic bytes field used to indicate the privilege that this admin address had + * @param admin the address to set privilege for + * @param newPrivilegeConfig the privileges that this admin has + */ + function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { + _onlyPrivilegeManagerAllowed(); + s_adminPrivilegeConfig[admin] = newPrivilegeConfig; + emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); + } + + /** + * @notice settles NOPs' LINK payment offchain + */ + function settleNOPsOffchain() external { + _onlyFinanceAdminAllowed(); + if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); + + uint96 totalPremium = s_hotVars.totalPremium; + uint256 activeTransmittersLength = s_transmittersList.length; + uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); + uint256 length = activeTransmittersLength + deactivatedTransmittersLength; + uint256[] memory payments = new uint256[](length); + address[] memory payees = new address[](length); + + for (uint256 i = 0; i < activeTransmittersLength; i++) { + address transmitterAddr = s_transmittersList[i]; + uint96 balance = _updateTransmitterBalanceFromPool( + transmitterAddr, + totalPremium, + uint96(activeTransmittersLength) + ); + + payments[i] = balance; + payees[i] = s_transmitterPayees[transmitterAddr]; + s_transmitters[transmitterAddr].balance = 0; + } + + for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { + address deactivatedAddr = s_deactivatedTransmitters.at(i); + Transmitter memory transmitter = s_transmitters[deactivatedAddr]; + + payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; + payments[i + activeTransmittersLength] = transmitter.balance; + s_transmitters[deactivatedAddr].balance = 0; + } + + // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode + s_reserveAmounts[IERC20(address(i_link))] = 0; + + for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { + s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); + } + + emit NOPsSettledOffchain(payees, payments); + } + + /** + * @notice disables offchain payment for NOPs + */ + function disableOffchainPayments() external onlyOwner { + s_payoutMode = PayoutMode.ON_CHAIN; + } + + // ================================================================ + // | GETTERS | + // ================================================================ + + function getConditionalGasOverhead() external pure returns (uint256) { + return REGISTRY_CONDITIONAL_OVERHEAD; + } + + function getLogGasOverhead() external pure returns (uint256) { + return REGISTRY_LOG_OVERHEAD; + } + + function getPerSignerGasOverhead() external pure returns (uint256) { + return REGISTRY_PER_SIGNER_GAS_OVERHEAD; + } + + function getCancellationDelay() external pure returns (uint256) { + return CANCELLATION_DELAY; + } + + function getLinkAddress() external view returns (address) { + return address(i_link); + } + + function getLinkUSDFeedAddress() external view returns (address) { + return address(i_linkUSDFeed); + } + + function getNativeUSDFeedAddress() external view returns (address) { + return address(i_nativeUSDFeed); + } + + function getFastGasFeedAddress() external view returns (address) { + return address(i_fastGasFeed); + } + + function getAutomationForwarderLogic() external view returns (address) { + return i_automationForwarderLogic; + } + + function getAllowedReadOnlyAddress() external view returns (address) { + return i_allowedReadOnlyAddress; + } + + function getWrappedNativeTokenAddress() external view returns (address) { + return address(i_wrappedNativeToken); + } + + function getBillingToken(uint256 upkeepID) external view returns (IERC20) { + return s_upkeep[upkeepID].billingToken; + } + + function getBillingTokens() external view returns (IERC20[] memory) { + return s_billingTokens; + } + + function supportsBillingToken(IERC20 token) external view returns (bool) { + return address(s_billingConfigs[token].priceFeed) != address(0); + } + + function getBillingTokenConfig(IERC20 token) external view returns (BillingConfig memory) { + return s_billingConfigs[token]; + } + + function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool) { + return s_upkeep[upkeepID].overridesEnabled; + } + + function getPayoutMode() external view returns (PayoutMode) { + return s_payoutMode; + } + + function upkeepVersion() public pure returns (uint8) { + return UPKEEP_VERSION_BASE; + } + + /** + * @notice gets the number of upkeeps on the registry + */ + function getNumUpkeeps() external view returns (uint256) { + return s_upkeepIDs.length(); + } + + /** + * @notice read all of the details about an upkeep + * @dev this function may be deprecated in a future version of automation in favor of individual + * getters for each field + */ + function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { + Upkeep memory reg = s_upkeep[id]; + address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); + upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ + target: target, + performGas: reg.performGas, + checkData: s_checkData[id], + balance: reg.balance, + admin: s_upkeepAdmin[id], + maxValidBlocknumber: reg.maxValidBlocknumber, + lastPerformedBlockNumber: reg.lastPerformedBlockNumber, + amountSpent: uint96(reg.amountSpent), // force casting to uint96 for backwards compatibility. Not an issue if it overflows. + paused: reg.paused, + offchainConfig: s_upkeepOffchainConfig[id] + }); + return upkeepInfo; + } + + /** + * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. + * @param startIndex starting index in list + * @param maxCount max count to retrieve (0 = unlimited) + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { + uint256 numUpkeeps = s_upkeepIDs.length(); + if (startIndex >= numUpkeeps) revert IndexOutOfRange(); + uint256 endIndex = startIndex + maxCount; + endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; + uint256[] memory ids = new uint256[](endIndex - startIndex); + for (uint256 idx = 0; idx < ids.length; idx++) { + ids[idx] = s_upkeepIDs.at(idx + startIndex); + } + return ids; + } + + /** + * @notice returns the upkeep's trigger type + */ + function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { + return _getTriggerType(upkeepId); + } + + /** + * @notice returns the trigger config for an upkeeep + */ + function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { + return s_upkeepTriggerConfig[upkeepId]; + } + + /** + * @notice read the current info about any transmitter address + */ + function getTransmitterInfo( + address query + ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { + Transmitter memory transmitter = s_transmitters[query]; + + uint96 pooledShare = 0; + if (transmitter.active) { + uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; + pooledShare = totalDifference / uint96(s_transmittersList.length); + } + + return ( + transmitter.active, + transmitter.index, + (transmitter.balance + pooledShare), + transmitter.lastCollected, + s_transmitterPayees[query] + ); + } + + /** + * @notice read the current info about any signer address + */ + function getSignerInfo(address query) external view returns (bool active, uint8 index) { + Signer memory signer = s_signers[query]; + return (signer.active, signer.index); + } + + /** + * @notice read the current on-chain config of the registry + * @dev this function will change between versions, it should never be used where + * backwards compatibility matters! + */ + function getConfig() external view returns (OnchainConfig memory) { + return + OnchainConfig({ + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + fallbackNativePrice: s_fallbackNativePrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager, + chainModule: s_hotVars.chainModule, + reorgProtectionEnabled: s_hotVars.reorgProtectionEnabled, + financeAdmin: s_storage.financeAdmin + }); + } + + /** + * @notice read the current state of the registry + * @dev this function is deprecated + */ + function getState() + external + view + returns ( + IAutomationV21PlusCommon.StateLegacy memory state, + IAutomationV21PlusCommon.OnchainConfigLegacy memory config, + address[] memory signers, + address[] memory transmitters, + uint8 f + ) + { + state = IAutomationV21PlusCommon.StateLegacy({ + nonce: s_storage.nonce, + ownerLinkBalance: 0, // deprecated + expectedLinkBalance: 0, // deprecated + totalPremium: s_hotVars.totalPremium, + numUpkeeps: s_upkeepIDs.length(), + configCount: s_storage.configCount, + latestConfigBlockNumber: s_storage.latestConfigBlockNumber, + latestConfigDigest: s_latestConfigDigest, + latestEpoch: s_hotVars.latestEpoch, + paused: s_hotVars.paused + }); + + config = IAutomationV21PlusCommon.OnchainConfigLegacy({ + paymentPremiumPPB: 0, // deprecated + flatFeeMicroLink: 0, // deprecated + checkGasLimit: s_storage.checkGasLimit, + stalenessSeconds: s_hotVars.stalenessSeconds, + gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, + minUpkeepSpend: 0, // deprecated + maxPerformGas: s_storage.maxPerformGas, + maxCheckDataSize: s_storage.maxCheckDataSize, + maxPerformDataSize: s_storage.maxPerformDataSize, + maxRevertDataSize: s_storage.maxRevertDataSize, + fallbackGasPrice: s_fallbackGasPrice, + fallbackLinkPrice: s_fallbackLinkPrice, + transcoder: s_storage.transcoder, + registrars: s_registrars.values(), + upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager + }); + + return (state, config, s_signersList, s_transmittersList, s_hotVars.f); + } + + /** + * @notice read the Storage data + * @dev this function signature will change with each version of automation + * this should not be treated as a stable function + */ + function getStorage() external view returns (Storage memory) { + return s_storage; + } + + /** + * @notice read the HotVars data + * @dev this function signature will change with each version of automation + * this should not be treated as a stable function + */ + function getHotVars() external view returns (HotVars memory) { + return s_hotVars; + } + + /** + * @notice get the chain module + */ + function getChainModule() external view returns (IChainModule chainModule) { + return s_hotVars.chainModule; + } + + /** + * @notice if this registry has reorg protection enabled + */ + function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { + return s_hotVars.reorgProtectionEnabled; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getBalance(uint256 id) external view returns (uint96 balance) { + return s_upkeep[id].balance; + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + */ + function getMinBalance(uint256 id) external view returns (uint96) { + return getMinBalanceForUpkeep(id); + } + + /** + * @notice calculates the minimum balance required for an upkeep to remain eligible + * @param id the upkeep id to calculate minimum balance for + * @dev this will be deprecated in a future version in favor of getMinBalance + */ + function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { + Upkeep memory upkeep = s_upkeep[id]; + return getMaxPaymentForGas(id, _getTriggerType(id), upkeep.performGas, upkeep.billingToken); + } + + /** + * @notice calculates the maximum payment for a given gas limit + * @param gasLimit the gas to calculate payment for + */ + function getMaxPaymentForGas( + uint256 id, + Trigger triggerType, + uint32 gasLimit, + IERC20 billingToken + ) public view returns (uint96 maxPayment) { + HotVars memory hotVars = s_hotVars; + (uint256 fastGasWei, uint256 linkUSD, uint256 nativeUSD) = _getFeedData(hotVars); + return _getMaxPayment(id, hotVars, triggerType, gasLimit, fastGasWei, linkUSD, nativeUSD, billingToken); + } + + /** + * @notice retrieves the migration permission for a peer registry + */ + function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { + return s_peerRegistryMigrationPermission[peer]; + } + + /** + * @notice returns the upkeep privilege config + */ + function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { + return s_upkeepPrivilegeConfig[upkeepId]; + } + + /** + * @notice returns the admin's privilege config + */ + function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { + return s_adminPrivilegeConfig[admin]; + } + + /** + * @notice returns the upkeep's forwarder contract + */ + function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { + return s_upkeep[upkeepID].forwarder; + } + + /** + * @notice returns if the dedupKey exists or not + */ + function hasDedupKey(bytes32 dedupKey) external view returns (bool) { + return s_dedupKeys[dedupKey]; + } + + /** + * @notice returns the fallback native price + */ + function getFallbackNativePrice() external view returns (uint256) { + return s_fallbackNativePrice; + } + + /** + * @notice returns the amount of a particular token that is reserved as + * user deposits / NOP payments + */ + function getReserveAmount(IERC20 billingToken) external view returns (uint256) { + return s_reserveAmounts[billingToken]; + } + + /** + * @notice returns the amount of a particular token that is withdraw-able by finance admin + */ + function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { + return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; + } + + /** + * @notice returns the size of the LINK liquidity pool + */ + function linkAvailableForPayment() public view returns (int256) { + return _linkAvailableForPayment(); + } + + /** + * @notice returns the BillingOverrides config for a given upkeep + */ + function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { + return s_billingOverrides[upkeepID]; + } + + /** + * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc + */ + function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { + return s_billingConfigs[billingToken]; + } + + /** + * @notice returns all active transmitters with their associated payees + */ + function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { + uint256 transmitterCount = s_transmittersList.length; + TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); + + for (uint256 i = 0; i < transmitterCount; i++) { + address transmitterAddress = s_transmittersList[i]; + address payeeAddress = s_transmitterPayees[transmitterAddress]; + + transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); + } + + return transmitters; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol new file mode 100644 index 0000000..8ae10d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -0,0 +1,1020 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; +import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; + +import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; +import {AggregatorV3Interface} from "./../shared/interfaces/AggregatorV3Interface.sol"; +import {Client} from "./libraries/Client.sol"; +import {Internal} from "./libraries/Internal.sol"; +import {Pool} from "./libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; + +import {KeystoneFeedsPermissionHandler} from "../keystone/KeystoneFeedsPermissionHandler.sol"; +import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; +import {KeystoneFeedDefaultMetadataLib} from "../keystone/lib/KeystoneFeedDefaultMetadataLib.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice The FeeQuoter contract responsibility is to: +/// - Store the current gas price in USD for a given destination chain, +/// - Store the price of a token in USD allowing the owner or priceUpdater to update this value. +/// - Manage chain specific fee calculations. +/// The authorized callers in the contract represent the fee price updaters. +contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, KeystoneFeedsPermissionHandler { + using EnumerableSet for EnumerableSet.AddressSet; + using USDPriceWith18Decimals for uint224; + using KeystoneFeedDefaultMetadataLib for bytes; + + error TokenNotSupported(address token); + error FeeTokenNotSupported(address token); + error ChainNotSupported(uint64 chain); + error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed); + error StaleKeystoneUpdate(address token, uint256 feedTimestamp, uint256 storedTimeStamp); + error DataFeedValueOutOfUint224Range(); + error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); + error MessageGasLimitTooHigh(); + error DestinationChainNotEnabled(uint64 destChainSelector); + error ExtraArgOutOfOrderExecutionMustBeTrue(); + error InvalidExtraArgsTag(); + error SourceTokenDataTooLarge(address token); + error InvalidDestChainConfig(uint64 destChainSelector); + error MessageFeeTooHigh(uint256 msgFeeJuels, uint256 maxFeeJuelsPerMsg); + error InvalidStaticConfig(); + error MessageTooLarge(uint256 maxSize, uint256 actualSize); + error UnsupportedNumberOfTokens(); + + event FeeTokenAdded(address indexed feeToken); + event FeeTokenRemoved(address indexed feeToken); + event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp); + event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); + event PriceFeedPerTokenUpdated(address indexed token, TokenPriceFeedConfig priceFeedConfig); + event TokenTransferFeeConfigUpdated( + uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig + ); + event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); + event PremiumMultiplierWeiPerEthUpdated(address indexed token, uint64 premiumMultiplierWeiPerEth); + event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + + /// @dev Token price data feed configuration + struct TokenPriceFeedConfig { + address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) + uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents + } + + /// @dev Token price data feed update + struct TokenPriceFeedUpdate { + address sourceToken; // Source token to update feed for + TokenPriceFeedConfig feedConfig; // Feed config update data + } + + /// @dev Struct that contains the static configuration + /// RMN depends on this struct, if changing, please notify the RMN maintainers. + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message + address linkToken; // ────────╯ LINK token address + uint32 stalenessThreshold; // The amount of time a gas price can be stale before it is considered invalid. + } + + /// @dev The struct representing the received CCIP feed report from keystone IReceiver.onReport() + struct ReceivedCCIPFeedReport { + address token; // Token address + uint224 price; // ─────────╮ Price of the token in USD with 18 decimals + uint32 timestamp; // ──────╯ Timestamp of the price update + } + + /// @dev Struct to hold the fee & validation configs for a destination chain + struct DestChainConfig { + bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs + uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs + uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver + uint32 destDataAvailabilityOverheadGas; // │ Extra data availability gas charged on top of the message, e.g. for OCR + uint16 destGasPerDataAvailabilityByte; // │ Amount of gas to charge per byte of message data that needs availability + uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 + // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token + uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer + uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute the token transfer on the destination chain + uint32 defaultTxGasLimit; //─────────────────╮ Default gas limit for a tx + uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. + uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD + bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. + bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. + } + + /// @dev Struct to hold the configs and its destination chain selector + /// Same as DestChainConfig but with the destChainSelector so that an array of these + /// can be passed in the constructor and the applyDestChainConfigUpdates function + //solhint-disable gas-struct-packing + struct DestChainConfigArgs { + uint64 destChainSelector; // Destination chain selector + DestChainConfig destChainConfig; // Config to update for the chain selector + } + + /// @dev Struct to hold the transfer fee configuration for token transfers + struct TokenTransferFeeConfig { + uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD + uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD + uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 + uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain + // │ Extra data availability bytes that are returned from the source pool and sent + uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees + } + + /// @dev Struct to hold the token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token address included so + /// that an array of these can be passed in the TokenTransferFeeConfigArgs struct to set the mapping + struct TokenTransferFeeConfigSingleTokenArgs { + address token; // Token address + TokenTransferFeeConfig tokenTransferFeeConfig; // Struct to hold the transfer fee configuration for token transfers + } + + /// @dev Struct to hold the token transfer fee configurations for a destination chain and a set of tokens. Same as TokenTransferFeeConfigSingleTokenArgs + /// but with the destChainSelector and an array of TokenTransferFeeConfigSingleTokenArgs included so that an array of these can be passed in the constructor + /// and the applyTokenTransferFeeConfigUpdates function + struct TokenTransferFeeConfigArgs { + uint64 destChainSelector; // Destination chain selector + TokenTransferFeeConfigSingleTokenArgs[] tokenTransferFeeConfigs; // Array of token transfer fee configurations + } + + /// @dev Struct to hold a pair of destination chain selector and token address so that an array of these can be passed in the + /// applyTokenTransferFeeConfigUpdates function to remove the token transfer fee configuration for a token + struct TokenTransferFeeConfigRemoveArgs { + uint64 destChainSelector; // ─╮ Destination chain selector + address token; // ────────────╯ Token address + } + + /// @dev Struct to hold the fee token configuration for a token, same as the s_premiumMultiplierWeiPerEth but with + /// the token address included so that an array of these can be passed in the constructor and + /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping + struct PremiumMultiplierWeiPerEthArgs { + address token; // // ───────────────────╮ Token address + uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. + } + + /// @dev The base decimals for cost calculations + uint256 public constant FEE_BASE_DECIMALS = 36; + /// @dev The decimals that Keystone reports prices in + uint256 public constant KEYSTONE_PRICE_DECIMALS = 18; + + string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; + + /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. + /// Multiple gas prices can be encoded into the same value. Each price takes {Internal.GAS_PRICE_BITS} bits. + /// For example, if Optimism is the destination chain, gas price can include L1 base fee and L2 gas price. + /// Logic to parse the price components is chain-specific, and should live in OnRamp. + /// @dev Price of 1e18 is 1 USD. Examples: + /// Very Expensive: 1 unit of gas costs 1 USD -> 1e18 + /// Expensive: 1 unit of gas costs 0.1 USD -> 1e17 + /// Cheap: 1 unit of gas costs 0.000001 USD -> 1e12 + mapping(uint64 destChainSelector => Internal.TimestampedPackedUint224 price) private + s_usdPerUnitGasByDestChainSelector; + + /// @dev The price, in USD with 18 decimals, per 1e18 of the smallest token denomination. + /// @dev Price of 1e18 represents 1 USD per 1e18 token amount. + /// 1 USDC = 1.00 USD per full token, each full token is 1e6 units -> 1 * 1e18 * 1e18 / 1e6 = 1e30 + /// 1 ETH = 2,000 USD per full token, each full token is 1e18 units -> 2000 * 1e18 * 1e18 / 1e18 = 2_000e18 + /// 1 LINK = 5.00 USD per full token, each full token is 1e18 units -> 5 * 1e18 * 1e18 / 1e18 = 5e18 + mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken; + + /// @dev Stores the price data feed configurations per token. + mapping(address token => TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; + + /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin + mapping(address token => uint64 premiumMultiplierWeiPerEth) private s_premiumMultiplierWeiPerEth; + + /// @dev The destination chain specific fee configs + mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; + + /// @dev The token transfer fee config that can be set by the owner or fee admin + mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) private + s_tokenTransferFeeConfig; + + /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. + uint96 internal immutable i_maxFeeJuelsPerMsg; + /// @dev The link token address + address internal immutable i_linkToken; + + /// @dev Subset of tokens which prices tracked by this registry which are fee tokens. + EnumerableSet.AddressSet private s_feeTokens; + /// @dev The amount of time a gas price can be stale before it is considered invalid. + uint32 private immutable i_stalenessThreshold; + + constructor( + StaticConfig memory staticConfig, + address[] memory priceUpdaters, + address[] memory feeTokens, + TokenPriceFeedUpdate[] memory tokenPriceFeeds, + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, + DestChainConfigArgs[] memory destChainConfigArgs + ) AuthorizedCallers(priceUpdaters) { + if ( + staticConfig.linkToken == address(0) || staticConfig.maxFeeJuelsPerMsg == 0 + || staticConfig.stalenessThreshold == 0 + ) { + revert InvalidStaticConfig(); + } + + i_linkToken = staticConfig.linkToken; + i_maxFeeJuelsPerMsg = staticConfig.maxFeeJuelsPerMsg; + i_stalenessThreshold = staticConfig.stalenessThreshold; + + _applyFeeTokensUpdates(feeTokens, new address[](0)); + _updateTokenPriceFeeds(tokenPriceFeeds); + _applyDestChainConfigUpdates(destChainConfigArgs); + _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, new TokenTransferFeeConfigRemoveArgs[](0)); + } + + // ================================================================ + // │ Price calculations │ + // ================================================================ + + /// @inheritdoc IPriceRegistry + function getTokenPrice( + address token + ) public view override returns (Internal.TimestampedPackedUint224 memory) { + Internal.TimestampedPackedUint224 memory tokenPrice = s_usdPerToken[token]; + + // If the token price is not stale, return it + if (block.timestamp - tokenPrice.timestamp < i_stalenessThreshold) { + return tokenPrice; + } + + TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + + // If the token price feed is not set, return the stale price + if (priceFeedConfig.dataFeedAddress == address(0)) { + return tokenPrice; + } + + // If the token price feed is set, return the price from the feed + // The price feed is the fallback because we do not expect it to be the default source due to the gas cost of reading from it + return _getTokenPriceFromDataFeed(priceFeedConfig); + } + + /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. + function getValidatedTokenPrice( + address token + ) external view returns (uint224) { + return _getValidatedTokenPrice(token); + } + + /// @notice Get the `tokenPrice` for an array of tokens. + /// @param tokens The tokens to get prices for. + /// @return tokenPrices The tokenPrices for the given tokens. + function getTokenPrices( + address[] calldata tokens + ) external view returns (Internal.TimestampedPackedUint224[] memory) { + uint256 length = tokens.length; + Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length); + for (uint256 i = 0; i < length; ++i) { + tokenPrices[i] = getTokenPrice(tokens[i]); + } + return tokenPrices; + } + + /// @notice Returns the token price data feed configuration + /// @param token The token to retrieve the feed config for + /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) + function getTokenPriceFeedConfig( + address token + ) external view returns (TokenPriceFeedConfig memory) { + return s_usdPriceFeedsPerToken[token]; + } + + /// @notice Get an encoded `gasPrice` for a given destination chain ID. + /// The 224-bit result encodes necessary gas price components. + /// On L1 chains like Ethereum or Avax, the only component is the gas price. + /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. + /// On future chains, there could be more or differing price components. + /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. + /// @param destChainSelector The destination chain to get the price for. + /// @return gasPrice The encoded gasPrice for the given destination chain ID. + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (Internal.TimestampedPackedUint224 memory) { + return s_usdPerUnitGasByDestChainSelector[destChainSelector]; + } + + /// @notice Gets the fee token price and the gas price, both denominated in dollars. + /// @param token The source token to get the price for. + /// @param destChainSelector The destination chain to get the gas price for. + /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. + /// @return gasPriceValue The price of gas in 1e18 dollars per base unit. + function getTokenAndGasPrices( + address token, + uint64 destChainSelector + ) public view returns (uint224 tokenPrice, uint224 gasPriceValue) { + Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; + // We do allow a gas price of 0, but no stale or unset gas prices + if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector); + uint256 timePassed = block.timestamp - gasPrice.timestamp; + if (timePassed > i_stalenessThreshold) revert StaleGasPrice(destChainSelector, i_stalenessThreshold, timePassed); + + return (_getValidatedTokenPrice(token), gasPrice.value); + } + + /// @notice Convert a given token amount to target token amount. + /// @dev this function assumes that no more than 1e59 dollars are sent as payment. + /// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow. + /// Since there isn't even close to 1e59 dollars in the world economy this is safe. + /// @param fromToken The given token address. + /// @param fromTokenAmount The given token amount. + /// @param toToken The target token address. + /// @return toTokenAmount The target token amount. + function convertTokenAmount( + address fromToken, + uint256 fromTokenAmount, + address toToken + ) public view returns (uint256) { + /// Example: + /// fromTokenAmount: 1e18 // 1 ETH + /// ETH: 2_000e18 + /// LINK: 5e18 + /// return: 1e18 * 2_000e18 / 5e18 = 400e18 (400 LINK) + return (fromTokenAmount * _getValidatedTokenPrice(fromToken)) / _getValidatedTokenPrice(toToken); + } + + /// @notice Gets the token price for a given token and reverts if the token is not supported + /// @param token The address of the token to get the price for + /// @return tokenPriceValue The token price + function _getValidatedTokenPrice( + address token + ) internal view returns (uint224) { + Internal.TimestampedPackedUint224 memory tokenPrice = getTokenPrice(token); + // Token price must be set at least once + if (tokenPrice.timestamp == 0 || tokenPrice.value == 0) revert TokenNotSupported(token); + return tokenPrice.value; + } + + /// @notice Gets the token price from a data feed address, rebased to the same units as s_usdPerToken + /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) + /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp + function _getTokenPriceFromDataFeed( + TokenPriceFeedConfig memory priceFeedConfig + ) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) { + AggregatorV3Interface dataFeedContract = AggregatorV3Interface(priceFeedConfig.dataFeedAddress); + ( + /* uint80 roundID */ + , + int256 dataFeedAnswer, + /* uint startedAt */ + , + /* uint256 updatedAt */ + , + /* uint80 answeredInRound */ + ) = dataFeedContract.latestRoundData(); + + if (dataFeedAnswer < 0) { + revert DataFeedValueOutOfUint224Range(); + } + uint224 rebasedValue = + _calculateRebasedValue(dataFeedContract.decimals(), priceFeedConfig.tokenDecimals, uint256(dataFeedAnswer)); + + // Data feed staleness is unchecked to decouple the FeeQuoter from data feed delay issues + return Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: uint32(block.timestamp)}); + } + + // ================================================================ + // │ Fee tokens │ + // ================================================================ + + /// @inheritdoc IPriceRegistry + function getFeeTokens() external view returns (address[] memory) { + return s_feeTokens.values(); + } + + /// @notice Add and remove tokens from feeTokens set. + /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. + /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens + /// and can be used to calculate fees. + function applyFeeTokensUpdates( + address[] memory feeTokensToAdd, + address[] memory feeTokensToRemove + ) external onlyOwner { + _applyFeeTokensUpdates(feeTokensToAdd, feeTokensToRemove); + } + + /// @notice Add and remove tokens from feeTokens set. + /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. + /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens + /// and can be used to calculate fees. + function _applyFeeTokensUpdates(address[] memory feeTokensToAdd, address[] memory feeTokensToRemove) private { + for (uint256 i = 0; i < feeTokensToAdd.length; ++i) { + if (s_feeTokens.add(feeTokensToAdd[i])) { + emit FeeTokenAdded(feeTokensToAdd[i]); + } + } + for (uint256 i = 0; i < feeTokensToRemove.length; ++i) { + if (s_feeTokens.remove(feeTokensToRemove[i])) { + emit FeeTokenRemoved(feeTokensToRemove[i]); + } + } + } + + // ================================================================ + // │ Price updates │ + // ================================================================ + + /// @inheritdoc IPriceRegistry + function updatePrices( + Internal.PriceUpdates calldata priceUpdates + ) external override { + // The caller must be the fee updater + _validateCaller(); + + uint256 tokenUpdatesLength = priceUpdates.tokenPriceUpdates.length; + + for (uint256 i = 0; i < tokenUpdatesLength; ++i) { + Internal.TokenPriceUpdate memory update = priceUpdates.tokenPriceUpdates[i]; + s_usdPerToken[update.sourceToken] = + Internal.TimestampedPackedUint224({value: update.usdPerToken, timestamp: uint32(block.timestamp)}); + emit UsdPerTokenUpdated(update.sourceToken, update.usdPerToken, block.timestamp); + } + + uint256 gasUpdatesLength = priceUpdates.gasPriceUpdates.length; + + for (uint256 i = 0; i < gasUpdatesLength; ++i) { + Internal.GasPriceUpdate memory update = priceUpdates.gasPriceUpdates[i]; + s_usdPerUnitGasByDestChainSelector[update.destChainSelector] = + Internal.TimestampedPackedUint224({value: update.usdPerUnitGas, timestamp: uint32(block.timestamp)}); + emit UsdPerUnitGasUpdated(update.destChainSelector, update.usdPerUnitGas, block.timestamp); + } + } + + /// @notice Updates the USD token price feeds for given tokens + /// @param tokenPriceFeedUpdates Token price feed updates to apply + function updateTokenPriceFeeds( + TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates + ) external onlyOwner { + _updateTokenPriceFeeds(tokenPriceFeedUpdates); + } + + /// @notice Updates the USD token price feeds for given tokens + /// @param tokenPriceFeedUpdates Token price feed updates to apply + function _updateTokenPriceFeeds( + TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates + ) private { + for (uint256 i; i < tokenPriceFeedUpdates.length; ++i) { + TokenPriceFeedUpdate memory update = tokenPriceFeedUpdates[i]; + address sourceToken = update.sourceToken; + TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; + + s_usdPriceFeedsPerToken[sourceToken] = tokenPriceFeedConfig; + emit PriceFeedPerTokenUpdated(sourceToken, tokenPriceFeedConfig); + } + } + + /// @notice Handles the report containing price feeds and updates the internal price storage + /// @inheritdoc IReceiver + /// @dev This function is called to process incoming price feed data. + /// @param metadata Arbitrary metadata associated with the report (not used in this implementation). + /// @param report Encoded report containing an array of `ReceivedCCIPFeedReport` structs. + function onReport(bytes calldata metadata, bytes calldata report) external { + (bytes10 workflowName, address workflowOwner, bytes2 reportName) = metadata._extractMetadataInfo(); + + _validateReportPermission(msg.sender, workflowOwner, workflowName, reportName); + + ReceivedCCIPFeedReport[] memory feeds = abi.decode(report, (ReceivedCCIPFeedReport[])); + + for (uint256 i = 0; i < feeds.length; ++i) { + uint8 tokenDecimals = s_usdPriceFeedsPerToken[feeds[i].token].tokenDecimals; + if (tokenDecimals == 0) { + revert TokenNotSupported(feeds[i].token); + } + // Keystone reports prices in USD with 18 decimals, so we passing it as 18 in the _calculateRebasedValue function + uint224 rebasedValue = _calculateRebasedValue(18, tokenDecimals, feeds[i].price); + + //if stale update then revert + if (feeds[i].timestamp < s_usdPerToken[feeds[i].token].timestamp) { + revert StaleKeystoneUpdate(feeds[i].token, feeds[i].timestamp, s_usdPerToken[feeds[i].token].timestamp); + } + + s_usdPerToken[feeds[i].token] = + Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: feeds[i].timestamp}); + emit UsdPerTokenUpdated(feeds[i].token, rebasedValue, feeds[i].timestamp); + } + } + + // ================================================================ + // │ Fee quoting │ + // ================================================================ + + /// @inheritdoc IFeeQuoter + /// @dev The function should always validate message.extraArgs, message.receiver and family-specific configs + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount) { + DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; + if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); + if (!s_feeTokens.contains(message.feeToken)) revert FeeTokenNotSupported(message.feeToken); + + uint256 numberOfTokens = message.tokenAmounts.length; + _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); + + // The below call asserts that feeToken is a supported token + (uint224 feeTokenPrice, uint224 packedGasPrice) = getTokenAndGasPrices(message.feeToken, destChainSelector); + + // Calculate premiumFee in USD with 18 decimals precision first. + // If message-only and no token transfers, a flat network fee is charged. + // If there are token transfers, premiumFee is calculated from token transfer fee. + // If there are both token transfers and message, premiumFee is only calculated from token transfer fee. + uint256 premiumFee = 0; + uint32 tokenTransferGas = 0; + uint32 tokenTransferBytesOverhead = 0; + if (numberOfTokens > 0) { + (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = + _getTokenTransferCost(destChainConfig, destChainSelector, message.feeToken, feeTokenPrice, message.tokenAmounts); + } else { + // Convert USD cents with 2 decimals to 18 decimals. + premiumFee = uint256(destChainConfig.networkFeeUSDCents) * 1e16; + } + + // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to post + // transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs. + uint256 dataAvailabilityCost = 0; + + // Only calculate data availability cost if data availability multiplier is non-zero. + // The multiplier should be set to 0 if destination chain does not charge data availability cost. + if (destChainConfig.destDataAvailabilityMultiplierBps > 0) { + dataAvailabilityCost = _getDataAvailabilityCost( + destChainConfig, + // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. + uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), + message.data.length, + numberOfTokens, + tokenTransferBytesOverhead + ); + } + + // Calculate execution gas fee on destination chain in USD with 36 decimals. + // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together. + // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals. + // uint112(packedGasPrice) = executionGasPrice + + // NOTE: when supporting non-EVM chains, revisit how generic this fee logic can be + // NOTE: revisit parsing non-EVM args + uint256 executionCost = uint112(packedGasPrice) + * ( + destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas + + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit + ) * destChainConfig.gasMultiplierWeiPerEth; + + // Calculate number of fee tokens to charge. + // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. + // Result of the division is the number of smallest token denominations. + return ((premiumFee * s_premiumMultiplierWeiPerEth[message.feeToken]) + executionCost + dataAvailabilityCost) + / feeTokenPrice; + } + + /// @notice Sets the fee configuration for a token. + /// @param premiumMultiplierWeiPerEthArgs Array of PremiumMultiplierWeiPerEthArgs structs. + function applyPremiumMultiplierWeiPerEthUpdates( + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs + ) external onlyOwner { + _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + } + + /// @dev Sets the fee config. + /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. + function _applyPremiumMultiplierWeiPerEthUpdates( + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs + ) internal { + for (uint256 i = 0; i < premiumMultiplierWeiPerEthArgs.length; ++i) { + address token = premiumMultiplierWeiPerEthArgs[i].token; + uint64 premiumMultiplierWeiPerEth = premiumMultiplierWeiPerEthArgs[i].premiumMultiplierWeiPerEth; + s_premiumMultiplierWeiPerEth[token] = premiumMultiplierWeiPerEth; + + emit PremiumMultiplierWeiPerEthUpdated(token, premiumMultiplierWeiPerEth); + } + } + + /// @notice Gets the fee configuration for a token. + /// @param token The token to get the fee configuration for. + /// @return premiumMultiplierWeiPerEth The multiplier for destination chain specific premiums. + function getPremiumMultiplierWeiPerEth( + address token + ) external view returns (uint64 premiumMultiplierWeiPerEth) { + return s_premiumMultiplierWeiPerEth[token]; + } + + /// @notice Returns the token transfer cost parameters. + /// A basis point fee is calculated from the USD value of each token transfer. + /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD]. + /// Total transfer fee is the sum of each individual token transfer fee. + /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere. + /// @dev Splitting one token transfer into multiple transfers is discouraged, + /// as it will result in a transferFee equal or greater than the same amount aggregated/de-duped. + /// @param destChainConfig the config configured for the destination chain selector. + /// @param destChainSelector the destination chain selector. + /// @param feeToken address of the feeToken. + /// @param feeTokenPrice price of feeToken in USD with 18 decimals. + /// @param tokenAmounts token transfers in the message. + /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals. + /// @return tokenTransferGas total execution gas of the token transfers. + /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. + function _getTokenTransferCost( + DestChainConfig memory destChainConfig, + uint64 destChainSelector, + address feeToken, + uint224 feeTokenPrice, + Client.EVMTokenAmount[] calldata tokenAmounts + ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) { + uint256 numberOfTokens = tokenAmounts.length; + + for (uint256 i = 0; i < numberOfTokens; ++i) { + Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i]; + TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][tokenAmount.token]; + + // If the token has no specific overrides configured, we use the global defaults. + if (!transferFeeConfig.isEnabled) { + tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; + tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; + tokenTransferBytesOverhead += Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES; + continue; + } + + uint256 bpsFeeUSDWei = 0; + // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. + // Useful for when the FeeQuoter cannot return a valid price for the token. + if (transferFeeConfig.deciBps > 0) { + uint224 tokenPrice = 0; + if (tokenAmount.token != feeToken) { + tokenPrice = _getValidatedTokenPrice(tokenAmount.token); + } else { + tokenPrice = feeTokenPrice; + } + + // Calculate token transfer value, then apply fee ratio + // ratio represents multiples of 0.1bps, or 1e-5 + bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5; + } + + tokenTransferGas += transferFeeConfig.destGasOverhead; + tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead; + + // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD]. + // Convert USD values with 2 decimals to 18 decimals. + uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16; + if (bpsFeeUSDWei < minFeeUSDWei) { + tokenTransferFeeUSDWei += minFeeUSDWei; + continue; + } + + uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16; + if (bpsFeeUSDWei > maxFeeUSDWei) { + tokenTransferFeeUSDWei += maxFeeUSDWei; + continue; + } + + tokenTransferFeeUSDWei += bpsFeeUSDWei; + } + + return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); + } + + /// @notice calculates the rebased value for 1e18 smallest token denomination + /// @param dataFeedDecimal decimal of the data feed + /// @param tokenDecimal decimal of the token + /// @param feedValue value of the data feed + /// @return rebasedValue rebased value + function _calculateRebasedValue( + uint8 dataFeedDecimal, + uint8 tokenDecimal, + uint256 feedValue + ) internal pure returns (uint224 rebasedValue) { + // Rebase formula for units in smallest token denomination: usdValue * (1e18 * 1e18) / 1eTokenDecimals + // feedValue * (10 ** (18 - feedDecimals)) * (10 ** (18 - erc20Decimals)) + // feedValue * (10 ** ((18 - feedDecimals) + (18 - erc20Decimals))) + // feedValue * (10 ** (36 - feedDecimals - erc20Decimals)) + // feedValue * (10 ** (36 - (feedDecimals + erc20Decimals))) + // feedValue * (10 ** (36 - excessDecimals)) + // If excessDecimals > 36 => flip it to feedValue / (10 ** (excessDecimals - 36)) + uint8 excessDecimals = dataFeedDecimal + tokenDecimal; + uint256 rebasedVal; + + if (excessDecimals > FEE_BASE_DECIMALS) { + rebasedVal = feedValue / (10 ** (excessDecimals - FEE_BASE_DECIMALS)); + } else { + rebasedVal = feedValue * (10 ** (FEE_BASE_DECIMALS - excessDecimals)); + } + + if (rebasedVal > type(uint224).max) { + revert DataFeedValueOutOfUint224Range(); + } + + return uint224(rebasedVal); + } + + /// @notice Returns the estimated data availability cost of the message. + /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. + /// @param destChainConfig the config configured for the destination chain selector. + /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals. + /// @param messageDataLength length of the data field in the message. + /// @param numberOfTokens number of distinct token transfers in the message. + /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. + /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals. + function _getDataAvailabilityCost( + DestChainConfig memory destChainConfig, + uint112 dataAvailabilityGasPrice, + uint256 messageDataLength, + uint256 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) internal pure returns (uint256 dataAvailabilityCostUSD36Decimal) { + // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. + // Fixed message fields do account for the offset and length slot of the dynamic fields. + uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + + // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. + // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. + uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * destChainConfig.destGasPerDataAvailabilityByte) + + destChainConfig.destDataAvailabilityOverheadGas; + + // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals + // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee. + return ((dataAvailabilityGas * dataAvailabilityGasPrice) * destChainConfig.destDataAvailabilityMultiplierBps) * 1e14; + } + + /// @notice Gets the transfer fee config for a given token. + /// @param destChainSelector The destination chain selector. + /// @param token The token address. + /// @return tokenTransferFeeConfig The transfer fee config for the token. + function getTokenTransferFeeConfig( + uint64 destChainSelector, + address token + ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) { + return s_tokenTransferFeeConfig[destChainSelector][token]; + } + + /// @notice Sets the transfer fee config. + /// @dev only callable by the owner or admin. + function applyTokenTransferFeeConfigUpdates( + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs + ) external onlyOwner { + _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs); + } + + /// @notice internal helper to set the token transfer fee config. + function _applyTokenTransferFeeConfigUpdates( + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs + ) internal { + for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { + TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = tokenTransferFeeConfigArgs[i]; + uint64 destChainSelector = tokenTransferFeeConfigArg.destChainSelector; + + for (uint256 j = 0; j < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++j) { + TokenTransferFeeConfig memory tokenTransferFeeConfig = + tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].tokenTransferFeeConfig; + address token = tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].token; + + if (tokenTransferFeeConfig.destBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { + revert InvalidDestBytesOverhead(token, tokenTransferFeeConfig.destBytesOverhead); + } + + s_tokenTransferFeeConfig[destChainSelector][token] = tokenTransferFeeConfig; + + emit TokenTransferFeeConfigUpdated(destChainSelector, token, tokenTransferFeeConfig); + } + } + + // Remove the custom fee configs for the tokens that are in the tokensToUseDefaultFeeConfigs array + for (uint256 i = 0; i < tokensToUseDefaultFeeConfigs.length; ++i) { + uint64 destChainSelector = tokensToUseDefaultFeeConfigs[i].destChainSelector; + address token = tokensToUseDefaultFeeConfigs[i].token; + delete s_tokenTransferFeeConfig[destChainSelector][token]; + emit TokenTransferFeeConfigDeleted(destChainSelector, token); + } + } + + // ================================================================ + // │ Validations & message processing │ + // ================================================================ + + /// @notice Validates that the destAddress matches the expected format of the family. + /// @param chainFamilySelector Tag to identify the target family. + /// @param destAddress Dest address to validate. + /// @dev precondition - assumes the family tag is correct and validated. + function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + Internal._validateEVMAddress(destAddress); + } + } + + /// @dev Convert the extra args bytes into a struct with validations against the dest chain config. + /// @param extraArgs The extra args bytes. + /// @param destChainConfig Dest chain config to validate against. + /// @return evmExtraArgs The EVMExtraArgs struct (latest version). + function _parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) internal pure returns (Client.EVMExtraArgsV2 memory) { + Client.EVMExtraArgsV2 memory evmExtraArgs = + _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); + + if (evmExtraArgs.gasLimit > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); + if (destChainConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { + revert ExtraArgOutOfOrderExecutionMustBeTrue(); + } + + return evmExtraArgs; + } + + /// @dev Convert the extra args bytes into a struct. + /// @param extraArgs The extra args bytes. + /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args. + /// @return EVMExtraArgs the extra args struct (latest version) + function _parseUnvalidatedEVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 defaultTxGasLimit + ) private pure returns (Client.EVMExtraArgsV2 memory) { + if (extraArgs.length == 0) { + // If extra args are empty, generate default values + return Client.EVMExtraArgsV2({gasLimit: defaultTxGasLimit, allowOutOfOrderExecution: false}); + } + + bytes4 extraArgsTag = bytes4(extraArgs); + bytes memory argsData = extraArgs[4:]; + + if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { + return abi.decode(argsData, (Client.EVMExtraArgsV2)); + } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { + // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. + // Clients may still include it but it will be ignored. + return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); + } + + revert InvalidExtraArgsTag(); + } + + /// @notice Validate the forwarded message to ensure it matches the configuration limits (message length, number of tokens) + /// and family-specific expectations (address format). + /// @param destChainConfig The destination chain config. + /// @param dataLength The length of the data field of the message. + /// @param numberOfTokens The number of tokens to be sent. + /// @param receiver Message receiver on the dest chain. + function _validateMessage( + DestChainConfig memory destChainConfig, + uint256 dataLength, + uint256 numberOfTokens, + bytes memory receiver + ) internal pure { + // Check that payload is formed correctly + if (dataLength > uint256(destChainConfig.maxDataBytes)) { + revert MessageTooLarge(uint256(destChainConfig.maxDataBytes), dataLength); + } + if (numberOfTokens > uint256(destChainConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); + _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); + } + + /// @inheritdoc IFeeQuoter + /// @dev precondition - onRampTokenTransfers and sourceTokenAmounts lengths must be equal + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes calldata extraArgs, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ) + { + // Convert feeToken to link if not already in link + if (feeToken == i_linkToken) { + msgFeeJuels = feeTokenAmount; + } else { + msgFeeJuels = convertTokenAmount(feeToken, feeTokenAmount, i_linkToken); + } + + if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); + + uint64 defaultTxGasLimit = s_destChainConfigs[destChainSelector].defaultTxGasLimit; + // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args. + // We can parse unvalidated args since this message is called after getFee (which will already validate the params) + Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); + isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; + destExecDataPerToken = _processPoolReturnData(destChainSelector, onRampTokenTransfers, sourceTokenAmounts); + + return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); + } + + /// @notice Validates pool return data + /// @param destChainSelector Destination chain selector to which the token amounts are sent to + /// @param onRampTokenTransfers Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return destExecDataPerToken Destination chain execution data + function _processPoolReturnData( + uint64 destChainSelector, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) internal view returns (bytes[] memory destExecDataPerToken) { + bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; + destExecDataPerToken = new bytes[](onRampTokenTransfers.length); + for (uint256 i = 0; i < onRampTokenTransfers.length; ++i) { + address sourceToken = sourceTokenAmounts[i].token; + + // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the + // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both + // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. + uint256 destPoolDataLength = onRampTokenTransfers[i].extraData.length; + if (destPoolDataLength > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { + if (destPoolDataLength > s_tokenTransferFeeConfig[destChainSelector][sourceToken].destBytesOverhead) { + revert SourceTokenDataTooLarge(sourceToken); + } + } + + _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_tokenTransferFeeConfig[destChainSelector][sourceToken]; + uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; + // NOTE: Revisit this when adding new non-EVM chain family selector support + uint32 destGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : defaultGasOverhead; + + // The user will be billed either the default or the override, so we send the exact amount that we billed for + // to the destination chain to be used for the token releaseOrMint and transfer. + destExecDataPerToken[i] = abi.encode(destGasAmount); + } + return destExecDataPerToken; + } + + // ================================================================ + // │ Configs │ + // ================================================================ + + /// @notice Returns the configured config for the dest chain selector. + /// @param destChainSelector Destination chain selector to fetch config for. + /// @return destChainConfig Config for the destination chain. + function getDestChainConfig( + uint64 destChainSelector + ) external view returns (DestChainConfig memory) { + return s_destChainConfigs[destChainSelector]; + } + + /// @notice Updates the destination chain specific config. + /// @param destChainConfigArgs Array of source chain specific configs. + function applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) external onlyOwner { + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + /// @notice Internal version of applyDestChainConfigUpdates. + function _applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) internal { + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig; + + // NOTE: when supporting non-EVM chains, update chainFamilySelector validations + if ( + destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 + || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM + || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit + ) { + revert InvalidDestChainConfig(destChainSelector); + } + + // The chain family selector cannot be zero - indicates that it is a new chain + if (s_destChainConfigs[destChainSelector].chainFamilySelector == 0) { + emit DestChainAdded(destChainSelector, destChainConfig); + } else { + emit DestChainConfigUpdated(destChainSelector, destChainConfig); + } + + s_destChainConfigs[destChainSelector] = destChainConfig; + } + } + + /// @notice Returns the static FeeQuoter config. + /// @dev RMN depends on this function, if updated, please notify the RMN maintainers. + /// @return staticConfig The static configuration. + function getStaticConfig() external view returns (StaticConfig memory) { + return StaticConfig({ + maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, + linkToken: i_linkToken, + stalenessThreshold: i_stalenessThreshold + }); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md new file mode 100644 index 0000000..812debd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 SmartContract ChainLink, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md new file mode 100644 index 0000000..b2e8248 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md @@ -0,0 +1,56 @@ +Business Source License 1.1 + +License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. +"Business Source License" is a trademark of MariaDB Corporation Ab. + +----------------------------------------------------------------------------- + +Parameters + +Licensor: SmartContract Chainlink Limited SEZC + +Licensed Work: Cross-Chain Interoperability Protocol v1.5 +The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC + +Additional Use Grant: Any uses listed and defined at [v1.5-CCIP-License-grants]( +./v1.5-CCIP-License-grants.md) + +Change Date: Aug 16, 2028 + +Change License: MIT + +----------------------------------------------------------------------------- + +Terms + +The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. + +Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. + +If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. + +All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. + +You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. + +Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. + +This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). + +TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. + +MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. + +----------------------------------------------------------------------------- + +Covenants of Licensor + +In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: + +1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. + +2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". + +3. To specify a Change Date. + +4. Not to modify this License in any other way. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol new file mode 100644 index 0000000..7dfcc0e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; +import {IMessageInterceptor} from "./interfaces/IMessageInterceptor.sol"; + +import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; +import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; +import {Client} from "./libraries/Client.sol"; +import {RateLimiter} from "./libraries/RateLimiter.sol"; +import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; + +/// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter +/// which permits rate limiting based on the aggregate value of a group of +/// token transfers, using a fee quoter to convert to a numeraire asset (e.g. USD). +/// The contract is a standalone multi-lane message validator contract, which can be called by authorized +/// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. +contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, ITypeAndVersion { + using RateLimiter for RateLimiter.TokenBucket; + using USDPriceWith18Decimals for uint224; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + error PriceNotFoundForToken(address token); + error ZeroChainSelectorNotAllowed(); + + event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, bool isOutboundLane, RateLimiter.Config config); + event FeeQuoterSet(address newFeeQuoter); + event TokenAggregateRateLimitAdded(uint64 remoteChainSelector, bytes remoteToken, address localToken); + event TokenAggregateRateLimitRemoved(uint64 remoteChainSelector, address localToken); + + /// @notice LocalRateLimitToken struct containing the local token address with the remote chain selector. + /// The struct is used for removals and updates, since the local -> remote token mappings are scoped per-chain. + struct LocalRateLimitToken { + uint64 remoteChainSelector; // ────╮ Remote chain selector for which to update the rate limit token mapping + address localToken; // ────────────╯ Token on the chain on which the multi-ARL is deployed + } + + /// @notice RateLimitTokenArgs struct containing both the local and remote token addresses. + struct RateLimitTokenArgs { + LocalRateLimitToken localTokenArgs; // Local token update args scoped to one remote chain + bytes remoteToken; // Token on the remote chain (for OnRamp - dest, of OffRamp - source) + } + + /// @notice Update args for a single rate limiter config update. + struct RateLimiterConfigArgs { + uint64 remoteChainSelector; // ────╮ Remote chain selector to set config for + bool isOutboundLane; // ───────────╯ If set to true, represents the outbound message lane (OnRamp), and the inbound message lane otherwise (OffRamp) + RateLimiter.Config rateLimiterConfig; // Rate limiter config to set + } + + /// @notice Struct to store rate limit token buckets for both lane directions. + struct RateLimiterBuckets { + RateLimiter.TokenBucket inboundLaneBucket; // Bucket for the inbound lane (remote -> local) + RateLimiter.TokenBucket outboundLaneBucket; // Bucket for the outbound lane (local -> remote) + } + + string public constant override typeAndVersion = "MultiAggregateRateLimiter 1.6.0-dev"; + + /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote), + /// grouped per-remote chain. + mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) private + s_rateLimitedTokensLocalToRemote; + + /// @notice The address of the FeeQuoter used to query token values for ratelimiting. + address internal s_feeQuoter; + + /// @notice Rate limiter token bucket states per chain, with separate buckets for inbound and outbound lanes. + mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) private s_rateLimitersByChainSelector; + + /// @param feeQuoter the fee quoter to set. + /// @param authorizedCallers the authorized callers to set. + constructor(address feeQuoter, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { + _setFeeQuoter(feeQuoter); + } + + /// @inheritdoc IMessageInterceptor + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external onlyAuthorizedCallers { + _applyRateLimit(message.sourceChainSelector, message.destTokenAmounts, false); + } + + /// @inheritdoc IMessageInterceptor + function onOutboundMessage( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external onlyAuthorizedCallers { + _applyRateLimit(destChainSelector, message.tokenAmounts, true); + } + + /// @notice Applies the rate limit to the token bucket if enabled. + /// @param remoteChainSelector The remote chain selector. + /// @param tokenAmounts The tokens and amounts to rate limit. + /// @param isOutgoingLane if set to true, fetches the bucket for the outgoing message lane (OnRamp). + function _applyRateLimit( + uint64 remoteChainSelector, + Client.EVMTokenAmount[] memory tokenAmounts, + bool isOutgoingLane + ) private { + RateLimiter.TokenBucket storage tokenBucket = _getTokenBucket(remoteChainSelector, isOutgoingLane); + + // Skip rate limiting if it is disabled + if (tokenBucket.isEnabled) { + uint256 value; + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].contains(tokenAmounts[i].token)) { + value += _getTokenValue(tokenAmounts[i]); + } + } + // Rate limit on aggregated token value + if (value > 0) tokenBucket._consume(value, address(0)); + } + } + + /// @param remoteChainSelector chain selector to retrieve token bucket for. + /// @param isOutboundLane if set to true, fetches the bucket for the outbound message lane (OnRamp). + /// Otherwise fetches for the inbound message lane (OffRamp). + /// @return bucket Storage pointer to the token bucket representing a specific lane. + function _getTokenBucket( + uint64 remoteChainSelector, + bool isOutboundLane + ) internal view returns (RateLimiter.TokenBucket storage) { + RateLimiterBuckets storage rateLimiterBuckets = s_rateLimitersByChainSelector[remoteChainSelector]; + if (isOutboundLane) { + return rateLimiterBuckets.outboundLaneBucket; + } else { + return rateLimiterBuckets.inboundLaneBucket; + } + } + + /// @notice Retrieves the token value for a token using the FeeQuoter. + /// @param tokenAmount The token and amount to get the value for. + /// @return tokenValue USD value in 18 decimals. + function _getTokenValue( + Client.EVMTokenAmount memory tokenAmount + ) internal view returns (uint256) { + // not fetching validated price, as price staleness is not important for value-based rate limiting + // we only need to verify the price is not 0 + uint224 pricePerToken = IFeeQuoter(s_feeQuoter).getTokenPrice(tokenAmount.token).value; + if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); + return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @param remoteChainSelector chain selector to retrieve state for + /// @param isOutboundLane if set to true, fetches the rate limit state for the outbound message lane (OnRamp). + /// Otherwise fetches for the inbound message lane (OffRamp). + /// The outbound and inbound message rate limit state is completely separated. + /// @return tokenBucket The token bucket. + function currentRateLimiterState( + uint64 remoteChainSelector, + bool isOutboundLane + ) external view returns (RateLimiter.TokenBucket memory) { + return _getTokenBucket(remoteChainSelector, isOutboundLane)._currentTokenBucketState(); + } + + /// @notice Applies the provided rate limiter config updates. + /// @param rateLimiterUpdates Rate limiter updates. + /// @dev Only callable by the owner. + function applyRateLimiterConfigUpdates( + RateLimiterConfigArgs[] memory rateLimiterUpdates + ) external onlyOwner { + for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { + RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; + RateLimiter.Config memory configUpdate = updateArgs.rateLimiterConfig; + uint64 remoteChainSelector = updateArgs.remoteChainSelector; + + if (remoteChainSelector == 0) { + revert ZeroChainSelectorNotAllowed(); + } + + bool isOutboundLane = updateArgs.isOutboundLane; + + RateLimiter.TokenBucket storage tokenBucket = _getTokenBucket(remoteChainSelector, isOutboundLane); + + if (tokenBucket.lastUpdated == 0) { + // Token bucket needs to be newly added + RateLimiter.TokenBucket memory newTokenBucket = RateLimiter.TokenBucket({ + rate: configUpdate.rate, + capacity: configUpdate.capacity, + tokens: configUpdate.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: configUpdate.isEnabled + }); + + if (isOutboundLane) { + s_rateLimitersByChainSelector[remoteChainSelector].outboundLaneBucket = newTokenBucket; + } else { + s_rateLimitersByChainSelector[remoteChainSelector].inboundLaneBucket = newTokenBucket; + } + } else { + tokenBucket._setTokenBucketConfig(configUpdate); + } + emit RateLimiterConfigUpdated(remoteChainSelector, isOutboundLane, configUpdate); + } + } + + /// @notice Gets all tokens which are included in Aggregate Rate Limiting. + /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when + /// making successive calls, one should keep the block height constant to ensure a consistent result. + /// @param remoteChainSelector chain selector to get rate limit tokens for. + /// @return localTokens The local chain representation of the tokens that are rate limited. + /// @return remoteTokens The remote representation of the tokens that are rate limited. + function getAllRateLimitTokens( + uint64 remoteChainSelector + ) external view returns (address[] memory localTokens, bytes[] memory remoteTokens) { + uint256 tokenCount = s_rateLimitedTokensLocalToRemote[remoteChainSelector].length(); + + localTokens = new address[](tokenCount); + remoteTokens = new bytes[](tokenCount); + + for (uint256 i = 0; i < tokenCount; ++i) { + (address localToken, bytes memory remoteToken) = s_rateLimitedTokensLocalToRemote[remoteChainSelector].at(i); + localTokens[i] = localToken; + remoteTokens[i] = remoteToken; + } + return (localTokens, remoteTokens); + } + + /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. + /// @param removes - A list of one or more tokens to be removed. + /// @param adds - A list of one or more tokens to be added. + function updateRateLimitTokens( + LocalRateLimitToken[] memory removes, + RateLimitTokenArgs[] memory adds + ) external onlyOwner { + for (uint256 i = 0; i < removes.length; ++i) { + address localToken = removes[i].localToken; + uint64 remoteChainSelector = removes[i].remoteChainSelector; + + if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].remove(localToken)) { + emit TokenAggregateRateLimitRemoved(remoteChainSelector, localToken); + } + } + + for (uint256 i = 0; i < adds.length; ++i) { + LocalRateLimitToken memory localTokenArgs = adds[i].localTokenArgs; + bytes memory remoteToken = adds[i].remoteToken; + address localToken = localTokenArgs.localToken; + + if (localToken == address(0) || remoteToken.length == 0) { + revert ZeroAddressNotAllowed(); + } + + uint64 remoteChainSelector = localTokenArgs.remoteChainSelector; + + if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].set(localToken, remoteToken)) { + emit TokenAggregateRateLimitAdded(remoteChainSelector, remoteToken, localToken); + } + } + } + + /// @return feeQuoter The configured FeeQuoter address. + function getFeeQuoter() external view returns (address feeQuoter) { + return s_feeQuoter; + } + + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. + /// @dev precondition The address must be a non-zero address. + function setFeeQuoter( + address newFeeQuoter + ) external onlyOwner { + _setFeeQuoter(newFeeQuoter); + } + + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. + /// @dev precondition The address must be a non-zero address. + function _setFeeQuoter( + address newFeeQuoter + ) internal { + if (newFeeQuoter == address(0)) { + revert ZeroAddressNotAllowed(); + } + + s_feeQuoter = newFeeQuoter; + emit FeeQuoterSet(newFeeQuoter); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol new file mode 100644 index 0000000..a1db80a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; +import {INonceManager} from "./interfaces/INonceManager.sol"; + +import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; + +/// @title NonceManager +/// @notice NonceManager contract that manages sender nonces for the on/off ramps +contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { + error PreviousRampAlreadySet(); + + event PreviousRampsUpdated(uint64 indexed remoteChainSelector, PreviousRamps prevRamp); + event SkippedIncorrectNonce(uint64 sourceChainSelector, uint64 nonce, bytes sender); + + /// @dev Struct that contains the previous on/off ramp addresses + struct PreviousRamps { + address prevOnRamp; // Previous onRamp + address prevOffRamp; // Previous offRamp + } + + /// @dev Struct that contains the chain selector and the previous on/off ramps, same as PreviousRamps but with the chain selector + /// so that an array of these can be passed to the applyPreviousRampsUpdates function + struct PreviousRampsArgs { + uint64 remoteChainSelector; // Chain selector + PreviousRamps prevRamps; // Previous on/off ramps + } + + string public constant override typeAndVersion = "NonceManager 1.6.0-dev"; + + /// @dev The previous on/off ramps per chain selector + mapping(uint64 chainSelector => PreviousRamps previousRamps) private s_previousRamps; + /// @dev The current outbound nonce per sender used on the onramp + mapping(uint64 destChainSelector => mapping(address sender => uint64 outboundNonce)) private s_outboundNonces; + /// @dev The current inbound nonce per sender used on the offramp + /// Eventually in sync with the outbound nonce in the remote source chain NonceManager, used to enforce that messages are + /// executed in the same order they are sent (assuming they are DON) + mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 inboundNonce)) private s_inboundNonces; + + constructor( + address[] memory authorizedCallers + ) AuthorizedCallers(authorizedCallers) {} + + /// @inheritdoc INonceManager + function getIncrementedOutboundNonce( + uint64 destChainSelector, + address sender + ) external onlyAuthorizedCallers returns (uint64) { + uint64 outboundNonce = _getOutboundNonce(destChainSelector, sender) + 1; + s_outboundNonces[destChainSelector][sender] = outboundNonce; + + return outboundNonce; + } + + /// @notice Returns the outbound nonce for a given sender on a given destination chain. + /// @param destChainSelector The destination chain selector. + /// @param sender The sender address. + /// @return outboundNonce The outbound nonce. + function getOutboundNonce(uint64 destChainSelector, address sender) external view returns (uint64) { + return _getOutboundNonce(destChainSelector, sender); + } + + function _getOutboundNonce(uint64 destChainSelector, address sender) private view returns (uint64) { + uint64 outboundNonce = s_outboundNonces[destChainSelector][sender]; + + // When introducing the NonceManager with existing lanes, we still want to have sequential nonces. + // Referencing the old onRamp preserves sequencing between updates. + if (outboundNonce == 0) { + address prevOnRamp = s_previousRamps[destChainSelector].prevOnRamp; + if (prevOnRamp != address(0)) { + return IEVM2AnyOnRamp(prevOnRamp).getSenderNonce(sender); + } + } + + return outboundNonce; + } + + /// @inheritdoc INonceManager + function incrementInboundNonce( + uint64 sourceChainSelector, + uint64 expectedNonce, + bytes calldata sender + ) external onlyAuthorizedCallers returns (bool) { + uint64 inboundNonce = _getInboundNonce(sourceChainSelector, sender) + 1; + + if (inboundNonce != expectedNonce) { + // If the nonce is not the expected one, this means that there are still messages in flight so we skip + // the nonce increment + emit SkippedIncorrectNonce(sourceChainSelector, expectedNonce, sender); + return false; + } + + s_inboundNonces[sourceChainSelector][sender] = inboundNonce; + + return true; + } + + /// @notice Returns the inbound nonce for a given sender on a given source chain. + /// @param sourceChainSelector The source chain selector. + /// @param sender The encoded sender address. + /// @return inboundNonce The inbound nonce. + function getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) external view returns (uint64) { + return _getInboundNonce(sourceChainSelector, sender); + } + + function _getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) private view returns (uint64) { + uint64 inboundNonce = s_inboundNonces[sourceChainSelector][sender]; + + // When introducing the NonceManager with existing lanes, we still want to have sequential nonces. + // Referencing the old offRamp to check the expected nonce if none is set for a + // given sender allows us to skip the current message in the current offRamp if it would not be the next according + // to the old offRamp. This preserves sequencing between updates. + if (inboundNonce == 0) { + address prevOffRamp = s_previousRamps[sourceChainSelector].prevOffRamp; + if (prevOffRamp != address(0)) { + // We only expect EVM previous offRamps here so we can safely decode the sender + return IEVM2AnyOnRamp(prevOffRamp).getSenderNonce(abi.decode(sender, (address))); + } + } + + return inboundNonce; + } + + /// @notice Updates the previous ramps addresses. + /// @param previousRampsArgs The previous on/off ramps addresses. + function applyPreviousRampsUpdates( + PreviousRampsArgs[] calldata previousRampsArgs + ) external onlyOwner { + for (uint256 i = 0; i < previousRampsArgs.length; ++i) { + PreviousRampsArgs calldata previousRampsArg = previousRampsArgs[i]; + + PreviousRamps storage prevRamps = s_previousRamps[previousRampsArg.remoteChainSelector]; + + // If the previous ramps are already set then they should not be updated. + // In versions prior to the introduction of the NonceManager contract, nonces were tracked in the on/off ramps. + // This config does a 1-time migration to move the nonce from on/off ramps into NonceManager + if (prevRamps.prevOnRamp != address(0) || prevRamps.prevOffRamp != address(0)) { + revert PreviousRampAlreadySet(); + } + + prevRamps.prevOnRamp = previousRampsArg.prevRamps.prevOnRamp; + prevRamps.prevOffRamp = previousRampsArg.prevRamps.prevOffRamp; + + emit PreviousRampsUpdated(previousRampsArg.remoteChainSelector, previousRampsArg.prevRamps); + } + } + + /// @notice Gets the previous onRamp address for the given chain selector + /// @param chainSelector The chain selector + /// @return previousRamps The previous on/offRamp addresses + function getPreviousRamps( + uint64 chainSelector + ) external view returns (PreviousRamps memory) { + return s_previousRamps[chainSelector]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol new file mode 100644 index 0000000..d83216f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IAny2EVMMessageReceiver} from "./interfaces/IAny2EVMMessageReceiver.sol"; +import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; +import {IRMN} from "./interfaces/IRMN.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; +import {IRouterClient} from "./interfaces/IRouterClient.sol"; +import {IWrappedNative} from "./interfaces/IWrappedNative.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; +import {CallWithExactGas} from "../shared/call/CallWithExactGas.sol"; +import {Client} from "./libraries/Client.sol"; +import {Internal} from "./libraries/Internal.sol"; + +import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @title Router +/// @notice This is the entry point for the end user wishing to send data across chains. +/// @dev This contract is used as a router for both on-ramps and off-ramps +contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + + error FailedToSendValue(); + error InvalidRecipientAddress(address to); + error OffRampMismatch(uint64 chainSelector, address offRamp); + error BadARMSignal(); + + event OnRampSet(uint64 indexed destChainSelector, address onRamp); + event OffRampAdded(uint64 indexed sourceChainSelector, address offRamp); + event OffRampRemoved(uint64 indexed sourceChainSelector, address offRamp); + event MessageExecuted(bytes32 messageId, uint64 sourceChainSelector, address offRamp, bytes32 calldataHash); + + struct OnRamp { + uint64 destChainSelector; + address onRamp; + } + + struct OffRamp { + uint64 sourceChainSelector; + address offRamp; + } + + string public constant override typeAndVersion = "Router 1.2.0"; + // We limit return data to a selector plus 4 words. This is to avoid + // malicious contracts from returning large amounts of data and causing + // repeated out-of-gas scenarios. + uint16 public constant MAX_RET_BYTES = 4 + 4 * 32; + // STATIC CONFIG + // Address of RMN proxy contract (formerly known as ARM) + address private immutable i_armProxy; + + // DYNAMIC CONFIG + address private s_wrappedNative; + // destChainSelector => onRamp address + // Only ever one onRamp enabled at a time for a given destChainSelector. + mapping(uint256 destChainSelector => address onRamp) private s_onRamps; + // Stores [sourceChainSelector << 160 + offramp] as a pair to allow for + // lookups for specific chain/offramp pairs. + EnumerableSet.UintSet private s_chainSelectorAndOffRamps; + + constructor(address wrappedNative, address armProxy) { + // Zero address indicates unsupported auto-wrapping, therefore, unsupported + // native fee token payments. + s_wrappedNative = wrappedNative; + i_armProxy = armProxy; + } + + // ================================================================ + // │ Message sending │ + // ================================================================ + + /// @inheritdoc IRouterClient + function getFee( + uint64 destinationChainSelector, + Client.EVM2AnyMessage memory message + ) external view returns (uint256 fee) { + if (message.feeToken == address(0)) { + // For empty feeToken return native quote. + message.feeToken = address(s_wrappedNative); + } + address onRamp = s_onRamps[destinationChainSelector]; + if (onRamp == address(0)) revert UnsupportedDestinationChain(destinationChainSelector); + return IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); + } + + /// @notice This functionality has been removed and will revert when called. + function getSupportedTokens( + uint64 chainSelector + ) external view returns (address[] memory) { + if (!isChainSupported(chainSelector)) { + return new address[](0); + } + return IEVM2AnyOnRamp(s_onRamps[uint256(chainSelector)]).getSupportedTokens(chainSelector); + } + + /// @inheritdoc IRouterClient + function isChainSupported( + uint64 chainSelector + ) public view returns (bool) { + return s_onRamps[chainSelector] != address(0); + } + + /// @inheritdoc IRouterClient + function ccipSend( + uint64 destinationChainSelector, + Client.EVM2AnyMessage memory message + ) external payable whenNotCursed returns (bytes32) { + address onRamp = s_onRamps[destinationChainSelector]; + if (onRamp == address(0)) revert UnsupportedDestinationChain(destinationChainSelector); + uint256 feeTokenAmount; + // address(0) signals payment in true native + if (message.feeToken == address(0)) { + // for fee calculation we check the wrapped native price as we wrap + // as part of the native fee coin payment. + message.feeToken = s_wrappedNative; + // We rely on getFee to validate that the feeToken is whitelisted. + feeTokenAmount = IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); + // Ensure sufficient native. + if (msg.value < feeTokenAmount) revert InsufficientFeeTokenAmount(); + // Wrap and send native payment. + // Note we take the whole msg.value regardless if its larger. + feeTokenAmount = msg.value; + IWrappedNative(message.feeToken).deposit{value: feeTokenAmount}(); + IERC20(message.feeToken).safeTransfer(onRamp, feeTokenAmount); + } else { + if (msg.value > 0) revert InvalidMsgValue(); + // We rely on getFee to validate that the feeToken is whitelisted. + feeTokenAmount = IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); + IERC20(message.feeToken).safeTransferFrom(msg.sender, onRamp, feeTokenAmount); + } + + // Transfer the tokens to the token pools. + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + IERC20 token = IERC20(message.tokenAmounts[i].token); + // We rely on getPoolBySourceToken to validate that the token is whitelisted. + token.safeTransferFrom( + msg.sender, + address(IEVM2AnyOnRamp(onRamp).getPoolBySourceToken(destinationChainSelector, token)), + message.tokenAmounts[i].amount + ); + } + + return IEVM2AnyOnRamp(onRamp).forwardFromRouter(destinationChainSelector, message, feeTokenAmount, msg.sender); + } + + // ================================================================ + // │ Message execution │ + // ================================================================ + + /// @inheritdoc IRouter + /// @dev _callWithExactGas protects against return data bombs by capping the return data size at MAX_RET_BYTES. + function routeMessage( + Client.Any2EVMMessage calldata message, + uint16 gasForCallExactCheck, + uint256 gasLimit, + address receiver + ) external override whenNotCursed returns (bool success, bytes memory retData, uint256 gasUsed) { + // We only permit offRamps to call this function. + if (!isOffRamp(message.sourceChainSelector, msg.sender)) revert OnlyOffRamp(); + + // We encode here instead of the offRamps to constrain specifically what functions + // can be called from the router. + bytes memory data = abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message); + + (success, retData, gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( + data, receiver, gasLimit, gasForCallExactCheck, Internal.MAX_RET_BYTES + ); + + emit MessageExecuted(message.messageId, message.sourceChainSelector, msg.sender, keccak256(data)); + return (success, retData, gasUsed); + } + + // @notice Merges a chain selector and offRamp address into a single uint256 by shifting the + // chain selector 160 bits to the left. + function _mergeChainSelectorAndOffRamp( + uint64 sourceChainSelector, + address offRampAddress + ) internal pure returns (uint256) { + return (uint256(sourceChainSelector) << 160) + uint160(offRampAddress); + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Gets the wrapped representation of the native fee coin. + /// @return The address of the ERC20 wrapped native. + function getWrappedNative() external view returns (address) { + return s_wrappedNative; + } + + /// @notice Sets a new wrapped native token. + /// @param wrappedNative The address of the new wrapped native ERC20 token. + function setWrappedNative( + address wrappedNative + ) external onlyOwner { + s_wrappedNative = wrappedNative; + } + + /// @notice Gets the RMN address, formerly known as ARM + /// @return The address of the RMN proxy contract, formerly known as ARM + function getArmProxy() external view returns (address) { + return i_armProxy; + } + + /// @inheritdoc IRouter + function getOnRamp( + uint64 destChainSelector + ) external view returns (address) { + return s_onRamps[destChainSelector]; + } + + function getOffRamps() external view returns (OffRamp[] memory) { + uint256[] memory encodedOffRamps = s_chainSelectorAndOffRamps.values(); + OffRamp[] memory offRamps = new OffRamp[](encodedOffRamps.length); + for (uint256 i = 0; i < encodedOffRamps.length; ++i) { + uint256 encodedOffRamp = encodedOffRamps[i]; + offRamps[i] = + OffRamp({sourceChainSelector: uint64(encodedOffRamp >> 160), offRamp: address(uint160(encodedOffRamp))}); + } + return offRamps; + } + + /// @inheritdoc IRouter + function isOffRamp(uint64 sourceChainSelector, address offRamp) public view returns (bool) { + // We have to encode the sourceChainSelector and offRamp into a uint256 to use as a key in the set. + return s_chainSelectorAndOffRamps.contains(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRamp)); + } + + /// @notice applyRampUpdates applies a set of ramp changes which provides + /// the ability to add new chains and upgrade ramps. + function applyRampUpdates( + OnRamp[] calldata onRampUpdates, + OffRamp[] calldata offRampRemoves, + OffRamp[] calldata offRampAdds + ) external onlyOwner { + // Apply egress updates. + // We permit zero address as way to disable egress. + for (uint256 i = 0; i < onRampUpdates.length; ++i) { + OnRamp memory onRampUpdate = onRampUpdates[i]; + s_onRamps[onRampUpdate.destChainSelector] = onRampUpdate.onRamp; + emit OnRampSet(onRampUpdate.destChainSelector, onRampUpdate.onRamp); + } + + // Apply ingress updates. + for (uint256 i = 0; i < offRampRemoves.length; ++i) { + uint64 sourceChainSelector = offRampRemoves[i].sourceChainSelector; + address offRampAddress = offRampRemoves[i].offRamp; + + // If the selector-offRamp pair does not exist, revert. + if (!s_chainSelectorAndOffRamps.remove(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRampAddress))) { + revert OffRampMismatch(sourceChainSelector, offRampAddress); + } + + emit OffRampRemoved(sourceChainSelector, offRampAddress); + } + + for (uint256 i = 0; i < offRampAdds.length; ++i) { + uint64 sourceChainSelector = offRampAdds[i].sourceChainSelector; + address offRampAddress = offRampAdds[i].offRamp; + + if (s_chainSelectorAndOffRamps.add(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRampAddress))) { + emit OffRampAdded(sourceChainSelector, offRampAddress); + } + } + } + + /// @notice Provides the ability for the owner to recover any tokens accidentally + /// sent to this contract. + /// @dev Must be onlyOwner to avoid malicious token contract calls. + /// @param tokenAddress ERC20-token to recover + /// @param to Destination address to send the tokens to. + function recoverTokens(address tokenAddress, address to, uint256 amount) external onlyOwner { + if (to == address(0)) revert InvalidRecipientAddress(to); + + if (tokenAddress == address(0)) { + (bool success,) = to.call{value: amount}(""); + if (!success) revert FailedToSendValue(); + return; + } + IERC20(tokenAddress).safeTransfer(to, amount); + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Ensure that the RMN has not cursed the network. + modifier whenNotCursed() { + if (IRMN(i_armProxy).isCursed()) revert BadARMSignal(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol new file mode 100644 index 0000000..56f3cd1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IRouterClient} from "../interfaces/IRouterClient.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Client} from "../libraries/Client.sol"; +import {CCIPReceiver} from "./CCIPReceiver.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +// @notice Example of a client which supports EVM/non-EVM chains +// @dev If chain specific logic is required for different chain families (e.g. particular +// decoding the bytes sender for authorization checks), it may be required to point to a helper +// authorization contract unless all chain families are known up front. +// @dev If contract does not implement IAny2EVMMessageReceiver and IERC165, +// and tokens are sent to it, ccipReceive will not be called but tokens will be transferred. +// @dev If the client is upgradeable you have significantly more flexibility and +// can avoid storage based options like the below contract uses. However it's +// worth carefully considering how the trust assumptions of your client dapp will +// change if you introduce upgradeability. An immutable dapp building on top of CCIP +// like the example below will inherit the trust properties of CCIP (i.e. the oracle network). +// @dev The receiver's are encoded offchain and passed as direct arguments to permit supporting +// new chain family receivers (e.g. a Solana encoded receiver address) without upgrading. +contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { + error InvalidChain(uint64 chainSelector); + + event MessageSent(bytes32 messageId); + event MessageReceived(bytes32 messageId); + + // Current feeToken + IERC20 public s_feeToken; + // Below is a simplistic example (same params for all messages) of using storage to allow for new options without + // upgrading the dapp. Note that extra args are chain family specific (e.g. gasLimit is EVM specific etc.). + // and will always be backwards compatible i.e. upgrades are opt-in. + // Offchain we can compute the V1 extraArgs: + // Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); + // bytes memory encodedV1ExtraArgs = Client._argsToBytes(extraArgs); + // Then later compute V2 extraArgs, for example if a refund feature was added: + // Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 300_000, destRefundAddress: 0x1234}); + // bytes memory encodedV2ExtraArgs = Client._argsToBytes(extraArgs); + // and update storage with the new args. + // If different options are required for different messages, for example different gas limits, + // one can simply key based on (chainSelector, messageType) instead of only chainSelector. + mapping(uint64 destChainSelector => bytes extraArgsBytes) public s_chains; + + constructor(IRouterClient router, IERC20 feeToken) CCIPReceiver(address(router)) { + s_feeToken = feeToken; + s_feeToken.approve(address(router), type(uint256).max); + } + + function enableChain(uint64 chainSelector, bytes memory extraArgs) external onlyOwner { + s_chains[chainSelector] = extraArgs; + } + + function disableChain( + uint64 chainSelector + ) external onlyOwner { + delete s_chains[chainSelector]; + } + + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external virtual override onlyRouter validChain(message.sourceChainSelector) { + // Extremely important to ensure only router calls this. + // Tokens in message if any will be transferred to this contract + // TODO: Validate sender/origin chain and process message and/or tokens. + _ccipReceive(message); + } + + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { + emit MessageReceived(message.messageId); + } + + /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native asset. + function sendDataPayNative( + uint64 destChainSelector, + bytes memory receiver, + bytes memory data + ) external validChain(destChainSelector) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: receiver, + data: data, + tokenAmounts: tokenAmounts, + extraArgs: s_chains[destChainSelector], + feeToken: address(0) // We leave the feeToken empty indicating we'll pay raw native. + }); + bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend{ + value: IRouterClient(i_ccipRouter).getFee(destChainSelector, message) + }(destChainSelector, message); + emit MessageSent(messageId); + } + + /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient feeToken. + function sendDataPayFeeToken( + uint64 destChainSelector, + bytes memory receiver, + bytes memory data + ) external validChain(destChainSelector) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: receiver, + data: data, + tokenAmounts: tokenAmounts, + extraArgs: s_chains[destChainSelector], + feeToken: address(s_feeToken) + }); + // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); + // Can decide if fee is acceptable. + // address(this) must have sufficient feeToken or the send will revert. + bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); + emit MessageSent(messageId); + } + + /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native token. + function sendDataAndTokens( + uint64 destChainSelector, + bytes memory receiver, + bytes memory data, + Client.EVMTokenAmount[] memory tokenAmounts + ) external validChain(destChainSelector) { + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); + IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); + } + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: receiver, + data: data, + tokenAmounts: tokenAmounts, + extraArgs: s_chains[destChainSelector], + feeToken: address(s_feeToken) + }); + // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); + // Can decide if fee is acceptable. + // address(this) must have sufficient feeToken or the send will revert. + bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); + emit MessageSent(messageId); + } + + // @notice user sends tokens to a receiver + // Approvals can be optimized with a whitelist of tokens and inf approvals if desired. + function sendTokens( + uint64 destChainSelector, + bytes memory receiver, + Client.EVMTokenAmount[] memory tokenAmounts + ) external validChain(destChainSelector) { + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); + IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); + } + bytes memory data; + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: receiver, + data: data, + tokenAmounts: tokenAmounts, + extraArgs: s_chains[destChainSelector], + feeToken: address(s_feeToken) + }); + // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); + // Can decide if fee is acceptable. + // address(this) must have sufficient feeToken or the send will revert. + bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); + emit MessageSent(messageId); + } + + modifier validChain( + uint64 chainSelector + ) { + if (s_chains[chainSelector].length == 0) revert InvalidChain(chainSelector); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol new file mode 100644 index 0000000..8caeb3f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; + +import {Client} from "../libraries/Client.sol"; + +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +/// @title CCIPReceiver - Base contract for CCIP applications that can receive messages. +abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 { + address internal immutable i_ccipRouter; + + constructor( + address router + ) { + if (router == address(0)) revert InvalidRouter(address(0)); + i_ccipRouter = router; + } + + /// @notice IERC165 supports an interfaceId + /// @param interfaceId The interfaceId to check + /// @return true if the interfaceId is supported + /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver + /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId + /// This allows CCIP to check if ccipReceive is available before calling it. + /// If this returns false or reverts, only tokens are transferred to the receiver. + /// If this returns true, tokens are transferred and ccipReceive is called atomically. + /// Additionally, if the receiver address does not have code associated with + /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } + + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external virtual override onlyRouter { + _ccipReceive(message); + } + + /// @notice Override this function in your implementation. + /// @param message Any2EVMMessage + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal virtual; + + ///////////////////////////////////////////////////////////////////// + // Plumbing + ///////////////////////////////////////////////////////////////////// + + /// @notice Return the current router + /// @return CCIP router address + function getRouter() public view virtual returns (address) { + return address(i_ccipRouter); + } + + error InvalidRouter(address router); + + /// @dev only calls from the set router are accepted. + modifier onlyRouter() { + if (msg.sender != getRouter()) revert InvalidRouter(msg.sender); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol new file mode 100644 index 0000000..dbe8550 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IRouterClient} from "../interfaces/IRouterClient.sol"; + +import {Client} from "../libraries/Client.sol"; +import {CCIPClientExample} from "./CCIPClientExample.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; + +contract DefensiveExample is CCIPClientExample { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + using SafeERC20 for IERC20; + + error OnlySelf(); + error ErrorCase(); + error MessageNotFailed(bytes32 messageId); + + event MessageFailed(bytes32 indexed messageId, bytes reason); + event MessageSucceeded(bytes32 indexed messageId); + event MessageRecovered(bytes32 indexed messageId); + + // Example error code, could have many different error codes. + enum ErrorCode { + // RESOLVED is first so that the default value is resolved. + RESOLVED, + // Could have any number of error codes here. + BASIC + } + + // The message contents of failed messages are stored here. + mapping(bytes32 messageId => Client.Any2EVMMessage contents) public s_messageContents; + + // Contains failed messages and their state. + EnumerableMap.Bytes32ToUintMap internal s_failedMessages; + + // This is used to simulate a revert in the processMessage function. + bool internal s_simRevert = false; + + constructor(IRouterClient router, IERC20 feeToken) CCIPClientExample(router, feeToken) {} + + /// @notice The entrypoint for the CCIP router to call. This function should + /// never revert, all errors should be handled internally in this contract. + /// @param message The message to process. + /// @dev Extremely important to ensure only router calls this. + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external override onlyRouter validChain(message.sourceChainSelector) { + try this.processMessage(message) {} + catch (bytes memory err) { + // Could set different error codes based on the caught error. Each could be + // handled differently. + s_failedMessages.set(message.messageId, uint256(ErrorCode.BASIC)); + s_messageContents[message.messageId] = message; + // Don't revert so CCIP doesn't revert. Emit event instead. + // The message can be retried later without having to do manual execution of CCIP. + emit MessageFailed(message.messageId, err); + return; + } + emit MessageSucceeded(message.messageId); + } + + /// @notice This function the entrypoint for this contract to process messages. + /// @param message The message to process. + /// @dev This example just sends the tokens to the owner of this contracts. More + /// interesting functions could be implemented. + /// @dev It has to be external because of the try/catch. + function processMessage( + Client.Any2EVMMessage calldata message + ) external onlySelf validChain(message.sourceChainSelector) { + // Simulate a revert + if (s_simRevert) revert ErrorCase(); + + // Send tokens to the owner + for (uint256 i = 0; i < message.destTokenAmounts.length; ++i) { + IERC20(message.destTokenAmounts[i].token).safeTransfer(owner(), message.destTokenAmounts[i].amount); + } + // Do other things that might revert + } + + /// @notice This function is callable by the owner when a message has failed + /// to unblock the tokens that are associated with that message. + /// @dev This function is only callable by the owner. + function retryFailedMessage(bytes32 messageId, address tokenReceiver) external onlyOwner { + if (s_failedMessages.get(messageId) != uint256(ErrorCode.BASIC)) revert MessageNotFailed(messageId); + // Set the error code to 0 to disallow reentry and retry the same failed message + // multiple times. + s_failedMessages.set(messageId, uint256(ErrorCode.RESOLVED)); + + // Do stuff to retry message, potentially just releasing the associated tokens + Client.Any2EVMMessage memory message = s_messageContents[messageId]; + + // send the tokens to the receiver as escape hatch + for (uint256 i = 0; i < message.destTokenAmounts.length; ++i) { + IERC20(message.destTokenAmounts[i].token).safeTransfer(tokenReceiver, message.destTokenAmounts[i].amount); + } + + emit MessageRecovered(messageId); + } + + // An example function to demonstrate recovery + function setSimRevert( + bool simRevert + ) external onlyOwner { + s_simRevert = simRevert; + } + + modifier onlySelf() { + if (msg.sender != address(this)) revert OnlySelf(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol new file mode 100644 index 0000000..5bb0193 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {IRouterClient} from "../interfaces/IRouterClient.sol"; +import {IWrappedNative} from "../interfaces/IWrappedNative.sol"; + +import {Client} from "./../libraries/Client.sol"; +import {CCIPReceiver} from "./CCIPReceiver.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +//solhint-disable interface-starts-with-i +interface CCIPRouter { + function getWrappedNative() external view returns (address); +} + +/// @notice A contract that can send raw ether cross-chain using CCIP. +/// Since CCIP only supports ERC-20 token transfers, this contract accepts +/// normal ether, wraps it, and uses CCIP to send it cross-chain. +/// On the receiving side, the wrapped ether is unwrapped and sent to the final receiver. +/// @notice This contract only supports chains where the wrapped native contract +/// is the WETH contract (i.e not WMATIC, or WAVAX, etc.). This is because the +/// receiving contract will always unwrap the ether using it's local wrapped native contract. +/// @dev This contract is both a sender and a receiver. This same contract can be +/// deployed on source and destination chains to facilitate cross-chain ether transfers +/// and act as a sender and a receiver. +/// @dev This contract is intentionally ownerless and permissionless. This contract +/// will never hold any excess funds, native or otherwise, when used correctly. +contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { + using SafeERC20 for IERC20; + + error InvalidTokenAmounts(uint256 gotAmounts); + error InvalidToken(address gotToken, address expectedToken); + error TokenAmountNotEqualToMsgValue(uint256 gotAmount, uint256 msgValue); + + string public constant override typeAndVersion = "EtherSenderReceiver 1.5.0"; + + /// @notice The wrapped native token address. + /// @dev If the wrapped native token address changes on the router, this contract will need to be redeployed. + IWrappedNative public immutable i_weth; + + /// @param router The CCIP router address. + constructor( + address router + ) CCIPReceiver(router) { + i_weth = IWrappedNative(CCIPRouter(router).getWrappedNative()); + i_weth.approve(router, type(uint256).max); + } + + /// @notice Need this in order to unwrap correctly. + receive() external payable {} + + /// @notice Get the fee for sending a message to a destination chain. + /// This is mirrored from the router for convenience, construct the appropriate + /// message and get it's fee. + /// @param destinationChainSelector The destination chainSelector + /// @param message The cross-chain CCIP message including data and/or tokens + /// @return fee returns execution fee for the message + /// delivery to destination chain, denominated in the feeToken specified in the message. + /// @dev Reverts with appropriate reason upon invalid message. + function getFee( + uint64 destinationChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 fee) { + Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); + + return IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); + } + + /// @notice Send raw native tokens cross-chain. + /// @param destinationChainSelector The destination chain selector. + /// @param message The CCIP message with the following fields correctly set: + /// - bytes receiver: The _contract_ address on the destination chain that will receive the wrapped ether. + /// The caller must ensure that this contract address is correct, otherwise funds may be lost forever. + /// - address feeToken: The fee token address. Must be address(0) for native tokens, or a supported CCIP fee token otherwise (i.e, LINK token). + /// In the event a feeToken is set, we will transferFrom the caller the fee amount before sending the message, in order to forward them to the router. + /// - EVMTokenAmount[] tokenAmounts: The tokenAmounts array must contain a single element with the following fields: + /// - uint256 amount: The amount of ether to send. + /// There are a couple of cases here that depend on the fee token specified: + /// 1. If feeToken == address(0), the fee must be included in msg.value. Therefore tokenAmounts[0].amount must be less than msg.value, + /// and the difference will be used as the fee. + /// 2. If feeToken != address(0), the fee is not included in msg.value, and tokenAmounts[0].amount must be equal to msg.value. + /// these fees to the CCIP router. + /// @return messageId The CCIP message ID. + function ccipSend( + uint64 destinationChainSelector, + Client.EVM2AnyMessage calldata message + ) external payable returns (bytes32) { + _validateFeeToken(message); + Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); + + i_weth.deposit{value: validatedMessage.tokenAmounts[0].amount}(); + + uint256 fee = IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); + if (validatedMessage.feeToken != address(0)) { + // If the fee token is not native, we need to transfer the fee to this contract and re-approve it to the router. + // Its not possible to have any leftover tokens in this path because we transferFrom the exact fee that CCIP + // requires from the caller. + IERC20(validatedMessage.feeToken).safeTransferFrom(msg.sender, address(this), fee); + + // We gave an infinite approval of weth to the router in the constructor. + if (validatedMessage.feeToken != address(i_weth)) { + IERC20(validatedMessage.feeToken).approve(getRouter(), fee); + } + + return IRouterClient(getRouter()).ccipSend(destinationChainSelector, validatedMessage); + } + + // We don't want to keep any excess ether in this contract, so we send over the entire address(this).balance as the fee. + // CCIP will revert if the fee is insufficient, so we don't need to check here. + return IRouterClient(getRouter()).ccipSend{value: address(this).balance}(destinationChainSelector, validatedMessage); + } + + /// @notice Validate the message content. + /// @dev Only allows a single token to be sent. Always overwritten to be address(i_weth) + /// and receiver is always msg.sender. + function _validatedMessage( + Client.EVM2AnyMessage calldata message + ) internal view returns (Client.EVM2AnyMessage memory) { + Client.EVM2AnyMessage memory validatedMessage = message; + + if (validatedMessage.tokenAmounts.length != 1) { + revert InvalidTokenAmounts(validatedMessage.tokenAmounts.length); + } + + validatedMessage.data = abi.encode(msg.sender); + validatedMessage.tokenAmounts[0].token = address(i_weth); + + return validatedMessage; + } + + function _validateFeeToken( + Client.EVM2AnyMessage calldata message + ) internal view { + uint256 tokenAmount = message.tokenAmounts[0].amount; + + if (message.feeToken != address(0)) { + // If the fee token is NOT native, then the token amount must be equal to msg.value. + // This is done to ensure that there is no leftover ether in this contract. + if (msg.value != tokenAmount) { + revert TokenAmountNotEqualToMsgValue(tokenAmount, msg.value); + } + } + } + + /// @notice Receive the wrapped ether, unwrap it, and send it to the specified EOA in the data field. + /// @param message The CCIP message containing the wrapped ether amount and the final receiver. + /// @dev The code below should never revert if the message being is valid according + /// to the above _validatedMessage and _validateFeeToken functions. + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { + address receiver = abi.decode(message.data, (address)); + + if (message.destTokenAmounts.length != 1) { + revert InvalidTokenAmounts(message.destTokenAmounts.length); + } + + if (message.destTokenAmounts[0].token != address(i_weth)) { + revert InvalidToken(message.destTokenAmounts[0].token, address(i_weth)); + } + + uint256 tokenAmount = message.destTokenAmounts[0].amount; + i_weth.withdraw(tokenAmount); + + // it is possible that the below call may fail if receiver.code.length > 0 and the contract + // doesn't e.g have a receive() or a fallback() function. + (bool success,) = payable(receiver).call{value: tokenAmount}(""); + if (!success) { + // We have a few options here: + // 1. Revert: this is bad generally because it may mean that these tokens are stuck. + // 2. Store the tokens in a mapping and allow the user to withdraw them with another tx. + // 3. Send WETH to the receiver address. + // We opt for (3) here because at least the receiver will have the funds and can unwrap them if needed. + // However it is worth noting that if receiver is actually a contract AND the contract _cannot_ withdraw + // the WETH, then the WETH will be stuck in this contract. + i_weth.deposit{value: tokenAmount}(); + i_weth.transfer(receiver, tokenAmount); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol new file mode 100644 index 0000000..3fd3eec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IRouterClient} from "../interfaces/IRouterClient.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Client} from "../libraries/Client.sol"; +import {CCIPReceiver} from "./CCIPReceiver.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +/// @title PingPongDemo - A simple ping-pong contract for demonstrating cross-chain communication +contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { + event Ping(uint256 pingPongCount); + event Pong(uint256 pingPongCount); + event OutOfOrderExecutionChange(bool isOutOfOrder); + + // Default gas limit used for EVMExtraArgsV2 construction + uint64 private constant DEFAULT_GAS_LIMIT = 200_000; + + // The chain ID of the counterpart ping pong contract + uint64 internal s_counterpartChainSelector; + // The contract address of the counterpart ping pong contract + address internal s_counterpartAddress; + // Pause ping-ponging + bool private s_isPaused; + // The fee token used to pay for CCIP transactions + IERC20 internal s_feeToken; + // Allowing out of order execution + bool private s_outOfOrderExecution; + + constructor(address router, IERC20 feeToken) CCIPReceiver(router) { + s_isPaused = false; + s_feeToken = feeToken; + s_feeToken.approve(address(router), type(uint256).max); + } + + function typeAndVersion() external pure virtual returns (string memory) { + return "PingPongDemo 1.5.0"; + } + + function setCounterpart(uint64 counterpartChainSelector, address counterpartAddress) external onlyOwner { + s_counterpartChainSelector = counterpartChainSelector; + s_counterpartAddress = counterpartAddress; + } + + function startPingPong() external onlyOwner { + s_isPaused = false; + _respond(1); + } + + function _respond( + uint256 pingPongCount + ) internal virtual { + if (pingPongCount & 1 == 1) { + emit Ping(pingPongCount); + } else { + emit Pong(pingPongCount); + } + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(s_counterpartAddress), + data: abi.encode(pingPongCount), + tokenAmounts: new Client.EVMTokenAmount[](0), + extraArgs: Client._argsToBytes( + Client.EVMExtraArgsV2({gasLimit: uint256(DEFAULT_GAS_LIMIT), allowOutOfOrderExecution: s_outOfOrderExecution}) + ), + feeToken: address(s_feeToken) + }); + IRouterClient(getRouter()).ccipSend(s_counterpartChainSelector, message); + } + + function _ccipReceive( + Client.Any2EVMMessage memory message + ) internal override { + uint256 pingPongCount = abi.decode(message.data, (uint256)); + if (!s_isPaused) { + _respond(pingPongCount + 1); + } + } + + ///////////////////////////////////////////////////////////////////// + // Plumbing + ///////////////////////////////////////////////////////////////////// + + function getCounterpartChainSelector() external view returns (uint64) { + return s_counterpartChainSelector; + } + + function setCounterpartChainSelector( + uint64 chainSelector + ) external onlyOwner { + s_counterpartChainSelector = chainSelector; + } + + function getCounterpartAddress() external view returns (address) { + return s_counterpartAddress; + } + + function getFeeToken() external view returns (IERC20) { + return s_feeToken; + } + + function setCounterpartAddress( + address addr + ) external onlyOwner { + s_counterpartAddress = addr; + } + + function isPaused() external view returns (bool) { + return s_isPaused; + } + + function setPaused( + bool pause + ) external onlyOwner { + s_isPaused = pause; + } + + function getOutOfOrderExecution() external view returns (bool) { + return s_outOfOrderExecution; + } + + function setOutOfOrderExecution( + bool outOfOrderExecution + ) external onlyOwner { + s_outOfOrderExecution = outOfOrderExecution; + emit OutOfOrderExecutionChange(outOfOrderExecution); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol new file mode 100644 index 0000000..e66e2f5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -0,0 +1,624 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ICapabilitiesRegistry} from "../interfaces/ICapabilitiesRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Internal} from "../libraries/Internal.sol"; + +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice CCIPHome stores the configuration for the CCIP capability. +/// We have two classes of configuration: chain configuration and DON (in the CapabilitiesRegistry sense) configuration. +/// Each chain will have a single configuration which includes information like the router address. +/// @dev This contract is a state machine with the following states: +/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. +/// [0, 0] +/// +/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. +/// [0, 1] +/// +/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. +/// [1, 0] +/// +/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. +/// [1, 1] +/// +/// The following state transitions are allowed: +/// - Init -> Candidate: setCandidate() +/// - Candidate -> Active: promoteCandidateAndRevokeActive() +/// - Candidate -> Candidate: setCandidate() +/// - Candidate -> Init: revokeCandidate() +/// - Active -> ActiveAndCandidate: setCandidate() +/// - Active -> Init: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: revokeCandidate() +/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() +/// +/// This means the following calls are not allowed at the following states: +/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. +/// - Init: revokeCandidate(), as there is no config to revoke +/// - Active: revokeCandidate(), as there is no candidate to revoke +/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but +/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable +/// config as candidate and promote that, but fully clearing it is cleaner. +/// +/// ┌─────────────┐ setCandidate ┌─────────────┐ +/// │ ├───────────────────►│ │ setCandidate +/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ +/// │ │ ┌─────────────────┤ │ +/// └─────────────┘ │ promote- └─────────────┘ +/// ▲ │ Candidate +/// promote- │ │ +/// Candidate │ │ +/// │ │ +/// ┌──────────┴──┐ │ promote- ┌─────────────┐ +/// │ │◄─┘ Candidate OR │ Active & │ setCandidate +/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ +/// │ ├───────────────────►│ │ +/// └─────────────┘ setSecondary └─────────────┘ +/// +contract CCIPHome is OwnerIsCreator, ITypeAndVersion, ICapabilityConfiguration, IERC165 { + using EnumerableSet for EnumerableSet.UintSet; + + event ChainConfigRemoved(uint64 chainSelector); + event ChainConfigSet(uint64 chainSelector, ChainConfig chainConfig); + event ConfigSet(bytes32 indexed configDigest, uint32 version, OCR3Config config); + event ActiveConfigRevoked(bytes32 indexed configDigest); + event CandidateConfigRevoked(bytes32 indexed configDigest); + event ConfigPromoted(bytes32 indexed configDigest); + + error NodeNotInRegistry(bytes32 p2pId); + error ChainSelectorNotFound(uint64 chainSelector); + error FChainMustBePositive(); + error ChainSelectorNotSet(); + error InvalidPluginType(); + error OfframpAddressCannotBeZero(); + error FChainTooHigh(uint256 fChain, uint256 FRoleDON); + error TooManySigners(); + error FTooHigh(); + error RMNHomeAddressCannotBeZero(); + error InvalidNode(OCR3Node node); + error NotEnoughTransmitters(uint256 got, uint256 minimum); + error OnlyCapabilitiesRegistryCanCall(); + error ZeroAddressNotAllowed(); + error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); + error CanOnlySelfCall(); + error RevokingZeroDigestNotAllowed(); + error NoOpStateTransitionNotAllowed(); + error InvalidSelector(bytes4 selector); + error DONIdMismatch(uint32 callDonId, uint32 capabilityRegistryDonId); + + error InvalidStateTransition( + bytes32 currentActiveDigest, + bytes32 currentCandidateDigest, + bytes32 proposedActiveDigest, + bytes32 proposedCandidateDigest + ); + + /// @notice Represents an oracle node in OCR3 configs part of the role DON. + /// Every configured node should be a signer, but does not have to be a transmitter. + struct OCR3Node { + bytes32 p2pId; // Peer2Peer connection ID of the oracle + bytes signerKey; // On-chain signer public key + bytes transmitterKey; // On-chain transmitter public key. Can be set to empty bytes to represent that the node is a signer but not a transmitter. + } + + /// @notice OCR3 configuration. + /// Note that FRoleDON >= fChain, since FRoleDON represents the role DON, and fChain represents sub-committees. + /// FRoleDON values are typically identical across multiple OCR3 configs since the chains pertain to one role DON, + /// but FRoleDON values can change across OCR3 configs to indicate role DON splits. + struct OCR3Config { + Internal.OCRPluginType pluginType; // ─╮ The plugin that the configuration is for. + uint64 chainSelector; // │ The (remote) chain that the configuration is for. + uint8 FRoleDON; // │ The "big F" parameter for the role DON. + uint64 offchainConfigVersion; // ──────╯ The version of the exec offchain configuration. + bytes offrampAddress; // The remote chain offramp address. + bytes rmnHomeAddress; // The home chain RMN home address. + OCR3Node[] nodes; // Keys & IDs of nodes part of the role DON + bytes offchainConfig; // The offchain configuration for the OCR3 plugin. Protobuf encoded. + } + + struct VersionedConfig { + uint32 version; + bytes32 configDigest; + OCR3Config config; + } + + /// @notice Chain configuration. + /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. + struct ChainConfig { + bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capabilities registry. + uint8 fChain; // The fault tolerance parameter of the chain. + bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. + } + + /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. + struct ChainConfigArgs { + uint64 chainSelector; + ChainConfig chainConfig; + } + + string public constant override typeAndVersion = "CCIPHome 1.6.0-dev"; + + /// @dev A prefix added to all config digests that is unique to the implementation + uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000a00..00 + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); + /// @dev 256 is the hard limit due to the bit encoding of their indexes into a uint256. + uint256 internal constant MAX_NUM_ORACLES = 256; + + /// @notice Used for encoding the config digest prefix + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + /// @notice The max number of configs that can be active at the same time. + uint256 private constant MAX_CONCURRENT_CONFIGS = 2; + /// @notice Helper to identify the zero config digest with less casting. + bytes32 private constant ZERO_DIGEST = bytes32(uint256(0)); + + /// @dev The canonical capabilities registry address. + address internal immutable i_capabilitiesRegistry; + + /// @dev chain configuration for each chain that CCIP is deployed on. + mapping(uint64 chainSelector => ChainConfig chainConfig) private s_chainConfigurations; + + /// @dev All chains that are configured. + EnumerableSet.UintSet private s_remoteChainSelectors; + + /// @notice This array holds the configs. + /// @dev A DonID covers a single chain, and the plugin type is used to differentiate between the commit and execution + mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => VersionedConfig[MAX_CONCURRENT_CONFIGS])) private + s_configs; + + /// @notice The total number of configs ever set, used for generating the version of the configs. + /// @dev Used to ensure unique digests across all configurations. + uint32 private s_currentVersion = 0; + /// @notice The index of the active config on a per-don and per-plugin basis. + mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => uint32)) private s_activeConfigIndexes; + + /// @notice Constructor for the CCIPHome contract takes in the address of the capabilities registry. This address + /// is the only allowed caller to mutate the configuration through beforeCapabilityConfigSet. + constructor( + address capabilitiesRegistry + ) { + if (capabilitiesRegistry == address(0)) { + revert ZeroAddressNotAllowed(); + } + i_capabilitiesRegistry = capabilitiesRegistry; + } + + // ================================================================ + // │ Capability Registry │ + // ================================================================ + + /// @notice Returns the capabilities registry address. + /// @return The capabilities registry address. + function getCapabilityRegistry() external view returns (address) { + return i_capabilitiesRegistry; + } + + /// @inheritdoc IERC165 + /// @dev Required for the capabilities registry to recognize this contract. + function supportsInterface( + bytes4 interfaceId + ) external pure override returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; + } + + /// @notice Called by the registry prior to the config being set for a particular DON. + /// @dev precondition Requires destination chain config to be set + function beforeCapabilityConfigSet( + bytes32[] calldata, // nodes + bytes calldata update, + // Config count is unused because we don't want to invalidate a config on blue/green promotions so we keep track of + // the actual newly submitted configs instead of the number of config mutations. + uint64, // config count + uint32 donId + ) external override { + if (msg.sender != i_capabilitiesRegistry) { + revert OnlyCapabilitiesRegistryCanCall(); + } + + bytes4 selector = bytes4(update[:4]); + // We only allow self-calls to the following approved methods + if ( + selector != this.setCandidate.selector && selector != this.revokeCandidate.selector + && selector != this.promoteCandidateAndRevokeActive.selector + ) { + revert InvalidSelector(selector); + } + + // We validate that the call contains the correct DON ID. The DON ID is always the first function argument. + uint256 callDonId = abi.decode(update[4:36], (uint256)); + if (callDonId != donId) { + revert DONIdMismatch(uint32(callDonId), donId); + } + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory retData) = address(this).call(update); + // if not successful, revert with the original revert + if (!success) { + assembly { + revert(add(retData, 0x20), returndatasize()) + } + } + } + + /// @inheritdoc ICapabilityConfiguration + /// @dev The CCIP capability will fetch the configuration needed directly from this contract. + /// The offchain syncer will call this function, so its important that it doesn't revert. + function getCapabilityConfiguration( + uint32 /* donId */ + ) external pure override returns (bytes memory configuration) { + return bytes(""); + } + + // ================================================================ + // │ Getters │ + // ================================================================ + + /// @notice Returns the current active and candidate config digests. + /// @dev Can be bytes32(0) if no config has been set yet or it has been revoked. + /// @param donId The key of the plugin to get the config digests for. + /// @return activeConfigDigest The digest of the active config. + /// @return candidateConfigDigest The digest of the candidate config. + function getConfigDigests( + uint32 donId, + Internal.OCRPluginType pluginType + ) public view returns (bytes32 activeConfigDigest, bytes32 candidateConfigDigest) { + return ( + s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest, + s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest + ); + } + + /// @notice Returns the active config digest for for a given key. + /// @param donId The key of the plugin to get the config digests for. + function getActiveDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { + return s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest; + } + + /// @notice Returns the candidate config digest for for a given key. + /// @param donId The key of the plugin to get the config digests for. + function getCandidateDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { + return s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest; + } + + /// @notice The offchain code can use this to fetch an old config which might still be in use by some remotes. Use + /// in case one of the configs is too large to be returnable by one of the other getters. + /// @param donId The unique key for the DON that the configuration applies to. + /// @param configDigest The digest of the config to fetch. + /// @return versionedConfig The config and its version. + /// @return ok True if the config was found, false otherwise. + function getConfig( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes32 configDigest + ) external view returns (VersionedConfig memory versionedConfig, bool ok) { + for (uint256 i = 0; i < MAX_CONCURRENT_CONFIGS; ++i) { + // We never want to return true for a zero digest, even if the caller is asking for it, as this can expose old + // config state that is invalid. + if (s_configs[donId][pluginType][i].configDigest == configDigest && configDigest != ZERO_DIGEST) { + return (s_configs[donId][pluginType][i], true); + } + } + // versionConfig is uninitialized so it contains default values. + return (versionedConfig, false); + } + + /// @notice Returns the active and candidate configuration for a given plugin key. + /// @param donId The unique key for the DON that the configuration applies to. + /// @return activeConfig The active configuration. + /// @return candidateConfig The candidate configuration. + function getAllConfigs( + uint32 donId, + Internal.OCRPluginType pluginType + ) external view returns (VersionedConfig memory activeConfig, VersionedConfig memory candidateConfig) { + VersionedConfig memory storedActiveConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; + if (storedActiveConfig.configDigest != ZERO_DIGEST) { + activeConfig = storedActiveConfig; + } + + VersionedConfig memory storedCandidateConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; + if (storedCandidateConfig.configDigest != ZERO_DIGEST) { + candidateConfig = storedCandidateConfig; + } + + return (activeConfig, candidateConfig); + } + + // ================================================================ + // │ State transitions │ + // ================================================================ + + /// @notice Sets a new config as the candidate config. Does not influence the active config. + /// @param donId The key of the plugin to set the config for. + /// @return newConfigDigest The digest of the new config. + function setCandidate( + uint32 donId, + Internal.OCRPluginType pluginType, + OCR3Config calldata config, + bytes32 digestToOverwrite + ) external returns (bytes32 newConfigDigest) { + _onlySelfCall(); + _validateConfig(config); + + bytes32 existingDigest = getCandidateDigest(donId, pluginType); + + if (existingDigest != digestToOverwrite) { + revert ConfigDigestMismatch(existingDigest, digestToOverwrite); + } + + // are we going to overwrite a config? If so, emit an event. + if (existingDigest != ZERO_DIGEST) { + emit CandidateConfigRevoked(digestToOverwrite); + } + + uint32 newVersion = ++s_currentVersion; + newConfigDigest = _calculateConfigDigest(donId, pluginType, abi.encode(config), newVersion); + + VersionedConfig storage existingConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; + existingConfig.configDigest = newConfigDigest; + existingConfig.version = newVersion; + existingConfig.config = config; + + emit ConfigSet(newConfigDigest, newVersion, config); + + return newConfigDigest; + } + + /// @notice Revokes a specific config by digest. + /// @param donId The key of the plugin to revoke the config for. + /// @param configDigest The digest of the config to revoke. This is done to prevent accidental revokes. + function revokeCandidate(uint32 donId, Internal.OCRPluginType pluginType, bytes32 configDigest) external { + _onlySelfCall(); + + if (configDigest == ZERO_DIGEST) { + revert RevokingZeroDigestNotAllowed(); + } + + uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); + if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != configDigest) { + revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, configDigest); + } + + emit CandidateConfigRevoked(configDigest); + // Delete only the digest, as that's what's used to determine if a config is active. This means the actual + // config stays in storage which should significantly reduce the gas cost of overwriting that storage space in + // the future. + delete s_configs[donId][pluginType][candidateConfigIndex].configDigest; + } + + /// @notice Promotes the candidate config to the active config and revokes the active config. + /// @param donId The key of the plugin to promote the config for. + /// @param digestToPromote The digest of the config to promote. + function promoteCandidateAndRevokeActive( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes32 digestToPromote, + bytes32 digestToRevoke + ) external { + _onlySelfCall(); + + if (digestToPromote == ZERO_DIGEST && digestToRevoke == ZERO_DIGEST) { + revert NoOpStateTransitionNotAllowed(); + } + + uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); + if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != digestToPromote) { + revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, digestToPromote); + } + + VersionedConfig storage activeConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; + if (activeConfig.configDigest != digestToRevoke) { + revert ConfigDigestMismatch(activeConfig.configDigest, digestToRevoke); + } + + delete activeConfig.configDigest; + + s_activeConfigIndexes[donId][pluginType] ^= 1; + if (digestToRevoke != ZERO_DIGEST) { + emit ActiveConfigRevoked(digestToRevoke); + } + emit ConfigPromoted(digestToPromote); + } + + /// @notice Calculates the config digest for a given plugin key, static config, and version. + /// @param donId The key of the plugin to calculate the digest for. + /// @param staticConfig The static part of the config. + /// @param version The version of the config. + /// @return The calculated config digest. + function _calculateConfigDigest( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes memory staticConfig, + uint32 version + ) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256( + bytes.concat( + abi.encode(bytes32("EVM"), block.chainid, address(this), donId, pluginType, version), staticConfig + ) + ) + ) & ~PREFIX_MASK + ) + ); + } + + function _getActiveIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { + return s_activeConfigIndexes[donId][pluginType]; + } + + function _getCandidateIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { + return s_activeConfigIndexes[donId][pluginType] ^ 1; + } + + // ================================================================ + // │ Validation │ + // ================================================================ + + function _validateConfig( + OCR3Config memory cfg + ) internal view { + if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); + if (cfg.pluginType != Internal.OCRPluginType.Commit && cfg.pluginType != Internal.OCRPluginType.Execution) { + revert InvalidPluginType(); + } + if (cfg.offrampAddress.length == 0 || keccak256(cfg.offrampAddress) == EMPTY_ENCODED_ADDRESS_HASH) { + revert OfframpAddressCannotBeZero(); + } + if (cfg.rmnHomeAddress.length == 0 || keccak256(cfg.rmnHomeAddress) == EMPTY_ENCODED_ADDRESS_HASH) { + revert RMNHomeAddressCannotBeZero(); + } + if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); + + // fChain cannot exceed FRoleDON, since it is a subcommittee in the larger DON + uint256 FRoleDON = cfg.FRoleDON; + uint256 fChain = s_chainConfigurations[cfg.chainSelector].fChain; + // fChain > 0 is enforced in applyChainConfigUpdates, and the presence of a chain config is checked above + // FRoleDON != 0 because FRoleDON >= fChain is enforced here + if (fChain > FRoleDON) { + revert FChainTooHigh(fChain, FRoleDON); + } + + // len(nodes) >= 3 * FRoleDON + 1 + // len(nodes) == numberOfSigners + uint256 numberOfNodes = cfg.nodes.length; + if (numberOfNodes > MAX_NUM_ORACLES) revert TooManySigners(); + if (numberOfNodes <= 3 * FRoleDON) revert FTooHigh(); + + uint256 nonZeroTransmitters = 0; + bytes32[] memory p2pIds = new bytes32[](numberOfNodes); + for (uint256 i = 0; i < numberOfNodes; ++i) { + OCR3Node memory node = cfg.nodes[i]; + + // 3 * fChain + 1 <= nonZeroTransmitters <= 3 * FRoleDON + 1 + // Transmitters can be set to 0 since there can be more signers than transmitters, + if (node.transmitterKey.length != 0) { + nonZeroTransmitters++; + } + + // Signer key and p2pIds must always be present + if (node.signerKey.length == 0 || node.p2pId == bytes32(0)) { + revert InvalidNode(node); + } + + p2pIds[i] = node.p2pId; + } + + // We check for chain config presence above, so fChain here must be non-zero. fChain <= FRoleDON due to the checks above. + // There can be less transmitters than signers - so they can be set to zero (which indicates that a node is a signer, but not a transmitter). + uint256 minTransmittersLength = 3 * fChain + 1; + if (nonZeroTransmitters < minTransmittersLength) { + revert NotEnoughTransmitters(nonZeroTransmitters, minTransmittersLength); + } + + // Check that the readers are in the capabilities registry. + _ensureInRegistry(p2pIds); + } + + function _onlySelfCall() internal view { + if (msg.sender != address(this)) { + revert CanOnlySelfCall(); + } + } + + // ================================================================ + // │ Chain Configuration │ + // ================================================================ + + /// @notice Returns the total number of chains configured. + /// @return The total number of chains configured. + function getNumChainConfigurations() external view returns (uint256) { + return s_remoteChainSelectors.length(); + } + + /// @notice Returns all the chain configurations. + /// @param pageIndex The page index. + /// @param pageSize The page size. + /// @return paginatedChainConfigs chain configurations. + function getAllChainConfigs(uint256 pageIndex, uint256 pageSize) external view returns (ChainConfigArgs[] memory) { + uint256 numberOfChains = s_remoteChainSelectors.length(); + uint256 startIndex = pageIndex * pageSize; + + if (pageSize == 0 || startIndex >= numberOfChains) { + return new ChainConfigArgs[](0); // Return an empty array if pageSize is 0 or pageIndex is out of bounds + } + + uint256 endIndex = startIndex + pageSize; + if (endIndex > numberOfChains) { + endIndex = numberOfChains; + } + + ChainConfigArgs[] memory paginatedChainConfigs = new ChainConfigArgs[](endIndex - startIndex); + + uint256[] memory chainSelectors = s_remoteChainSelectors.values(); + for (uint256 i = startIndex; i < endIndex; ++i) { + uint64 chainSelector = uint64(chainSelectors[i]); + paginatedChainConfigs[i - startIndex] = + ChainConfigArgs({chainSelector: chainSelector, chainConfig: s_chainConfigurations[chainSelector]}); + } + + return paginatedChainConfigs; + } + + /// @notice Sets and/or removes chain configurations. + /// Does not validate that fChain <= FRoleDON and relies on OCR3Configs to be changed in case fChain becomes larger than the FRoleDON value. + /// @param chainSelectorRemoves The chain configurations to remove. + /// @param chainConfigAdds The chain configurations to add. + function applyChainConfigUpdates( + uint64[] calldata chainSelectorRemoves, + ChainConfigArgs[] calldata chainConfigAdds + ) external onlyOwner { + // Process removals first. + for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { + // check if the chain selector is in s_remoteChainSelectors first. + if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { + revert ChainSelectorNotFound(chainSelectorRemoves[i]); + } + + delete s_chainConfigurations[chainSelectorRemoves[i]]; + s_remoteChainSelectors.remove(chainSelectorRemoves[i]); + + emit ChainConfigRemoved(chainSelectorRemoves[i]); + } + + // Process additions next. + for (uint256 i = 0; i < chainConfigAdds.length; ++i) { + ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; + uint64 chainSelector = chainConfigAdds[i].chainSelector; + + // Verify that the provided readers are present in the capabilities registry. + _ensureInRegistry(chainConfig.readers); + + // Verify that fChain is positive. + if (chainConfig.fChain == 0) { + revert FChainMustBePositive(); + } + + s_chainConfigurations[chainSelector] = chainConfig; + s_remoteChainSelectors.add(chainSelector); + + emit ChainConfigSet(chainSelector, chainConfig); + } + } + + /// @notice Helper function to ensure that a node is in the capabilities registry. + /// @param p2pIds The P2P IDs of the node to check. + function _ensureInRegistry( + bytes32[] memory p2pIds + ) internal view { + for (uint256 i = 0; i < p2pIds.length; ++i) { + // TODO add a method that does the validation in the ICapabilitiesRegistry contract + if (ICapabilitiesRegistry(i_capabilitiesRegistry).getNode(p2pIds[i]).p2pId == bytes32("")) { + revert NodeNotInRegistry(p2pIds[i]); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol new file mode 100644 index 0000000..2a38d82 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Client} from "../libraries/Client.sol"; + +/// @notice Application contracts that intend to receive messages from +/// the router should implement this interface. +interface IAny2EVMMessageReceiver { + /// @notice Called by the Router to deliver a message. + /// If this reverts, any token transfers also revert. The message + /// will move to a FAILED state and become available for manual execution. + /// @param message CCIP Message + /// @dev Note ensure you check the msg.sender is the OffRampRouter + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol new file mode 100644 index 0000000..f18c6a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IAny2EVMOffRamp { + /// @notice Returns the the current nonce for a receiver. + /// @param sender The sender address + /// @return nonce The nonce value belonging to the sender address. + function getSenderNonce( + address sender + ) external view returns (uint64 nonce); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol new file mode 100644 index 0000000..d036642 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +interface ICapabilitiesRegistry { + struct NodeInfo { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The number of times the node's configuration has been updated + uint32 configCount; + /// @notice The ID of the Workflow DON that the node belongs to. A node can + /// only belong to one DON that accepts Workflows. + uint32 workflowDONId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. + /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is + /// used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + /// @notice The list of capabilities DON Ids supported by the node. A node + /// can belong to multiple capabilities DONs. This list does not include a + /// Workflow DON id if the node belongs to one. + uint256[] capabilitiesDONIds; + } + + /// @notice Gets a node's data + /// @param p2pId The P2P ID of the node to query for + /// @return NodeInfo The node data + function getNode( + bytes32 p2pId + ) external view returns (NodeInfo memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol new file mode 100644 index 0000000..1183eb2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ICommitStore { + /// @notice Returns timestamp of when root was accepted or 0 if verification fails. + /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, + /// proofs and proofFlagBits being used to get the root of the inner tree. + /// This root is then used as the singular leaf of the outer tree. + function verify( + bytes32[] calldata hashedLeaves, + bytes32[] calldata proofs, + uint256 proofFlagBits + ) external view returns (uint256 timestamp); + + /// @notice Returns the expected next sequence number + function getExpectedNextSequenceNumber() external view returns (uint64 sequenceNumber); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol new file mode 100644 index 0000000..c2d0d6c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IEVM2AnyOnRampClient} from "./IEVM2AnyOnRampClient.sol"; + +interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient { + /// @notice Gets the next sequence number to be used in the onRamp + /// @return the next sequence number to be used + function getExpectedNextSequenceNumber() external view returns (uint64); + + /// @notice Get the next nonce for a given sender + /// @param sender The sender to get the nonce for + /// @return nonce The next nonce for the sender + function getSenderNonce( + address sender + ) external view returns (uint64 nonce); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol new file mode 100644 index 0000000..d2fe347 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IPoolV1} from "./IPool.sol"; + +import {Client} from "../libraries/Client.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +interface IEVM2AnyOnRampClient { + /// @notice Get the fee for a given ccip message + /// @param destChainSelector The destination chain selector + /// @param message The message to calculate the cost for + /// @return fee The calculated fee + function getFee(uint64 destChainSelector, Client.EVM2AnyMessage calldata message) external view returns (uint256 fee); + + /// @notice Get the pool for a specific token + /// @param destChainSelector The destination chain selector + /// @param sourceToken The source chain token to get the pool for + /// @return pool Token pool + function getPoolBySourceToken(uint64 destChainSelector, IERC20 sourceToken) external view returns (IPoolV1); + + /// @notice Gets a list of all supported source chain tokens. + /// @param destChainSelector The destination chain selector + /// @return tokens The addresses of all tokens that this onRamp supports the given destination chain + function getSupportedTokens( + uint64 destChainSelector + ) external view returns (address[] memory tokens); + + /// @notice Send a message to the remote chain + /// @dev only callable by the Router + /// @dev approve() must have already been called on the token using the this ramp address as the spender. + /// @dev if the contract is paused, this function will revert. + /// @param destChainSelector The destination chain selector + /// @param message Message struct to send + /// @param feeTokenAmount Amount of fee tokens for payment + /// @param originalSender The original initiator of the CCIP request + /// @return messageId The message id + function forwardFromRouter( + uint64 destChainSelector, + Client.EVM2AnyMessage memory message, + uint256 feeTokenAmount, + address originalSender + ) external returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol new file mode 100644 index 0000000..84d4304 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {IPriceRegistry} from "./IPriceRegistry.sol"; + +interface IFeeQuoter is IPriceRegistry { + /// @notice Validates the ccip message & returns the fee + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount); + + /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels + /// @notice Validates pool return data + /// @param destChainSelector destination chain selector to process + /// @param feeToken Fee token address used to pay for message fees + /// @param feeTokenAmount Fee token amount + /// @param extraArgs Message extra args that were passed in by the client + /// @param onRampTokenTransfers Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return msgFeeJuels message fee in juels + /// @return isOutOfOrderExecution true if the message should be executed out of order + /// @return convertedExtraArgs extra args converted to the latest family-specific args version + /// @return destExecDataPerToken Destination chain execution data + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes memory extraArgs, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol new file mode 100644 index 0000000..d83a1f3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IGetCCIPAdmin { + /// @notice Returns the admin of the token. + /// @dev This method is named to never conflict with existing methods. + function getCCIPAdmin() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol new file mode 100644 index 0000000..0432a22 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Client} from "../libraries/Client.sol"; + +/// @notice Interface for plug-in message hook contracts that intercept OffRamp & OnRamp messages +/// and perform validations / state changes on top of the messages. The interceptor functions are expected to +/// revert on validation failures. +interface IMessageInterceptor { + /// @notice Common error that can be thrown on validation failures and used by consumers + /// @param errorReason abi encoded revert reason + error MessageValidationError(bytes errorReason); + + /// @notice Intercepts & validates the given OffRamp message. Reverts on validation failure + /// @param message to validate + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external; + + /// @notice Intercepts & validates the given OnRamp message. Reverts on validation failure + /// @param destChainSelector remote destination chain selector where the message is being sent to + /// @param message to validate + function onOutboundMessage(uint64 destChainSelector, Client.EVM2AnyMessage memory message) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol new file mode 100644 index 0000000..3a6eff6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice Contract interface that allows managing sender nonces +interface INonceManager { + /// @notice Increments the outbound nonce for a given sender on a given destination chain. + /// @param destChainSelector The destination chain selector. + /// @param sender The sender address. + /// @return incrementedOutboundNonce The new outbound nonce. + function getIncrementedOutboundNonce(uint64 destChainSelector, address sender) external returns (uint64); + + /// @notice Increments the inbound nonce for a given sender on a given source chain. + /// @notice The increment is only applied if the resulting nonce matches the expectedNonce. + /// @param sourceChainSelector The destination chain selector. + /// @param expectedNonce The expected inbound nonce. + /// @param sender The encoded sender address. + /// @return incremented True if the nonce was incremented, false otherwise. + function incrementInboundNonce( + uint64 sourceChainSelector, + uint64 expectedNonce, + bytes calldata sender + ) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol new file mode 100644 index 0000000..ccb1039 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOwner { + /// @notice Returns the owner of the contract. + /// @dev This method is named to match with the OpenZeppelin Ownable contract. + function owner() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol new file mode 100644 index 0000000..3545e57 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Pool} from "../libraries/Pool.sol"; + +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +/// @notice Shared public interface for multiple V1 pool types. +/// Each pool type handles a different child token model (lock/unlock, mint/burn.) +interface IPoolV1 is IERC165 { + /// @notice Lock tokens into the pool or burn the tokens. + /// @param lockOrBurnIn Encoded data fields for the processing of tokens on the source chain. + /// @return lockOrBurnOut Encoded data fields for the processing of tokens on the destination chain. + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); + + /// @notice Releases or mints tokens to the receiver address. + /// @param releaseOrMintIn All data required to release or mint tokens. + /// @return releaseOrMintOut The amount of tokens released or minted on the local chain, denominated + /// in the local token's decimals. + /// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number + /// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts. + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external returns (Pool.ReleaseOrMintOutV1 memory); + + /// @notice Checks whether a remote chain is supported in the token pool. + /// @param remoteChainSelector The selector of the remote chain. + /// @return true if the given chain is a permissioned remote chain. + function isSupportedChain( + uint64 remoteChainSelector + ) external view returns (bool); + + /// @notice Returns if the token pool supports the given token. + /// @param token The address of the token. + /// @return true if the token is supported by the pool. + function isSupportedToken( + address token + ) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol new file mode 100644 index 0000000..d8a2f15 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +// Shared public interface for multiple pool types. +// Each pool type handles a different child token model (lock/unlock, mint/burn.) +interface IPoolPriorTo1_5 { + /// @notice Lock tokens into the pool or burn the tokens. + /// @param originalSender Original sender of the tokens. + /// @param receiver Receiver of the tokens on destination chain. + /// @param amount Amount to lock or burn. + /// @param remoteChainSelector Destination chain Id. + /// @param extraArgs Additional data passed in by sender for lockOrBurn processing + /// in custom pools on source chain. + /// @return retData Optional field that contains bytes. Unused for now but already + /// implemented to allow future upgrades while preserving the interface. + function lockOrBurn( + address originalSender, + bytes calldata receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes calldata extraArgs + ) external returns (bytes memory); + + /// @notice Releases or mints tokens to the receiver address. + /// @param originalSender Original sender of the tokens. + /// @param receiver Receiver of the tokens. + /// @param amount Amount to release or mint. + /// @param remoteChainSelector Source chain Id. + /// @param extraData Additional data supplied offchain for releaseOrMint processing in + /// custom pools on dest chain. This could be an attestation that was retrieved through a + /// third party API. + /// @dev offchainData can come from any untrusted source. + function releaseOrMint( + bytes memory originalSender, + address receiver, + uint256 amount, + uint64 remoteChainSelector, + bytes memory extraData + ) external; + + /// @notice Gets the IERC20 token that this pool can lock or burn. + /// @return token The IERC20 token representation. + function getToken() external view returns (IERC20 token); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol new file mode 100644 index 0000000..b20c1b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Internal} from "../libraries/Internal.sol"; + +interface IPriceRegistry { + /// @notice Update the price for given tokens and gas prices for given chains. + /// @param priceUpdates The price updates to apply. + function updatePrices( + Internal.PriceUpdates memory priceUpdates + ) external; + + /// @notice Get the `tokenPrice` for a given token. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token. + function getTokenPrice( + address token + ) external view returns (Internal.TimestampedPackedUint224 memory); + + /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. + function getValidatedTokenPrice( + address token + ) external view returns (uint224); + + /// @notice Get the `tokenPrice` for an array of tokens. + /// @param tokens The tokens to get prices for. + /// @return tokenPrices The tokenPrices for the given tokens. + function getTokenPrices( + address[] calldata tokens + ) external view returns (Internal.TimestampedPackedUint224[] memory); + + /// @notice Get an encoded `gasPrice` for a given destination chain ID. + /// The 224-bit result encodes necessary gas price components. + /// On L1 chains like Ethereum or Avax, the only component is the gas price. + /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. + /// On future chains, there could be more or differing price components. + /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. + /// @param destChainSelector The destination chain to get the price for. + /// @return gasPrice The encoded gasPrice for the given destination chain ID. + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (Internal.TimestampedPackedUint224 memory); + + /// @notice Gets the fee token price and the gas price, both denominated in dollars. + /// @param token The source token to get the price for. + /// @param destChainSelector The destination chain to get the gas price for. + /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. + /// @return gasPrice The price of gas in 1e18 dollars per base unit. + function getTokenAndGasPrices( + address token, + uint64 destChainSelector + ) external view returns (uint224 tokenPrice, uint224 gasPrice); + + /// @notice Convert a given token amount to target token amount. + /// @param fromToken The given token address. + /// @param fromTokenAmount The given token amount. + /// @param toToken The target token address. + /// @return toTokenAmount The target token amount. + function convertTokenAmount( + address fromToken, + uint256 fromTokenAmount, + address toToken + ) external view returns (uint256 toTokenAmount); + + /// @notice Get the list of fee tokens. + /// @return feeTokens The tokens set as fee tokens. + function getFeeTokens() external view returns (address[] memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol new file mode 100644 index 0000000..4bd8f83 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. +interface IRMN { + /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. + struct TaggedRoot { + address commitStore; + bytes32 root; + } + + /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. + function isBlessed( + TaggedRoot calldata taggedRoot + ) external view returns (bool); + + /// @notice Iff there is an active global or legacy curse, this function returns true. + function isCursed() external view returns (bool); + + /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true. + /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + function isCursed( + bytes16 subject + ) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol new file mode 100644 index 0000000..3754a2f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Internal} from "../libraries/Internal.sol"; + +/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. +interface IRMNRemote { + /// @notice signature components from RMN nodes + struct Signature { + bytes32 r; + bytes32 s; + } + + /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport + /// @param offRampAddress is not inferred by msg.sender, in case the call is made through ARMProxy + /// @param merkleRoots must be well formed, and is a representation of the CommitReport received from the oracles + /// @param signatures rmnNodes ECDSA sigs, only r & s, must be sorted in ascending order by signer address + /// @param rawVs rmnNodes ECDSA sigs, part v bitmap + /// @dev Will revert if verification fails + function verify( + address offRampAddress, + Internal.MerkleRoot[] memory merkleRoots, + Signature[] memory signatures, + uint256 rawVs + ) external view; + + /// @notice gets the current set of cursed subjects + /// @return subjects the list of cursed subjects + function getCursedSubjects() external view returns (bytes16[] memory subjects); + + /// @notice If there is an active global or legacy curse, this function returns true. + /// @return bool true if there is an active global curse + function isCursed() external view returns (bool); + + /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. + /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + /// @return bool true if the provided subject is cured *or* if there is an active global curse + function isCursed( + bytes16 subject + ) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol new file mode 100644 index 0000000..d8f19bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Client} from "../libraries/Client.sol"; + +interface IRouter { + error OnlyOffRamp(); + + /// @notice Route the message to its intended receiver contract. + /// @param message Client.Any2EVMMessage struct. + /// @param gasForCallExactCheck of params for exec + /// @param gasLimit set of params for exec + /// @param receiver set of params for exec + /// @dev if the receiver is a contracts that signals support for CCIP execution through EIP-165. + /// the contract is called. If not, only tokens are transferred. + /// @return success A boolean value indicating whether the ccip message was received without errors. + /// @return retBytes A bytes array containing return data form CCIP receiver. + /// @return gasUsed the gas used by the external customer call. Does not include any overhead. + function routeMessage( + Client.Any2EVMMessage calldata message, + uint16 gasForCallExactCheck, + uint256 gasLimit, + address receiver + ) external returns (bool success, bytes memory retBytes, uint256 gasUsed); + + /// @notice Returns the configured onramp for a specific destination chain. + /// @param destChainSelector The destination chain Id to get the onRamp for. + /// @return onRampAddress The address of the onRamp. + function getOnRamp( + uint64 destChainSelector + ) external view returns (address onRampAddress); + + /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. + /// @param sourceChainSelector The source chain selector to check. + /// @param offRamp The address of the offRamp to check. + function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool isOffRamp); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol new file mode 100644 index 0000000..36218b3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Client} from "../libraries/Client.sol"; + +interface IRouterClient { + error UnsupportedDestinationChain(uint64 destChainSelector); + error InsufficientFeeTokenAmount(); + error InvalidMsgValue(); + + /// @notice Checks if the given chain ID is supported for sending/receiving. + /// @param destChainSelector The chain to check. + /// @return supported is true if it is supported, false if not. + function isChainSupported( + uint64 destChainSelector + ) external view returns (bool supported); + + /// @param destinationChainSelector The destination chainSelector + /// @param message The cross-chain CCIP message including data and/or tokens + /// @return fee returns execution fee for the message + /// delivery to destination chain, denominated in the feeToken specified in the message. + /// @dev Reverts with appropriate reason upon invalid message. + function getFee( + uint64 destinationChainSelector, + Client.EVM2AnyMessage memory message + ) external view returns (uint256 fee); + + /// @notice Request a message to be sent to the destination chain + /// @param destinationChainSelector The destination chain ID + /// @param message The cross-chain CCIP message including data and/or tokens + /// @return messageId The message ID + /// @dev Note if msg.value is larger than the required fee (from getFee) we accept + /// the overpayment with no refund. + /// @dev Reverts with appropriate reason upon invalid message. + function ccipSend( + uint64 destinationChainSelector, + Client.EVM2AnyMessage calldata message + ) external payable returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol new file mode 100644 index 0000000..04bacba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +interface ITokenAdminRegistry { + /// @notice Returns the pool for the given token. + function getPool( + address token + ) external view returns (address); + + /// @notice Proposes an administrator for the given token as pending administrator. + /// @param localToken The token to register the administrator for. + /// @param administrator The administrator to register. + function proposeAdministrator(address localToken, address administrator) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol new file mode 100644 index 0000000..f4f8243 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +interface IWrappedNative is IERC20 { + function deposit() external payable; + + function withdraw( + uint256 wad + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol new file mode 100644 index 0000000..b0dad9a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice Implement this contract so that a keeper-compatible contract can monitor +/// and fund the implementation contract with LINK if it falls below a defined threshold. +interface ILinkAvailable { + function linkAvailableForPayment() external view returns (int256 availableBalance); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol new file mode 100644 index 0000000..a5792f1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {CCIPHome} from "../../capability/CCIPHome.sol"; + +import {OffRamp} from "../../offRamp/OffRamp.sol"; +import {RMNRemote} from "../../rmn/RMNRemote.sol"; + +/// @dev this file exposes structs that are otherwise internal to the CCIP codebase +/// doing this allows those structs to be encoded and decoded with type safety in offchain code +/// and tests because generated wrappers are available +interface ICCIPEncodingUtils { + /// @dev the RMN Report struct is used in integration / E2E tests + function exposeRmnReport(bytes32 rmnReportVersion, RMNRemote.Report memory rmnReport) external; + + /// @dev the OCR3Config Config struct is used in integration / E2E tests + function exposeOCR3Config( + CCIPHome.OCR3Config[] calldata config + ) external view returns (bytes memory); + + /// @dev used to encode commit reports for onchain transmission. + function exposeCommitReport( + OffRamp.CommitReport memory commitReport + ) external view returns (bytes memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol new file mode 100644 index 0000000..de1f6f1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// End consumer library. +library Client { + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct EVMTokenAmount { + address token; // token address on the local chain. + uint256 amount; // Amount of tokens. + } + + struct Any2EVMMessage { + bytes32 messageId; // MessageId corresponding to ccipSend on source. + uint64 sourceChainSelector; // Source chain selector. + bytes sender; // abi.decode(sender) if coming from an EVM chain. + bytes data; // payload sent in original message. + EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. + } + + // If extraArgs is empty bytes, the default is 200k gas limit. + struct EVM2AnyMessage { + bytes receiver; // abi.encode(receiver address) for dest EVM chains + bytes data; // Data payload + EVMTokenAmount[] tokenAmounts; // Token transfers + address feeToken; // Address of feeToken. address(0) means you will send msg.value. + bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV2) + } + + // bytes4(keccak256("CCIP EVMExtraArgsV1")); + bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; + + struct EVMExtraArgsV1 { + uint256 gasLimit; + } + + function _argsToBytes( + EVMExtraArgsV1 memory extraArgs + ) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); + } + + // bytes4(keccak256("CCIP EVMExtraArgsV2")); + bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; + + /// @param gasLimit: gas limit for the callback on the destination chain. + /// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to other messages from the same sender. + /// This value's default varies by chain. On some chains, a particular value is enforced, meaning if the expected value + /// is not set, the message request will revert. + struct EVMExtraArgsV2 { + uint256 gasLimit; + bool allowOutOfOrderExecution; + } + + function _argsToBytes( + EVMExtraArgsV2 memory extraArgs + ) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol new file mode 100644 index 0000000..7e58c96 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; + +// Library for CCIP internal definitions common to multiple contracts. +library Internal { + error InvalidEVMAddress(bytes encodedAddress); + + /// @dev The minimum amount of gas to perform the call with exact gas. + /// We include this in the offramp so that we can redeploy to adjust it + /// should a hardfork change the gas costs of relevant opcodes in callWithExactGas. + uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // @dev We limit return data to a selector plus 4 words. This is to avoid + // malicious contracts from returning large amounts of data and causing + // repeated out-of-gas scenarios. + uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32; + /// @dev The expected number of bytes returned by the balanceOf function. + uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32; + + /// @notice A collection of token price and gas price updates. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct PriceUpdates { + TokenPriceUpdate[] tokenPriceUpdates; + GasPriceUpdate[] gasPriceUpdates; + } + + /// @notice Token price in USD. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct TokenPriceUpdate { + address sourceToken; // Source token + uint224 usdPerToken; // 1e18 USD per 1e18 of the smallest token denomination. + } + + /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct GasPriceUpdate { + uint64 destChainSelector; // Destination chain selector + uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas + } + + /// @notice A timestamped uint224 value that can contain several tightly packed fields. + struct TimestampedPackedUint224 { + uint224 value; // ──────╮ Value in uint224, packed. + uint32 timestamp; // ───╯ Timestamp of the most recent price update. + } + + /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices. + /// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits. + /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning. + uint8 public constant GAS_PRICE_BITS = 112; + + struct SourceTokenData { + // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be + // relied upon by the destination pool to validate the source pool. + bytes sourcePoolAddress; + // The address of the destination token, abi encoded in the case of EVM chains + // This value is UNTRUSTED as any pool owner can return whatever value they want. + bytes destTokenAddress; + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes extraData; + uint32 destGasAmount; // The amount of gas available for the releaseOrMint and balanceOf calls on the offRamp + } + + /// @notice Report that is submitted by the execution DON at the execution phase. (including chain selector data) + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct ExecutionReport { + uint64 sourceChainSelector; // Source chain selector for which the report is submitted + Any2EVMRampMessage[] messages; + // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token + bytes[][] offchainTokenData; + bytes32[] proofs; + uint256 proofFlagBits; + } + + /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts). + /// Each variable array takes 1 more slot to store its length. + /// When abi encoded, excluding array contents, + /// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each. + /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14. + /// The fixed bytes does not cover struct data (this is represented by MESSAGE_FIXED_BYTES_PER_TOKEN) + uint256 public constant MESSAGE_FIXED_BYTES = 32 * 14; + + /// @dev Each token transfer adds 1 RampTokenAmount + /// RampTokenAmount has 5 fields, 2 of which are bytes type, 1 Address, 1 uint256 and 1 uint32. + /// Each bytes type takes 1 slot for length, 1 slot for data and 1 slot for the offset. + /// address + /// uint256 amount takes 1 slot. + /// uint32 destGasAmount takes 1 slot. + uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((2 * 3) + 3); + + bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); + bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1"); + + /// @dev Used to hash messages for multi-lane family-agnostic OffRamps. + /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId + /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage) + /// @param original OffRamp message to hash + /// @param metadataHash Hash preimage to ensure global uniqueness + /// @return hashedMessage hashed message as a keccak256 + function _hash(Any2EVMRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { + // Fixed-size message fields are included in nested hash to reduce stack pressure. + // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. + return keccak256( + abi.encode( + MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, + metadataHash, + keccak256( + abi.encode( + original.header.messageId, + original.receiver, + original.header.sequenceNumber, + original.gasLimit, + original.header.nonce + ) + ), + keccak256(original.sender), + keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)) + ) + ); + } + + function _hash(EVM2AnyRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { + // Fixed-size message fields are included in nested hash to reduce stack pressure. + // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. + return keccak256( + abi.encode( + MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, + metadataHash, + keccak256( + abi.encode( + original.sender, + original.header.sequenceNumber, + original.header.nonce, + original.feeToken, + original.feeTokenAmount + ) + ), + keccak256(original.receiver), + keccak256(original.data), + keccak256(abi.encode(original.tokenAmounts)), + keccak256(original.extraArgs) + ) + ); + } + + /// @dev We disallow the first 1024 addresses to avoid calling into a range known for hosting precompiles. Calling + /// into precompiles probably won't cause any issues, but to be safe we can disallow this range. It is extremely + /// unlikely that anyone would ever be able to generate an address in this range. There is no official range of + /// precompiles, but EIP-7587 proposes to reserve the range 0x100 to 0x1ff. Our range is more conservative, even + /// though it might not be exhaustive for all chains, which is OK. We also disallow the zero address, which is a + /// common practice. + uint256 public constant PRECOMPILE_SPACE = 1024; + + /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the + /// address is within the EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which + /// we can catch and handle more gracefully than a revert from abi.decode. + /// @return The address if it is valid, the function will revert otherwise. + function _validateEVMAddress( + bytes memory encodedAddress + ) internal pure returns (address) { + if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress); + uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256)); + if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) { + revert InvalidEVMAddress(encodedAddress); + } + return address(uint160(encodedAddressUint)); + } + + /// @notice Enum listing the possible message execution states within + /// the offRamp contract. + /// UNTOUCHED never executed + /// IN_PROGRESS currently being executed, used a replay protection + /// SUCCESS successfully executed. End state + /// FAILURE unsuccessfully executed, manual execution is now enabled. + /// @dev RMN depends on this enum, if changing, please notify the RMN maintainers. + enum MessageExecutionState { + UNTOUCHED, + IN_PROGRESS, + SUCCESS, + FAILURE + } + + /// @notice CCIP OCR plugin type, used to separate execution & commit transmissions and configs + enum OCRPluginType { + Commit, + Execution + } + + /// @notice Family-agnostic header for OnRamp & OffRamp messages. + /// The messageId is not expected to match hash(message), since it may originate from another ramp family + struct RampMessageHeader { + bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) + uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId + uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId + uint64 sequenceNumber; // │ sequence number, not unique across lanes + uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes + } + + struct EVM2AnyTokenTransfer { + // The source pool EVM address. This value is trusted as it was obtained through the onRamp. It can be + // relied upon by the destination pool to validate the source pool. + address sourcePoolAddress; + // The EVM address of the destination token + // This value is UNTRUSTED as any pool owner can return whatever value they want. + bytes destTokenAddress; + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes extraData; + uint256 amount; // Amount of tokens. + // Destination chain specific execution data encoded in bytes + // for an EVM destination, it consists of the amount of gas available for the releaseOrMint + // and transfer calls made by the offRamp + bytes destExecData; + } + + struct Any2EVMTokenTransfer { + // The source pool EVM address encoded to bytes. This value is trusted as it is obtained through the onRamp. It can be + // relied upon by the destination pool to validate the source pool. + bytes sourcePoolAddress; + address destTokenAddress; // ───╮ Address of destination token + uint32 destGasAmount; //────────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes extraData; + uint256 amount; // Amount of tokens. + } + + /// @notice Family-agnostic message routed to an OffRamp + /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage), hash(Any2EVMRampMessage) != messageId + /// due to encoding & parameter differences + struct Any2EVMRampMessage { + RampMessageHeader header; // Message header + bytes sender; // sender address on the source chain + bytes data; // arbitrary data payload supplied by the message sender + address receiver; // receiver address on the destination chain + uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution + Any2EVMTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer + } + + /// @notice Family-agnostic message emitted from the OnRamp + /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage) due to encoding & parameter differences + /// messageId = hash(EVM2AnyRampMessage) using the source EVM chain's encoding format + struct EVM2AnyRampMessage { + RampMessageHeader header; // Message header + address sender; // sender address on the source chain + bytes data; // arbitrary data payload supplied by the message sender + bytes receiver; // receiver address on the destination chain + bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains + address feeToken; // fee token + uint256 feeTokenAmount; // fee token amount + uint256 feeValueJuels; // fee amount in Juels + EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer + } + + // bytes4(keccak256("CCIP ChainFamilySelector EVM")) + bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + + /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + /// @dev inefficient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. + // solhint-disable-next-line gas-struct-packing + struct MerkleRoot { + uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to + bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode + uint64 minSeqNr; // ──────────╮ Minimum sequence number, inclusive + uint64 maxSeqNr; // ──────────╯ Maximum sequence number, inclusive + bytes32 merkleRoot; // Merkle root covering the interval & source chain messages + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol new file mode 100644 index 0000000..95f52bd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; + +library MerkleMultiProof { + /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage. + bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000; + /// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preiimage. + bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR = + 0x0000000000000000000000000000000000000000000000000000000000000001; + + uint256 internal constant MAX_NUM_HASHES = 256; + + error InvalidProof(); + error LeavesCannotBeEmpty(); + + /// @notice Computes the root based on provided pre-hashed leaf nodes in + /// leaves, internal nodes in proofs, and using proofFlagBits' i-th bit to + /// determine if an element of proofs or one of the previously computed leafs + /// or internal nodes will be used for the i-th hash. + /// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's + /// preimage should match LEAF_DOMAIN_SEPARATOR. + /// @param proofs The hashes to be used instead of a leaf hash when the proofFlagBits + /// indicates a proof should be used. + /// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or + /// a proof needs to be used in a hash operation. + /// @dev the maximum number of hash operations it set to 256. Any input that would require + /// more than 256 hashes to get to a root will revert. + /// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5 + /// totalHashes = 3 + 1 - 1 = 3 + /// ** round 1 ** + /// proofFlagBits = (5 >> 0) & 1 = true + /// hashes[0] = hashPair(a, b) + /// (leafPos, hashPos, proofPos) = (2, 0, 0); + /// + /// ** round 2 ** + /// proofFlagBits = (5 >> 1) & 1 = false + /// hashes[1] = hashPair(D, c) + /// (leafPos, hashPos, proofPos) = (3, 0, 1); + /// + /// ** round 3 ** + /// proofFlagBits = (5 >> 2) & 1 = true + /// hashes[2] = hashPair(hashes[0], hashes[1]) + /// (leafPos, hashPos, proofPos) = (3, 2, 1); + /// + /// i = 3 and no longer < totalHashes. The algorithm is done + /// return hashes[totalHashes - 1] = hashes[2]; the last hash we computed. + // We mark this function as internal to force it to be inlined in contracts + // that use it, but semantically it is public. + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function merkleRoot( + bytes32[] memory leaves, + bytes32[] memory proofs, + uint256 proofFlagBits + ) internal pure returns (bytes32) { + unchecked { + uint256 leavesLen = leaves.length; + uint256 proofsLen = proofs.length; + if (leavesLen == 0) revert LeavesCannotBeEmpty(); + if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof(); + uint256 totalHashes = leavesLen + proofsLen - 1; + if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof(); + if (totalHashes == 0) { + return leaves[0]; + } + bytes32[] memory hashes = new bytes32[](totalHashes); + (uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0); + + for (uint256 i = 0; i < totalHashes; ++i) { + // Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash. + bytes32 a; + if (proofFlagBits & (1 << i) == (1 << i)) { + // Use a leaf or a previously computed hash. + if (leafPos < leavesLen) { + a = leaves[leafPos++]; + } else { + a = hashes[hashPos++]; + } + } else { + // Use a supplied proof. + a = proofs[proofPos++]; + } + + // The second part of the hashed pair is never a proof as hashing two proofs would result in a + // hash that can already be computed offchain. + bytes32 b; + if (leafPos < leavesLen) { + b = leaves[leafPos++]; + } else { + b = hashes[hashPos++]; + } + + if (!(hashPos <= i)) revert InvalidProof(); + + hashes[i] = _hashPair(a, b); + } + if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof(); + // Return the last hash. + return hashes[totalHashes - 1]; + } + } + + /// @notice Hashes two bytes32 objects in their given order, prepended by the + /// INTERNAL_DOMAIN_SEPARATOR. + function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) { + return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right)); + } + + /// @notice Hashes two bytes32 objects. The order is taken into account, + /// using the lower value first. + function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { + return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol new file mode 100644 index 0000000..391beb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice This library contains various token pool functions to aid constructing the return data. +library Pool { + // The tag used to signal support for the pool v1 standard + // bytes4(keccak256("CCIP_POOL_V1")) + bytes4 public constant CCIP_POOL_V1 = 0xaff2afbf; + + // The number of bytes in the return data for a pool v1 releaseOrMint call. + // This should match the size of the ReleaseOrMintOutV1 struct. + uint16 public constant CCIP_POOL_V1_RET_BYTES = 32; + + // The default max number of bytes in the return data for a pool v1 lockOrBurn call. + // This data can be used to send information to the destination chain token pool. Can be overwritten + // in the TokenTransferFeeConfig.destBytesOverhead if more data is required. + uint32 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32; + + struct LockOrBurnInV1 { + bytes receiver; // The recipient of the tokens on the destination chain, abi encoded + uint64 remoteChainSelector; // ─╮ The chain ID of the destination chain + address originalSender; // ─────╯ The original sender of the tx on the source chain + uint256 amount; // The amount of tokens to lock or burn, denominated in the source token's decimals + address localToken; // The address on this chain of the token to lock or burn + } + + struct LockOrBurnOutV1 { + // The address of the destination token, abi encoded in the case of EVM chains + // This value is UNTRUSTED as any pool owner can return whatever value they want. + bytes destTokenAddress; + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes destPoolData; + } + + struct ReleaseOrMintInV1 { + bytes originalSender; // The original sender of the tx on the source chain + uint64 remoteChainSelector; // ─╮ The chain ID of the source chain + address receiver; // ───────────╯ The recipient of the tokens on the destination chain. + uint256 amount; // The amount of tokens to release or mint, denominated in the source token's decimals + address localToken; // The address on this chain of the token to release or mint + /// @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the + /// expected pool address for the given remoteChainSelector. + bytes sourcePoolAddress; // The address of the source pool, abi encoded in the case of EVM chains + bytes sourcePoolData; // The data received from the source pool to process the release or mint + /// @dev WARNING: offchainTokenData is untrusted data. + bytes offchainTokenData; // The offchain data to process the release or mint + } + + struct ReleaseOrMintOutV1 { + // The number of tokens released or minted on the destination chain, denominated in the local token's decimals. + // This value is expected to be equal to the ReleaseOrMintInV1.amount in the case where the source and destination + // chain have the same number of decimals. + uint256 destinationAmount; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol new file mode 100644 index 0000000..431b772 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; + +/// @notice Implements Token Bucket rate limiting. +/// @dev uint128 is safe for rate limiter state. +/// For USD value rate limiting, it can adequately store USD value in 18 decimals. +/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most +/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. +/// In exceptional scenarios where tokens consumed may be larger than uint128, +/// e.g. compromised issuer, an enabled RateLimiter will check and revert. +library RateLimiter { + error BucketOverfilled(); + error OnlyCallableByAdminOrOwner(); + error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); + error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error InvalidRateLimitRate(Config rateLimiterConfig); + error DisabledNonZeroRateLimit(Config config); + error RateLimitMustBeDisabled(); + + event TokensConsumed(uint256 tokens); + event ConfigChanged(Config config); + + struct TokenBucket { + uint128 tokens; // ──────╮ Current number of tokens that are in the bucket. + uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years. + bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not + uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket. + uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled. + } + + struct Config { + bool isEnabled; // Indication whether the rate limiting should be enabled + uint128 capacity; // ────╮ Specifies the capacity of the rate limiter + uint128 rate; // ───────╯ Specifies the rate of the rate limiter + } + + /// @notice _consume removes the given tokens from the pool, lowering the + /// rate tokens allowed to be consumed for subsequent calls. + /// @param requestTokens The total tokens to be consumed from the bucket. + /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. + /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket + /// @dev emits removal of requestTokens if requestTokens is > 0 + function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal { + // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage + if (!s_bucket.isEnabled || requestTokens == 0) { + return; + } + + uint256 tokens = s_bucket.tokens; + uint256 capacity = s_bucket.capacity; + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + + if (timeDiff != 0) { + if (tokens > capacity) revert BucketOverfilled(); + + // Refill tokens when arriving at a new block time + tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + if (capacity < requestTokens) { + // Token address 0 indicates consuming aggregate value rate limit capacity. + if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); + revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); + } + if (tokens < requestTokens) { + uint256 rate = s_bucket.rate; + // Wait required until the bucket is refilled enough to accept this value, round up to next higher second + // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. + // This acts as a lower bound of wait time. + uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; + + if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); + revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); + } + tokens -= requestTokens; + + // Downcast is safe here, as tokens is not larger than capacity + s_bucket.tokens = uint128(tokens); + emit TokensConsumed(requestTokens); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function _currentTokenBucketState( + TokenBucket memory bucket + ) internal view returns (TokenBucket memory) { + // We update the bucket to reflect the status at the exact time of the + // call. This means we might need to refill a part of the bucket based + // on the time that has passed since the last update. + bucket.tokens = + uint128(_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)); + bucket.lastUpdated = uint32(block.timestamp); + return bucket; + } + + /// @notice Sets the rate limited config. + /// @param s_bucket The token bucket + /// @param config The new config + function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { + // First update the bucket to make sure the proper rate is used for all the time + // up until the config change. + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + if (timeDiff != 0) { + s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate)); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); + s_bucket.isEnabled = config.isEnabled; + s_bucket.capacity = config.capacity; + s_bucket.rate = config.rate; + + emit ConfigChanged(config); + } + + /// @notice Validates the token bucket config + function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { + if (config.isEnabled) { + if (config.rate >= config.capacity || config.rate == 0) { + revert InvalidRateLimitRate(config); + } + if (mustBeDisabled) { + revert RateLimitMustBeDisabled(); + } + } else { + if (config.rate != 0 || config.capacity != 0) { + revert DisabledNonZeroRateLimit(config); + } + } + } + + /// @notice Calculate refilled tokens + /// @param capacity bucket capacity + /// @param tokens current bucket tokens + /// @param timeDiff block time difference since last refill + /// @param rate bucket refill rate + /// @return the value of tokens after refill + function _calculateRefill( + uint256 capacity, + uint256 tokens, + uint256 timeDiff, + uint256 rate + ) private pure returns (uint256) { + return _min(capacity, tokens + timeDiff * rate); + } + + /// @notice Return the smallest of two integers + /// @param a first int + /// @param b second int + /// @return smallest + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol new file mode 100644 index 0000000..3508276 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +library USDPriceWith18Decimals { + /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount, + /// and amount of the smallest token denomination, + /// calculates the value in USD with 18 decimals. + /// @param tokenPrice The USD price of the token. + /// @param tokenAmount Amount of the smallest token denomination. + /// @return USD value with 18 decimals. + /// @dev this function assumes that no more than 1e59 US dollar worth of token is passed in. + /// If more is sent, this function will overflow and revert. + /// Since there isn't even close to 1e59 dollars, this is ok for all legit tokens. + function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { + /// LINK Example: + /// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals + /// tokenAmount: 2e18 -> 2 LINK + /// result: 8e18 * 2e18 / 1e18 -> 16e18 with 18 decimals = $16 + + /// USDC Example: + /// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals + /// tokenAmount: 5e6 -> 5 USDC + /// result: 1e30 * 5e6 / 1e18 -> 5e18 with 18 decimals = $5 + return (tokenPrice * tokenAmount) / 1e18; + } + + /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount, + /// and USD value with 18 decimals, + /// calculates amount of the smallest token denomination. + /// @param tokenPrice The USD price of the token. + /// @param usdValue USD value with 18 decimals. + /// @return Amount of the smallest token denomination. + function _calcTokenAmountFromUSDValue(uint224 tokenPrice, uint256 usdValue) internal pure returns (uint256) { + /// LINK Example: + /// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals + /// usdValue: 16e18 -> $16 + /// result: 16e18 * 1e18 / 8e18 -> 2e18 = 2 LINK + + /// USDC Example: + /// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals + /// usdValue: 5e18 -> $5 + /// result: 5e18 * 1e18 / 1e30 -> 5e6 = 5 USDC + return (usdValue * 1e18) / tokenPrice; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol new file mode 100644 index 0000000..ba1dc1e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +/// @notice Onchain verification of reports from the offchain reporting protocol +/// with multiple OCR plugin support. +abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 256; + + /// @notice Triggers a new run of the offchain reporting protocol + /// @param ocrPluginType OCR plugin type for which the config was set + /// @param configDigest configDigest of this configuration + /// @param signers ith element is address ith oracle uses to sign a report + /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + /// @param F maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + event ConfigSet(uint8 ocrPluginType, bytes32 configDigest, address[] signers, address[] transmitters, uint8 F); + + /// @notice Optionally emitted to indicate the latest configDigest and sequence number + /// for which a report was successfully transmitted. Alternatively, the contract may + /// use latestConfigDigestAndEpoch with scanLogs set to false. + event Transmitted(uint8 indexed ocrPluginType, bytes32 configDigest, uint64 sequenceNumber); + + enum InvalidConfigErrorType { + F_MUST_BE_POSITIVE, + TOO_MANY_TRANSMITTERS, + TOO_MANY_SIGNERS, + F_TOO_HIGH, + REPEATED_ORACLE_ADDRESS, + NO_TRANSMITTERS + } + + error InvalidConfig(InvalidConfigErrorType errorType); + error WrongMessageLength(uint256 expected, uint256 actual); + error ConfigDigestMismatch(bytes32 expected, bytes32 actual); + error ForkedChain(uint256 expected, uint256 actual); + error WrongNumberOfSignatures(); + error SignaturesOutOfRegistration(); + error UnauthorizedTransmitter(); + error UnauthorizedSigner(); + error NonUniqueSignatures(); + error OracleCannotBeZeroAddress(); + error StaticConfigCannotBeChanged(uint8 ocrPluginType); + + /// @dev Packing these fields used on the hot path in a ConfigInfo variable reduces the + /// retrieval of all of them to a minimum number of SLOADs. + struct ConfigInfo { + bytes32 configDigest; + uint8 F; // ──────────────────────────────╮ maximum number of faulty/dishonest oracles the system can tolerate + uint8 n; // │ number of signers / transmitters + bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification + } + + /// @notice Used for s_oracles[a].role, where a is an address, to track the purpose + /// of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // ───╮ Index of oracle in s_signers/s_transmitters + Role role; // ─────╯ Role of the address which mapped to this struct + } + + /// @notice OCR configuration for a single OCR plugin within a DON. + struct OCRConfig { + ConfigInfo configInfo; // latest OCR config + // NOTE: len(signers) can be different from len(transmitters). There is no index relationship between the two arrays + address[] signers; // addresses oracles use to sign the reports + address[] transmitters; // addresses oracles use to transmit the reports + } + + /// @notice Args to update an OCR Config. + struct OCRConfigArgs { + bytes32 configDigest; // Config digest to update to + uint8 ocrPluginType; // ──────────────────╮ OCR plugin type to update config for + uint8 F; // │ maximum number of faulty/dishonest oracles + bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification + address[] signers; // signing address of each oracle + address[] transmitters; // transmission address of each oracle (i.e. the address the oracle actually sends transactions to the contract from) + } + + /// @notice mapping of OCR plugin type -> DON config + mapping(uint8 ocrPluginType => OCRConfig config) internal s_ocrConfigs; + + /// @notice OCR plugin type => signer OR transmitter address mapping + mapping(uint8 ocrPluginType => mapping(address signerOrTransmiter => Oracle oracle)) internal s_oracles; + + // Constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + + /// @notice Constant length component for transmit functions with no signatures. + /// The signatures are expected to match transmitPlugin(reportContext, report). + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector + + 3 * 32 // 3 words containing reportContext + + 32 // word containing start location of abiencoded report value + + 32; // word containing length of report + + /// @notice Extra constant length component for transmit functions with signatures (relative to no signatures). + /// The signatures are expected to match transmitPlugin(reportContext, report, rs, ss, rawVs). + uint16 private constant TRANSMIT_MSGDATA_EXTRA_CONSTANT_LENGTH_COMPONENT_FOR_SIGNATURES = 32 // word containing location start of abiencoded rs value + + 32 // word containing start location of abiencoded ss value + + 32 // rawVs value + + 32 // word containing length rs + + 32; // word containing length of ss + + uint256 internal immutable i_chainID; + + constructor() { + i_chainID = block.chainid; + } + + /// @notice Sets offchain reporting protocol configuration incl. participating oracles. + /// NOTE: The OCR3 config must be sanity-checked against the home-chain registry configuration, to ensure + /// home-chain and remote-chain parity! + /// @param ocrConfigArgs OCR config update args. + /// @dev precondition number of transmitters should match the expected F/fChain relationship. + /// For transmitters, the function only validates that len(transmitters) > 0 && len(transmitters) <= MAX_NUM_ORACLES + /// && len(transmitters) <= len(signers) [if sig verification is enabled] + function setOCR3Configs( + OCRConfigArgs[] memory ocrConfigArgs + ) external onlyOwner { + for (uint256 i; i < ocrConfigArgs.length; ++i) { + _setOCR3Config(ocrConfigArgs[i]); + } + } + + /// @notice Sets offchain reporting protocol configuration incl. participating oracles for a single OCR plugin type. + /// @param ocrConfigArgs OCR config update args. + function _setOCR3Config( + OCRConfigArgs memory ocrConfigArgs + ) internal { + if (ocrConfigArgs.F == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE); + + uint8 ocrPluginType = ocrConfigArgs.ocrPluginType; + OCRConfig storage ocrConfig = s_ocrConfigs[ocrPluginType]; + ConfigInfo storage configInfo = ocrConfig.configInfo; + + // If F is 0, then the config is not yet set + if (configInfo.F == 0) { + configInfo.isSignatureVerificationEnabled = ocrConfigArgs.isSignatureVerificationEnabled; + } else if (configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled) { + revert StaticConfigCannotBeChanged(ocrPluginType); + } + + address[] memory transmitters = ocrConfigArgs.transmitters; + if (transmitters.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + if (transmitters.length == 0) revert InvalidConfig(InvalidConfigErrorType.NO_TRANSMITTERS); + + _clearOracleRoles(ocrPluginType, ocrConfig.transmitters); + + if (ocrConfigArgs.isSignatureVerificationEnabled) { + _clearOracleRoles(ocrPluginType, ocrConfig.signers); + + address[] memory signers = ocrConfigArgs.signers; + + if (signers.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); + if (signers.length <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); + // NOTE: Transmitters cannot exceed signers. Transmitters do not have to be >= 3F + 1 because they can match >= 3fChain + 1, where fChain <= F. + // fChain is not represented in MultiOCR3Base - so we skip this check. + if (signers.length < transmitters.length) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + + configInfo.n = uint8(signers.length); + ocrConfig.signers = signers; + + _assignOracleRoles(ocrPluginType, signers, Role.Signer); + } + + _assignOracleRoles(ocrPluginType, transmitters, Role.Transmitter); + + ocrConfig.transmitters = transmitters; + configInfo.F = ocrConfigArgs.F; + configInfo.configDigest = ocrConfigArgs.configDigest; + + emit ConfigSet( + ocrPluginType, ocrConfigArgs.configDigest, ocrConfig.signers, ocrConfigArgs.transmitters, ocrConfigArgs.F + ); + _afterOCR3ConfigSet(ocrPluginType); + } + + /// @notice Hook that is called after a plugin's OCR3 config changes. + /// @param ocrPluginType Plugin type for which the config changed. + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal virtual; + + /// @notice Clears oracle roles for the provided oracle addresses. + /// @param ocrPluginType OCR plugin type to clear roles for. + /// @param oracleAddresses Oracle addresses to clear roles for. + function _clearOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses) internal { + for (uint256 i = 0; i < oracleAddresses.length; ++i) { + delete s_oracles[ocrPluginType][oracleAddresses[i]]; + } + } + + /// @notice Assigns oracles roles for the provided oracle addresses with uniqueness verification. + /// @param ocrPluginType OCR plugin type to assign roles for. + /// @param oracleAddresses Oracle addresses to assign roles to. + /// @param role Role to assign. + function _assignOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses, Role role) internal { + for (uint256 i = 0; i < oracleAddresses.length; ++i) { + address oracle = oracleAddresses[i]; + if (s_oracles[ocrPluginType][oracle].role != Role.Unset) { + revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); + } + if (oracle == address(0)) revert OracleCannotBeZeroAddress(); + s_oracles[ocrPluginType][oracle] = Oracle(uint8(i), role); + } + } + + /// @notice _transmit is called to post a new report to the contract. + /// The function should be called after the per-DON reporting logic is completed. + /// @param ocrPluginType OCR plugin type to transmit report for + /// @param report serialized report, which the signatures are signing. + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. + /// @param rawVs ith element is the the V component of the ith signature. + function _transmit( + uint8 ocrPluginType, + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs // signatures + ) internal { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 24 byte padding, 8 byte sequence number + // reportContext[2]: ExtraHash + ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; + bytes32 configDigest = reportContext[0]; + + // Scoping this reduces stack pressure and gas usage + { + uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES) + report.length; // one byte pure entry in _report + + if (configInfo.isSignatureVerificationEnabled) { + expectedDataLength += TRANSMIT_MSGDATA_EXTRA_CONSTANT_LENGTH_COMPONENT_FOR_SIGNATURES + rs.length * 32 // 32 bytes per entry in _rs + + ss.length * 32; // 32 bytes per entry in _ss) + } + + if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); + } + + if (configInfo.configDigest != configDigest) { + revert ConfigDigestMismatch(configInfo.configDigest, configDigest); + } + // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. + // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest + // calculated from chain A and so OCR reports will be valid on both forks. + _whenChainNotForked(); + + // Scoping this reduces stack pressure and gas usage + { + Oracle memory transmitter = s_oracles[ocrPluginType][msg.sender]; + // Check that sender is authorized to report + if ( + !( + transmitter.role == Role.Transmitter + && msg.sender == s_ocrConfigs[ocrPluginType].transmitters[transmitter.index] + ) + ) { + revert UnauthorizedTransmitter(); + } + } + + if (configInfo.isSignatureVerificationEnabled) { + // Scoping to reduce stack pressure + { + if (rs.length != configInfo.F + 1) revert WrongNumberOfSignatures(); + if (rs.length != ss.length) revert SignaturesOutOfRegistration(); + } + + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + _verifySignatures(ocrPluginType, h, rs, ss, rawVs); + } + + emit Transmitted(ocrPluginType, configDigest, uint64(uint256(reportContext[1]))); + } + + /// @notice Verifies the signatures of a hashed report value for one OCR plugin type. + /// @param ocrPluginType OCR plugin type to transmit report for. + /// @param hashedReport hashed encoded packing of report + reportContext. + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. + /// @param rawVs ith element is the the V component of the ith signature. + function _verifySignatures( + uint8 ocrPluginType, + bytes32 hashedReport, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) internal view { + // Verify signatures attached to report. Using a uint256 means we can only verify up to 256 oracles. + uint256 signed = 0; + + uint256 numberOfSignatures = rs.length; + for (uint256 i; i < numberOfSignatures; ++i) { + // Safe from ECDSA malleability here since we check for duplicate signers. + address signer = ecrecover(hashedReport, uint8(rawVs[i]) + 27, rs[i], ss[i]); + // Since we disallow address(0) as a valid signer address, it can never have a signer role. + Oracle memory oracle = s_oracles[ocrPluginType][signer]; + if (oracle.role != Role.Signer) revert UnauthorizedSigner(); + if (signed & (0x1 << oracle.index) != 0) revert NonUniqueSignatures(); + signed |= 0x1 << oracle.index; + } + } + + /// @notice Validates that the chain ID has not diverged after deployment. Reverts if the chain IDs do not match. + function _whenChainNotForked() internal view { + if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); + } + + /// @notice Information about current offchain reporting protocol configuration. + /// @param ocrPluginType OCR plugin type to return config details for. + /// @return ocrConfig OCR config for the plugin type. + function latestConfigDetails( + uint8 ocrPluginType + ) external view returns (OCRConfig memory ocrConfig) { + return s_ocrConfigs[ocrPluginType]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol new file mode 100644 index 0000000..51e8787 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -0,0 +1,1044 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; +import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; +import {INonceManager} from "../interfaces/INonceManager.sol"; +import {IPoolV1} from "../interfaces/IPool.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; + +import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; +import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; +import {Pool} from "../libraries/Pool.sol"; +import {MultiOCR3Base} from "../ocr/MultiOCR3Base.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol"; +import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice OffRamp enables OCR networks to execute multiple messages +/// in an OffRamp in a single transaction. +/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them +/// results an onchain upgrade of both contracts. +/// @dev MultiOCR3Base is used to store multiple OCR configs for the OffRamp. +/// The execution plugin type has to be configured without signature verification, and the commit +/// plugin type with verification. +contract OffRamp is ITypeAndVersion, MultiOCR3Base { + using ERC165Checker for address; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableSet for EnumerableSet.UintSet; + + error ZeroChainSelectorNotAllowed(); + error ExecutionError(bytes32 messageId, bytes err); + error SourceChainNotEnabled(uint64 sourceChainSelector); + error TokenDataMismatch(uint64 sourceChainSelector, uint64 sequenceNumber); + error UnexpectedTokenData(); + error ManualExecutionNotYetEnabled(uint64 sourceChainSelector); + error ManualExecutionGasLimitMismatch(); + error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, bytes32 messageId, uint256 newLimit); + error InvalidManualExecutionTokenGasOverride( + bytes32 messageId, uint256 tokenIndex, uint256 oldLimit, uint256 tokenGasOverride + ); + error ManualExecutionGasAmountCountMismatch(bytes32 messageId, uint64 sequenceNumber); + error RootNotCommitted(uint64 sourceChainSelector); + error RootAlreadyCommitted(uint64 sourceChainSelector, bytes32 merkleRoot); + error InvalidRoot(); + error CanOnlySelfCall(); + error ReceiverError(bytes err); + error TokenHandlingError(bytes err); + error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost); + error EmptyReport(); + error CursedByRMN(uint64 sourceChainSelector); + error NotACompatiblePool(address notPool); + error InvalidDataLength(uint256 expected, uint256 got); + error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); + error StaleCommitReport(); + error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); + error ZeroAddressNotAllowed(); + error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); + error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); + error SignatureVerificationDisabled(); + error CommitOnRampMismatch(bytes reportOnRamp, bytes configOnRamp); + error InvalidOnRampUpdate(uint64 sourceChainSelector); + + /// @dev Atlas depends on this event, if changing, please notify Atlas. + event StaticConfigSet(StaticConfig staticConfig); + event DynamicConfigSet(DynamicConfig dynamicConfig); + /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. + event ExecutionStateChanged( + uint64 indexed sourceChainSelector, + uint64 indexed sequenceNumber, + bytes32 indexed messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes returnData, + uint256 gasUsed + ); + event SourceChainSelectorAdded(uint64 sourceChainSelector); + event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig); + event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); + event AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); + /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. + event CommitReportAccepted(Internal.MerkleRoot[] merkleRoots, Internal.PriceUpdates priceUpdates); + event RootRemoved(bytes32 root); + event SkippedReportExecution(uint64 sourceChainSelector); + + /// @dev Struct that contains the static configuration + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + /// @dev not sure why solhint complains about this, seems like a buggy detector + /// https://github.com/protofire/solhint/issues/597 + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint64 chainSelector; // ───╮ Destination chainSelector + IRMNRemote rmnRemote; // ───╯ RMN Verification Contract + address tokenAdminRegistry; // Token admin registry address + address nonceManager; // Nonce manager address + } + + /// @dev Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) + struct SourceChainConfig { + IRouter router; // ──────────╮ Local router to use for messages coming from this source chain + bool isEnabled; // | Flag whether the source chain is enabled or not + uint64 minSeqNr; // ─────────╯ The min sequence number expected for future messages + bytes onRamp; // OnRamp address on the source chain + } + + /// @dev Same as SourceChainConfig but with source chain selector so that an array of these + /// can be passed in the constructor and the applySourceChainConfigUpdates function. + struct SourceChainConfigArgs { + IRouter router; // ────────────────╮ Local router to use for messages coming from this source chain + uint64 sourceChainSelector; // | Source chain selector of the config to update + bool isEnabled; // ────────────────╯ Flag whether the source chain is enabled or not + bytes onRamp; // OnRamp address on the source chain + } + + /// @dev Dynamic offRamp config + /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas + struct DynamicConfig { + address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain + uint32 permissionLessExecutionThresholdSeconds; //──╯ Waiting time before manual execution is enabled + address messageInterceptor; // Optional message interceptor to validate incoming messages (zero address = no interceptor) + } + + /// @dev Report that is committed by the observing DON at the committing phase + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct CommitReport { + Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit + Internal.MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit + IRMNRemote.Signature[] rmnSignatures; // RMN signatures on the merkle roots + uint256 rmnRawVs; // Raw v values of the RMN signatures + } + + struct GasLimitOverride { + // A value of zero in both fields signifies no override and allows the corresponding field to be overridden as valid + uint256 receiverExecutionGasLimit; // Overrides EVM2EVMMessage.gasLimit. + uint32[] tokenGasOverrides; // Overrides EVM2EVMMessage.sourceTokenData.destGasAmount, length must be same as tokenAmounts. + } + + // STATIC CONFIG + string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; + /// @dev Hash of encoded address(0) used for empty address checks + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); + /// @dev ChainSelector of this chain + uint64 internal immutable i_chainSelector; + /// @dev The RMN verification contract + IRMNRemote internal immutable i_rmnRemote; + /// @dev The address of the token admin registry + address internal immutable i_tokenAdminRegistry; + /// @dev The address of the nonce manager + address internal immutable i_nonceManager; + + // DYNAMIC CONFIG + DynamicConfig internal s_dynamicConfig; + + /// @notice Set of source chain selectors + EnumerableSet.UintSet internal s_sourceChainSelectors; + + /// @notice SourceChainConfig per chain + /// (forms lane configurations from sourceChainSelector => StaticConfig.chainSelector) + mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) private s_sourceChainConfigs; + + // STATE + /// @dev A mapping of sequence numbers (per source chain) to execution state using a bitmap with each execution + /// state only taking up 2 bits of the uint256, packing 128 states into a single slot. + /// Message state is tracked to ensure message can only be executed successfully once. + mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => uint256 executionStateBitmap)) internal + s_executionStates; + + /// @notice Commit timestamp of merkle roots per source chain + mapping(uint64 sourceChainSelector => mapping(bytes32 merkleRoot => uint256 timestamp)) internal s_roots; + /// @dev The sequence number of the last price update + uint64 private s_latestPriceSequenceNumber; + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + SourceChainConfigArgs[] memory sourceChainConfigs + ) MultiOCR3Base() { + if ( + address(staticConfig.rmnRemote) == address(0) || staticConfig.tokenAdminRegistry == address(0) + || staticConfig.nonceManager == address(0) + ) { + revert ZeroAddressNotAllowed(); + } + + if (staticConfig.chainSelector == 0) { + revert ZeroChainSelectorNotAllowed(); + } + + i_chainSelector = staticConfig.chainSelector; + i_rmnRemote = staticConfig.rmnRemote; + i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; + i_nonceManager = staticConfig.nonceManager; + emit StaticConfigSet(staticConfig); + + _setDynamicConfig(dynamicConfig); + _applySourceChainConfigUpdates(sourceChainConfigs); + } + + // ================================================================ + // │ Execution │ + // ================================================================ + + // The size of the execution state in bits + uint256 private constant MESSAGE_EXECUTION_STATE_BIT_WIDTH = 2; + // The mask for the execution state bits + uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1; + + /// @notice Returns the current execution state of a message based on its sequenceNumber. + /// @param sourceChainSelector The source chain to get the execution state for + /// @param sequenceNumber The sequence number of the message to get the execution state for. + /// @return executionState The current execution state of the message. + /// @dev We use the literal number 128 because using a constant increased gas usage. + function getExecutionState( + uint64 sourceChainSelector, + uint64 sequenceNumber + ) public view returns (Internal.MessageExecutionState) { + return Internal.MessageExecutionState( + ( + _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber) + >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH) + ) & MESSAGE_EXECUTION_STATE_MASK + ); + } + + /// @notice Sets a new execution state for a given sequence number. It will overwrite any existing state. + /// @param sourceChainSelector The source chain to set the execution state for + /// @param sequenceNumber The sequence number for which the state will be saved. + /// @param newState The new value the state will be in after this function is called. + /// @dev We use the literal number 128 because using a constant increased gas usage. + function _setExecutionState( + uint64 sourceChainSelector, + uint64 sequenceNumber, + Internal.MessageExecutionState newState + ) internal { + uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH; + uint256 bitmap = _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber); + // To unset any potential existing state we zero the bits of the section the state occupies, + // then we do an AND operation to blank out any existing state for the section. + bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset); + // Set the new state + bitmap |= uint256(newState) << offset; + + s_executionStates[sourceChainSelector][sequenceNumber / 128] = bitmap; + } + + /// @param sourceChainSelector remote source chain selector to get sequence number bitmap for + /// @param sequenceNumber sequence number to get bitmap for + /// @return bitmap Bitmap of the given sequence number for the provided source chain selector. One bitmap represents 128 sequence numbers + function _getSequenceNumberBitmap( + uint64 sourceChainSelector, + uint64 sequenceNumber + ) internal view returns (uint256 bitmap) { + return s_executionStates[sourceChainSelector][sequenceNumber / 128]; + } + + /// @notice Manually executes a set of reports. + /// @param reports Internal.ExecutionReportSingleChain[] - list of reports to execute + /// @param gasLimitOverrides New gasLimit for each message per report + // The outer array represents each report, inner array represents each message in the report. + // i.e. gasLimitOverrides[report1][report1Message1] -> access message1 from report1 + /// @dev We permit gas limit overrides so that users may manually execute messages which failed due to + /// insufficient gas provided. + /// The reports do not have to contain all the messages (they can be omitted). Multiple reports can be passed in simultaneously. + function manuallyExecute( + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory gasLimitOverrides + ) external { + // We do this here because the other _execute path is already covered by MultiOCR3Base. + _whenChainNotForked(); + + uint256 numReports = reports.length; + if (numReports != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); + + for (uint256 reportIndex = 0; reportIndex < numReports; ++reportIndex) { + Internal.ExecutionReport memory report = reports[reportIndex]; + + uint256 numMsgs = report.messages.length; + GasLimitOverride[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; + if (numMsgs != msgGasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); + + for (uint256 msgIndex = 0; msgIndex < numMsgs; ++msgIndex) { + uint256 newLimit = msgGasLimitOverrides[msgIndex].receiverExecutionGasLimit; + // Checks to ensure message cannot be executed with less gas than specified. + Internal.Any2EVMRampMessage memory message = report.messages[msgIndex]; + if (newLimit != 0) { + if (newLimit < message.gasLimit) { + revert InvalidManualExecutionGasLimit(report.sourceChainSelector, message.header.messageId, newLimit); + } + } + if (message.tokenAmounts.length != msgGasLimitOverrides[msgIndex].tokenGasOverrides.length) { + revert ManualExecutionGasAmountCountMismatch(message.header.messageId, message.header.sequenceNumber); + } + + // The gas limit can not be lowered as that could cause the message to fail. If manual execution is done + // from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with + // lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON + // would not attempt it with the correct gas limit. + for (uint256 tokenIndex = 0; tokenIndex < message.tokenAmounts.length; ++tokenIndex) { + uint256 tokenGasOverride = msgGasLimitOverrides[msgIndex].tokenGasOverrides[tokenIndex]; + if (tokenGasOverride != 0) { + uint256 destGasAmount = message.tokenAmounts[tokenIndex].destGasAmount; + if (tokenGasOverride < destGasAmount) { + revert InvalidManualExecutionTokenGasOverride( + message.header.messageId, tokenIndex, destGasAmount, tokenGasOverride + ); + } + } + } + } + } + + _batchExecute(reports, gasLimitOverrides); + } + + /// @notice Transmit function for execution reports. The function takes no signatures, + /// and expects the exec plugin type to be configured with no signatures. + /// @param report serialized execution report + function execute(bytes32[3] calldata reportContext, bytes calldata report) external { + _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); + + bytes32[] memory emptySigs = new bytes32[](0); + _transmit(uint8(Internal.OCRPluginType.Execution), reportContext, report, emptySigs, emptySigs, bytes32("")); + } + + /// @notice Batch executes a set of reports, each report matching one single source chain + /// @param reports Set of execution reports (one per chain) containing the messages and proofs + /// @param manualExecGasLimits An array of gas limits to use for manual execution + // The outer array represents each report, inner array represents each message in the report. + // i.e. gasLimitOverrides[report1][report1Message1] -> access message1 from report1 + /// @dev The manualExecGasLimits array should either be empty, or match the length of the reports array + /// @dev If called from manual execution, each inner array's length has to match the number of messages. + function _batchExecute( + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory manualExecGasOverrides + ) internal { + if (reports.length == 0) revert EmptyReport(); + + bool areManualGasLimitsEmpty = manualExecGasOverrides.length == 0; + // Cache array for gas savings in the loop's condition + GasLimitOverride[] memory emptyGasLimits = new GasLimitOverride[](0); + + for (uint256 i = 0; i < reports.length; ++i) { + _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasOverrides[i]); + } + } + + /// @notice Executes a report, executing each message in order. + /// @param report The execution report containing the messages and proofs. + /// @param manualExecGasExecOverrides An array of gas limits to use for manual execution. + /// @dev If called from the DON, this array is always empty. + /// @dev If called from manual execution, this array is always same length as messages. + function _executeSingleReport( + Internal.ExecutionReport memory report, + GasLimitOverride[] memory manualExecGasExecOverrides + ) internal { + uint64 sourceChainSelector = report.sourceChainSelector; + bool manualExecution = manualExecGasExecOverrides.length != 0; + if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { + if (manualExecution) { + // For manual execution we don't want to silently fail so we revert + revert CursedByRMN(sourceChainSelector); + } + // For DON execution we do not revert as a single lane curse can revert the entire batch + emit SkippedReportExecution(sourceChainSelector); + return; + } + + bytes memory onRamp = _getEnabledSourceChainConfig(sourceChainSelector).onRamp; + + uint256 numMsgs = report.messages.length; + if (numMsgs == 0) revert EmptyReport(); + if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData(); + + bytes32[] memory hashedLeaves = new bytes32[](numMsgs); + + for (uint256 i = 0; i < numMsgs; ++i) { + Internal.Any2EVMRampMessage memory message = report.messages[i]; + + // Commits do not verify the destChainSelector in the message, since only the root is committed, + // so we have to check it explicitly + if (message.header.destChainSelector != i_chainSelector) { + revert InvalidMessageDestChainSelector(message.header.destChainSelector); + } + // If the message source chain selector does not match the report's source chain selector and + // the root has not been committed for the report source chain selector, this will be caught by the root verification. + // This acts as an extra check. + if (message.header.sourceChainSelector != sourceChainSelector) { + revert SourceChainSelectorMismatch(sourceChainSelector, message.header.sourceChainSelector); + } + + // We do this hash here instead of in _verify to avoid two separate loops + // over the same data, which increases gas cost. + // Hashing all of the message fields ensures that the message being executed is correct and not tampered with. + // Including the known OnRamp ensures that the message originates from the correct on ramp version + hashedLeaves[i] = Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); + } + + // SECURITY CRITICAL CHECK + // NOTE: This check also verifies that all messages match the report's sourceChainSelector + uint256 timestampCommitted = _verify(sourceChainSelector, hashedLeaves, report.proofs, report.proofFlagBits); + if (timestampCommitted == 0) revert RootNotCommitted(sourceChainSelector); + + // Execute messages + for (uint256 i = 0; i < numMsgs; ++i) { + uint256 gasStart = gasleft(); + Internal.Any2EVMRampMessage memory message = report.messages[i]; + + Internal.MessageExecutionState originalState = + getExecutionState(sourceChainSelector, message.header.sequenceNumber); + // Two valid cases here, we either have never touched this message before, or we tried to execute + // and failed. This check protects against reentry and re-execution because the other state is + // IN_PROGRESS which should not be allowed to execute. + if ( + !( + originalState == Internal.MessageExecutionState.UNTOUCHED + || originalState == Internal.MessageExecutionState.FAILURE + ) + ) { + // If the message has already been executed, we skip it. We want to not revert on race conditions between + // executing parties. This will allow us to open up manual exec while also attempting with the DON, without + // reverting an entire DON batch when a user manually executes while the tx is inflight. + emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); + continue; + } + uint32[] memory tokenGasOverrides; + if (manualExecution) { + tokenGasOverrides = manualExecGasExecOverrides[i].tokenGasOverrides; + bool isOldCommitReport = + (block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds; + // Manually execution is fine if we previously failed or if the commit report is just too old + // Acceptable state transitions: FAILURE->SUCCESS, UNTOUCHED->SUCCESS, FAILURE->FAILURE + if (!(isOldCommitReport || originalState == Internal.MessageExecutionState.FAILURE)) { + revert ManualExecutionNotYetEnabled(sourceChainSelector); + } + + // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override. + if (manualExecGasExecOverrides[i].receiverExecutionGasLimit != 0) { + message.gasLimit = manualExecGasExecOverrides[i].receiverExecutionGasLimit; + } + } else { + // DON can only execute a message once + // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE + if (originalState != Internal.MessageExecutionState.UNTOUCHED) { + emit AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber); + continue; + } + } + + // Nonce changes per state transition (these only apply for ordered messages): + // UNTOUCHED -> FAILURE nonce bump + // UNTOUCHED -> SUCCESS nonce bump + // FAILURE -> FAILURE no nonce bump + // FAILURE -> SUCCESS no nonce bump + // UNTOUCHED messages MUST be executed in order always + // If nonce == 0 then out of order execution is allowed + if (message.header.nonce != 0) { + if (originalState == Internal.MessageExecutionState.UNTOUCHED) { + // If a nonce is not incremented, that means it was skipped, and we can ignore the message + if ( + !INonceManager(i_nonceManager).incrementInboundNonce( + sourceChainSelector, message.header.nonce, message.sender + ) + ) continue; + } + } + + // Although we expect only valid messages will be committed, we check again + // when executing as a defense in depth measure. + bytes[] memory offchainTokenData = report.offchainTokenData[i]; + if (message.tokenAmounts.length != offchainTokenData.length) { + revert TokenDataMismatch(sourceChainSelector, message.header.sequenceNumber); + } + + _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); + (Internal.MessageExecutionState newState, bytes memory returnData) = + _trialExecute(message, offchainTokenData, tokenGasOverrides); + _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); + + // Since it's hard to estimate whether manual execution will succeed, we + // revert the entire transaction if it fails. This will show the user if + // their manual exec will fail before they submit it. + if (manualExecution) { + if (newState == Internal.MessageExecutionState.FAILURE) { + if (originalState != Internal.MessageExecutionState.UNTOUCHED) { + // If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we + // would still be making progress by changing the state from UNTOUCHED to FAILURE. + revert ExecutionError(message.header.messageId, returnData); + } + } + } + + // The only valid prior states are UNTOUCHED and FAILURE (checked above) + // The only valid post states are FAILURE and SUCCESS (checked below) + if (newState != Internal.MessageExecutionState.SUCCESS) { + if (newState != Internal.MessageExecutionState.FAILURE) { + revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState); + } + } + + emit ExecutionStateChanged( + sourceChainSelector, + message.header.sequenceNumber, + message.header.messageId, + hashedLeaves[i], + newState, + returnData, + // This emit covers not only the execution through the router, but also all of the overhead in executing the + // message. This gives the most accurate representation of the gas used in the execution. + gasStart - gasleft() + ); + } + } + + /// @notice Try executing a message. + /// @param message Internal.Any2EVMRampMessage memory message. + /// @param offchainTokenData Data provided by the DON for token transfers. + /// @return executionState The new state of the message, being either SUCCESS or FAILURE. + /// @return errData Revert data in bytes if CCIP receiver reverted during execution. + function _trialExecute( + Internal.Any2EVMRampMessage memory message, + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides + ) internal returns (Internal.MessageExecutionState executionState, bytes memory) { + try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {} + catch (bytes memory err) { + // return the message execution state as FAILURE and the revert data + // Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES + return (Internal.MessageExecutionState.FAILURE, err); + } + // If message execution succeeded, no CCIP receiver return data is expected, return with empty bytes. + return (Internal.MessageExecutionState.SUCCESS, ""); + } + + /// @notice Executes a single message. + /// @param message The message that will be executed. + /// @param offchainTokenData Token transfer data to be passed to TokenPool. + /// @dev We make this external and callable by the contract itself, in order to try/catch + /// its execution and enforce atomicity among successful message processing and token transfer. + /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts + /// (for example smart contract wallets) without an associated message. + function executeSingleMessage( + Internal.Any2EVMRampMessage memory message, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) external { + if (msg.sender != address(this)) revert CanOnlySelfCall(); + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); + if (message.tokenAmounts.length > 0) { + destTokenAmounts = _releaseOrMintTokens( + message.tokenAmounts, + message.sender, + message.receiver, + message.header.sourceChainSelector, + offchainTokenData, + tokenGasOverrides + ); + } + + Client.Any2EVMMessage memory any2EvmMessage = Client.Any2EVMMessage({ + messageId: message.header.messageId, + sourceChainSelector: message.header.sourceChainSelector, + sender: abi.encode(message.sender), + data: message.data, + destTokenAmounts: destTokenAmounts + }); + + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + try IMessageInterceptor(messageInterceptor).onInboundMessage(any2EvmMessage) {} + catch (bytes memory err) { + revert IMessageInterceptor.MessageValidationError(err); + } + } + + // There are three cases in which we skip calling the receiver: + // 1. If the message data is empty AND the gas limit is 0. + // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract + // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the + // receiver without any gas, which would revert the transaction. + // 2. If the receiver is not a contract. + // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. + // + // The ordering of these checks is important, as the first check is the cheapest to execute. + if ( + (message.data.length == 0 && message.gasLimit == 0) || message.receiver.code.length == 0 + || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) + ) return; + + (bool success, bytes memory returnData,) = s_sourceChainConfigs[message.header.sourceChainSelector] + .router + .routeMessage(any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver); + // If CCIP receiver execution is not successful, revert the call including token transfers + if (!success) revert ReceiverError(returnData); + } + + // ================================================================ + // │ Tokens and pools │ + // ================================================================ + + /// @notice Uses a pool to release or mint a token to a receiver address, with balance checks before and after the + /// transfer. This is done to ensure the exact number of tokens the pool claims to release are actually transferred. + /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the + /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by + /// registering the token on this chain, and re-trying the msg. + /// @param sourceTokenAmount Amount and source data of the token to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector + /// @param offchainTokenData Data fetched offchain by the DON. + /// @return destTokenAmount local token address with amount + function _releaseOrMintSingleToken( + Internal.Any2EVMTokenTransfer memory sourceTokenAmount, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes memory offchainTokenData + ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { + // We need to safely decode the token address from the sourceTokenData, as it could be wrong, + // in which case it doesn't have to be a valid EVM address. + // We assume this destTokenAddress has already been fully validated by a (trusted) OnRamp. + address localToken = sourceTokenAmount.destTokenAddress; + // We check with the token admin registry if the token has a pool on this chain. + address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); + // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. + // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. + // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should + // account for 90k gas overhead due to the interface check. + if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { + revert NotACompatiblePool(localPoolAddress); + } + + // We retrieve the local token balance of the receiver before the pool call. + (uint256 balancePre, uint256 gasLeft) = _getBalanceOfReceiver(receiver, localToken, sourceTokenAmount.destGasAmount); + + // We determined that the pool address is a valid EVM address, but that does not mean the code at this + // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location + // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. + // We call the pool with exact gas to increase resistance against malicious tokens or token pools. + // We protect against return data bombs by capping the return data size at MAX_RET_BYTES. + (bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas + ._callWithExactGasSafeReturnData( + abi.encodeCall( + IPoolV1.releaseOrMint, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: receiver, + amount: sourceTokenAmount.amount, + localToken: localToken, + remoteChainSelector: sourceChainSelector, + sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, + sourcePoolData: sourceTokenAmount.extraData, + offchainTokenData: offchainTokenData + }) + ), + localPoolAddress, + gasLeft, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + + // Wrap and rethrow the error so we can catch it lower in the stack + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should be the local token address. + if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { + revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); + } + + uint256 localAmount = abi.decode(returnData, (uint256)); + // We don't need to do balance checks if the pool is the receiver, as they would always fail in the case + // of a lockRelease pool. + if (receiver != localPoolAddress) { + (uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint); + + // First we check if the subtraction would result in an underflow to ensure we revert with a clear error + if (balancePost < balancePre || balancePost - balancePre != localAmount) { + revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost); + } + } + + return Client.EVMTokenAmount({token: localToken, amount: localAmount}); + } + + /// @notice Retrieves the balance of a receiver address for a given token. + /// @param receiver The address to check the balance of. + /// @param token The token address. + /// @param gasLimit The gas limit to use for the call. + /// @return balance The balance of the receiver. + /// @return gasLeft The gas left after the call. + function _getBalanceOfReceiver( + address receiver, + address token, + uint256 gasLimit + ) internal returns (uint256 balance, uint256 gasLeft) { + (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( + abi.encodeCall(IERC20.balanceOf, (receiver)), + token, + gasLimit, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should contain only the balance. + if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { + revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length); + } + + // Return the decoded balance, which cannot fail as we checked the length, and the gas that is left + // after this call. + return (abi.decode(returnData, (uint256)), gasLimit - gasUsed); + } + + /// @notice Uses pools to release or mint a number of different tokens to a receiver address. + /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector. + /// @param offchainTokenData Array of token data fetched offchain by the DON. + /// @return destTokenAmounts local token addresses with amounts + /// @dev This function wraps the token pool call in a try catch block to gracefully handle + /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error + /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. + function _releaseOrMintTokens( + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { + destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); + bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; + for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { + if (!isTokenGasOverridesEmpty) { + if (tokenGasOverrides[i] != 0) { + sourceTokenAmounts[i].destGasAmount = tokenGasOverrides[i]; + } + } + destTokenAmounts[i] = _releaseOrMintSingleToken( + sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] + ); + } + + return destTokenAmounts; + } + + // ================================================================ + // │ Commit │ + // ================================================================ + + /// @notice Transmit function for commit reports. The function requires signatures, + /// and expects the commit plugin type to be configured with signatures. + /// @param report serialized commit report + /// @dev A commitReport can have two distinct parts (batched together to amortize the cost of checking sigs): + /// 1. Price updates + /// 2. A batch of merkle root and sequence number intervals (per-source) + /// Both have their own, separate, staleness checks, with price updates using the epoch and round + /// number of the latest price update. The merkle root checks for staleness are based on the seqNums. + /// They need to be separate because a price report for round t+2 might be included before a report + /// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid + /// and should not be rejected. When a report with a stale root but valid price updates is submitted, + /// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges. + /// If that happens, prices will be updated in later rounds. + function commit( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external { + CommitReport memory commitReport = abi.decode(report, (CommitReport)); + + // Verify RMN signatures + if (commitReport.merkleRoots.length > 0) { + i_rmnRemote.verify(address(this), commitReport.merkleRoots, commitReport.rmnSignatures, commitReport.rmnRawVs); + } + + // Check if the report contains price updates + if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) + { + uint64 ocrSequenceNumber = uint64(uint256(reportContext[1])); + + // Check for price staleness based on the epoch and round + if (s_latestPriceSequenceNumber < ocrSequenceNumber) { + // If prices are not stale, update the latest epoch and round + s_latestPriceSequenceNumber = ocrSequenceNumber; + // And update the prices in the fee quoter + IFeeQuoter(s_dynamicConfig.feeQuoter).updatePrices(commitReport.priceUpdates); + } else { + // If prices are stale and the report doesn't contain a root, this report + // does not have any valid information and we revert. + // If it does contain a merkle root, continue to the root checking section. + if (commitReport.merkleRoots.length == 0) revert StaleCommitReport(); + } + } + + for (uint256 i = 0; i < commitReport.merkleRoots.length; ++i) { + Internal.MerkleRoot memory root = commitReport.merkleRoots[i]; + uint64 sourceChainSelector = root.sourceChainSelector; + + if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { + revert CursedByRMN(sourceChainSelector); + } + + SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); + + if (keccak256(root.onRampAddress) != keccak256(sourceChainConfig.onRamp)) { + revert CommitOnRampMismatch(root.onRampAddress, sourceChainConfig.onRamp); + } + + if (sourceChainConfig.minSeqNr != root.minSeqNr || root.minSeqNr > root.maxSeqNr) { + revert InvalidInterval(root.sourceChainSelector, root.minSeqNr, root.maxSeqNr); + } + + bytes32 merkleRoot = root.merkleRoot; + if (merkleRoot == bytes32(0)) revert InvalidRoot(); + // If we reached this section, the report should contain a valid root + // We disallow duplicate roots as that would reset the timestamp and + // delay potential manual execution. + if (s_roots[root.sourceChainSelector][merkleRoot] != 0) { + revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot); + } + + sourceChainConfig.minSeqNr = root.maxSeqNr + 1; + s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; + } + + emit CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); + } + + /// @notice Returns the sequence number of the last price update. + /// @return sequenceNumber The latest price update sequence number. + function getLatestPriceSequenceNumber() external view returns (uint64) { + return s_latestPriceSequenceNumber; + } + + /// @notice Returns the timestamp of a potentially previously committed merkle root. + /// If the root was never committed 0 will be returned. + /// @param sourceChainSelector The source chain selector. + /// @param root The merkle root to check the commit status for. + /// @return timestamp The timestamp of the committed root or zero in the case that it was never + /// committed. + function getMerkleRoot(uint64 sourceChainSelector, bytes32 root) external view returns (uint256) { + return s_roots[sourceChainSelector][root]; + } + + /// @notice Returns timestamp of when root was accepted or 0 if verification fails. + /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, + /// proofs and proofFlagBits being used to get the root of the inner tree. + /// This root is then used as the singular leaf of the outer tree. + /// @return timestamp The commit timestamp of the root + function _verify( + uint64 sourceChainSelector, + bytes32[] memory hashedLeaves, + bytes32[] memory proofs, + uint256 proofFlagBits + ) internal view virtual returns (uint256 timestamp) { + bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); + return s_roots[sourceChainSelector][root]; + } + + /// @inheritdoc MultiOCR3Base + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal override { + if (ocrPluginType == uint8(Internal.OCRPluginType.Commit)) { + // Signature verification must be enabled for commit plugin + if (!s_ocrConfigs[ocrPluginType].configInfo.isSignatureVerificationEnabled) { + revert SignatureVerificationDisabled(); + } + // When the OCR config changes, we reset the sequence number + // since it is scoped per config digest. + // Note that s_minSeqNr/roots do not need to be reset as the roots persist + // across reconfigurations and are de-duplicated separately. + s_latestPriceSequenceNumber = 0; + } + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Returns the static config. + /// @dev This function will always return the same struct as the contents is static and can never change. + /// RMN depends on this function, if changing, please notify the RMN maintainers. + /// @return staticConfig The static config. + function getStaticConfig() external view returns (StaticConfig memory) { + return StaticConfig({ + chainSelector: i_chainSelector, + rmnRemote: i_rmnRemote, + tokenAdminRegistry: i_tokenAdminRegistry, + nonceManager: i_nonceManager + }); + } + + /// @notice Returns the current dynamic config. + /// @return dynamicConfig The current dynamic config. + function getDynamicConfig() external view returns (DynamicConfig memory) { + return s_dynamicConfig; + } + + /// @notice Returns the source chain config for the provided source chain selector + /// @param sourceChainSelector chain to retrieve configuration for + /// @return sourceChainConfig The config for the source chain + function getSourceChainConfig( + uint64 sourceChainSelector + ) external view returns (SourceChainConfig memory) { + return s_sourceChainConfigs[sourceChainSelector]; + } + + /// @notice Returns all source chain configs + /// @return sourceChainConfigs The source chain configs corresponding to all the supported chain selectors + function getAllSourceChainConfigs() external view returns (uint64[] memory, SourceChainConfig[] memory) { + SourceChainConfig[] memory sourceChainConfigs = new SourceChainConfig[](s_sourceChainSelectors.length()); + uint64[] memory sourceChainSelectors = new uint64[](s_sourceChainSelectors.length()); + for (uint256 i = 0; i < s_sourceChainSelectors.length(); ++i) { + sourceChainSelectors[i] = uint64(s_sourceChainSelectors.at(i)); + sourceChainConfigs[i] = s_sourceChainConfigs[sourceChainSelectors[i]]; + } + return (sourceChainSelectors, sourceChainConfigs); + } + + /// @notice Updates source configs + /// @param sourceChainConfigUpdates Source chain configs + function applySourceChainConfigUpdates( + SourceChainConfigArgs[] memory sourceChainConfigUpdates + ) external onlyOwner { + _applySourceChainConfigUpdates(sourceChainConfigUpdates); + } + + /// @notice Updates source configs + /// @param sourceChainConfigUpdates Source chain configs + function _applySourceChainConfigUpdates( + SourceChainConfigArgs[] memory sourceChainConfigUpdates + ) internal { + for (uint256 i = 0; i < sourceChainConfigUpdates.length; ++i) { + SourceChainConfigArgs memory sourceConfigUpdate = sourceChainConfigUpdates[i]; + uint64 sourceChainSelector = sourceConfigUpdate.sourceChainSelector; + + if (sourceChainSelector == 0) { + revert ZeroChainSelectorNotAllowed(); + } + + if (address(sourceConfigUpdate.router) == address(0)) { + revert ZeroAddressNotAllowed(); + } + + SourceChainConfig storage currentConfig = s_sourceChainConfigs[sourceChainSelector]; + bytes memory newOnRamp = sourceConfigUpdate.onRamp; + + if (currentConfig.onRamp.length == 0) { + currentConfig.minSeqNr = 1; + emit SourceChainSelectorAdded(sourceChainSelector); + } else if (currentConfig.minSeqNr != 1) { + // OnRamp updates should only happens due to a misconfiguration + // If an OnRamp is misconfigured not reports should have been committed and no messages should have been executed + // This is enforced byt the onRamp address check in the commit function + revert InvalidOnRampUpdate(sourceChainSelector); + } + + // OnRamp can never be zero - if it is, then the source chain has been added for the first time + if (newOnRamp.length == 0 || keccak256(newOnRamp) == EMPTY_ENCODED_ADDRESS_HASH) { + revert ZeroAddressNotAllowed(); + } + + currentConfig.onRamp = newOnRamp; + currentConfig.isEnabled = sourceConfigUpdate.isEnabled; + currentConfig.router = sourceConfigUpdate.router; + + // We don't need to check the return value, as inserting the item twice has no effect. + s_sourceChainSelectors.add(sourceChainSelector); + + emit SourceChainConfigSet(sourceChainSelector, currentConfig); + } + } + + /// @notice Sets the dynamic config. + /// @param dynamicConfig The new dynamic config. + function setDynamicConfig( + DynamicConfig memory dynamicConfig + ) external onlyOwner { + _setDynamicConfig(dynamicConfig); + } + + /// @notice Sets the dynamic config. + /// @param dynamicConfig The dynamic config. + function _setDynamicConfig( + DynamicConfig memory dynamicConfig + ) internal { + if (dynamicConfig.feeQuoter == address(0)) { + revert ZeroAddressNotAllowed(); + } + + s_dynamicConfig = dynamicConfig; + + emit DynamicConfigSet(dynamicConfig); + } + + /// @notice Returns a source chain config with a check that the config is enabled + /// @param sourceChainSelector Source chain selector to check for cursing + /// @return sourceChainConfig The source chain config storage pointer + function _getEnabledSourceChainConfig( + uint64 sourceChainSelector + ) internal view returns (SourceChainConfig storage) { + SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; + if (!sourceChainConfig.isEnabled) { + revert SourceChainNotEnabled(sourceChainSelector); + } + + return sourceChainConfig; + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Reverts as this contract should not be able to receive CCIP messages + function ccipReceive( + Client.Any2EVMMessage calldata + ) external pure { + // solhint-disable-next-line + revert(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol new file mode 100644 index 0000000..d7af0d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; +import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; +import {INonceManager} from "../interfaces/INonceManager.sol"; +import {IPoolV1} from "../interfaces/IPool.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {Pool} from "../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice The OnRamp is a contract that handles lane-specific fee logic +/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them +/// results in an onchain upgrade of all 3. +contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.AddressSet; + using USDPriceWith18Decimals for uint224; + + error CannotSendZeroTokens(); + error UnsupportedToken(address token); + error MustBeCalledByRouter(); + error RouterMustSetOriginalSender(); + error InvalidConfig(); + error CursedByRMN(uint64 sourceChainSelector); + error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); + error InvalidDestChainConfig(uint64 sourceChainSelector); + error OnlyCallableByOwnerOrAllowlistAdmin(); + error SenderNotAllowed(address sender); + error InvalidAllowListRequest(uint64 destChainSelector); + error ReentrancyGuardReentrantCall(); + + event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); + event DestChainConfigSet( + uint64 indexed destChainSelector, uint64 sequenceNumber, IRouter router, bool allowListEnabled + ); + event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); + /// RMN depends on this event, if changing, please notify the RMN maintainers. + event CCIPMessageSent( + uint64 indexed destChainSelector, uint64 indexed sequenceNumber, Internal.EVM2AnyRampMessage message + ); + event AllowListAdminSet(address indexed allowListAdmin); + event AllowListSendersAdded(uint64 indexed destChainSelector, address[] senders); + event AllowListSendersRemoved(uint64 indexed destChainSelector, address[] senders); + + /// @dev Struct that contains the static configuration + /// RMN depends on this struct, if changing, please notify the RMN maintainers. + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint64 chainSelector; // ─────╮ Source chain selector + IRMNRemote rmnRemote; // ─────╯ RMN remote address + address nonceManager; // Nonce manager address + address tokenAdminRegistry; // Token admin registry address + } + + /// @dev Struct that contains the dynamic configuration + // solhint-disable-next-line gas-struct-packing + struct DynamicConfig { + address feeQuoter; // FeeQuoter address + bool reentrancyGuardEntered; // Reentrancy protection + address messageInterceptor; // Optional message interceptor to validate outbound messages (zero address = no interceptor) + address feeAggregator; // Fee aggregator address + address allowListAdmin; // authorized admin to add or remove allowed senders + } + + /// @dev Struct to hold the configs for a destination chain + /// @dev sequenceNumber, allowListEnabled, router will all be packed in 1 slot + struct DestChainConfig { + // The last used sequence number. This is zero in the case where no messages have yet been sent. + // 0 is not a valid sequence number for any real transaction. + uint64 sequenceNumber; // ──────╮ The last used sequence number + bool allowListEnabled; // │ boolean indicator to specify if allowList check is enabled + IRouter router; // ─────────────╯ Local router address that is allowed to send messages to the destination chain. + // This is the list of addresses allowed to send messages from onRamp + EnumerableSet.AddressSet allowedSendersList; + } + + /// @dev Same as DestChainConfig but with the destChainSelector so that an array of these + /// can be passed in the constructor and the applyDestChainConfigUpdates function + //solhint-disable gas-struct-packing + struct DestChainConfigArgs { + uint64 destChainSelector; // ─╮ Destination chain selector + IRouter router; // │ Source router address + bool allowListEnabled; //─────╯ Boolean indicator to specify if allowList check is enabled + } + + /// @dev Struct used to apply AllowList Senders for multiple destChainSelectors + /// @dev the senders in the AllowlistedSenders here is the user that sends the message + /// @dev the config restricts the chain to allow only allowedList of senders to send message from this chain to a destChainSelector + /// @dev destChainSelector, allowListEnabled will be packed in 1 slot + //solhint-disable gas-struct-packing + struct AllowListConfigArgs { + uint64 destChainSelector; // ─────────────╮ Destination chain selector + // │ destChainSelector and allowListEnabled are packed in the same slot + bool allowListEnabled; // ────────────────╯ boolean indicator to specify if allowList check is enabled. + address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList + address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList + } + + // STATIC CONFIG + string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; + /// @dev The chain ID of the source chain that this contract is deployed to + uint64 private immutable i_chainSelector; + /// @dev The rmn contract + IRMNRemote private immutable i_rmnRemote; + /// @dev The address of the nonce manager + address private immutable i_nonceManager; + /// @dev The address of the token admin registry + address private immutable i_tokenAdminRegistry; + + // DYNAMIC CONFIG + /// @dev The dynamic config for the onRamp + DynamicConfig private s_dynamicConfig; + + /// @dev The destination chain specific configs + mapping(uint64 destChainSelector => DestChainConfig destChainConfig) private s_destChainConfigs; + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + DestChainConfigArgs[] memory destChainConfigArgs + ) { + if ( + staticConfig.chainSelector == 0 || address(staticConfig.rmnRemote) == address(0) + || staticConfig.nonceManager == address(0) || staticConfig.tokenAdminRegistry == address(0) + ) { + revert InvalidConfig(); + } + + i_chainSelector = staticConfig.chainSelector; + i_rmnRemote = staticConfig.rmnRemote; + i_nonceManager = staticConfig.nonceManager; + i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; + + _setDynamicConfig(dynamicConfig); + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + // ================================================================ + // │ Messaging │ + // ================================================================ + + /// @notice Gets the next sequence number to be used in the onRamp + /// @param destChainSelector The destination chain selector + /// @return nextSequenceNumber The next sequence number to be used + function getExpectedNextSequenceNumber( + uint64 destChainSelector + ) external view returns (uint64) { + return s_destChainConfigs[destChainSelector].sequenceNumber + 1; + } + + /// @inheritdoc IEVM2AnyOnRampClient + function forwardFromRouter( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message, + uint256 feeTokenAmount, + address originalSender + ) external returns (bytes32) { + // We rely on a reentrancy guard here due to the untrusted calls performed to the pools + // This enables some optimizations by not following the CEI pattern + if (s_dynamicConfig.reentrancyGuardEntered) revert ReentrancyGuardReentrantCall(); + + s_dynamicConfig.reentrancyGuardEntered = true; + + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; + + // NOTE: assumes the message has already been validated through the getFee call + // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. + if (originalSender == address(0)) revert RouterMustSetOriginalSender(); + + if (destChainConfig.allowListEnabled) { + if (!destChainConfig.allowedSendersList.contains(originalSender)) { + revert SenderNotAllowed(originalSender); + } + } + + // Router address may be zero intentionally to pause. + if (msg.sender != address(destChainConfig.router)) revert MustBeCalledByRouter(); + + { + // scoped to reduce stack usage + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + IMessageInterceptor(messageInterceptor).onOutboundMessage(destChainSelector, message); + } + } + + Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + // Should be generated after the message is complete + messageId: "", + sourceChainSelector: i_chainSelector, + destChainSelector: destChainSelector, + // We need the next available sequence number so we increment before we use the value + sequenceNumber: ++destChainConfig.sequenceNumber, + // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we + // may block ordered message nonces, which is not what we want. + nonce: 0 + }), + sender: originalSender, + data: message.data, + extraArgs: "", + receiver: message.receiver, + feeToken: message.feeToken, + feeTokenAmount: feeTokenAmount, + feeValueJuels: 0, // calculated later + // Should be populated via lock / burn pool calls + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) + }); + + // Lock / burn the tokens as last step. TokenPools may not always be trusted. + Client.EVMTokenAmount[] memory tokenAmounts = message.tokenAmounts; + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i] = + _lockOrBurnSingleToken(tokenAmounts[i], destChainSelector, message.receiver, originalSender); + } + + // Convert message fee to juels and retrieve converted args + // Validate pool return data after it is populated (view function - no state changes) + bool isOutOfOrderExecution; + bytes memory convertedExtraArgs; + bytes[] memory destExecDataPerToken; + (newMessage.feeValueJuels, isOutOfOrderExecution, convertedExtraArgs, destExecDataPerToken) = IFeeQuoter( + s_dynamicConfig.feeQuoter + ).processMessageArgs( + destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs, newMessage.tokenAmounts, tokenAmounts + ); + + newMessage.header.nonce = isOutOfOrderExecution + ? 0 + : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); + newMessage.extraArgs = convertedExtraArgs; + + for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; + } + + // Hash only after all fields have been set + newMessage.header.messageId = Internal._hash( + newMessage, + // Metadata hash preimage to ensure global uniqueness, ensuring 2 identical messages sent to 2 different + // lanes will have a distinct hash. + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) + ); + + // Emit message request + // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this + // event in the offchain code. + emit CCIPMessageSent(destChainSelector, newMessage.header.sequenceNumber, newMessage); + + s_dynamicConfig.reentrancyGuardEntered = false; + + return newMessage.header.messageId; + } + + /// @notice Uses a pool to lock or burn a token + /// @param tokenAndAmount Token address and amount to lock or burn + /// @param destChainSelector Target destination chain selector of the message + /// @param receiver Message receiver + /// @param originalSender Message sender + /// @return evm2AnyTokenTransfer EVM2Any token and amount data + function _lockOrBurnSingleToken( + Client.EVMTokenAmount memory tokenAndAmount, + uint64 destChainSelector, + bytes memory receiver, + address originalSender + ) internal returns (Internal.EVM2AnyTokenTransfer memory) { + if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); + + IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); + // We don't have to check if it supports the pool version in a non-reverting way here because + // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface + // function and not through the ERC165Checker. + if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { + revert UnsupportedToken(tokenAndAmount.token); + } + + Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( + Pool.LockOrBurnInV1({ + receiver: receiver, + remoteChainSelector: destChainSelector, + originalSender: originalSender, + amount: tokenAndAmount.amount, + localToken: tokenAndAmount.token + }) + ); + + // NOTE: pool data validations are outsourced to the FeeQuoter to handle family-specific logic handling + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: address(sourcePool), + destTokenAddress: poolReturnData.destTokenAddress, + extraData: poolReturnData.destPoolData, + amount: tokenAndAmount.amount, + destExecData: "" // This is set in the processPoolReturnData function + }); + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Returns the static onRamp config. + /// @dev RMN depends on this function, if modified, please notify the RMN maintainers. + /// @return staticConfig the static configuration. + function getStaticConfig() external view returns (StaticConfig memory) { + return StaticConfig({ + chainSelector: i_chainSelector, + rmnRemote: i_rmnRemote, + nonceManager: i_nonceManager, + tokenAdminRegistry: i_tokenAdminRegistry + }); + } + + /// @notice Returns the dynamic onRamp config. + /// @return dynamicConfig the dynamic configuration. + function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) { + return s_dynamicConfig; + } + + /// @notice Sets the dynamic configuration. + /// @param dynamicConfig The configuration. + function setDynamicConfig( + DynamicConfig memory dynamicConfig + ) external onlyOwner { + _setDynamicConfig(dynamicConfig); + } + + /// @notice Gets the source router for a destination chain + /// @param destChainSelector The destination chain selector + /// @return router the router for the provided destination chain + function getRouter( + uint64 destChainSelector + ) external view returns (IRouter) { + return s_destChainConfigs[destChainSelector].router; + } + + /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. + function _setDynamicConfig( + DynamicConfig memory dynamicConfig + ) internal { + if ( + dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0) + || dynamicConfig.reentrancyGuardEntered + ) revert InvalidConfig(); + + s_dynamicConfig = dynamicConfig; + + emit ConfigSet( + StaticConfig({ + chainSelector: i_chainSelector, + rmnRemote: i_rmnRemote, + nonceManager: i_nonceManager, + tokenAdminRegistry: i_tokenAdminRegistry + }), + dynamicConfig + ); + } + + /// @notice Updates destination chains specific configs. + /// @param destChainConfigArgs Array of destination chain specific configs. + function applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) external onlyOwner { + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + /// @notice Internal version of applyDestChainConfigUpdates. + function _applyDestChainConfigUpdates( + DestChainConfigArgs[] memory destChainConfigArgs + ) internal { + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + + if (destChainSelector == 0) { + revert InvalidDestChainConfig(destChainSelector); + } + + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; + destChainConfig.router = destChainConfigArg.router; + destChainConfig.allowListEnabled = destChainConfigArg.allowListEnabled; + + emit DestChainConfigSet( + destChainSelector, destChainConfig.sequenceNumber, destChainConfigArg.router, destChainConfig.allowListEnabled + ); + } + } + + /// @notice get ChainConfig configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return sequenceNumber The last used sequence number + /// @return allowListEnabled boolean indicator to specify if allowList check is enabled + /// @return router address of the router + function getDestChainConfig( + uint64 destChainSelector + ) public view returns (uint64 sequenceNumber, bool allowListEnabled, address router) { + DestChainConfig storage config = s_destChainConfigs[destChainSelector]; + sequenceNumber = config.sequenceNumber; + allowListEnabled = config.allowListEnabled; + router = address(config.router); + return (sequenceNumber, allowListEnabled, router); + } + + /// @notice get allowedSenders List configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return array of allowedList of Senders + function getAllowedSendersList( + uint64 destChainSelector + ) public view returns (address[] memory) { + return s_destChainConfigs[destChainSelector].allowedSendersList.values(); + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + /// @notice Updates allowListConfig for Senders + /// @dev configuration used to set the list of senders who are authorized to send messages + /// @param allowListConfigArgsItems Array of AllowListConfigArguments where each item is for a destChainSelector + function applyAllowListUpdates( + AllowListConfigArgs[] calldata allowListConfigArgsItems + ) external { + if (msg.sender != owner()) { + if (msg.sender != s_dynamicConfig.allowListAdmin) { + revert OnlyCallableByOwnerOrAllowlistAdmin(); + } + } + + for (uint256 i = 0; i < allowListConfigArgsItems.length; ++i) { + AllowListConfigArgs memory allowListConfigArgs = allowListConfigArgsItems[i]; + + DestChainConfig storage destChainConfig = s_destChainConfigs[allowListConfigArgs.destChainSelector]; + destChainConfig.allowListEnabled = allowListConfigArgs.allowListEnabled; + + if (allowListConfigArgs.addedAllowlistedSenders.length > 0) { + if (allowListConfigArgs.allowListEnabled) { + for (uint256 j = 0; j < allowListConfigArgs.addedAllowlistedSenders.length; ++j) { + address toAdd = allowListConfigArgs.addedAllowlistedSenders[j]; + if (toAdd == address(0)) { + revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); + } + destChainConfig.allowedSendersList.add(toAdd); + } + + emit AllowListSendersAdded(allowListConfigArgs.destChainSelector, allowListConfigArgs.addedAllowlistedSenders); + } else { + revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); + } + } + + for (uint256 j = 0; j < allowListConfigArgs.removedAllowlistedSenders.length; ++j) { + destChainConfig.allowedSendersList.remove(allowListConfigArgs.removedAllowlistedSenders[j]); + } + + if (allowListConfigArgs.removedAllowlistedSenders.length > 0) { + emit AllowListSendersRemoved( + allowListConfigArgs.destChainSelector, allowListConfigArgs.removedAllowlistedSenders + ); + } + } + } + + // ================================================================ + // │ Tokens and pools │ + // ================================================================ + + /// @inheritdoc IEVM2AnyOnRampClient + function getPoolBySourceToken(uint64, /*destChainSelector*/ IERC20 sourceToken) public view returns (IPoolV1) { + return IPoolV1(ITokenAdminRegistry(i_tokenAdminRegistry).getPool(address(sourceToken))); + } + + /// @inheritdoc IEVM2AnyOnRampClient + function getSupportedTokens( + uint64 /*destChainSelector*/ + ) external pure returns (address[] memory) { + revert GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); + } + + // ================================================================ + // │ Fees │ + // ================================================================ + + /// @inheritdoc IEVM2AnyOnRampClient + /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does. + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount) { + if (i_rmnRemote.isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); + + return IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedFee(destChainSelector, message); + } + + /// @notice Withdraws the outstanding fee token balances to the fee aggregator. + /// @dev This function can be permissionless as it only transfers accepted fee tokens to the fee aggregator which is a trusted address. + function withdrawFeeTokens() external { + address[] memory feeTokens = IFeeQuoter(s_dynamicConfig.feeQuoter).getFeeTokens(); + address feeAggregator = s_dynamicConfig.feeAggregator; + + for (uint256 i = 0; i < feeTokens.length; ++i) { + IERC20 feeToken = IERC20(feeTokens[i]); + uint256 feeTokenBalance = feeToken.balanceOf(address(this)); + + if (feeTokenBalance > 0) { + feeToken.safeTransfer(feeAggregator, feeTokenBalance); + + emit FeeTokenWithdrawn(feeAggregator, address(feeToken), feeTokenBalance); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol new file mode 100644 index 0000000..1ba13a4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; +import {TokenPool} from "./TokenPool.sol"; + +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice This pool mints and burns a 3rd-party token. +/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. +/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. +/// The only way to change whitelisting mode is to deploy a new pool. +/// If that is expected, please make sure the token's burner/minter roles are adjustable. +/// @dev This contract is a variant of BurnMintTokenPool that uses `burnFrom(from, amount)`. +contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { + using SafeERC20 for IBurnMintERC20; + + string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0"; + + constructor( + IBurnMintERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, allowlist, rmnProxy, router) { + // Some tokens allow burning from the sender without approval, but not all do. + // To be safe, we approve the pool to burn from the pool. + token.safeIncreaseAllowance(address(this), type(uint256).max); + } + + /// @inheritdoc BurnMintTokenPoolAbstract + function _burn( + uint256 amount + ) internal virtual override { + IBurnMintERC20(address(i_token)).burnFrom(address(this), amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol new file mode 100644 index 0000000..33026cf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; +import {TokenPool} from "./TokenPool.sol"; + +/// @notice This pool mints and burns a 3rd-party token. +/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. +/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. +/// The only way to change whitelisting mode is to deploy a new pool. +/// If that is expected, please make sure the token's burner/minter roles are adjustable. +/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`. +contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { + string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0"; + + constructor( + IBurnMintERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, allowlist, rmnProxy, router) {} + + /// @inheritdoc BurnMintTokenPoolAbstract + function _burn( + uint256 amount + ) internal virtual override { + IBurnMintERC20(address(i_token)).burn(amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol new file mode 100644 index 0000000..6d743ed --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {Pool} from "../libraries/Pool.sol"; +import {TokenPool} from "./TokenPool.sol"; + +abstract contract BurnMintTokenPoolAbstract is TokenPool { + /// @notice Contains the specific burn call for a pool. + /// @dev overriding this method allows us to create pools with different burn signatures + /// without duplicating the underlying logic. + function _burn( + uint256 amount + ) internal virtual; + + /// @notice Burn the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + _burn(lockOrBurnIn.amount); + + emit Burned(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + /// @notice Mint tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Mint to the receiver + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); + + emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol new file mode 100644 index 0000000..37541bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; +import {TokenPool} from "./TokenPool.sol"; + +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice This pool mints and burns a 3rd-party token. +/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. +/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. +/// The only way to change whitelisting mode is to deploy a new pool. +/// If that is expected, please make sure the token's burner/minter roles are adjustable. +/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(from, amount)`. +contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { + using SafeERC20 for IBurnMintERC20; + + constructor( + IBurnMintERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, allowlist, rmnProxy, router) { + // Some tokens allow burning from the sender without approval, but not all do. + // To be safe, we approve the pool to burn from the pool. + token.safeIncreaseAllowance(address(this), type(uint256).max); + } + + /// @inheritdoc BurnMintTokenPoolAbstract + function _burn( + uint256 amount + ) internal virtual override { + IBurnMintERC20(address(i_token)).burn(address(this), amount); + } + + function typeAndVersion() external pure virtual override returns (string memory) { + return "BurnWithFromMintTokenPool 1.5.0"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol new file mode 100644 index 0000000..0f77304 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {Pool} from "../libraries/Pool.sol"; +import {TokenPool} from "./TokenPool.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice Token pool used for tokens on their native chain. This uses a lock and release mechanism. +/// Because of lock/unlock requiring liquidity, this pool contract also has function to add and remove +/// liquidity. This allows for proper bookkeeping for both user and liquidity provider balances. +/// @dev One token per LockReleaseTokenPool. +contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion { + using SafeERC20 for IERC20; + + error InsufficientLiquidity(); + error LiquidityNotAccepted(); + + event LiquidityTransferred(address indexed from, uint256 amount); + + string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0"; + + /// @dev Whether or not the pool accepts liquidity. + /// External liquidity is not required when there is one canonical token deployed to a chain, + /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant + /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold + bool internal immutable i_acceptLiquidity; + /// @notice The address of the rebalancer. + address internal s_rebalancer; + + constructor( + IERC20 token, + address[] memory allowlist, + address rmnProxy, + bool acceptLiquidity, + address router + ) TokenPool(token, allowlist, rmnProxy, router) { + i_acceptLiquidity = acceptLiquidity; + } + + /// @notice Locks the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + emit Locked(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + /// @notice Release tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Release to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); + + emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + // @inheritdoc IERC165 + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { + return interfaceId == type(ILiquidityContainer).interfaceId || super.supportsInterface(interfaceId); + } + + /// @notice Gets LiquidityManager, can be address(0) if none is configured. + /// @return The current liquidity manager. + function getRebalancer() external view returns (address) { + return s_rebalancer; + } + + /// @notice Sets the LiquidityManager address. + /// @dev Only callable by the owner. + function setRebalancer( + address rebalancer + ) external onlyOwner { + s_rebalancer = rebalancer; + } + + /// @notice Checks if the pool can accept liquidity. + /// @return true if the pool can accept liquidity, false otherwise. + function canAcceptLiquidity() external view returns (bool) { + return i_acceptLiquidity; + } + + /// @notice Adds liquidity to the pool. The tokens should be approved first. + /// @param amount The amount of liquidity to provide. + function provideLiquidity( + uint256 amount + ) external { + if (!i_acceptLiquidity) revert LiquidityNotAccepted(); + if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); + + i_token.safeTransferFrom(msg.sender, address(this), amount); + emit LiquidityAdded(msg.sender, amount); + } + + /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. + /// @param amount The amount of liquidity to remove. + function withdrawLiquidity( + uint256 amount + ) external { + if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); + + if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); + i_token.safeTransfer(msg.sender, amount); + emit LiquidityRemoved(msg.sender, amount); + } + + /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so + /// this pool will have to be set as the rebalancer in the older version of the pool. This allows it to transfer the + /// funds in the old pool to the new pool. + /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the + /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. + /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before + /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the + /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its + /// liquidity. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. + /// @param from The address of the old pool. + /// @param amount The amount of liquidity to transfer. + function transferLiquidity(address from, uint256 amount) external onlyOwner { + LockReleaseTokenPool(from).withdrawLiquidity(amount); + + emit LiquidityTransferred(from, amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol new file mode 100644 index 0000000..e3b4e92 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IPoolV1} from "../interfaces/IPool.sol"; +import {IRMN} from "../interfaces/IRMN.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Pool} from "../libraries/Pool.sol"; +import {RateLimiter} from "../libraries/RateLimiter.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice Base abstract class with common functions for all token pools. +/// A token pool serves as isolated place for holding tokens and token specific logic +/// that may execute as tokens move across the bridge. +abstract contract TokenPool is IPoolV1, OwnerIsCreator { + using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableSet for EnumerableSet.UintSet; + using RateLimiter for RateLimiter.TokenBucket; + + error CallerIsNotARampOnRouter(address caller); + error ZeroAddressNotAllowed(); + error SenderNotAllowed(address sender); + error AllowListNotEnabled(); + error NonExistentChain(uint64 remoteChainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error CursedByRMN(); + error ChainAlreadyExists(uint64 chainSelector); + error InvalidSourcePoolAddress(bytes sourcePoolAddress); + error InvalidToken(address token); + error Unauthorized(address caller); + + event Locked(address indexed sender, uint256 amount); + event Burned(address indexed sender, uint256 amount); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event ChainAdded( + uint64 remoteChainSelector, + bytes remoteToken, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainRemoved(uint64 remoteChainSelector); + event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); + event AllowListAdd(address sender); + event AllowListRemove(address sender); + event RouterUpdated(address oldRouter, address newRouter); + + struct ChainUpdate { + uint64 remoteChainSelector; // ──╮ Remote chain selector + bool allowed; // ────────────────╯ Whether the chain should be enabled + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain + RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + } + + struct RemoteChainConfig { + RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain + RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + } + + /// @dev The bridgeable token that is managed by this pool. + IERC20 internal immutable i_token; + /// @dev The address of the RMN proxy + address internal immutable i_rmnProxy; + /// @dev The immutable flag that indicates if the pool is access-controlled. + bool internal immutable i_allowlistEnabled; + /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. + /// Only takes effect if i_allowlistEnabled is true. + /// This can be used to ensure only token-issuer specified addresses can + /// move tokens. + EnumerableSet.AddressSet internal s_allowList; + /// @dev The address of the router + IRouter internal s_router; + /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to + /// be able to quickly determine (without parsing logs) who can access the pool. + /// @dev The chain selectors are in uint256 format because of the EnumerableSet implementation. + EnumerableSet.UintSet internal s_remoteChainSelectors; + mapping(uint64 remoteChainSelector => RemoteChainConfig) internal s_remoteChainConfigs; + /// @notice The address of the rate limiter admin. + /// @dev Can be address(0) if none is configured. + address internal s_rateLimitAdmin; + + constructor(IERC20 token, address[] memory allowlist, address rmnProxy, address router) { + if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); + i_token = token; + i_rmnProxy = rmnProxy; + s_router = IRouter(router); + + // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. + i_allowlistEnabled = allowlist.length > 0; + if (i_allowlistEnabled) { + _applyAllowListUpdates(new address[](0), allowlist); + } + } + + /// @notice Get RMN proxy address + /// @return rmnProxy Address of RMN proxy + function getRmnProxy() public view returns (address rmnProxy) { + return i_rmnProxy; + } + + /// @inheritdoc IPoolV1 + function isSupportedToken( + address token + ) public view virtual returns (bool) { + return token == address(i_token); + } + + /// @notice Gets the IERC20 token that this pool can lock or burn. + /// @return token The IERC20 token representation. + function getToken() public view returns (IERC20 token) { + return i_token; + } + + /// @notice Gets the pool's Router + /// @return router The pool's Router + function getRouter() public view returns (address router) { + return address(s_router); + } + + /// @notice Sets the pool's Router + /// @param newRouter The new Router + function setRouter( + address newRouter + ) public onlyOwner { + if (newRouter == address(0)) revert ZeroAddressNotAllowed(); + address oldRouter = address(s_router); + s_router = IRouter(newRouter); + + emit RouterUpdated(oldRouter, newRouter); + } + + /// @notice Signals which version of the pool interface is supported + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { + return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId + || interfaceId == type(IERC165).interfaceId; + } + + // ================================================================ + // │ Validation │ + // ================================================================ + + /// @notice Validates the lock or burn input for correctness on + /// - token to be locked or burned + /// - RMN curse status + /// - allowlist status + /// - if the sender is a valid onRamp + /// - rate limit status + /// @param lockOrBurnIn The input to validate. + /// @dev This function should always be called before executing a lock or burn. Not doing so would allow + /// for various exploits. + function _validateLockOrBurn( + Pool.LockOrBurnInV1 memory lockOrBurnIn + ) internal { + if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); + _checkAllowList(lockOrBurnIn.originalSender); + + _onlyOnRamp(lockOrBurnIn.remoteChainSelector); + _consumeOutboundRateLimit(lockOrBurnIn.remoteChainSelector, lockOrBurnIn.amount); + } + + /// @notice Validates the release or mint input for correctness on + /// - token to be released or minted + /// - RMN curse status + /// - if the sender is a valid offRamp + /// - if the source pool is valid + /// - rate limit status + /// @param releaseOrMintIn The input to validate. + /// @dev This function should always be called before executing a release or mint. Not doing so would allow + /// for various exploits. + function _validateReleaseOrMint( + Pool.ReleaseOrMintInV1 memory releaseOrMintIn + ) internal { + if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); + _onlyOffRamp(releaseOrMintIn.remoteChainSelector); + + // Validates that the source pool address is configured on this pool. + bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.remoteChainSelector); + if ( + configuredRemotePool.length == 0 + || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) + ) { + revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); + } + _consumeInboundRateLimit(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); + } + + // ================================================================ + // │ Chain permissions │ + // ================================================================ + + /// @notice Gets the pool address on the remote chain. + /// @param remoteChainSelector Remote chain selector. + /// @dev To support non-evm chains, this value is encoded into bytes + function getRemotePool( + uint64 remoteChainSelector + ) public view returns (bytes memory) { + return s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; + } + + /// @notice Gets the token address on the remote chain. + /// @param remoteChainSelector Remote chain selector. + /// @dev To support non-evm chains, this value is encoded into bytes + function getRemoteToken( + uint64 remoteChainSelector + ) public view returns (bytes memory) { + return s_remoteChainConfigs[remoteChainSelector].remoteTokenAddress; + } + + /// @notice Sets the remote pool address for a given chain selector. + /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. + /// @param remotePoolAddress The address of the remote pool. + function setRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + + bytes memory prevAddress = s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; + s_remoteChainConfigs[remoteChainSelector].remotePoolAddress = remotePoolAddress; + + emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); + } + + /// @inheritdoc IPoolV1 + function isSupportedChain( + uint64 remoteChainSelector + ) public view returns (bool) { + return s_remoteChainSelectors.contains(remoteChainSelector); + } + + /// @notice Get list of allowed chains + /// @return list of chains. + function getSupportedChains() public view returns (uint64[] memory) { + uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); + uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); + for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { + chainSelectors[i] = uint64(uint256ChainSelectors[i]); + } + + return chainSelectors; + } + + /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains + /// need to be allowed on the Router to interact with this pool. + /// @dev Only callable by the owner + /// @param chains A list of chains and their new permission status & rate limits. Rate limits + /// are only used when the chain is being added through `allowed` being true. + function applyChainUpdates( + ChainUpdate[] calldata chains + ) external virtual onlyOwner { + for (uint256 i = 0; i < chains.length; ++i) { + ChainUpdate memory update = chains[i]; + RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); + RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); + + if (update.allowed) { + // If the chain already exists, revert + if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { + revert ChainAlreadyExists(update.remoteChainSelector); + } + + if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { + revert ZeroAddressNotAllowed(); + } + + s_remoteChainConfigs[update.remoteChainSelector] = RemoteChainConfig({ + outboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.outboundRateLimiterConfig.rate, + capacity: update.outboundRateLimiterConfig.capacity, + tokens: update.outboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.outboundRateLimiterConfig.isEnabled + }), + inboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.inboundRateLimiterConfig.rate, + capacity: update.inboundRateLimiterConfig.capacity, + tokens: update.inboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.inboundRateLimiterConfig.isEnabled + }), + remotePoolAddress: update.remotePoolAddress, + remoteTokenAddress: update.remoteTokenAddress + }); + + emit ChainAdded( + update.remoteChainSelector, + update.remoteTokenAddress, + update.outboundRateLimiterConfig, + update.inboundRateLimiterConfig + ); + } else { + // If the chain doesn't exist, revert + if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { + revert NonExistentChain(update.remoteChainSelector); + } + + delete s_remoteChainConfigs[update.remoteChainSelector]; + + emit ChainRemoved(update.remoteChainSelector); + } + } + } + + // ================================================================ + // │ Rate limiting │ + // ================================================================ + + /// @notice Sets the rate limiter admin address. + /// @dev Only callable by the owner. + /// @param rateLimitAdmin The new rate limiter admin address. + function setRateLimitAdmin( + address rateLimitAdmin + ) external onlyOwner { + s_rateLimitAdmin = rateLimitAdmin; + } + + /// @notice Gets the rate limiter admin address. + function getRateLimitAdmin() external view returns (address) { + return s_rateLimitAdmin; + } + + /// @notice Consumes outbound rate limiting capacity in this pool + function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { + s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._consume(amount, address(i_token)); + } + + /// @notice Consumes inbound rate limiting capacity in this pool + function _consumeInboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { + s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._consume(amount, address(i_token)); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); + } + + /// @notice Sets the chain rate limiter config. + /// @param remoteChainSelector The remote chain selector for which the rate limits apply. + /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. + /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. + function setChainRateLimiterConfig( + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) external { + if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); + + _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); + } + + function _setRateLimitConfig( + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) internal { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + RateLimiter._validateTokenBucketConfig(outboundConfig, false); + s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._setTokenBucketConfig(outboundConfig); + RateLimiter._validateTokenBucketConfig(inboundConfig, false); + s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._setTokenBucketConfig(inboundConfig); + emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned onRamp for the given chain on the Router. + function _onlyOnRamp( + uint64 remoteChainSelector + ) internal view { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); + } + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned offRamp for the given chain on the Router. + function _onlyOffRamp( + uint64 remoteChainSelector + ) internal view { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + function _checkAllowList( + address sender + ) internal view { + if (i_allowlistEnabled) { + if (!s_allowList.contains(sender)) { + revert SenderNotAllowed(sender); + } + } + } + + /// @notice Gets whether the allowList functionality is enabled. + /// @return true is enabled, false if not. + function getAllowListEnabled() external view returns (bool) { + return i_allowlistEnabled; + } + + /// @notice Gets the allowed addresses. + /// @return The allowed addresses. + function getAllowList() external view returns (address[] memory) { + return s_allowList.values(); + } + + /// @notice Apply updates to the allow list. + /// @param removes The addresses to be removed. + /// @param adds The addresses to be added. + function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { + _applyAllowListUpdates(removes, adds); + } + + /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. + function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { + if (!i_allowlistEnabled) revert AllowListNotEnabled(); + + for (uint256 i = 0; i < removes.length; ++i) { + address toRemove = removes[i]; + if (s_allowList.remove(toRemove)) { + emit AllowListRemove(toRemove); + } + } + for (uint256 i = 0; i < adds.length; ++i) { + address toAdd = adds[i]; + if (toAdd == address(0)) { + continue; + } + if (s_allowList.add(toAdd)) { + emit AllowListAdd(toAdd); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol new file mode 100644 index 0000000..3691ef1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {TokenPool} from "../TokenPool.sol"; +import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; +import {USDCBridgeMigrator} from "./USDCBridgeMigrator.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A token pool for USDC which uses CCTP for supported chains and Lock/Release for all others +/// @dev The functionality from LockReleaseTokenPool.sol has been duplicated due to lack of compiler support for shared +/// constructors between parents +/// @dev The primary token mechanism in this pool is Burn/Mint with CCTP, with Lock/Release as the +/// secondary, opt in mechanism for chains not currently supporting CCTP. +contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + + event LiquidityTransferred(address indexed from, uint64 indexed remoteChainSelector, uint256 amount); + event LiquidityProviderSet( + address indexed oldProvider, address indexed newProvider, uint64 indexed remoteChainSelector + ); + + event LockReleaseEnabled(uint64 indexed remoteChainSelector); + event LockReleaseDisabled(uint64 indexed remoteChainSelector); + + error LanePausedForCCTPMigration(uint64 remoteChainSelector); + error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); + + /// bytes4(keccak256("NO_CTTP_USE_LOCK_RELEASE")) + bytes4 public constant LOCK_RELEASE_FLAG = 0xd43c7897; + + /// @notice The address of the liquidity provider for a specific chain. + /// External liquidity is not required when there is one canonical token deployed to a chain, + /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant + /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold + mapping(uint64 remoteChainSelector => address liquidityProvider) internal s_liquidityProvider; + + constructor( + ITokenMessenger tokenMessenger, + IERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token), router) {} + + // ================================================================ + // │ Incoming/Outgoing Mechanisms | + // ================================================================ + + /// @notice Locks the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { + // // If the alternative mechanism (L/R) for chains which have it enabled + if (!shouldUseLockRelease(lockOrBurnIn.remoteChainSelector)) { + return super.lockOrBurn(lockOrBurnIn); + } + + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == lockOrBurnIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + + return _lockReleaseOutgoingMessage(lockOrBurnIn); + } + + /// @notice Release tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + // Use CCTP Burn/Mint mechanism for chains which have it enabled. The LOCK_RELEASE_FLAG is used in sourcePoolData to + // discern this, since the source-chain will not be a hybrid-pool but a standard burn-mint. In the event of a + // stuck message after a migration has occured, and the message was not executed properly before the migration + // began, and locked tokens were not released until now, the message will already have been committed to with this + // flag so it is safe to release the tokens. The source USDC pool is trusted to send messages with the correct + // flag as well. + if (bytes4(releaseOrMintIn.sourcePoolData) != LOCK_RELEASE_FLAG) { + return super.releaseOrMint(releaseOrMintIn); + } + + return _lockReleaseIncomingMessage(releaseOrMintIn); + } + + /// @notice Contains the alternative mechanism for incoming tokens, in this implementation is "Release" incoming tokens + function _lockReleaseIncomingMessage( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) internal virtual returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Circle requires a supply-lock to prevent incoming messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == releaseOrMintIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + + // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration + // If the chain has already been migrated, then this mapping would be zero, and the operation would underflow. + // This branch ensures that we're subtracting from the correct mapping. It is also safe to subtract from the + // excluded tokens mapping, as this function would only be invoked in the event of a stuck tx after a migration + if (s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] == 0) { + s_tokensExcludedFromBurn[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } else { + s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } + + // Release to the offRamp, which forwards it to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); + + emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + /// @notice Contains the alternative mechanism, in this implementation is "Lock" on outgoing tokens + function _lockReleaseOutgoingMessage( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) internal virtual returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + // Increase internal accounting of locked tokens for burnLockedUSDC() migration + s_lockedTokensByChainSelector[lockOrBurnIn.remoteChainSelector] += lockOrBurnIn.amount; + + emit Locked(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: abi.encode(LOCK_RELEASE_FLAG) + }); + } + + // ================================================================ + // │ Liquidity Management | + // ================================================================ + + /// @notice Gets LiquidityManager, can be address(0) if none is configured. + /// @return The current liquidity manager for the given chain selector + function getLiquidityProvider( + uint64 remoteChainSelector + ) external view returns (address) { + return s_liquidityProvider[remoteChainSelector]; + } + + /// @notice Sets the LiquidityManager address. + /// @dev Only callable by the owner. + function setLiquidityProvider(uint64 remoteChainSelector, address liquidityProvider) external onlyOwner { + address oldProvider = s_liquidityProvider[remoteChainSelector]; + + s_liquidityProvider[remoteChainSelector] = liquidityProvider; + + emit LiquidityProviderSet(oldProvider, liquidityProvider, remoteChainSelector); + } + + /// @notice Adds liquidity to the pool for a specific chain. The tokens should be approved first. + /// @dev Liquidity is expected to be added on a per chain basis. Parties are expected to provide liquidity for their + /// own chain which implements non canonical USDC and liquidity is not shared across lanes. + /// @dev Once liquidity is added, it is locked in the pool until it is removed by an incoming message on the + /// lock release mechanism. This is a hard requirement by Circle to ensure parity with the destination chain + /// supply is maintained. + /// @param amount The amount of tokens to provide as liquidity. + /// @param remoteChainSelector The chain for which liquidity is provided to. Necessary to ensure there's accurate + /// parity between locked USDC in this contract and the circulating supply on the remote chain + function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { + if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + + s_lockedTokensByChainSelector[remoteChainSelector] += amount; + + i_token.safeTransferFrom(msg.sender, address(this), amount); + + emit ILiquidityContainer.LiquidityAdded(msg.sender, amount); + } + + /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. + /// @param remoteChainSelector The chain where liquidity is being released. + /// @param amount The amount of liquidity to remove. + /// @dev The function should only be called if non canonical USDC on the remote chain has been burned and is not being + /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply + /// which may block a potential future migration of the chain to CCTP. + function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (remoteChainSelector == s_proposedUSDCMigrationChain) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } + + s_lockedTokensByChainSelector[remoteChainSelector] -= amount; + + i_token.safeTransfer(msg.sender, amount); + + emit ILiquidityContainer.LiquidityRemoved(msg.sender, amount); + } + + /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so + /// this pool must be the owner of the old pool. Since the pool uses two-step ownership transfer, the old pool must + /// first propose the ownership transfer, and then this pool must accept it. This function can only be called after + /// the ownership transfer has been proposed, as it will accept it and then make the call to withdrawLiquidity + /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the + /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. + /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before + /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the + /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its + /// liquidity. + /// @param from The address of the old pool. + /// @param remoteChainSelector The chain for which liquidity is being transferred. + function transferLiquidity(address from, uint64 remoteChainSelector) external onlyOwner { + // Prevent Liquidity Transfers when a migration is pending. This prevents requiring the new pool to manage + // token exclusions for edge-case messages and ensures that the migration is completed before any new liquidity + // is added to the pool. + if (HybridLockReleaseUSDCTokenPool(from).getCurrentProposedCCTPChainMigration() == remoteChainSelector) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } + + OwnerIsCreator(from).acceptOwnership(); + + // Withdraw all available liquidity from the old pool. + uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); + HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); + + s_lockedTokensByChainSelector[remoteChainSelector] += withdrawAmount; + + emit LiquidityTransferred(from, remoteChainSelector, withdrawAmount); + } + + // ================================================================ + // │ Alt Mechanism Logic | + // ================================================================ + + /// @notice Return whether a lane should use the alternative L/R mechanism in the token pool. + /// @param remoteChainSelector the remote chain the lane is interacting with + /// @return bool Return true if the alternative L/R mechanism should be used + function shouldUseLockRelease( + uint64 remoteChainSelector + ) public view virtual returns (bool) { + return s_shouldUseLockRelease[remoteChainSelector]; + } + + /// @notice Updates Updates designations for chains on whether to use primary or alt mechanism on CCIP messages + /// @param removes A list of chain selectors to disable Lock-Release, and enforce BM + /// @param adds A list of chain selectors to enable LR instead of BM + function updateChainSelectorMechanisms(uint64[] calldata removes, uint64[] calldata adds) external onlyOwner { + for (uint256 i = 0; i < removes.length; ++i) { + delete s_shouldUseLockRelease[removes[i]]; + emit LockReleaseDisabled(removes[i]); + } + + for (uint256 i = 0; i < adds.length; ++i) { + s_shouldUseLockRelease[adds[i]] = true; + emit LockReleaseEnabled(adds[i]); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol new file mode 100644 index 0000000..1b2a0f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, Circle Internet Financial Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pragma solidity ^0.8.0; + +interface IMessageTransmitter { + /// @notice Unlocks USDC tokens on the destination chain + /// @param message The original message on the source chain + /// * Message format: + /// * Field Bytes Type Index + /// * version 4 uint32 0 + /// * sourceDomain 4 uint32 4 + /// * destinationDomain 4 uint32 8 + /// * nonce 8 uint64 12 + /// * sender 32 bytes32 20 + /// * recipient 32 bytes32 52 + /// * destinationCaller 32 bytes32 84 + /// * messageBody dynamic bytes 116 + /// param attestation A valid attestation is the concatenated 65-byte signature(s) of + /// exactly `thresholdSignature` signatures, in increasing order of attester address. + /// ***If the attester addresses recovered from signatures are not in increasing order, + /// signature verification will fail.*** + /// If incorrect number of signatures or duplicate signatures are supplied, + /// signature verification will fail. + function receiveMessage(bytes calldata message, bytes calldata attestation) external returns (bool success); + + /// Returns domain of chain on which the contract is deployed. + /// @dev immutable + function localDomain() external view returns (uint32); + + /// Returns message format version. + /// @dev immutable + function version() external view returns (uint32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol new file mode 100644 index 0000000..ce5923c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022, Circle Internet Financial Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pragma solidity ^0.8.0; + +interface ITokenMessenger { + /// @notice Emitted when a DepositForBurn message is sent + /// @param nonce Unique nonce reserved by message + /// @param burnToken Address of token burnt on source domain + /// @param amount Deposit amount + /// @param depositor Address where deposit is transferred from + /// @param mintRecipient Address receiving minted tokens on destination domain as bytes32 + /// @param destinationDomain Destination domain + /// @param destinationTokenMessenger Address of TokenMessenger on destination domain as bytes32 + /// @param destinationCaller Authorized caller as bytes32 of receiveMessage() on destination domain, + /// if not equal to bytes32(0). If equal to bytes32(0), any address can call receiveMessage(). + event DepositForBurn( + uint64 indexed nonce, + address indexed burnToken, + uint256 amount, + address indexed depositor, + bytes32 mintRecipient, + uint32 destinationDomain, + bytes32 destinationTokenMessenger, + bytes32 destinationCaller + ); + + /// @notice Burns the tokens on the source side to produce a nonce through + /// Circles Cross Chain Transfer Protocol. + /// @param amount Amount of tokens to deposit and burn. + /// @param destinationDomain Destination domain identifier. + /// @param mintRecipient Address of mint recipient on destination domain. + /// @param burnToken Address of contract to burn deposited tokens, on local domain. + /// @param destinationCaller Caller on the destination domain, as bytes32. + /// @return nonce The unique nonce used in unlocking the funds on the destination chain. + /// @dev emits DepositForBurn + function depositForBurnWithCaller( + uint256 amount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken, + bytes32 destinationCaller + ) external returns (uint64 nonce); + + /// Returns the version of the message body format. + /// @dev immutable + function messageBodyVersion() external view returns (uint32); + + /// Returns local Message Transmitter responsible for sending and receiving messages + /// to/from remote domainsmessage transmitter for this token messenger. + /// @dev immutable + function localMessageTransmitter() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol new file mode 100644 index 0000000..4737a83 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -0,0 +1,162 @@ +pragma solidity ^0.8.24; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +import {Router} from "../../Router.sol"; + +/// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract +/// functionality is based on hard requirements defined by Circle to allow for future CCTP compatibility +/// https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md +abstract contract USDCBridgeMigrator is OwnerIsCreator { + using EnumerableSet for EnumerableSet.UintSet; + + event CCTPMigrationProposed(uint64 remoteChainSelector); + event CCTPMigrationExecuted(uint64 remoteChainSelector, uint256 USDCBurned); + event CCTPMigrationCancelled(uint64 existingProposalSelector); + event CircleMigratorAddressSet(address migratorAddress); + event TokensExcludedFromBurn( + uint64 indexed remoteChainSelector, uint256 amount, uint256 burnableAmountAfterExclusion + ); + + error onlyCircle(); + error ExistingMigrationProposal(); + error NoExistingMigrationProposal(); + error NoMigrationProposalPending(); + error InvalidChainSelector(uint64 remoteChainSelector); + + IBurnMintERC20 internal immutable i_USDC; + Router internal immutable i_router; + + address internal s_circleUSDCMigrator; + uint64 internal s_proposedUSDCMigrationChain; + + mapping(uint64 chainSelector => uint256 lockedBalance) internal s_lockedTokensByChainSelector; + mapping(uint64 remoteChainSelector => uint256 excludedTokens) internal s_tokensExcludedFromBurn; + + mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; + + constructor(address token, address router) { + i_USDC = IBurnMintERC20(token); + i_router = Router(router); + } + + /// @notice Burn USDC locked for a specific lane so that destination USDC can be converted from + /// non-canonical to canonical USDC. + /// @dev This function can only be called by an address specified by the owner to be controlled by circle + /// @dev proposeCCTPMigration must be called first on an approved lane to execute properly. + /// @dev This function signature should NEVER be overwritten, otherwise it will be unable to be called by + /// circle to properly migrate USDC over to CCTP. + function burnLockedUSDC() public { + if (msg.sender != s_circleUSDCMigrator) revert onlyCircle(); + if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); + + uint64 burnChainSelector = s_proposedUSDCMigrationChain; + + // Burnable tokens is the total locked minus the amount excluded from burn + uint256 tokensToBurn = + s_lockedTokensByChainSelector[burnChainSelector] - s_tokensExcludedFromBurn[burnChainSelector]; + + // Even though USDC is a trusted call, ensure CEI by updating state first + delete s_lockedTokensByChainSelector[burnChainSelector]; + delete s_proposedUSDCMigrationChain; + + // This should only be called after this contract has been granted a "zero allowance minter role" on USDC by Circle, + // otherwise the call will revert. Executing this burn will functionally convert all USDC on the destination chain + // to canonical USDC by removing the canonical USDC backing it from circulation. + i_USDC.burn(tokensToBurn); + + // Disable L/R automatically on burned chain and enable CCTP + delete s_shouldUseLockRelease[burnChainSelector]; + + emit CCTPMigrationExecuted(burnChainSelector, tokensToBurn); + } + + /// @notice Propose a destination chain to migrate from lock/release mechanism to CCTP enabled burn/mint + /// through a Circle controlled burn. + /// @param remoteChainSelector the CCIP specific selector for the remote chain currently using a + /// non-canonical form of USDC which they wish to update to canonical. Function will revert if an existing migration + /// proposal is already in progress. + /// @dev This function can only be called by the owner + function proposeCCTPMigration( + uint64 remoteChainSelector + ) external onlyOwner { + // Prevent overwriting existing migration proposals until the current one is finished + if (s_proposedUSDCMigrationChain != 0) revert ExistingMigrationProposal(); + + s_proposedUSDCMigrationChain = remoteChainSelector; + + emit CCTPMigrationProposed(remoteChainSelector); + } + + /// @notice Cancel an existing proposal to migrate a lane to CCTP. + /// @notice This function will revert if no proposal is currently in progress. + function cancelExistingCCTPMigrationProposal() external onlyOwner { + if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); + + uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; + delete s_proposedUSDCMigrationChain; + + // If a migration is cancelled, the tokens excluded from burn should be reset, and must be manually + // re-excluded if the proposal is re-proposed in the future + delete s_tokensExcludedFromBurn[currentProposalChainSelector]; + + emit CCTPMigrationCancelled(currentProposalChainSelector); + } + + /// @notice retrieve the chain selector for an ongoing CCTP migration in progress. + /// @return uint64 the chain selector of the lane to be migrated. Will be zero if no proposal currently + /// exists + function getCurrentProposedCCTPChainMigration() public view returns (uint64) { + return s_proposedUSDCMigrationChain; + } + + /// @notice Set the address of the circle-controlled wallet which will execute a CCTP lane migration + /// @dev The function should only be invoked once the address has been confirmed by Circle prior to + /// chain expansion. + function setCircleMigratorAddress( + address migrator + ) external onlyOwner { + s_circleUSDCMigrator = migrator; + + emit CircleMigratorAddressSet(migrator); + } + + /// @notice Retrieve the amount of canonical USDC locked into this lane and minted on the destination + /// @param remoteChainSelector the CCIP specific destination chain implementing a mintable and + /// non-canonical form of USDC at present. + /// @return uint256 the amount of USDC locked into the specified lane. If non-zero, the number + /// should match the current circulating supply of USDC on the destination chain + function getLockedTokensForChain( + uint64 remoteChainSelector + ) public view returns (uint256) { + return s_lockedTokensByChainSelector[remoteChainSelector]; + } + + /// @notice Exclude tokens to be burned in a CCTP-migration because the amount are locked in an undelivered message. + /// @dev When a message is sitting in manual execution from the L/R chain, those tokens need to be excluded from + /// being burned in a CCTP-migration otherwise the message will never be able to be delivered due to it not having + /// an attestation on the source-chain to mint. In that instance it should use provided liquidity that was designated + /// @dev This function should ONLY be called on the home chain, where tokens are locked, NOT on the remote chain + /// and strict scrutiny should be applied to ensure that the amount of tokens excluded is accurate. + function excludeTokensFromBurn(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + s_tokensExcludedFromBurn[remoteChainSelector] += amount; + + uint256 burnableAmountAfterExclusion = + s_lockedTokensByChainSelector[remoteChainSelector] - s_tokensExcludedFromBurn[remoteChainSelector]; + + emit TokensExcludedFromBurn(remoteChainSelector, amount, burnableAmountAfterExclusion); + } + + /// @notice Get the amount of tokens excluded from being burned in a CCTP-migration + /// @dev The sum of locked tokens and excluded tokens should equal the supply of the token on the remote chain + /// @param remoteChainSelector The chain for which the excluded tokens are being queried + /// @return uint256 amount of tokens excluded from being burned in a CCTP-migration + function getExcludedTokensByChain( + uint64 remoteChainSelector + ) public view returns (uint256) { + return s_tokensExcludedFromBurn[remoteChainSelector]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol new file mode 100644 index 0000000..addfe06 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IMessageTransmitter} from "./IMessageTransmitter.sol"; +import {ITokenMessenger} from "./ITokenMessenger.sol"; + +import {Pool} from "../../libraries/Pool.sol"; +import {TokenPool} from "../TokenPool.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice This pool mints and burns USDC tokens through the Cross Chain Transfer +/// Protocol (CCTP). +contract USDCTokenPool is TokenPool, ITypeAndVersion { + using SafeERC20 for IERC20; + + event DomainsSet(DomainUpdate[]); + event ConfigSet(address tokenMessenger); + + error UnknownDomain(uint64 domain); + error UnlockingUSDCFailed(); + error InvalidConfig(); + error InvalidDomain(DomainUpdate domain); + error InvalidMessageVersion(uint32 version); + error InvalidTokenMessengerVersion(uint32 version); + error InvalidNonce(uint64 expected, uint64 got); + error InvalidSourceDomain(uint32 expected, uint32 got); + error InvalidDestinationDomain(uint32 expected, uint32 got); + error InvalidReceiver(bytes receiver); + + // This data is supplied from offchain and contains everything needed + // to receive the USDC tokens. + struct MessageAndAttestation { + bytes message; + bytes attestation; + } + + // A domain is a USDC representation of a chain. + struct DomainUpdate { + bytes32 allowedCaller; // Address allowed to mint on the domain + uint32 domainIdentifier; // ──╮ Unique domain ID + uint64 destChainSelector; // │ The destination chain for this domain + bool enabled; // ─────────────╯ Whether the domain is enabled + } + + struct SourceTokenDataPayload { + uint64 nonce; + uint32 sourceDomain; + } + + string public constant override typeAndVersion = "USDCTokenPool 1.5.0"; + + // We restrict to the first version. New pool may be required for subsequent versions. + uint32 public constant SUPPORTED_USDC_VERSION = 0; + + // The local USDC config + ITokenMessenger public immutable i_tokenMessenger; + IMessageTransmitter public immutable i_messageTransmitter; + uint32 public immutable i_localDomainIdentifier; + + /// A domain is a USDC representation of a destination chain. + /// @dev Zero is a valid domain identifier. + /// @dev The address to mint on the destination chain is the corresponding USDC pool. + struct Domain { + bytes32 allowedCaller; // Address allowed to mint on the domain + uint32 domainIdentifier; // ─╮ Unique domain ID + bool enabled; // ────────────╯ Whether the domain is enabled + } + + // A mapping of CCIP chain identifiers to destination domains + mapping(uint64 chainSelector => Domain CCTPDomain) private s_chainToDomain; + + constructor( + ITokenMessenger tokenMessenger, + IERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, allowlist, rmnProxy, router) { + if (address(tokenMessenger) == address(0)) revert InvalidConfig(); + IMessageTransmitter transmitter = IMessageTransmitter(tokenMessenger.localMessageTransmitter()); + uint32 transmitterVersion = transmitter.version(); + if (transmitterVersion != SUPPORTED_USDC_VERSION) revert InvalidMessageVersion(transmitterVersion); + uint32 tokenMessengerVersion = tokenMessenger.messageBodyVersion(); + if (tokenMessengerVersion != SUPPORTED_USDC_VERSION) revert InvalidTokenMessengerVersion(tokenMessengerVersion); + + i_tokenMessenger = tokenMessenger; + i_messageTransmitter = transmitter; + i_localDomainIdentifier = transmitter.localDomain(); + i_token.safeIncreaseAllowance(address(i_tokenMessenger), type(uint256).max); + emit ConfigSet(address(tokenMessenger)); + } + + /// @notice Burn the token in the pool + /// @dev emits ITokenMessenger.DepositForBurn + /// @dev Assumes caller has validated destinationReceiver + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + Domain memory domain = s_chainToDomain[lockOrBurnIn.remoteChainSelector]; + if (!domain.enabled) revert UnknownDomain(lockOrBurnIn.remoteChainSelector); + + if (lockOrBurnIn.receiver.length != 32) { + revert InvalidReceiver(lockOrBurnIn.receiver); + } + bytes32 decodedReceiver = abi.decode(lockOrBurnIn.receiver, (bytes32)); + + // Since this pool is the msg sender of the CCTP transaction, only this contract + // is able to call replaceDepositForBurn. Since this contract does not implement + // replaceDepositForBurn, the tokens cannot be maliciously re-routed to another address. + uint64 nonce = i_tokenMessenger.depositForBurnWithCaller( + lockOrBurnIn.amount, domain.domainIdentifier, decodedReceiver, address(i_token), domain.allowedCaller + ); + + emit Burned(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: abi.encode(SourceTokenDataPayload({nonce: nonce, sourceDomain: i_localDomainIdentifier})) + }); + } + + /// @notice Mint tokens from the pool to the recipient + /// * sourceTokenData is part of the verified message and passed directly from + /// the offramp so it is guaranteed to be what the lockOrBurn pool released on the + /// source chain. It contains (nonce, sourceDomain) which is guaranteed by CCTP + /// to be unique. + /// * offchainTokenData is untrusted (can be supplied by manual execution), but we assert + /// that (nonce, sourceDomain) is equal to the message's (nonce, sourceDomain) and + /// receiveMessage will assert that Attestation contains a valid attestation signature + /// for that message, including its (nonce, sourceDomain). This way, the only + /// non-reverting offchainTokenData that can be supplied is a valid attestation for the + /// specific message that was sent on source. + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + SourceTokenDataPayload memory sourceTokenDataPayload = + abi.decode(releaseOrMintIn.sourcePoolData, (SourceTokenDataPayload)); + MessageAndAttestation memory msgAndAttestation = + abi.decode(releaseOrMintIn.offchainTokenData, (MessageAndAttestation)); + + _validateMessage(msgAndAttestation.message, sourceTokenDataPayload); + + if (!i_messageTransmitter.receiveMessage(msgAndAttestation.message, msgAndAttestation.attestation)) { + revert UnlockingUSDCFailed(); + } + + emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + /// @notice Validates the USDC encoded message against the given parameters. + /// @param usdcMessage The USDC encoded message + /// @param sourceTokenData The expected source chain token data to check against + /// @dev Only supports version SUPPORTED_USDC_VERSION of the CCTP message format + /// @dev Message format for USDC: + /// * Field Bytes Type Index + /// * version 4 uint32 0 + /// * sourceDomain 4 uint32 4 + /// * destinationDomain 4 uint32 8 + /// * nonce 8 uint64 12 + /// * sender 32 bytes32 20 + /// * recipient 32 bytes32 52 + /// * destinationCaller 32 bytes32 84 + /// * messageBody dynamic bytes 116 + function _validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) internal view { + uint32 version; + // solhint-disable-next-line no-inline-assembly + assembly { + // We truncate using the datatype of the version variable, meaning + // we will only be left with the first 4 bytes of the message. + version := mload(add(usdcMessage, 4)) // 0 + 4 = 4 + } + // This token pool only supports version 0 of the CCTP message format + // We check the version prior to loading the rest of the message + // to avoid unexpected reverts due to out-of-bounds reads. + if (version != SUPPORTED_USDC_VERSION) revert InvalidMessageVersion(version); + + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + + // solhint-disable-next-line no-inline-assembly + assembly { + sourceDomain := mload(add(usdcMessage, 8)) // 4 + 4 = 8 + destinationDomain := mload(add(usdcMessage, 12)) // 8 + 4 = 12 + nonce := mload(add(usdcMessage, 20)) // 12 + 8 = 20 + } + + if (sourceDomain != sourceTokenData.sourceDomain) { + revert InvalidSourceDomain(sourceTokenData.sourceDomain, sourceDomain); + } + if (destinationDomain != i_localDomainIdentifier) { + revert InvalidDestinationDomain(i_localDomainIdentifier, destinationDomain); + } + if (nonce != sourceTokenData.nonce) revert InvalidNonce(sourceTokenData.nonce, nonce); + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Gets the CCTP domain for a given CCIP chain selector. + function getDomain( + uint64 chainSelector + ) external view returns (Domain memory) { + return s_chainToDomain[chainSelector]; + } + + /// @notice Sets the CCTP domain for a CCIP chain selector. + /// @dev Must verify mapping of selectors -> (domain, caller) offchain. + function setDomains( + DomainUpdate[] calldata domains + ) external onlyOwner { + for (uint256 i = 0; i < domains.length; ++i) { + DomainUpdate memory domain = domains[i]; + if (domain.allowedCaller == bytes32(0) || domain.destChainSelector == 0) revert InvalidDomain(domain); + + s_chainToDomain[domain.destChainSelector] = Domain({ + domainIdentifier: domain.domainIdentifier, + allowedCaller: domain.allowedCaller, + enabled: domain.enabled + }); + } + emit DomainsSet(domains); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol new file mode 100644 index 0000000..9645826 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +/// @notice The ARMProxy serves to allow CCIP contracts +/// to point to a static address for ARM queries, which saves gas +/// since each contract need not store an ARM address in storage. That way +/// we can add ARM queries along many code paths for increased defense in depth +/// with minimal additional cost. +contract ARMProxy is OwnerIsCreator, ITypeAndVersion { + error ZeroAddressNotAllowed(); + + event ARMSet(address arm); + + // STATIC CONFIG + string public constant override typeAndVersion = "ARMProxy 1.0.0"; + + // DYNAMIC CONFIG + address private s_arm; + + constructor( + address arm + ) { + setARM(arm); + } + + /// @notice SetARM sets the ARM implementation contract address. + /// @param arm The address of the arm implementation contract. + function setARM( + address arm + ) public onlyOwner { + if (arm == address(0)) revert ZeroAddressNotAllowed(); + s_arm = arm; + emit ARMSet(arm); + } + + /// @notice getARM gets the ARM implementation contract address. + /// @return arm The address of the arm implementation contract. + function getARM() external view returns (address) { + return s_arm; + } + + // We use a fallback function instead of explicit implementations of the functions + // defined in IRMN.sol to preserve compatibility with future additions to the IRMN + // interface. Calling IRMN interface methods in ARMProxy should be transparent, i.e. + // their input/output behaviour should be identical to calling the proxied s_arm + // contract directly. (If s_arm doesn't point to a contract, we always revert.) + // solhint-disable-next-line payable-fallback, no-complex-fallback + fallback() external { + address arm = s_arm; + // solhint-disable-next-line no-inline-assembly + assembly { + // Revert if no contract present at destination address, otherwise call + // might succeed unintentionally. + if iszero(extcodesize(arm)) { revert(0, 0) } + // We use memory starting at zero, overwriting anything that might already + // be stored there. This messes with Solidity's expectations around memory + // layout, but it's fine because we always exit execution of this contract + // inside this assembly block, i.e. we don't cede control to code generated + // by the Solidity compiler that might have expectations around memory + // layout. + // Copy calldatasize() bytes from calldata offset 0 to memory offset 0. + calldatacopy(0, 0, calldatasize()) + // Call the underlying ARM implementation. out and outsize are 0 because + // we don't know the size yet. We hardcode value to zero. + let success := call(gas(), arm, 0, 0, calldatasize(), 0, 0) + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + // Pass through successful return or revert and associated data. + if success { return(0, returndatasize()) } + revert(0, returndatasize()) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol new file mode 100644 index 0000000..978b200 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +/// @notice Stores the home configuration for RMN, that is referenced by CCIP oracles, RMN nodes, and the RMNRemote +/// contracts. +/// @dev This contract is a state machine with the following states: +/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. +/// [0, 0] +/// +/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. +/// [0, 1] +/// +/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. +/// [1, 0] +/// +/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. +/// [1, 1] +/// +/// The following state transitions are allowed: +/// - Init -> Candidate: setCandidate() +/// - Candidate -> Active: promoteCandidateAndRevokeActive() +/// - Candidate -> Candidate: setCandidate() +/// - Candidate -> Init: revokeCandidate() +/// - Active -> ActiveAndCandidate: setCandidate() +/// - Active -> Init: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() +/// - ActiveAndCandidate -> Active: revokeCandidate() +/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() +/// +/// This means the following calls are not allowed at the following states: +/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. +/// - Init: revokeCandidate(), as there is no config to revoke +/// - Active: revokeCandidate(), as there is no candidate to revoke +/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but +/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable +/// config as candidate and promote that, but fully clearing it is cleaner. +/// +/// ┌─────────────┐ setCandidate ┌─────────────┐ +/// │ ├───────────────────►│ │ setCandidate +/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ +/// │ │ ┌─────────────────┤ │ +/// └─────────────┘ │ promote- └─────────────┘ +/// ▲ │ Candidate +/// promote- │ │ +/// Candidate │ │ +/// │ │ +/// ┌──────────┴──┐ │ promote- ┌─────────────┐ +/// │ │◄─┘ Candidate OR │ Active & │ setCandidate +/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ +/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ +/// │ ├───────────────────►│ │ +/// └─────────────┘ setSecondary └─────────────┘ +/// +contract RMNHome is OwnerIsCreator, ITypeAndVersion { + event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); + event ActiveConfigRevoked(bytes32 indexed configDigest); + event CandidateConfigRevoked(bytes32 indexed configDigest); + event DynamicConfigSet(bytes32 indexed configDigest, DynamicConfig dynamicConfig); + event ConfigPromoted(bytes32 indexed configDigest); + + error OutOfBoundsNodesLength(); + error DuplicatePeerId(); + error DuplicateOffchainPublicKey(); + error DuplicateSourceChain(); + error OutOfBoundsObserverNodeIndex(); + error MinObserversTooHigh(); + error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); + error DigestNotFound(bytes32 configDigest); + error RevokingZeroDigestNotAllowed(); + error NoOpStateTransitionNotAllowed(); + + struct Node { + bytes32 peerId; // Used for p2p communication. + bytes32 offchainPublicKey; // Observations are signed with this public key, and are only verified offchain. + } + + struct SourceChain { + uint64 chainSelector; // ─────╮ The Source chain selector. + uint64 minObservers; // ──────╯ Required number of observers to agree on an observation for this source chain. + // ObserverNodesBitmap & (1< MAX_NODES) { + revert OutOfBoundsNodesLength(); + } + + // Ensure no peerId or offchainPublicKey is duplicated. + for (uint256 i = 0; i < staticConfig.nodes.length; ++i) { + for (uint256 j = i + 1; j < staticConfig.nodes.length; ++j) { + if (staticConfig.nodes[i].peerId == staticConfig.nodes[j].peerId) { + revert DuplicatePeerId(); + } + if (staticConfig.nodes[i].offchainPublicKey == staticConfig.nodes[j].offchainPublicKey) { + revert DuplicateOffchainPublicKey(); + } + } + } + + _validateDynamicConfig(dynamicConfig, staticConfig.nodes.length); + } + + /// @notice Validates the dynamic config. Reverts when the config is invalid. + /// @param dynamicConfig The dynamic part of the config. + /// @param numberOfNodes The number of nodes in the static config. + function _validateDynamicConfig(DynamicConfig memory dynamicConfig, uint256 numberOfNodes) internal pure { + uint256 numberOfSourceChains = dynamicConfig.sourceChains.length; + for (uint256 i = 0; i < numberOfSourceChains; ++i) { + SourceChain memory currentSourceChain = dynamicConfig.sourceChains[i]; + // Ensure the source chain is unique. + for (uint256 j = i + 1; j < numberOfSourceChains; ++j) { + if (currentSourceChain.chainSelector == dynamicConfig.sourceChains[j].chainSelector) { + revert DuplicateSourceChain(); + } + } + + // all observer node indices are valid + uint256 bitmap = currentSourceChain.observerNodesBitmap; + // Check if there are any bits set for indexes outside of the expected range. + if (bitmap & (type(uint256).max >> (256 - numberOfNodes)) != bitmap) { + revert OutOfBoundsObserverNodeIndex(); + } + + uint256 observersCount = 0; + for (; bitmap != 0; ++observersCount) { + bitmap &= bitmap - 1; + } + + // minObservers are tenable + if (currentSourceChain.minObservers > observersCount) { + revert MinObserversTooHigh(); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol new file mode 100644 index 0000000..6a4366e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -0,0 +1,261 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; +import {Internal} from "../libraries/Internal.sol"; + +/// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a +/// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is +/// deployed, relying on isCursed(). +bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; + +/// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject for +/// issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using +/// the local chain selector as a subject. +bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; + +/// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. +contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNRemote { + using EnumerableSet for EnumerableSet.Bytes16Set; + + error AlreadyCursed(bytes16 subject); + error ConfigNotSet(); + error DuplicateOnchainPublicKey(); + error InvalidSignature(); + error InvalidSignerOrder(); + error MinSignersTooHigh(); + error NotCursed(bytes16 subject); + error OutOfOrderSignatures(); + error ThresholdNotMet(); + error UnexpectedSigner(); + error ZeroValueNotAllowed(); + + event ConfigSet(uint32 indexed version, Config config); + event Cursed(bytes16[] subjects); + event Uncursed(bytes16[] subjects); + + /// @dev the configuration of an RMN signer + struct Signer { + address onchainPublicKey; // ────╮ For signing reports + uint64 nodeIndex; // ────────────╯ Maps to nodes in home chain config, should be strictly increasing + } + + /// @dev the contract config + /// @dev note: minSigners can be set to 0 to disable verification for chains without RMN support + struct Config { + bytes32 rmnHomeContractConfigDigest; // Digest of the RMNHome contract config + Signer[] signers; // List of signers + uint64 minSigners; // Threshold for the number of signers required to verify a report + } + + /// @dev part of the payload that RMN nodes sign: keccak256(abi.encode(RMN_V1_6_ANY2EVM_REPORT, report)) + /// @dev this struct is only ever abi-encoded and hashed; it is never stored + struct Report { + uint256 destChainId; // To guard against chain selector misconfiguration + uint64 destChainSelector; // ────────────╮ The chain selector of the destination chain + address rmnRemoteContractAddress; // ─────╯ The address of this contract + address offrampAddress; // The address of the offramp on the same chain as this contract + bytes32 rmnHomeContractConfigDigest; // The digest of the RMNHome contract config + Internal.MerkleRoot[] merkleRoots; // The dest lane updates + } + + /// @dev this is included in the preimage of the digest that RMN nodes sign + bytes32 private constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); + + string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; + uint64 internal immutable i_localChainSelector; + + Config private s_config; + uint32 private s_configCount; + + EnumerableSet.Bytes16Set private s_cursedSubjects; + mapping(address signer => bool exists) private s_signers; // for more gas efficient verify + + /// @param localChainSelector the chain selector of the chain this contract is deployed to + constructor( + uint64 localChainSelector + ) { + if (localChainSelector == 0) revert ZeroValueNotAllowed(); + i_localChainSelector = localChainSelector; + } + + // ================================================================ + // │ Verification │ + // ================================================================ + + /// @inheritdoc IRMNRemote + function verify( + address offrampAddress, + Internal.MerkleRoot[] calldata merkleRoots, + Signature[] calldata signatures, + uint256 rawVs + ) external view { + if (s_configCount == 0) { + revert ConfigNotSet(); + } + if (signatures.length < s_config.minSigners) revert ThresholdNotMet(); + + bytes32 digest = keccak256( + abi.encode( + RMN_V1_6_ANY2EVM_REPORT, + Report({ + destChainId: block.chainid, + destChainSelector: i_localChainSelector, + rmnRemoteContractAddress: address(this), + offrampAddress: offrampAddress, + rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + + address prevAddress; + address signerAddress; + for (uint256 i = 0; i < signatures.length; ++i) { + // The v value is bit-encoded into rawVs + signerAddress = ecrecover(digest, 27 + uint8(rawVs & 0x01 << i), signatures[i].r, signatures[i].s); + if (signerAddress == address(0)) revert InvalidSignature(); + if (prevAddress >= signerAddress) revert OutOfOrderSignatures(); + if (!s_signers[signerAddress]) revert UnexpectedSigner(); + prevAddress = signerAddress; + } + } + + // ================================================================ + // │ Config │ + // ================================================================ + + /// @notice Sets the configuration of the contract + /// @param newConfig the new configuration + /// @dev setting config is atomic; we delete all pre-existing config and set everything from scratch + function setConfig( + Config calldata newConfig + ) external onlyOwner { + // signers are in ascending order of nodeIndex + for (uint256 i = 1; i < newConfig.signers.length; ++i) { + if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { + revert InvalidSignerOrder(); + } + } + + // minSigners is tenable + if (!(newConfig.minSigners <= newConfig.signers.length)) { + revert MinSignersTooHigh(); + } + + // clear the old signers + for (uint256 i = s_config.signers.length; i > 0; --i) { + delete s_signers[s_config.signers[i - 1].onchainPublicKey]; + } + + // set the new signers + for (uint256 i = 0; i < newConfig.signers.length; ++i) { + if (s_signers[newConfig.signers[i].onchainPublicKey]) { + revert DuplicateOnchainPublicKey(); + } + s_signers[newConfig.signers[i].onchainPublicKey] = true; + } + + s_config = newConfig; + uint32 newConfigCount = ++s_configCount; + emit ConfigSet(newConfigCount, newConfig); + } + + /// @notice Returns the current configuration of the contract and a version number + /// @return version the current configs version + /// @return config the current config + function getVersionedConfig() external view returns (uint32 version, Config memory config) { + return (s_configCount, s_config); + } + + /// @notice Returns the chain selector configured at deployment time + /// @return localChainSelector the chain selector (not the chain ID) + function getLocalChainSelector() external view returns (uint64 localChainSelector) { + return i_localChainSelector; + } + + /// @notice Returns the 32 byte header used in computing the report digest + /// @return digestHeader the digest header + function getReportDigestHeader() external pure returns (bytes32 digestHeader) { + return RMN_V1_6_ANY2EVM_REPORT; + } + + // ================================================================ + // │ Cursing │ + // ================================================================ + + /// @notice Curse a single subject + /// @param subject the subject to curse + function curse( + bytes16 subject + ) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + curse(subjects); + } + + /// @notice Curse an array of subjects + /// @param subjects the subjects to curse + /// @dev reverts if any of the subjects are already cursed or if there is a duplicate + function curse( + bytes16[] memory subjects + ) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.add(subjects[i])) { + revert AlreadyCursed(subjects[i]); + } + } + emit Cursed(subjects); + } + + /// @notice Uncurse a single subject + /// @param subject the subject to uncurse + function uncurse( + bytes16 subject + ) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + uncurse(subjects); + } + + /// @notice Uncurse an array of subjects + /// @param subjects the subjects to uncurse + /// @dev reverts if any of the subjects are not cursed or if there is a duplicate + function uncurse( + bytes16[] memory subjects + ) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.remove(subjects[i])) { + revert NotCursed(subjects[i]); + } + } + emit Uncursed(subjects); + } + + /// @inheritdoc IRMNRemote + function getCursedSubjects() external view returns (bytes16[] memory subjects) { + return s_cursedSubjects.values(); + } + + /// @inheritdoc IRMNRemote + function isCursed() external view returns (bool) { + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(LEGACY_CURSE_SUBJECT) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); + } + + /// @inheritdoc IRMNRemote + function isCursed( + bytes16 subject + ) external view returns (bool) { + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol new file mode 100644 index 0000000..ea75b4e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +// Imports to any non-library are not allowed due to the significant cascading +// compile time increase they cause when imported into this base test. + +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {RateLimiter} from "../libraries/RateLimiter.sol"; +import {MockRMN} from "./mocks/MockRMN.sol"; +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + // Addresses + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + address internal constant STRANGER = address(999999); + address internal constant DUMMY_CONTRACT_ADDRESS = 0x1111111111111111111111111111111111111112; + address internal constant ON_RAMP_ADDRESS = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; + address internal constant ZERO_ADDRESS = address(0); + address internal constant FEE_AGGREGATOR = 0xa33CDB32eAEce34F6affEfF4899cef45744EDea3; + + address internal constant USER_1 = address(1); + address internal constant USER_2 = address(2); + address internal constant USER_3 = address(3); + address internal constant USER_4 = address(4); + + // Message info + uint64 internal constant SOURCE_CHAIN_SELECTOR = 1; + uint64 internal constant DEST_CHAIN_SELECTOR = 2; + uint32 internal constant GAS_LIMIT = 200_000; + + // Timing + uint256 internal constant BLOCK_TIME = 1234567890; + uint32 internal constant TWELVE_HOURS = 60 * 60 * 12; + + // Onramp + uint96 internal constant MAX_NOP_FEES_JUELS = 1e27; + uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; + uint32 internal constant DEST_GAS_OVERHEAD = 300_000; + uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE = 16; + + uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; + uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 90_000; + uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; + + bool private s_baseTestInitialized; + + // Use 16 gas per data availability byte in our tests. + // This is an overestimation in OP stack, it ignores 4 gas per 0 byte rule. + // Arbitrum on the other hand, does always use 16 gas per data availability byte. + // This value may be substantially decreased after EIP 4844. + uint16 internal constant DEST_GAS_PER_DATA_AVAILABILITY_BYTE = 16; + + // Total L1 data availability overhead estimate is 33_596 gas. + // This value includes complete CommitStore and OffRamp call data. + uint32 internal constant DEST_DATA_AVAILABILITY_OVERHEAD_GAS = 188 // Fixed data availability overhead in OP stack. + + (32 * 31 + 4) * DEST_GAS_PER_DATA_AVAILABILITY_BYTE // CommitStore single-root transmission takes up about 31 slots, plus selector. + + (32 * 34 + 4) * DEST_GAS_PER_DATA_AVAILABILITY_BYTE; // OffRamp transmission excluding EVM2EVMMessage takes up about 34 slots, plus selector. + + // Multiples of bps, or 0.0001, use 6840 to be same as OP mainnet compression factor of 0.684. + uint16 internal constant DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS = 6840; + + // OffRamp + uint32 internal constant MAX_DATA_SIZE = 30_000; + uint16 internal constant MAX_TOKENS_LENGTH = 5; + uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5000; + uint32 internal constant PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS = 500; + uint32 internal constant MAX_GAS_LIMIT = 4_000_000; + + // Rate limiter + address internal constant ADMIN = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; + + MockRMN internal s_mockRMN; + IRMNRemote internal s_mockRMNRemote; + + // nonce for pseudo-random number generation, not to be exposed to test suites + uint256 private randNonce; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + // Set the sender to OWNER permanently + vm.startPrank(OWNER); + deal(OWNER, 1e20); + vm.label(OWNER, "Owner"); + vm.label(STRANGER, "Stranger"); + + // Set the block time to a constant known value + vm.warp(BLOCK_TIME); + + // setup mock RMN & RMNRemote + s_mockRMN = new MockRMN(); + s_mockRMNRemote = IRMNRemote(makeAddr("MOCK RMN REMOTE")); + vm.etch(address(s_mockRMNRemote), bytes("fake bytecode")); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + _setMockRMNGlobalCurse(false); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(false)); // no curses by defaule + } + + function _setMockRMNGlobalCurse( + bool isCursed + ) internal { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(isCursed)); + } + + function _setMockRMNChainCurse(uint64 chainSelector, bool isCursed) internal { + vm.mockCall( + address(s_mockRMNRemote), + abi.encodeWithSignature("isCursed(bytes16)", bytes16(uint128(chainSelector))), + abi.encode(isCursed) + ); + } + + function _getOutboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e15}); + } + + function _getInboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { + return RateLimiter.Config({isEnabled: true, capacity: 222e30, rate: 1e18}); + } + + function _getSingleTokenPriceUpdateStruct( + address token, + uint224 price + ) internal pure returns (Internal.PriceUpdates memory) { + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](1); + tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: token, usdPerToken: price}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); + + return priceUpdates; + } + + /// @dev returns a pseudo-random bytes32 + function _randomBytes32() internal returns (bytes32) { + return keccak256(abi.encodePacked(++randNonce)); + } + + /// @dev returns a pseudo-random number + function _randomNum() internal returns (uint256) { + return uint256(_randomBytes32()); + } + + /// @dev returns a pseudo-random address + function _randomAddress() internal returns (address) { + return address(uint160(_randomNum())); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol new file mode 100644 index 0000000..0dfa2fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICommitStore} from "../interfaces/ICommitStore.sol"; +import {IEVM2AnyOnRamp} from "../interfaces/IEVM2AnyOnRamp.sol"; + +import {NonceManager} from "../NonceManager.sol"; +import {Router} from "../Router.sol"; +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {Pool} from "../libraries/Pool.sol"; +import {RateLimiter} from "../libraries/RateLimiter.sol"; +import {OffRamp} from "../offRamp/OffRamp.sol"; +import {OnRamp} from "../onRamp/OnRamp.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {EVM2EVMOffRampHelper} from "./helpers/EVM2EVMOffRampHelper.sol"; +import {OnRampHelper} from "./helpers/OnRampHelper.sol"; +import {OffRampSetup} from "./offRamp/OffRampSetup.t.sol"; +import {OnRampSetup} from "./onRamp/OnRampSetup.t.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract NonceManager_typeAndVersion is Test { + NonceManager private s_nonceManager; + + function setUp() public { + s_nonceManager = new NonceManager(new address[](0)); + } + + function test_typeAndVersion() public view { + assertEq(s_nonceManager.typeAndVersion(), "NonceManager 1.6.0-dev"); + } +} + +contract NonceManager_NonceIncrementation is BaseTest { + NonceManager private s_nonceManager; + + function setUp() public override { + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(this); + s_nonceManager = new NonceManager(authorizedCallers); + } + + function test_getIncrementedOutboundNonce_Success() public { + address sender = address(this); + + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); + + uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); + assertEq(outboundNonce, 1); + } + + function test_incrementInboundNonce_Success() public { + address sender = address(this); + + s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, 1, abi.encode(sender)); + + assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 1); + } + + function test_incrementInboundNonce_Skip() public { + address sender = address(this); + uint64 expectedNonce = 2; + + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); + + s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); + + assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 0); + } + + function test_incrementNoncesInboundAndOutbound_Success() public { + address sender = address(this); + + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); + uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); + assertEq(outboundNonce, 1); + + // Inbound nonce unchanged + assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 0); + + s_nonceManager.incrementInboundNonce(DEST_CHAIN_SELECTOR, 1, abi.encode(sender)); + assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 1); + + // Outbound nonce unchanged + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 1); + } +} + +contract NonceManager_applyPreviousRampsUpdates is OnRampSetup { + function test_SingleRampUpdate() public { + address prevOnRamp = makeAddr("prevOnRamp"); + address prevOffRamp = makeAddr("prevOffRamp"); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); + } + + function test_MultipleRampsUpdates() public { + address prevOnRamp1 = makeAddr("prevOnRamp1"); + address prevOnRamp2 = makeAddr("prevOnRamp2"); + address prevOffRamp1 = makeAddr("prevOffRamp1"); + address prevOffRamp2 = makeAddr("prevOffRamp2"); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](2); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1)); + previousRamps[1] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR + 1, NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2)); + + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR + 1, previousRamps[1].prevRamps); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); + _assertPreviousRampsEqual( + s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR + 1), previousRamps[1].prevRamps + ); + } + + function test_ZeroInput() public { + vm.recordLogs(); + s_outboundNonceManager.applyPreviousRampsUpdates(new NonceManager.PreviousRampsArgs[](0)); + + assertEq(vm.getRecordedLogs().length, 0); + } + + function test_PreviousRampAlreadySetOnRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOnRamp = makeAddr("prevOnRamp"); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_PreviousRampAlreadySetOffRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOnRamp = makeAddr("prevOnRamp"); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function _assertPreviousRampsEqual( + NonceManager.PreviousRamps memory a, + NonceManager.PreviousRamps memory b + ) internal pure { + assertEq(a.prevOnRamp, b.prevOnRamp); + assertEq(a.prevOffRamp, b.prevOffRamp); + } +} + +contract NonceManager_OnRampUpgrade is OnRampSetup { + uint256 internal constant FEE_AMOUNT = 1234567890; + OnRampHelper internal s_prevOnRamp; + + function setUp() public virtual override { + super.setUp(); + + (s_prevOnRamp,) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) + ); + + // Since the previous onRamp is not a 1.5 ramp it doesn't have the getSenderNonce function. We mock it to return 0 + vm.mockCall(address(s_prevOnRamp), abi.encodeWithSelector(IEVM2AnyOnRamp.getSenderNonce.selector), abi.encode(0)); + + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = + NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(s_prevOnRamp), address(0))); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + (s_onRamp, s_metadataHash) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) + ); + + vm.startPrank(address(s_sourceRouter)); + } + + function test_Upgrade_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + } + + function test_UpgradeSenderNoncesReadsPreviousRamp_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + + for (uint64 i = 1; i < 4; ++i) { + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + assertEq(startNonce + i, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + } + } + + function test_UpgradeNonceStartsAtV1Nonce_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + + // send 1 message from previous onramp + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 1, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + + // new onramp nonce should start from 2, while sequence number start from 1 + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + + // after another send, nonce should be 3, and sequence number be 2 + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 2, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + } + + function test_UpgradeNonceNewSenderStartsAtZero_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + // send 1 message from previous onramp from OWNER + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + address newSender = address(1234567); + // new onramp nonce should start from 1 for new sender + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); + } +} + +contract NonceManager_OffRampUpgrade is OffRampSetup { + EVM2EVMOffRampHelper internal s_prevOffRamp; + + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_3 = abi.decode(ON_RAMP_ADDRESS_3, (address)); + + function setUp() public virtual override { + super.setUp(); + + s_prevOffRamp = new EVM2EVMOffRampHelper(); + + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = NonceManager.PreviousRampsArgs( + SOURCE_CHAIN_SELECTOR_1, NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)) + ); + + s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_1 + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_2 + }); + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_3 + }); + + _setupMultipleOffRampsFromConfigs(sourceChainConfigs); + + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); + } + + function test_Upgraded_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_NoPrevOffRampForChain_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); + + // Nonce unchanged for chain 3 + assertEq(startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0]))); + + Internal.Any2EVMRampMessage[] memory messagesChain3 = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_3, + messagesChain3[0].header.sequenceNumber, + messagesChain3[0].header.messageId, + _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) + ); + } + + function test_UpgradedSenderNoncesReadsPreviousRamp_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); + + for (uint64 i = 1; i < 4; ++i) { + s_prevOffRamp.execute(senders); + + assertEq(startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + } + } + + function test_UpgradedNonceStartsAtV1Nonce_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); + + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + messagesMultiRamp[0].header.nonce++; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) + ); + + messagesMultiRamp[0].header.nonce++; + messagesMultiRamp[0].header.sequenceNumber++; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) + ); + } + + function test_UpgradedNonceNewSenderStartsAtZero_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + s_prevOffRamp.execute(senders); + + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + bytes memory newSender = abi.encode(address(1234567)); + messagesMultiRamp[0].sender = newSender; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + // new sender nonce in new offramp should go from 0 -> 1 + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); + } + + function test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + address newSender = address(1234567); + messages[0].sender = abi.encode(newSender); + messages[0].header.nonce = 2; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + + // new offramp sees msg nonce higher than senderNonce + // it waits for previous offramp to execute + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + + address[] memory senders = new address[](1); + senders[0] = newSender; + + // previous offramp executes msg and increases nonce + s_prevOffRamp.execute(senders); + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + + messages[0].header.nonce = 2; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + // new offramp is able to execute + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md new file mode 100644 index 0000000..99223e1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md @@ -0,0 +1,89 @@ +# Foundry Test Guidelines + +We're using Foundry to test our CCIP smart contracts here. This enables us to test in Solidity. If you need to add tests for anything outside the CCIP contracts, please write them in hardhat (for the time being). + +## Directory Structure + +The test directory structure mimics the source contract file structure as closely as possible. Example: + +`./offRamp/SomeOffRamp.sol` should have a test contract `./test/offRamp/SomeOffRamp.t.sol`. + +## Test File Structure + +Break the test file down into multiple contracts, each contract testing a specific function inside the source contract. + +For Example, here's a source contract `SomeOffRamp`: + +``` +contract SomeOffRamp { + + constructor() { + ... set some state + } + + function firstFunction() public { + ... + } + + function theNextFunction() public { + ... + } + + function _anInternalFunction() internal { + ... + } +} +``` + +Our test file `SomeOffRamp.t.sol` should be structured like this: + +``` +contract SomeOffRamp_constructor { + // constructor state setup tests here +} + +contract SomeOffRamp_firstFunction { + // first function tests here +} + +contract SomeOffRamp_theNextFunction { + // tests here too... +} + +contract SomeOffRamp_anInternalFunction { + // This function will require a helper contract to expose it. +} +``` + +## Test Structure + +Inside each test contract, group tests into `Success` and `Reverts` by starting with all the success cases and then adding a `// Reverts` comments to indicate the failure cases below. + +``` +contract SomeOffRamp_firstFunction { + function testZeroValueSuccess() public { + ... + } + + ... + + + // Reverts + + function testOwnerReverts() public { + // test that an ownable function reverts when not called by the owner + ... + } + + ... + +} +``` + +Function naming should follow this structure, where the `_fuzz_` section denotes whether it's a fuzz test. Do not write tests that are named `testSuccess`, always include the description of the test, even if it's just the name of the function that is being called. + +`test{_fuzz_}{description of test}[Success|Reverts]` + +Try to cover all the code paths present in each function being tested. In most cases, this will result in many more failure tests than success tests. + +If a test file requires a complicated setUp, or if it requires many helper functions (like `_generateAMessageWithNoTokensStruct()`), create a separate file to perform this setup in. Using the example above, `SomeOffRampSetup.t.sol`. Inherit this and call the setUp function in the test file. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol new file mode 100644 index 0000000..2031458 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC677} from "../../shared/token/ERC677/BurnMintERC677.sol"; +import {Client} from "../libraries/Client.sol"; +import {BurnMintTokenPool} from "../pools/BurnMintTokenPool.sol"; +import {LockReleaseTokenPool} from "../pools/LockReleaseTokenPool.sol"; +import {TokenPool} from "../pools/TokenPool.sol"; +import {TokenAdminRegistry} from "../tokenAdminRegistry/TokenAdminRegistry.sol"; +import {MaybeRevertingBurnMintTokenPool} from "./helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {RouterSetup} from "./router/RouterSetup.t.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract TokenSetup is RouterSetup { + address[] internal s_sourceTokens; + address[] internal s_destTokens; + + address internal s_sourceFeeToken; + address internal s_destFeeToken; + + TokenAdminRegistry internal s_tokenAdminRegistry; + + mapping(address sourceToken => address sourcePool) internal s_sourcePoolByToken; + mapping(address sourceToken => address destPool) internal s_destPoolBySourceToken; + mapping(address destToken => address destPool) internal s_destPoolByToken; + mapping(address sourceToken => address destToken) internal s_destTokenBySourceToken; + + function _deploySourceToken(string memory tokenName, uint256 dealAmount, uint8 decimals) internal returns (address) { + BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, decimals, 0); + s_sourceTokens.push(address(token)); + deal(address(token), OWNER, dealAmount); + return address(token); + } + + function _deployDestToken(string memory tokenName, uint256 dealAmount) internal returns (address) { + BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, 18, 0); + s_destTokens.push(address(token)); + deal(address(token), OWNER, dealAmount); + return address(token); + } + + function _deployLockReleasePool(address token, bool isSourcePool) internal { + address router = address(s_sourceRouter); + if (!isSourcePool) { + router = address(s_destRouter); + } + + LockReleaseTokenPool pool = + new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, router); + + if (isSourcePool) { + s_sourcePoolByToken[address(token)] = address(pool); + } else { + s_destPoolByToken[address(token)] = address(pool); + s_destPoolBySourceToken[s_sourceTokens[s_destTokens.length - 1]] = address(pool); + } + } + + function _deployTokenAndBurnMintPool(address token, bool isSourcePool) internal { + address router = address(s_sourceRouter); + if (!isSourcePool) { + router = address(s_destRouter); + } + + BurnMintTokenPool pool = + new MaybeRevertingBurnMintTokenPool(BurnMintERC677(token), new address[](0), address(s_mockRMN), router); + BurnMintERC677(token).grantMintAndBurnRoles(address(pool)); + + if (isSourcePool) { + s_sourcePoolByToken[address(token)] = address(pool); + } else { + s_destPoolByToken[address(token)] = address(pool); + s_destPoolBySourceToken[s_sourceTokens[s_destTokens.length - 1]] = address(pool); + } + } + + function setUp() public virtual override { + RouterSetup.setUp(); + + bool isSetup = s_sourceTokens.length != 0; + if (isSetup) { + return; + } + + // Source tokens & pools + address sourceLink = _deploySourceToken("sLINK", type(uint256).max, 18); + _deployLockReleasePool(sourceLink, true); + s_sourceFeeToken = sourceLink; + + address sourceEth = _deploySourceToken("sETH", 2 ** 128, 18); + _deployTokenAndBurnMintPool(sourceEth, true); + + // Destination tokens & pools + address destLink = _deployDestToken("dLINK", type(uint256).max); + _deployLockReleasePool(destLink, false); + s_destFeeToken = destLink; + + s_destTokenBySourceToken[sourceLink] = destLink; + + address destEth = _deployDestToken("dETH", 2 ** 128); + _deployTokenAndBurnMintPool(destEth, false); + + s_destTokenBySourceToken[sourceEth] = destEth; + + // Float the dest link lock release pool with funds + IERC20(destLink).transfer(s_destPoolByToken[destLink], 1000 ether); + + s_tokenAdminRegistry = new TokenAdminRegistry(); + + // Set pools in the registry + for (uint256 i = 0; i < s_sourceTokens.length; ++i) { + address token = s_sourceTokens[i]; + address pool = s_sourcePoolByToken[token]; + + _setPool( + s_tokenAdminRegistry, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] + ); + } + + for (uint256 i = 0; i < s_destTokens.length; ++i) { + address token = s_destTokens[i]; + address pool = s_destPoolByToken[token]; + s_tokenAdminRegistry.proposeAdministrator(token, OWNER); + s_tokenAdminRegistry.acceptAdminRole(token); + s_tokenAdminRegistry.setPool(token, pool); + + _setPool( + s_tokenAdminRegistry, + token, + pool, + SOURCE_CHAIN_SELECTOR, + s_sourcePoolByToken[s_sourceTokens[i]], + s_sourceTokens[i] + ); + } + } + + function _getCastedSourceEVMTokenAmountsWithZeroAmounts() + internal + view + returns (Client.EVMTokenAmount[] memory tokenAmounts) + { + tokenAmounts = new Client.EVMTokenAmount[](s_sourceTokens.length); + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + tokenAmounts[i].token = s_sourceTokens[i]; + } + return tokenAmounts; + } + + function _setPool( + TokenAdminRegistry tokenAdminRegistry, + address token, + address pool, + uint64 remoteChainSelector, + address remotePoolAddress, + address remoteToken + ) internal { + if (!tokenAdminRegistry.isAdministrator(token, OWNER)) { + tokenAdminRegistry.proposeAdministrator(token, OWNER); + tokenAdminRegistry.acceptAdminRole(token); + } + + tokenAdminRegistry.setPool(token, pool); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: remoteChainSelector, + remotePoolAddress: abi.encode(remotePoolAddress), + remoteTokenAddress: abi.encode(remoteToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + TokenPool(pool).applyChainUpdates(chainUpdates); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol new file mode 100644 index 0000000..bfd2b5f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol @@ -0,0 +1,84 @@ +// Submitted for verification at Etherscan.io on 2017-12-12 + +// Copyright (C) 2015, 2016, 2017 Dapphub + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +pragma solidity 0.8.24; + +// solhint-disable +contract WETH9 { + string public name = "Wrapped Ether"; + string public symbol = "WETH"; + uint8 public decimals = 18; + + event Approval(address indexed src, address indexed guy, uint256 wad); + event Transfer(address indexed src, address indexed dst, uint256 wad); + event Deposit(address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + receive() external payable { + _deposit(); + } + + function _deposit() internal { + balanceOf[msg.sender] += msg.value; + emit Deposit(msg.sender, msg.value); + } + + function deposit() external payable { + _deposit(); + } + + function withdraw( + uint256 wad + ) external { + require(balanceOf[msg.sender] >= wad); + balanceOf[msg.sender] -= wad; + payable(msg.sender).transfer(wad); + emit Withdrawal(msg.sender, wad); + } + + function totalSupply() public view returns (uint256) { + return address(this).balance; + } + + function approve(address guy, uint256 wad) public returns (bool) { + allowance[msg.sender][guy] = wad; + emit Approval(msg.sender, guy, wad); + return true; + } + + function transfer(address dst, uint256 wad) public returns (bool) { + return transferFrom(msg.sender, dst, wad); + } + + function transferFrom(address src, address dst, uint256 wad) public returns (bool) { + require(balanceOf[src] >= wad); + + if (src != msg.sender && allowance[src][msg.sender] != type(uint128).max) { + require(allowance[src][msg.sender] >= wad); + allowance[src][msg.sender] -= wad; + } + + balanceOf[src] -= wad; + balanceOf[dst] += wad; + + emit Transfer(src, dst, wad); + + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol new file mode 100644 index 0000000..c68907b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {DefensiveExample} from "../../applications/DefensiveExample.sol"; +import {Client} from "../../libraries/Client.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract DefensiveExampleTest is OnRampSetup { + event MessageFailed(bytes32 indexed messageId, bytes reason); + event MessageSucceeded(bytes32 indexed messageId); + event MessageRecovered(bytes32 indexed messageId); + + DefensiveExample internal s_receiver; + uint64 internal sourceChainSelector = 7331; + + function setUp() public virtual override { + super.setUp(); + + s_receiver = new DefensiveExample(s_destRouter, IERC20(s_destFeeToken)); + s_receiver.enableChain(sourceChainSelector, abi.encode("")); + } + + function test_Recovery() public { + bytes32 messageId = keccak256("messageId"); + address token = address(s_destFeeToken); + uint256 amount = 111333333777; + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + + // Make sure we give the receiver contract enough tokens like CCIP would. + deal(token, address(s_receiver), amount); + + // Make sure the contract call reverts so we can test recovery. + s_receiver.setSimRevert(true); + + // The receiver contract will revert if the router is not the sender. + vm.startPrank(address(s_destRouter)); + + vm.expectEmit(); + emit MessageFailed(messageId, abi.encodeWithSelector(DefensiveExample.ErrorCase.selector)); + + s_receiver.ccipReceive( + Client.Any2EVMMessage({ + messageId: messageId, + sourceChainSelector: sourceChainSelector, + sender: abi.encode(address(0)), // wrong sender, will revert internally + data: "", + destTokenAmounts: destTokenAmounts + }) + ); + + address tokenReceiver = address(0x000001337); + uint256 tokenReceiverBalancePre = IERC20(token).balanceOf(tokenReceiver); + uint256 receiverBalancePre = IERC20(token).balanceOf(address(s_receiver)); + + // Recovery can only be done by the owner. + vm.startPrank(OWNER); + + vm.expectEmit(); + emit MessageRecovered(messageId); + + s_receiver.retryFailedMessage(messageId, tokenReceiver); + + // Assert the tokens have successfully been rescued from the contract. + assertEq(IERC20(token).balanceOf(tokenReceiver), tokenReceiverBalancePre + amount); + assertEq(IERC20(token).balanceOf(address(s_receiver)), receiverBalancePre - amount); + } + + function test_HappyPath_Success() public { + bytes32 messageId = keccak256("messageId"); + address token = address(s_destFeeToken); + uint256 amount = 111333333777; + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + + // Make sure we give the receiver contract enough tokens like CCIP would. + deal(token, address(s_receiver), amount); + + // The receiver contract will revert if the router is not the sender. + vm.startPrank(address(s_destRouter)); + + vm.expectEmit(); + emit MessageSucceeded(messageId); + + s_receiver.ccipReceive( + Client.Any2EVMMessage({ + messageId: messageId, + sourceChainSelector: sourceChainSelector, + sender: abi.encode(address(s_receiver)), // correct sender + data: "", + destTokenAmounts: destTokenAmounts + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol new file mode 100644 index 0000000..489ebcf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol @@ -0,0 +1,724 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +import {CCIPRouter} from "../../applications/EtherSenderReceiver.sol"; + +import {IRouterClient} from "../../interfaces/IRouterClient.sol"; +import {Client} from "../../libraries/Client.sol"; +import {WETH9} from "../WETH9.sol"; +import {EtherSenderReceiverHelper} from "./../helpers/EtherSenderReceiverHelper.sol"; + +import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; + +contract EtherSenderReceiverTest is Test { + EtherSenderReceiverHelper internal s_etherSenderReceiver; + WETH9 internal s_weth; + WETH9 internal s_someOtherWeth; + ERC20 internal s_linkToken; + + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + address internal constant ROUTER = 0x0F3779ee3a832D10158073ae2F5e61ac7FBBF880; + address internal constant XCHAIN_RECEIVER = 0xBd91b2073218AF872BF73b65e2e5950ea356d147; + + function setUp() public { + vm.startPrank(OWNER); + + s_linkToken = new ERC20("Chainlink Token", "LINK"); + s_someOtherWeth = new WETH9(); + s_weth = new WETH9(); + vm.mockCall(ROUTER, abi.encodeWithSelector(CCIPRouter.getWrappedNative.selector), abi.encode(address(s_weth))); + s_etherSenderReceiver = new EtherSenderReceiverHelper(ROUTER); + + deal(OWNER, 1_000_000 ether); + deal(address(s_linkToken), OWNER, 1_000_000 ether); + + // deposit some eth into the weth contract. + s_weth.deposit{value: 10 ether}(); + uint256 wethSupply = s_weth.totalSupply(); + assertEq(wethSupply, 10 ether, "total weth supply must be 10 ether"); + } +} + +contract EtherSenderReceiverTest_constructor is EtherSenderReceiverTest { + function test_constructor() public view { + assertEq(s_etherSenderReceiver.getRouter(), ROUTER, "router must be set correctly"); + uint256 allowance = s_weth.allowance(address(s_etherSenderReceiver), ROUTER); + assertEq(allowance, type(uint256).max, "allowance must be set infinite"); + } +} + +contract EtherSenderReceiverTest_validateFeeToken is EtherSenderReceiverTest { + uint256 internal constant amount = 100; + + error InsufficientMsgValue(uint256 gotAmount, uint256 msgValue); + error TokenAmountNotEqualToMsgValue(uint256 gotAmount, uint256 msgValue); + + function test_validateFeeToken_valid_native() public { + Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); + tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmount, + feeToken: address(0), + extraArgs: "" + }); + + s_etherSenderReceiver.validateFeeToken{value: amount + 1}(message); + } + + function test_validateFeeToken_valid_feeToken() public { + Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); + tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmount, + feeToken: address(s_weth), + extraArgs: "" + }); + + s_etherSenderReceiver.validateFeeToken{value: amount}(message); + } + + function test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() public { + Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); + tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmount, + feeToken: address(s_weth), + extraArgs: "" + }); + + vm.expectRevert(abi.encodeWithSelector(TokenAmountNotEqualToMsgValue.selector, amount, amount + 1)); + s_etherSenderReceiver.validateFeeToken{value: amount + 1}(message); + } +} + +contract EtherSenderReceiverTest_validatedMessage is EtherSenderReceiverTest { + error InvalidDestinationReceiver(bytes destReceiver); + error InvalidTokenAmounts(uint256 gotAmounts); + error InvalidWethAddress(address want, address got); + error GasLimitTooLow(uint256 minLimit, uint256 gotLimit); + + uint256 internal constant amount = 100; + + function test_Fuzz_validatedMessage_msgSenderOverwrite( + bytes memory data + ) public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: data, + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); + } + + function test_Fuzz_validatedMessage_tokenAddressOverwrite( + address token + ) public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); + } + + function test_validatedMessage_emptyDataOverwrittenToMsgSender() public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); + } + + function test_validatedMessage_dataOverwrittenToMsgSender() public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: abi.encode(address(42)), + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); + } + + function test_validatedMessage_tokenOverwrittenToWeth() public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(42), // incorrect token. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); + } + + function test_validatedMessage_validMessage_extraArgs() public view { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})) + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); + assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); + assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); + assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); + assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); + assertEq( + validatedMessage.extraArgs, + Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), + "extraArgs must be correct" + ); + } + + function test_validatedMessage_invalidTokenAmounts() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: address(0), amount: amount}); + tokenAmounts[1] = Client.EVMTokenAmount({token: address(0), amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + vm.expectRevert(abi.encodeWithSelector(InvalidTokenAmounts.selector, uint256(2))); + s_etherSenderReceiver.validatedMessage(message); + } +} + +contract EtherSenderReceiverTest_getFee is EtherSenderReceiverTest { + uint64 internal constant destinationChainSelector = 424242; + uint256 internal constant feeWei = 121212; + uint256 internal constant amount = 100; + + function test_getFee() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: address(0), amount: amount}); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + + uint256 fee = s_etherSenderReceiver.getFee(destinationChainSelector, message); + assertEq(fee, feeWei, "fee must be feeWei"); + } +} + +contract EtherSenderReceiverTest_ccipReceive is EtherSenderReceiverTest { + uint256 internal constant amount = 100; + uint64 internal constant sourceChainSelector = 424242; + address internal constant XCHAIN_SENDER = 0x9951529C13B01E542f7eE3b6D6665D292e9BA2E0; + + error InvalidTokenAmounts(uint256 gotAmounts); + error InvalidToken(address gotToken, address expectedToken); + + function test_Fuzz_ccipReceive( + uint256 tokenAmount + ) public { + // cap to 10 ether because OWNER only has 10 ether. + if (tokenAmount > 10 ether) { + return; + } + + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: tokenAmount}); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: keccak256(abi.encode("ccip send")), + sourceChainSelector: sourceChainSelector, + sender: abi.encode(XCHAIN_SENDER), + data: abi.encode(OWNER), + destTokenAmounts: destTokenAmounts + }); + + // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. + s_weth.transfer(address(s_etherSenderReceiver), tokenAmount); + + uint256 balanceBefore = OWNER.balance; + s_etherSenderReceiver.publicCcipReceive(message); + uint256 balanceAfter = OWNER.balance; + assertEq(balanceAfter, balanceBefore + tokenAmount, "balance must be correct"); + } + + function test_ccipReceive_happyPath() public { + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: keccak256(abi.encode("ccip send")), + sourceChainSelector: 424242, + sender: abi.encode(XCHAIN_SENDER), + data: abi.encode(OWNER), + destTokenAmounts: destTokenAmounts + }); + + // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. + s_weth.transfer(address(s_etherSenderReceiver), amount); + + uint256 balanceBefore = OWNER.balance; + s_etherSenderReceiver.publicCcipReceive(message); + uint256 balanceAfter = OWNER.balance; + assertEq(balanceAfter, balanceBefore + amount, "balance must be correct"); + } + + function test_ccipReceive_fallbackToWethTransfer() public { + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: keccak256(abi.encode("ccip send")), + sourceChainSelector: 424242, + sender: abi.encode(XCHAIN_SENDER), + data: abi.encode(address(s_linkToken)), // ERC20 cannot receive() ether. + destTokenAmounts: destTokenAmounts + }); + + // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. + s_weth.transfer(address(s_etherSenderReceiver), amount); + + uint256 balanceBefore = address(s_linkToken).balance; + s_etherSenderReceiver.publicCcipReceive(message); + uint256 balanceAfter = address(s_linkToken).balance; + assertEq(balanceAfter, balanceBefore, "balance must be unchanged"); + uint256 wethBalance = s_weth.balanceOf(address(s_linkToken)); + assertEq(wethBalance, amount, "weth balance must be correct"); + } + + function test_ccipReceive_wrongTokenAmount() public { + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](2); + destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + destTokenAmounts[1] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: keccak256(abi.encode("ccip send")), + sourceChainSelector: 424242, + sender: abi.encode(XCHAIN_SENDER), + data: abi.encode(OWNER), + destTokenAmounts: destTokenAmounts + }); + + vm.expectRevert(abi.encodeWithSelector(InvalidTokenAmounts.selector, uint256(2))); + s_etherSenderReceiver.publicCcipReceive(message); + } + + function test_ccipReceive_wrongToken() public { + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); + destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_someOtherWeth), amount: amount}); + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: keccak256(abi.encode("ccip send")), + sourceChainSelector: 424242, + sender: abi.encode(XCHAIN_SENDER), + data: abi.encode(OWNER), + destTokenAmounts: destTokenAmounts + }); + + vm.expectRevert(abi.encodeWithSelector(InvalidToken.selector, address(s_someOtherWeth), address(s_weth))); + s_etherSenderReceiver.publicCcipReceive(message); + } +} + +contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTest { + error InsufficientFee(uint256 gotFee, uint256 fee); + + uint256 internal constant amount = 100; + uint64 internal constant destinationChainSelector = 424242; + uint256 internal constant feeWei = 121212; + uint256 internal constant feeJuels = 232323; + + function test_Fuzz_ccipSend(uint256 feeFromRouter, uint256 feeSupplied) public { + // cap the fuzzer because OWNER only has a million ether. + vm.assume(feeSupplied < 1_000_000 ether - amount); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeFromRouter) + ); + + if (feeSupplied < feeFromRouter) { + vm.expectRevert(); + s_etherSenderReceiver.ccipSend{value: amount + feeSupplied}(destinationChainSelector, message); + } else { + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + feeSupplied, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + bytes32 actualMsgId = + s_etherSenderReceiver.ccipSend{value: amount + feeSupplied}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + } + } + + function test_Fuzz_ccipSend_feeToken(uint256 feeFromRouter, uint256 feeSupplied) public { + // cap the fuzzer because OWNER only has a million LINK. + vm.assume(feeSupplied < 1_000_000 ether - amount); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(s_linkToken), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeFromRouter) + ); + + s_linkToken.approve(address(s_etherSenderReceiver), feeSupplied); + + if (feeSupplied < feeFromRouter) { + vm.expectRevert(); + s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + } else { + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + } + } + + function test_ccipSend_reverts_insufficientFee_weth() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(s_weth), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + + s_weth.approve(address(s_etherSenderReceiver), feeWei - 1); + + vm.expectRevert("SafeERC20: low-level call failed"); + s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + } + + function test_ccipSend_reverts_insufficientFee_feeToken() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(s_linkToken), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeJuels) + ); + + s_linkToken.approve(address(s_etherSenderReceiver), feeJuels - 1); + + vm.expectRevert("ERC20: insufficient allowance"); + s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + } + + function test_ccipSend_reverts_insufficientFee_native() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + + vm.expectRevert(); + s_etherSenderReceiver.ccipSend{value: amount + feeWei - 1}(destinationChainSelector, message); + } + + function test_ccipSend_success_nativeExcess() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + + // we assert that the correct value is sent to the router call, which should be + // the msg.value - feeWei. + vm.mockCall( + ROUTER, + feeWei + 1, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount + feeWei + 1}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + } + + function test_ccipSend_success_native() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(0), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + vm.mockCall( + ROUTER, + feeWei, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount + feeWei}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + } + + function test_ccipSend_success_feeToken() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(s_linkToken), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeJuels) + ); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + s_linkToken.approve(address(s_etherSenderReceiver), feeJuels); + + bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + uint256 routerAllowance = s_linkToken.allowance(address(s_etherSenderReceiver), ROUTER); + assertEq(routerAllowance, feeJuels, "router allowance must be feeJuels"); + } + + function test_ccipSend_success_weth() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({ + token: address(0), // callers may not specify this. + amount: amount + }); + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(XCHAIN_RECEIVER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: address(s_weth), + extraArgs: "" + }); + + Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); + + bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), + abi.encode(feeWei) + ); + vm.mockCall( + ROUTER, + abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), + abi.encode(expectedMsgId) + ); + + s_weth.approve(address(s_etherSenderReceiver), feeWei); + + bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); + assertEq(actualMsgId, expectedMsgId, "message id must be correct"); + uint256 routerAllowance = s_weth.allowance(address(s_etherSenderReceiver), ROUTER); + assertEq(routerAllowance, type(uint256).max, "router allowance must be max for weth"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol new file mode 100644 index 0000000..61b0204 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol @@ -0,0 +1,61 @@ +pragma solidity ^0.8.0; + +import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; + +import {CCIPClientExample} from "../../applications/CCIPClientExample.sol"; +import {Client} from "../../libraries/Client.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {ERC165Checker} from + "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; + +contract CCIPClientExample_sanity is OnRampSetup { + function test_ImmutableExamples_Success() public { + CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); + deal(address(exampleContract), 100 ether); + deal(s_sourceFeeToken, address(exampleContract), 100 ether); + + // feeToken approval works + assertEq(IERC20(s_sourceFeeToken).allowance(address(exampleContract), address(s_sourceRouter)), 2 ** 256 - 1); + + // Can set chain + Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); + bytes memory encodedExtraArgs = Client._argsToBytes(extraArgs); + exampleContract.enableChain(DEST_CHAIN_SELECTOR, encodedExtraArgs); + assertEq(exampleContract.s_chains(DEST_CHAIN_SELECTOR), encodedExtraArgs); + + address toAddress = makeAddr("toAddress"); + + // Can send data pay native + exampleContract.sendDataPayNative(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); + + // Can send data pay feeToken + exampleContract.sendDataPayFeeToken(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); + + // Can send data tokens + address sourceToken = s_sourceTokens[1]; + assertEq( + address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(sourceToken))), + address(s_sourcePoolByToken[sourceToken]) + ); + deal(sourceToken, OWNER, 100 ether); + IERC20(sourceToken).approve(address(exampleContract), 1 ether); + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: sourceToken, amount: 1 ether}); + exampleContract.sendDataAndTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello"), tokenAmounts); + // Tokens transferred from owner to router then burned in pool. + assertEq(IERC20(sourceToken).balanceOf(OWNER), 99 ether); + assertEq(IERC20(sourceToken).balanceOf(address(s_sourceRouter)), 0); + + // Can send just tokens + IERC20(sourceToken).approve(address(exampleContract), 1 ether); + exampleContract.sendTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), tokenAmounts); + + // Can receive + assertTrue(ERC165Checker.supportsInterface(address(exampleContract), type(IAny2EVMMessageReceiver).interfaceId)); + + // Can disable chain + exampleContract.disableChain(DEST_CHAIN_SELECTOR); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol new file mode 100644 index 0000000..d47ba1c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {PingPongDemo} from "../../applications/PingPongDemo.sol"; +import {Client} from "../../libraries/Client.sol"; +import "../onRamp/OnRampSetup.t.sol"; + +// setup +contract PingPongDappSetup is OnRampSetup { + PingPongDemo internal s_pingPong; + IERC20 internal s_feeToken; + + address internal immutable i_pongContract = makeAddr("ping_pong_counterpart"); + + function setUp() public virtual override { + super.setUp(); + + s_feeToken = IERC20(s_sourceTokens[0]); + s_pingPong = new PingPongDemo(address(s_sourceRouter), s_feeToken); + s_pingPong.setCounterpart(DEST_CHAIN_SELECTOR, i_pongContract); + + uint256 fundingAmount = 1e18; + + // Fund the contract with LINK tokens + s_feeToken.transfer(address(s_pingPong), fundingAmount); + } +} + +contract PingPong_startPingPong is PingPongDappSetup { + uint256 internal pingPongNumber = 1; + + function test_StartPingPong_With_Sequenced_Ordered_Success() public { + _assertPingPongSuccess(); + } + + function test_StartPingPong_With_OOO_Success() public { + s_pingPong.setOutOfOrderExecution(true); + + _assertPingPongSuccess(); + } + + function _assertPingPongSuccess() internal { + vm.expectEmit(); + emit PingPongDemo.Ping(pingPongNumber); + + Internal.EVM2AnyRampMessage memory message; + + vm.expectEmit(false, false, false, false); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, message); + + s_pingPong.startPingPong(); + } +} + +contract PingPong_ccipReceive is PingPongDappSetup { + function test_CcipReceive_Success() public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); + + uint256 pingPongNumber = 5; + + Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: DEST_CHAIN_SELECTOR, + sender: abi.encode(i_pongContract), + data: abi.encode(pingPongNumber), + destTokenAmounts: tokenAmounts + }); + + vm.startPrank(address(s_sourceRouter)); + + vm.expectEmit(); + emit PingPongDemo.Pong(pingPongNumber + 1); + + s_pingPong.ccipReceive(message); + } +} + +contract PingPong_plumbing is PingPongDappSetup { + function test_Fuzz_CounterPartChainSelector_Success( + uint64 chainSelector + ) public { + s_pingPong.setCounterpartChainSelector(chainSelector); + + assertEq(s_pingPong.getCounterpartChainSelector(), chainSelector); + } + + function test_Fuzz_CounterPartAddress_Success( + address counterpartAddress + ) public { + s_pingPong.setCounterpartAddress(counterpartAddress); + + assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); + } + + function test_Fuzz_CounterPartAddress_Success(uint64 chainSelector, address counterpartAddress) public { + s_pingPong.setCounterpartChainSelector(chainSelector); + + s_pingPong.setCounterpart(chainSelector, counterpartAddress); + + assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); + assertEq(s_pingPong.getCounterpartChainSelector(), chainSelector); + } + + function test_Pausing_Success() public { + assertFalse(s_pingPong.isPaused()); + + s_pingPong.setPaused(true); + + assertTrue(s_pingPong.isPaused()); + } + + function test_OutOfOrderExecution_Success() public { + assertFalse(s_pingPong.getOutOfOrderExecution()); + + vm.expectEmit(); + emit PingPongDemo.OutOfOrderExecutionChange(true); + + s_pingPong.setOutOfOrderExecution(true); + + assertTrue(s_pingPong.getOutOfOrderExecution()); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol new file mode 100644 index 0000000..8947a27 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; + +import {Client} from "../../../libraries/Client.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +/// @title FacadeClient - A simple proxy for calling Router +contract FacadeClient { + address private immutable i_router; + uint64 private immutable i_destChainSelector; + IERC20 private immutable i_sourceToken; + IERC20 private immutable i_feeToken; + address private immutable i_receiver; + + uint256 private s_msg_sequence = 1; + + constructor(address router, uint64 destChainSelector, IERC20 sourceToken, IERC20 feeToken, address receiver) { + i_router = router; + i_destChainSelector = destChainSelector; + i_sourceToken = sourceToken; + i_feeToken = feeToken; + i_receiver = receiver; + + sourceToken.approve(address(router), 2 ** 256 - 1); + feeToken.approve(address(router), 2 ** 256 - 1); + } + + /// @dev Calls Router to initiate CCIP send. + /// The expectation is that s_msg_sequence will always match the sequence in emitted CCIP messages. + function send( + uint256 amount + ) public { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0].token = address(i_sourceToken); + tokenAmounts[0].amount = amount; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(i_receiver), + data: abi.encodePacked(s_msg_sequence), + tokenAmounts: tokenAmounts, + extraArgs: "", + feeToken: address(i_feeToken) + }); + + s_msg_sequence++; + + IRouterClient(i_router).ccipSend(i_destChainSelector, message); + } + + function getSequence() public view returns (uint256) { + return s_msg_sequence; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol new file mode 100644 index 0000000..0c1cc71 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {OnRamp} from "../../../onRamp/OnRamp.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {OnRampSetup} from "../../onRamp/OnRampSetup.t.sol"; +import {FacadeClient} from "./FacadeClient.sol"; +import {ReentrantMaliciousTokenPool} from "./ReentrantMaliciousTokenPool.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +/// @title MultiOnRampTokenPoolReentrancy +/// Attempts to perform a reentrancy exploit on Onramp with a malicious TokenPool +contract OnRampTokenPoolReentrancy is OnRampSetup { + FacadeClient internal s_facadeClient; + ReentrantMaliciousTokenPool internal s_maliciousTokenPool; + IERC20 internal s_sourceToken; + IERC20 internal s_feeToken; + address internal immutable i_receiver = makeAddr("receiver"); + + function setUp() public virtual override { + OnRampSetup.setUp(); + + s_sourceToken = IERC20(s_sourceTokens[0]); + s_feeToken = IERC20(s_sourceTokens[0]); + + s_facadeClient = + new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); + + s_maliciousTokenPool = new ReentrantMaliciousTokenPool( + address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) + ); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), + remoteTokenAddress: abi.encode(s_destTokens[0]), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_maliciousTokenPool.applyChainUpdates(chainUpdates); + s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); + + s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); + + s_sourceToken.transfer(address(s_facadeClient), 1e18); + s_feeToken.transfer(address(s_facadeClient), 1e18); + } + + /// @dev This test was used to showcase a reentrancy exploit on OnRamp with malicious TokenPool. + /// How it worked: OnRamp used to construct EVM2Any messages after calling TokenPool's lockOrBurn. + /// This allowed the malicious TokenPool to break message sequencing expectations as follows: + /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> + /// (reenter)-> Facade -> 2nd call to ccipSend + /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. + /// The issue was fixed by implementing a reentrancy guard in OnRamp. + function test_OnRampTokenPoolReentrancy_Success() public { + uint256 amount = 1; + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0].token = address(s_sourceToken); + tokenAmounts[0].amount = amount; + + Client.EVM2AnyMessage memory message1 = Client.EVM2AnyMessage({ + receiver: abi.encode(i_receiver), + data: abi.encodePacked(uint256(1)), // message 1 contains data 1 + tokenAmounts: tokenAmounts, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), + feeToken: address(s_feeToken) + }); + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); + assertGt(expectedFee, 0); + + vm.expectRevert(OnRamp.ReentrancyGuardReentrantCall.selector); + s_facadeClient.send(amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol new file mode 100644 index 0000000..f50f233 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {FacadeClient} from "./FacadeClient.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract ReentrantMaliciousTokenPool is TokenPool { + address private immutable i_facade; + + bool private s_attacked; + + constructor( + address facade, + IERC20 token, + address rmnProxy, + address router + ) TokenPool(token, new address[](0), rmnProxy, router) { + i_facade = facade; + } + + /// @dev Calls into Facade to reenter Router exactly 1 time + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external override returns (Pool.LockOrBurnOutV1 memory) { + if (s_attacked) { + return + Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + s_attacked = true; + + // solhint-disable-next-line check-send-result + FacadeClient(i_facade).send(lockOrBurnIn.amount); + emit Burned(msg.sender, lockOrBurnIn.amount); + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol new file mode 100644 index 0000000..b03081b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol @@ -0,0 +1,969 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../../keystone/interfaces/ICapabilityConfiguration.sol"; +import {ICapabilitiesRegistry} from "../../interfaces/ICapabilitiesRegistry.sol"; + +import {CCIPHome} from "../../capability/CCIPHome.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {CCIPHomeHelper} from "../helpers/CCIPHomeHelper.sol"; +import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; + +contract CCIPHomeTest is Test { + // address internal constant OWNER = address(0x0000000123123123123); + bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); + address internal constant CAPABILITIES_REGISTRY = address(0x0000000123123123123); + Internal.OCRPluginType internal constant DEFAULT_PLUGIN_TYPE = Internal.OCRPluginType.Commit; + uint32 internal constant DEFAULT_DON_ID = 78978987; + + CCIPHomeHelper public s_ccipHome; + + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000b00..00 + + uint64 private constant DEFAULT_CHAIN_SELECTOR = 9381579735; + + function setUp() public virtual { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), _getBaseChainConfigs()); + + ICapabilitiesRegistry.NodeInfo memory nodeInfo = ICapabilitiesRegistry.NodeInfo({ + p2pId: keccak256("p2pId"), + signer: keccak256("signer"), + nodeOperatorId: 1, + configCount: 1, + workflowDONId: 1, + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + capabilitiesDONIds: new uint256[](0) + }); + + vm.mockCall( + CAPABILITIES_REGISTRY, abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector), abi.encode(nodeInfo) + ); + + vm.startPrank(address(s_ccipHome)); + } + + function _getBaseChainConfigs() internal pure returns (CCIPHome.ChainConfigArgs[] memory) { + CCIPHome.ChainConfigArgs[] memory configs = new CCIPHome.ChainConfigArgs[](1); + CCIPHome.ChainConfig memory chainConfig = + CCIPHome.ChainConfig({readers: new bytes32[](0), fChain: 1, config: abi.encode("chainConfig")}); + configs[0] = CCIPHome.ChainConfigArgs({chainSelector: DEFAULT_CHAIN_SELECTOR, chainConfig: chainConfig}); + + return configs; + } + + function _getConfigDigest( + uint32 donId, + Internal.OCRPluginType pluginType, + bytes memory config, + uint32 version + ) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256( + bytes.concat( + abi.encode(bytes32("EVM"), block.chainid, address(s_ccipHome), donId, pluginType, version), config + ) + ) + ) & ~PREFIX_MASK + ) + ); + } + + function _getBaseConfig( + Internal.OCRPluginType pluginType + ) internal pure returns (CCIPHome.OCR3Config memory) { + CCIPHome.OCR3Node[] memory nodes = new CCIPHome.OCR3Node[](4); + for (uint256 i = 0; i < nodes.length; i++) { + nodes[i] = CCIPHome.OCR3Node({ + p2pId: keccak256(abi.encode("p2pId", i)), + signerKey: abi.encode("signerKey"), + transmitterKey: abi.encode("transmitterKey") + }); + } + + return CCIPHome.OCR3Config({ + pluginType: pluginType, + chainSelector: DEFAULT_CHAIN_SELECTOR, + FRoleDON: 1, + offchainConfigVersion: 98765, + offrampAddress: abi.encode("offrampAddress"), + rmnHomeAddress: abi.encode("rmnHomeAddress"), + nodes: nodes, + offchainConfig: abi.encode("offchainConfig") + }); + } +} + +contract CCIPHome_constructor is CCIPHomeTest { + function test_constructor_success() public { + CCIPHome ccipHome = new CCIPHome(CAPABILITIES_REGISTRY); + + assertEq(address(ccipHome.getCapabilityRegistry()), CAPABILITIES_REGISTRY); + } + + function test_supportsInterface_success() public view { + assertTrue(s_ccipHome.supportsInterface(type(IERC165).interfaceId)); + assertTrue(s_ccipHome.supportsInterface(type(ICapabilityConfiguration).interfaceId)); + } + + function test_getCapabilityConfiguration_success() public view { + bytes memory config = s_ccipHome.getCapabilityConfiguration(DEFAULT_DON_ID); + assertEq(config.length, 0); + } + + function test_constructor_CapabilitiesRegistryAddressZero_reverts() public { + vm.expectRevert(CCIPHome.ZeroAddressNotAllowed.selector); + new CCIPHome(address(0)); + } +} + +contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTest { + function setUp() public virtual override { + super.setUp(); + vm.stopPrank(); + vm.startPrank(address(CAPABILITIES_REGISTRY)); + } + + function test_beforeCapabilityConfigSet_success() public { + // first set a config + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then revoke the config + bytes32 candidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertNotEq(candidateDigest, ZERO_DIGEST); + + callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, candidateDigest)); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then set a new config + callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + // Then promote the new config + + bytes32 newCandidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertNotEq(newCandidateDigest, ZERO_DIGEST); + + callData = abi.encodeCall( + CCIPHome.promoteCandidateAndRevokeActive, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, newCandidateDigest, ZERO_DIGEST) + ); + + vm.expectCall(address(s_ccipHome), callData); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + + bytes32 activeDigest = s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, newCandidateDigest); + } + + function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() public { + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.stopPrank(); + + vm.expectRevert(CCIPHome.OnlyCapabilitiesRegistryCanCall.selector); + + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + } + + function test_beforeCapabilityConfigSet_InvalidSelector_reverts() public { + bytes memory callData = abi.encodeCall(CCIPHome.getConfigDigests, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidSelector.selector, CCIPHome.getConfigDigests.selector)); + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + } + + function test_beforeCapabilityConfigSet_DONIdMismatch_reverts() public { + uint32 wrongDonId = DEFAULT_DON_ID + 1; + + bytes memory callData = abi.encodeCall( + CCIPHome.setCandidate, + (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) + ); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.DONIdMismatch.selector, DEFAULT_DON_ID, wrongDonId)); + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, wrongDonId); + } + + function test_beforeCapabilityConfigSet_InnerCallReverts_reverts() public { + bytes memory callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST)); + + vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); + s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); + } +} + +contract CCIPHome_getConfigDigests is CCIPHomeTest { + function test_getConfigDigests_success() public { + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, firstDigest); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, secondDigest); + + assertEq(activeDigest, s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); + assertEq(candidateDigest, s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); + } +} + +contract CCIPHome_getAllConfigs is CCIPHomeTest { + function test_getAllConfigs_success() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = + s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, firstDigest); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, firstDigest); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, firstDigest); + assertEq(candidateConfig.configDigest, secondDigest); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID + 1, DEFAULT_PLUGIN_TYPE); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + + (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); + assertEq(activeConfig.configDigest, ZERO_DIGEST); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + } +} + +contract CCIPHome_setCandidate is CCIPHomeTest { + function test_setCandidate_success() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + CCIPHome.VersionedConfig memory versionedConfig = + CCIPHome.VersionedConfig({version: 1, config: config, configDigest: ZERO_DIGEST}); + + versionedConfig.configDigest = + _getConfigDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, abi.encode(versionedConfig.config), versionedConfig.version); + + vm.expectEmit(); + emit CCIPHome.ConfigSet(versionedConfig.configDigest, versionedConfig.version, versionedConfig.config); + + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.config, ZERO_DIGEST); + + (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = + s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.configDigest); + assertTrue(ok); + assertEq(storedVersionedConfig.version, versionedConfig.version); + assertEq(storedVersionedConfig.configDigest, versionedConfig.configDigest); + assertEq(keccak256(abi.encode(storedVersionedConfig.config)), keccak256(abi.encode(versionedConfig.config))); + } + + function test_setCandidate_ConfigDigestMismatch_reverts() public { + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + + bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.CandidateConfigRevoked(digest); + + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, digest); + } + + function test_setCandidate_CanOnlySelfCall_reverts() public { + vm.stopPrank(); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.setCandidate( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST + ); + } +} + +contract CCIPHome_revokeCandidate is CCIPHomeTest { + // Sets two configs + function setUp() public virtual override { + super.setUp(); + CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); + bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, digest, ZERO_DIGEST); + + config.offrampAddress = abi.encode("new_offrampAddress"); + s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); + } + + function test_revokeCandidate_success() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + + vm.expectEmit(); + emit CCIPHome.CandidateConfigRevoked(priorCandidateDigest); + + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); + + (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = + s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); + assertFalse(ok); + // Ensure no old data is returned, even though it's still in storage + assertEq(storedVersionedConfig.version, 0); + assertEq(storedVersionedConfig.config.chainSelector, 0); + assertEq(storedVersionedConfig.config.FRoleDON, 0); + + // Asser the active digest is unaffected but the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, ZERO_DIGEST); + assertTrue(candidateDigest != priorCandidateDigest); + } + + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + (, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + + bytes32 wrongDigest = keccak256("wrong_digest"); + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongDigest); + } + + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST); + } + + function test_revokeCandidate_CanOnlySelfCall_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("configDigest")); + } +} + +contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTest { + function test_promoteCandidateAndRevokeActive_multiplePlugins_success() public { + promoteCandidateAndRevokeActive(Internal.OCRPluginType.Commit); + promoteCandidateAndRevokeActive(Internal.OCRPluginType.Execution); + + // check that the two plugins have only active configs and no candidates. + (bytes32 activeDigest, bytes32 candidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Commit); + assertTrue(activeDigest != ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); + assertTrue(activeDigest != ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + } + + function promoteCandidateAndRevokeActive( + Internal.OCRPluginType pluginType + ) public { + CCIPHome.OCR3Config memory config = _getBaseConfig(pluginType); + bytes32 firstConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.ConfigPromoted(firstConfigToPromote); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, firstConfigToPromote, ZERO_DIGEST); + + // Assert the active digest is updated and the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, pluginType); + assertEq(activeDigest, firstConfigToPromote); + assertEq(candidateDigest, ZERO_DIGEST); + + // Set a new candidate to promote over a non-zero active config. + config.offchainConfig = abi.encode("new_offchainConfig_config"); + bytes32 secondConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); + + vm.expectEmit(); + emit CCIPHome.ActiveConfigRevoked(firstConfigToPromote); + + vm.expectEmit(); + emit CCIPHome.ConfigPromoted(secondConfigToPromote); + + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, secondConfigToPromote, firstConfigToPromote); + + (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = + s_ccipHome.getAllConfigs(DEFAULT_DON_ID, pluginType); + assertEq(activeConfig.configDigest, secondConfigToPromote); + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + assertEq(keccak256(abi.encode(activeConfig.config)), keccak256(abi.encode(config))); + } + + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { + vm.expectRevert(CCIPHome.NoOpStateTransitionNotAllowed.selector); + s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST, ZERO_DIGEST); + } + + function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = + s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); + bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); + bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); + + vm.expectRevert( + abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) + ); + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongCandidateDigest, wrongActiveDigest + ); + + vm.expectRevert( + abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest) + ); + + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest, wrongActiveDigest + ); + } + + function test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() public { + vm.stopPrank(); + + vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); + s_ccipHome.promoteCandidateAndRevokeActive( + DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("toPromote"), keccak256("ToRevoke") + ); + } +} + +contract CCIPHome__validateConfig is CCIPHomeTest { + function setUp() public virtual override { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + } + + function _addChainConfig( + uint256 numNodes + ) internal returns (CCIPHome.OCR3Node[] memory nodes) { + return _addChainConfig(numNodes, 1); + } + + function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { + arr = new bytes32[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = keccak256(abi.encode(i, 1, seed)); + } + return arr; + } + + function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { + arr = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + arr[i] = abi.encode(keccak256(abi.encode(i, 1, seed))); + } + return arr; + } + + function _addChainConfig(uint256 numNodes, uint8 fChain) internal returns (CCIPHome.OCR3Node[] memory nodes) { + bytes32[] memory p2pIds = _makeBytes32Array(numNodes, 0); + bytes[] memory signers = _makeBytesArray(numNodes, 10); + bytes[] memory transmitters = _makeBytesArray(numNodes, 20); + + nodes = new CCIPHome.OCR3Node[](numNodes); + + for (uint256 i = 0; i < numNodes; i++) { + nodes[i] = CCIPHome.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, p2pIds[i]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(signers[i]), + p2pId: p2pIds[i], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + } + // Add chain selector for chain 1. + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: p2pIds, fChain: fChain, config: bytes("config1")}) + }); + + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + return nodes; + } + + function _getCorrectOCR3Config(uint8 numNodes, uint8 FRoleDON) internal returns (CCIPHome.OCR3Config memory) { + CCIPHome.OCR3Node[] memory nodes = _addChainConfig(numNodes); + + return CCIPHome.OCR3Config({ + pluginType: Internal.OCRPluginType.Commit, + offrampAddress: abi.encode(keccak256(abi.encode("offramp"))), + rmnHomeAddress: abi.encode(keccak256(abi.encode("rmnHome"))), + chainSelector: 1, + nodes: nodes, + FRoleDON: FRoleDON, + offchainConfigVersion: 30, + offchainConfig: bytes("offchainConfig") + }); + } + + function _getCorrectOCR3Config() internal returns (CCIPHome.OCR3Config memory) { + return _getCorrectOCR3Config(4, 1); + } + + // Successes. + + function test__validateConfig_Success() public { + s_ccipHome.validateConfig(_getCorrectOCR3Config()); + } + + function test__validateConfigLessTransmittersThanSigners_Success() public { + // fChain is 1, so there should be at least 4 transmitters. + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(5, 1); + config.nodes[1].transmitterKey = bytes(""); + + s_ccipHome.validateConfig(config); + } + + function test__validateConfigSmallerFChain_Success() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(11, 3); + + // Set fChain to 2 + _addChainConfig(4, 2); + + s_ccipHome.validateConfig(config); + } + + // Reverts + + function test__validateConfig_ChainSelectorNotSet_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 0; // invalid + + vm.expectRevert(CCIPHome.ChainSelectorNotSet.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = ""; // invalid + + vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = abi.encode(address(0)); // invalid + + vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.rmnHomeAddress = ""; // invalid + + vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.rmnHomeAddress = abi.encode(address(0)); // invalid + + vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ChainSelectorNotFound_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 2; // not set + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 2)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmitters_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + uint256 numberOfTransmitters = 3; + + // 32 > 31 (max num oracles) + CCIPHome.OCR3Node[] memory nodes = _addChainConfig(31); + + // truncate transmitters to < 3 * fChain + 1 + // since fChain is 1 in this case, we need to truncate to 3 transmitters. + for (uint256 i = numberOfTransmitters; i < nodes.length; ++i) { + nodes[i].transmitterKey = bytes(""); + } + + config.nodes = nodes; + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, numberOfTransmitters, 4)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[0].transmitterKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 3, 4)); + s_ccipHome.validateConfig(config); + + // Zero out remaining transmitters to verify error changes + for (uint256 i = 1; i < config.nodes.length; ++i) { + config.nodes[i].transmitterKey = bytes(""); + } + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 0, 4)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_TooManySigners_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes = new CCIPHome.OCR3Node[](257); + + vm.expectRevert(CCIPHome.TooManySigners.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FChainTooHigh_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 2; // too low + + // Set fChain to 3 + _addChainConfig(4, 3); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 3, 2)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FMustBePositive_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 0; // not positive + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 1, 0)); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_FTooHigh_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 2; // too high + + vm.expectRevert(CCIPHome.FTooHigh.selector); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ZeroP2PId_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[1].p2pId = bytes32(0); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[1])); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_ZeroSignerKey_Reverts() public { + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[2].signerKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[2])); + s_ccipHome.validateConfig(config); + } + + function test__validateConfig_NodeNotInRegistry_Reverts() public { + CCIPHome.OCR3Node[] memory nodes = _addChainConfig(4); + bytes32 nonExistentP2PId = keccak256("notInRegistry"); + nodes[0].p2pId = nonExistentP2PId; + + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, nonExistentP2PId), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes = nodes; + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NodeNotInRegistry.selector, nonExistentP2PId)); + s_ccipHome.validateConfig(config); + } +} + +contract CCIPHome_applyChainConfigUpdates is CCIPHomeTest { + function setUp() public virtual override { + s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); + } + + function test_applyChainConfigUpdates_addChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); + } + + function test_getPaginatedCCIPHomes_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(0, 1); + assertEq(configs.length, 1, "chain configs length must be 1"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(0, 10); + assertEq(configs.length, 2, "chain configs length must be 2"); + assertEq(configs[0].chainSelector, 1, "chain selector must match"); + assertEq(configs[1].chainSelector, 2, "chain selector must match"); + + configs = s_ccipHome.getAllChainConfigs(1, 1); + assertEq(configs.length, 1, "chain configs length must be 1"); + + configs = s_ccipHome.getAllChainConfigs(1, 2); + assertEq(configs.length, 0, "chain configs length must be 0"); + } + + function test_applyChainConfigUpdates_removeChainConfigs_Success() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) + }); + + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); + vm.expectEmit(); + emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + + assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); + + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectEmit(); + emit CCIPHome.ChainConfigRemoved(1); + s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); + + assertEq(s_ccipHome.getNumChainConfigurations(), 1, "total chain configs must be 1"); + } + + // Reverts. + + function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { + uint64[] memory removes = new uint64[](1); + removes[0] = uint64(1); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 1)); + s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); + } + + function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) + }); + + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 0, + signer: bytes32(0), + p2pId: bytes32(uint256(0)), + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + + vm.expectRevert(abi.encodeWithSelector(CCIPHome.NodeNotInRegistry.selector, chainReaders[0])); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + } + + function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { + bytes32[] memory chainReaders = new bytes32[](1); + chainReaders[0] = keccak256(abi.encode(1)); + CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); + adds[0] = CCIPHome.ChainConfigArgs({ + chainSelector: 1, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) + }); + adds[1] = CCIPHome.ChainConfigArgs({ + chainSelector: 2, + chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain + }); + + vm.mockCall( + CAPABILITIES_REGISTRY, + abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), + abi.encode( + ICapabilitiesRegistry.NodeInfo({ + nodeOperatorId: 1, + signer: bytes32(uint256(1)), + p2pId: chainReaders[0], + encryptionPublicKey: keccak256("encryptionPublicKey"), + hashedCapabilityIds: new bytes32[](0), + configCount: uint32(1), + workflowDONId: uint32(1), + capabilitiesDONIds: new uint256[](0) + }) + ) + ); + + vm.expectRevert(CCIPHome.FChainMustBePositive.selector); + s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol new file mode 100644 index 0000000..4d462ad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; + +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {NonceManager} from "../../NonceManager.sol"; +import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; +import "../helpers/MerkleHelper.sol"; +import "../offRamp/OffRampSetup.t.sol"; +import "../onRamp/OnRampSetup.t.sol"; + +/// @notice This E2E test implements the following scenario: +/// 1. Send multiple messages from multiple source chains to a single destination chain (2 messages from source chain 1 and 1 from +/// source chain 2). +/// 2. Commit multiple merkle roots (1 for each source chain). +/// 3. Batch execute all the committed messages. +contract E2E is OnRampSetup, OffRampSetup { + using Internal for Internal.Any2EVMRampMessage; + + Router internal s_sourceRouter2; + OnRampHelper internal s_onRamp2; + TokenAdminRegistry internal s_tokenAdminRegistry2; + NonceManager internal s_nonceManager2; + + bytes32 internal s_metadataHash2; + + mapping(address destPool => address sourcePool) internal s_sourcePoolByDestPool; + + function setUp() public virtual override(OnRampSetup, OffRampSetup) { + OnRampSetup.setUp(); + OffRampSetup.setUp(); + + // Deploy new source router for the new source chain + s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); + + // Deploy new TokenAdminRegistry for the new source chain + s_tokenAdminRegistry2 = new TokenAdminRegistry(); + + // Deploy new token pools and set them on the new TokenAdminRegistry + for (uint256 i = 0; i < s_sourceTokens.length; ++i) { + address token = s_sourceTokens[i]; + address pool = address( + new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) + ); + + s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; + + _setPool( + s_tokenAdminRegistry2, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] + ); + } + + for (uint256 i = 0; i < s_destTokens.length; ++i) { + address token = s_destTokens[i]; + address pool = s_destPoolByToken[token]; + + _setPool( + s_tokenAdminRegistry2, token, pool, SOURCE_CHAIN_SELECTOR + 1, s_sourcePoolByDestPool[pool], s_sourceTokens[i] + ); + } + + s_nonceManager2 = new NonceManager(new address[](0)); + + ( + // Deploy the new source chain onramp + // Outsource to shared helper function with OnRampSetup + s_onRamp2, + s_metadataHash2 + ) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR + 1, s_sourceRouter2, address(s_nonceManager2), address(s_tokenAdminRegistry2) + ); + + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(s_onRamp2); + s_nonceManager2.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + + // Enable destination chain on new source chain router + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp2)}); + s_sourceRouter2.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + // Deploy offramp + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); + + // Enable source chains on offramp + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR, + isEnabled: true, + // Must match OnRamp address + onRamp: abi.encode(address(s_onRamp)) + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + isEnabled: true, + onRamp: abi.encode(address(s_onRamp2)) + }); + + _setupMultipleOffRampsFromConfigs(sourceChainConfigs); + } + + function test_E2E_3MessagesMMultiOffRampSuccess_gas() public { + vm.pauseGasMetering(); + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + // Scoped to sending to reduce stack pressure + { + IERC20 token0 = IERC20(s_sourceTokens[0]); + IERC20 token1 = IERC20(s_sourceTokens[1]); + + uint256 balance0Pre = token0.balanceOf(OWNER); + uint256 balance1Pre = token1.balanceOf(OWNER); + + // Send messages + messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages2[0] = + _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); + // Asserts that the tokens have been sent and the fee has been paid. + assertEq( + balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) + ); + assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); + } + + // Commit + + bytes32[] memory merkleRoots = new bytes32[](2); + + // Scoped to commit to reduce stack pressure + { + bytes32[] memory hashedMessages1 = new bytes32[](2); + hashedMessages1[0] = _hashMessage(messages1[0], abi.encode(address(s_onRamp))); + hashedMessages1[1] = _hashMessage(messages1[1], abi.encode(address(s_onRamp))); + bytes32[] memory hashedMessages2 = new bytes32[](1); + hashedMessages2[0] = _hashMessage(messages2[0], abi.encode(address(s_onRamp2))); + + merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); + merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); + + // TODO make these real sigs :) + IRMNRemote.Signature[] memory rmnSignatures = new IRMNRemote.Signature[](0); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR, + onRampAddress: abi.encode(address(s_onRamp)), + minSeqNr: messages1[0].header.sequenceNumber, + maxSeqNr: messages1[1].header.sequenceNumber, + merkleRoot: merkleRoots[0] + }); + roots[1] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + onRampAddress: abi.encode(address(s_onRamp2)), + minSeqNr: messages2[0].header.sequenceNumber, + maxSeqNr: messages2[0].header.sequenceNumber, + merkleRoot: merkleRoots[1] + }); + + OffRamp.CommitReport memory report = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: rmnSignatures, + rmnRawVs: 0 + }); + + vm.resumeGasMetering(); + _commit(report, ++s_latestSequenceNumber); + vm.pauseGasMetering(); + } + + // Scoped to RMN and verify to reduce stack pressure + { + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); + + bytes32[] memory proofs = new bytes32[](0); + bytes32[] memory hashedLeaves = new bytes32[](1); + hashedLeaves[0] = merkleRoots[0]; + + uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); + hashedLeaves[0] = merkleRoots[1]; + timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); + + // We change the block time so when execute would e.g. use the current + // block time instead of the committed block time the value would be + // incorrect in the checks below. + vm.warp(BLOCK_TIME + 2000); + } + + // Execute + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR + 1, messages2); + + vm.resumeGasMetering(); + vm.recordLogs(); + _execute(reports); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], abi.encode(address(s_onRamp))), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], abi.encode(address(s_onRamp))), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR + 1, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], abi.encode(address(s_onRamp2))), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function _sendRequest( + uint64 expectedSeqNum, + uint64 sourceChainSelector, + uint64 nonce, + bytes32 metadataHash, + Router router, + TokenAdminRegistry tokenAdminRegistry + ) public returns (Internal.Any2EVMRampMessage memory) { + Client.EVM2AnyMessage memory message = _generateTokenMessage(); + IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + router.getFee(DEST_CHAIN_SELECTOR, message)); + IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); + + uint256 feeAmount = router.getFee(DEST_CHAIN_SELECTOR, message); + + message.receiver = abi.encode(address(s_receiver)); + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( + message, + sourceChainSelector, + DEST_CHAIN_SELECTOR, + expectedSeqNum, + nonce, + feeAmount, + feeAmount, + OWNER, + metadataHash, + tokenAdminRegistry + ); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedSeqNum, msgEvent); + + vm.resumeGasMetering(); + router.ccipSend(DEST_CHAIN_SELECTOR, message); + vm.pauseGasMetering(); + + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](message.tokenAmounts.length); + + for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(msgEvent.tokenAmounts[i].sourcePoolAddress), + destTokenAddress: abi.decode(msgEvent.tokenAmounts[i].destTokenAddress, (address)), + extraData: msgEvent.tokenAmounts[i].extraData, + amount: msgEvent.tokenAmounts[i].amount, + destGasAmount: abi.decode(msgEvent.tokenAmounts[i].destExecData, (uint32)) + }); + } + + return Internal.Any2EVMRampMessage({ + header: Internal.RampMessageHeader({ + messageId: msgEvent.header.messageId, + sourceChainSelector: sourceChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, + sequenceNumber: msgEvent.header.sequenceNumber, + nonce: msgEvent.header.nonce + }), + sender: abi.encode(msgEvent.sender), + data: msgEvent.data, + receiver: abi.decode(msgEvent.receiver, (address)), + gasLimit: s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit, + tokenAmounts: any2EVMTokenTransfer + }); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol new file mode 100644 index 0000000..3356b25 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -0,0 +1,2251 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; + +import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; +import {FeeQuoterFeeSetup, FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; + +import {Vm} from "forge-std/Vm.sol"; + +contract FeeQuoter_constructor is FeeQuoterSetup { + function test_Setup_Success() public virtual { + address[] memory priceUpdaters = new address[](2); + priceUpdaters[0] = STRANGER; + priceUpdaters[1] = OWNER; + address[] memory feeTokens = new address[](2); + feeTokens[0] = s_sourceTokens[0]; + feeTokens[1] = s_sourceTokens[1]; + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + tokenPriceFeedUpdates[1] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + destChainConfigArgs + ); + + _assertFeeQuoterStaticConfigsEqual(s_feeQuoter.getStaticConfig(), staticConfig); + assertEq(feeTokens, s_feeQuoter.getFeeTokens()); + assertEq(priceUpdaters, s_feeQuoter.getAllAuthorizedCallers()); + assertEq(s_feeQuoter.typeAndVersion(), "FeeQuoter 1.6.0-dev"); + + _assertTokenPriceFeedConfigEquality( + tokenPriceFeedUpdates[0].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[0]) + ); + + _assertTokenPriceFeedConfigEquality( + tokenPriceFeedUpdates[1].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[1]) + ); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].token) + ); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].token) + ); + + FeeQuoter.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = s_feeQuoterTokenTransferFeeConfigArgs[0]; + for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; + + _assertTokenTransferFeeConfigEqual( + tokenFeeArgs.tokenTransferFeeConfig, + s_feeQuoter.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) + ); + } + + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + FeeQuoter.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + + _assertFeeQuoterDestChainConfigsEqual(expectedConfig, s_feeQuoter.getDestChainConfig(destChainSelector)); + } + } + + function test_InvalidStalenessThreshold_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: 0 + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } + + function test_InvalidLinkTokenEqZeroAddress_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: address(0), + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } + + function test_InvalidMaxFeeJuelsPerMsg_Revert() public { + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: 0, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); + + s_feeQuoter = new FeeQuoterHelper( + staticConfig, + new address[](0), + new address[](0), + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) + ); + } +} + +contract FeeQuoter_getTokenPrices is FeeQuoterSetup { + function test_GetTokenPrices_Success() public view { + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + + address[] memory tokens = new address[](3); + tokens[0] = s_sourceTokens[0]; + tokens[1] = s_sourceTokens[1]; + tokens[2] = s_weth; + + Internal.TimestampedPackedUint224[] memory tokenPrices = s_feeQuoter.getTokenPrices(tokens); + + assertEq(tokenPrices.length, 3); + assertEq(tokenPrices[0].value, priceUpdates.tokenPriceUpdates[0].usdPerToken); + assertEq(tokenPrices[1].value, priceUpdates.tokenPriceUpdates[1].usdPerToken); + assertEq(tokenPrices[2].value, priceUpdates.tokenPriceUpdates[2].usdPerToken); + } +} + +contract FeeQuoter_getTokenPrice is FeeQuoterSetup { + function test_GetTokenPriceFromFeed_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Above staleness threshold + vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().stalenessThreshold + 1); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer.value, uint224(1e18)); + assertEq(tokenPriceAnswer.timestamp, uint32(block.timestamp)); + } +} + +contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { + function test_GetValidatedTokenPrice_Success() public view { + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + address token = priceUpdates.tokenPriceUpdates[0].sourceToken; + + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); + + assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); + } + + function test_GetValidatedTokenPriceFromFeed_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Right below staleness threshold + vm.warp(originalTimestampValue + TWELVE_HOURS); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { + uint256 originalTimestampValue = block.timestamp; + + // Right above staleness threshold + vm.warp(originalTimestampValue + TWELVE_HOURS + 1); + + address sourceToken = _initialiseSingleTokenPriceFeed(); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); + + // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is: uint224.MAX_VALUE * (10 ** (36 - 18 - 18)) + assertEq(tokenPriceAnswer, uint224(type(uint224).max)); + } + + function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 6); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 6); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e6) -> expected 1e30 + assertEq(tokenPriceAnswer, uint224(1e30)); + } + + function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 24); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 24); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e24) -> expected 1e12 + assertEq(tokenPriceAnswer, uint224(1e12)); + } + + function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 + assertEq(tokenPriceAnswer, uint224(1e18)); + } + + function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 0); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 0); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e31 (0 decimal token) - unit is (1e18 * 1e18 / 1e0) -> expected 1e36 + assertEq(tokenPriceAnswer, uint224(1e67)); + } + + function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { + address tokenAddress = _deploySourceToken("testToken", 0, 20); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 20); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); + + // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e20) -> expected 1e14 + assertEq(tokenPriceAnswer, uint224(1e14)); + } + + function test_StaleFeeToken_Success() public { + vm.warp(block.timestamp + TWELVE_HOURS + 1); + + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + address token = priceUpdates.tokenPriceUpdates[0].sourceToken; + + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); + + assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); + } + + // Reverts + + function test_OverflowFeedPrice_Revert() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); + } + + function test_UnderflowFeedPrice_Revert() public { + address tokenAddress = _deploySourceToken("testToken", 0, 18); + address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); + } + + function test_TokenNotSupported_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); + } + + function test_TokenNotSupportedFeed_Revert() public { + address sourceToken = _initialiseSingleTokenPriceFeed(); + MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: sourceToken, usdPerToken: 0}); + + s_feeQuoter.updatePrices(priceUpdates); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, sourceToken)); + s_feeQuoter.getValidatedTokenPrice(sourceToken); + } +} + +contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { + function test_ApplyFeeTokensUpdates_Success() public { + address[] memory feeTokens = new address[](1); + feeTokens[0] = s_sourceTokens[1]; + + vm.expectEmit(); + emit FeeQuoter.FeeTokenAdded(feeTokens[0]); + + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); + + // add same feeToken is no-op + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); + + vm.expectEmit(); + emit FeeQuoter.FeeTokenRemoved(feeTokens[0]); + + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 2); + + // removing already removed feeToken is no-op + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 2); + } + + function test_OnlyCallableByOwner_Revert() public { + address[] memory feeTokens = new address[](1); + feeTokens[0] = STRANGER; + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + } +} + +contract FeeQuoter_updatePrices is FeeQuoterSetup { + function test_OnlyTokenPrice_Success() public { + Internal.PriceUpdates memory update = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + update.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp + ); + + s_feeQuoter.updatePrices(update); + + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); + } + + function test_OnlyGasPrice_Success() public { + Internal.PriceUpdates memory update = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](1) + }); + update.gasPriceUpdates[0] = + Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); + + vm.expectEmit(); + emit FeeQuoter.UsdPerUnitGasUpdated( + update.gasPriceUpdates[0].destChainSelector, update.gasPriceUpdates[0].usdPerUnitGas, block.timestamp + ); + + s_feeQuoter.updatePrices(update); + + assertEq( + s_feeQuoter.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas + ); + } + + function test_UpdateMultiplePrices_Success() public { + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](3); + tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); + tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[1], usdPerToken: 1800e18}); + tokenPriceUpdates[2] = Internal.TokenPriceUpdate({sourceToken: address(12345), usdPerToken: 1e18}); + + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](3); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2e6}); + gasPriceUpdates[1] = Internal.GasPriceUpdate({destChainSelector: SOURCE_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); + gasPriceUpdates[2] = Internal.GasPriceUpdate({destChainSelector: 12345, usdPerUnitGas: 1e18}); + + Internal.PriceUpdates memory update = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); + + for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + update.tokenPriceUpdates[i].sourceToken, update.tokenPriceUpdates[i].usdPerToken, block.timestamp + ); + } + for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { + vm.expectEmit(); + emit FeeQuoter.UsdPerUnitGasUpdated( + update.gasPriceUpdates[i].destChainSelector, update.gasPriceUpdates[i].usdPerUnitGas, block.timestamp + ); + } + + s_feeQuoter.updatePrices(update); + + for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { + assertEq( + s_feeQuoter.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken + ); + } + for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { + assertEq( + s_feeQuoter.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, + gasPriceUpdates[i].usdPerUnitGas + ); + } + } + + function test_UpdatableByAuthorizedCaller_Success() public { + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); + + // Revert when caller is not authorized + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = STRANGER; + vm.startPrank(OWNER); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) + ); + + // Stranger is now an authorized caller to update prices + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated( + priceUpdates.tokenPriceUpdates[0].sourceToken, priceUpdates.tokenPriceUpdates[0].usdPerToken, block.timestamp + ); + s_feeQuoter.updatePrices(priceUpdates); + + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); + + vm.startPrank(OWNER); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: new address[](0), removedCallers: priceUpdaters}) + ); + + // Revert when authorized caller is removed + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + } + + // Reverts + + function test_OnlyCallableByUpdater_Revert() public { + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_feeQuoter.updatePrices(priceUpdates); + } +} + +contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { + function test_ConvertTokenAmount_Success() public view { + Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + uint256 amount = 3e16; + uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) + / uint256(initialPriceUpdates.tokenPriceUpdates[0].usdPerToken); + uint256 expected = (amount * conversionRate) / 1e18; + assertEq(s_feeQuoter.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); + } + + function test_Fuzz_ConvertTokenAmount_Success( + uint256 feeTokenAmount, + uint224 usdPerFeeToken, + uint160 usdPerLinkToken, + uint224 usdPerUnitGas + ) public { + vm.assume(usdPerFeeToken > 0); + vm.assume(usdPerLinkToken > 0); + // We bound the max fees to be at most uint96.max link. + feeTokenAmount = bound(feeTokenAmount, 0, (uint256(type(uint96).max) * usdPerLinkToken) / usdPerFeeToken); + + address feeToken = address(1); + address linkToken = address(2); + address[] memory feeTokens = new address[](1); + feeTokens[0] = feeToken; + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](2); + tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: feeToken, usdPerToken: usdPerFeeToken}); + tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: linkToken, usdPerToken: usdPerLinkToken}); + + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: usdPerUnitGas}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); + + s_feeQuoter.updatePrices(priceUpdates); + + uint256 linkFee = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, linkToken); + assertEq(linkFee, (feeTokenAmount * usdPerFeeToken) / usdPerLinkToken); + } + + // Reverts + + function test_LinkTokenNotSupported_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); + } +} + +contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { + function test_GetFeeTokenAndGasPrices_Success() public view { + (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); + + Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); + + assertEq(feeTokenPrice, s_sourceTokenPrices[0]); + assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); + } + + function test_ZeroGasPrice_Success() public { + uint64 zeroGasDestChainSelector = 345678; + Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); + gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: zeroGasDestChainSelector, usdPerUnitGas: 0}); + + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); + s_feeQuoter.updatePrices(priceUpdates); + + (, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); + + assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); + } + + function test_UnsupportedChain_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.ChainNotSupported.selector, DEST_CHAIN_SELECTOR + 1)); + s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); + } + + function test_StaleGasPrice_Revert() public { + uint256 diff = TWELVE_HOURS + 1; + vm.warp(block.timestamp + diff); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); + s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); + } +} + +contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { + function test_ZeroFeeds_Success() public { + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); + vm.recordLogs(); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + // Verify no log emissions + assertEq(logEntries.length, 0); + } + + function test_SingleFeedUpdate_Success() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken)); + + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + } + + function test_MultipleFeedUpdate_Success() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); + + for (uint256 i = 0; i < 2; ++i) { + tokenPriceFeedUpdates[i] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[i], s_dataFeedByToken[s_sourceTokens[i]], 18); + + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken)); + + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig); + } + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig + ); + } + + function test_FeedUnset_Success() public { + Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); + assertFalse(priceQueryInitial.value == 0); + assertFalse(priceQueryInitial.timestamp == 0); + + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + + tokenPriceFeedUpdates[0].feedConfig.dataFeedAddress = address(0); + vm.expectEmit(); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + + // Price data should remain after a feed has been set->unset + Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); + assertEq(priceQueryPostUnsetFeed.value, priceQueryInitial.value); + assertEq(priceQueryPostUnsetFeed.timestamp, priceQueryInitial.timestamp); + } + + function test_FeedNotUpdated() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + + _assertTokenPriceFeedConfigEquality( + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + ); + } + + // Reverts + + function test_FeedUpdatedByNonOwner_Revert() public { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + } +} + +contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { + function test_Fuzz_applyDestChainConfigUpdates_Success( + FeeQuoter.DestChainConfigArgs memory destChainConfigArgs + ) public { + vm.assume(destChainConfigArgs.destChainSelector != 0); + vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); + destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( + bound( + destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit + ) + ); + destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + + bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; + + FeeQuoter.DestChainConfigArgs[] memory newDestChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + newDestChainConfigArgs[0] = destChainConfigArgs; + + if (isNewChain) { + vm.expectEmit(); + emit FeeQuoter.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + } else { + vm.expectEmit(); + emit FeeQuoter.DestChainConfigUpdated(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + } + + s_feeQuoter.applyDestChainConfigUpdates(newDestChainConfigArgs); + + _assertFeeQuoterDestChainConfigsEqual( + destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector) + ); + } + + function test_applyDestChainConfigUpdates_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); + destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; + destChainConfigArgs[0].destChainConfig.isEnabled = false; + destChainConfigArgs[1] = _generateFeeQuoterDestChainConfigArgs()[0]; + destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + vm.expectEmit(); + emit FeeQuoter.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); + vm.expectEmit(); + emit FeeQuoter.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); + + vm.recordLogs(); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + FeeQuoter.DestChainConfig memory gotDestChainConfig0 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory gotDestChainConfig1 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + + assertEq(vm.getRecordedLogs().length, 2); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); + } + + function test_applyDestChainConfigUpdatesZeroIntput_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); + + vm.recordLogs(); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + // Allow setting to the max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + // Revert when exceeding max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainSelector = 0; + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidChainFamilySelector_Revert() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); + + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + } +} + +contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { + function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { + uint256 dataAvailabilityCostUSD = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + + // Test that the cost is destnation chain specific + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = + destChainConfig.destDataAvailabilityOverheadGas * 2; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = + destChainConfig.destGasPerDataAvailabilityByte * 2; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = + destChainConfig.destDataAvailabilityMultiplierBps * 2; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + uint256 dataAvailabilityCostUSD2 = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; + expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); + assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); + } + + function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { + uint256 dataAvailabilityCostUSD = + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityLengthBytes = + Internal.MESSAGE_FIXED_BYTES + 100 + (5 * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } + + function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + assertEq(dataAvailabilityCostUSD, 0); + } + + function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public view { + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead + ); + + assertEq(0, dataAvailabilityCostUSD); + } + + function test_Fuzz_CalculateDataAvailabilityCost_Success( + uint64 destChainSelector, + uint32 destDataAvailabilityOverheadGas, + uint16 destGasPerDataAvailabilityByte, + uint16 destDataAvailabilityMultiplierBps, + uint112 dataAvailabilityGasPrice, + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public { + vm.assume(destChainSelector != 0); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(destChainSelector); + destChainConfigArgs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; + destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( + destChainConfigArgs[0].destChainSelector, + dataAvailabilityGasPrice, + messageDataLength, + numberOfTokens, + tokenTransferBytesOverhead + ); + + uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + + uint256 dataAvailabilityGas = + destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } +} + +contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { + function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( + FeeQuoter.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg + ) public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); + + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + vm.expectEmit(); + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( + vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth + ); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + assertEq( + premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(2)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { + vm.recordLogs(); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](0)); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + } +} + +contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { + function test_Fuzz_ApplyTokenTransferFeeConfig_Success( + FeeQuoter.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs + ) public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(2, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { + for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { + tokenTransferFeeConfigs[j].destBytesOverhead = uint32( + bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) + ); + address feeToken = s_sourceTokens[j]; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] + ); + } + } + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigs[i], + s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token + ) + ); + } + } + + function test_ApplyTokenTransferFeeConfig_Success() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: 312, + isEnabled: true + }); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 12, + maxFeeUSDCents: 13, + deciBps: 14, + destGasOverhead: 15, + destBytesOverhead: 394, + isEnabled: true + }); + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig + ); + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig + ); + + FeeQuoter.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = + new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0); + s_feeQuoter.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); + + FeeQuoter.TokenTransferFeeConfig memory config0 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + FeeQuoter.TokenTransferFeeConfig memory config1 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 + ); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + + // Remove only the first token and validate only the first token is removed + tokensToRemove = new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](1); + tokensToRemove[0] = FeeQuoter.TokenTransferFeeConfigRemoveArgs({ + destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, + token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + }); + + vm.expectEmit(); + emit FeeQuoter.TokenTransferFeeConfigDeleted( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates(new FeeQuoter.TokenTransferFeeConfigArgs[](0), tokensToRemove); + + config0 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + config1 = s_feeQuoter.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + FeeQuoter.TokenTransferFeeConfig memory emptyConfig; + + _assertTokenTransferFeeConfigEqual(emptyConfig, config0); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + } + + function test_ApplyTokenTransferFeeZeroInput() public { + vm.recordLogs(); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + new FeeQuoter.TokenTransferFeeConfigArgs[](0), new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + vm.startPrank(STRANGER); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; + + vm.expectRevert("Only callable by owner"); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + } + + function test_InvalidDestBytesOverhead_Revert() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), + isEnabled: true + }); + + vm.expectRevert( + abi.encodeWithSelector( + FeeQuoter.InvalidDestBytesOverhead.selector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead + ) + ); + + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + } +} + +contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_NoTokenTransferChargesZeroFee_Success() public view { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(0, feeUSDWei); + assertEq(0, destGasOverhead); + assertEq(0, destBytesOverhead); + } + + function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); + + // Get config to assert it isn't set + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + assertFalse(transferFeeConfig.isEnabled); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // Assert that the default values are used + assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); + assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); + assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); + } + + function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(_configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_FeeTokenBpsFee_Success() public view { + uint256 tokenAmount = 10000e18; + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = _calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); + uint256 bpsUSDWei = _applyBpsRatio( + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_CustomTokenBpsFee_Success() public view { + uint256 tokenAmount = 200000e18; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](1), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); + + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = _calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); + uint256 bpsUSDWei = _applyBpsRatio( + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroFeeConfigChargesMinFee_Success() public { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // if token charges 0 bps, it should cost minFee to transfer + assertEq( + _configUSDCentToWei( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents + ), + feeUSDWei + ); + assertEq(0, destGasOverhead); + assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); + } + + function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { + // It shouldn't be possible to pay materially lower fees by splitting up the transfers. + // Note it is possible to pay higher fees since the minimum fees are added. + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); + // Cap amount to avoid overflow + amount = bound(amount, 0, 1e36); + Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); + for (uint256 i = 0; i < transfers; ++i) { + multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); + } + Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); + single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); + + address feeToken = s_sourceRouter.getWrappedNative(); + + (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); + (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); + + // Note that there can be a rounding error once per split. + assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); + assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); + assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); + } + + function test_MixedTokenTransferFee_Success() public view { + address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; + uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; + FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) + ]; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](3), + feeToken: s_sourceRouter.getWrappedNative(), + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + uint256 expectedTotalGas = 0; + uint256 expectedTotalBytes = 0; + + // Start with small token transfers, total bps fee is lower than min token transfer fee + for (uint256 i = 0; i < testTokens.length; ++i) { + message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]); + + expectedTotalGas += tokenTransferFeeConfig.destGasOverhead == 0 + ? DEFAULT_TOKEN_DEST_GAS_OVERHEAD + : tokenTransferFeeConfig.destGasOverhead; + expectedTotalBytes += tokenTransferFeeConfig.destBytesOverhead == 0 + ? DEFAULT_TOKEN_BYTES_OVERHEAD + : tokenTransferFeeConfig.destBytesOverhead; + } + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + + uint256 expectedFeeUSDWei = 0; + for (uint256 i = 0; i < testTokens.length; ++i) { + expectedFeeUSDWei += _configUSDCentToWei( + tokenTransferFeeConfigs[i].minFeeUSDCents == 0 + ? DEFAULT_TOKEN_FEE_USD_CENTS + : tokenTransferFeeConfigs[i].minFeeUSDCents + ); + } + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 1"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 1"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 1"); + + // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee + message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); + + uint256 token0USDWei = _applyBpsRatio( + _calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps + ); + uint256 token1USDWei = _configUSDCentToWei(DEFAULT_TOKEN_FEE_USD_CENTS); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 2"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 2"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 2"); + + // Set 2nd token transfer to a large amount that is higher than maxFeeUSD + message.tokenAmounts[2] = Client.EVMTokenAmount({token: testTokens[2], amount: 1e36}); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); + expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].maxFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 3"); + assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 3"); + assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 3"); + } +} + +contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_ZeroDataAvailabilityMultiplier_Success() public { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + destChainConfigArgs[0] = + FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; + assertEq(totalPriceInFeeToken, feeAmount); + } + + function test_HighGasMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = MAX_GAS_LIMIT; + uint256 customDataSize = MAX_DATA_SIZE; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: new bytes(customDataSize), + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint32 destBytesOverhead = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; + uint32 tokenBytesOverhead = + destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; + + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + (uint256 transferFeeUSD,,) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); + uint256 messageFeeUSD = (transferFeeUSD * s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken)); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_MessageWithDataAndTokenTransfer_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = 1_000_000; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](2), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + + message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount + message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount + message.data = "random bits and bytes that should be factored into the cost of the message"; + + uint32 tokenGasOverhead = 0; + uint32 tokenBytesOverhead = 0; + for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { + tokenGasOverhead += + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; + uint32 destBytesOverhead = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destBytesOverhead; + tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; + } + + uint256 gasUsed = + customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + (uint256 transferFeeUSD,,) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); + uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message)); + } + } + + function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { + // Update config to enforce allowOutOfOrderExecution = defaultVal. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) + ); + + // If enforcement is on, only true should be allowed. + if (enforce && !allowOutOfOrderExecution) { + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + } + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Reverts + + function test_DestinationChainNotEnabled_Revert() public { + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); + } + + function test_EnforceOutOfOrder_Revert() public { + // Update config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Empty extraArgs to should revert since it enforceOutOfOrder is true. + message.extraArgs = ""; + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_MessageTooLarge_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.data = new bytes(MAX_DATA_SIZE + 1); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_TooManyTokens_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint256 tooMany = MAX_TOKENS_LENGTH + 1; + message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); + vm.expectRevert(FeeQuoter.UnsupportedNumberOfTokens.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Asserts gasLimit must be <=maxGasLimit + function test_MessageGasLimitTooHigh_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageGasLimitTooHigh.selector)); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_NotAFeeToken_Revert() public { + address notAFeeToken = address(0x111111); + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); + message.feeToken = notAFeeToken; + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, notAFeeToken)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_InvalidEVMAddress_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.receiver = abi.encode(type(uint208).max); + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); + + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } +} + +contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { + using USDPriceWith18Decimals for uint224; + + function setUp() public virtual override { + super.setUp(); + } + + function test_processMessageArgs_WithLinkTokenAmount_Success() public view { + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + , + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + // LINK + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); + } + + function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { + address feeToken = s_sourceTokens[1]; + uint256 feeTokenAmount = 10_000 gwei; + uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); + + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + , + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + feeToken, + feeTokenAmount, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(msgFeeJuels, expectedConvertedAmount); + } + + function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(isOutOfOrderExecution, false); + assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); + } + + function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); + + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + extraArgs, + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(isOutOfOrderExecution, false); + assertEq( + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); + + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + extraArgs, + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + + assertEq(isOutOfOrderExecution, true); + assertEq( + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + // Reverts + + function test_processMessageArgs_MessageFeeTooHigh_Revert() public { + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + ); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS + 1, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_InvalidExtraArgs_Revert() public { + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "abcde", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { + // abi.decode error + vm.expectRevert(); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})), + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + sourceTokenAmounts[1].amount = 1e18; + sourceTokenAmounts[1].token = CUSTOM_TOKEN_2; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](2); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + bytes[] memory expectedDestExecData = new bytes[](2); + expectedDestExecData[0] = abi.encode( + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead + ); + expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false + + // No revert - successful + ( /* msgFeeJuels */ , /* isOutOfOrderExecution */, /* convertedExtraArgs */, bytes[] memory destExecData) = + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + for (uint256 i = 0; i < destExecData.length; ++i) { + assertEq(destExecData[i], expectedDestExecData[i]); + } + } + + function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + + // Revert due to index out of bounds access + vm.expectRevert(); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "", + new Internal.EVM2AnyTokenTransfer[](1), + new Client.EVMTokenAmount[](0) + ); + } + + function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { + address sourceETH = s_sourceTokens[1]; + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1000; + sourceTokenAmounts[0].token = sourceETH; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + + // No data set, should succeed + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set max data length, should succeed + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set data to max length +1, should revert + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set token config to allow larger data + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + + // Set the token data larger than the configured token data, should revert + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + } + + function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { + bytes memory nonEvmAddress = abi.encode(type(uint208).max); + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[0].destTokenAddress = nonEvmAddress; + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts + ); + } +} + +contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { + function test_ValidEVMAddress_Success() public view { + bytes memory encodedAddress = abi.encode(address(10000)); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + } + + function test_ValidNonEVMAddress_Success() public view { + s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + } + + // Reverts + + function test_InvalidEVMAddress_Revert() public { + bytes memory invalidAddress = abi.encode(type(uint208).max); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + function test_InvalidEVMAddressEncodePacked_Revert() public { + bytes memory invalidAddress = abi.encodePacked(address(234)); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + function test_InvalidEVMAddressPrecompiles_Revert() public { + for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { + bytes memory invalidAddress = abi.encode(address(i)); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + s_feeQuoter.validateDestFamilyAddress( + Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) + ); + } +} + +contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { + FeeQuoter.DestChainConfig private s_destChainConfig; + + function setUp() public virtual override { + super.setUp(); + s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; + } + + function test_EVMExtraArgsV1_Success() public view { + Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + + vm.assertEq( + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), + abi.encode(expectedOutputArgs) + ); + } + + function test_EVMExtraArgsV2_Success() public view { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.assertEq( + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) + ); + } + + function test_EVMExtraArgsDefault_Success() public view { + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); + + vm.assertEq( + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) + ); + } + + // Reverts + + function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + // Invalidate selector + inputExtraArgs[0] = bytes1(uint8(0)); + + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + s_destChainConfig.enforceOutOfOrder = true; + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_EVMExtraArgsGasLimitTooHigh_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.expectRevert(FeeQuoter.MessageGasLimitTooHigh.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } +} + +contract FeeQuoter_KeystoneSetup is FeeQuoterSetup { + address internal constant FORWARDER_1 = address(0x1); + address internal constant WORKFLOW_OWNER_1 = address(0x3); + bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; + bytes2 internal constant REPORT_NAME_1 = "01"; + address internal onReportTestToken1; + address internal onReportTestToken2; + + function setUp() public virtual override { + super.setUp(); + onReportTestToken1 = s_sourceTokens[0]; + onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); + + KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); + permissions[0] = KeystoneFeedsPermissionHandler.Permission({ + forwarder: FORWARDER_1, + workflowOwner: WORKFLOW_OWNER_1, + workflowName: WORKFLOW_NAME_1, + reportName: REPORT_NAME_1, + isAllowed: true + }); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); + tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: onReportTestToken1, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) + }); + tokenPriceFeeds[1] = FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: onReportTestToken2, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) + }); + s_feeQuoter.setReportPermissions(permissions); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); + } +} + +contract FeeQuoter_onReport is FeeQuoter_KeystoneSetup { + function test_onReport_Success() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + report[1] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); + uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, report[1].price); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredToken1Price, block.timestamp); + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken2, expectedStoredToken2Price, block.timestamp); + + changePrank(FORWARDER_1); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).timestamp, report[0].timestamp); + + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).value, expectedStoredToken2Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); + } + + function test_onReport_InvalidForwarder_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); + + vm.expectRevert( + abi.encodeWithSelector( + KeystoneFeedsPermissionHandler.ReportForwarderUnauthorized.selector, + STRANGER, + WORKFLOW_OWNER_1, + WORKFLOW_NAME_1, + REPORT_NAME_1 + ) + ); + changePrank(STRANGER); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } + + function test_onReport_UnsupportedToken_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); + changePrank(FORWARDER_1); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } + + function test_OnReport_StaleUpdate_Revert() public { + //Creating a correct report + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + + uint224 expectedStoredTokenPrice = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredTokenPrice, block.timestamp); + + changePrank(FORWARDER_1); + //setting the correct price and time with the correct report + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + + //create a stale report + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp - 1)}); + //expecting a revert + vm.expectRevert( + abi.encodeWithSelector( + FeeQuoter.StaleKeystoneUpdate.selector, onReportTestToken1, block.timestamp - 1, block.timestamp + ) + ); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol new file mode 100644 index 0000000..056c749 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; + +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; +import {TokenSetup} from "../TokenSetup.t.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; + +contract FeeQuoterSetup is TokenSetup { + uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei + uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei + + address internal constant CUSTOM_TOKEN = address(12345); + address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); + + uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM + uint224 internal constant CUSTOM_TOKEN_PRICE_2 = 1e18; // $1 CUSTOM + + // Encode L1 gas price and L2 gas price into a packed price. + // L1 gas price is left-shifted to the higher-order bits. + uint224 internal constant PACKED_USD_PER_GAS = + (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; + + FeeQuoterHelper internal s_feeQuoter; + // Cheat to store the price updates in storage since struct arrays aren't supported. + bytes internal s_encodedInitialPriceUpdates; + address internal s_weth; + + address[] internal s_sourceFeeTokens; + uint224[] internal s_sourceTokenPrices; + address[] internal s_destFeeTokens; + uint224[] internal s_destTokenPrices; + + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] internal s_feeQuoterPremiumMultiplierWeiPerEthArgs; + FeeQuoter.TokenTransferFeeConfigArgs[] internal s_feeQuoterTokenTransferFeeConfigArgs; + + mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; + + function setUp() public virtual override { + TokenSetup.setUp(); + + _deployTokenPriceDataFeed(s_sourceFeeToken, 8, 1e8); + + s_weth = s_sourceRouter.getWrappedNative(); + _deployTokenPriceDataFeed(s_weth, 8, 1e11); + + address[] memory sourceFeeTokens = new address[](3); + sourceFeeTokens[0] = s_sourceTokens[0]; + sourceFeeTokens[1] = s_sourceTokens[1]; + sourceFeeTokens[2] = s_sourceRouter.getWrappedNative(); + s_sourceFeeTokens = sourceFeeTokens; + + uint224[] memory sourceTokenPrices = new uint224[](3); + sourceTokenPrices[0] = 5e18; + sourceTokenPrices[1] = 2000e18; + sourceTokenPrices[2] = 2000e18; + s_sourceTokenPrices = sourceTokenPrices; + + address[] memory destFeeTokens = new address[](3); + destFeeTokens[0] = s_destTokens[0]; + destFeeTokens[1] = s_destTokens[1]; + destFeeTokens[2] = s_destRouter.getWrappedNative(); + s_destFeeTokens = destFeeTokens; + + uint224[] memory destTokenPrices = new uint224[](3); + destTokenPrices[0] = 5e18; + destTokenPrices[1] = 2000e18; + destTokenPrices[2] = 2000e18; + s_destTokenPrices = destTokenPrices; + + uint256 sourceTokenCount = sourceFeeTokens.length; + uint256 destTokenCount = destFeeTokens.length; + address[] memory pricedTokens = new address[](sourceTokenCount + destTokenCount); + uint224[] memory tokenPrices = new uint224[](sourceTokenCount + destTokenCount); + for (uint256 i = 0; i < sourceTokenCount; ++i) { + pricedTokens[i] = sourceFeeTokens[i]; + tokenPrices[i] = sourceTokenPrices[i]; + } + for (uint256 i = 0; i < destTokenCount; ++i) { + pricedTokens[i + sourceTokenCount] = destFeeTokens[i]; + tokenPrices[i + sourceTokenCount] = destTokenPrices[i]; + } + + Internal.PriceUpdates memory priceUpdates = _getPriceUpdatesStruct(pricedTokens, tokenPrices); + priceUpdates.gasPriceUpdates = new Internal.GasPriceUpdate[](1); + priceUpdates.gasPriceUpdates[0] = + Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: PACKED_USD_PER_GAS}); + + s_encodedInitialPriceUpdates = abi.encode(priceUpdates); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = OWNER; + address[] memory feeTokens = new address[](2); + feeTokens[0] = s_sourceTokens[0]; + feeTokens[1] = s_weth; + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); + + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceFeeToken, + premiumMultiplierWeiPerEth: 5e17 // 0.5x + }) + ); + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceRouter.getWrappedNative(), + premiumMultiplierWeiPerEth: 2e18 // 2x + }) + ); + + s_feeQuoterTokenTransferFeeConfigArgs.push(); + s_feeQuoterTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: s_sourceFeeToken, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1_00, // 1 USD + maxFeeUSDCents: 1000_00, // 1,000 USD + deciBps: 2_5, // 2.5 bps, or 0.025% + destGasOverhead: 100_000, + destBytesOverhead: 32, + isEnabled: true + }) + }) + ); + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 95_000, + destBytesOverhead: 200, + isEnabled: true + }) + }) + ); + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN_2, + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 1, + destBytesOverhead: 200, + isEnabled: false + }) + }) + ); + + //setting up the destination token for CUSTOM_TOKEN_2 here as it is specific to these tests + s_destTokenBySourceToken[CUSTOM_TOKEN_2] = address(bytes20(keccak256("CUSTOM_TOKEN_2_DEST"))); + + s_feeQuoter = new FeeQuoterHelper( + FeeQuoter.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }), + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + _generateFeeQuoterDestChainConfigArgs() + ); + s_feeQuoter.updatePrices(priceUpdates); + } + + function _deployTokenPriceDataFeed(address token, uint8 decimals, int256 initialAnswer) internal returns (address) { + MockV3Aggregator dataFeed = new MockV3Aggregator(decimals, initialAnswer); + s_dataFeedByToken[token] = address(dataFeed); + return address(dataFeed); + } + + function _getPriceUpdatesStruct( + address[] memory tokens, + uint224[] memory prices + ) internal pure returns (Internal.PriceUpdates memory) { + uint256 length = tokens.length; + + Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](length); + for (uint256 i = 0; i < length; ++i) { + tokenPriceUpdates[i] = Internal.TokenPriceUpdate({sourceToken: tokens[i], usdPerToken: prices[i]}); + } + Internal.PriceUpdates memory priceUpdates = + Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); + + return priceUpdates; + } + + function _getEmptyPriceUpdates() internal pure returns (Internal.PriceUpdates memory priceUpdates) { + return Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + } + + function _getSingleTokenPriceFeedUpdateStruct( + address sourceToken, + address dataFeedAddress, + uint8 tokenDecimals + ) internal pure returns (FeeQuoter.TokenPriceFeedUpdate memory) { + return FeeQuoter.TokenPriceFeedUpdate({ + sourceToken: sourceToken, + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) + }); + } + + function _initialiseSingleTokenPriceFeed() internal returns (address) { + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); + tokenPriceFeedUpdates[0] = + _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + return s_sourceTokens[0]; + } + + function _generateTokenTransferFeeConfigArgs( + uint256 destChainSelectorLength, + uint256 tokenLength + ) internal pure returns (FeeQuoter.TokenTransferFeeConfigArgs[] memory) { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + new FeeQuoter.TokenTransferFeeConfigArgs[](destChainSelectorLength); + for (uint256 i = 0; i < destChainSelectorLength; ++i) { + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = + new FeeQuoter.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); + } + return tokenTransferFeeConfigArgs; + } + + function _generateFeeQuoterDestChainConfigArgs() internal pure returns (FeeQuoter.DestChainConfigArgs[] memory) { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); + destChainConfigs[0] = FeeQuoter.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + destChainConfig: FeeQuoter.DestChainConfig({ + isEnabled: true, + maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, + destGasOverhead: DEST_GAS_OVERHEAD, + destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, + destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, + destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, + destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, + maxDataBytes: MAX_DATA_SIZE, + maxPerMsgGasLimit: MAX_GAS_LIMIT, + defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, + defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + defaultTxGasLimit: GAS_LIMIT, + gasMultiplierWeiPerEth: 5e17, + networkFeeUSDCents: 1_00, + enforceOutOfOrder: false, + chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM + }) + }); + return destChainConfigs; + } + + function _assertTokenPriceFeedConfigEquality( + FeeQuoter.TokenPriceFeedConfig memory config1, + FeeQuoter.TokenPriceFeedConfig memory config2 + ) internal pure virtual { + assertEq(config1.dataFeedAddress, config2.dataFeedAddress); + assertEq(config1.tokenDecimals, config2.tokenDecimals); + } + + function _assertTokenPriceFeedConfigUnconfigured( + FeeQuoter.TokenPriceFeedConfig memory config + ) internal pure virtual { + _assertTokenPriceFeedConfigEquality( + config, FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) + ); + } + + function _assertTokenTransferFeeConfigEqual( + FeeQuoter.TokenTransferFeeConfig memory a, + FeeQuoter.TokenTransferFeeConfig memory b + ) internal pure { + assertEq(a.minFeeUSDCents, b.minFeeUSDCents); + assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); + assertEq(a.deciBps, b.deciBps); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destBytesOverhead, b.destBytesOverhead); + assertEq(a.isEnabled, b.isEnabled); + } + + function _assertFeeQuoterStaticConfigsEqual( + FeeQuoter.StaticConfig memory a, + FeeQuoter.StaticConfig memory b + ) internal pure { + assertEq(a.linkToken, b.linkToken); + assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); + } + + function _assertFeeQuoterDestChainConfigsEqual( + FeeQuoter.DestChainConfig memory a, + FeeQuoter.DestChainConfig memory b + ) internal pure { + assertEq(a.isEnabled, b.isEnabled); + assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); + assertEq(a.maxDataBytes, b.maxDataBytes); + assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); + assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); + assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); + assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); + assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); + assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); + assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); + } +} + +contract FeeQuoterFeeSetup is FeeQuoterSetup { + uint224 internal s_feeTokenPrice; + uint224 internal s_wrappedTokenPrice; + uint224 internal s_customTokenPrice; + + address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); + + address internal s_destTokenPool = makeAddr("destTokenPool"); + address internal s_destToken = makeAddr("destToken"); + + function setUp() public virtual override { + super.setUp(); + + s_feeTokenPrice = s_sourceTokenPrices[0]; + s_wrappedTokenPrice = s_sourceTokenPrices[2]; + s_customTokenPrice = CUSTOM_TOKEN_PRICE; + + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); + } + + function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _generateSingleTokenMessage( + address token, + uint256 amount + ) public view returns (Client.EVM2AnyMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 sourceChainSelector, + uint64 destChainSelector, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + uint256 feeValueJuels, + address originalSender, + bytes32 metadataHash, + TokenAdminRegistry tokenAdminRegistry + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + Client.EVMExtraArgsV2 memory extraArgs = + s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + + Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: destChainSelector, + sequenceNumber: seqNum, + nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce + }), + sender: originalSender, + data: message.data, + receiver: message.receiver, + extraArgs: Client._argsToBytes(extraArgs), + feeToken: message.feeToken, + feeTokenAmount: feeTokenAmount, + feeValueJuels: feeValueJuels, + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) + }); + + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + messageEvent.tokenAmounts[i] = + _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry, DEST_CHAIN_SELECTOR); + } + + messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); + return messageEvent; + } + + function _getSourceTokenData( + Client.EVMTokenAmount memory tokenAmount, + TokenAdminRegistry tokenAdminRegistry, + uint64 destChainSelector + ) internal view returns (Internal.EVM2AnyTokenTransfer memory) { + address destToken = s_destTokenBySourceToken[tokenAmount.token]; + + uint32 expectedDestGasAmount; + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + FeeQuoter(s_feeQuoter).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); + expectedDestGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, + destTokenAddress: abi.encode(destToken), + extraData: "", + amount: tokenAmount.amount, + destExecData: abi.encode(expectedDestGasAmount) + }); + } + + function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { + return (tokenPrice * tokenAmount) / 1e18; + } + + function _applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { + return (tokenAmount * ratio) / 1e5; + } + + function _configUSDCentToWei( + uint256 usdCent + ) internal pure returns (uint256) { + return usdCent * 1e16; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol new file mode 100644 index 0000000..c3f95a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; + +contract BurnMintERC677Helper is BurnMintERC677, IGetCCIPAdmin { + constructor(string memory name, string memory symbol) BurnMintERC677(name, symbol, 18, 0) {} + + // Gives one full token to any given address. + function drip( + address to + ) external { + _mint(to, 1e18); + } + + function getCCIPAdmin() external view override returns (address) { + return owner(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol new file mode 100644 index 0000000..bb1d4c9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {Pool} from "../../libraries/Pool.sol"; +import {MultiTokenPool} from "./MultiTokenPool.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnMintMultiTokenPool is MultiTokenPool { + constructor( + IERC20[] memory tokens, + address[] memory allowlist, + address rmnProxy, + address router + ) MultiTokenPool(tokens, allowlist, rmnProxy, router) {} + + /// @notice Burn the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + IBurnMintERC20(lockOrBurnIn.localToken).burn(lockOrBurnIn.amount); + + emit Burned(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.localToken, lockOrBurnIn.remoteChainSelector), + destPoolData: "" + }); + } + + /// @notice Mint tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + // Mint to the receiver + IBurnMintERC20(releaseOrMintIn.localToken).mint(msg.sender, releaseOrMintIn.amount); + + emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol new file mode 100644 index 0000000..0bc97c7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {CCIPHome} from "../../capability/CCIPHome.sol"; + +contract CCIPHomeHelper is CCIPHome { + constructor( + address capabilitiesRegistry + ) CCIPHome(capabilitiesRegistry) {} + + function validateConfig( + OCR3Config memory cfg + ) external view { + return _validateConfig(cfg); + } + + function ensureInRegistry( + bytes32[] memory p2pIds + ) external view { + return _ensureInRegistry(p2pIds); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol new file mode 100644 index 0000000..617d39a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; + +contract ERC20RebasingHelper is ERC20 { + uint16 public s_multiplierPercentage = 100; + bool public s_mintShouldBurn = false; + + constructor() ERC20("Rebasing", "REB") {} + + function mint(address to, uint256 amount) external { + if (!s_mintShouldBurn) { + _mint(to, amount * s_multiplierPercentage / 100); + return; + } + _burn(to, amount * s_multiplierPercentage / 100); + } + + function setMultiplierPercentage( + uint16 multiplierPercentage + ) external { + s_multiplierPercentage = multiplierPercentage; + } + + function setMintShouldBurn( + bool mintShouldBurn + ) external { + s_mintShouldBurn = mintShouldBurn; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol new file mode 100644 index 0000000..9f4ca68 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +contract EVM2EVMOffRampHelper { + uint64 public s_nonce; + mapping(address sender => uint64 nonce) public s_nonces; + + function execute( + address[] memory senders + ) external { + for (uint256 i; i < senders.length; i++) { + s_nonces[senders[i]]++; + } + } + + function metadataHash() external pure returns (bytes32) { + return 0x0; + } + + function getSenderNonce( + address sender + ) external view returns (uint64 nonce) { + return s_nonces[sender]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol new file mode 100644 index 0000000..e357645 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {EtherSenderReceiver} from "../../applications/EtherSenderReceiver.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract EtherSenderReceiverHelper is EtherSenderReceiver { + constructor( + address router + ) EtherSenderReceiver(router) {} + + function validatedMessage( + Client.EVM2AnyMessage calldata message + ) public view returns (Client.EVM2AnyMessage memory) { + return _validatedMessage(message); + } + + function validateFeeToken( + Client.EVM2AnyMessage calldata message + ) public payable { + _validateFeeToken(message); + } + + function publicCcipReceive( + Client.Any2EVMMessage memory message + ) public { + _ccipReceive(message); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol new file mode 100644 index 0000000..e392ba0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract FeeQuoterHelper is FeeQuoter { + constructor( + StaticConfig memory staticConfig, + address[] memory priceUpdaters, + address[] memory feeTokens, + TokenPriceFeedUpdate[] memory tokenPriceFeeds, + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, + DestChainConfigArgs[] memory destChainConfigArgs + ) + FeeQuoter( + staticConfig, + priceUpdaters, + feeTokens, + tokenPriceFeeds, + tokenTransferFeeConfigArgs, + premiumMultiplierWeiPerEthArgs, + destChainConfigArgs + ) + {} + + function getDataAvailabilityCost( + uint64 destChainSelector, + uint112 dataAvailabilityGasPrice, + uint256 messageDataLength, + uint256 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) external view returns (uint256) { + return _getDataAvailabilityCost( + s_destChainConfigs[destChainSelector], + dataAvailabilityGasPrice, + messageDataLength, + numberOfTokens, + tokenTransferBytesOverhead + ); + } + + function getTokenTransferCost( + uint64 destChainSelector, + address feeToken, + uint224 feeTokenPrice, + Client.EVMTokenAmount[] calldata tokenAmounts + ) external view returns (uint256, uint32, uint32) { + return _getTokenTransferCost( + s_destChainConfigs[destChainSelector], destChainSelector, feeToken, feeTokenPrice, tokenAmounts + ); + } + + function parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 destChainSelector + ) external view returns (Client.EVMExtraArgsV2 memory) { + return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfigs[destChainSelector]); + } + + function parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) external pure returns (Client.EVMExtraArgsV2 memory) { + return _parseEVMExtraArgsFromBytes(extraArgs, destChainConfig); + } + + function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { + _validateDestFamilyAddress(chainFamilySelector, destAddress); + } + + function calculateRebasedValue( + uint8 dataFeedDecimal, + uint8 tokenDecimal, + uint256 feedValue + ) external pure returns (uint224) { + return _calculateRebasedValue(dataFeedDecimal, tokenDecimal, feedValue); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol new file mode 100644 index 0000000..b301240 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +contract IgnoreContractSize { + // test contracts are excluded from forge build --sizes by default + // --sizes exits with code 1 if any contract is over limit, which fails CI + // for helper contracts that are not explicit test contracts + // use this flag to exclude from --sizes + bool public IS_SCRIPT = true; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol new file mode 100644 index 0000000..23e13aa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {Pool} from "../../libraries/Pool.sol"; +import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; + +contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { + bytes public s_revertReason = ""; + bytes public s_sourceTokenData = ""; + uint256 public s_releaseOrMintMultiplier = 1; + + constructor( + IBurnMintERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} + + function setShouldRevert( + bytes calldata revertReason + ) external { + s_revertReason = revertReason; + } + + function setSourceTokenData( + bytes calldata sourceTokenData + ) external { + s_sourceTokenData = sourceTokenData; + } + + function setReleaseOrMintMultiplier( + uint256 multiplier + ) external { + s_releaseOrMintMultiplier = multiplier; + } + + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + bytes memory revertReason = s_revertReason; + if (revertReason.length != 0) { + assembly { + revert(add(32, revertReason), mload(revertReason)) + } + } + + IBurnMintERC20(address(i_token)).burn(lockOrBurnIn.amount); + emit Burned(msg.sender, lockOrBurnIn.amount); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: s_sourceTokenData + }); + } + + /// @notice Reverts depending on the value of `s_revertReason` + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + + bytes memory revertReason = s_revertReason; + if (revertReason.length != 0) { + assembly { + revert(add(32, revertReason), mload(revertReason)) + } + } + uint256 amount = releaseOrMintIn.amount * s_releaseOrMintMultiplier; + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, amount); + + emit Minted(msg.sender, releaseOrMintIn.receiver, amount); + return Pool.ReleaseOrMintOutV1({destinationAmount: amount}); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol new file mode 100644 index 0000000..3893d08 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; + +library MerkleHelper { + /// @notice Generate a Merkle Root from a full set of leaves. When a tree is unbalanced + /// the value is brought up in the tree. For example consider (a,b,c) as leaves. This would + /// result in the following tree with d being computed from hash(a,c) and the root r from + /// hash(d,c). Notice c is not being rehashed when it is brought up in the tree, so the + /// root is NOT hash(d,hash(c)) but instead hash(d,c) == hash(hash(a,b),c). + /// r + /// / \ + /// d c + /// / \ + /// a b + function getMerkleRoot( + bytes32[] memory hashedLeaves + ) public pure returns (bytes32) { + // solhint-disable-next-line reason-string,gas-custom-errors + require(hashedLeaves.length <= 256); + while (hashedLeaves.length > 1) { + hashedLeaves = computeNextLayer(hashedLeaves); + } + return hashedLeaves[0]; + } + + /// @notice Computes a single layer of a merkle proof by hashing each pair (i, i+1) for + /// each i, i+2, i+4.. n. When an uneven number of leaves is supplied the last item + /// is simply included as the last element in the result set and not hashed. + function computeNextLayer( + bytes32[] memory layer + ) public pure returns (bytes32[] memory) { + uint256 leavesLen = layer.length; + if (leavesLen == 1) return layer; + + unchecked { + bytes32[] memory nextLayer = new bytes32[]((leavesLen + 1) / 2); + for (uint256 i = 0; i < leavesLen; i += 2) { + if (i == leavesLen - 1) { + nextLayer[i / 2] = layer[i]; + } else { + nextLayer[i / 2] = hashPair(layer[i], layer[i + 1]); + } + } + return nextLayer; + } + } + + function hashPair(bytes32 a, bytes32 b) public pure returns (bytes32) { + return a < b ? hashInternalNode(a, b) : hashInternalNode(b, a); + } + + function hashInternalNode(bytes32 left, bytes32 right) public pure returns (bytes32 hash) { + return keccak256(abi.encode(MerkleMultiProof.INTERNAL_DOMAIN_SEPARATOR, left, right)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol new file mode 100644 index 0000000..68d6dc4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.4; + +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; + +/// @notice MessageHasher is a contract that utility functions to hash an Any2EVMRampMessage +/// and encode various preimages for the final hash of the message. +/// @dev This is only deployed in tests and is not part of the production contracts. +contract MessageHasher { + function hash(Internal.Any2EVMRampMessage memory message, bytes memory onRamp) public pure returns (bytes32) { + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); + } + + function encodeAny2EVMTokenAmountsHashPreimage( + Internal.Any2EVMTokenTransfer[] memory tokenAmounts + ) public pure returns (bytes memory) { + return abi.encode(tokenAmounts); + } + + function encodeEVM2AnyTokenAmountsHashPreimage( + Internal.EVM2AnyTokenTransfer[] memory tokenAmount + ) public pure returns (bytes memory) { + return abi.encode(tokenAmount); + } + + function encodeMetadataHashPreimage( + bytes32 any2EVMMessageHash, + uint64 sourceChainSelector, + uint64 destChainSelector, + bytes32 onRampHash + ) public pure returns (bytes memory) { + return abi.encode(any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash); + } + + function encodeFixedSizeFieldsHashPreimage( + bytes32 messageId, + address receiver, + uint64 sequenceNumber, + uint256 gasLimit, + uint64 nonce + ) public pure returns (bytes memory) { + return abi.encode(messageId, receiver, sequenceNumber, gasLimit, nonce); + } + + function encodeFinalHashPreimage( + bytes32 leafDomainSeparator, + bytes32 metaDataHash, + bytes32 fixedSizeFieldsHash, + bytes32 senderHash, + bytes32 dataHash, + bytes32 tokenAmountsHash + ) public pure returns (bytes memory) { + return abi.encode(leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash); + } + + function encodeEVMExtraArgsV1( + Client.EVMExtraArgsV1 memory extraArgs + ) public pure returns (bytes memory) { + return Client._argsToBytes(extraArgs); + } + + function encodeEVMExtraArgsV2( + Client.EVMExtraArgsV2 memory extraArgs + ) public pure returns (bytes memory) { + return Client._argsToBytes(extraArgs); + } + + function decodeEVMExtraArgsV1( + uint256 gasLimit + ) public pure returns (Client.EVMExtraArgsV1 memory) { + return Client.EVMExtraArgsV1(gasLimit); + } + + function decodeEVMExtraArgsV2( + uint256 gasLimit, + bool allowOutOfOrderExecution + ) public pure returns (Client.EVMExtraArgsV2 memory) { + return Client.EVMExtraArgsV2(gasLimit, allowOutOfOrderExecution); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol new file mode 100644 index 0000000..80cdf61 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract MessageInterceptorHelper is IMessageInterceptor { + mapping(bytes32 messageId => bool isInvalid) internal s_invalidMessageIds; + + constructor() {} + + function setMessageIdValidationState(bytes32 messageId, bool isInvalid) external { + s_invalidMessageIds[messageId] = isInvalid; + } + + /// @inheritdoc IMessageInterceptor + function onInboundMessage( + Client.Any2EVMMessage memory message + ) external view { + if (s_invalidMessageIds[message.messageId]) { + revert MessageValidationError(bytes("Invalid message")); + } + } + + /// @inheritdoc IMessageInterceptor + function onOutboundMessage(uint64, Client.EVM2AnyMessage calldata message) external view { + if (s_invalidMessageIds[keccak256(abi.encode(message))]) { + revert MessageValidationError(bytes("Invalid message")); + } + return; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol new file mode 100644 index 0000000..7c2e6cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { + constructor( + address feeQuoter, + address[] memory authorizedCallers + ) MultiAggregateRateLimiter(feeQuoter, authorizedCallers) {} + + function getTokenValue( + Client.EVMTokenAmount memory tokenAmount + ) public view returns (uint256) { + return _getTokenValue(tokenAmount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol new file mode 100644 index 0000000..e760b79 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; + +contract MultiOCR3Helper is MultiOCR3Base { + event AfterConfigSet(uint8 ocrPluginType); + + /// @dev OCR plugin type used for transmit. + /// Defined in storage since it cannot be passed as calldata due to strict transmit checks + uint8 internal s_transmitOcrPluginType; + + function setTransmitOcrPluginType( + uint8 ocrPluginType + ) external { + s_transmitOcrPluginType = ocrPluginType; + } + + /// @dev transmit function with signatures + function transmitWithSignatures( + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs + ) external { + _transmit(s_transmitOcrPluginType, reportContext, report, rs, ss, rawVs); + } + + /// @dev transmit function with no signatures + function transmitWithoutSignatures(bytes32[3] calldata reportContext, bytes calldata report) external { + bytes32[] memory emptySigs = new bytes32[](0); + _transmit(s_transmitOcrPluginType, reportContext, report, emptySigs, emptySigs, bytes32("")); + } + + function getOracle(uint8 ocrPluginType, address oracleAddress) external view returns (Oracle memory) { + return s_oracles[ocrPluginType][oracleAddress]; + } + + function typeAndVersion() public pure override returns (string memory) { + return "MultiOCR3BaseHelper 1.0.0"; + } + + function _afterOCR3ConfigSet( + uint8 ocrPluginType + ) internal virtual override { + emit AfterConfigSet(ocrPluginType); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol new file mode 100644 index 0000000..316439b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IPoolV1} from "../../interfaces/IPool.sol"; +import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice This contract is a proof of concept and should NOT be used in production. +abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { + using EnumerableSet for EnumerableSet.AddressSet; + using EnumerableSet for EnumerableSet.UintSet; + using RateLimiter for RateLimiter.TokenBucket; + + error CallerIsNotARampOnRouter(address caller); + error ZeroAddressNotAllowed(); + error SenderNotAllowed(address sender); + error AllowListNotEnabled(); + error NonExistentChain(uint64 remoteChainSelector); + error ChainNotAllowed(uint64 remoteChainSelector); + error CursedByRMN(); + error ChainAlreadyExists(uint64 chainSelector); + error InvalidSourcePoolAddress(bytes sourcePoolAddress); + error InvalidToken(address token); + + event Locked(address indexed sender, uint256 amount); + event Burned(address indexed sender, uint256 amount); + event Released(address indexed sender, address indexed recipient, uint256 amount); + event Minted(address indexed sender, address indexed recipient, uint256 amount); + event ChainAdded( + uint64 remoteChainSelector, + bytes remoteToken, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainConfigured( + uint64 remoteChainSelector, + RateLimiter.Config outboundRateLimiterConfig, + RateLimiter.Config inboundRateLimiterConfig + ); + event ChainRemoved(uint64 remoteChainSelector); + event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); + event AllowListAdd(address sender); + event AllowListRemove(address sender); + event RouterUpdated(address oldRouter, address newRouter); + + struct ChainUpdate { + uint64 remoteChainSelector; // ──╮ Remote chain selector + bool allowed; // ────────────────╯ Whether the chain is allowed + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain + RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + } + + struct RemoteChainConfig { + RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain + RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + } + + /// @dev The IERC20 token that this pool supports + EnumerableSet.AddressSet internal s_tokens; + /// @dev The address of the RMN proxy + address internal immutable i_rmnProxy; + /// @dev The immutable flag that indicates if the pool is access-controlled. + bool internal immutable i_allowlistEnabled; + /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. + /// Only takes effect if i_allowlistEnabled is true. + /// This can be used to ensure only token-issuer specified addresses can + /// move tokens. + EnumerableSet.AddressSet internal s_allowList; + /// @dev The address of the router + IRouter internal s_router; + /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to + /// be able to quickly determine (without parsing logs) who can access the pool. + /// @dev The chain selectors are in uin256 format because of the EnumerableSet implementation. + EnumerableSet.UintSet internal s_remoteChainSelectors; + mapping(address token => mapping(uint64 remoteChainSelector => RemoteChainConfig)) internal s_remoteChainConfigs; + + constructor(IERC20[] memory token, address[] memory allowlist, address rmnProxy, address router) { + if (router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); + for (uint256 i = 0; i < token.length; ++i) { + s_tokens.add(address(token[i])); + } + i_rmnProxy = rmnProxy; + s_router = IRouter(router); + + // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. + i_allowlistEnabled = allowlist.length > 0; + if (i_allowlistEnabled) { + _applyAllowListUpdates(new address[](0), allowlist); + } + } + + /// @notice Get RMN proxy address + /// @return rmnProxy Address of RMN proxy + function getRmnProxy() public view returns (address rmnProxy) { + return i_rmnProxy; + } + + /// @inheritdoc IPoolV1 + function isSupportedToken( + address token + ) public view virtual returns (bool) { + return s_tokens.contains(token); + } + + /// @notice Gets the IERC20 token that this pool can lock or burn. + /// @return tokens The IERC20 token representation. + function getTokens() public view returns (IERC20[] memory tokens) { + tokens = new IERC20[](s_tokens.length()); + for (uint256 i = 0; i < s_tokens.length(); ++i) { + tokens[i] = IERC20(s_tokens.at(i)); + } + return tokens; + } + + /// @notice Gets the pool's Router + /// @return router The pool's Router + function getRouter() public view returns (address router) { + return address(s_router); + } + + /// @notice Sets the pool's Router + /// @param newRouter The new Router + function setRouter( + address newRouter + ) public onlyOwner { + if (newRouter == address(0)) revert ZeroAddressNotAllowed(); + address oldRouter = address(s_router); + s_router = IRouter(newRouter); + + emit RouterUpdated(oldRouter, newRouter); + } + + /// @notice Signals which version of the pool interface is supported + function supportsInterface( + bytes4 interfaceId + ) public pure virtual override returns (bool) { + return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId + || interfaceId == type(IERC165).interfaceId; + } + + // ================================================================ + // │ Validation │ + // ================================================================ + + /// @notice Validates the lock or burn input for correctness on + /// - token to be locked or burned + /// - RMN curse status + /// - allowlist status + /// - if the sender is a valid onRamp + /// - rate limit status + /// @param lockOrBurnIn The input to validate. + /// @dev This function should always be called before executing a lock or burn. Not doing so would allow + /// for various exploits. + function _validateLockOrBurn( + Pool.LockOrBurnInV1 memory lockOrBurnIn + ) internal { + if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); + _checkAllowList(lockOrBurnIn.originalSender); + + _onlyOnRamp(lockOrBurnIn.remoteChainSelector); + _consumeOutboundRateLimit(lockOrBurnIn.localToken, lockOrBurnIn.remoteChainSelector, lockOrBurnIn.amount); + } + + /// @notice Validates the release or mint input for correctness on + /// - token to be released or minted + /// - RMN curse status + /// - if the sender is a valid offRamp + /// - if the source pool is valid + /// - rate limit status + /// @param releaseOrMintIn The input to validate. + /// @dev This function should always be called before executing a lock or burn. Not doing so would allow + /// for various exploits. + function _validateReleaseOrMint( + Pool.ReleaseOrMintInV1 memory releaseOrMintIn + ) internal { + if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); + _onlyOffRamp(releaseOrMintIn.remoteChainSelector); + + // Validates that the source pool address is configured on this pool. + bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.localToken, releaseOrMintIn.remoteChainSelector); + if ( + configuredRemotePool.length == 0 + || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) + ) { + revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); + } + _consumeInboundRateLimit(releaseOrMintIn.localToken, releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); + } + + // ================================================================ + // │ Chain permissions │ + // ================================================================ + + /// @notice Gets the pool address on the remote chain. + /// @param remoteChainSelector Remote chain selector. + /// @dev To support non-evm chains, this value is encoded into bytes + function getRemotePool(address token, uint64 remoteChainSelector) public view returns (bytes memory) { + return s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress; + } + + /// @notice Gets the token address on the remote chain. + /// @param remoteChainSelector Remote chain selector. + /// @dev To support non-evm chains, this value is encoded into bytes + function getRemoteToken(address token, uint64 remoteChainSelector) public view returns (bytes memory) { + return s_remoteChainConfigs[token][remoteChainSelector].remoteTokenAddress; + } + + /// @notice Sets the remote pool address for a given chain selector. + /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. + /// @param remotePoolAddress The address of the remote pool. + function setRemotePool( + address token, + uint64 remoteChainSelector, + bytes calldata remotePoolAddress + ) external onlyOwner { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + + bytes memory prevAddress = s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress; + s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress = remotePoolAddress; + + emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); + } + + /// @inheritdoc IPoolV1 + function isSupportedChain( + uint64 remoteChainSelector + ) public view returns (bool) { + return s_remoteChainSelectors.contains(remoteChainSelector); + } + + /// @notice Get list of allowed chains + /// @return list of chains. + function getSupportedChains() public view returns (uint64[] memory) { + uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); + uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); + for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { + chainSelectors[i] = uint64(uint256ChainSelectors[i]); + } + + return chainSelectors; + } + + /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains + /// need to be allowed on the Router to interact with this pool. + /// @dev Only callable by the owner + /// @param chains A list of chains and their new permission status & rate limits. Rate limits + /// are only used when the chain is being added through `allowed` being true. + function applyChainUpdates(address token, ChainUpdate[] calldata chains) external virtual onlyOwner { + for (uint256 i = 0; i < chains.length; ++i) { + ChainUpdate memory update = chains[i]; + RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); + RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); + + if (update.allowed) { + // If the chain already exists, revert + if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { + revert ChainAlreadyExists(update.remoteChainSelector); + } + + if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { + revert ZeroAddressNotAllowed(); + } + + s_remoteChainConfigs[token][update.remoteChainSelector] = RemoteChainConfig({ + outboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.outboundRateLimiterConfig.rate, + capacity: update.outboundRateLimiterConfig.capacity, + tokens: update.outboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.outboundRateLimiterConfig.isEnabled + }), + inboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.inboundRateLimiterConfig.rate, + capacity: update.inboundRateLimiterConfig.capacity, + tokens: update.inboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.inboundRateLimiterConfig.isEnabled + }), + remotePoolAddress: update.remotePoolAddress, + remoteTokenAddress: update.remoteTokenAddress + }); + + emit ChainAdded( + update.remoteChainSelector, + update.remoteTokenAddress, + update.outboundRateLimiterConfig, + update.inboundRateLimiterConfig + ); + } else { + // If the chain doesn't exist, revert + if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { + revert NonExistentChain(update.remoteChainSelector); + } + + delete s_remoteChainConfigs[token][update.remoteChainSelector]; + + emit ChainRemoved(update.remoteChainSelector); + } + } + } + + // ================================================================ + // │ Rate limiting │ + // ================================================================ + + /// @notice Consumes outbound rate limiting capacity in this pool + function _consumeOutboundRateLimit(address token, uint64 remoteChainSelector, uint256 amount) internal { + s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._consume(amount, token); + } + + /// @notice Consumes inbound rate limiting capacity in this pool + function _consumeInboundRateLimit(address token, uint64 remoteChainSelector, uint256 amount) internal { + s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._consume(amount, token); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentOutboundRateLimiterState( + address token, + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function getCurrentInboundRateLimiterState( + address token, + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { + return s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); + } + + /// @notice Sets the chain rate limiter config. + /// @param remoteChainSelector The remote chain selector for which the rate limits apply. + /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. + /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. + function _setChainRateLimiterConfig( + address token, + uint64 remoteChainSelector, + RateLimiter.Config memory outboundConfig, + RateLimiter.Config memory inboundConfig + ) internal { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + RateLimiter._validateTokenBucketConfig(outboundConfig, false); + s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._setTokenBucketConfig(outboundConfig); + RateLimiter._validateTokenBucketConfig(inboundConfig, false); + s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._setTokenBucketConfig(inboundConfig); + emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned onRamp for the given chain on the Router. + function _onlyOnRamp( + uint64 remoteChainSelector + ) internal view { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); + } + + /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender + /// is a permissioned offRamp for the given chain on the Router. + function _onlyOffRamp( + uint64 remoteChainSelector + ) internal view { + if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); + if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + function _checkAllowList( + address sender + ) internal view { + if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); + } + + /// @notice Gets whether the allowList functionality is enabled. + /// @return true is enabled, false if not. + function getAllowListEnabled() external view returns (bool) { + return i_allowlistEnabled; + } + + /// @notice Gets the allowed addresses. + /// @return The allowed addresses. + function getAllowList() external view returns (address[] memory) { + return s_allowList.values(); + } + + /// @notice Apply updates to the allow list. + /// @param removes The addresses to be removed. + /// @param adds The addresses to be added. + /// @dev allowListing will be removed before public launch + function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { + _applyAllowListUpdates(removes, adds); + } + + /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. + function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { + if (!i_allowlistEnabled) revert AllowListNotEnabled(); + + for (uint256 i = 0; i < removes.length; ++i) { + address toRemove = removes[i]; + if (s_allowList.remove(toRemove)) { + emit AllowListRemove(toRemove); + } + } + for (uint256 i = 0; i < adds.length; ++i) { + address toAdd = adds[i]; + if (toAdd == address(0)) { + continue; + } + if (s_allowList.add(toAdd)) { + emit AllowListAdd(toAdd); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol new file mode 100644 index 0000000..40f7ccb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; +import {IgnoreContractSize} from "./IgnoreContractSize.sol"; + +contract OffRampHelper is OffRamp, IgnoreContractSize { + using EnumerableSet for EnumerableSet.UintSet; + + mapping(uint64 sourceChainSelector => uint256 overrideTimestamp) private s_sourceChainVerificationOverride; + + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + SourceChainConfigArgs[] memory sourceChainConfigs + ) OffRamp(staticConfig, dynamicConfig, sourceChainConfigs) {} + + function setExecutionStateHelper( + uint64 sourceChainSelector, + uint64 sequenceNumber, + Internal.MessageExecutionState state + ) public { + _setExecutionState(sourceChainSelector, sequenceNumber, state); + } + + function getExecutionStateBitMap(uint64 sourceChainSelector, uint64 bitmapIndex) public view returns (uint256) { + return s_executionStates[sourceChainSelector][bitmapIndex]; + } + + function releaseOrMintSingleToken( + Internal.Any2EVMTokenTransfer calldata sourceTokenAmount, + bytes calldata originalSender, + address receiver, + uint64 sourceChainSelector, + bytes calldata offchainTokenData + ) external returns (Client.EVMTokenAmount memory) { + return + _releaseOrMintSingleToken(sourceTokenAmount, originalSender, receiver, sourceChainSelector, offchainTokenData); + } + + function releaseOrMintTokens( + Internal.Any2EVMTokenTransfer[] calldata sourceTokenAmounts, + bytes calldata originalSender, + address receiver, + uint64 sourceChainSelector, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) external returns (Client.EVMTokenAmount[] memory) { + return _releaseOrMintTokens( + sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData, tokenGasOverrides + ); + } + + function trialExecute( + Internal.Any2EVMRampMessage memory message, + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides + ) external returns (Internal.MessageExecutionState, bytes memory) { + return _trialExecute(message, offchainTokenData, tokenGasOverrides); + } + + function executeSingleReport( + Internal.ExecutionReport memory rep, + GasLimitOverride[] memory manualExecGasExecOverrides + ) external { + _executeSingleReport(rep, manualExecGasExecOverrides); + } + + function batchExecute( + Internal.ExecutionReport[] memory reports, + GasLimitOverride[][] memory manualExecGasLimits + ) external { + _batchExecute(reports, manualExecGasLimits); + } + + function verify( + uint64 sourceChainSelector, + bytes32[] memory hashedLeaves, + bytes32[] memory proofs, + uint256 proofFlagBits + ) external view returns (uint256 timestamp) { + return super._verify(sourceChainSelector, hashedLeaves, proofs, proofFlagBits); + } + + function _verify( + uint64 sourceChainSelector, + bytes32[] memory hashedLeaves, + bytes32[] memory proofs, + uint256 proofFlagBits + ) internal view override returns (uint256 timestamp) { + uint256 overrideTimestamp = s_sourceChainVerificationOverride[sourceChainSelector]; + + return overrideTimestamp == 0 + ? super._verify(sourceChainSelector, hashedLeaves, proofs, proofFlagBits) + : overrideTimestamp; + } + + /// @dev Test helper to override _verify result for easier exec testing + function setVerifyOverrideResult(uint64 sourceChainSelector, uint256 overrideTimestamp) external { + s_sourceChainVerificationOverride[sourceChainSelector] = overrideTimestamp; + } + + /// @dev Test helper to directly set a root's timestamp + function setRootTimestamp(uint64 sourceChainSelector, bytes32 root, uint256 timestamp) external { + s_roots[sourceChainSelector][root] = timestamp; + } + + function getSourceChainSelectors() external view returns (uint256[] memory chainSelectors) { + return s_sourceChainSelectors.values(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol new file mode 100644 index 0000000..d315a58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {IgnoreContractSize} from "./IgnoreContractSize.sol"; + +contract OnRampHelper is OnRamp, IgnoreContractSize { + constructor( + StaticConfig memory staticConfig, + DynamicConfig memory dynamicConfig, + DestChainConfigArgs[] memory destChainConfigArgs + ) OnRamp(staticConfig, dynamicConfig, destChainConfigArgs) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol new file mode 100644 index 0000000..6cd1c18 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +contract RateLimiterHelper { + using RateLimiter for RateLimiter.TokenBucket; + + RateLimiter.TokenBucket internal s_rateLimiter; + + constructor( + RateLimiter.Config memory config + ) { + s_rateLimiter = RateLimiter.TokenBucket({ + rate: config.rate, + capacity: config.capacity, + tokens: config.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: config.isEnabled + }); + } + + function consume(uint256 requestTokens, address tokenAddress) external { + s_rateLimiter._consume(requestTokens, tokenAddress); + } + + function currentTokenBucketState() external view returns (RateLimiter.TokenBucket memory) { + return s_rateLimiter._currentTokenBucketState(); + } + + function setTokenBucketConfig( + RateLimiter.Config memory config + ) external { + s_rateLimiter._setTokenBucketConfig(config); + } + + function getRateLimiter() external view returns (RateLimiter.TokenBucket memory) { + return s_rateLimiter; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol new file mode 100644 index 0000000..41e4a95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; + +contract ReportCodec { + event ExecuteReportDecoded(Internal.ExecutionReport[] report); + event CommitReportDecoded(OffRamp.CommitReport report); + + function decodeExecuteReport( + bytes memory report + ) public pure returns (Internal.ExecutionReport[] memory) { + return abi.decode(report, (Internal.ExecutionReport[])); + } + + function decodeCommitReport( + bytes memory report + ) public pure returns (OffRamp.CommitReport memory) { + return abi.decode(report, (OffRamp.CommitReport)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol new file mode 100644 index 0000000..75f6b1b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../libraries/Pool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract TokenPoolHelper is TokenPool { + constructor( + IERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) TokenPool(token, allowlist, rmnProxy, router) {} + + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external view override returns (Pool.LockOrBurnOutV1 memory) { + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + function onlyOnRampModifier( + uint64 remoteChainSelector + ) external view { + _onlyOnRamp(remoteChainSelector); + } + + function onlyOffRampModifier( + uint64 remoteChainSelector + ) external view { + _onlyOffRamp(remoteChainSelector); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol new file mode 100644 index 0000000..d1baa22 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +contract USDCReaderTester { + event MessageSent(bytes); + + // emitMessageSent reflects the logic from Circle's MessageTransmitter emitting MeseageSent(bytes) events + // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L41 + // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L365 + function emitMessageSent( + uint32 version, + uint32 sourceDomain, + uint32 destinationDomain, + bytes32 recipient, + bytes32 destinationCaller, + bytes32 sender, + uint64 nonce, + bytes calldata messageBody + ) external { + bytes memory _message = + _formatMessage(version, sourceDomain, destinationDomain, nonce, sender, recipient, destinationCaller, messageBody); + emit MessageSent(_message); + } + + /** + * @notice Returns formatted (packed) message with provided fields + * It's a copy paste of the Message._formatMessage() call in MessageTransmitter.sol + * https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/Message.sol#L54C1-L65C9 + * Check the chainlink-ccip repo for the offchain implementation of matching this format + * @param _msgVersion the version of the message format + * @param _msgSourceDomain Domain of home chain + * @param _msgDestinationDomain Domain of destination chain + * @param _msgNonce Destination-specific nonce + * @param _msgSender Address of sender on source chain as bytes32 + * @param _msgRecipient Address of recipient on destination chain as bytes32 + * @param _msgDestinationCaller Address of caller on destination chain as bytes32 + * @param _msgRawBody Raw bytes of message body + * @return Formatted message + * + */ + function _formatMessage( + uint32 _msgVersion, + uint32 _msgSourceDomain, + uint32 _msgDestinationDomain, + uint64 _msgNonce, + bytes32 _msgSender, + bytes32 _msgRecipient, + bytes32 _msgDestinationCaller, + bytes memory _msgRawBody + ) internal pure returns (bytes memory) { + return abi.encodePacked( + _msgVersion, + _msgSourceDomain, + _msgDestinationDomain, + _msgNonce, + _msgSender, + _msgRecipient, + _msgDestinationCaller, + _msgRawBody + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol new file mode 100644 index 0000000..7a34005 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; +import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; + +contract USDCTokenPoolHelper is USDCTokenPool { + constructor( + ITokenMessenger tokenMessenger, + IBurnMintERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) {} + + function validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) external view { + return _validateMessage(usdcMessage, sourceTokenData); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol new file mode 100644 index 0000000..d4102da --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; +import {Client} from "../../../libraries/Client.sol"; + +contract ConformingReceiver is CCIPReceiver { + event MessageReceived(); + + constructor(address router, address feeToken) CCIPReceiver(router) {} + + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal virtual override { + emit MessageReceived(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol new file mode 100644 index 0000000..b40b2c3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; +import {Client} from "../../../libraries/Client.sol"; + +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 { + error ReceiveRevert(); + error CustomError(bytes err); + + event ValueReceived(uint256 amount); + event MessageReceived(); + + address private s_manager; + bool public s_toRevert; + bytes private s_err; + + constructor( + bool toRevert + ) { + s_manager = msg.sender; + s_toRevert = toRevert; + } + + function setRevert( + bool toRevert + ) external { + s_toRevert = toRevert; + } + + function setErr( + bytes memory err + ) external { + s_err = err; + } + + /// @notice IERC165 supports an interfaceId + /// @param interfaceId The interfaceId to check + /// @return true if the interfaceId is supported + function supportsInterface( + bytes4 interfaceId + ) public pure override returns (bool) { + return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } + + function ccipReceive( + Client.Any2EVMMessage calldata + ) external override { + if (s_toRevert) { + revert CustomError(s_err); + } + emit MessageReceived(); + } + + // solhint-disable-next-line no-complex-fallback + receive() external payable { + if (s_toRevert) { + revert ReceiveRevert(); + } + + emit ValueReceived(msg.value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol new file mode 100644 index 0000000..07e5ac8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; + +import {Client} from "../../../libraries/Client.sol"; + +contract MaybeRevertMessageReceiverNo165 is IAny2EVMMessageReceiver { + address private s_manager; + bool public s_toRevert; + + event MessageReceived(); + + constructor( + bool toRevert + ) { + s_manager = msg.sender; + s_toRevert = toRevert; + } + + function setRevert( + bool toRevert + ) external { + s_toRevert = toRevert; + } + + function ccipReceive( + Client.Any2EVMMessage calldata + ) external override { + if (s_toRevert) { + // solhint-disable-next-line reason-string,gas-custom-errors + revert(); + } + emit MessageReceived(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol new file mode 100644 index 0000000..b8aeeb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {OffRamp} from "../../../offRamp/OffRamp.sol"; + +contract ReentrancyAbuser is CCIPReceiver { + event ReentrancySucceeded(); + + uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 144_000; + + bool internal s_ReentrancyDone = false; + Internal.ExecutionReport internal s_payload; + OffRamp internal s_offRamp; + + constructor(address router, OffRamp offRamp) CCIPReceiver(router) { + s_offRamp = offRamp; + } + + function setPayload( + Internal.ExecutionReport calldata payload + ) public { + s_payload = payload; + } + + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal override { + // Use original message gas limits in manual execution + OffRamp.GasLimitOverride[][] memory gasOverrides = _getGasLimitsFromMessages(s_payload.messages); + + if (!s_ReentrancyDone) { + // Could do more rounds but a PoC one is enough + s_ReentrancyDone = true; + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); + reports[0] = s_payload; + + s_offRamp.manuallyExecute(reports, gasOverrides); + } else { + emit ReentrancySucceeded(); + } + } + + function _getGasLimitsFromMessages( + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (OffRamp.GasLimitOverride[][] memory) { + OffRamp.GasLimitOverride[] memory gasLimitOverrides = new OffRamp.GasLimitOverride[](messages.length); + for (uint256 i = 0; i < messages.length; ++i) { + gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit; + gasLimitOverrides[i].tokenGasOverrides = new uint32[](messages[i].tokenAmounts.length); + + for (uint256 j = 0; j < messages[i].tokenAmounts.length; ++j) { + gasLimitOverrides[i].tokenGasOverrides[j] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; + } + } + + OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); + gasOverrides[0] = gasLimitOverrides; + return gasOverrides; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol new file mode 100644 index 0000000..d3d0fd3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.19; + +import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {OffRamp} from "../../../offRamp/OffRamp.sol"; + +contract ReentrancyAbuserMultiRamp is CCIPReceiver { + event ReentrancySucceeded(); + + bool internal s_ReentrancyDone = false; + Internal.ExecutionReport internal s_payload; + OffRamp internal s_offRamp; + + constructor(address router, OffRamp offRamp) CCIPReceiver(router) { + s_offRamp = offRamp; + } + + function setPayload( + Internal.ExecutionReport calldata payload + ) public { + s_payload = payload; + } + + function _ccipReceive( + Client.Any2EVMMessage memory + ) internal override { + // Use original message gas limits in manual execution + uint256 numMsgs = s_payload.messages.length; + OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); + gasOverrides[0] = new OffRamp.GasLimitOverride[](numMsgs); + for (uint256 i = 0; i < numMsgs; ++i) { + gasOverrides[0][i].receiverExecutionGasLimit = 0; + gasOverrides[0][i].tokenGasOverrides = new uint32[](s_payload.messages[i].tokenAmounts.length); + } + + Internal.ExecutionReport[] memory batchPayload = new Internal.ExecutionReport[](1); + batchPayload[0] = s_payload; + + if (!s_ReentrancyDone) { + // Could do more rounds but a PoC one is enough + s_ReentrancyDone = true; + s_offRamp.manuallyExecute(batchPayload, gasOverrides); + } else { + emit ReentrancySucceeded(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol new file mode 100644 index 0000000..e2fc981 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; +import {MerkleHelper} from "../helpers/MerkleHelper.sol"; +import {Test} from "forge-std/Test.sol"; + +contract MerkleMultiProofTest is Test { + // This must match the spec + function test_SpecSync_gas() public pure { + bytes32 expectedRoot = 0xd4f0f3c40a4d583d98c17d89e550b1143fe4d3d759f25ccc63131c90b183928e; + + bytes32[] memory leaves = new bytes32[](10); + leaves[0] = 0xa20c0244af79697a4ef4e2378c9d5d14cbd49ddab3427b12594c7cfa67a7f240; + leaves[1] = 0x3de96afb24ce2ac45a5595aa13d1a5163ae0b3c94cef6b2dc306b5966f32dfa5; + leaves[2] = 0xacadf7b4d13cd57c5d25f1d27be39b656347fe8f8e0de8db9c76d979dff57736; + leaves[3] = 0xc21c26a709802fe1ae52a9cd8ad94d15bf142ded26314339cd87a13e5b468165; + leaves[4] = 0x55f6df03562738c9a6437cd9ad221c52b76906a175ae96188cff60e0a2a59933; + leaves[5] = 0x2dbbe66452e43fec839dc65d5945aad6433d410c65863eaf1d876e1e0b06343c; + leaves[6] = 0x8beab00297b94bf079fcd5893b0a33ebf6b0ce862cd06be07c87d3c63e1c4acf; + leaves[7] = 0xcabdd3ad25daeb1e0541042f2ea4cd177f54e67aa4a2c697acd4bb682e94de59; + leaves[8] = 0x7e01d497203685e99e34df33d55465c66b2253fa1630ee2fe5c4997968e4a6fa; + leaves[9] = 0x1a03d013f1e2fa9cc04f89c7528ac3216e3e096a1185d7247304e97c59f9661f; + + bytes32[] memory proofs = new bytes32[](33); + proofs[0] = 0xde96f24fcf9ddd20c803dc9c5fba7c478a5598a08a0faa5f032c65823b8e26a3; + proofs[1] = 0xe1303cffc3958a6b93e2dc04caf21f200ff5aa5be090c5013f37804b91488bc2; + proofs[2] = 0x90d80c76bccb44a91f4e16604976163aaa39e9a1588b0b24b33a61f1d4ba7bb5; + proofs[3] = 0x012a299b25539d513c8677ecf37968774e9e4b045e79737f48defd350224cdfd; + proofs[4] = 0x420a36c5a73f87d8fb98e70c48d0d6f9dd83f50b7b91416a6f5f91fac4db800f; + proofs[5] = 0x5857d8d1b56abcd7f863cedd3c3f8677256f54d675be61f05efa45d6495fc30a; + proofs[6] = 0xbf176d20166fdeb72593ff97efec1ce6244af41ca46cf0bc902d19d50c446f7b; + proofs[7] = 0xa9221608e4380250a1815fb308632bce99f611a673d2e17fc617123fdc6afcd2; + proofs[8] = 0xbd14f3366c73186314f182027217d0f70eba55817561de9e9a1f2c78bf5cbead; + proofs[9] = 0x2f9aa48c0c9f82aaac65d7a9374a52d9dc138ed100a5809ede57e70697f48b56; + proofs[10] = 0x2ae60afa54271cb421c12e4441c2dac0a25f25c9433a6d07cb32419e993fe344; + proofs[11] = 0xc765c091680f0434b74c44507b932e5c80f6e995a975a275e5b130af1de1064c; + proofs[12] = 0x59d2d6e0c4a5d07b169dbcdfa39dad7aea7b7783a814399f4f44c4a36b6336d3; + proofs[13] = 0xdd14d1387d10740187d71ad9500475399559c0922dbe2576882e61f1edd84692; + proofs[14] = 0x5412b8395509935406811ab3da43ab80be7acd8ffb5f398ab70f056ff3740f46; + proofs[15] = 0xeadab258ae7d779ce5f10fbb1bb0273116b8eccbf738ed878db570de78bed1e4; + proofs[16] = 0x6133aa40e6db75373b7cfc79e6f8b8ce80e441e6c1f98b85a593464dda3cf9c0; + proofs[17] = 0x5418948467112660639b932af9b1b212e40d71b24326b4606679d168a765af4f; + proofs[18] = 0x44f618505355c7e4e7c0f81d6bb15d2ec9cf9b366f9e1dc37db52745486e6b0f; + proofs[19] = 0xa410ee174a66a4d64f3c000b93efe15b5b1f3e39e962af2580fcd30bce07d039; + proofs[20] = 0x09c3eb05ac9552022a45c00d01a47cd56f95f94afdd4402299dba1291a17f976; + proofs[21] = 0x0e780f6acd081b07320a55208fa3e1d884e2e95cb13d1c98c74b7e853372c813; + proofs[22] = 0x2b60e8c21f78ef22fa4297f28f1d8c747181edfc465121b39c16be97d4fb8a04; + proofs[23] = 0xf24da95060a8598c06e9dfb3926e1a8c8bd8ec2c65be10e69323442840724888; + proofs[24] = 0x7e220fc095bcd2b0f5ef134d9620d89f6d7a1e8719ce8893bb9aff15e847578f; + proofs[25] = 0xcfe9e475c4bd32f1e36b2cc65a959c403c59979ff914fb629a64385b0c680a71; + proofs[26] = 0x25237fb8d1bfdc01ca5363ec3166a2b40789e38d5adcc8627801da683d2e1d76; + proofs[27] = 0x42647949fed0250139c01212d739d8c83d2852589ebc892d3490ae52e411432c; + proofs[28] = 0x34397a30930e6dd4fb5af48084afc5cfbe02c18dd9544b3faff4e2e90bf00cb9; + proofs[29] = 0xa028f33226adc3d1cb72b19eb6808dab9190b25066a45cacb5dfe5d640e57cf2; + proofs[30] = 0x7cff66ba47a05f932d06d168c294266dcb0d3943a4f2a4a75c860b9fd6e53092; + proofs[31] = 0x5ca1b32f1dbfadd83205882be5eb76f34c49e834726f5239905a0e70d0a5e0eb; + proofs[32] = 0x1b4b087a89e4eca6cdd237210932559dc8fd167d5f4f2d9acb13264e1e305479; + + uint256 flagsUint256 = 0x2f3c0000000; + + bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, flagsUint256); + + assertEq(expectedRoot, root); + } + + function test_Fuzz_MerkleRoot2(bytes32 left, bytes32 right) public pure { + bytes32[] memory leaves = new bytes32[](2); + leaves[0] = left; + leaves[1] = right; + bytes32[] memory proofs = new bytes32[](0); + + bytes32 expectedRoot = MerkleHelper.hashPair(left, right); + + bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, 2 ** 2 - 1); + + assertEq(root, expectedRoot); + } + + function test_MerkleRoot256() public pure { + bytes32[] memory leaves = new bytes32[](256); + for (uint256 i = 0; i < leaves.length; ++i) { + leaves[i] = keccak256("a"); + } + bytes32[] memory proofs = new bytes32[](0); + + bytes32 expectedRoot = MerkleHelper.getMerkleRoot(leaves); + + bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, 2 ** 256 - 1); + + assertEq(root, expectedRoot); + } + + function test_Fuzz_MerkleMulti1of4(bytes32 leaf1, bytes32 proof1, bytes32 proof2) public pure { + bytes32[] memory leaves = new bytes32[](1); + leaves[0] = leaf1; + bytes32[] memory proofs = new bytes32[](2); + proofs[0] = proof1; + proofs[1] = proof2; + + // Proof flag = false + bytes32 result = MerkleHelper.hashPair(leaves[0], proofs[0]); + // Proof flag = false + result = MerkleHelper.hashPair(result, proofs[1]); + + assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 0), result); + } + + function test_Fuzz_MerkleMulti2of4(bytes32 leaf1, bytes32 leaf2, bytes32 proof1, bytes32 proof2) public pure { + bytes32[] memory leaves = new bytes32[](2); + leaves[0] = leaf1; + leaves[1] = leaf2; + bytes32[] memory proofs = new bytes32[](2); + proofs[0] = proof1; + proofs[1] = proof2; + + // Proof flag = false + bytes32 result1 = MerkleHelper.hashPair(leaves[0], proofs[0]); + // Proof flag = false + bytes32 result2 = MerkleHelper.hashPair(leaves[1], proofs[1]); + // Proof flag = true + bytes32 finalResult = MerkleHelper.hashPair(result1, result2); + + assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 4), finalResult); + } + + function test_Fuzz_MerkleMulti3of4(bytes32 leaf1, bytes32 leaf2, bytes32 leaf3, bytes32 proof) public pure { + bytes32[] memory leaves = new bytes32[](3); + leaves[0] = leaf1; + leaves[1] = leaf2; + leaves[2] = leaf3; + bytes32[] memory proofs = new bytes32[](1); + proofs[0] = proof; + + // Proof flag = true + bytes32 result1 = MerkleHelper.hashPair(leaves[0], leaves[1]); + // Proof flag = false + bytes32 result2 = MerkleHelper.hashPair(leaves[2], proofs[0]); + // Proof flag = true + bytes32 finalResult = MerkleHelper.hashPair(result1, result2); + + assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 5), finalResult); + } + + function test_Fuzz_MerkleMulti4of4(bytes32 leaf1, bytes32 leaf2, bytes32 leaf3, bytes32 leaf4) public pure { + bytes32[] memory leaves = new bytes32[](4); + leaves[0] = leaf1; + leaves[1] = leaf2; + leaves[2] = leaf3; + leaves[3] = leaf4; + bytes32[] memory proofs = new bytes32[](0); + + // Proof flag = true + bytes32 result1 = MerkleHelper.hashPair(leaves[0], leaves[1]); + // Proof flag = true + bytes32 result2 = MerkleHelper.hashPair(leaves[2], leaves[3]); + // Proof flag = true + bytes32 finalResult = MerkleHelper.hashPair(result1, result2); + + assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 7), finalResult); + } + + function test_MerkleRootSingleLeaf_Success() public pure { + bytes32[] memory leaves = new bytes32[](1); + leaves[0] = "root"; + bytes32[] memory proofs = new bytes32[](0); + assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 0), leaves[0]); + } + + function test_EmptyLeaf_Revert() public { + bytes32[] memory leaves = new bytes32[](0); + bytes32[] memory proofs = new bytes32[](0); + + vm.expectRevert(abi.encodeWithSelector(MerkleMultiProof.LeavesCannotBeEmpty.selector)); + MerkleMultiProof.merkleRoot(leaves, proofs, 0); + } + + function test_CVE_2023_34459() public { + bytes32[] memory leaves = new bytes32[](2); + // leaves[0] stays uninitialized, i.e., 0x000...0 + leaves[1] = "leaf"; + + bytes32[] memory proof = new bytes32[](2); + proof[0] = leaves[1]; + proof[1] = "will never be used"; + + bytes32[] memory malicious = new bytes32[](2); + malicious[0] = "malicious leaf"; + malicious[1] = "another malicious leaf"; + + vm.expectRevert(abi.encodeWithSelector(MerkleMultiProof.InvalidProof.selector)); + MerkleMultiProof.merkleRoot(malicious, proof, 3); + // Note, that without the revert the above computed root + // would equal MerkleHelper.hashPair(leaves[0], leaves[1]). + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol new file mode 100644 index 0000000..da6a6f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {RateLimiterHelper} from "../helpers/RateLimiterHelper.sol"; +import {Test} from "forge-std/Test.sol"; + +contract RateLimiterSetup is Test { + RateLimiterHelper internal s_helper; + RateLimiter.Config internal s_config; + + uint256 internal constant BLOCK_TIME = 1234567890; + + function setUp() public virtual { + s_config = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); + s_helper = new RateLimiterHelper(s_config); + } +} + +contract RateLimiter_constructor is RateLimiterSetup { + function test_Constructor_Success() public view { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } +} + +contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { + function test_SetRateLimiterConfig_Success() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + + s_config = + RateLimiter.Config({isEnabled: true, rate: uint128(rateLimiter.rate * 2), capacity: rateLimiter.capacity * 8}); + + vm.expectEmit(); + emit RateLimiter.ConfigChanged(s_config); + + s_helper.setTokenBucketConfig(s_config); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity / 8, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } +} + +contract RateLimiter_currentTokenBucketState is RateLimiterSetup { + function test_CurrentTokenBucketState_Success() public { + RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + s_config = RateLimiter.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); + + s_helper.setTokenBucketConfig(s_config); + + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity / 8, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + + function test_Refill_Success() public { + RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + s_config = RateLimiter.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); + + s_helper.setTokenBucketConfig(s_config); + + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity / 8, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + uint256 warpTime = 4; + vm.warp(BLOCK_TIME + warpTime); + + bucket = s_helper.currentTokenBucketState(); + + assertEq(s_config.capacity / 8 + warpTime * s_config.rate, bucket.tokens); + + vm.warp(BLOCK_TIME + warpTime * 100); + + // Bucket overflow + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.capacity, bucket.tokens); + } +} + +contract RateLimiter_consume is RateLimiterSetup { + address internal s_token = address(100); + + function test_ConsumeAggregateValue_Success() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + + uint256 requestTokens = 50; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(requestTokens); + + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } + + function test_ConsumeTokens_Success() public { + uint256 requestTokens = 50; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(requestTokens); + + s_helper.consume(requestTokens, s_token); + } + + function test_Refill_Success() public { + uint256 requestTokens = 50; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(requestTokens); + + s_helper.consume(requestTokens, address(0)); + + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + + uint256 warpTime = 4; + vm.warp(BLOCK_TIME + warpTime); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(requestTokens); + + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens * 2 + warpTime * s_config.rate, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); + } + + function test_ConsumeUnlimited_Success() public { + s_helper.consume(0, address(0)); + + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + + RateLimiter.Config memory disableConfig = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); + + s_helper.setTokenBucketConfig(disableConfig); + + uint256 requestTokens = 50; + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(disableConfig.capacity, rateLimiter.tokens); + assertEq(disableConfig.isEnabled, rateLimiter.isEnabled); + + s_helper.setTokenBucketConfig(s_config); + + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 10, 0)); + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(0, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + } + + // Reverts + + function test_AggregateValueMaxCapacityExceeded_Revert() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiter.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1 + ) + ); + s_helper.consume(rateLimiter.capacity + 1, address(0)); + } + + function test_TokenMaxCapacityExceeded_Revert() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiter.TokenMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1, s_token + ) + ); + s_helper.consume(rateLimiter.capacity + 1, s_token); + } + + function test_ConsumingMoreThanUint128_Revert() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 request = uint256(type(uint128).max) + 1; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, request) + ); + s_helper.consume(request, address(0)); + } + + function test_AggregateValueRateLimitReached_Revert() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 overLimit = 20; + uint256 requestTokens1 = rateLimiter.capacity / 2; + uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; + + uint256 waitInSeconds = overLimit / rateLimiter.rate; + + s_helper.consume(requestTokens1, address(0)); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiter.AggregateValueRateLimitReached.selector, waitInSeconds, rateLimiter.capacity - requestTokens1 + ) + ); + s_helper.consume(requestTokens2, address(0)); + } + + function test_TokenRateLimitReached_Revert() public { + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 overLimit = 20; + uint256 requestTokens1 = rateLimiter.capacity / 2; + uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; + + uint256 waitInSeconds = overLimit / rateLimiter.rate; + + s_helper.consume(requestTokens1, s_token); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiter.TokenRateLimitReached.selector, waitInSeconds, rateLimiter.capacity - requestTokens1, s_token + ) + ); + s_helper.consume(requestTokens2, s_token); + } + + function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { + uint256 initBlockTime = BLOCK_TIME + 10000; + vm.warp(initBlockTime); + + RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(rateLimiter.capacity); + + s_helper.consume(rateLimiter.capacity, address(0)); + + vm.warp(initBlockTime + 1); + + // Over rate limit by 1, force 1 second wait + uint256 overLimit = 1; + + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 1, rateLimiter.rate)); + s_helper.consume(rateLimiter.rate + overLimit, address(0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol new file mode 100644 index 0000000..c142cb8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2022, Circle Internet Financial Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; +import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWithRelay.sol"; + +// This contract mocks both the ITokenMessenger and IMessageTransmitter +// contracts involved with the Cross Chain Token Protocol. +// solhint-disable +contract MockE2EUSDCTokenMessenger is ITokenMessenger { + uint32 private immutable i_messageBodyVersion; + address private immutable i_transmitter; + + bytes32 public constant DESTINATION_TOKEN_MESSENGER = keccak256("i_destinationTokenMessenger"); + + uint64 public s_nonce; + + // Local Message Transmitter responsible for sending and receiving messages to/from remote domains + IMessageTransmitterWithRelay public immutable localMessageTransmitterWithRelay; + + constructor(uint32 version, address transmitter) { + i_messageBodyVersion = version; + s_nonce = 1; + i_transmitter = transmitter; + localMessageTransmitterWithRelay = IMessageTransmitterWithRelay(transmitter); + } + + // The mock function is based on the same function in https://github.com/circlefin/evm-cctp-contracts/blob/master/src/TokenMessenger.sol + function depositForBurnWithCaller( + uint256 amount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken, + bytes32 destinationCaller + ) external returns (uint64) { + IBurnMintERC20(burnToken).transferFrom(msg.sender, address(this), amount); + IBurnMintERC20(burnToken).burn(amount); + // Format message body + bytes memory _burnMessage = _formatMessage( + i_messageBodyVersion, + bytes32(uint256(uint160(burnToken))), + mintRecipient, + amount, + bytes32(uint256(uint160(msg.sender))) + ); + s_nonce = + _sendDepositForBurnMessage(destinationDomain, DESTINATION_TOKEN_MESSENGER, destinationCaller, _burnMessage); + emit DepositForBurn( + s_nonce, + burnToken, + amount, + msg.sender, + mintRecipient, + destinationDomain, + DESTINATION_TOKEN_MESSENGER, + destinationCaller + ); + return s_nonce; + } + + function messageBodyVersion() external view returns (uint32) { + return i_messageBodyVersion; + } + + function localMessageTransmitter() external view returns (address) { + return i_transmitter; + } + + /** + * @notice Sends a BurnMessage through the local message transmitter + * @dev calls local message transmitter's sendMessage() function if `_destinationCaller` == bytes32(0), + * or else calls sendMessageWithCaller(). + * @param _destinationDomain destination domain + * @param _destinationTokenMessenger address of registered TokenMessenger contract on destination domain, as bytes32 + * @param _destinationCaller caller on the destination domain, as bytes32. If `_destinationCaller` == bytes32(0), + * any address can call receiveMessage() on destination domain. + * @param _burnMessage formatted BurnMessage bytes (message body) + * @return nonce unique nonce reserved by message + */ + function _sendDepositForBurnMessage( + uint32 _destinationDomain, + bytes32 _destinationTokenMessenger, + bytes32 _destinationCaller, + bytes memory _burnMessage + ) internal returns (uint64 nonce) { + if (_destinationCaller == bytes32(0)) { + return localMessageTransmitterWithRelay.sendMessage(_destinationDomain, _destinationTokenMessenger, _burnMessage); + } else { + return localMessageTransmitterWithRelay.sendMessageWithCaller( + _destinationDomain, _destinationTokenMessenger, _destinationCaller, _burnMessage + ); + } + } + + /** + * @notice Formats Burn message + * @param _version The message body version + * @param _burnToken The burn token address on source domain as bytes32 + * @param _mintRecipient The mint recipient address as bytes32 + * @param _amount The burn amount + * @param _messageSender The message sender + * @return Burn formatted message. + */ + function _formatMessage( + uint32 _version, + bytes32 _burnToken, + bytes32 _mintRecipient, + uint256 _amount, + bytes32 _messageSender + ) internal pure returns (bytes memory) { + return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol new file mode 100644 index 0000000..4ed47b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022, Circle Internet Financial Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pragma solidity ^0.8.0; + +import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWithRelay.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; + +// solhint-disable +contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { + // Indicated whether the receiveMessage() call should succeed. + bool public s_shouldSucceed; + uint32 private immutable i_version; + uint32 private immutable i_localDomain; + // Next available nonce from this source domain + uint64 public nextAvailableNonce; + + BurnMintERC677 internal immutable i_token; + + /** + * @notice Emitted when a new message is dispatched + * @param message Raw bytes of message + */ + event MessageSent(bytes message); + + constructor(uint32 _version, uint32 _localDomain, address token) { + i_version = _version; + i_localDomain = _localDomain; + s_shouldSucceed = true; + + i_token = BurnMintERC677(token); + } + + /// @param message The original message on the source chain + /// * Message format: + /// * Field Bytes Type Index + /// * version 4 uint32 0 + /// * sourceDomain 4 uint32 4 + /// * destinationDomain 4 uint32 8 + /// * nonce 8 uint64 12 + /// * sender 32 bytes32 20 + /// * recipient 32 bytes32 52 + /// * destinationCaller 32 bytes32 84 + /// * messageBody dynamic bytes 116 + function receiveMessage(bytes calldata message, bytes calldata) external returns (bool success) { + // The receiver of the funds is the _mintRecipient in the following encoded format + // function _formatMessage( + // uint32 _version, 4 + // bytes32 _burnToken, 32 + // bytes32 _mintRecipient, 32, first 12 empty for EVM addresses + // uint256 _amount, + // bytes32 _messageSender + // ) internal pure returns (bytes memory) { + // return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + // } + address recipient = address(bytes20(message[116 + 36 + 12:116 + 36 + 12 + 20])); + // We always mint 1 token to not complicate the test. + i_token.mint(recipient, 1); + + return s_shouldSucceed; + } + + function setShouldSucceed( + bool shouldSucceed + ) external { + s_shouldSucceed = shouldSucceed; + } + + function version() external view returns (uint32) { + return i_version; + } + + function localDomain() external view returns (uint32) { + return i_localDomain; + } + + /** + * This is based on similar function in https://github.com/circlefin/evm-cctp-contracts/blob/master/src/MessageTransmitter.sol + * @notice Send the message to the destination domain and recipient + * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. + * @param destinationDomain Domain of destination chain + * @param recipient Address of message recipient on destination chain as bytes32 + * @param messageBody Raw bytes content of message + * @return nonce reserved by message + */ + function sendMessage( + uint32 destinationDomain, + bytes32 recipient, + bytes calldata messageBody + ) external returns (uint64) { + bytes32 _emptyDestinationCaller = bytes32(0); + uint64 _nonce = _reserveAndIncrementNonce(); + bytes32 _messageSender = bytes32(uint256(uint160((msg.sender)))); + + _sendMessage(destinationDomain, recipient, _emptyDestinationCaller, _messageSender, _nonce, messageBody); + + return _nonce; + } + + /** + * @notice Send the message to the destination domain and recipient, for a specified `destinationCaller` on the + * destination domain. + * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. + * WARNING: if the `destinationCaller` does not represent a valid address, then it will not be possible + * to broadcast the message on the destination domain. This is an advanced feature, and the standard + * sendMessage() should be preferred for use cases where a specific destination caller is not required. + * @param destinationDomain Domain of destination chain + * @param recipient Address of message recipient on destination domain as bytes32 + * @param destinationCaller caller on the destination domain, as bytes32 + * @param messageBody Raw bytes content of message + * @return nonce reserved by message + */ + function sendMessageWithCaller( + uint32 destinationDomain, + bytes32 recipient, + bytes32 destinationCaller, + bytes calldata messageBody + ) external returns (uint64) { + require(destinationCaller != bytes32(0), "Destination caller must be nonzero"); + + uint64 _nonce = _reserveAndIncrementNonce(); + bytes32 _messageSender = bytes32(uint256(uint160((msg.sender)))); + + _sendMessage(destinationDomain, recipient, destinationCaller, _messageSender, _nonce, messageBody); + + return _nonce; + } + + /** + * Reserve and increment next available nonce + * @return nonce reserved + */ + function _reserveAndIncrementNonce() internal returns (uint64) { + uint64 _nonceReserved = nextAvailableNonce; + nextAvailableNonce = nextAvailableNonce + 1; + return _nonceReserved; + } + + /** + * @notice Send the message to the destination domain and recipient. If `_destinationCaller` is not equal to bytes32(0), + * the message can only be received on the destination chain when called by `_destinationCaller`. + * @dev Format the message and emit `MessageSent` event with message information. + * @param _destinationDomain Domain of destination chain + * @param _recipient Address of message recipient on destination domain as bytes32 + * @param _destinationCaller caller on the destination domain, as bytes32 + * @param _sender message sender, as bytes32 + * @param _nonce nonce reserved for message + * @param _messageBody Raw bytes content of message + */ + function _sendMessage( + uint32 _destinationDomain, + bytes32 _recipient, + bytes32 _destinationCaller, + bytes32 _sender, + uint64 _nonce, + bytes calldata _messageBody + ) internal { + require(_recipient != bytes32(0), "Recipient must be nonzero"); + // serialize message + bytes memory _message = abi.encodePacked( + i_version, i_localDomain, _destinationDomain, _nonce, _sender, _recipient, _destinationCaller, _messageBody + ); + + // Emit MessageSent event + emit MessageSent(_message); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol new file mode 100644 index 0000000..435c669 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMN} from "../../interfaces/IRMN.sol"; + +/// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. +contract MockRMN is IRMN { + error CustomError(bytes err); + + bytes private s_isCursedRevert; + + bool private s_globalCursed; + mapping(bytes16 subject => bool cursed) private s_cursedBySubject; + mapping(address commitStore => mapping(bytes32 root => bool blessed)) private s_blessedByRoot; + + function setTaggedRootBlessed(IRMN.TaggedRoot calldata taggedRoot, bool blessed) external { + s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root] = blessed; + } + + function setGlobalCursed( + bool cursed + ) external { + s_globalCursed = cursed; + } + + function setChainCursed(uint64 chainSelector, bool cursed) external { + s_cursedBySubject[bytes16(uint128(chainSelector))] = cursed; + } + + /// @notice Setting a revert error with length of 0 will disable reverts + /// @dev Useful to test revert handling of ARMProxy + function setIsCursedRevert( + bytes calldata revertErr + ) external { + s_isCursedRevert = revertErr; + } + + // IRMN implementation follows + + function isCursed() external view returns (bool) { + if (s_isCursedRevert.length > 0) { + revert CustomError(s_isCursedRevert); + } + return s_globalCursed; + } + + function isCursed( + bytes16 subject + ) external view returns (bool) { + if (s_isCursedRevert.length > 0) { + revert CustomError(s_isCursedRevert); + } + return s_globalCursed || s_cursedBySubject[subject]; + } + + function isBlessed( + IRMN.TaggedRoot calldata taggedRoot + ) external view returns (bool) { + return s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol new file mode 100644 index 0000000..0abe4fd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; +import {IRouterClient} from "../../interfaces/IRouterClient.sol"; + +import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {ERC165Checker} from + "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; + +contract MockCCIPRouter is IRouter, IRouterClient { + using SafeERC20 for IERC20; + using ERC165Checker for address; + + error InvalidAddress(bytes encodedAddress); + error InvalidExtraArgsTag(); + error ReceiverError(bytes err); + + event MessageExecuted(bytes32 messageId, uint64 sourceChainSelector, address offRamp, bytes32 calldataHash); + event MsgExecuted(bool success, bytes retData, uint256 gasUsed); + + uint16 public constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + uint32 public constant DEFAULT_GAS_LIMIT = 200_000; + + uint256 internal s_mockFeeTokenAmount; //use setFee() to change to non-zero to test fees + + function routeMessage( + Client.Any2EVMMessage calldata message, + uint16 gasForCallExactCheck, + uint256 gasLimit, + address receiver + ) external returns (bool success, bytes memory retData, uint256 gasUsed) { + return _routeMessage(message, gasForCallExactCheck, gasLimit, receiver); + } + + function _routeMessage( + Client.Any2EVMMessage memory message, + uint16 gasForCallExactCheck, + uint256 gasLimit, + address receiver + ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { + // There are three cases in which we skip calling the receiver: + // 1. If the message data is empty AND the gas limit is 0. + // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract + // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the + // receiver without any gas, which would revert the transaction. + // 2. If the receiver is not a contract. + // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. + // + // The ordering of these checks is important, as the first check is the cheapest to execute. + if ( + (message.data.length == 0 && gasLimit == 0) || receiver.code.length == 0 + || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) + ) { + return (true, "", 0); + } + + bytes memory data = abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message); + + (success, retData, gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( + data, receiver, gasLimit, gasForCallExactCheck, Internal.MAX_RET_BYTES + ); + + // Event to assist testing, does not exist on real deployments + emit MsgExecuted(success, retData, gasUsed); + + // Real router event + emit MessageExecuted(message.messageId, message.sourceChainSelector, msg.sender, keccak256(data)); + return (success, retData, gasUsed); + } + + /// @notice Sends the tx locally to the receiver instead of on the destination chain. + /// @dev Ignores destinationChainSelector + /// @dev Returns a mock message ID, which is not calculated from the message contents in the + /// same way as the real message ID. + function ccipSend( + uint64 destinationChainSelector, + Client.EVM2AnyMessage calldata message + ) external payable returns (bytes32) { + if (message.receiver.length != 32) revert InvalidAddress(message.receiver); + uint256 decodedReceiver = abi.decode(message.receiver, (uint256)); + // We want to disallow sending to address(0) and to precompiles, which exist on address(1) through address(9). + if (decodedReceiver > type(uint160).max || decodedReceiver < 10) revert InvalidAddress(message.receiver); + + uint256 feeTokenAmount = getFee(destinationChainSelector, message); + if (message.feeToken == address(0)) { + if (msg.value < feeTokenAmount) revert InsufficientFeeTokenAmount(); + } else { + if (msg.value > 0) revert InvalidMsgValue(); + IERC20(message.feeToken).safeTransferFrom(msg.sender, address(this), feeTokenAmount); + } + + address receiver = address(uint160(decodedReceiver)); + uint256 gasLimit = _fromBytes(message.extraArgs).gasLimit; + bytes32 mockMsgId = keccak256(abi.encode(message)); + + Client.Any2EVMMessage memory executableMsg = Client.Any2EVMMessage({ + messageId: mockMsgId, + sourceChainSelector: 16015286601757825753, // Sepolia + sender: abi.encode(msg.sender), + data: message.data, + destTokenAmounts: message.tokenAmounts + }); + + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + IERC20(message.tokenAmounts[i].token).safeTransferFrom(msg.sender, receiver, message.tokenAmounts[i].amount); + } + + (bool success, bytes memory retData,) = _routeMessage(executableMsg, GAS_FOR_CALL_EXACT_CHECK, gasLimit, receiver); + + if (!success) revert ReceiverError(retData); + + return mockMsgId; + } + + function _fromBytes( + bytes calldata extraArgs + ) internal pure returns (Client.EVMExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return Client.EVMExtraArgsV1({gasLimit: DEFAULT_GAS_LIMIT}); + } + if (bytes4(extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV1)); + } + + /// @notice Always returns true to make sure this check can be performed on any chain. + function isChainSupported( + uint64 + ) external pure returns (bool supported) { + return true; + } + + /// @notice Returns an empty array. + function getSupportedTokens( + uint64 + ) external pure returns (address[] memory tokens) { + return new address[](0); + } + + /// @notice Returns 0 as the fee is not supported in this mock contract. + function getFee(uint64, Client.EVM2AnyMessage memory) public view returns (uint256) { + return s_mockFeeTokenAmount; + } + + /// @notice Sets the fees returned by getFee but is only checked when using native fee tokens + function setFee( + uint256 feeAmount + ) external { + s_mockFeeTokenAmount = feeAmount; + } + + /// @notice Always returns address(1234567890) + function getOnRamp( + uint64 /* destChainSelector */ + ) external pure returns (address onRampAddress) { + return address(1234567890); + } + + /// @notice Always returns true + function isOffRamp(uint64, /* sourceChainSelector */ address /* offRamp */ ) external pure returns (bool) { + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol new file mode 100644 index 0000000..562a9f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; + +// This contract mocks both the ITokenMessenger and IMessageTransmitter +// contracts involved with the Cross Chain Token Protocol. +contract MockUSDCTokenMessenger is ITokenMessenger { + uint32 private immutable i_messageBodyVersion; + address private immutable i_transmitter; + + bytes32 public constant DESTINATION_TOKEN_MESSENGER = keccak256("i_destinationTokenMessenger"); + + uint64 public s_nonce; + + constructor(uint32 version, address transmitter) { + i_messageBodyVersion = version; + s_nonce = 1; + i_transmitter = transmitter; + } + + function depositForBurnWithCaller( + uint256 amount, + uint32 destinationDomain, + bytes32 mintRecipient, + address burnToken, + bytes32 destinationCaller + ) external returns (uint64) { + IBurnMintERC20(burnToken).transferFrom(msg.sender, address(this), amount); + IBurnMintERC20(burnToken).burn(amount); + emit DepositForBurn( + s_nonce, + burnToken, + amount, + msg.sender, + mintRecipient, + destinationDomain, + DESTINATION_TOKEN_MESSENGER, + destinationCaller + ); + return s_nonce++; + } + + function messageBodyVersion() external view returns (uint32) { + return i_messageBodyVersion; + } + + function localMessageTransmitter() external view returns (address) { + return i_transmitter; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol new file mode 100644 index 0000000..dc9c644 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022, Circle Internet Financial Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +pragma solidity ^0.8.0; + +import {IMessageTransmitter} from "../../../pools/USDC/IMessageTransmitter.sol"; + +// This follows https://github.com/circlefin/evm-cctp-contracts/blob/master/src/interfaces/IMessageTransmitter.sol +interface IMessageTransmitterWithRelay is IMessageTransmitter { + /** + * @notice Sends an outgoing message from the source domain. + * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. + * @param destinationDomain Domain of destination chain + * @param recipient Address of message recipient on destination domain as bytes32 + * @param messageBody Raw bytes content of message + * @return nonce reserved by message + */ + function sendMessage( + uint32 destinationDomain, + bytes32 recipient, + bytes calldata messageBody + ) external returns (uint64); + + /** + * @notice Sends an outgoing message from the source domain, with a specified caller on the + * destination domain. + * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. + * WARNING: if the `destinationCaller` does not represent a valid address as bytes32, then it will not be possible + * to broadcast the message on the destination domain. This is an advanced feature, and the standard + * sendMessage() should be preferred for use cases where a specific destination caller is not required. + * @param destinationDomain Domain of destination chain + * @param recipient Address of message recipient on destination domain as bytes32 + * @param destinationCaller caller on the destination domain, as bytes32 + * @param messageBody Raw bytes content of message + * @return nonce reserved by message + */ + function sendMessageWithCaller( + uint32 destinationDomain, + bytes32 recipient, + bytes32 destinationCaller, + bytes calldata messageBody + ) external returns (uint64); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol new file mode 100644 index 0000000..6cbe7bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.8.0; + +import {Client} from "../../../libraries/Client.sol"; + +import {TokenSetup} from "../../TokenSetup.t.sol"; +import {IRouterClient, MockCCIPRouter} from "../MockRouter.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract MockRouterTest is TokenSetup { + using SafeERC20 for IERC20; + + MockCCIPRouter public mockRouter; + + uint64 public constant mockChainSelector = 123456; + + Client.EVM2AnyMessage public message; + + function setUp() public override { + mockRouter = new MockCCIPRouter(); + + //Configure the Fee to 0.1 ether for native token fees + mockRouter.setFee(0.1 ether); + + deal(address(this), 100 ether); + + message.receiver = abi.encode(address(0x12345)); + message.data = abi.encode("Hello World"); + + s_sourceFeeToken = _deploySourceToken("sLINK", type(uint256).max, 18); + } + + function test_ccipSendWithInsufficientNativeTokens_Revert() public { + //Should revert because did not include sufficient eth to pay for fees + vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); + mockRouter.ccipSend(mockChainSelector, message); + } + + function test_ccipSendWithSufficientNativeFeeTokens_Success() public { + //ccipSend with sufficient native tokens for fees + mockRouter.ccipSend{value: 0.1 ether}(mockChainSelector, message); + } + + function test_ccipSendWithInvalidMsgValue_Revert() public { + message.feeToken = address(1); //Set to non native-token fees + + vm.expectRevert(IRouterClient.InvalidMsgValue.selector); + mockRouter.ccipSend{value: 0.1 ether}(mockChainSelector, message); + } + + function test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() public { + message.feeToken = s_sourceFeeToken; + + vm.expectRevert(bytes("ERC20: insufficient allowance")); + mockRouter.ccipSend(mockChainSelector, message); + } + + function test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() public { + message.feeToken = s_sourceFeeToken; + + vm.startPrank(OWNER, OWNER); + + IERC20(s_sourceFeeToken).safeApprove(address(mockRouter), type(uint256).max); + + mockRouter.ccipSend(mockChainSelector, message); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol new file mode 100644 index 0000000..2783608 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol @@ -0,0 +1,1006 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; +import {MultiOCR3Helper} from "../helpers/MultiOCR3Helper.sol"; +import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; + +import {Vm} from "forge-std/Vm.sol"; + +contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { + bytes32 internal s_configDigest1; + bytes32 internal s_configDigest2; + bytes32 internal s_configDigest3; + + function setUp() public virtual override { + super.setUp(); + + s_configDigest1 = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); + s_configDigest2 = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); + s_configDigest3 = _getBasicConfigDigest(2, s_emptySigners, s_validTransmitters); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](3); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: s_configDigest1, + F: 1, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 1, + configDigest: s_configDigest2, + F: 2, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + ocrConfigs[2] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 2, + configDigest: s_configDigest3, + F: 1, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_TransmitSigners_gas_Success() public { + vm.pauseGasMetering(); + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + // F = 2, need 2 signatures + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(0, s_configDigest1, uint64(uint256(s_configDigest1))); + + vm.startPrank(s_validTransmitters[1]); + vm.resumeGasMetering(); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_TransmitWithoutSignatureVerification_gas_Success() public { + vm.pauseGasMetering(); + bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; + + s_multiOCR3.setTransmitOcrPluginType(2); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(2, s_configDigest3, uint64(uint256(s_configDigest3))); + + vm.startPrank(s_validTransmitters[0]); + vm.resumeGasMetering(); + s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); + } + + function test_Fuzz_TransmitSignersWithSignatures_Success(uint8 F, uint64 randomAddressOffset) public { + vm.pauseGasMetering(); + + F = uint8(bound(F, 1, 3)); + + // condition: signers.length > 3F + uint8 signersLength = 3 * F + 1; + address[] memory signers = new address[](signersLength); + address[] memory transmitters = new address[](signersLength); + uint256[] memory signerKeys = new uint256[](signersLength); + + // Force addresses to be unique (with a random offset for broader testing) + for (uint160 i = 0; i < signersLength; ++i) { + transmitters[i] = vm.addr(PRIVATE0 + randomAddressOffset + i); + // condition: non-zero oracle address + vm.assume(transmitters[i] != address(0)); + + // condition: non-repeating addresses (no clashes with transmitters) + signerKeys[i] = PRIVATE0 + randomAddressOffset + i + signersLength; + signers[i] = vm.addr(signerKeys[i]); + vm.assume(signers[i] != address(0)); + } + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 3, + configDigest: s_configDigest1, + F: F, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + s_multiOCR3.setOCR3Configs(ocrConfigs); + s_multiOCR3.setTransmitOcrPluginType(3); + + // Randomise picked transmitter with random offset + vm.startPrank(transmitters[randomAddressOffset % signersLength]); + + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + // condition: matches signature expectation for transmit + uint8 numSignatures = F + 1; + uint256[] memory pickedSignerKeys = new uint256[](numSignatures); + + // Randomise picked signers with random offset + for (uint256 i; i < numSignatures; ++i) { + pickedSignerKeys[i] = signerKeys[(i + randomAddressOffset) % numSignatures]; + } + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(pickedSignerKeys, REPORT, reportContext, numSignatures); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(3, s_configDigest1, uint64(uint256(s_configDigest1))); + + vm.resumeGasMetering(); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + // Reverts + function test_ForkedChain_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); + + s_multiOCR3.setTransmitOcrPluginType(0); + + uint256 chain1 = block.chainid; + uint256 chain2 = chain1 + 1; + vm.chainId(chain2); + vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); + + vm.startPrank(s_validTransmitters[0]); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_ZeroSignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), bytes32("")); + } + + function test_TooManySignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + // 1 signature too many + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 6); + + s_multiOCR3.setTransmitOcrPluginType(1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_InsufficientSignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + // Missing 1 signature for unique report + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 4); + + s_multiOCR3.setTransmitOcrPluginType(1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_ConfigDigestMismatch_Revert() public { + bytes32 configDigest; + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + + (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ConfigDigestMismatch.selector, s_configDigest1, configDigest)); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), rawVs); + } + + function test_SignatureOutOfRegistration_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](1); + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.SignaturesOutOfRegistration.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); + } + + function test_UnAuthorizedTransmitter_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](2); + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); + } + + function test_NonUniqueSignature_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); + + rs[1] = rs[0]; + ss[1] = ss[0]; + // Need to reset the rawVs to be valid + rawVs = bytes32(bytes1(vs[0] - 27)) | (bytes32(bytes1(vs[0] - 27)) >> 8); + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.NonUniqueSignatures.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_UnauthorizedSigner_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); + + rs[0] = s_configDigest1; + ss = rs; + + s_multiOCR3.setTransmitOcrPluginType(0); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.UnauthorizedSigner.selector); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); + } + + function test_UnconfiguredPlugin_Revert() public { + bytes32 configDigest; + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + + s_multiOCR3.setTransmitOcrPluginType(42); + + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); + } + + function test_TransmitWithLessCalldataArgs_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + + s_multiOCR3.setTransmitOcrPluginType(0); + + // The transmit should fail, since we are trying to transmit without signatures when signatures are enabled + vm.startPrank(s_validTransmitters[1]); + + // report length + function selector + report length + abiencoded location of report value + report context words + uint256 receivedLength = REPORT.length + 4 + 5 * 32; + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.WrongMessageLength.selector, + // Expecting inclusion of signature constant length components + receivedLength + 5 * 32, + receivedLength + ) + ); + s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); + } + + function test_TransmitWithExtraCalldataArgs_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](2); + + s_multiOCR3.setTransmitOcrPluginType(2); + + // The transmit should fail, since we are trying to transmit with signatures when signatures are disabled + vm.startPrank(s_validTransmitters[1]); + + // dynamic length + function selector + report length + abiencoded location of report value + report context words + // rawVs value, lengths of rs, ss, and start locations of rs & ss -> 5 words + uint256 receivedLength = REPORT.length + 4 + (5 * 32) + (5 * 32) + (2 * 32) + (2 * 32); + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.WrongMessageLength.selector, + // Expecting exclusion of signature constant length components and rs, ss words + receivedLength - (5 * 32) - (4 * 32), + receivedLength + ) + ); + s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); + } +} + +contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { + function test_SetConfigsZeroInput_Success() public { + vm.recordLogs(); + s_multiOCR3.setOCR3Configs(new MultiOCR3Base.OCRConfigArgs[](0)); + + // No logs emitted + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_SetConfigWithSigners_Success() public { + uint8 F = 2; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_validSigners, + transmitters: s_validTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + } + + function test_SetConfigWithSignersMismatchingTransmitters_Success() public { + uint8 F = 2; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, s_validSigners, s_partialTransmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + } + + function test_SetConfigWithoutSigners_Success() public { + uint8 F = 1; + address[] memory signers = new address[](0); + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, signers, s_validTransmitters), + F: F, + isSignatureVerificationEnabled: false, + signers: signers, + transmitters: s_validTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: signers, + transmitters: s_validTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + } + + function test_SetConfigIgnoreSigners_Success() public { + uint8 F = 1; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, new address[](0), s_validTransmitters), + F: F, + isSignatureVerificationEnabled: false, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + s_emptySigners, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: 0, + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + + // Verify no signer role is set + for (uint256 i = 0; i < s_validSigners.length; ++i) { + MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, s_validSigners[i]); + assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Unset)); + } + } + + function test_SetMultipleConfigs_Success() public { + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(1)); + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(2)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](3); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), + F: 2, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 1, + configDigest: _getBasicConfigDigest(1, s_validSigners, s_validTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + ocrConfigs[2] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 2, + configDigest: _getBasicConfigDigest(1, s_partialSigners, s_partialTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: s_partialSigners, + transmitters: s_partialTransmitters + }); + + for (uint256 i; i < ocrConfigs.length; ++i) { + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[i].ocrPluginType, + ocrConfigs[i].configDigest, + ocrConfigs[i].signers, + ocrConfigs[i].transmitters, + ocrConfigs[i].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[i].ocrPluginType); + } + s_multiOCR3.setOCR3Configs(ocrConfigs); + + for (uint256 i; i < ocrConfigs.length; ++i) { + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[i].configDigest, + F: ocrConfigs[i].F, + n: uint8(ocrConfigs[i].signers.length), + isSignatureVerificationEnabled: ocrConfigs[i].isSignatureVerificationEnabled + }), + signers: ocrConfigs[i].signers, + transmitters: ocrConfigs[i].transmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfigs[i].ocrPluginType), expectedConfig); + } + + // pluginType 3 remains unconfigured + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(3)); + } + + function test_Fuzz_SetConfig_Success(MultiOCR3Base.OCRConfigArgs memory ocrConfig, uint64 randomAddressOffset) public { + // condition: cannot assume max oracle count + vm.assume(ocrConfig.transmitters.length <= 255); + vm.assume(ocrConfig.signers.length <= 255); + // condition: at least one transmitter + vm.assume(ocrConfig.transmitters.length > 0); + // condition: number of transmitters does not exceed signers + vm.assume(ocrConfig.signers.length == 0 || ocrConfig.transmitters.length <= ocrConfig.signers.length); + + // condition: F > 0 + ocrConfig.F = uint8(bound(ocrConfig.F, 1, 3)); + + uint256 transmittersLength = ocrConfig.transmitters.length; + + // Force addresses to be unique (with a random offset for broader testing) + for (uint160 i = 0; i < transmittersLength; ++i) { + ocrConfig.transmitters[i] = vm.addr(PRIVATE0 + randomAddressOffset + i); + // condition: non-zero oracle address + vm.assume(ocrConfig.transmitters[i] != address(0)); + } + + if (ocrConfig.signers.length == 0) { + ocrConfig.isSignatureVerificationEnabled = false; + } else { + ocrConfig.isSignatureVerificationEnabled = true; + + // condition: number of signers > 3F + vm.assume(ocrConfig.signers.length > 3 * ocrConfig.F); + + uint256 signersLength = ocrConfig.signers.length; + + // Force addresses to be unique - continuing generation with an offset after the transmitter addresses + for (uint160 i = 0; i < signersLength; ++i) { + ocrConfig.signers[i] = vm.addr(PRIVATE0 + randomAddressOffset + i + transmittersLength); + // condition: non-zero oracle address + vm.assume(ocrConfig.signers[i] != address(0)); + } + } + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = ocrConfig; + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfig.ocrPluginType, ocrConfig.configDigest, ocrConfig.signers, ocrConfig.transmitters, ocrConfig.F + ); + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfig.ocrPluginType); + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfig.configDigest, + F: ocrConfig.F, + n: ocrConfig.isSignatureVerificationEnabled ? uint8(ocrConfig.signers.length) : 0, + isSignatureVerificationEnabled: ocrConfig.isSignatureVerificationEnabled + }), + signers: ocrConfig.signers, + transmitters: ocrConfig.transmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType), expectedConfig); + } + + function test_UpdateConfigTransmittersWithoutSigners_Success() public { + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, s_emptySigners, s_validTransmitters), + F: 1, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + s_multiOCR3.setOCR3Configs(ocrConfigs); + + address[] memory newTransmitters = s_partialSigners; + + ocrConfigs[0].F = 2; + ocrConfigs[0].configDigest = _getBasicConfigDigest(2, s_emptySigners, newTransmitters); + ocrConfigs[0].transmitters = newTransmitters; + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_emptySigners, + transmitters: newTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + + // Verify oracle roles get correctly re-assigned + for (uint256 i; i < newTransmitters.length; ++i) { + MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, newTransmitters[i]); + assertEq(transmitterOracle.index, i); + assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Transmitter)); + } + + // Verify old transmitters get correctly unset + for (uint256 i = newTransmitters.length; i < s_validTransmitters.length; ++i) { + MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, s_validTransmitters[i]); + assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Unset)); + } + } + + function test_UpdateConfigSigners_Success() public { + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), + F: 2, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + s_multiOCR3.setOCR3Configs(ocrConfigs); + + address[] memory newSigners = s_partialTransmitters; + address[] memory newTransmitters = s_partialSigners; + + ocrConfigs[0].F = 1; + ocrConfigs[0].configDigest = _getBasicConfigDigest(1, newSigners, newTransmitters); + ocrConfigs[0].signers = newSigners; + ocrConfigs[0].transmitters = newTransmitters; + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: newSigners, + transmitters: newTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + + // Verify oracle roles get correctly re-assigned + for (uint256 i; i < newSigners.length; ++i) { + MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, newSigners[i]); + assertEq(signerOracle.index, i); + assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Signer)); + + MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, newTransmitters[i]); + assertEq(transmitterOracle.index, i); + assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Transmitter)); + } + + // Verify old signers / transmitters get correctly unset + for (uint256 i = newSigners.length; i < s_validSigners.length; ++i) { + MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, s_validSigners[i]); + assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Unset)); + + MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, s_validTransmitters[i]); + assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Unset)); + } + } + + // Reverts + + function test_RepeatTransmitterAddress_Revert() public { + address[] memory signers = s_validSigners; + address[] memory transmitters = s_validTransmitters; + transmitters[0] = signers[0]; + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_RepeatSignerAddress_Revert() public { + address[] memory signers = s_validSigners; + address[] memory transmitters = s_validTransmitters; + signers[1] = signers[0]; + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_SignerCannotBeZeroAddress_Revert() public { + uint8 F = 1; + address[] memory signers = new address[](3 * F + 1); + address[] memory transmitters = new address[](3 * F + 1); + for (uint160 i = 0; i < 3 * F + 1; ++i) { + signers[i] = address(i + 1); + transmitters[i] = address(i + 1000); + } + + signers[0] = address(0); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, signers, transmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert(MultiOCR3Base.OracleCannotBeZeroAddress.selector); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_TransmitterCannotBeZeroAddress_Revert() public { + uint8 F = 1; + address[] memory signers = new address[](3 * F + 1); + address[] memory transmitters = new address[](3 * F + 1); + for (uint160 i = 0; i < 3 * F + 1; ++i) { + signers[i] = address(i + 1); + transmitters[i] = address(i + 1000); + } + + transmitters[0] = address(0); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, signers, transmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert(MultiOCR3Base.OracleCannotBeZeroAddress.selector); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_StaticConfigChange_Revert() public { + uint8 F = 1; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + // signature verification cannot change + ocrConfigs[0].isSignatureVerificationEnabled = false; + vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.StaticConfigCannotBeChanged.selector, 0)); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_FTooHigh_Revert() public { + address[] memory signers = new address[](0); + address[] memory transmitters = new address[](1); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.F_TOO_HIGH) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_FMustBePositive_Revert() public { + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(0, s_validSigners, s_validTransmitters), + F: 0, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.F_MUST_BE_POSITIVE + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_NoTransmitters_Revert() public { + address[] memory signers = new address[](0); + address[] memory transmitters = new address[](0); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(10, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: false, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.NO_TRANSMITTERS) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_TooManyTransmitters_Revert() public { + address[] memory signers = new address[](0); + address[] memory transmitters = new address[](257); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(10, signers, transmitters), + F: 10, + isSignatureVerificationEnabled: false, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_TooManySigners_Revert() public { + address[] memory signers = new address[](257); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, signers, s_validTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: signers, + transmitters: s_validTransmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_SIGNERS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + + function test_MoreTransmittersThanSigners_Revert() public { + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, s_validSigners, s_partialTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: s_partialSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol new file mode 100644 index 0000000..9cfddf0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {MultiOCR3Helper} from "../helpers/MultiOCR3Helper.sol"; + +contract MultiOCR3BaseSetup is BaseTest { + // Signer private keys used for these test + uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + + address[] internal s_validSigners; + address[] internal s_validTransmitters; + uint256[] internal s_validSignerKeys; + + address[] internal s_partialSigners; + address[] internal s_partialTransmitters; + uint256[] internal s_partialSignerKeys; + + address[] internal s_emptySigners; + + bytes internal constant REPORT = abi.encode("testReport"); + MultiOCR3Helper internal s_multiOCR3; + + function setUp() public virtual override { + BaseTest.setUp(); + + uint160 numSigners = 7; + s_validSignerKeys = new uint256[](numSigners); + s_validSigners = new address[](numSigners); + s_validTransmitters = new address[](numSigners); + + for (uint160 i; i < numSigners; ++i) { + s_validTransmitters[i] = address(4 + i); + s_validSignerKeys[i] = PRIVATE0 + i; + s_validSigners[i] = vm.addr(s_validSignerKeys[i]); + } + + s_partialSigners = new address[](4); + s_partialSignerKeys = new uint256[](4); + s_partialTransmitters = new address[](4); + for (uint256 i; i < s_partialSigners.length; ++i) { + s_partialSigners[i] = s_validSigners[i]; + s_partialSignerKeys[i] = s_validSignerKeys[i]; + s_partialTransmitters[i] = s_validTransmitters[i]; + } + + s_emptySigners = new address[](0); + + s_multiOCR3 = new MultiOCR3Helper(); + } + + /// @dev returns a mock config digest with config digest computation logic similar to OCR2Base + function _getBasicConfigDigest( + uint8 F, + address[] memory signers, + address[] memory transmitters + ) internal view returns (bytes32) { + bytes memory configBytes = abi.encode(""); + uint256 configVersion = 1; + + uint256 h = uint256( + keccak256( + abi.encode( + block.chainid, address(s_multiOCR3), signers, transmitters, F, configBytes, configVersion, configBytes + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + function _assertOCRConfigEquality( + MultiOCR3Base.OCRConfig memory configA, + MultiOCR3Base.OCRConfig memory configB + ) internal pure { + vm.assertEq(configA.configInfo.configDigest, configB.configInfo.configDigest); + vm.assertEq(configA.configInfo.F, configB.configInfo.F); + vm.assertEq(configA.configInfo.n, configB.configInfo.n); + vm.assertEq(configA.configInfo.isSignatureVerificationEnabled, configB.configInfo.isSignatureVerificationEnabled); + + vm.assertEq(configA.signers, configB.signers); + vm.assertEq(configA.transmitters, configB.transmitters); + } + + function _assertOCRConfigUnconfigured( + MultiOCR3Base.OCRConfig memory config + ) internal pure { + assertEq(config.configInfo.configDigest, bytes32("")); + assertEq(config.signers.length, 0); + assertEq(config.transmitters.length, 0); + } + + function _getSignaturesForDigest( + uint256[] memory signerPrivateKeys, + bytes memory report, + bytes32[3] memory reportContext, + uint8 signatureCount + ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { + rs = new bytes32[](signatureCount); + ss = new bytes32[](signatureCount); + vs = new uint8[](signatureCount); + + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + // Calculate signatures + for (uint256 i; i < signatureCount; ++i) { + (vs[i], rs[i], ss[i]) = vm.sign(signerPrivateKeys[i], reportDigest); + rawVs = rawVs | (bytes32(bytes1(vs[i] - 27)) >> (8 * i)); + } + + return (rs, ss, vs, rawVs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol new file mode 100644 index 0000000..c458b67 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -0,0 +1,3797 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; +import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; + +import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {NonceManager} from "../../NonceManager.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; +import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {OffRampHelper} from "../helpers/OffRampHelper.sol"; +import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; +import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; +import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; +import {ReentrancyAbuserMultiRamp} from "../helpers/receivers/ReentrancyAbuserMultiRamp.sol"; +import {OffRampSetup} from "./OffRampSetup.t.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract OffRamp_constructor is OffRampSetup { + function test_Constructor_Success() public { + OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, + onRamp: ON_RAMP_ADDRESS_2, + isEnabled: true + }); + + OffRamp.SourceChainConfig memory expectedSourceChainConfig1 = OffRamp.SourceChainConfig({ + router: s_destRouter, + isEnabled: true, + minSeqNr: 1, + onRamp: sourceChainConfigs[0].onRamp + }); + + OffRamp.SourceChainConfig memory expectedSourceChainConfig2 = OffRamp.SourceChainConfig({ + router: s_destRouter, + isEnabled: true, + minSeqNr: 1, + onRamp: sourceChainConfigs[1].onRamp + }); + + uint64[] memory expectedSourceChainSelectors = new uint64[](2); + expectedSourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + expectedSourceChainSelectors[1] = SOURCE_CHAIN_SELECTOR_1 + 1; + + vm.expectEmit(); + emit OffRamp.StaticConfigSet(staticConfig); + + vm.expectEmit(); + emit OffRamp.DynamicConfigSet(dynamicConfig); + + vm.expectEmit(); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig1); + + vm.expectEmit(); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1 + 1); + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1 + 1, expectedSourceChainConfig2); + + s_offRamp = new OffRampHelper(staticConfig, dynamicConfig, sourceChainConfigs); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + + s_offRamp.setOCR3Configs(ocrConfigs); + + // Static config + OffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); + assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); + assertEq(address(staticConfig.rmnRemote), address(gotStaticConfig.rmnRemote)); + assertEq(staticConfig.tokenAdminRegistry, gotStaticConfig.tokenAdminRegistry); + + // Dynamic config + OffRamp.DynamicConfig memory gotDynamicConfig = s_offRamp.getDynamicConfig(); + _assertSameConfig(dynamicConfig, gotDynamicConfig); + + // OCR Config + MultiOCR3Base.OCRConfig memory expectedOCRConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: 0, + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + MultiOCR3Base.OCRConfig memory gotOCRConfig = s_offRamp.latestConfigDetails(uint8(Internal.OCRPluginType.Execution)); + _assertOCRConfigEquality(expectedOCRConfig, gotOCRConfig); + + (uint64[] memory actualSourceChainSelectors, OffRamp.SourceChainConfig[] memory actualSourceChainConfigs) = + s_offRamp.getAllSourceChainConfigs(); + + _assertSourceChainConfigEquality(actualSourceChainConfigs[0], expectedSourceChainConfig1); + _assertSourceChainConfigEquality(actualSourceChainConfigs[1], expectedSourceChainConfig2); + + // OffRamp initial values + assertEq("OffRamp 1.6.0-dev", s_offRamp.typeAndVersion()); + assertEq(OWNER, s_offRamp.owner()); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + + // assertion for source chain selector + for (uint256 i = 0; i < expectedSourceChainSelectors.length; i++) { + assertEq(expectedSourceChainSelectors[i], actualSourceChainSelectors[i]); + } + } + + // Revert + function test_ZeroOnRampAddress_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: new bytes(0), + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } + + function test_SourceChainSelector_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: 0, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } + + function test_ZeroRMNRemote_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: IRMNRemote(ZERO_ADDRESS), + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } + + function test_ZeroChainSelector_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: 0, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } + + function test_ZeroTokenAdminRegistry_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: ZERO_ADDRESS, + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } + + function test_ZeroNonceManager_Revert() public { + uint64[] memory sourceChainSelectors = new uint64[](1); + sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: ZERO_ADDRESS + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + } +} + +contract OffRamp_setDynamicConfig is OffRampSetup { + function test_SetDynamicConfig_Success() public { + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); + + vm.expectEmit(); + emit OffRamp.DynamicConfigSet(dynamicConfig); + + s_offRamp.setDynamicConfig(dynamicConfig); + + OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); + _assertSameConfig(dynamicConfig, newConfig); + } + + function test_SetDynamicConfigWithInterceptor_Success() public { + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); + + vm.expectEmit(); + emit OffRamp.DynamicConfigSet(dynamicConfig); + + s_offRamp.setDynamicConfig(dynamicConfig); + + OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); + _assertSameConfig(dynamicConfig, newConfig); + } + + // Reverts + + function test_NonOwner_Revert() public { + vm.startPrank(STRANGER); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); + + vm.expectRevert("Only callable by owner"); + + s_offRamp.setDynamicConfig(dynamicConfig); + } + + function test_FeeQuoterZeroAddress_Revert() public { + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(ZERO_ADDRESS); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + + s_offRamp.setDynamicConfig(dynamicConfig); + } +} + +contract OffRamp_ccipReceive is OffRampSetup { + // Reverts + + function test_Reverts() public { + Client.Any2EVMMessage memory message = + _convertToGeneralMessage(_generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1)); + vm.expectRevert(); + s_offRamp.ccipReceive(message); + } +} + +contract OffRamp_executeSingleReport is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); + } + + function test_SingleMessageNoTokens_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + messages[0].header.nonce++; + messages[0].header.sequenceNumber++; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); + } + + function test_SingleMessageNoTokensUnordered_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].header.nonce = 0; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + // Nonce never increments on unordered messages. + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), + nonceBefore, + "nonce must remain unchanged on unordered messages" + ); + + messages[0].header.sequenceNumber++; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + // Nonce never increments on unordered messages. + nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertEq( + s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), + nonceBefore, + "nonce must remain unchanged on unordered messages" + ); + } + + function test_SingleMessageNoTokensOtherChain_Success() public { + Internal.Any2EVMRampMessage[] memory messagesChain1 = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new OffRamp.GasLimitOverride[](0) + ); + + uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender); + assertGt(nonceChain1, 0); + + Internal.Any2EVMRampMessage[] memory messagesChain2 = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new OffRamp.GasLimitOverride[](0) + ); + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); + + // Other chain's nonce is unaffected + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender), nonceChain1); + } + + function test_ReceiverError_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + bytes memory realError1 = new bytes(2); + realError1[0] = 0xbe; + realError1[1] = 0xef; + s_reverting_receiver.setErr(realError1); + + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + // Nonce should increment on non-strict + assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + OffRamp.ReceiverError.selector, + abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) + ) + ); + assertEq(uint64(1), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + } + + function test_SkippedIncorrectNonce_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + messages[0].header.nonce++; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce( + messages[0].header.sourceChainSelector, messages[0].header.nonce, messages[0].sender + ); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + function test_SkippedIncorrectNonceStillExecutes_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + messages[1].header.nonce++; + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test__execute_SkippedAlreadyExecutedMessage_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + vm.expectEmit(); + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].header.nonce = 0; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + vm.expectEmit(); + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + // Send a message to a contract that does not implement the CCIPReceiver interface + // This should execute successfully. + function test_SingleMessageToNonCCIPReceiver_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); + messages[0].receiver = address(newReceiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_SingleMessagesNoTokensSuccess_gas() public { + vm.pauseGasMetering(); + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.resumeGasMetering(); + vm.recordLogs(); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_TwoMessagesWithTokensSuccess_gas() public { + vm.pauseGasMetering(); + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + // Set message 1 to use another receiver to simulate more fair gas costs + messages[1].receiver = address(s_secondary_receiver); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.resumeGasMetering(); + vm.recordLogs(); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[1].header.sequenceNumber, + messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_TwoMessagesWithTokensAndGE_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + // Set message 1 to use another receiver to simulate more fair gas costs + messages[1].receiver = address(s_secondary_receiver); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + + assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) + ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[1].header.sequenceNumber, + messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertEq(uint64(2), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); + } + + function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success( + bool[7] memory orderings + ) public { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](orderings.length); + // number of tokens needs to be capped otherwise we hit UnsupportedNumberOfTokens. + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](3); + for (uint256 i = 0; i < 3; ++i) { + tokenAmounts[i].token = s_sourceTokens[i % s_sourceTokens.length]; + tokenAmounts[i].amount = 1e18; + } + uint64 expectedNonce = 0; + + for (uint256 i = 0; i < orderings.length; ++i) { + messages[i] = + _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, uint64(i + 1), tokenAmounts, !orderings[i]); + if (orderings[i]) { + messages[i].header.nonce = ++expectedNonce; + } + messages[i].header.messageId = _hashMessage(messages[i], ON_RAMP_ADDRESS_1); + } + + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)); + assertEq(uint64(0), nonceBefore, "nonce before exec should be 0"); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) + ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + // all executions should succeed. + for (uint256 i = 0; i < orderings.length; ++i) { + assertEq( + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber)), + uint256(Internal.MessageExecutionState.SUCCESS) + ); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[i].header.sequenceNumber, + messages[i].header.messageId, + _hashMessage(messages[i], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + assertEq( + nonceBefore + expectedNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)) + ); + } + + function test_InvalidSourcePoolAddress_Success() public { + address fakePoolAddress = address(0x0000000000333333); + + Internal.Any2EVMRampMessage[] memory messages = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].tokenAmounts[0].sourcePoolAddress = abi.encode(fakePoolAddress); + + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + OffRamp.TokenHandlingError.selector, + abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) + ) + ); + } + + function test_WithCurseOnAnotherSourceChain_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[](0) + ); + } + + function test_Unhealthy_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[](0) + ); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[](0) + ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + // Reverts + + function test_MismatchingDestChainSelector_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; + + Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectRevert( + abi.encodeWithSelector(OffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector) + ); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); + } + + function test_UnhealthySingleChainCurse_Revert() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[](0) + ); + vm.recordLogs(); + // Uncurse should succeed + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[](0) + ); + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + function test_UnexpectedTokenData_Revert() public { + Internal.ExecutionReport memory report = _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ); + report.offchainTokenData = new bytes[][](report.messages.length + 1); + + vm.expectRevert(OffRamp.UnexpectedTokenData.selector); + + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + } + + function test_EmptyReport_Revert() public { + vm.expectRevert(OffRamp.EmptyReport.selector); + s_offRamp.executeSingleReport( + Internal.ExecutionReport({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + proofs: new bytes32[](0), + proofFlagBits: 0, + messages: new Internal.Any2EVMRampMessage[](0), + offchainTokenData: new bytes[][](0) + }), + new OffRamp.GasLimitOverride[](0) + ); + } + + function test_RootNotCommitted_Revert() public { + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); + vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) + ); + } + + function test_ManualExecutionNotYetEnabled_Revert() public { + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, BLOCK_TIME); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1)); + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) + ); + } + + function test_NonExistingSourceChain_Revert() public { + uint64 newSourceChainSelector = SOURCE_CHAIN_SELECTOR_1 + 1; + bytes memory newOnRamp = abi.encode(ON_RAMP_ADDRESS, 1); + + Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(newSourceChainSelector, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + function test_DisabledSourceChain_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + function test_TokenDataMismatch_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + report.offchainTokenData[0] = new bytes[](messages[0].tokenAmounts.length + 1); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber + ) + ); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); + } + + function test_RouterYULCall_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + // gas limit too high, Router's external call should revert + messages[0].gasLimit = 1e36; + messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.recordLogs(); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) + ); + } + + function test_RetryFailedMessageWithoutManualExecution_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + bytes memory realError1 = new bytes(2); + realError1[0] = 0xbe; + realError1[1] = 0xef; + s_reverting_receiver.setErr(realError1); + + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + OffRamp.ReceiverError.selector, + abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) + ) + ); + + // The second time should skip the msg + vm.expectEmit(); + emit OffRamp.AlreadyAttempted(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + } + + function _constructCommitReport( + bytes32 merkleRoot + ) internal view returns (OffRamp.CommitReport memory) { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: merkleRoot + }); + + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + } +} + +contract OffRamp_executeSingleMessage is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + vm.startPrank(address(s_offRamp)); + } + + function test_executeSingleMessage_NoTokens_Success() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_executeSingleMessage_WithTokens_Success() public { + Internal.Any2EVMRampMessage memory message = + _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; + bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); + + vm.expectCall( + s_destPoolByToken[s_destTokens[0]], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: message.sender, + receiver: message.receiver, + amount: message.tokenAmounts[0].amount, + localToken: message.tokenAmounts[0].destTokenAddress, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: message.tokenAmounts[0].sourcePoolAddress, + sourcePoolData: message.tokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ) + ); + + s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); + } + + function test_executeSingleMessage_WithVInterception_Success() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableInboundMessageInterceptor(); + vm.startPrank(address(s_offRamp)); + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_NonContract_Success() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + message.receiver = STRANGER; + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_NonContractWithTokens_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; + vm.expectEmit(); + emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); + vm.expectEmit(); + emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + message.receiver = STRANGER; + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + // Reverts + + function test_TokenHandlingError_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; + + bytes memory errorMessage = "Random token pool issue"; + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + s_maybeRevertingPool.setShouldRevert(errorMessage); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); + + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_ZeroGasDONExecution_Revert() public { + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + message.gasLimit = 0; + + vm.expectRevert(abi.encodeWithSelector(OffRamp.ReceiverError.selector, "")); + + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_MessageSender_Revert() public { + vm.stopPrank(); + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + vm.expectRevert(OffRamp.CanOnlySelfCall.selector); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_executeSingleMessage_WithFailingValidation_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableInboundMessageInterceptor(); + vm.startPrank(address(s_offRamp)); + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ) + ); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } + + function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableInboundMessageInterceptor(); + vm.startPrank(address(s_offRamp)); + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + // Setup the receiver to a non-CCIP Receiver, which will skip the Router call (but should still perform the validation) + MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); + message.receiver = address(newReceiver); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); + + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ) + ); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + } +} + +contract OffRamp_batchExecute is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); + } + + function test_SingleReport_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); + } + + function test_MultipleReportsSameChain_Success() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); + vm.recordLogs(); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); + } + + function test_MultipleReportsDifferentChains_Success() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + vm.recordLogs(); + + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_3), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); + uint64 nonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messages2[0].sender); + + assertTrue(nonceChain1 != nonceChain3); + assertGt(nonceChain1, 0); + assertGt(nonceChain3, 0); + } + + function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + vm.recordLogs(); + + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState,,) = abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logSourceChainSelector, messages2[0].header.sourceChainSelector); + assertEq(logSequenceNumber, messages2[0].header.sequenceNumber); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logMessageHash, _hashMessage(messages2[0], ON_RAMP_ADDRESS_3)); + assertEq(logState, uint8(Internal.MessageExecutionState.SUCCESS)); + } + } + } + + function test_MultipleReportsSkipDuplicate_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectEmit(); + emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); + + vm.recordLogs(); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + assertExecutionStateChangedEventLogs( + messages[0].header.sourceChainSelector, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_Unhealthy_Success() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + s_offRamp.batchExecute( + _generateBatchReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[][](1) + ); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); + + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new OffRamp.GasLimitOverride[][](1) + ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + // Reverts + function test_ZeroReports_Revert() public { + vm.expectRevert(OffRamp.EmptyReport.selector); + s_offRamp.batchExecute(new Internal.ExecutionReport[](0), new OffRamp.GasLimitOverride[][](1)); + } + + function test_OutOfBoundsGasLimitsAccess_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + vm.expectRevert(); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](1)); + } +} + +contract OffRamp_manuallyExecute is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); + } + + function test_manuallyExecute_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + + s_reverting_receiver.setRevert(false); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](messages.length); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_manuallyExecute_WithGasOverride_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + + s_reverting_receiver.setRevert(false); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + assertEq( + messages[0].header.nonce - 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) + ); + + s_reverting_receiver.setRevert(true); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") + ) + ); + + assertEq( + messages[0].header.nonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) + ); + } + + function test_manuallyExecute_WithMultiReportGasOverride_Success() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); + + for (uint64 i = 0; i < 3; ++i) { + messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); + messages1[i].receiver = address(s_reverting_receiver); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); + } + + for (uint64 i = 0; i < 2; ++i) { + messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); + messages2[i].receiver = address(s_reverting_receiver); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); + } + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); + + s_reverting_receiver.setRevert(false); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + for (uint256 i = 0; i < 3; ++i) { + gasLimitOverrides[0][i].receiverExecutionGasLimit += 1; + } + + for (uint256 i = 0; i < 2; ++i) { + gasLimitOverrides[1][i].receiverExecutionGasLimit += 1; + } + + vm.recordLogs(); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 j = 0; j < 3; ++j) { + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages1[j].header.sequenceNumber, + messages1[j].header.messageId, + _hashMessage(messages1[j], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + for (uint256 k = 0; k < 2; ++k) { + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_3, + messages2[k].header.sequenceNumber, + messages2[k].header.messageId, + _hashMessage(messages2[k], ON_RAMP_ADDRESS_3), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + } + + function test_manuallyExecute_WithPartialMessages_Success() public { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); + + for (uint64 i = 0; i < 3; ++i) { + messages[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); + } + + messages[1].receiver = address(s_reverting_receiver); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[1].header.sequenceNumber, + messages[1].header.messageId, + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + OffRamp.ReceiverError.selector, + abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) + ) + ); + + assertExecutionStateChangedEventLogs( + logs, + SOURCE_CHAIN_SELECTOR_1, + messages[2].header.sequenceNumber, + messages[2].header.messageId, + _hashMessage(messages[2], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + s_reverting_receiver.setRevert(false); + + // Only the 2nd message reverted + Internal.Any2EVMRampMessage[] memory newMessages = new Internal.Any2EVMRampMessage[](1); + newMessages[0] = messages[1]; + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(newMessages); + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, newMessages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_manuallyExecute_LowGasLimit_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].gasLimit = 1; + messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") + ); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); + gasLimitOverrides[0][0].receiverExecutionGasLimit = 100_000; + + vm.expectEmit(); + emit ConformingReceiver.MessageReceived(); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + // Reverts + + function test_manuallyExecute_ForkedChain_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + uint256 chain1 = block.chainid; + uint256 chain2 = chain1 + 1; + vm.chainId(chain2); + vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } + + function test_ManualExecGasLimitMismatchSingleReport_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); + messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + // No overrides for report + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); + + // No messages + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + // 1 message missing + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + // 1 message in excess + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } + + function test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](1)); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + // 2nd report empty + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](2); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + // 1st report empty + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](0); + gasLimitOverrides[1] = new OffRamp.GasLimitOverride[](1); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + + // 1st report oversized + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); + + vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } + + function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].receiverExecutionGasLimit--; + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidManualExecutionGasLimit.selector, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.messageId, + gasLimitOverrides[0][0].receiverExecutionGasLimit + ) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + // empty tokenGasOverride array provided + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + + //trying with excesss elements tokenGasOverride array provided + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](3); + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + uint32[] memory tokenGasOverrides = new uint32[](2); + tokenGasOverrides[0] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + tokenGasOverrides[1] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD - 1; //invalid token gas override value + gasLimitOverrides[0][0].tokenGasOverrides = tokenGasOverrides; + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidManualExecutionTokenGasOverride.selector, + messages[0].header.messageId, + 1, + DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + tokenGasOverrides[1] + ) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_FailedTx_Revert() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + messages[0].receiver = address(s_reverting_receiver); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); + + s_reverting_receiver.setRevert(true); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.ExecutionError.selector, + messages[0].header.messageId, + abi.encodeWithSelector( + OffRamp.ReceiverError.selector, + abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) + ) + ) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_ReentrancyFails_Success() public { + uint256 tokenAmount = 1e9; + IERC20 tokenToAbuse = IERC20(s_destFeeToken); + + // This needs to be deployed before the source chain message is sent + // because we need the address for the receiver. + ReentrancyAbuserMultiRamp receiver = new ReentrancyAbuserMultiRamp(address(s_destRouter), s_offRamp); + uint256 balancePre = tokenToAbuse.balanceOf(address(receiver)); + + // For this test any message will be flagged as correct by the + // commitStore. In a real scenario the abuser would have to actually + // send the message that they want to replay. + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + messages[0].tokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + messages[0].tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), + destTokenAddress: s_destTokenBySourceToken[s_sourceFeeToken], + extraData: "", + amount: tokenAmount, + destGasAmount: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS + }); + + messages[0].receiver = address(receiver); + + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + // sets the report to be repeated on the ReentrancyAbuser to be able to replay + receiver.setPayload(report); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](messages[0].tokenAmounts.length); + + // The first entry should be fine and triggers the second entry which is skipped. Due to the reentrancy + // the second completes first, so we expect the skip event before the success event. + vm.expectEmit(); + emit OffRamp.SkippedAlreadyExecutedMessage( + messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber + ); + + vm.recordLogs(); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + // Since the tx failed we don't release the tokens + assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); + } + + function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); + + for (uint64 i = 0; i < 3; ++i) { + messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); + messages1[i].receiver = address(s_reverting_receiver); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); + } + + for (uint64 i = 0; i < 2; ++i) { + messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); + messages2[i].receiver = address(s_reverting_receiver); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); + } + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_3, true); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_3)); + + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } + + function test_manuallyExecute_SourceChainSelectorMismatch_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](1); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.SourceChainSelectorMismatch.selector, SOURCE_CHAIN_SELECTOR_3, SOURCE_CHAIN_SELECTOR_1 + ) + ); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } +} + +contract OffRamp_execute is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + } + + // Asserts that execute completes + function test_SingleReport_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + + _execute(reports); + + assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_MultipleReports_Success() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_LargeBatch_Success() public { + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](10); + for (uint64 i = 0; i < reports.length; ++i) { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); + messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1 + i * 3); + messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2 + i * 3); + messages[2] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3 + i * 3); + + reports[i] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + } + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint64 i = 0; i < reports.length; ++i) { + for (uint64 j = 0; j < reports[i].messages.length; ++j) { + assertExecutionStateChangedEventLogs( + logs, + reports[i].messages[j].header.sourceChainSelector, + reports[i].messages[j].header.sequenceNumber, + reports[i].messages[j].header.messageId, + _hashMessage(reports[i].messages[j], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + } + } + + function test_MultipleReportsWithPartialValidationFailures_Success() public { + _enableInboundMessageInterceptor(); + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); + + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + s_inboundMessageInterceptor.setMessageIdValidationState(messages1[0].header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(messages2[0].header.messageId, true); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted( + uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) + ); + + vm.recordLogs(); + _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + assertExecutionStateChangedEventLogs( + logs, + messages1[0].header.sourceChainSelector, + messages1[0].header.sequenceNumber, + messages1[0].header.messageId, + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ) + ); + + assertExecutionStateChangedEventLogs( + logs, + messages1[1].header.sourceChainSelector, + messages1[1].header.sequenceNumber, + messages1[1].header.messageId, + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertExecutionStateChangedEventLogs( + logs, + messages2[0].header.sourceChainSelector, + messages2[0].header.sequenceNumber, + messages2[0].header.messageId, + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ) + ); + } + + // Reverts + + function test_UnauthorizedTransmitter_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_offRamp.execute(reportContext, abi.encode(reports)); + } + + function test_NoConfig_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_offRamp.execute(reportContext, abi.encode(reports)); + } + + function test_NoConfigWithOtherConfigPresent_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_offRamp.execute(reportContext, abi.encode(reports)); + } + + function test_WrongConfigWithSigners_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + + s_configDigestExec = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.expectRevert(); + _execute(reports); + } + + function test_ZeroReports_Revert() public { + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](0); + + vm.expectRevert(OffRamp.EmptyReport.selector); + _execute(reports); + } + + function test_IncorrectArrayType_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + uint256[] memory wrongData = new uint256[](2); + wrongData[0] = 1; + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.execute(reportContext, abi.encode(wrongData)); + } + + function test_NonArray_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.execute(reportContext, abi.encode(report)); + } +} + +contract OffRamp_getExecutionState is OffRampSetup { + mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => Internal.MessageExecutionState state)) internal + s_differentialExecutionState; + + /// forge-config: default.fuzz.runs = 32 + /// forge-config: ccip.fuzz.runs = 32 + function test_Fuzz_Differential_Success( + uint64 sourceChainSelector, + uint16[500] memory seqNums, + uint8[500] memory values + ) public { + for (uint256 i = 0; i < seqNums.length; ++i) { + // Only use the first three slots. This makes sure existing slots get overwritten + // as the tests uses 500 sequence numbers. + uint16 seqNum = seqNums[i] % 386; + Internal.MessageExecutionState state = Internal.MessageExecutionState(values[i] % 4); + s_differentialExecutionState[sourceChainSelector][seqNum] = state; + s_offRamp.setExecutionStateHelper(sourceChainSelector, seqNum, state); + assertEq(uint256(state), uint256(s_offRamp.getExecutionState(sourceChainSelector, seqNum))); + } + + for (uint256 i = 0; i < seqNums.length; ++i) { + uint16 seqNum = seqNums[i] % 386; + Internal.MessageExecutionState expectedState = s_differentialExecutionState[sourceChainSelector][seqNum]; + assertEq(uint256(expectedState), uint256(s_offRamp.getExecutionState(sourceChainSelector, seqNum))); + } + } + + function test_GetExecutionState_Success() public { + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 1, Internal.MessageExecutionState.FAILURE); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (3 << 2)); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 1, Internal.MessageExecutionState.IN_PROGRESS); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2)); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 2, Internal.MessageExecutionState.FAILURE); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4)); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 127, Internal.MessageExecutionState.IN_PROGRESS); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 128, Internal.MessageExecutionState.SUCCESS); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); + + assertEq( + uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 0)) + ); + assertEq( + uint256(Internal.MessageExecutionState.IN_PROGRESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 1)) + ); + assertEq( + uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 2)) + ); + assertEq( + uint256(Internal.MessageExecutionState.IN_PROGRESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 127)) + ); + assertEq( + uint256(Internal.MessageExecutionState.SUCCESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 128)) + ); + } + + function test_GetDifferentChainExecutionState_Success() public { + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 127, Internal.MessageExecutionState.IN_PROGRESS); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 128, Internal.MessageExecutionState.SUCCESS); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 1), 0); + + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1 + 1, 127, Internal.MessageExecutionState.FAILURE); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), (3 << 254)); + assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 1), 0); + + assertEq( + uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 0)) + ); + assertEq( + uint256(Internal.MessageExecutionState.IN_PROGRESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 127)) + ); + assertEq( + uint256(Internal.MessageExecutionState.SUCCESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 128)) + ); + + assertEq( + uint256(Internal.MessageExecutionState.UNTOUCHED), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 0)) + ); + assertEq( + uint256(Internal.MessageExecutionState.FAILURE), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 127)) + ); + assertEq( + uint256(Internal.MessageExecutionState.UNTOUCHED), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 128)) + ); + } + + function test_FillExecutionState_Success() public { + for (uint64 i = 0; i < 384; ++i) { + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.FAILURE); + } + + for (uint64 i = 0; i < 384; ++i) { + assertEq( + uint256(Internal.MessageExecutionState.FAILURE), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, i)) + ); + } + + for (uint64 i = 0; i < 3; ++i) { + assertEq(type(uint256).max, s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, i)); + } + + for (uint64 i = 0; i < 384; ++i) { + s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.IN_PROGRESS); + } + + for (uint64 i = 0; i < 384; ++i) { + assertEq( + uint256(Internal.MessageExecutionState.IN_PROGRESS), + uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, i)) + ); + } + + for (uint64 i = 0; i < 3; ++i) { + // 0x555... == 0b101010101010..... + assertEq( + 0x5555555555555555555555555555555555555555555555555555555555555555, + s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, i) + ); + } + } +} + +contract OffRamp_trialExecute is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + } + + function test_trialExecute_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + IERC20 dstToken0 = IERC20(s_destTokens[0]); + uint256 startingBalance = dstToken0.balanceOf(message.receiver); + + (Internal.MessageExecutionState newState, bytes memory err) = + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); + assertEq("", err); + + // Check that the tokens were transferred + assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); + } + + function test_TokenHandlingErrorIsCaught_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; + + IERC20 dstToken0 = IERC20(s_destTokens[0]); + uint256 startingBalance = dstToken0.balanceOf(OWNER); + + bytes memory errorMessage = "Random token pool issue"; + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + s_maybeRevertingPool.setShouldRevert(errorMessage); + + (Internal.MessageExecutionState newState, bytes memory err) = + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); + + // Expect the balance to remain the same + assertEq(startingBalance, dstToken0.balanceOf(OWNER)); + } + + function test_RateLimitError_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; + + bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + s_maybeRevertingPool.setShouldRevert(errorMessage); + + (Internal.MessageExecutionState newState, bytes memory err) = + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); + } + + // TODO test actual pool exists but isn't compatible instead of just no pool + function test_TokenPoolIsNotAContract_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 10000; + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + // Happy path, pool is correct + (Internal.MessageExecutionState newState, bytes memory err) = + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + + assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); + assertEq("", err); + + // address 0 has no contract + assertEq(address(0).code.length, 0); + + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(address(0)), + destTokenAddress: address(0), + extraData: "", + amount: message.tokenAmounts[0].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); + + // Unhappy path, no revert but marked as failed. + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); + assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); + + address notAContract = makeAddr("not_a_contract"); + + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(address(0)), + destTokenAddress: notAContract, + extraData: "", + amount: message.tokenAmounts[0].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); + + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); + + assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); + assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); + } +} + +contract OffRamp_releaseOrMintSingleToken is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + } + + function test__releaseOrMintSingleToken_Success() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + vm.expectCall( + s_destPoolBySourceToken[token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: OWNER, + amount: amount, + localToken: s_destTokenBySourceToken[token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: tokenAmount.sourcePoolAddress, + sourcePoolData: tokenAmount.extraData, + offchainTokenData: offchainTokenData + }) + ) + ); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); + + assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); + } + + function test_releaseOrMintToken_InvalidDataLength_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + // Mock the call so returns 2 slots of data + vm.mockCall( + s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), abi.encode(0, 0) + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Internal.MAX_BALANCE_OF_RET_BYTES, 64)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + bytes memory revertData = "failed to balanceOf"; + + // Mock the call so returns 2 slots of data + vm.mockCallRevert( + s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + uint256 mockedStaticBalance = 50000; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + vm.mockCall( + s_destTokenBySourceToken[token], + abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), + abi.encode(mockedStaticBalance) + ); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.ReleaseOrMintBalanceMismatch.selector, amount, mockedStaticBalance, mockedStaticBalance + ) + ); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); + } + + function test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + uint256 mockedStaticBalance = 50000; + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + // This should make the call fail if it does not skip the check + vm.mockCall( + s_destTokenBySourceToken[token], + abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), + abi.encode(mockedStaticBalance) + ); + + s_offRamp.releaseOrMintSingleToken( + tokenAmount, abi.encode(OWNER), s_destPoolBySourceToken[token], SOURCE_CHAIN_SELECTOR, "" + ); + } + + function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { + uint256 amount = 123123; + address token = s_sourceTokens[0]; + address destToken = s_destTokenBySourceToken[token]; + vm.label(destToken, "destToken"); + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: destToken, + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + // Address(0) should always revert + address returnedPool = address(0); + + vm.mockCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), + abi.encode(returnedPool) + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); + + // A contract that doesn't support the interface should also revert + returnedPool = address(s_offRamp); + + vm.mockCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), + abi.encode(returnedPool) + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); + + s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); + } + + function test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() public { + address receiver = makeAddr("receiver"); + uint256 amount = 123123; + address token = s_sourceTokens[0]; + address destToken = s_destTokenBySourceToken[token]; + bytes memory originalSender = abi.encode(OWNER); + bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); + + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), + destTokenAddress: destToken, + extraData: "", + amount: amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + bytes memory revertData = "call reverted :o"; + + vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); + s_offRamp.releaseOrMintSingleToken( + tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + ); + } +} + +contract OffRamp_releaseOrMintTokens is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + } + + function test_releaseOrMintTokens_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + IERC20 dstToken1 = IERC20(s_destFeeToken); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + uint256 amount1 = 100; + srcTokenAmounts[0].amount = amount1; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + offchainTokenData[0] = abi.encode(0x12345678); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + vm.expectCall( + s_destPoolBySourceToken[srcTokenAmounts[0].token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: srcTokenAmounts[0].amount, + localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ) + ); + + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) + ); + + assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); + } + + function test_releaseOrMintTokens_WithGasOverride_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + IERC20 dstToken1 = IERC20(s_destFeeToken); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + uint256 amount1 = 100; + srcTokenAmounts[0].amount = amount1; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + offchainTokenData[0] = abi.encode(0x12345678); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + vm.expectCall( + s_destPoolBySourceToken[srcTokenAmounts[0].token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: srcTokenAmounts[0].amount, + localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ) + ); + + uint32[] memory gasOverrides = new uint32[](sourceTokenAmounts.length); + for (uint256 i = 0; i < gasOverrides.length; i++) { + gasOverrides[i] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; + } + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, gasOverrides + ); + + assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); + } + + function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + uint256 amount = 100; + uint256 destinationDenominationMultiplier = 1000; + srcTokenAmounts[1].amount = amount; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + address pool = s_destPoolBySourceToken[srcTokenAmounts[1].token]; + address destToken = s_destTokenBySourceToken[srcTokenAmounts[1].token]; + + MaybeRevertingBurnMintTokenPool(pool).setReleaseOrMintMultiplier(destinationDenominationMultiplier); + + Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) + ); + assertEq(destTokenAmounts[1].amount, amount * destinationDenominationMultiplier); + assertEq(destTokenAmounts[1].token, destToken); + } + + // Revert + + function test_TokenHandlingError_Reverts() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + + bytes memory unknownError = bytes("unknown error"); + s_maybeRevertingPool.setShouldRevert(unknownError); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, unknownError)); + + s_offRamp.releaseOrMintTokens( + _getDefaultSourceTokenData(srcTokenAmounts), + abi.encode(OWNER), + OWNER, + SOURCE_CHAIN_SELECTOR_1, + new bytes[](srcTokenAmounts.length), + new uint32[](0) + ); + } + + function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { + uint256 amount = 100; + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + srcTokenAmounts[0].amount = amount; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + vm.mockCall( + s_destPoolBySourceToken[srcTokenAmounts[0].token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ), + // Includes the amount twice, this will revert due to the return data being to long + abi.encode(amount, amount) + ); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64)); + + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) + ); + } + + function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { + // The offRamp is a contract, but not a pool + address fakePoolAddress = address(s_offRamp); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(fakePoolAddress), + destTokenAddress: address(s_offRamp), + extraData: "", + amount: 1, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) + ); + } + + function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + uint256 amount1 = 100; + srcTokenAmounts[0].amount = amount1; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + offchainTokenData[0] = abi.encode(0x12345678); + + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + vm.expectCall( + s_destPoolBySourceToken[srcTokenAmounts[0].token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: srcTokenAmounts[0].amount, + localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_3, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ) + ); + vm.expectRevert(); + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData, new uint32[](0) + ); + } + + /// forge-config: default.fuzz.runs = 32 + /// forge-config: ccip.fuzz.runs = 1024 + // Uint256 gives a good range of values to test, both inside and outside of the eth address space. + function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success( + address destPool + ) public { + // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C + // triggers some Create2Deployer and causes it to fail + vm.assume(destPool != 0x4e59b44847b379578588920cA78FbF26c0B4956C); + bytes memory unusedVar = abi.encode(makeAddr("unused")); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: unusedVar, + destTokenAddress: destPool, + extraData: unusedVar, + amount: 1, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + + try s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) + ) {} catch (bytes memory reason) { + // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp + assertTrue( + bytes4(reason) == OffRamp.TokenHandlingError.selector || bytes4(reason) == Internal.InvalidEVMAddress.selector + || bytes4(reason) == OffRamp.InvalidDataLength.selector + || bytes4(reason) == CallWithExactGas.NoContract.selector + || bytes4(reason) == OffRamp.NotACompatiblePool.selector, + "Expected TokenHandlingError or InvalidEVMAddress" + ); + + if (uint160(destPool) > type(uint160).max) { + assertEq(reason, abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(destPool))); + } + } + } +} + +contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { + function test_ApplyZeroUpdates_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + vm.recordLogs(); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + // No logs emitted + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + + assertEq(s_offRamp.getSourceChainSelectors().length, 0); + } + + function test_AddNewChain_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + OffRamp.SourceChainConfig memory expectedSourceChainConfig = + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); + + vm.expectEmit(); + emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); + } + + function test_ReplaceExistingChain_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].isEnabled = false; + OffRamp.SourceChainConfig memory expectedSourceChainConfig = + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: false, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); + + vm.recordLogs(); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + // No log emitted for chain selector added (only for setting the config) + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + + _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); + + uint256[] memory resultSourceChainSelectors = s_offRamp.getSourceChainSelectors(); + assertEq(resultSourceChainSelectors.length, 1); + } + + function test_AddMultipleChains_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 0), + isEnabled: true + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 1), + isEnabled: false + }); + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 2, + onRamp: abi.encode(ON_RAMP_ADDRESS_1, 2), + isEnabled: true + }); + + OffRamp.SourceChainConfig[] memory expectedSourceChainConfigs = new OffRamp.SourceChainConfig[](3); + for (uint256 i = 0; i < 3; ++i) { + expectedSourceChainConfigs[i] = OffRamp.SourceChainConfig({ + router: s_destRouter, + isEnabled: sourceChainConfigs[i].isEnabled, + minSeqNr: 1, + onRamp: abi.encode(ON_RAMP_ADDRESS_1, i) + }); + + vm.expectEmit(); + emit OffRamp.SourceChainSelectorAdded(sourceChainConfigs[i].sourceChainSelector); + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(sourceChainConfigs[i].sourceChainSelector, expectedSourceChainConfigs[i]); + } + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + for (uint256 i = 0; i < 3; ++i) { + _assertSourceChainConfigEquality( + s_offRamp.getSourceChainConfig(sourceChainConfigs[i].sourceChainSelector), expectedSourceChainConfigs[i] + ); + } + } + + function test_Fuzz_applySourceChainConfigUpdate_Success( + OffRamp.SourceChainConfigArgs memory sourceChainConfigArgs + ) public { + // Skip invalid inputs + vm.assume(sourceChainConfigArgs.sourceChainSelector != 0); + vm.assume(sourceChainConfigArgs.onRamp.length != 0); + vm.assume(address(sourceChainConfigArgs.router) != address(0)); + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + sourceChainConfigs[1] = sourceChainConfigArgs; + + // Handle cases when an update occurs + bool isNewChain = sourceChainConfigs[1].sourceChainSelector != SOURCE_CHAIN_SELECTOR_1; + if (!isNewChain) { + sourceChainConfigs[1].onRamp = sourceChainConfigs[0].onRamp; + } + + OffRamp.SourceChainConfig memory expectedSourceChainConfig = OffRamp.SourceChainConfig({ + router: sourceChainConfigArgs.router, + isEnabled: sourceChainConfigArgs.isEnabled, + minSeqNr: 1, + onRamp: sourceChainConfigArgs.onRamp + }); + + if (isNewChain) { + vm.expectEmit(); + emit OffRamp.SourceChainSelectorAdded(sourceChainConfigArgs.sourceChainSelector); + } + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet(sourceChainConfigArgs.sourceChainSelector, expectedSourceChainConfig); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + _assertSourceChainConfigEquality( + s_offRamp.getSourceChainConfig(sourceChainConfigArgs.sourceChainSelector), expectedSourceChainConfig + ); + } + + function test_ReplaceExistingChainOnRamp_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet( + SOURCE_CHAIN_SELECTOR_1, + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_2}) + ); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + + // Reverts + + function test_ZeroOnRampAddress_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: new bytes(0), + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = abi.encode(address(0)); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + + function test_RouterAddress_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: IRouter(address(0)), + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + + function test_ZeroSourceChainSelector_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: 0, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + + function test_InvalidOnRampUpdate_Revert() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "test #2" + }); + + _commit( + OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }), + s_latestSequenceNumber + ); + + vm.stopPrank(); + vm.startPrank(OWNER); + + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; + + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidOnRampUpdate.selector, SOURCE_CHAIN_SELECTOR_1)); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } +} + +contract OffRamp_commit is OffRampSetup { + uint64 internal s_maxInterval = 12; + + function setUp() public virtual override { + super.setUp(); + _setupMultipleOffRamps(); + + s_latestSequenceNumber = uint64(uint256(s_configDigestCommit)); + } + + function test_ReportAndPriceUpdate_Success() public { + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + vm.expectEmit(); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(s_maxInterval + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + } + + function test_ReportOnlyRootSuccess_gas() public { + uint64 max1 = 931; + bytes32 root = "Only a single root"; + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: max1, + merkleRoot: root + }); + + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(max1 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); + } + + function test_StaleReportWithRoot_Success() public { + uint64 maxSeq = 12; + uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: maxSeq, + merkleRoot: "stale report 1" + }); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + + commitReport.merkleRoots[0].minSeqNr = maxSeq + 1; + commitReport.merkleRoots[0].maxSeqNr = maxSeq * 2; + commitReport.merkleRoots[0].merkleRoot = "stale report 2"; + + vm.expectEmit(); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(maxSeq * 2 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); + } + + function test_OnlyTokenPriceUpdates_Success() public { + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + } + + function test_OnlyGasPriceUpdates_Success() public { + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + } + + function test_PriceSequenceNumberCleared_Success() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + _commit(commitReport, s_latestSequenceNumber); + + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + + vm.startPrank(OWNER); + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + // Execution plugin OCR config should not clear latest epoch and round + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + + // Commit plugin config should clear latest epoch & round + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); + + // The same sequence number can be reported again + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + + _commit(commitReport, s_latestSequenceNumber); + } + + function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { + uint64 maxSeq = 12; + uint224 tokenPrice1 = 4e18; + uint224 tokenPrice2 = 5e18; + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + + roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: maxSeq, + merkleRoot: "stale report" + }); + commitReport.priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); + commitReport.merkleRoots = roots; + + vm.expectEmit(); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); + + vm.expectEmit(); + emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); + + _commit(commitReport, s_latestSequenceNumber); + + assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); + assertEq(tokenPrice1, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); + assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); + } + + // Reverts + + function test_UnauthorizedTransmitter_Revert() public { + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = + [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_NoConfig_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_NoConfigWithOtherConfigPresent_Revert() public { + _redeployOffRampWithNoOCRConfigs(); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + s_offRamp.setOCR3Configs(ocrConfigs); + + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + vm.expectRevert(); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function test_FailedRMNVerification_Reverts() public { + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); + + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + vm.expectRevert(); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_Unhealthy_Revert() public { + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + }); + + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_InvalidRootRevert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 4, + merkleRoot: bytes32(0) + }); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert(OffRamp.InvalidRoot.selector); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_InvalidInterval_Revert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 2, + maxSeqNr: 2, + merkleRoot: bytes32(0) + }); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) + ); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_InvalidIntervalMinLargerThanMax_Revert() public { + s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 0, + merkleRoot: bytes32(0) + }); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) + ); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_ZeroEpochAndRound_Revert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert(OffRamp.StaleCommitReport.selector); + _commit(commitReport, 0); + } + + function test_OnlyPriceUpdateStaleReport_Revert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectEmit(); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + _commit(commitReport, s_latestSequenceNumber); + + vm.expectRevert(OffRamp.StaleCommitReport.selector); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_SourceChainNotEnabled_Revert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: 0, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root" + }); + + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, 0)); + _commit(commitReport, s_latestSequenceNumber); + } + + function test_RootAlreadyCommitted_Revert() public { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root" + }); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + + _commit(commitReport, s_latestSequenceNumber); + commitReport.merkleRoots[0].minSeqNr = 3; + commitReport.merkleRoots[0].maxSeqNr = 3; + + vm.expectRevert( + abi.encodeWithSelector(OffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot) + ); + _commit(commitReport, ++s_latestSequenceNumber); + } + + function test_CommitOnRampMismatch_Revert() public { + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CommitOnRampMismatch.selector, ON_RAMP_ADDRESS_2, ON_RAMP_ADDRESS_1)); + _commit(commitReport, s_latestSequenceNumber); + } + + function _constructCommitReport() internal view returns (OffRamp.CommitReport memory) { + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: s_maxInterval, + merkleRoot: "test #2" + }); + + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); + } +} + +contract OffRamp_afterOC3ConfigSet is OffRampSetup { + function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + new OffRamp.SourceChainConfigArgs[](0) + ); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert(OffRamp.SignatureVerificationDisabled.selector); + s_offRamp.setOCR3Configs(ocrConfigs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol new file mode 100644 index 0000000..a789bc2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; +import {ICommitStore} from "../../interfaces/ICommitStore.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; + +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {NonceManager} from "../../NonceManager.sol"; +import {Router} from "../../Router.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; +import {OffRamp} from "../../offRamp/OffRamp.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; +import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; +import {OffRampHelper} from "../helpers/OffRampHelper.sol"; +import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; +import {MultiOCR3BaseSetup} from "../ocr/MultiOCR3BaseSetup.t.sol"; +import {Vm} from "forge-std/Test.sol"; + +contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { + uint64 internal constant SOURCE_CHAIN_SELECTOR_1 = SOURCE_CHAIN_SELECTOR; + uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; + uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; + + bytes internal constant ON_RAMP_ADDRESS_1 = abi.encode(ON_RAMP_ADDRESS); + bytes internal constant ON_RAMP_ADDRESS_2 = abi.encode(0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4); + bytes internal constant ON_RAMP_ADDRESS_3 = abi.encode(0x71830C37Cb193e820de488Da111cfbFcC680a1b9); + + address internal constant BLESS_VOTE_ADDR = address(8888); + + IAny2EVMMessageReceiver internal s_receiver; + IAny2EVMMessageReceiver internal s_secondary_receiver; + MaybeRevertMessageReceiver internal s_reverting_receiver; + + MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; + + OffRampHelper internal s_offRamp; + MessageInterceptorHelper internal s_inboundMessageInterceptor; + NonceManager internal s_inboundNonceManager; + address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); + + bytes32 internal s_configDigestExec; + bytes32 internal s_configDigestCommit; + uint64 internal constant s_offchainConfigVersion = 3; + uint8 internal constant s_F = 1; + + uint64 internal s_latestSequenceNumber; + + IRMNRemote.Signature[] internal s_rmnSignatures; + + function setUp() public virtual override(FeeQuoterSetup, MultiOCR3BaseSetup) { + FeeQuoterSetup.setUp(); + MultiOCR3BaseSetup.setUp(); + + s_inboundMessageInterceptor = new MessageInterceptorHelper(); + s_receiver = new MaybeRevertMessageReceiver(false); + s_secondary_receiver = new MaybeRevertMessageReceiver(false); + s_reverting_receiver = new MaybeRevertMessageReceiver(true); + + s_maybeRevertingPool = MaybeRevertingBurnMintTokenPool(s_destPoolByToken[s_destTokens[1]]); + s_inboundNonceManager = new NonceManager(new address[](0)); + + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); + } + + function _deployOffRamp(IRMNRemote rmnRemote, NonceManager nonceManager) internal { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); + + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: rmnRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(nonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + sourceChainConfigs + ); + + s_configDigestExec = _getBasicConfigDigest(s_F, s_emptySigners, s_validTransmitters); + s_configDigestCommit = _getBasicConfigDigest(s_F, s_validSigners, s_validTransmitters); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](2); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Execution), + configDigest: s_configDigestExec, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_emptySigners, + transmitters: s_validTransmitters + }); + ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + s_offRamp.setDynamicConfig(_generateDynamicOffRampConfig(address(s_feeQuoter))); + s_offRamp.setOCR3Configs(ocrConfigs); + + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(s_offRamp); + NonceManager(nonceManager).applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = address(s_offRamp); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) + ); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: address(s_offRamp)}); + s_destRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); + } + + function _setupMultipleOffRamps() internal { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, + onRamp: ON_RAMP_ADDRESS_2, + isEnabled: false + }); + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, + onRamp: ON_RAMP_ADDRESS_3, + isEnabled: true + }); + _setupMultipleOffRampsFromConfigs(sourceChainConfigs); + } + + function _setupMultipleOffRampsFromConfigs( + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs + ) internal { + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2 * sourceChainConfigs.length); + + for (uint256 i = 0; i < sourceChainConfigs.length; ++i) { + uint64 sourceChainSelector = sourceChainConfigs[i].sourceChainSelector; + + offRampUpdates[2 * i] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(s_offRamp)}); + offRampUpdates[2 * i + 1] = Router.OffRamp({ + sourceChainSelector: sourceChainSelector, + offRamp: s_inboundNonceManager.getPreviousRamps(sourceChainSelector).prevOffRamp + }); + } + + s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + uint32 internal constant MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS = 200_000; + uint32 internal constant MAX_TOKEN_POOL_TRANSFER_GAS = 50_000; + + function _generateDynamicOffRampConfig( + address feeQuoter + ) internal pure returns (OffRamp.DynamicConfig memory) { + return OffRamp.DynamicConfig({ + permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, + feeQuoter: feeQuoter, + messageInterceptor: address(0) + }); + } + + function _convertToGeneralMessage( + Internal.Any2EVMRampMessage memory original + ) internal view returns (Client.Any2EVMMessage memory message) { + uint256 numberOfTokens = original.tokenAmounts.length; + Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); + + for (uint256 i = 0; i < numberOfTokens; ++i) { + Internal.Any2EVMTokenTransfer memory tokenAmount = original.tokenAmounts[i]; + + address destPoolAddress = tokenAmount.destTokenAddress; + TokenPool pool = TokenPool(destPoolAddress); + destTokenAmounts[i].token = address(pool.getToken()); + destTokenAmounts[i].amount = tokenAmount.amount; + } + + return Client.Any2EVMMessage({ + messageId: original.header.messageId, + sourceChainSelector: original.header.sourceChainSelector, + sender: abi.encode(original.sender), + data: original.data, + destTokenAmounts: destTokenAmounts + }); + } + + function _generateAny2EVMMessageNoTokens( + uint64 sourceChainSelector, + bytes memory onRamp, + uint64 sequenceNumber + ) internal view returns (Internal.Any2EVMRampMessage memory) { + return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, new Client.EVMTokenAmount[](0), false); + } + + function _generateAny2EVMMessageWithTokens( + uint64 sourceChainSelector, + bytes memory onRamp, + uint64 sequenceNumber, + uint256[] memory amounts + ) internal view returns (Internal.Any2EVMRampMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + tokenAmounts[i].amount = amounts[i]; + } + return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, tokenAmounts, false); + } + + function _generateAny2EVMMessage( + uint64 sourceChainSelector, + bytes memory onRamp, + uint64 sequenceNumber, + Client.EVMTokenAmount[] memory tokenAmounts, + bool allowOutOfOrderExecution + ) internal view returns (Internal.Any2EVMRampMessage memory) { + bytes memory data = abi.encode(0); + + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); + + // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], + extraData: "", + amount: tokenAmounts[i].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + } + + Internal.Any2EVMRampMessage memory message = Internal.Any2EVMRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: DEST_CHAIN_SELECTOR, + sequenceNumber: sequenceNumber, + nonce: allowOutOfOrderExecution ? 0 : sequenceNumber + }), + sender: abi.encode(OWNER), + data: data, + receiver: address(s_receiver), + tokenAmounts: any2EVMTokenTransfer, + gasLimit: GAS_LIMIT + }); + + message.header.messageId = _hashMessage(message, onRamp); + + return message; + } + + function _generateSingleBasicMessage( + uint64 sourceChainSelector, + bytes memory onRamp + ) internal view returns (Internal.Any2EVMRampMessage[] memory) { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageNoTokens(sourceChainSelector, onRamp, 1); + return messages; + } + + function _generateMessagesWithTokens( + uint64 sourceChainSelector, + bytes memory onRamp + ) internal view returns (Internal.Any2EVMRampMessage[] memory) { + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + tokenAmounts[0].amount = 1e18; + tokenAmounts[1].amount = 5e18; + messages[0] = _generateAny2EVMMessage(sourceChainSelector, onRamp, 1, tokenAmounts, false); + messages[1] = _generateAny2EVMMessage(sourceChainSelector, onRamp, 2, tokenAmounts, false); + + return messages; + } + + function _generateReportFromMessages( + uint64 sourceChainSelector, + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (Internal.ExecutionReport memory) { + bytes[][] memory offchainTokenData = new bytes[][](messages.length); + + for (uint256 i = 0; i < messages.length; ++i) { + offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); + } + + return Internal.ExecutionReport({ + sourceChainSelector: sourceChainSelector, + proofs: new bytes32[](0), + proofFlagBits: 2 ** 256 - 1, + messages: messages, + offchainTokenData: offchainTokenData + }); + } + + function _generateBatchReportFromMessages( + uint64 sourceChainSelector, + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (Internal.ExecutionReport[] memory) { + Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); + reports[0] = _generateReportFromMessages(sourceChainSelector, messages); + return reports; + } + + function _getGasLimitsFromMessages( + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (OffRamp.GasLimitOverride[] memory) { + OffRamp.GasLimitOverride[] memory gasLimits = new OffRamp.GasLimitOverride[](messages.length); + for (uint256 i = 0; i < messages.length; ++i) { + gasLimits[i].receiverExecutionGasLimit = messages[i].gasLimit; + } + + return gasLimits; + } + + function _assertSameConfig(OffRamp.DynamicConfig memory a, OffRamp.DynamicConfig memory b) public pure { + assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); + assertEq(a.messageInterceptor, b.messageInterceptor); + assertEq(a.feeQuoter, b.feeQuoter); + } + + function _assertSourceChainConfigEquality( + OffRamp.SourceChainConfig memory config1, + OffRamp.SourceChainConfig memory config2 + ) internal pure { + assertEq(config1.isEnabled, config2.isEnabled); + assertEq(config1.minSeqNr, config2.minSeqNr); + assertEq(config1.onRamp, config2.onRamp); + assertEq(address(config1.router), address(config2.router)); + } + + function _getDefaultSourceTokenData( + Client.EVMTokenAmount[] memory srcTokenAmounts + ) internal view returns (Internal.Any2EVMTokenTransfer[] memory) { + Internal.Any2EVMTokenTransfer[] memory sourceTokenData = new Internal.Any2EVMTokenTransfer[](srcTokenAmounts.length); + for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { + sourceTokenData[i] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[srcTokenAmounts[i].token], + extraData: "", + amount: srcTokenAmounts[i].amount, + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + } + return sourceTokenData; + } + + function _enableInboundMessageInterceptor() internal { + OffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); + s_offRamp.setDynamicConfig(dynamicConfig); + } + + function _redeployOffRampWithNoOCRConfigs() internal { + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + new OffRamp.SourceChainConfigArgs[](0) + ); + + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(s_offRamp); + s_inboundNonceManager.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + _setupMultipleOffRamps(); + + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = address(s_offRamp); + s_feeQuoter.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) + ); + } + + function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { + bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; + + (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = + _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); + + vm.startPrank(s_validTransmitters[0]); + s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); + } + + function _execute( + Internal.ExecutionReport[] memory reports + ) internal { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; + + vm.startPrank(s_validTransmitters[0]); + s_offRamp.execute(reportContext, abi.encode(reports)); + } + + function assertExecutionStateChangedEventLogs( + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData + ) public { + Vm.Log[] memory logs = vm.getRecordedLogs(); + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + if (logMessageId == messageId) { + assertEq(logSourceChainSelector, sourceChainSelector); + assertEq(logSequenceNumber, sequenceNumber); + assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); + assertEq(logState, uint8(state)); + assertEq(logReturnData, returnData); + } + } + } + } + + function assertExecutionStateChangedEventLogs( + Vm.Log[] memory logs, + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData + ) public pure { + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + if (logMessageId == messageId) { + assertEq(logSourceChainSelector, sourceChainSelector); + assertEq(logSequenceNumber, sequenceNumber); + assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); + assertEq(logState, uint8(state)); + assertEq(logReturnData, returnData); + } + } + } + } + + function _assertNoEmit( + bytes32 eventSelector + ) internal { + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; i++) { + assertTrue(logs[i].topics[0] != eventSelector); + } + } + + function _hashMessage( + Internal.Any2EVMRampMessage memory message, + bytes memory onRamp + ) internal pure returns (bytes32) { + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol new file mode 100644 index 0000000..3562a6f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -0,0 +1,1080 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import "./OnRampSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract OnRamp_constructor is OnRampSetup { + function test_Constructor_Success() public { + OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }); + OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, dynamicConfig); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + + _deployOnRamp(SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry)); + + OnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); + _assertStaticConfigsEqual(staticConfig, gotStaticConfig); + + OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); + _assertDynamicConfigsEqual(dynamicConfig, gotDynamicConfig); + + // Initial values + assertEq("OnRamp 1.6.0-dev", s_onRamp.typeAndVersion()); + assertEq(OWNER, s_onRamp.owner()); + assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); + assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + } + + function test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() public { + OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }); + + OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); + + // Creating a DestChainConfig and setting allowListEnabled : true + OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); + destChainConfigs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowListEnabled: true + }); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, dynamicConfig); + + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, true); + + OnRampHelper tempOnRamp = new OnRampHelper(staticConfig, dynamicConfig, destChainConfigs); + + // Sending a message and expecting revert as allowList is enabled with no address in allowlist + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, OWNER)); + tempOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: 0, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp = new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: IRMNRemote(address(0)), + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(0), + tokenAdminRegistry: address(s_tokenAdminRegistry) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } + + function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { + vm.expectRevert(OnRamp.InvalidConfig.selector); + new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: SOURCE_CHAIN_SELECTOR, + rmnRemote: s_mockRMNRemote, + nonceManager: address(s_outboundNonceManager), + tokenAdminRegistry: address(0) + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(IRouter(address(0))) + ); + } +} + +contract OnRamp_forwardFromRouter is OnRampSetup { + struct LegacyExtraArgs { + uint256 gasLimit; + bool strict; + } + + function setUp() public virtual override { + super.setUp(); + + address[] memory feeTokens = new address[](1); + feeTokens[0] = s_sourceTokens[1]; + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = OWNER; + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addAllowedList, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + + // Since we'll mostly be testing for valid calls from the router we'll + // mock all calls to be originating from the router and re-mock in + // tests that require failure. + vm.startPrank(address(s_sourceRouter)); + } + + function test_ForwardFromRouterSuccessCustomExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouter_Success_ConfigurableSourceRouter() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + // Change the source router for this lane + IRouter newRouter = IRouter(makeAddr("NEW ROUTER")); + vm.stopPrank(); + vm.prank(OWNER); + s_onRamp.applyDestChainConfigUpdates(_generateDestChainConfigArgs(newRouter)); + + // forward fails from wrong router + vm.prank(address(s_sourceRouter)); + vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + // forward succeeds from correct router + vm.prank(address(newRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterSuccessLegacyExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V1_TAG, LegacyExtraArgs({gasLimit: GAS_LIMIT * 2, strict: true})); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + // We expect the message to be emitted with strict = false. + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterSuccessEmptyExtraArgs() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = ""; + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + // We expect the message to be emitted with strict = false. + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouter_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterExtraArgsV2_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) + ); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) + ); + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_ShouldIncrementSeqNumAndNonce_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + for (uint64 i = 1; i < 4; ++i) { + uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + assertEq(nonceAfter, nonceBefore + 1); + assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); + } + } + + function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) + ); + + for (uint64 i = 1; i < 4; ++i) { + uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; + assertEq(nonceAfter, nonceBefore); + assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); + } + } + + function test_ShouldStoreLinkFees() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = 1234567890; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); + } + + function test_ShouldStoreNonLinkFees() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + + uint256 feeAmount = 1234567890; + IERC20(s_sourceTokens[1]).transferFrom(OWNER, address(s_onRamp), feeAmount); + + // Calculate conversion done by prices contract + uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; + uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; + uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; + uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, expectedJuels, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); + } + + // Make sure any valid sender, receiver and feeAmount can be handled. + // @TODO Temporarily setting lower fuzz run as 256 triggers snapshot gas off by 1 error. + // https://github.com/foundry-rs/foundry/issues/5689 + /// forge-dynamicConfig: default.fuzz.runs = 32 + /// forge-dynamicConfig: ccip.fuzz.runs = 32 + function test_Fuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { + // To avoid RouterMustSetOriginalSender + vm.assume(originalSender != address(0)); + vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); + feeTokenAmount = uint96(bound(feeTokenAmount, 0, MAX_MSG_FEES_JUELS)); + vm.stopPrank(); + + vm.startPrank(OWNER); + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = originalSender; + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addAllowedList, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + + vm.startPrank(address(s_sourceRouter)); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.receiver = abi.encode(receiver); + + // Make sure the tokens are in the contract + deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); + + Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent.header.sequenceNumber, expectedEvent); + + // Assert the message Id is correct + assertEq( + expectedEvent.header.messageId, + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) + ); + } + + function test_forwardFromRouter_WithInterception_Success() public { + _enableOutboundMessageInterceptor(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), false); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + // Reverts + + function test_Paused_Revert() public { + // We pause by disabling the whitelist + vm.stopPrank(); + vm.startPrank(OWNER); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); + } + + function test_InvalidExtraArgsTag_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = bytes("bad args"); + + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_Permissions_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); + } + + function test_OriginalSender_Revert() public { + vm.expectRevert(OnRamp.RouterMustSetOriginalSender.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); + } + + function test_UnAllowedOriginalSender_Revert() public { + vm.stopPrank(); + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, STRANGER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); + } + + function test_MessageInterceptionError_Revert() public { + _enableOutboundMessageInterceptor(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); + uint256 feeAmount = 1234567890; + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1e18; + message.tokenAmounts[0].token = s_sourceTokens[0]; + IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); + s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), true); + + vm.expectRevert( + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) + ); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + + function test_MultiCannotSendZeroTokens_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 0; + message.tokenAmounts[0].token = s_sourceTokens[0]; + vm.expectRevert(OnRamp.CannotSendZeroTokens.selector); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_UnsupportedToken_Revert() public { + address wrongToken = address(1); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].token = wrongToken; + message.tokenAmounts[0].amount = 1; + + // We need to set the price of this new token to be able to reach + // the proper revert point. This must be called by the owner. + vm.stopPrank(); + vm.startPrank(OWNER); + + Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(wrongToken, 1); + s_feeQuoter.updatePrices(priceUpdates); + + // Change back to the router + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, wrongToken)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_forwardFromRouter_UnsupportedToken_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1; + message.tokenAmounts[0].token = address(1); + + vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } + + function test_MesssageFeeTooHigh_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + vm.expectRevert( + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + ); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); + } + + function test_SourceTokenDataTooLarge_Revert() public { + address sourceETH = s_sourceTokens[1]; + vm.stopPrank(); + vm.startPrank(OWNER); + + MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( + BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) + ); + BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); + deal(address(sourceETH), address(newPool), type(uint256).max); + + // Add TokenPool to OnRamp + s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); + + // Allow chain in TokenPool + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destTokenPool), + remoteTokenAddress: abi.encode(s_destToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + newPool.applyChainUpdates(chainUpdates); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); + + // No data set, should succeed + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set max data length, should succeed + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES)); + + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set data to max length +1, should revert + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); + + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set token config to allow larger data + vm.startPrank(OWNER); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, + isEnabled: true + }); + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) + ); + + vm.startPrank(address(s_sourceRouter)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + // Set the token data larger than the configured token data, should revert + vm.startPrank(OWNER); + newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); + + vm.startPrank(address(s_sourceRouter)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + } +} + +contract OnRamp_getSupportedTokens is OnRampSetup { + function test_GetSupportedTokens_Revert() public { + vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); + s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); + } +} + +contract OnRamp_getFee is OnRampSetup { + using USDPriceWith18Decimals for uint224; + + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + assertEq(expectedFeeAmount, feeAmount); + } + } + + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + assertEq(expectedFeeAmount, feeAmount); + } + } + + function test_GetFeeOfZeroForTokenMessage_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + assertTrue(feeAmount > 0); + + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory tokenMults = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + tokenMults[0] = FeeQuoter.PremiumMultiplierWeiPerEthArgs({token: message.feeToken, premiumMultiplierWeiPerEth: 0}); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(tokenMults); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + destChainConfigArgs[0].destChainConfig.gasMultiplierWeiPerEth = 0; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + + assertEq(0, feeAmount); + } + + // Reverts + + function test_Unhealthy_Revert() public { + _setMockRMNChainCurse(DEST_CHAIN_SELECTOR, true); + vm.expectRevert(abi.encodeWithSelector(OnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); + s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); + } + + function test_EnforceOutOfOrder_Revert() public { + // Update dynamic config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Empty extraArgs to should revert since it enforceOutOfOrder is true. + message.extraArgs = ""; + + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + } + + function test_NotAFeeTokenButPricedToken_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, message.feeToken)); + + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + } +} + +contract OnRamp_setDynamicConfig is OnRampSetup { + function test_setDynamicConfig_Success() public { + OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: makeAddr("messageInterceptor"), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); + + vm.expectEmit(); + emit OnRamp.ConfigSet(staticConfig, newConfig); + + s_onRamp.setDynamicConfig(newConfig); + + OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); + assertEq(newConfig.feeQuoter, gotDynamicConfig.feeQuoter); + } + + // Reverts + + function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(0), + reentrancyGuardEntered: false, + feeAggregator: FEE_AGGREGATOR, + messageInterceptor: makeAddr("messageInterceptor"), + allowListAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); + + // Invalid price reg reverts. + newConfig.feeQuoter = address(0); + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: address(0), + allowListAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } + + function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + vm.startPrank(ADMIN); + vm.expectRevert("Only callable by owner"); + s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); + } + + function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: true, + messageInterceptor: makeAddr("messageInterceptor"), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } +} + +contract OnRamp_withdrawFeeTokens is OnRampSetup { + mapping(address => uint256) internal s_nopFees; + + function setUp() public virtual override { + super.setUp(); + + // Since we'll mostly be testing for valid calls from the router we'll + // mock all calls to be originating from the router and re-mock in + // tests that require failure. + vm.startPrank(address(s_sourceRouter)); + + uint256 feeAmount = 1234567890; + + // Send a bunch of messages, increasing the juels in the contract + for (uint256 i = 0; i < s_sourceFeeTokens.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceFeeTokens[i % s_sourceFeeTokens.length]; + uint256 newFeeTokenBalance = IERC20(message.feeToken).balanceOf(address(s_onRamp)) + feeAmount; + deal(message.feeToken, address(s_onRamp), newFeeTokenBalance); + s_nopFees[message.feeToken] = newFeeTokenBalance; + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + } + } + + function test_Fuzz_WithdrawFeeTokens_Success( + uint256[5] memory amounts + ) public { + vm.startPrank(OWNER); + address[] memory feeTokens = new address[](amounts.length); + for (uint256 i = 0; i < amounts.length; ++i) { + vm.assume(amounts[i] > 0); + feeTokens[i] = _deploySourceToken("", amounts[i], 18); + IERC20(feeTokens[i]).transfer(address(s_onRamp), amounts[i]); + } + + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + for (uint256 i = 0; i < feeTokens.length; ++i) { + vm.expectEmit(); + emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, feeTokens[i], amounts[i]); + } + + s_onRamp.withdrawFeeTokens(); + + for (uint256 i = 0; i < feeTokens.length; ++i) { + assertEq(IERC20(feeTokens[i]).balanceOf(FEE_AGGREGATOR), amounts[i]); + assertEq(IERC20(feeTokens[i]).balanceOf(address(s_onRamp)), 0); + } + } + + function test_WithdrawFeeTokens_Success() public { + vm.expectEmit(); + emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); + + s_onRamp.withdrawFeeTokens(); + + assertEq(IERC20(s_sourceFeeToken).balanceOf(FEE_AGGREGATOR), s_nopFees[s_sourceFeeToken]); + assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), 0); + } +} + +contract OnRamp_getTokenPool is OnRampSetup { + function test_GetTokenPool_Success() public view { + assertEq( + s_sourcePoolByToken[s_sourceTokens[0]], + address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) + ); + assertEq( + s_sourcePoolByToken[s_sourceTokens[1]], + address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[1]))) + ); + + address wrongToken = address(123); + address nonExistentPool = address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(wrongToken))); + + assertEq(address(0), nonExistentPool); + } +} + +contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { + function test_ApplyDestChainConfigUpdates_Success() external { + vm.stopPrank(); + vm.startPrank(OWNER); + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); + configArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + + // supports disabling a lane by setting a router to zero + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, IRouter(address(0)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(address(0), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + + // supports updating and adding lanes simultaneously + configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowListEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); + assertEq(address(9999), address(s_onRamp.getRouter(9999))); + + // handles empty list + uint256 numLogs = vm.getRecordedLogs().length; + configArgs = new OnRamp.DestChainConfigArgs[](0); + s_onRamp.applyDestChainConfigUpdates(configArgs); + assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made + } + + function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { + vm.stopPrank(); + vm.startPrank(OWNER); + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); + configArgs[0].destChainSelector = 0; // invalid + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidDestChainConfig.selector, 0)); + s_onRamp.applyDestChainConfigUpdates(configArgs); + } +} + +contract OnRamp_applyAllowListUpdates is OnRampSetup { + function test_applyAllowListUpdates_Success() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowListEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + (uint64 sequenceNumber, bool allowListEnabled, address router) = s_onRamp.getDestChainConfig(9999); + assertEq(sequenceNumber, 0); + assertEq(allowListEnabled, false); + assertEq(router, address(9999)); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + assertEq(4, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + + assertEq(addedAllowlistedSenders, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR)); + + address[] memory removedAllowlistedSenders = new address[](1); + removedAllowlistedSenders[0] = vm.addr(2); + + vm.expectEmit(); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: new address[](0), + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_2 = new OnRamp.AllowListConfigArgs[](1); + allowListConfigArgsItems_2[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_2); + assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + + addedAllowlistedSenders = new address[](2); + addedAllowlistedSenders[0] = vm.addr(5); + addedAllowlistedSenders[1] = vm.addr(6); + + removedAllowlistedSenders = new address[](2); + removedAllowlistedSenders[0] = vm.addr(1); + removedAllowlistedSenders[1] = vm.addr(3); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_3 = new OnRamp.AllowListConfigArgs[](1); + allowListConfigArgsItems_3[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_3); + assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + } + + function test_applyAllowListUpdates_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + router: s_sourceRouter, + allowListEnabled: false + }); + configArgs[1] = + OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + vm.startPrank(STRANGER); + vm.expectRevert(OnRamp.OnlyCallableByOwnerOrAllowlistAdmin.selector); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + + applyAllowListConfigArgsItems[0].addedAllowlistedSenders[0] = address(0); + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + vm.startPrank(OWNER); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + } + + function test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + address[] memory addedAllowlistedSenders = new address[](1); + addedAllowlistedSenders[0] = vm.addr(1); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: false, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol new file mode 100644 index 0000000..08b213c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRouter} from "../../interfaces/IRouter.sol"; + +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {NonceManager} from "../../NonceManager.sol"; +import {Router} from "../../Router.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {FeeQuoterFeeSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; +import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; +import {OnRampHelper} from "../helpers/OnRampHelper.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract OnRampSetup is FeeQuoterFeeSetup { + uint256 internal immutable i_tokenAmount0 = 9; + uint256 internal immutable i_tokenAmount1 = 7; + + bytes32 internal s_metadataHash; + + OnRampHelper internal s_onRamp; + MessageInterceptorHelper internal s_outboundMessageInterceptor; + address[] internal s_offRamps; + NonceManager internal s_outboundNonceManager; + + function setUp() public virtual override { + super.setUp(); + + s_outboundMessageInterceptor = new MessageInterceptorHelper(); + s_outboundNonceManager = new NonceManager(new address[](0)); + (s_onRamp, s_metadataHash) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) + ); + + s_offRamps = new address[](2); + s_offRamps[0] = address(10); + s_offRamps[1] = address(11); + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp)}); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[0]}); + offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[1]}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + + // Pre approve the first token so the gas estimates of the tests + // only cover actual gas usage from the ramps + IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 2 ** 128); + IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), 2 ** 128); + } + + function _generateTokenMessage() public view returns (Client.EVM2AnyMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + tokenAmounts[0].amount = i_tokenAmount0; + tokenAmounts[1].amount = i_tokenAmount1; + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + /// @dev a helper function to compose EVM2AnyRampMessage messages + /// @dev it is assumed that LINK is the payment token because feeTokenAmount == feeValueJuels + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + address originalSender + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + return _messageToEvent( + message, + seqNum, + nonce, + feeTokenAmount, // fee paid + feeTokenAmount, // conversion to jules is the same + originalSender + ); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + uint256 feeValueJuels, + address originalSender + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + return _messageToEvent( + message, + SOURCE_CHAIN_SELECTOR, + DEST_CHAIN_SELECTOR, + seqNum, + nonce, + feeTokenAmount, + feeValueJuels, + originalSender, + s_metadataHash, + s_tokenAdminRegistry + ); + } + + function _generateDynamicOnRampConfig( + address feeQuoter + ) internal pure returns (OnRamp.DynamicConfig memory) { + return OnRamp.DynamicConfig({ + feeQuoter: feeQuoter, + reentrancyGuardEntered: false, + messageInterceptor: address(0), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); + } + + // Slicing is only available for calldata. So we have to build a new bytes array. + function _removeFirst4Bytes( + bytes memory data + ) internal pure returns (bytes memory) { + bytes memory result = new bytes(data.length - 4); + for (uint256 i = 4; i < data.length; ++i) { + result[i - 4] = data[i]; + } + return result; + } + + function _generateDestChainConfigArgs( + IRouter router + ) internal pure returns (OnRamp.DestChainConfigArgs[] memory) { + OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); + destChainConfigs[0] = + OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: router, allowListEnabled: false}); + return destChainConfigs; + } + + function _deployOnRamp( + uint64 sourceChainSelector, + IRouter router, + address nonceManager, + address tokenAdminRegistry + ) internal returns (OnRampHelper, bytes32 metadataHash) { + OnRampHelper onRamp = new OnRampHelper( + OnRamp.StaticConfig({ + chainSelector: sourceChainSelector, + rmnRemote: s_mockRMNRemote, + nonceManager: nonceManager, + tokenAdminRegistry: tokenAdminRegistry + }), + _generateDynamicOnRampConfig(address(s_feeQuoter)), + _generateDestChainConfigArgs(router) + ); + + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(onRamp); + + NonceManager(nonceManager).applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + + return ( + onRamp, + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, address(onRamp))) + ); + } + + function _enableOutboundMessageInterceptor() internal { + (, address msgSender,) = vm.readCallers(); + + bool resetPrank = false; + + if (msgSender != OWNER) { + vm.stopPrank(); + vm.startPrank(OWNER); + resetPrank = true; + } + + OnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); + dynamicConfig.messageInterceptor = address(s_outboundMessageInterceptor); + s_onRamp.setDynamicConfig(dynamicConfig); + + if (resetPrank) { + vm.stopPrank(); + vm.startPrank(msgSender); + } + } + + function _assertStaticConfigsEqual(OnRamp.StaticConfig memory a, OnRamp.StaticConfig memory b) internal pure { + assertEq(a.chainSelector, b.chainSelector); + assertEq(address(a.rmnRemote), address(b.rmnRemote)); + assertEq(a.tokenAdminRegistry, b.tokenAdminRegistry); + } + + function _assertDynamicConfigsEqual(OnRamp.DynamicConfig memory a, OnRamp.DynamicConfig memory b) internal pure { + assertEq(a.feeQuoter, b.feeQuoter); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol new file mode 100644 index 0000000..b5967e7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {BurnFromMintTokenPool} from "../../pools/BurnFromMintTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {BurnMintSetup} from "./BurnMintSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnFromMintTokenPoolSetup is BurnMintSetup { + BurnFromMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(false, s_pool.getAllowListEnabled()); + assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); + assertEq("BurnFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); + } + + function test_PoolBurn_Success() public { + uint256 burnAmount = 20_000e18; + + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(burnAmount); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), address(0), burnAmount); + + vm.expectEmit(); + emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); + + bytes4 expectedSignature = bytes4(keccak256("burnFrom(address,uint256)")); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: burnAmount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); + } + + // Should not burn tokens if cursed. + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); + vm.startPrank(s_burnMintOnRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1, + localToken: address(s_burnMintERC677), + remoteChainSelector: wrongChainSelector, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol new file mode 100644 index 0000000..7bf0ce5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {RouterSetup} from "../router/RouterSetup.t.sol"; + +contract BurnMintSetup is RouterSetup { + BurnMintERC677 internal s_burnMintERC677; + address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); + address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); + + address internal s_remoteBurnMintPool = makeAddr("remote_burn_mint_pool"); + address internal s_remoteToken = makeAddr("remote_token"); + + function setUp() public virtual override { + RouterSetup.setUp(); + + s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 0); + } + + function _applyChainUpdates( + address pool + ) internal { + TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); + chains[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_remoteBurnMintPool), + remoteTokenAddress: abi.encode(s_remoteToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + BurnMintTokenPool(pool).applyChainUpdates(chains); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_burnMintOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_burnMintOffRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol new file mode 100644 index 0000000..8a6d047 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {BurnMintSetup} from "./BurnMintSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnMintTokenPoolSetup is BurnMintSetup { + BurnMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(false, s_pool.getAllowListEnabled()); + assertEq("BurnMintTokenPool 1.5.0", s_pool.typeAndVersion()); + } + + function test_PoolBurn_Success() public { + uint256 burnAmount = 20_000e18; + + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(burnAmount); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), address(0), burnAmount); + + vm.expectEmit(); + emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); + + bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, burnAmount)); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: burnAmount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); + } + + // Should not burn tokens if cursed. + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); + vm.startPrank(s_burnMintOnRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1, + remoteChainSelector: wrongChainSelector, + localToken: address(s_burnMintERC677) + }) + ); + } +} + +contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { + function test_PoolMint_Success() public { + uint256 amount = 1e19; + address receiver = makeAddr("receiver_address"); + + vm.startPrank(s_burnMintOffRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(0), receiver, amount); + + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: receiver, + amount: amount, + localToken: address(s_burnMintERC677), + remoteChainSelector: DEST_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_remoteBurnMintPool), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(s_burnMintERC677.balanceOf(receiver), amount); + } + + function test_PoolMintNotHealthy_Revert() public { + // Should not mint tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(OWNER); + vm.startPrank(s_burnMintOffRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_burnMintERC677), + remoteChainSelector: DEST_CHAIN_SELECTOR, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + + assertEq(s_burnMintERC677.balanceOf(OWNER), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1, + localToken: address(s_burnMintERC677), + remoteChainSelector: wrongChainSelector, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol new file mode 100644 index 0000000..92e8717 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {BurnWithFromMintTokenPool} from "../../pools/BurnWithFromMintTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {BurnMintSetup} from "./BurnMintSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { + BurnWithFromMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = + new BurnWithFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup { + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(false, s_pool.getAllowListEnabled()); + assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); + assertEq("BurnWithFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); + } + + function test_PoolBurn_Success() public { + uint256 burnAmount = 20_000e18; + + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(burnAmount); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), address(0), burnAmount); + + vm.expectEmit(); + emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); + + bytes4 expectedSignature = bytes4(keccak256("burn(address,uint256)")); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: burnAmount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); + } + + // Should not burn tokens if cursed. + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); + vm.startPrank(s_burnMintOnRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC677) + }) + ); + + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1, + localToken: address(s_burnMintERC677), + remoteChainSelector: wrongChainSelector, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol new file mode 100644 index 0000000..7342612 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol @@ -0,0 +1,886 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {IPoolV1} from "../../interfaces/IPool.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +import {TokenPool} from "../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + +contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { + function test_LockOrBurn_onLockReleaseMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + } + + function test_MintOrRelease_OnLockReleaseMechanism_Success() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e12; + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + + // Simulate the off-ramp forwarding tokens to the recipient on destination chain + // s_token.transfer(recipient, amount); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount - amount, + "Incorrect remaining liquidity in TokenPool" + ); + assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); + } + + function test_LockOrBurn_PrimaryMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + + vm.startPrank(OWNER); + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_MintOrRelease_incomingMessageWithPrimaryMechanism() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() public { + // Test Enabling the LR mechanism and sending an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = DEST_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + // Send an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() public { + test_MintOrRelease_OnLockReleaseMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = SOURCE_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(OWNER, OWNER, SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Test incoming on the primary mechanism after disable LR, simulating Circle's new support for CCTP on + // DEST_CHAIN_SELECTOR + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); + } + + function test_LockOrBurn_WhileMigrationPause_Revert() public { + // Create a fake migration proposal + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); + + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_ReleaseOrMint_WhileMigrationPause_Revert() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory sourcePoolDataLockRelease = abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + // Expect revert because the lane is paused and no incoming messages should be allowed + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourcePoolDataLockRelease, + offchainTokenData: "" + }) + ); + } + + function test_transferLiquidity_Success() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + vm.expectEmit(); + emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( + address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.owner(), + address(s_usdcTokenPoolTransferLiquidity), + "Ownership of the old pool should be transferred to the new pool" + ); + + assertEq( + s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + liquidityAmount, + "Tokens locked for dest chain doesn't match expected amount in storage" + ); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), + liquidityAmount, + "Liquidity amount of tokens should be new in new pool, but aren't" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + 0, + "Liquidity amount of tokens should be zero in old pool, but aren't" + ); + } + + function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + } +} + +contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { + function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + // Ensure that the tokens are properly locked + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + amount, + "Internal locked token accounting is incorrect" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" + ); + + // Impersonate the set circle address and execute the proposal + vm.startPrank(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); + + // Ensure the call to the burn function is properly + vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); + + s_usdcTokenPool.burnLockedUSDC(); + + // Assert that the tokens were actually burned + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); + + // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" + ); + + assertFalse( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" + ); + + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_cancelExistingCCTPMigrationProposal() public { + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "migration proposal should exist, but doesn't" + ); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + 0, + "migration proposal exists, but shouldn't after being cancelled" + ); + + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_burnLockedUSDC_invalidPermissions_Revert() public { + address CIRCLE = makeAddr("CIRCLE"); + + vm.startPrank(OWNER); + + // Set the circle migrator address for later, but don't start pranking as it yet + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); + + // Should fail because only Circle can call this function + s_usdcTokenPool.burnLockedUSDC(); + + vm.startPrank(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.ExistingMigrationProposal.selector)); + s_usdcTokenPool.burnLockedUSDC(); + } + + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + address randomAddr = makeAddr("RANDOM"); + + vm.startPrank(randomAddr); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } + + function test_cannotCancelANonExistentMigrationProposal() public { + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + + // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_unstickManualTxAfterMigration_destChain_Success() public { + address recipient = address(1234); + // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that + // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, + // which should tell it to use the lock-release mechanism with the tokens provided. + + // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as + // liquidity + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); + + // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message + // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released + // instead of minted since there's no attestation for us to use. + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the + // recipient + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + // which after a migration will mean all new messages. + + // The message should fail without an error because it failed to decode a non-existent attestation which would + // revert without an error + vm.expectRevert(); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_unstickManualTxAfterMigration_homeChain_Success() public { + address CIRCLE = makeAddr("CIRCLE"); + address recipient = address(1234); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking + // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 + + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + // I picked 3x the amount to be stuck so that we can have enough to release with a buffer + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); + + // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens + // stuck coming back from the destination, to the home chain. This way they can be released and not minted + // since there's no corresponding attestation to use for minting. + vm.startPrank(OWNER); + + // Exclude the tokens from being burned and check for the event + vm.expectEmit(); + emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); + + s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), + (amount * 3), + "Tokens locked minus ones excluded from the burn should be 2e6" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "1e6 tokens should be excluded from the burn" + ); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + vm.startPrank(CIRCLE); + + s_usdcTokenPool.burnLockedUSDC(); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "There should still be 1e6 tokens excluded from the burn" + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); + + // Now that the burn is successful, we can release the tokens that were excluded from the burn + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 0, + "All tokens should be released from the exclusion list" + ); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol new file mode 100644 index 0000000..eea7f2a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IPoolV1} from "../../interfaces/IPool.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; +import {RouterSetup} from "../router/RouterSetup.t.sol"; + +contract LockReleaseTokenPoolSetup is RouterSetup { + IERC20 internal s_token; + LockReleaseTokenPool internal s_lockReleaseTokenPool; + LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; + address[] internal s_allowedList; + + address internal s_allowedOnRamp = address(123); + address internal s_allowedOffRamp = address(234); + + address internal s_destPoolAddress = address(2736782345); + address internal s_sourcePoolAddress = address(53852352095); + + function setUp() public virtual override { + RouterSetup.setUp(); + s_token = new BurnMintERC677("LINK", "LNK", 18, 0); + deal(address(s_token), OWNER, type(uint256).max); + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); + + s_allowedList.push(USER_1); + s_allowedList.push(DUMMY_CONTRACT_ADDRESS); + s_lockReleaseTokenPoolWithAllowList = + new LockReleaseTokenPool(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destPoolAddress), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); + s_lockReleaseTokenPool.setRebalancer(OWNER); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } +} + +contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { + function test_SetRebalancer_Success() public { + assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); + s_lockReleaseTokenPool.setRebalancer(STRANGER); + assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); + } + + function test_SetRebalancer_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_lockReleaseTokenPool.setRebalancer(STRANGER); + } +} + +contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { + function test_Fuzz_LockOrBurnNoAllowList_Success( + uint256 amount + ) public { + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + vm.startPrank(s_allowedOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Success() public { + uint256 amount = 100; + vm.startPrank(s_allowedOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[1], + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Revert() public { + vm.startPrank(s_allowedOnRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: 100, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_PoolBurnRevertNotHealthy_Revert() public { + // Should not burn tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); + + vm.startPrank(s_allowedOnRamp); + vm.expectRevert(TokenPool.CursedByRMN.selector); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)), before); + } +} + +contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { + function setUp() public virtual override { + LockReleaseTokenPoolSetup.setUp(); + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_sourcePoolAddress), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); + } + + function test_ReleaseOrMint_Success() public { + vm.startPrank(s_allowedOffRamp); + + uint256 amount = 100; + deal(address(s_token), address(s_lockReleaseTokenPool), amount); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Released(s_allowedOffRamp, OWNER, amount); + + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { + // Since the owner already has tokens this would break the checks + vm.assume(recipient != OWNER); + vm.assume(recipient != address(0)); + vm.assume(recipient != address(s_token)); + + // Makes sure the pool always has enough funds + deal(address(s_token), address(s_lockReleaseTokenPool), amount); + vm.startPrank(s_allowedOffRamp); + + uint256 capacity = _getInboundRateLimiterConfig().capacity; + // Determine if we hit the rate limit or the txs should succeed. + if (amount > capacity) { + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) + ); + } else { + // Only rate limit if the amount is >0 + if (amount > 0) { + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + } + + vm.expectEmit(); + emit TokenPool.Released(s_allowedOffRamp, recipient, amount); + } + + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_ChainNotAllowed_Revert() public { + address notAllowedRemotePoolAddress = address(1); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(notAllowedRemotePoolAddress), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); + + vm.startPrank(s_allowedOffRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, SOURCE_CHAIN_SELECTOR)); + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_PoolMintNotHealthy_Revert() public { + // Should not mint tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_token.balanceOf(OWNER); + vm.startPrank(s_allowedOffRamp); + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + + assertEq(s_token.balanceOf(OWNER), before); + } +} + +contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { + function test_CanAcceptLiquidity_Success() public { + assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); + + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); + assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); + } +} + +contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { + function test_Fuzz_ProvideLiquidity_Success( + uint256 amount + ) public { + uint256 balancePre = s_token.balanceOf(OWNER); + s_token.approve(address(s_lockReleaseTokenPool), amount); + + s_lockReleaseTokenPool.provideLiquidity(amount); + + assertEq(s_token.balanceOf(OWNER), balancePre - amount); + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), amount); + } + + // Reverts + + function test_Unauthorized_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + + s_lockReleaseTokenPool.provideLiquidity(1); + } + + function test_Fuzz_ExceedsAllowance( + uint256 amount + ) public { + vm.assume(amount > 0); + vm.expectRevert("ERC20: insufficient allowance"); + s_lockReleaseTokenPool.provideLiquidity(amount); + } + + function test_LiquidityNotAccepted_Revert() public { + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); + + vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); + s_lockReleaseTokenPool.provideLiquidity(1); + } +} + +contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { + function test_Fuzz_WithdrawalLiquidity_Success( + uint256 amount + ) public { + uint256 balancePre = s_token.balanceOf(OWNER); + s_token.approve(address(s_lockReleaseTokenPool), amount); + s_lockReleaseTokenPool.provideLiquidity(amount); + + s_lockReleaseTokenPool.withdrawLiquidity(amount); + + assertEq(s_token.balanceOf(OWNER), balancePre); + } + + // Reverts + + function test_Unauthorized_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + + s_lockReleaseTokenPool.withdrawLiquidity(1); + } + + function test_InsufficientLiquidity_Revert() public { + uint256 maxUint256 = 2 ** 256 - 1; + s_token.approve(address(s_lockReleaseTokenPool), maxUint256); + s_lockReleaseTokenPool.provideLiquidity(maxUint256); + + vm.startPrank(address(s_lockReleaseTokenPool)); + s_token.transfer(OWNER, maxUint256); + vm.startPrank(OWNER); + + vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); + s_lockReleaseTokenPool.withdrawLiquidity(1); + } +} + +contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { + LockReleaseTokenPool internal s_oldLockReleaseTokenPool; + uint256 internal s_amount = 100000; + + function setUp() public virtual override { + super.setUp(); + + s_oldLockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); + + deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); + } + + function test_transferLiquidity_Success() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); + + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); + + vm.expectEmit(); + emit LockReleaseTokenPool.LiquidityTransferred(address(s_oldLockReleaseTokenPool), s_amount); + + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); + } + + function test_transferLiquidity_transferTooMuch_Revert() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); + + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); + + vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount + 1); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre); + } +} + +contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); + assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol new file mode 100644 index 0000000..766a487 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol @@ -0,0 +1,785 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../helpers/TokenPoolHelper.sol"; +import {RouterSetup} from "../router/RouterSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract TokenPoolSetup is RouterSetup { + IERC20 internal s_token; + TokenPoolHelper internal s_tokenPool; + + function setUp() public virtual override { + RouterSetup.setUp(); + s_token = new BurnMintERC677("LINK", "LNK", 18, 0); + deal(address(s_token), OWNER, type(uint256).max); + + s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + } +} + +contract TokenPool_constructor is TokenPoolSetup { + function test_immutableFields_Success() public view { + assertEq(address(s_token), address(s_tokenPool.getToken())); + assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); + assertEq(false, s_tokenPool.getAllowListEnabled()); + assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); + } + + // Reverts + function test_ZeroAddressNotAllowed_Revert() public { + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + + s_tokenPool = new TokenPoolHelper(IERC20(address(0)), new address[](0), address(s_mockRMN), address(s_sourceRouter)); + } +} + +contract TokenPool_getRemotePool is TokenPoolSetup { + function test_getRemotePool_Success() public { + uint64 chainSelector = 123124; + address remotePool = makeAddr("remotePool"); + address remoteToken = makeAddr("remoteToken"); + + // Zero indicates nothing is set + assertEq(0, s_tokenPool.getRemotePool(chainSelector).length); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(remotePool), + remoteTokenAddress: abi.encode(remoteToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdates); + + assertEq(remotePool, abi.decode(s_tokenPool.getRemotePool(chainSelector), (address))); + } +} + +contract TokenPool_setRemotePool is TokenPoolSetup { + function test_setRemotePool_Success() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address initialPool = makeAddr("remotePool"); + address remoteToken = makeAddr("remoteToken"); + // The new pool is a non-evm pool, as it doesn't fit in the normal 160 bits + bytes memory newPool = abi.encode(type(uint256).max); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(initialPool), + remoteTokenAddress: abi.encode(remoteToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdates); + + vm.expectEmit(); + emit TokenPool.RemotePoolSet(chainSelector, abi.encode(initialPool), newPool); + + s_tokenPool.setRemotePool(chainSelector, newPool); + + assertEq(keccak256(newPool), keccak256(s_tokenPool.getRemotePool(chainSelector))); + } + + // Reverts + + function test_setRemotePool_NonExistentChain_Reverts() public { + uint64 chainSelector = 123124; + bytes memory remotePool = abi.encode(makeAddr("remotePool")); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); + s_tokenPool.setRemotePool(chainSelector, remotePool); + } + + function test_setRemotePool_OnlyOwner_Reverts() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_tokenPool.setRemotePool(123124, abi.encode(makeAddr("remotePool"))); + } +} + +contract TokenPool_applyChainUpdates is TokenPoolSetup { + function assertState( + TokenPool.ChainUpdate[] memory chainUpdates + ) public view { + uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); + for (uint256 i = 0; i < chainUpdates.length; i++) { + assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i]); + } + + for (uint256 i = 0; i < chainUpdates.length; ++i) { + assertTrue(s_tokenPool.isSupportedChain(chainUpdates[i].remoteChainSelector)); + RateLimiter.TokenBucket memory bkt = + s_tokenPool.getCurrentOutboundRateLimiterState(chainUpdates[i].remoteChainSelector); + assertEq(bkt.capacity, chainUpdates[i].outboundRateLimiterConfig.capacity); + assertEq(bkt.rate, chainUpdates[i].outboundRateLimiterConfig.rate); + assertEq(bkt.isEnabled, chainUpdates[i].outboundRateLimiterConfig.isEnabled); + + bkt = s_tokenPool.getCurrentInboundRateLimiterState(chainUpdates[i].remoteChainSelector); + assertEq(bkt.capacity, chainUpdates[i].inboundRateLimiterConfig.capacity); + assertEq(bkt.rate, chainUpdates[i].inboundRateLimiterConfig.rate); + assertEq(bkt.isEnabled, chainUpdates[i].inboundRateLimiterConfig.isEnabled); + } + } + + function test_applyChainUpdates_Success() public { + RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); + RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); + RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); + RateLimiter.Config memory inboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e27, rate: 1e17}); + + // EVM chain, which uses the 160 bit evm address space + uint64 evmChainSelector = 1; + bytes memory evmRemotePool = abi.encode(makeAddr("evm_remote_pool")); + bytes memory evmRemoteToken = abi.encode(makeAddr("evm_remote_token")); + + // Non EVM chain, which uses the full 256 bits + uint64 nonEvmChainSelector = type(uint64).max; + bytes memory nonEvmRemotePool = abi.encode(keccak256("non_evm_remote_pool")); + bytes memory nonEvmRemoteToken = abi.encode(keccak256("non_evm_remote_token")); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: evmChainSelector, + remotePoolAddress: evmRemotePool, + remoteTokenAddress: evmRemoteToken, + allowed: true, + outboundRateLimiterConfig: outboundRateLimit1, + inboundRateLimiterConfig: inboundRateLimit1 + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: nonEvmChainSelector, + remotePoolAddress: nonEvmRemotePool, + remoteTokenAddress: nonEvmRemoteToken, + allowed: true, + outboundRateLimiterConfig: outboundRateLimit2, + inboundRateLimiterConfig: inboundRateLimit2 + }); + + // Assert configuration is applied + vm.expectEmit(); + emit TokenPool.ChainAdded( + chainUpdates[0].remoteChainSelector, + chainUpdates[0].remoteTokenAddress, + chainUpdates[0].outboundRateLimiterConfig, + chainUpdates[0].inboundRateLimiterConfig + ); + vm.expectEmit(); + emit TokenPool.ChainAdded( + chainUpdates[1].remoteChainSelector, + chainUpdates[1].remoteTokenAddress, + chainUpdates[1].outboundRateLimiterConfig, + chainUpdates[1].inboundRateLimiterConfig + ); + s_tokenPool.applyChainUpdates(chainUpdates); + // on1: rateLimit1, on2: rateLimit2, off1: rateLimit1, off2: rateLimit3 + assertState(chainUpdates); + + // Removing an non-existent chain should revert + TokenPool.ChainUpdate[] memory chainRemoves = new TokenPool.ChainUpdate[](1); + uint64 strangerChainSelector = 120938; + chainRemoves[0] = TokenPool.ChainUpdate({ + remoteChainSelector: strangerChainSelector, + remotePoolAddress: evmRemotePool, + remoteTokenAddress: evmRemoteToken, + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, strangerChainSelector)); + s_tokenPool.applyChainUpdates(chainRemoves); + // State remains + assertState(chainUpdates); + + // Can remove a chain + chainRemoves[0].remoteChainSelector = evmChainSelector; + + vm.expectEmit(); + emit TokenPool.ChainRemoved(chainRemoves[0].remoteChainSelector); + + s_tokenPool.applyChainUpdates(chainRemoves); + + // State updated, only chain 2 remains + TokenPool.ChainUpdate[] memory singleChainConfigured = new TokenPool.ChainUpdate[](1); + singleChainConfigured[0] = chainUpdates[1]; + assertState(singleChainConfigured); + + // Cannot reset already configured ramp + vm.expectRevert( + abi.encodeWithSelector(TokenPool.ChainAlreadyExists.selector, singleChainConfigured[0].remoteChainSelector) + ); + s_tokenPool.applyChainUpdates(singleChainConfigured); + } + + // Reverts + + function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_tokenPool.applyChainUpdates(new TokenPool.ChainUpdate[](0)); + } + + function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: "", + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) + }); + + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(2)), + remoteTokenAddress: "", + allowed: true, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) + }); + + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + s_tokenPool.applyChainUpdates(chainUpdates); + } + + function test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() public { + RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); + RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: outboundRateLimit, + inboundRateLimiterConfig: inboundRateLimit + }); + + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].allowed = false; + chainUpdates[0].outboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); + chainUpdates[0].inboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.DisabledNonZeroRateLimit.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + } + + function test_applyChainUpdates_NonExistentChain_Revert() public { + RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: outboundRateLimit, + inboundRateLimiterConfig: inboundRateLimit + }); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainUpdates[0].remoteChainSelector)); + s_tokenPool.applyChainUpdates(chainUpdates); + } + + function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}) + }); + + // Outbound + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.rate = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.capacity = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.capacity = 101; + + s_tokenPool.applyChainUpdates(chainUpdates); + + // Change the chain selector as adding the same one would revert + chainUpdates[0].remoteChainSelector = 2; + + // Inbound + + chainUpdates[0].inboundRateLimiterConfig.capacity = 0; + chainUpdates[0].inboundRateLimiterConfig.rate = 0; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.rate = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.capacity = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.capacity = 101; + + s_tokenPool.applyChainUpdates(chainUpdates); + } +} + +contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { + uint64 internal s_remoteChainSelector; + + function setUp() public virtual override { + TokenPoolSetup.setUp(); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + s_remoteChainSelector = 123124; + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: s_remoteChainSelector, + remotePoolAddress: abi.encode(address(2)), + remoteTokenAddress: abi.encode(address(3)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdates); + } + + function test_Fuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { + // Cap the lower bound to 4 so 4/2 is still >= 2 + vm.assume(capacity >= 4); + // Cap the lower bound to 2 so 2/2 is still >= 1 + rate = uint128(bound(rate, 2, capacity - 2)); + // Bucket updates only work on increasing time + newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); + vm.warp(newTime); + + uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; + uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; + + RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); + RateLimiter.Config memory newInboundConfig = + RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); + + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newOutboundConfig); + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newInboundConfig); + vm.expectEmit(); + emit TokenPool.ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); + + s_tokenPool.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); + + uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); + + RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector); + assertEq(bucket.capacity, newOutboundConfig.capacity); + assertEq(bucket.rate, newOutboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + + expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); + + bucket = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector); + assertEq(bucket.capacity, newInboundConfig.capacity); + assertEq(bucket.rate, newInboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + } + + // Reverts + + function test_OnlyOwnerOrRateLimitAdmin_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + s_tokenPool.setChainRateLimiterConfig( + s_remoteChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() + ); + } + + function test_NonExistentChain_Revert() public { + uint64 wrongChainSelector = 9084102894; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); + s_tokenPool.setChainRateLimiterConfig( + wrongChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() + ); + } +} + +contract LockRelease_setRateLimitAdmin is TokenPoolSetup { + function test_SetRateLimitAdmin_Success() public { + assertEq(address(0), s_tokenPool.getRateLimitAdmin()); + s_tokenPool.setRateLimitAdmin(OWNER); + assertEq(OWNER, s_tokenPool.getRateLimitAdmin()); + } + + // Reverts + + function test_SetRateLimitAdmin_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + s_tokenPool.setRateLimitAdmin(STRANGER); + } +} + +contract TokenPool_onlyOnRamp is TokenPoolSetup { + function test_onlyOnRamp_Success() public { + uint64 chainSelector = 13377; + address onRamp = makeAddr("onRamp"); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + vm.startPrank(onRamp); + + s_tokenPool.onlyOnRampModifier(chainSelector); + } + + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = 13377; + address onRamp = makeAddr("onRamp"); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOnRampModifier(chainSelector); + + vm.startPrank(OWNER); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + vm.startPrank(onRamp); + // Should succeed now that we've added the chain + s_tokenPool.onlyOnRampModifier(chainSelector); + + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(chainUpdate); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = 13377; + address onRamp = makeAddr("onRamp"); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, onRamp)); + + s_tokenPool.onlyOnRampModifier(chainSelector); + } +} + +contract TokenPool_onlyOffRamp is TokenPoolSetup { + function test_onlyOffRamp_Success() public { + uint64 chainSelector = 13377; + address offRamp = makeAddr("onRamp"); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); + + vm.startPrank(offRamp); + + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = 13377; + address offRamp = makeAddr("onRamp"); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + + vm.startPrank(OWNER); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); + + vm.startPrank(offRamp); + // Should succeed now that we've added the chain + s_tokenPool.onlyOffRampModifier(chainSelector); + + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(chainUpdate); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = 13377; + address offRamp = makeAddr("offRamp"); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, offRamp)); + + s_tokenPool.onlyOffRampModifier(chainSelector); + } +} + +contract TokenPoolWithAllowListSetup is TokenPoolSetup { + address[] internal s_allowedSenders; + + function setUp() public virtual override { + TokenPoolSetup.setUp(); + + s_allowedSenders.push(STRANGER); + s_allowedSenders.push(DUMMY_CONTRACT_ADDRESS); + + s_tokenPool = new TokenPoolHelper(s_token, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter)); + } +} + +contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { + function test_GetAllowListEnabled_Success() public view { + assertTrue(s_tokenPool.getAllowListEnabled()); + } +} + +contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { + function test_SetRouter_Success() public { + assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); + + address newRouter = makeAddr("newRouter"); + + vm.expectEmit(); + emit TokenPool.RouterUpdated(address(s_sourceRouter), newRouter); + + s_tokenPool.setRouter(newRouter); + + assertEq(newRouter, s_tokenPool.getRouter()); + } +} + +contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { + function test_GetAllowList_Success() public view { + address[] memory setAddresses = s_tokenPool.getAllowList(); + assertEq(2, setAddresses.length); + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + } +} + +contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { + function test_SetAllowList_Success() public { + address[] memory newAddresses = new address[](2); + newAddresses[0] = address(1); + newAddresses[1] = address(2); + + for (uint256 i = 0; i < 2; ++i) { + vm.expectEmit(); + emit TokenPool.AllowListAdd(newAddresses[i]); + } + + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + address[] memory setAddresses = s_tokenPool.getAllowList(); + + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + assertEq(address(1), setAddresses[2]); + assertEq(address(2), setAddresses[3]); + + // address(2) exists noop, add address(3), remove address(1) + newAddresses = new address[](2); + newAddresses[0] = address(2); + newAddresses[1] = address(3); + + address[] memory removeAddresses = new address[](1); + removeAddresses[0] = address(1); + + vm.expectEmit(); + emit TokenPool.AllowListRemove(address(1)); + + vm.expectEmit(); + emit TokenPool.AllowListAdd(address(3)); + + s_tokenPool.applyAllowListUpdates(removeAddresses, newAddresses); + setAddresses = s_tokenPool.getAllowList(); + + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + assertEq(address(2), setAddresses[2]); + assertEq(address(3), setAddresses[3]); + + // remove all from allowList + for (uint256 i = 0; i < setAddresses.length; ++i) { + vm.expectEmit(); + emit TokenPool.AllowListRemove(setAddresses[i]); + } + + s_tokenPool.applyAllowListUpdates(setAddresses, new address[](0)); + setAddresses = s_tokenPool.getAllowList(); + + assertEq(0, setAddresses.length); + } + + function test_SetAllowListSkipsZero_Success() public { + uint256 setAddressesLength = s_tokenPool.getAllowList().length; + + address[] memory newAddresses = new address[](1); + newAddresses[0] = address(0); + + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + address[] memory setAddresses = s_tokenPool.getAllowList(); + + assertEq(setAddresses.length, setAddressesLength); + } + + // Reverts + + function test_OnlyOwner_Revert() public { + vm.stopPrank(); + vm.expectRevert("Only callable by owner"); + address[] memory newAddresses = new address[](2); + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + } + + function test_AllowListNotEnabled_Revert() public { + s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert(TokenPool.AllowListNotEnabled.selector); + + s_tokenPool.applyAllowListUpdates(new address[](0), new address[](2)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol new file mode 100644 index 0000000..da5caba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol @@ -0,0 +1,702 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {IPoolV1} from "../../interfaces/IPool.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; +import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + USDCTokenPoolHelper internal s_usdcTokenPool; + USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + + s_allowedList.push(USER_1); + s_usdcTokenPoolWithAllowList = + new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + s_usdcTokenPoolWithAllowList.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + s_usdcTokenPoolWithAllowList.setDomains(domains); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + +contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { + // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. + function test_LockOrBurn_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + s_token.transfer(address(s_usdcTokenPool), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + function test_Fuzz_LockOrBurn_Success(bytes32 destinationReceiver, uint256 amount) public { + vm.assume(destinationReceiver != bytes32(0)); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + s_token.transfer(address(s_usdcTokenPool), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + destinationReceiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(destinationReceiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); + } + + function test_Fuzz_LockOrBurnWithAllowList_Success(bytes32 destinationReceiver, uint256 amount) public { + vm.assume(destinationReceiver != bytes32(0)); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + s_token.transfer(address(s_usdcTokenPoolWithAllowList), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPoolWithAllowList.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPoolWithAllowList), + destinationReceiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: abi.encodePacked(destinationReceiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); + } + + // Reverts + function test_UnknownDomain_Revert() public { + uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; + // We need to setup the wrong chainSelector so it reaches the domain check + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: wrongDomain, onRamp: s_routerAllowedOnRamp}); + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: wrongDomain, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + uint256 amount = 1000; + vm.startPrank(s_routerAllowedOnRamp); + deal(address(s_token), s_routerAllowedOnRamp, amount); + s_token.approve(address(s_usdcTokenPool), amount); + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.UnknownDomain.selector, wrongDomain)); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(address(0)), + amount: amount, + remoteChainSelector: wrongDomain, + localToken: address(s_token) + }) + ); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(address(0)), + amount: 0, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Revert() public { + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); + + s_usdcTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: abi.encodePacked(address(0)), + amount: 1000, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } +} + +contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { + // From https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/BurnMessage.sol#L57 + function _formatMessage( + uint32 _version, + bytes32 _burnToken, + bytes32 _mintRecipient, + uint256 _amount, + bytes32 _messageSender + ) internal pure returns (bytes memory) { + return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + } + + function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { + vm.assume(recipient != address(0) && recipient != address(s_token)); + amount = bound(amount, 0, _getInboundRateLimiterConfig().capacity); + + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: SOURCE_DOMAIN_IDENTIFIER, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 0x060606060606, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(uint160(recipient))), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(recipient))), + amount, + bytes32(uint256(uint160(OWNER))) + ) + }); + + bytes memory message = _generateUSDCMessage(usdcMessage); + bytes memory attestation = bytes("attestation bytes"); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode( + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) + ), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: message, attestation: attestation})); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + vm.expectEmit(); + emit TokenPool.Minted(s_routerAllowedOffRamp, recipient, amount); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, message, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_ReleaseOrMintRealTx_Success() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + // Reverts + function test_UnlockingUSDCFailed_Revert() public { + vm.startPrank(s_routerAllowedOffRamp); + s_mockUSDCTransmitter.setShouldSucceed(false); + + uint256 amount = 13255235235; + + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: SOURCE_DOMAIN_IDENTIFIER, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 0x060606060606, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(uint160(address(s_mockUSDC)))), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(OWNER))), + amount, + bytes32(uint256(uint160(OWNER))) + ) + }); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode( + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) + ), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = abi.encode( + USDCTokenPool.MessageAndAttestation({message: _generateUSDCMessage(usdcMessage), attestation: bytes("")}) + ); + + vm.expectRevert(USDCTokenPool.UnlockingUSDCFailed.selector); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_TokenMaxCapacityExceeded_Revert() public { + uint256 capacity = _getInboundRateLimiterConfig().capacity; + uint256 amount = 10 * capacity; + address recipient = address(1); + vm.startPrank(s_routerAllowedOffRamp); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: bytes(""), attestation: bytes("")})); + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } +} + +contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); + assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); + } +} + +contract USDCTokenPool_setDomains is USDCTokenPoolSetup { + mapping(uint64 destChainSelector => USDCTokenPool.Domain domain) private s_chainToDomain; + + // Setting lower fuzz run as 256 runs was causing differing gas results in snapshot. + /// forge-config: default.fuzz.runs = 32 + /// forge-config: ccip.fuzz.runs = 32 + function test_Fuzz_SetDomains_Success( + bytes32[5] calldata allowedCallers, + uint32[5] calldata domainIdentifiers, + uint64[5] calldata destChainSelectors + ) public { + uint256 numberOfDomains = allowedCallers.length; + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](numberOfDomains); + for (uint256 i = 0; i < numberOfDomains; ++i) { + vm.assume(allowedCallers[i] != bytes32(0) && domainIdentifiers[i] != 0 && destChainSelectors[i] != 0); + + domainUpdates[i] = USDCTokenPool.DomainUpdate({ + allowedCaller: allowedCallers[i], + domainIdentifier: domainIdentifiers[i], + destChainSelector: destChainSelectors[i], + enabled: true + }); + + s_chainToDomain[destChainSelectors[i]] = + USDCTokenPool.Domain({domainIdentifier: domainIdentifiers[i], allowedCaller: allowedCallers[i], enabled: true}); + } + + vm.expectEmit(); + emit USDCTokenPool.DomainsSet(domainUpdates); + + s_usdcTokenPool.setDomains(domainUpdates); + + for (uint256 i = 0; i < numberOfDomains; ++i) { + USDCTokenPool.Domain memory expected = s_chainToDomain[destChainSelectors[i]]; + USDCTokenPool.Domain memory got = s_usdcTokenPool.getDomain(destChainSelectors[i]); + assertEq(got.allowedCaller, expected.allowedCaller); + assertEq(got.domainIdentifier, expected.domainIdentifier); + } + } + + // Reverts + + function test_OnlyOwner_Revert() public { + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); + + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + + s_usdcTokenPool.setDomains(domainUpdates); + } + + function test_InvalidDomain_Revert() public { + bytes32 validCaller = bytes32(uint256(25)); + // Ensure valid domain works + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); + domainUpdates[0] = USDCTokenPool.DomainUpdate({ + allowedCaller: validCaller, + domainIdentifier: 0, // ensures 0 is valid, as this is eth mainnet + destChainSelector: 45690, + enabled: true + }); + + s_usdcTokenPool.setDomains(domainUpdates); + + // Make update invalid on allowedCaller + domainUpdates[0].allowedCaller = bytes32(0); + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); + + s_usdcTokenPool.setDomains(domainUpdates); + + // Make valid again + domainUpdates[0].allowedCaller = validCaller; + + // Make invalid on destChainSelector + domainUpdates[0].destChainSelector = 0; + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); + + s_usdcTokenPool.setDomains(domainUpdates); + } +} + +contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { + function test_Fuzz_ValidateMessage_Success(uint32 sourceDomain, uint64 nonce) public { + vm.pauseGasMetering(); + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: sourceDomain, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: nonce, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(299999)), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: bytes("") + }); + + bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + vm.resumeGasMetering(); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain}) + ); + } + + // Reverts + + function test_ValidateInvalidMessage_Revert() public { + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: 1553252, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 387289284924, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(92398429395823)), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: bytes("") + }); + + USDCTokenPool.SourceTokenDataPayload memory sourceTokenData = + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}); + + bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); + + uint32 expectedSourceDomain = usdcMessage.sourceDomain + 1; + + vm.expectRevert( + abi.encodeWithSelector(USDCTokenPool.InvalidSourceDomain.selector, expectedSourceDomain, usdcMessage.sourceDomain) + ); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: expectedSourceDomain}) + ); + + uint64 expectedNonce = usdcMessage.nonce + 1; + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidNonce.selector, expectedNonce, usdcMessage.nonce)); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, + USDCTokenPool.SourceTokenDataPayload({nonce: expectedNonce, sourceDomain: usdcMessage.sourceDomain}) + ); + + usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER + 1; + vm.expectRevert( + abi.encodeWithSelector( + USDCTokenPool.InvalidDestinationDomain.selector, DEST_DOMAIN_IDENTIFIER, usdcMessage.destinationDomain + ) + ); + + s_usdcTokenPool.validateMessage( + _generateUSDCMessage(usdcMessage), + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}) + ); + usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER; + + uint32 wrongVersion = usdcMessage.version + 1; + + usdcMessage.version = wrongVersion; + encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidMessageVersion.selector, wrongVersion)); + s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol new file mode 100644 index 0000000..a7d73cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -0,0 +1,1196 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; +import {BaseTest} from "../BaseTest.t.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; +import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; +import {stdError} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; + +contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { + MultiAggregateRateLimiterHelper internal s_rateLimiter; + + address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; + uint224 internal constant TOKEN_PRICE = 4e18; + + uint64 internal constant CHAIN_SELECTOR_1 = 5009297550715157269; + uint64 internal constant CHAIN_SELECTOR_2 = 4949039107694359620; + + RateLimiter.Config internal RATE_LIMITER_CONFIG_1 = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); + RateLimiter.Config internal RATE_LIMITER_CONFIG_2 = RateLimiter.Config({isEnabled: true, rate: 10, capacity: 200}); + + address internal immutable MOCK_OFFRAMP = address(1111); + address internal immutable MOCK_ONRAMP = address(1112); + + address[] internal s_authorizedCallers; + + function setUp() public virtual override(BaseTest, FeeQuoterSetup) { + BaseTest.setUp(); + FeeQuoterSetup.setUp(); + + Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); + s_feeQuoter.updatePrices(priceUpdates); + + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](4); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_2, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + configUpdates[2] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: true, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[3] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_2, + isOutboundLane: true, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + + s_authorizedCallers = new address[](2); + s_authorizedCallers[0] = MOCK_OFFRAMP; + s_authorizedCallers[1] = MOCK_ONRAMP; + + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), s_authorizedCallers); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + } + + function _assertConfigWithTokenBucketEquality( + RateLimiter.Config memory config, + RateLimiter.TokenBucket memory tokenBucket + ) internal pure { + assertEq(config.rate, tokenBucket.rate); + assertEq(config.capacity, tokenBucket.capacity); + assertEq(config.capacity, tokenBucket.tokens); + assertEq(config.isEnabled, tokenBucket.isEnabled); + } + + function _assertTokenBucketEquality( + RateLimiter.TokenBucket memory tokenBucketA, + RateLimiter.TokenBucket memory tokenBucketB + ) internal pure { + assertEq(tokenBucketA.rate, tokenBucketB.rate); + assertEq(tokenBucketA.capacity, tokenBucketB.capacity); + assertEq(tokenBucketA.tokens, tokenBucketB.tokens); + assertEq(tokenBucketA.isEnabled, tokenBucketB.isEnabled); + } + + function _generateAny2EVMMessage( + uint64 sourceChainSelector, + Client.EVMTokenAmount[] memory tokenAmounts + ) internal pure returns (Client.Any2EVMMessage memory) { + return Client.Any2EVMMessage({ + messageId: keccak256(bytes("messageId")), + sourceChainSelector: sourceChainSelector, + sender: abi.encode(OWNER), + data: abi.encode(0), + destTokenAmounts: tokenAmounts + }); + } + + function _generateAny2EVMMessageNoTokens( + uint64 sourceChainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { + return _generateAny2EVMMessage(sourceChainSelector, new Client.EVMTokenAmount[](0)); + } +} + +contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { + function test_ConstructorNoAuthorizedCallers_Success() public { + address[] memory authorizedCallers = new address[](0); + + vm.recordLogs(); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); + + // FeeQuoterSet + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + + assertEq(OWNER, s_rateLimiter.owner()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); + } + + function test_Constructor_Success() public { + address[] memory authorizedCallers = new address[](2); + authorizedCallers[0] = MOCK_OFFRAMP; + authorizedCallers[1] = MOCK_ONRAMP; + + vm.expectEmit(); + emit MultiAggregateRateLimiter.FeeQuoterSet(address(s_feeQuoter)); + + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); + + assertEq(OWNER, s_rateLimiter.owner()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); + assertEq(s_rateLimiter.typeAndVersion(), "MultiAggregateRateLimiter 1.6.0-dev"); + } +} + +contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { + function test_Owner_Success() public { + address newAddress = address(42); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.FeeQuoterSet(newAddress); + + s_rateLimiter.setFeeQuoter(newAddress); + assertEq(newAddress, s_rateLimiter.getFeeQuoter()); + } + + // Reverts + + function test_OnlyOwner_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(bytes("Only callable by owner")); + + s_rateLimiter.setFeeQuoter(STRANGER); + } + + function test_ZeroAddress_Revert() public { + vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); + s_rateLimiter.setFeeQuoter(address(0)); + } +} + +contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { + function test_GetTokenBucket_Success() public view { + RateLimiter.TokenBucket memory bucketInbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketInbound); + assertEq(BLOCK_TIME, bucketInbound.lastUpdated); + + RateLimiter.TokenBucket memory bucketOutbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketOutbound); + assertEq(BLOCK_TIME, bucketOutbound.lastUpdated); + } + + function test_Refill_Success() public { + RATE_LIMITER_CONFIG_1.capacity = RATE_LIMITER_CONFIG_1.capacity * 2; + + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + + assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); + assertEq(RATE_LIMITER_CONFIG_1.capacity / 2, bucket.tokens); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + uint256 warpTime = 4; + vm.warp(BLOCK_TIME + warpTime); + + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + + assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); + assertEq(RATE_LIMITER_CONFIG_1.capacity / 2 + warpTime * RATE_LIMITER_CONFIG_1.rate, bucket.tokens); + assertEq(BLOCK_TIME + warpTime, bucket.lastUpdated); + + vm.warp(BLOCK_TIME + warpTime * 100); + + // Bucket overflow + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); + } + + // Reverts + + function test_TimeUnderflow_Revert() public { + vm.warp(BLOCK_TIME - 1); + + vm.expectRevert(stdError.arithmeticError); + s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + } +} + +contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { + function test_ZeroConfigs_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_SingleConfig_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); + assertEq(BLOCK_TIME, bucket1.lastUpdated); + } + + function test_SingleConfigOutbound_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutboundLane: true, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].remoteChainSelector, true, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, true); + _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); + assertEq(BLOCK_TIME, bucket1.lastUpdated); + } + + function test_MultipleConfigs_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](5); + + for (uint64 i; i < configUpdates.length; ++i) { + configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + i + 1, + isOutboundLane: i % 2 == 0 ? false : true, + rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane, configUpdates[i].rateLimiterConfig + ); + } + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, configUpdates.length); + + for (uint256 i; i < configUpdates.length; ++i) { + RateLimiter.TokenBucket memory bucket = + s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane); + _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + } + + function test_MultipleConfigsBothLanes_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + + for (uint64 i; i < configUpdates.length; ++i) { + configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutboundLane: i % 2 == 0 ? false : true, + rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane, configUpdates[i].rateLimiterConfig + ); + } + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, configUpdates.length); + + for (uint256 i; i < configUpdates.length; ++i) { + RateLimiter.TokenBucket memory bucket = + s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane); + _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + } + + function test_UpdateExistingConfig_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + + // Capacity equals tokens + assertEq(bucket1.capacity, bucket1.tokens); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + vm.warp(BLOCK_TIME + 1); + bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + assertEq(BLOCK_TIME + 1, bucket1.lastUpdated); + + // Tokens < capacity since capacity doubled + assertTrue(bucket1.capacity != bucket1.tokens); + + // Outbound lane config remains unchanged + _assertConfigWithTokenBucketEquality( + RATE_LIMITER_CONFIG_1, s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true) + ); + } + + function test_UpdateExistingConfigWithNoDifference_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + RateLimiter.TokenBucket memory bucketPreUpdate = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + vm.warp(BLOCK_TIME + 1); + RateLimiter.TokenBucket memory bucketPostUpdate = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); + assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); + } + + // Reverts + function test_ZeroChainSelector_Revert() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: 0, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + vm.expectRevert(MultiAggregateRateLimiter.ZeroChainSelectorNotAllowed.selector); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + } + + function test_OnlyCallableByOwner_Revert() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + } +} + +contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSetup { + function test_GetTokenValue_Success() public view { + uint256 numberOfTokens = 10; + Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); + uint256 value = s_rateLimiter.getTokenValue(tokenAmount); + assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); + } + + // Reverts + function test_NoTokenPrice_Reverts() public { + address tokenWithNoPrice = makeAddr("Token with no price"); + Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); + + vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); + s_rateLimiter.getTokenValue(tokenAmount); + } +} + +contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLimiterSetup { + function setUp() public virtual override { + super.setUp(); + + // Clear rate limit tokens state + MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = + new MultiAggregateRateLimiter.LocalRateLimitToken[](s_sourceTokens.length); + for (uint256 i = 0; i < s_sourceTokens.length; ++i) { + removes[i] = MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[i] + }); + } + s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); + } + + function test_UpdateRateLimitTokensSingleChain_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[0] + }), + remoteToken: abi.encode(s_sourceTokens[0]) + }); + adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[1] + }), + remoteToken: abi.encode(s_sourceTokens[1]) + }); + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( + CHAIN_SELECTOR_1, adds[i].remoteToken, adds[i].localTokenArgs.localToken + ); + } + + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); + + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + + assertEq(localTokens.length, adds.length); + assertEq(localTokens.length, remoteTokens.length); + + for (uint256 i = 0; i < adds.length; ++i) { + assertEq(adds[i].remoteToken, remoteTokens[i]); + assertEq(adds[i].localTokenArgs.localToken, localTokens[i]); + } + } + + function test_UpdateRateLimitTokensMultipleChains_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[0] + }), + remoteToken: abi.encode(s_sourceTokens[0]) + }); + adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_2, + localToken: s_destTokens[1] + }), + remoteToken: abi.encode(s_sourceTokens[1]) + }); + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( + adds[i].localTokenArgs.remoteChainSelector, adds[i].remoteToken, adds[i].localTokenArgs.localToken + ); + } + + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); + + (address[] memory localTokensChain1, bytes[] memory remoteTokensChain1) = + s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + + assertEq(localTokensChain1.length, 1); + assertEq(localTokensChain1.length, remoteTokensChain1.length); + assertEq(localTokensChain1[0], adds[0].localTokenArgs.localToken); + assertEq(remoteTokensChain1[0], adds[0].remoteToken); + + (address[] memory localTokensChain2, bytes[] memory remoteTokensChain2) = + s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_2); + + assertEq(localTokensChain2.length, 1); + assertEq(localTokensChain2.length, remoteTokensChain2.length); + assertEq(localTokensChain2[0], adds[1].localTokenArgs.localToken); + assertEq(remoteTokensChain2[0], adds[1].remoteToken); + } + + function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[0] + }), + remoteToken: abi.encode(s_sourceTokens[0]) + }); + adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[1] + }), + remoteToken: abi.encode(s_sourceTokens[1]) + }); + + MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = + new MultiAggregateRateLimiter.LocalRateLimitToken[](1); + removes[0] = adds[0].localTokenArgs; + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( + CHAIN_SELECTOR_1, adds[i].remoteToken, adds[i].localTokenArgs.localToken + ); + } + + s_rateLimiter.updateRateLimitTokens(removes, adds); + + for (uint256 i = 0; i < removes.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitRemoved(CHAIN_SELECTOR_1, removes[i].localToken); + } + + s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); + + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + + assertEq(1, remoteTokens.length); + assertEq(adds[1].remoteToken, remoteTokens[0]); + + assertEq(1, localTokens.length); + assertEq(adds[1].localTokenArgs.localToken, localTokens[0]); + } + + function test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](0); + + MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = + new MultiAggregateRateLimiter.LocalRateLimitToken[](1); + removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[0] + }); + + vm.recordLogs(); + s_rateLimiter.updateRateLimitTokens(removes, adds); + + // No event since no remove occurred + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + + (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); + + assertEq(localTokens.length, 0); + assertEq(localTokens.length, remoteTokens.length); + } + + // Reverts + + function test_ZeroSourceToken_Revert() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); + adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[0] + }), + remoteToken: new bytes(0) + }); + + vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); + } + + function test_ZeroDestToken_Revert() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); + adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: address(0) + }), + remoteToken: abi.encode(s_destTokens[0]) + }); + + vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); + } + + function test_NonOwner_Revert() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](4); + + vm.startPrank(STRANGER); + + vm.expectRevert(bytes("Only callable by owner")); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); + } +} + +contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiterSetup { + address internal immutable MOCK_RECEIVER = address(1113); + + function setUp() public virtual override { + super.setUp(); + + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); + for (uint224 i = 0; i < s_sourceTokens.length; ++i) { + tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[i] + }), + remoteToken: abi.encode(s_sourceTokens[i]) + }); + + Internal.PriceUpdates memory priceUpdates = + _getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); + s_feeQuoter.updatePrices(priceUpdates); + } + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + } + + function test_ValidateMessageWithNoTokens_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + vm.recordLogs(); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + + // No consumed rate limit events + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_ValidateMessageWithTokens_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 3}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) + vm.expectEmit(); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageWithDisabledRateLimitToken_Success() public { + MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = + new MultiAggregateRateLimiter.LocalRateLimitToken[](1); + removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_destTokens[1] + }); + s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 5}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + vm.startPrank(MOCK_OFFRAMP); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageWithRateLimitDisabled_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[0].rateLimiterConfig.isEnabled = false; + + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 1000}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 50}); + + vm.startPrank(MOCK_OFFRAMP); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // No consumed rate limit events + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_ValidateMessageWithTokensOnDifferentChains_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); + for (uint224 i = 0; i < s_sourceTokens.length; ++i) { + tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_2, + localToken: s_destTokens[i] + }), + // Create a remote token address that is different from CHAIN_SELECTOR_1 + remoteToken: abi.encode(uint256(uint160(s_sourceTokens[i])) + type(uint160).max + 1) + }); + } + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 2}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) + uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Chain 1 changed + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 unchanged + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); + assertEq(bucketChain2.capacity, bucketChain2.tokens); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(totalValue); + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); + + // Chain 1 unchanged + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 changed + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); + assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); + } + + function test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); + + // Only 1 rate limited token on different chain + tokensToAdd[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_2, + localToken: s_destTokens[0] + }), + // Create a remote token address that is different from CHAIN_SELECTOR_1 + remoteToken: abi.encode(uint256(uint160(s_sourceTokens[0])) + type(uint160).max + 1) + }); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 3}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + // 3 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) + uint256 totalValue = (5 * TOKEN_PRICE) / 1e18; + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Chain 1 changed + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 unchanged + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); + assertEq(bucketChain2.capacity, bucketChain2.tokens); + + // 3 tokens * (TOKEN_PRICE) + uint256 totalValue2 = (3 * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(totalValue2); + + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); + + // Chain 1 unchanged + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 changed + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); + assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); + } + + function test_ValidateMessageWithRateLimitReset_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 20}); + + // Remaining capacity: 100 -> 20 + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) + vm.warp(BLOCK_TIME + 3); + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Remaining capacity: 35 -> 80 (can fit exactly 80) + vm.warp(BLOCK_TIME + 12); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + // Reverts + + function test_ValidateMessageWithRateLimitExceeded_Revert() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 80}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 30}); + + uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageFromUnauthorizedCaller_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + } +} + +contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimiterSetup { + function setUp() public virtual override { + super.setUp(); + + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); + for (uint224 i = 0; i < s_sourceTokens.length; ++i) { + tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_sourceTokens[i] + }), + remoteToken: abi.encode(bytes20(s_destTokenBySourceToken[s_sourceTokens[i]])) + }); + + Internal.PriceUpdates memory priceUpdates = + _getSingleTokenPriceUpdateStruct(s_sourceTokens[i], TOKEN_PRICE * (i + 1)); + s_feeQuoter.updatePrices(priceUpdates); + } + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + } + + function test_ValidateMessageWithNoTokens_Success() public { + vm.startPrank(MOCK_ONRAMP); + + vm.recordLogs(); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); + + // No consumed rate limit events + assertEq(vm.getRecordedLogs().length, 0); + } + + function test_onOutboundMessage_ValidateMessageWithTokens_Success() public { + vm.startPrank(MOCK_ONRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 3}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); + + // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) + vm.expectEmit(); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + } + + function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() public { + MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = + new MultiAggregateRateLimiter.LocalRateLimitToken[](1); + removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_1, + localToken: s_sourceTokens[1] + }); + s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 5}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); + + vm.startPrank(MOCK_ONRAMP); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + } + + function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutboundLane: true, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[0].rateLimiterConfig.isEnabled = false; + + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 1000}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 50}); + + vm.startPrank(MOCK_ONRAMP); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // No consumed rate limit events + assertEq(vm.getRecordedLogs().length, 0); + } + + function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); + for (uint224 i = 0; i < s_sourceTokens.length; ++i) { + tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_2, + localToken: s_sourceTokens[i] + }), + // Create a remote token address that is different from CHAIN_SELECTOR_1 + remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[i]])) + type(uint160).max + 1) + }); + } + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + + vm.startPrank(MOCK_ONRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 2}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); + + // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) + uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // Chain 1 changed + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 unchanged + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); + assertEq(bucketChain2.capacity, bucketChain2.tokens); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(totalValue); + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_2, _generateEVM2AnyMessage(tokenAmounts)); + + // Chain 1 unchanged + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 changed + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); + assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); + } + + function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { + MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); + + // Only 1 rate limited token on different chain + tokensToAdd[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ + localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ + remoteChainSelector: CHAIN_SELECTOR_2, + localToken: s_sourceTokens[0] + }), + // Create a remote token address that is different from CHAIN_SELECTOR_1 + remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[0]])) + type(uint160).max + 1) + }); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); + + vm.startPrank(MOCK_ONRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 3}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); + + // 3 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) + uint256 totalValue = (5 * TOKEN_PRICE) / 1e18; + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // Chain 1 changed + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 unchanged + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); + assertEq(bucketChain2.capacity, bucketChain2.tokens); + + // 3 tokens * (TOKEN_PRICE) + uint256 totalValue2 = (3 * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(totalValue2); + + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_2, _generateEVM2AnyMessage(tokenAmounts)); + + // Chain 1 unchanged + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 changed + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); + assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); + } + + function test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() public { + vm.startPrank(MOCK_ONRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 20}); + + // Remaining capacity: 100 -> 20 + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) + vm.warp(BLOCK_TIME + 3); + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + + // Remaining capacity: 35 -> 80 (can fit exactly 80) + vm.warp(BLOCK_TIME + 12); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + } + + function test_RateLimitValueDifferentLanes_Success() public { + vm.pauseGasMetering(); + // start from blocktime that does not equal rate limiter init timestamp + vm.warp(BLOCK_TIME + 1); + + // 10 (tokens) * 4 (price) * 2 (number of times) = 80 < 100 (capacity) + uint256 numberOfTokens = 10; + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: numberOfTokens}); + uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(value); + + vm.resumeGasMetering(); + vm.startPrank(MOCK_ONRAMP); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + vm.pauseGasMetering(); + + // Get the updated bucket status + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + + // Assert the proper value has been taken out of the bucket + assertEq(bucket1.capacity - value, bucket1.tokens); + // Inbound lane should remain unchanged + assertEq(bucket2.capacity, bucket2.tokens); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(value); + + vm.resumeGasMetering(); + s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + vm.pauseGasMetering(); + + bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + + // Inbound lane should remain unchanged + assertEq(bucket1.capacity - value, bucket1.tokens); + assertEq(bucket2.capacity - value, bucket2.tokens); + } + + // Reverts + + function test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 80}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 30}); + + uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); + } + + function test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); + s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); + } + + function _generateEVM2AnyMessage( + Client.EVMTokenAmount[] memory tokenAmounts + ) public view returns (Client.EVM2AnyMessage memory) { + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _generateEVM2AnyMessageNoTokens() internal view returns (Client.EVM2AnyMessage memory) { + return _generateEVM2AnyMessage(new Client.EVMTokenAmount[](0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol new file mode 100644 index 0000000..efcdfd8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMN} from "../../interfaces/IRMN.sol"; + +import {ARMProxy} from "../../rmn/ARMProxy.sol"; +import {MockRMN} from "../mocks/MockRMN.sol"; +import {Test} from "forge-std/Test.sol"; + +contract ARMProxyTest is Test { + MockRMN internal s_mockRMN; + ARMProxy internal s_armProxy; + + function setUp() public virtual { + s_mockRMN = new MockRMN(); + s_armProxy = new ARMProxy(address(s_mockRMN)); + } + + function test_ARMIsCursed_Success() public { + s_armProxy.setARM(address(s_mockRMN)); + assertFalse(IRMN(address(s_armProxy)).isCursed()); + s_mockRMN.setGlobalCursed(true); + assertTrue(IRMN(address(s_armProxy)).isCursed()); + } + + function test_ARMCallRevertReasonForwarded() public { + bytes memory err = bytes("revert"); + s_mockRMN.setIsCursedRevert(err); + s_armProxy.setARM(address(s_mockRMN)); + vm.expectRevert(abi.encodeWithSelector(MockRMN.CustomError.selector, err)); + IRMN(address(s_armProxy)).isCursed(); + } +} + +contract ARMProxyStandaloneTest is Test { + address internal constant EMPTY_ADDRESS = address(0x1); + address internal constant OWNER_ADDRESS = 0xC0ffeeEeC0fFeeeEc0ffeEeEc0ffEEEEC0FfEEee; + address internal constant MOCK_RMN_ADDRESS = 0x1337133713371337133713371337133713371337; + + ARMProxy internal s_armProxy; + + function setUp() public virtual { + // needed so that the extcodesize check in ARMProxy.fallback doesn't revert + vm.etch(MOCK_RMN_ADDRESS, bytes("fake bytecode")); + + vm.prank(OWNER_ADDRESS); + s_armProxy = new ARMProxy(MOCK_RMN_ADDRESS); + } + + function test_Constructor() public { + vm.expectEmit(); + emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); + ARMProxy proxy = new ARMProxy(MOCK_RMN_ADDRESS); + assertEq(proxy.getARM(), MOCK_RMN_ADDRESS); + } + + function test_SetARM() public { + vm.expectEmit(); + emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); + vm.prank(OWNER_ADDRESS); + s_armProxy.setARM(MOCK_RMN_ADDRESS); + assertEq(s_armProxy.getARM(), MOCK_RMN_ADDRESS); + } + + function test_SetARMzero() public { + vm.expectRevert(abi.encodeWithSelector(ARMProxy.ZeroAddressNotAllowed.selector)); + vm.prank(OWNER_ADDRESS); + s_armProxy.setARM(address(0x0)); + } + + function test_ARMCallEmptyContractRevert() public { + vm.prank(OWNER_ADDRESS); + s_armProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. + vm.expectRevert(); + bytes memory b = new bytes(0); + (bool success,) = address(s_armProxy).call(b); + success; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol new file mode 100644 index 0000000..c5226d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {RMNHome} from "../../rmn/RMNHome.sol"; +import {Test} from "forge-std/Test.sol"; +import {Vm} from "forge-std/Vm.sol"; + +contract RMNHomeTest is Test { + struct Config { + RMNHome.StaticConfig staticConfig; + RMNHome.DynamicConfig dynamicConfig; + } + + bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); + RMNHome public s_rmnHome = new RMNHome(); + + function _getBaseConfig() internal pure returns (Config memory) { + RMNHome.Node[] memory nodes = new RMNHome.Node[](3); + nodes[0] = RMNHome.Node({peerId: keccak256("peerId_0"), offchainPublicKey: keccak256("offchainPublicKey_0")}); + nodes[1] = RMNHome.Node({peerId: keccak256("peerId_1"), offchainPublicKey: keccak256("offchainPublicKey_1")}); + nodes[2] = RMNHome.Node({peerId: keccak256("peerId_2"), offchainPublicKey: keccak256("offchainPublicKey_2")}); + + RMNHome.SourceChain[] memory sourceChains = new RMNHome.SourceChain[](2); + // Observer 0 for source chain 9000 + sourceChains[0] = RMNHome.SourceChain({chainSelector: 9000, minObservers: 1, observerNodesBitmap: 1 << 0}); + // Observers 1 and 2 for source chain 9001 + sourceChains[1] = RMNHome.SourceChain({chainSelector: 9001, minObservers: 2, observerNodesBitmap: 1 << 1 | 1 << 2}); + + return Config({ + staticConfig: RMNHome.StaticConfig({nodes: nodes, offchainConfig: abi.encode("static_config")}), + dynamicConfig: RMNHome.DynamicConfig({sourceChains: sourceChains, offchainConfig: abi.encode("dynamic_config")}) + }); + } + + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 private constant PREFIX = 0x000b << (256 - 16); // 0x000b00..00 + + function _getConfigDigest(bytes memory staticConfig, uint32 version) internal view returns (bytes32) { + return bytes32( + (PREFIX & PREFIX_MASK) + | ( + uint256( + keccak256(bytes.concat(abi.encode(bytes32("EVM"), block.chainid, address(s_rmnHome), version), staticConfig)) + ) & ~PREFIX_MASK + ) + ); + } +} + +contract RMNHome_getConfigDigests is RMNHomeTest { + function test_getConfigDigests_success() public { + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, ZERO_DIGEST); + + Config memory config = _getBaseConfig(); + bytes32 firstDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, ZERO_DIGEST); + assertEq(candidateDigest, firstDigest); + + s_rmnHome.promoteCandidateAndRevokeActive(firstDigest, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, ZERO_DIGEST); + + bytes32 secondDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstDigest); + assertEq(candidateDigest, secondDigest); + + assertEq(activeDigest, s_rmnHome.getActiveDigest()); + assertEq(candidateDigest, s_rmnHome.getCandidateDigest()); + } +} + +contract RMNHome_setCandidate is RMNHomeTest { + function test_setCandidate_success() public { + Config memory config = _getBaseConfig(); + RMNHome.VersionedConfig memory versionedConfig = RMNHome.VersionedConfig({ + version: 1, + staticConfig: config.staticConfig, + dynamicConfig: config.dynamicConfig, + configDigest: ZERO_DIGEST + }); + + versionedConfig.configDigest = _getConfigDigest(abi.encode(versionedConfig.staticConfig), versionedConfig.version); + + vm.expectEmit(); + emit RMNHome.ConfigSet( + versionedConfig.configDigest, versionedConfig.version, versionedConfig.staticConfig, versionedConfig.dynamicConfig + ); + + s_rmnHome.setCandidate(versionedConfig.staticConfig, versionedConfig.dynamicConfig, ZERO_DIGEST); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(versionedConfig.configDigest); + assertTrue(ok); + assertEq(storedVersionedConfig.version, versionedConfig.version); + RMNHome.StaticConfig memory storedStaticConfig = storedVersionedConfig.staticConfig; + RMNHome.DynamicConfig memory storedDynamicConfig = storedVersionedConfig.dynamicConfig; + + assertEq(storedStaticConfig.nodes.length, versionedConfig.staticConfig.nodes.length); + for (uint256 i = 0; i < storedStaticConfig.nodes.length; i++) { + RMNHome.Node memory storedNode = storedStaticConfig.nodes[i]; + assertEq(storedNode.peerId, versionedConfig.staticConfig.nodes[i].peerId); + assertEq(storedNode.offchainPublicKey, versionedConfig.staticConfig.nodes[i].offchainPublicKey); + } + + assertEq(storedDynamicConfig.sourceChains.length, versionedConfig.dynamicConfig.sourceChains.length); + for (uint256 i = 0; i < storedDynamicConfig.sourceChains.length; i++) { + RMNHome.SourceChain memory storedSourceChain = storedDynamicConfig.sourceChains[i]; + assertEq(storedSourceChain.chainSelector, versionedConfig.dynamicConfig.sourceChains[i].chainSelector); + assertEq(storedSourceChain.minObservers, versionedConfig.dynamicConfig.sourceChains[i].minObservers); + assertEq(storedSourceChain.observerNodesBitmap, versionedConfig.dynamicConfig.sourceChains[i].observerNodesBitmap); + } + assertEq(storedDynamicConfig.offchainConfig, versionedConfig.dynamicConfig.offchainConfig); + assertEq(storedStaticConfig.offchainConfig, versionedConfig.staticConfig.offchainConfig); + } + + function test_setCandidate_ConfigDigestMismatch_reverts() public { + Config memory config = _getBaseConfig(); + + bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.CandidateConfigRevoked(digest); + + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, digest); + } + + function test_setCandidate_OnlyOwner_reverts() public { + Config memory config = _getBaseConfig(); + + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } +} + +contract RMNHome_revokeCandidate is RMNHomeTest { + // Sets two configs + function setUp() public { + Config memory config = _getBaseConfig(); + bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + s_rmnHome.promoteCandidateAndRevokeActive(digest, ZERO_DIGEST); + + config.dynamicConfig.sourceChains[0].minObservers--; + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_revokeCandidate_success() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + + vm.expectEmit(); + emit RMNHome.CandidateConfigRevoked(priorCandidateDigest); + + s_rmnHome.revokeCandidate(priorCandidateDigest); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(priorCandidateDigest); + assertFalse(ok); + // Ensure no old data is returned, even though it's still in storage + assertEq(storedVersionedConfig.version, 0); + assertEq(storedVersionedConfig.staticConfig.nodes.length, 0); + assertEq(storedVersionedConfig.dynamicConfig.sourceChains.length, 0); + + // Asser the active digest is unaffected but the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, ZERO_DIGEST); + assertTrue(candidateDigest != priorCandidateDigest); + } + + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { + (, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + + bytes32 wrongDigest = keccak256("wrong_digest"); + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); + s_rmnHome.revokeCandidate(wrongDigest); + } + + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { + vm.expectRevert(RMNHome.RevokingZeroDigestNotAllowed.selector); + s_rmnHome.revokeCandidate(ZERO_DIGEST); + } + + function test_revokeCandidate_OnlyOwner_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.revokeCandidate(keccak256("configDigest")); + } +} + +contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTest { + function test_promoteCandidateAndRevokeActive_success() public { + Config memory config = _getBaseConfig(); + bytes32 firstConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.ConfigPromoted(firstConfigToPromote); + + s_rmnHome.promoteCandidateAndRevokeActive(firstConfigToPromote, ZERO_DIGEST); + + // Assert the active digest is updated and the candidate digest is set to zero + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, firstConfigToPromote); + assertEq(candidateDigest, ZERO_DIGEST); + + // Set a new candidate to promote over a non-zero active config. + config.staticConfig.offchainConfig = abi.encode("new_static_config"); + config.dynamicConfig.offchainConfig = abi.encode("new_dynamic_config"); + bytes32 secondConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + + vm.expectEmit(); + emit RMNHome.ActiveConfigRevoked(firstConfigToPromote); + + vm.expectEmit(); + emit RMNHome.ConfigPromoted(secondConfigToPromote); + + s_rmnHome.promoteCandidateAndRevokeActive(secondConfigToPromote, firstConfigToPromote); + + (RMNHome.VersionedConfig memory activeConfig, RMNHome.VersionedConfig memory candidateConfig) = + s_rmnHome.getAllConfigs(); + assertEq(activeConfig.configDigest, secondConfigToPromote); + assertEq(activeConfig.staticConfig.offchainConfig, config.staticConfig.offchainConfig); + assertEq(activeConfig.dynamicConfig.offchainConfig, config.dynamicConfig.offchainConfig); + + assertEq(candidateConfig.configDigest, ZERO_DIGEST); + } + + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { + vm.expectRevert(RMNHome.NoOpStateTransitionNotAllowed.selector); + s_rmnHome.promoteCandidateAndRevokeActive(ZERO_DIGEST, ZERO_DIGEST); + } + + function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { + (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); + bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); + bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); + + vm.expectRevert( + abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) + ); + s_rmnHome.promoteCandidateAndRevokeActive(wrongCandidateDigest, wrongActiveDigest); + + vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest)); + + s_rmnHome.promoteCandidateAndRevokeActive(priorCandidateDigest, wrongActiveDigest); + } + + function test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() public { + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.promoteCandidateAndRevokeActive(keccak256("toPromote"), keccak256("ToRevoke")); + } +} + +contract RMNHome__validateStaticAndDynamicConfig is RMNHomeTest { + function test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes = new RMNHome.Node[](257); + + vm.expectRevert(RMNHome.OutOfBoundsNodesLength.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes[1].peerId = config.staticConfig.nodes[0].peerId; + + vm.expectRevert(RMNHome.DuplicatePeerId.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() public { + Config memory config = _getBaseConfig(); + config.staticConfig.nodes[1].offchainPublicKey = config.staticConfig.nodes[0].offchainPublicKey; + + vm.expectRevert(RMNHome.DuplicateOffchainPublicKey.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[1].chainSelector = config.dynamicConfig.sourceChains[0].chainSelector; + + vm.expectRevert(RMNHome.DuplicateSourceChain.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].observerNodesBitmap = 1 << config.staticConfig.nodes.length; + + vm.expectRevert(RMNHome.OutOfBoundsObserverNodeIndex.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_validateStaticAndDynamicConfig_MinObserversTooHigh_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers++; + + vm.expectRevert(RMNHome.MinObserversTooHigh.selector); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } +} + +contract RMNHome_setDynamicConfig is RMNHomeTest { + function setUp() public { + Config memory config = _getBaseConfig(); + s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); + } + + function test_setDynamicConfig_success() public { + (bytes32 priorActiveDigest,) = s_rmnHome.getConfigDigests(); + + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers--; + + (, bytes32 candidateConfigDigest) = s_rmnHome.getConfigDigests(); + + vm.expectEmit(); + emit RMNHome.DynamicConfigSet(candidateConfigDigest, config.dynamicConfig); + + s_rmnHome.setDynamicConfig(config.dynamicConfig, candidateConfigDigest); + + (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(candidateConfigDigest); + assertTrue(ok); + assertEq( + storedVersionedConfig.dynamicConfig.sourceChains[0].minObservers, + config.dynamicConfig.sourceChains[0].minObservers + ); + + // Asser the digests don't change when updating the dynamic config + (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); + assertEq(activeDigest, priorActiveDigest); + assertEq(candidateDigest, candidateConfigDigest); + } + + // Asserts the validation function is being called + function test_setDynamicConfig_MinObserversTooHigh_reverts() public { + Config memory config = _getBaseConfig(); + config.dynamicConfig.sourceChains[0].minObservers++; + + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); + s_rmnHome.setDynamicConfig(config.dynamicConfig, ZERO_DIGEST); + } + + function test_setDynamicConfig_DigestNotFound_reverts() public { + // Zero always reverts + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); + s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, ZERO_DIGEST); + + // Non-existent digest reverts + bytes32 nonExistentDigest = keccak256("nonExistentDigest"); + vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, nonExistentDigest)); + s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, nonExistentDigest); + } + + function test_setDynamicConfig_OnlyOwner_reverts() public { + Config memory config = _getBaseConfig(); + + vm.startPrank(address(0)); + + vm.expectRevert("Only callable by owner"); + s_rmnHome.setDynamicConfig(config.dynamicConfig, keccak256("configDigest")); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol new file mode 100644 index 0000000..5f46f85 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT, RMNRemote} from "../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_constructor is RMNRemoteSetup { + function test_constructor_success() public view { + assertEq(s_rmnRemote.getLocalChainSelector(), 1); + } + + function test_constructor_zeroChainSelector_reverts() public { + vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); + new RMNRemote(0); + } +} + +contract RMNRemote_setConfig is RMNRemoteSetup { + function test_setConfig_minSignersIs0_success() public { + // Initially there is no config, the version is 0 + uint32 currentConfigVersion = 0; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.minSigners, 0); + assertEq(version, currentConfigVersion); + + // A new config should increment the version + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + } + + function test_setConfig_addSigner_removeSigner_success() public { + uint32 currentConfigVersion = 0; + uint256 numSigners = s_signers.length; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + // add a signer + address newSigner = makeAddr("new signer"); + s_signers.push(RMNRemote.Signer({onchainPublicKey: newSigner, nodeIndex: uint64(numSigners)})); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(gotConfig.signers[numSigners].onchainPublicKey, newSigner); + assertEq(gotConfig.signers[numSigners].nodeIndex, uint64(numSigners)); + assertEq(version, currentConfigVersion); + + // remove two signers + s_signers.pop(); + s_signers.pop(); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (version, gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(version, currentConfigVersion); + } + + function test_setConfig_invalidSignerOrder_reverts() public { + s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectRevert(RMNRemote.InvalidSignerOrder.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_minSignersTooHigh_reverts() public { + RMNRemote.Config memory config = RMNRemote.Config({ + rmnHomeContractConfigDigest: _randomBytes32(), + signers: s_signers, + minSigners: uint64(s_signers.length + 1) + }); + + vm.expectRevert(RMNRemote.MinSignersTooHigh.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_duplicateOnChainPublicKey_reverts() public { + s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[0].addr, nodeIndex: uint64(s_signers.length)})); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectRevert(RMNRemote.DuplicateOnchainPublicKey.selector); + s_rmnRemote.setConfig(config); + } +} + +contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { + function test_verify_reverts() public { + Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); + IRMNRemote.Signature[] memory signatures = new IRMNRemote.Signature[](0); + + vm.expectRevert(RMNRemote.ConfigNotSet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, merkleRoots, signatures, 0); + } +} + +contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 2}); + s_rmnRemote.setConfig(config); + _generatePayloadAndSigs(2, 2); + } + + function test_verify_success() public view { + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_minSignersIsZero_success() public { + vm.stopPrank(); + vm.prank(OWNER); + s_rmnRemote.setConfig( + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}) + ); + + vm.stopPrank(); + vm.prank(OFF_RAMP_ADDRESS); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, new IRMNRemote.Signature[](0), s_v); + } + + function test_verify_InvalidSignature_reverts() public { + IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 1]; + sig.r = _randomBytes32(); + s_signatures.pop(); + s_signatures.push(sig); + + vm.expectRevert(RMNRemote.InvalidSignature.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_not_sorted_reverts() public { + IRMNRemote.Signature memory sig1 = s_signatures[s_signatures.length - 1]; + s_signatures.pop(); + IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 1]; + s_signatures.pop(); + s_signatures.push(sig1); + s_signatures.push(sig2); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { + IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 2]; + s_signatures.pop(); + s_signatures.push(sig); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_UnexpectedSigner_reverts() public { + _setupSigners(2); // create 2 new signers that aren't configured on RMNRemote + _generatePayloadAndSigs(2, 2); + + vm.expectRevert(RMNRemote.UnexpectedSigner.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_ThresholdNotMet_reverts() public { + _generatePayloadAndSigs(2, 1); // 1 sig requested, but 2 required + + vm.expectRevert(RMNRemote.ThresholdNotMet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } +} + +contract RMNRemote_curse is RMNRemoteSetup { + function test_curse_success() public { + vm.expectEmit(); + emit RMNRemote.Cursed(s_curseSubjects); + + s_rmnRemote.curse(s_curseSubjects); + + assertEq(abi.encode(s_rmnRemote.getCursedSubjects()), abi.encode(s_curseSubjects)); + assertTrue(s_rmnRemote.isCursed(curseSubj1)); + assertTrue(s_rmnRemote.isCursed(curseSubj2)); + // Should not have cursed a random subject + assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); + } + + function test_curse_AlreadyCursed_duplicateSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, curseSubj1)); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_curse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.curse(s_curseSubjects); + } +} + +contract RMNRemote_uncurse is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_uncurse_success() public { + vm.expectEmit(); + emit RMNRemote.Uncursed(s_curseSubjects); + + s_rmnRemote.uncurse(s_curseSubjects); + + assertEq(s_rmnRemote.getCursedSubjects().length, 0); + assertFalse(s_rmnRemote.isCursed(curseSubj1)); + assertFalse(s_rmnRemote.isCursed(curseSubj2)); + } + + function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, curseSubj1)); + s_rmnRemote.uncurse(s_curseSubjects); + } + + function test_uncurse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.uncurse(s_curseSubjects); + } +} + +contract RMNRemote_global_and_legacy_curses is RMNRemoteSetup { + function test_global_and_legacy_curses_success() public { + bytes16 randSubject = bytes16(keccak256("random subject")); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertTrue(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(LEGACY_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); // legacy curse doesn't affect specific subjects + + s_rmnRemote.uncurse(LEGACY_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol new file mode 100644 index 0000000..131dfec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {RMNRemote} from "../../rmn/RMNRemote.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import "forge-std/console.sol"; + +contract RMNRemoteSetup is BaseTest { + RMNRemote public s_rmnRemote; + address public OFF_RAMP_ADDRESS; + + RMNRemote.Signer[] public s_signers; + Vm.Wallet[] public s_signerWallets; + + Internal.MerkleRoot[] s_merkleRoots; + IRMNRemote.Signature[] s_signatures; + uint256 internal s_v; + + bytes16 internal constant curseSubj1 = bytes16(keccak256("subject 1")); + bytes16 internal constant curseSubj2 = bytes16(keccak256("subject 2")); + bytes16[] internal s_curseSubjects; + + function setUp() public virtual override { + super.setUp(); + s_rmnRemote = new RMNRemote(1); + OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); + s_curseSubjects = [curseSubj1, curseSubj2]; + + _setupSigners(10); + } + + /// @notice sets up a list of signers with strictly increasing onchain public keys + /// @dev signers do not have to be in order when configured, but they do when generating signatures + /// rather than sort signers every time, we do it once here and store the sorted list + function _setupSigners( + uint256 numSigners + ) internal { + // remove any existing config + while (s_signerWallets.length > 0) { + s_signerWallets.pop(); + } + while (s_signers.length > 0) { + s_signers.pop(); + } + + for (uint256 i = 0; i < numSigners; i++) { + s_signerWallets.push(vm.createWallet(_randomNum())); + } + + _sort(s_signerWallets); + + for (uint256 i = 0; i < numSigners; i++) { + s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[i].addr, nodeIndex: uint64(i)})); + } + } + + /// @notice generates n merkleRoots and matching valid signatures and populates them into + /// the shared storage vars + function _generatePayloadAndSigs(uint256 numUpdates, uint256 numSigs) internal { + require(numUpdates > 0, "need at least 1 dest lane update"); + require(numSigs <= s_signerWallets.length, "cannot generate more sigs than signers"); + + // remove any existing merkleRoots and sigs + while (s_merkleRoots.length > 0) { + s_merkleRoots.pop(); + } + while (s_signatures.length > 0) { + s_signatures.pop(); + } + s_v = 0; + + for (uint256 i = 0; i < numUpdates; i++) { + s_merkleRoots.push(_generateRandomDestLaneUpdate()); + } + + for (uint256 i = 0; i < numSigs; i++) { + (uint8 v, IRMNRemote.Signature memory sig) = _signDestLaneUpdate(s_merkleRoots, s_signerWallets[i]); + s_signatures.push(sig); + if (v == 28) { + s_v += 1 << i; + } + } + } + + /// @notice generates a random dest lane update + function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { + uint64 minSeqNum = uint32(_randomNum()); + uint64 maxSeqNum = minSeqNum + 100; + return Internal.MerkleRoot({ + sourceChainSelector: uint64(_randomNum()), + onRampAddress: abi.encode(_randomAddress()), + minSeqNr: minSeqNum, + maxSeqNr: maxSeqNum, + merkleRoot: _randomBytes32() + }); + } + + /// @notice signs the provided payload with the provided wallet + /// @return sigV v, either 27 of 28 + /// @return sig the signature + function _signDestLaneUpdate( + Internal.MerkleRoot[] memory merkleRoots, + Vm.Wallet memory wallet + ) private returns (uint8 sigV, IRMNRemote.Signature memory) { + (, RMNRemote.Config memory config) = s_rmnRemote.getVersionedConfig(); + bytes32 digest = keccak256( + abi.encode( + s_rmnRemote.getReportDigestHeader(), + RMNRemote.Report({ + destChainId: block.chainid, + destChainSelector: s_rmnRemote.getLocalChainSelector(), + rmnRemoteContractAddress: address(s_rmnRemote), + offrampAddress: OFF_RAMP_ADDRESS, + rmnHomeContractConfigDigest: config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet, digest); + return (v, IRMNRemote.Signature({r: r, s: s})); + } + + /// @notice bubble sort on a storage array of wallets + function _sort( + Vm.Wallet[] storage wallets + ) private { + bool swapped; + for (uint256 i = 1; i < wallets.length; i++) { + swapped = false; + for (uint256 j = 0; j < wallets.length - i; j++) { + Vm.Wallet memory next = wallets[j + 1]; + Vm.Wallet memory actual = wallets[j]; + if (next.addr < actual.addr) { + wallets[j] = next; + wallets[j + 1] = actual; + swapped = true; + } + } + if (!swapped) { + return; + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol new file mode 100644 index 0000000..e5e8ffd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol @@ -0,0 +1,819 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; +import {IRouter} from "../../interfaces/IRouter.sol"; +import {IRouterClient} from "../../interfaces/IRouterClient.sol"; +import {IWrappedNative} from "../../interfaces/IWrappedNative.sol"; + +import {Router} from "../../Router.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; +import {OffRampSetup} from "../offRamp/OffRampSetup.t.sol"; +import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; +import {RouterSetup} from "../router/RouterSetup.t.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract Router_constructor is OnRampSetup { + function test_Constructor_Success() public view { + assertEq("Router 1.2.0", s_sourceRouter.typeAndVersion()); + assertEq(OWNER, s_sourceRouter.owner()); + } +} + +contract Router_recoverTokens is OnRampSetup { + function test_RecoverTokens_Success() public { + // Assert we can recover sourceToken + IERC20 token = IERC20(s_sourceTokens[0]); + uint256 balanceBefore = token.balanceOf(OWNER); + token.transfer(address(s_sourceRouter), 1); + assertEq(token.balanceOf(address(s_sourceRouter)), 1); + s_sourceRouter.recoverTokens(address(token), OWNER, 1); + assertEq(token.balanceOf(address(s_sourceRouter)), 0); + assertEq(token.balanceOf(OWNER), balanceBefore); + + // Assert we can recover native + balanceBefore = OWNER.balance; + deal(address(s_sourceRouter), 10); + assertEq(address(s_sourceRouter).balance, 10); + s_sourceRouter.recoverTokens(address(0), OWNER, 10); + assertEq(OWNER.balance, balanceBefore + 10); + assertEq(address(s_sourceRouter).balance, 0); + } + + function test_RecoverTokensNonOwner_Revert() public { + // Reverts if not owner + vm.startPrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_sourceRouter.recoverTokens(address(0), STRANGER, 1); + } + + function test_RecoverTokensInvalidRecipient_Revert() public { + vm.expectRevert(abi.encodeWithSelector(Router.InvalidRecipientAddress.selector, address(0))); + s_sourceRouter.recoverTokens(address(0), address(0), 1); + } + + function test_RecoverTokensNoFunds_Revert() public { + // Reverts if no funds present + vm.expectRevert(); + s_sourceRouter.recoverTokens(address(0), OWNER, 10); + } + + function test_RecoverTokensValueReceiver_Revert() public { + MaybeRevertMessageReceiver revertingValueReceiver = new MaybeRevertMessageReceiver(true); + deal(address(s_sourceRouter), 10); + + // Value receiver reverts + vm.expectRevert(Router.FailedToSendValue.selector); + s_sourceRouter.recoverTokens(address(0), address(revertingValueReceiver), 10); + } +} + +contract Router_ccipSend is OnRampSetup { + event Burned(address indexed sender, uint256 amount); + + function test_CCIPSendLinkFeeOneTokenSuccess_gas() public { + vm.pauseGasMetering(); + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + IERC20 sourceToken1 = IERC20(s_sourceTokens[1]); + sourceToken1.approve(address(s_sourceRouter), 2 ** 64); + + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 2 ** 64; + message.tokenAmounts[0].token = s_sourceTokens[1]; + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 0); + + uint256 balanceBefore = sourceToken1.balanceOf(OWNER); + + // Assert that the tokens are burned + vm.expectEmit(); + emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); + + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); + + vm.resumeGasMetering(); + bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + vm.pauseGasMetering(); + + assertEq(msgEvent.header.messageId, messageId); + // Assert the user balance is lowered by the tokenAmounts sent and the fee amount + uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); + assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); + vm.resumeGasMetering(); + } + + function test_CCIPSendLinkFeeNoTokenSuccess_gas() public { + vm.pauseGasMetering(); + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 0); + + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); + + vm.resumeGasMetering(); + bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + vm.pauseGasMetering(); + + assertEq(msgEvent.header.messageId, messageId); + vm.resumeGasMetering(); + } + + function test_ccipSend_nativeFeeOneTokenSuccess_gas() public { + vm.pauseGasMetering(); + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + IERC20 sourceToken1 = IERC20(s_sourceTokens[1]); + sourceToken1.approve(address(s_sourceRouter), 2 ** 64); + + uint256 balanceBefore = sourceToken1.balanceOf(OWNER); + + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 2 ** 64; + message.tokenAmounts[0].token = s_sourceTokens[1]; + // Native fees will be wrapped so we need to calculate the event with + // the wrapped native feeCoin address. + message.feeToken = s_sourceRouter.getWrappedNative(); + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 0); + + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; + + message.feeToken = address(0); + // Assert that the tokens are burned + vm.expectEmit(); + emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); + + vm.resumeGasMetering(); + bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); + vm.pauseGasMetering(); + + assertEq(msgEvent.header.messageId, messageId); + // Assert the user balance is lowered by the tokenAmounts sent and the fee amount + uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); + assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); + vm.resumeGasMetering(); + } + + function test_ccipSend_nativeFeeNoTokenSuccess_gas() public { + vm.pauseGasMetering(); + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + // Native fees will be wrapped so we need to calculate the event with + // the wrapped native feeCoin address. + message.feeToken = s_sourceRouter.getWrappedNative(); + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 0); + + Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); + msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; + // Set it to address(0) to indicate native + message.feeToken = address(0); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); + + vm.resumeGasMetering(); + bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); + vm.pauseGasMetering(); + + assertEq(msgEvent.header.messageId, messageId); + // Assert the user balance is lowered by the tokenAmounts sent and the fee amount + vm.resumeGasMetering(); + } + + function test_NonLinkFeeToken_Success() public { + address[] memory feeTokens = new address[](1); + feeTokens[0] = s_sourceTokens[1]; + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), 2 ** 64); + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + } + + function test_NativeFeeToken_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = address(0); // Raw native + uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + vm.stopPrank(); + hoax(address(1), 100 ether); + s_sourceRouter.ccipSend{value: nativeQuote}(DEST_CHAIN_SELECTOR, message); + } + + function test_NativeFeeTokenOverpay_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = address(0); // Raw native + uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + vm.stopPrank(); + hoax(address(1), 100 ether); + s_sourceRouter.ccipSend{value: nativeQuote + 1}(DEST_CHAIN_SELECTOR, message); + // We expect the overpayment to be taken in full. + assertEq(address(1).balance, 100 ether - (nativeQuote + 1)); + assertEq(address(s_sourceRouter).balance, 0); + } + + function test_WrappedNativeFeeToken_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceRouter.getWrappedNative(); + uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + vm.stopPrank(); + hoax(address(1), 100 ether); + // Now address(1) has nativeQuote wrapped. + IWrappedNative(s_sourceRouter.getWrappedNative()).deposit{value: nativeQuote}(); + IWrappedNative(s_sourceRouter.getWrappedNative()).approve(address(s_sourceRouter), nativeQuote); + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + } + + // Reverts + + function test_WhenNotHealthy_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + s_mockRMN.setGlobalCursed(true); + vm.expectRevert(Router.BadARMSignal.selector); + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + } + + function test_UnsupportedDestinationChain_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 wrongChain = DEST_CHAIN_SELECTOR + 1; + + vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, wrongChain)); + + s_sourceRouter.ccipSend(wrongChain, message); + } + + function test_FeeTokenAmountTooLow_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 0); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + } + + function test_InvalidMsgValue() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Non-empty feeToken but with msg.value should revert + vm.stopPrank(); + hoax(address(1), 1); + vm.expectRevert(IRouterClient.InvalidMsgValue.selector); + s_sourceRouter.ccipSend{value: 1}(DEST_CHAIN_SELECTOR, message); + } + + function test_NativeFeeTokenZeroValue() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = address(0); // Raw native + // Include no value, should revert + vm.expectRevert(); + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); + } + + function test_NativeFeeTokenInsufficientValue() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = address(0); // Raw native + // Include insufficient, should also revert + vm.stopPrank(); + + hoax(address(1), 1); + vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); + s_sourceRouter.ccipSend{value: 1}(DEST_CHAIN_SELECTOR, message); + } +} + +contract Router_getArmProxy is RouterSetup { + function test_getArmProxy() public view { + assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMN)); + } +} + +contract Router_applyRampUpdates is RouterSetup { + MaybeRevertMessageReceiver internal s_receiver; + + function setUp() public virtual override(RouterSetup) { + super.setUp(); + s_receiver = new MaybeRevertMessageReceiver(false); + } + + function _assertOffRampRouteSucceeds( + Router.OffRamp memory offRamp + ) internal { + vm.startPrank(offRamp.offRamp); + + Client.Any2EVMMessage memory message = _generateReceiverMessage(offRamp.sourceChainSelector); + vm.expectCall(address(s_receiver), abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)); + s_sourceRouter.routeMessage(message, GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver)); + } + + function _assertOffRampRouteReverts( + Router.OffRamp memory offRamp + ) internal { + vm.startPrank(offRamp.offRamp); + + vm.expectRevert(IRouter.OnlyOffRamp.selector); + s_sourceRouter.routeMessage( + _generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + ); + } + + function test_Fuzz_OffRampUpdates( + address[20] memory offRampsInput + ) public { + Router.OffRamp[] memory offRamps = new Router.OffRamp[](20); + + for (uint256 i = 0; i < offRampsInput.length; ++i) { + offRamps[i] = Router.OffRamp({sourceChainSelector: uint64(i), offRamp: offRampsInput[i]}); + } + + // Test adding offRamps + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRamps); + + // There is no uniqueness guarantee on fuzz input, offRamps will not emit in case of a duplicate, + // hence cannot assert on number of offRamps event emissions, we need to use isOffRa + for (uint256 i = 0; i < offRamps.length; ++i) { + assertTrue(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); + } + + // Test removing offRamps + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), s_sourceRouter.getOffRamps(), new Router.OffRamp[](0)); + + assertEq(0, s_sourceRouter.getOffRamps().length); + for (uint256 i = 0; i < offRamps.length; ++i) { + assertFalse(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); + } + + // Testing removing and adding in same call + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRamps); + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), offRamps, offRamps); + for (uint256 i = 0; i < offRamps.length; ++i) { + assertTrue(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); + } + } + + function test_OffRampUpdatesWithRouting() public { + // Explicitly construct chain selectors and ramp addresses so we have ramp uniqueness for the various test scenarios. + uint256 numberOfSelectors = 10; + uint64[] memory sourceChainSelectors = new uint64[](numberOfSelectors); + for (uint256 i = 0; i < numberOfSelectors; ++i) { + sourceChainSelectors[i] = uint64(i); + } + + uint256 numberOfOffRamps = 5; + address[] memory offRamps = new address[](numberOfOffRamps); + for (uint256 i = 0; i < numberOfOffRamps; ++i) { + offRamps[i] = address(uint160(i * 10)); + } + + // 1st test scenario: add offramps. + // Check all the offramps are added correctly, and can route messages. + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](numberOfSelectors * numberOfOffRamps); + + // Ensure there are multi-offramp source and multi-source offramps + for (uint256 i = 0; i < numberOfSelectors; ++i) { + for (uint256 j = 0; j < numberOfOffRamps; ++j) { + offRampUpdates[(i * numberOfOffRamps) + j] = Router.OffRamp(sourceChainSelectors[i], offRamps[j]); + } + } + + for (uint256 i = 0; i < offRampUpdates.length; ++i) { + vm.expectEmit(); + emit Router.OffRampAdded(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp); + } + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + + Router.OffRamp[] memory gotOffRamps = s_sourceRouter.getOffRamps(); + assertEq(offRampUpdates.length, gotOffRamps.length); + + for (uint256 i = 0; i < offRampUpdates.length; ++i) { + assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); + assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); + _assertOffRampRouteSucceeds(offRampUpdates[i]); + } + + vm.startPrank(OWNER); + + // 2nd test scenario: partially remove existing offramps, add new offramps. + // Check offramps are removed correctly. Removed offramps cannot route messages. + // Check new offramps are added correctly. New offramps can route messages. + // Check unmodified offramps remain correct, and can still route messages. + uint256 numberOfPartialUpdates = offRampUpdates.length / 2; + Router.OffRamp[] memory partialOffRampRemoves = new Router.OffRamp[](numberOfPartialUpdates); + Router.OffRamp[] memory partialOffRampAdds = new Router.OffRamp[](numberOfPartialUpdates); + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + partialOffRampRemoves[i] = offRampUpdates[i]; + partialOffRampAdds[i] = Router.OffRamp({ + sourceChainSelector: offRampUpdates[i].sourceChainSelector, + offRamp: address(uint160(offRampUpdates[i].offRamp) + 1e18) // Ensure unique new offRamps addresses + }); + } + + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + vm.expectEmit(); + emit Router.OffRampRemoved(partialOffRampRemoves[i].sourceChainSelector, partialOffRampRemoves[i].offRamp); + } + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + vm.expectEmit(); + emit Router.OffRampAdded(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp); + } + s_sourceRouter.applyRampUpdates(onRampUpdates, partialOffRampRemoves, partialOffRampAdds); + + gotOffRamps = s_sourceRouter.getOffRamps(); + assertEq(offRampUpdates.length, gotOffRamps.length); + + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + assertFalse( + s_sourceRouter.isOffRamp(partialOffRampRemoves[i].sourceChainSelector, partialOffRampRemoves[i].offRamp) + ); + _assertOffRampRouteReverts(partialOffRampRemoves[i]); + + assertTrue(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); + _assertOffRampRouteSucceeds(partialOffRampAdds[i]); + } + for (uint256 i = numberOfPartialUpdates; i < offRampUpdates.length; ++i) { + assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); + _assertOffRampRouteSucceeds(offRampUpdates[i]); + } + + vm.startPrank(OWNER); + + // 3rd test scenario: remove all offRamps. + // Check all offramps have been removed, no offramp is able to route messages. + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + vm.expectEmit(); + emit Router.OffRampRemoved(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp); + } + s_sourceRouter.applyRampUpdates(onRampUpdates, partialOffRampAdds, new Router.OffRamp[](0)); + + uint256 numberOfRemainingOfframps = offRampUpdates.length - numberOfPartialUpdates; + Router.OffRamp[] memory remainingOffRampRemoves = new Router.OffRamp[](numberOfRemainingOfframps); + for (uint256 i = 0; i < numberOfRemainingOfframps; ++i) { + remainingOffRampRemoves[i] = offRampUpdates[i + numberOfPartialUpdates]; + } + + for (uint256 i = 0; i < numberOfRemainingOfframps; ++i) { + vm.expectEmit(); + emit Router.OffRampRemoved(remainingOffRampRemoves[i].sourceChainSelector, remainingOffRampRemoves[i].offRamp); + } + s_sourceRouter.applyRampUpdates(onRampUpdates, remainingOffRampRemoves, new Router.OffRamp[](0)); + + // Check there are no offRamps. + assertEq(0, s_sourceRouter.getOffRamps().length); + + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); + _assertOffRampRouteReverts(partialOffRampAdds[i]); + } + for (uint256 i = 0; i < offRampUpdates.length; ++i) { + assertFalse(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); + _assertOffRampRouteReverts(offRampUpdates[i]); + } + + vm.startPrank(OWNER); + + // 4th test scenario: add initial onRamps back. + // Check the offramps are added correctly, and can route messages. + // Check offramps that were not added back remain unset, and cannot route messages. + for (uint256 i = 0; i < offRampUpdates.length; ++i) { + vm.expectEmit(); + emit Router.OffRampAdded(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp); + } + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + + // Check initial offRamps are added back and can route to receiver. + gotOffRamps = s_sourceRouter.getOffRamps(); + assertEq(offRampUpdates.length, gotOffRamps.length); + + for (uint256 i = 0; i < offRampUpdates.length; ++i) { + assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); + assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); + _assertOffRampRouteSucceeds(offRampUpdates[i]); + } + + // Check offramps that were not added back remain unset. + for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { + assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); + _assertOffRampRouteReverts(partialOffRampAdds[i]); + } + } + + function test_Fuzz_OnRampUpdates( + Router.OnRamp[] memory onRamps + ) public { + // Test adding onRamps + for (uint256 i = 0; i < onRamps.length; ++i) { + vm.expectEmit(); + emit Router.OnRampSet(onRamps[i].destChainSelector, onRamps[i].onRamp); + } + + s_sourceRouter.applyRampUpdates(onRamps, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + // Test setting onRamps to unsupported + for (uint256 i = 0; i < onRamps.length; ++i) { + onRamps[i].onRamp = address(0); + + vm.expectEmit(); + emit Router.OnRampSet(onRamps[i].destChainSelector, onRamps[i].onRamp); + } + s_sourceRouter.applyRampUpdates(onRamps, new Router.OffRamp[](0), new Router.OffRamp[](0)); + for (uint256 i = 0; i < onRamps.length; ++i) { + assertEq(address(0), s_sourceRouter.getOnRamp(onRamps[i].destChainSelector)); + assertFalse(s_sourceRouter.isChainSupported(onRamps[i].destChainSelector)); + } + } + + function test_OnRampDisable() public { + // Add onRamp + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](0); + address onRamp = address(uint160(2)); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + assertEq(onRamp, s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); + assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); + + // Disable onRamp + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(0)}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + assertEq(address(0), s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); + assertFalse(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); + + // Re-enable onRamp + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + assertEq(onRamp, s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); + assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); + } + + function test_OnlyOwner_Revert() public { + vm.stopPrank(); + vm.expectRevert("Only callable by owner"); + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](0); + s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); + } + + function test_OffRampMismatch_Revert() public { + address offRamp = address(uint160(2)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp(DEST_CHAIN_SELECTOR, offRamp); + + vm.expectEmit(); + emit Router.OffRampAdded(DEST_CHAIN_SELECTOR, offRamp); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + + offRampUpdates[0] = Router.OffRamp(SOURCE_CHAIN_SELECTOR, offRamp); + + vm.expectRevert(abi.encodeWithSelector(Router.OffRampMismatch.selector, SOURCE_CHAIN_SELECTOR, offRamp)); + s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); + } +} + +contract Router_setWrappedNative is OnRampSetup { + function test_Fuzz_SetWrappedNative_Success( + address wrappedNative + ) public { + s_sourceRouter.setWrappedNative(wrappedNative); + assertEq(wrappedNative, s_sourceRouter.getWrappedNative()); + } + + // Reverts + function test_OnlyOwner_Revert() public { + vm.stopPrank(); + vm.expectRevert("Only callable by owner"); + s_sourceRouter.setWrappedNative(address(1)); + } +} + +contract Router_getSupportedTokens is OnRampSetup { + function test_GetSupportedTokens_Revert() public { + vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); + s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); + } +} + +contract Router_routeMessage is OffRampSetup { + function setUp() public virtual override { + super.setUp(); + vm.startPrank(address(s_offRamp)); + } + + function _generateManualGasLimit( + uint256 callDataLength + ) internal view returns (uint256) { + return ((gasleft() - 2 * (16 * callDataLength + GAS_FOR_CALL_EXACT_CHECK)) * 62) / 64; + } + + function test_routeMessage_ManualExec_Success() public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + // Manuel execution cannot run out of gas + + (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + GAS_FOR_CALL_EXACT_CHECK, + _generateManualGasLimit(message.data.length), + address(s_receiver) + ); + assertTrue(success); + assertEq("", retData); + assertGt(gasUsed, 3_000); + } + + function test_routeMessage_ExecutionEvent_Success() public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + // Should revert with reason + bytes memory realError1 = new bytes(2); + realError1[0] = 0xbe; + realError1[1] = 0xef; + s_reverting_receiver.setErr(realError1); + + vm.expectEmit(); + emit Router.MessageExecuted( + message.messageId, + message.sourceChainSelector, + address(s_offRamp), + keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) + ); + + (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + GAS_FOR_CALL_EXACT_CHECK, + _generateManualGasLimit(message.data.length), + address(s_reverting_receiver) + ); + + assertFalse(success); + assertEq(abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1), retData); + assertGt(gasUsed, 3_000); + + // Reason is truncated + // Over the MAX_RET_BYTES limit (including offset and length word since we have a dynamic values), should be ignored + bytes memory realError2 = new bytes(32 * 2 + 1); + realError2[32 * 2 - 1] = 0xAA; + realError2[32 * 2] = 0xFF; + s_reverting_receiver.setErr(realError2); + + vm.expectEmit(); + emit Router.MessageExecuted( + message.messageId, + message.sourceChainSelector, + address(s_offRamp), + keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) + ); + + (success, retData, gasUsed) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + GAS_FOR_CALL_EXACT_CHECK, + _generateManualGasLimit(message.data.length), + address(s_reverting_receiver) + ); + + assertFalse(success); + assertEq( + abi.encodeWithSelector( + MaybeRevertMessageReceiver.CustomError.selector, + uint256(32), + uint256(realError2.length), + uint256(0), + uint256(0xAA) + ), + retData + ); + assertGt(gasUsed, 3_000); + + // Should emit success + vm.expectEmit(); + emit Router.MessageExecuted( + message.messageId, + message.sourceChainSelector, + address(s_offRamp), + keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) + ); + + (success, retData, gasUsed) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + GAS_FOR_CALL_EXACT_CHECK, + _generateManualGasLimit(message.data.length), + address(s_receiver) + ); + + assertTrue(success); + assertEq("", retData); + assertGt(gasUsed, 3_000); + } + + function testFuzz_routeMessage_ExecutionEvent_Success( + bytes calldata error + ) public { + Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); + s_reverting_receiver.setErr(error); + + bytes memory expectedRetData; + + if (error.length >= 33) { + uint256 cutOff = error.length > 64 ? 64 : error.length; + vm.expectEmit(); + emit Router.MessageExecuted( + message.messageId, + message.sourceChainSelector, + address(s_offRamp), + keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) + ); + expectedRetData = abi.encodeWithSelector( + MaybeRevertMessageReceiver.CustomError.selector, + uint256(32), + uint256(error.length), + bytes32(error[:32]), + bytes32(error[32:cutOff]) + ); + } else { + vm.expectEmit(); + emit Router.MessageExecuted( + message.messageId, + message.sourceChainSelector, + address(s_offRamp), + keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) + ); + expectedRetData = abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, error); + } + + (bool success, bytes memory retData,) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), + GAS_FOR_CALL_EXACT_CHECK, + _generateManualGasLimit(message.data.length), + address(s_reverting_receiver) + ); + + assertFalse(success); + assertEq(expectedRetData, retData); + } + + function test_routeMessage_AutoExec_Success() public { + (bool success,,) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + ); + + assertTrue(success); + + (success,,) = s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 1, address(s_receiver) + ); + + // Can run out of gas, should return false + assertFalse(success); + } + + // Reverts + function test_routeMessage_OnlyOffRamp_Revert() public { + vm.stopPrank(); + vm.startPrank(STRANGER); + + vm.expectRevert(IRouter.OnlyOffRamp.selector); + s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + ); + } + + function test_routeMessage_WhenNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + vm.expectRevert(Router.BadARMSignal.selector); + s_destRouter.routeMessage( + _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) + ); + } +} + +contract Router_getFee is OnRampSetup { + function test_GetFeeSupportedChain_Success() public view { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); + assertGt(expectedFee, 10e9); + } + + // Reverts + function test_UnsupportedDestinationChain_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, 999)); + s_sourceRouter.getFee(999, message); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol new file mode 100644 index 0000000..f4c1114 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Router} from "../../Router.sol"; +import {Client} from "../../libraries/Client.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {WETH9} from "../WETH9.sol"; + +contract RouterSetup is BaseTest { + Router internal s_sourceRouter; + Router internal s_destRouter; + + function setUp() public virtual override { + BaseTest.setUp(); + + if (address(s_sourceRouter) == address(0)) { + WETH9 weth = new WETH9(); + s_sourceRouter = new Router(address(weth), address(s_mockRMN)); + vm.label(address(s_sourceRouter), "sourceRouter"); + } + if (address(s_destRouter) == address(0)) { + WETH9 weth = new WETH9(); + s_destRouter = new Router(address(weth), address(s_mockRMN)); + vm.label(address(s_destRouter), "destRouter"); + } + } + + function _generateReceiverMessage( + uint64 chainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { + Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); + return Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: chainSelector, + sender: bytes("a"), + data: bytes("a"), + destTokenAmounts: ta + }); + } + + function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { + return Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(address(12312412312)), + destTokenAddress: abi.encode(address(9809808909)), + extraData: "", + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol new file mode 100644 index 0000000..dfb599b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; +import {IOwner} from "../../interfaces/IOwner.sol"; + +import {RegistryModuleOwnerCustom} from "../../tokenAdminRegistry/RegistryModuleOwnerCustom.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; +import {BurnMintERC677Helper} from "../helpers/BurnMintERC677Helper.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract RegistryModuleOwnerCustomSetup is Test { + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + + RegistryModuleOwnerCustom internal s_registryModuleOwnerCustom; + TokenAdminRegistry internal s_tokenAdminRegistry; + address internal s_token; + + function setUp() public virtual { + vm.startPrank(OWNER); + + s_tokenAdminRegistry = new TokenAdminRegistry(); + s_token = address(new BurnMintERC677Helper("Test", "TST")); + s_registryModuleOwnerCustom = new RegistryModuleOwnerCustom(address(s_tokenAdminRegistry)); + s_tokenAdminRegistry.addRegistryModule(address(s_registryModuleOwnerCustom)); + } +} + +contract RegistryModuleOwnerCustom_constructor is RegistryModuleOwnerCustomSetup { + function test_constructor_Revert() public { + vm.expectRevert(abi.encodeWithSelector(RegistryModuleOwnerCustom.AddressZero.selector)); + + new RegistryModuleOwnerCustom(address(0)); + } +} + +contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModuleOwnerCustomSetup { + function test_registerAdminViaGetCCIPAdmin_Success() public { + assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); + + address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); + + vm.expectCall(s_token, abi.encodeWithSelector(IGetCCIPAdmin.getCCIPAdmin.selector), 1); + vm.expectCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(TokenAdminRegistry.proposeAdministrator.selector, s_token, expectedOwner), + 1 + ); + + vm.expectEmit(); + emit RegistryModuleOwnerCustom.AdministratorRegistered(s_token, expectedOwner); + + s_registryModuleOwnerCustom.registerAdminViaGetCCIPAdmin(s_token); + + assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); + } + + function test_registerAdminViaGetCCIPAdmin_Revert() public { + address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); + + vm.startPrank(makeAddr("Not_expected_owner")); + + vm.expectRevert( + abi.encodeWithSelector(RegistryModuleOwnerCustom.CanOnlySelfRegister.selector, expectedOwner, s_token) + ); + + s_registryModuleOwnerCustom.registerAdminViaGetCCIPAdmin(s_token); + } +} + +contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerCustomSetup { + function test_registerAdminViaOwner_Success() public { + assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); + + address expectedOwner = IOwner(s_token).owner(); + + vm.expectCall(s_token, abi.encodeWithSelector(IOwner.owner.selector), 1); + vm.expectCall( + address(s_tokenAdminRegistry), + abi.encodeWithSelector(TokenAdminRegistry.proposeAdministrator.selector, s_token, expectedOwner), + 1 + ); + + vm.expectEmit(); + emit RegistryModuleOwnerCustom.AdministratorRegistered(s_token, expectedOwner); + + s_registryModuleOwnerCustom.registerAdminViaOwner(s_token); + + assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); + } + + function test_registerAdminViaOwner_Revert() public { + address expectedOwner = IOwner(s_token).owner(); + + vm.startPrank(makeAddr("Not_expected_owner")); + + vm.expectRevert( + abi.encodeWithSelector(RegistryModuleOwnerCustom.CanOnlySelfRegister.selector, expectedOwner, s_token) + ); + + s_registryModuleOwnerCustom.registerAdminViaOwner(s_token); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol new file mode 100644 index 0000000..a5c2487 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol @@ -0,0 +1,395 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IPoolV1} from "../../interfaces/IPool.sol"; + +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; +import {TokenSetup} from "../TokenSetup.t.sol"; + +contract TokenAdminRegistrySetup is TokenSetup { + address internal s_registryModule = makeAddr("registryModule"); + + function setUp() public virtual override { + TokenSetup.setUp(); + + s_tokenAdminRegistry.addRegistryModule(s_registryModule); + } +} + +contract TokenAdminRegistry_getPools is TokenAdminRegistrySetup { + function test_getPools_Success() public { + address[] memory tokens = new address[](1); + tokens[0] = s_sourceTokens[0]; + + address[] memory got = s_tokenAdminRegistry.getPools(tokens); + assertEq(got.length, 1); + assertEq(got[0], s_sourcePoolByToken[tokens[0]]); + + got = s_tokenAdminRegistry.getPools(s_sourceTokens); + assertEq(got.length, s_sourceTokens.length); + for (uint256 i = 0; i < s_sourceTokens.length; i++) { + assertEq(got[i], s_sourcePoolByToken[s_sourceTokens[i]]); + } + + address doesNotExist = makeAddr("doesNotExist"); + tokens[0] = doesNotExist; + got = s_tokenAdminRegistry.getPools(tokens); + assertEq(got.length, 1); + assertEq(got[0], address(0)); + } +} + +contract TokenAdminRegistry_getPool is TokenAdminRegistrySetup { + function test_getPool_Success() public view { + address got = s_tokenAdminRegistry.getPool(s_sourceTokens[0]); + assertEq(got, s_sourcePoolByToken[s_sourceTokens[0]]); + } +} + +contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { + function test_setPool_Success() public { + address pool = makeAddr("pool"); + vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); + + vm.expectEmit(); + emit TokenAdminRegistry.PoolSet(s_sourceTokens[0], s_sourcePoolByToken[s_sourceTokens[0]], pool); + + s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); + + assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), pool); + + // Assert the event is not emitted if the pool is the same as the current pool. + vm.recordLogs(); + s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); + + vm.assertEq(vm.getRecordedLogs().length, 0); + } + + function test_setPool_ZeroAddressRemovesPool_Success() public { + address pool = makeAddr("pool"); + vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); + s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); + + assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), pool); + + vm.expectEmit(); + emit TokenAdminRegistry.PoolSet(s_sourceTokens[0], pool, address(0)); + + s_tokenAdminRegistry.setPool(s_sourceTokens[0], address(0)); + + assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), address(0)); + } + + function test_setPool_InvalidTokenPoolToken_Revert() public { + address pool = makeAddr("pool"); + vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(false)); + + vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.InvalidTokenPoolToken.selector, s_sourceTokens[0])); + s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); + } + + function test_setPool_OnlyAdministrator_Revert() public { + vm.stopPrank(); + + vm.expectRevert( + abi.encodeWithSelector(TokenAdminRegistry.OnlyAdministrator.selector, address(this), s_sourceTokens[0]) + ); + s_tokenAdminRegistry.setPool(s_sourceTokens[0], makeAddr("pool")); + } +} + +contract TokenAdminRegistry_getAllConfiguredTokens is TokenAdminRegistrySetup { + function test_Fuzz_getAllConfiguredTokens_Success( + uint8 numberOfTokens + ) public { + TokenAdminRegistry cleanTokenAdminRegistry = new TokenAdminRegistry(); + for (uint160 i = 0; i < numberOfTokens; ++i) { + cleanTokenAdminRegistry.proposeAdministrator(address(i), address(i + 1000)); + } + + uint160 count = 0; + for (uint160 start = 0; start < numberOfTokens; start += count++) { + address[] memory got = cleanTokenAdminRegistry.getAllConfiguredTokens(uint64(start), uint64(count)); + if (start + count > numberOfTokens) { + assertEq(got.length, numberOfTokens - start); + } else { + assertEq(got.length, count); + } + + for (uint160 j = 0; j < got.length; ++j) { + assertEq(got[j], address(j + start)); + } + } + } + + function test_getAllConfiguredTokens_outOfBounds_Success() public view { + address[] memory tokens = s_tokenAdminRegistry.getAllConfiguredTokens(type(uint64).max, 10); + assertEq(tokens.length, 0); + } +} + +contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { + function test_transferAdminRole_Success() public { + address token = s_sourceTokens[0]; + + address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; + address newAdmin = makeAddr("newAdmin"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(token, currentAdmin, newAdmin); + + s_tokenAdminRegistry.transferAdminRole(token, newAdmin); + + TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); + + // Assert only the pending admin updates, without affecting the pending admin. + assertEq(config.pendingAdministrator, newAdmin); + assertEq(config.administrator, currentAdmin); + } + + function test_transferAdminRole_OnlyAdministrator_Revert() public { + vm.stopPrank(); + + vm.expectRevert( + abi.encodeWithSelector(TokenAdminRegistry.OnlyAdministrator.selector, address(this), s_sourceTokens[0]) + ); + s_tokenAdminRegistry.transferAdminRole(s_sourceTokens[0], makeAddr("newAdmin")); + } +} + +contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { + function test_acceptAdminRole_Success() public { + address token = s_sourceTokens[0]; + + address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; + address newAdmin = makeAddr("newAdmin"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(token, currentAdmin, newAdmin); + + s_tokenAdminRegistry.transferAdminRole(token, newAdmin); + + TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); + + // Assert only the pending admin updates, without affecting the pending admin. + assertEq(config.pendingAdministrator, newAdmin); + assertEq(config.administrator, currentAdmin); + + vm.startPrank(newAdmin); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferred(token, newAdmin); + + s_tokenAdminRegistry.acceptAdminRole(token); + + config = s_tokenAdminRegistry.getTokenConfig(token); + + // Assert only the pending admin updates, without affecting the pending admin. + assertEq(config.pendingAdministrator, address(0)); + assertEq(config.administrator, newAdmin); + } + + function test_acceptAdminRole_OnlyPendingAdministrator_Revert() public { + address token = s_sourceTokens[0]; + address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; + address newAdmin = makeAddr("newAdmin"); + + s_tokenAdminRegistry.transferAdminRole(token, newAdmin); + + TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); + + // Assert only the pending admin updates, without affecting the pending admin. + assertEq(config.pendingAdministrator, newAdmin); + assertEq(config.administrator, currentAdmin); + + address notNewAdmin = makeAddr("notNewAdmin"); + vm.startPrank(notNewAdmin); + + vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.OnlyPendingAdministrator.selector, notNewAdmin, token)); + s_tokenAdminRegistry.acceptAdminRole(token); + } +} + +contract TokenAdminRegistry_isAdministrator is TokenAdminRegistrySetup { + function test_isAdministrator_Success() public { + address newAdmin = makeAddr("newAdmin"); + address newToken = makeAddr("newToken"); + assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); + assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, OWNER)); + + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + changePrank(newAdmin); + s_tokenAdminRegistry.acceptAdminRole(newToken); + + assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); + assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, OWNER)); + } +} + +contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { + function test_proposeAdministrator_module_Success() public { + vm.startPrank(s_registryModule); + address newAdmin = makeAddr("newAdmin"); + address newToken = makeAddr("newToken"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); + + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + + assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); + assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).administrator, address(0)); + assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).tokenPool, address(0)); + + changePrank(newAdmin); + s_tokenAdminRegistry.acceptAdminRole(newToken); + + assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); + } + + function test_proposeAdministrator_owner_Success() public { + address newAdmin = makeAddr("newAdmin"); + address newToken = makeAddr("newToken"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); + + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + + assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); + + changePrank(newAdmin); + s_tokenAdminRegistry.acceptAdminRole(newToken); + + assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); + } + + function test_proposeAdministrator_reRegisterWhileUnclaimed_Success() public { + address newAdmin = makeAddr("wrongAddress"); + address newToken = makeAddr("newToken"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); + + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + + assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); + + newAdmin = makeAddr("correctAddress"); + + vm.expectEmit(); + emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); + + // Ensure we can still register the correct admin while the previous admin is unclaimed. + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + + changePrank(newAdmin); + s_tokenAdminRegistry.acceptAdminRole(newToken); + + assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); + } + + mapping(address token => address admin) internal s_AdminByToken; + + function test_Fuzz_proposeAdministrator_Success(address[50] memory tokens, address[50] memory admins) public { + TokenAdminRegistry cleanTokenAdminRegistry = new TokenAdminRegistry(); + for (uint256 i = 0; i < tokens.length; i++) { + if (admins[i] == address(0)) { + continue; + } + if (cleanTokenAdminRegistry.getTokenConfig(tokens[i]).administrator != address(0)) { + continue; + } + cleanTokenAdminRegistry.proposeAdministrator(tokens[i], admins[i]); + s_AdminByToken[tokens[i]] = admins[i]; + } + + for (uint256 i = 0; i < tokens.length; i++) { + assertEq(cleanTokenAdminRegistry.getTokenConfig(tokens[i]).pendingAdministrator, s_AdminByToken[tokens[i]]); + } + } + + function test_proposeAdministrator_OnlyRegistryModule_Revert() public { + address newToken = makeAddr("newToken"); + vm.stopPrank(); + + vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.OnlyRegistryModuleOrOwner.selector, address(this))); + s_tokenAdminRegistry.proposeAdministrator(newToken, OWNER); + } + + function test_proposeAdministrator_ZeroAddress_Revert() public { + address newToken = makeAddr("newToken"); + + vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.ZeroAddress.selector)); + s_tokenAdminRegistry.proposeAdministrator(newToken, address(0)); + } + + function test_proposeAdministrator_AlreadyRegistered_Revert() public { + address newAdmin = makeAddr("newAdmin"); + address newToken = makeAddr("newToken"); + + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + changePrank(newAdmin); + s_tokenAdminRegistry.acceptAdminRole(newToken); + + changePrank(OWNER); + + vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.AlreadyRegistered.selector, newToken)); + s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); + } +} + +contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { + function test_addRegistryModule_Success() public { + address newModule = makeAddr("newModule"); + + s_tokenAdminRegistry.addRegistryModule(newModule); + + assertTrue(s_tokenAdminRegistry.isRegistryModule(newModule)); + + // Assert the event is not emitted if the module is already added. + vm.recordLogs(); + s_tokenAdminRegistry.addRegistryModule(newModule); + + vm.assertEq(vm.getRecordedLogs().length, 0); + } + + function test_addRegistryModule_OnlyOwner_Revert() public { + address newModule = makeAddr("newModule"); + vm.stopPrank(); + + vm.expectRevert("Only callable by owner"); + s_tokenAdminRegistry.addRegistryModule(newModule); + } +} + +contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { + function test_removeRegistryModule_Success() public { + address newModule = makeAddr("newModule"); + + s_tokenAdminRegistry.addRegistryModule(newModule); + + assertTrue(s_tokenAdminRegistry.isRegistryModule(newModule)); + + vm.expectEmit(); + emit TokenAdminRegistry.RegistryModuleRemoved(newModule); + + s_tokenAdminRegistry.removeRegistryModule(newModule); + + assertFalse(s_tokenAdminRegistry.isRegistryModule(newModule)); + + // Assert the event is not emitted if the module is already removed. + vm.recordLogs(); + s_tokenAdminRegistry.removeRegistryModule(newModule); + + vm.assertEq(vm.getRecordedLogs().length, 0); + } + + function test_removeRegistryModule_OnlyOwner_Revert() public { + address newModule = makeAddr("newModule"); + vm.stopPrank(); + + vm.expectRevert("Only callable by owner"); + s_tokenAdminRegistry.removeRegistryModule(newModule); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol new file mode 100644 index 0000000..dd2c82f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IGetCCIPAdmin} from "../interfaces/IGetCCIPAdmin.sol"; +import {IOwner} from "../interfaces/IOwner.sol"; +import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; + +contract RegistryModuleOwnerCustom is ITypeAndVersion { + error CanOnlySelfRegister(address admin, address token); + error AddressZero(); + + event AdministratorRegistered(address indexed token, address indexed administrator); + + string public constant override typeAndVersion = "RegistryModuleOwnerCustom 1.5.0"; + + // The TokenAdminRegistry contract + ITokenAdminRegistry internal immutable i_tokenAdminRegistry; + + constructor( + address tokenAdminRegistry + ) { + if (tokenAdminRegistry == address(0)) { + revert AddressZero(); + } + i_tokenAdminRegistry = ITokenAdminRegistry(tokenAdminRegistry); + } + + /// @notice Registers the admin of the token using the `getCCIPAdmin` method. + /// @param token The token to register the admin for. + /// @dev The caller must be the admin returned by the `getCCIPAdmin` method. + function registerAdminViaGetCCIPAdmin( + address token + ) external { + _registerAdmin(token, IGetCCIPAdmin(token).getCCIPAdmin()); + } + + /// @notice Registers the admin of the token using the `owner` method. + /// @param token The token to register the admin for. + /// @dev The caller must be the admin returned by the `owner` method. + function registerAdminViaOwner( + address token + ) external { + _registerAdmin(token, IOwner(token).owner()); + } + + /// @notice Registers the admin of the token to msg.sender given that the + /// admin is equal to msg.sender. + /// @param token The token to register the admin for. + /// @param admin The caller must be the admin. + function _registerAdmin(address token, address admin) internal { + if (admin != msg.sender) { + revert CanOnlySelfRegister(admin, token); + } + + i_tokenAdminRegistry.proposeAdministrator(token, admin); + + emit AdministratorRegistered(token, admin); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol new file mode 100644 index 0000000..fbe821e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IPoolV1} from "../interfaces/IPool.sol"; +import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice This contract stores the token pool configuration for all CCIP enabled tokens. It works +/// on a self-serve basis, where tokens can be registered without intervention from the CCIP owner. +/// @dev This contract is not considered upgradable, as it is a customer facing contract that will store +/// significant amounts of data. +contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCreator { + using EnumerableSet for EnumerableSet.AddressSet; + + error OnlyRegistryModuleOrOwner(address sender); + error OnlyAdministrator(address sender, address token); + error OnlyPendingAdministrator(address sender, address token); + error AlreadyRegistered(address token); + error ZeroAddress(); + error InvalidTokenPoolToken(address token); + + event PoolSet(address indexed token, address indexed previousPool, address indexed newPool); + event AdministratorTransferRequested(address indexed token, address indexed currentAdmin, address indexed newAdmin); + event AdministratorTransferred(address indexed token, address indexed newAdmin); + event RegistryModuleAdded(address module); + event RegistryModuleRemoved(address indexed module); + + // The struct is packed in a way that optimizes the attributes that are accessed together. + // solhint-disable-next-line gas-struct-packing + struct TokenConfig { + address administrator; // the current administrator of the token + address pendingAdministrator; // the address that is pending to become the new administrator + address tokenPool; // the token pool for this token. Can be address(0) if not deployed or not configured. + } + + string public constant override typeAndVersion = "TokenAdminRegistry 1.5.0"; + + // Mapping of token address to token configuration + mapping(address token => TokenConfig) internal s_tokenConfig; + + // All tokens that have been configured + EnumerableSet.AddressSet internal s_tokens; + + // Registry modules are allowed to register administrators for tokens + EnumerableSet.AddressSet internal s_registryModules; + + /// @notice Returns all pools for the given tokens. + /// @dev Will return address(0) for tokens that do not have a pool. + function getPools( + address[] calldata tokens + ) external view returns (address[] memory) { + address[] memory pools = new address[](tokens.length); + for (uint256 i = 0; i < tokens.length; ++i) { + pools[i] = s_tokenConfig[tokens[i]].tokenPool; + } + return pools; + } + + /// @inheritdoc ITokenAdminRegistry + function getPool( + address token + ) external view returns (address) { + return s_tokenConfig[token].tokenPool; + } + + /// @notice Returns the configuration for a token. + /// @param token The token to get the configuration for. + /// @return config The configuration for the token. + function getTokenConfig( + address token + ) external view returns (TokenConfig memory) { + return s_tokenConfig[token]; + } + + /// @notice Returns a list of tokens that are configured in the token admin registry. + /// @param startIndex Starting index in list, can be 0 if you want to start from the beginning. + /// @param maxCount Maximum number of tokens to retrieve. Since the list can be large, + /// it is recommended to use a paging mechanism to retrieve all tokens. If querying for very + /// large lists, RPCs can time out. If you want all tokens, use type(uint64).max. + /// @return tokens List of configured tokens. + /// @dev The function is paginated to avoid RPC timeouts. + /// @dev The ordering is guaranteed to remain the same as it is not possible to remove tokens + /// from s_tokens. + function getAllConfiguredTokens(uint64 startIndex, uint64 maxCount) external view returns (address[] memory tokens) { + uint256 numberOfTokens = s_tokens.length(); + if (startIndex >= numberOfTokens) { + return tokens; + } + uint256 count = maxCount; + if (count + startIndex > numberOfTokens) { + count = numberOfTokens - startIndex; + } + tokens = new address[](count); + for (uint256 i = 0; i < count; ++i) { + tokens[i] = s_tokens.at(startIndex + i); + } + + return tokens; + } + + // ================================================================ + // │ Administrator functions │ + // ================================================================ + + /// @notice Sets the pool for a token. Setting the pool to address(0) effectively delists the token + /// from CCIP. Setting the pool to any other address enables the token on CCIP. + /// @param localToken The token to set the pool for. + /// @param pool The pool to set for the token. + function setPool(address localToken, address pool) external onlyTokenAdmin(localToken) { + // The pool has to support the token, but we want to allow removing the pool, so we only check + // if the pool supports the token if it is not address(0). + if (pool != address(0) && !IPoolV1(pool).isSupportedToken(localToken)) { + revert InvalidTokenPoolToken(localToken); + } + + TokenConfig storage config = s_tokenConfig[localToken]; + + address previousPool = config.tokenPool; + config.tokenPool = pool; + + if (previousPool != pool) { + emit PoolSet(localToken, previousPool, pool); + } + } + + /// @notice Transfers the administrator role for a token to a new address with a 2-step process. + /// @param localToken The token to transfer the administrator role for. + /// @param newAdmin The address to transfer the administrator role to. Can be address(0) to cancel + /// a pending transfer. + /// @dev The new admin must call `acceptAdminRole` to accept the role. + function transferAdminRole(address localToken, address newAdmin) external onlyTokenAdmin(localToken) { + TokenConfig storage config = s_tokenConfig[localToken]; + config.pendingAdministrator = newAdmin; + + emit AdministratorTransferRequested(localToken, msg.sender, newAdmin); + } + + /// @notice Accepts the administrator role for a token. + /// @param localToken The token to accept the administrator role for. + /// @dev This function can only be called by the pending administrator. + function acceptAdminRole( + address localToken + ) external { + TokenConfig storage config = s_tokenConfig[localToken]; + if (config.pendingAdministrator != msg.sender) { + revert OnlyPendingAdministrator(msg.sender, localToken); + } + + config.administrator = msg.sender; + config.pendingAdministrator = address(0); + + emit AdministratorTransferred(localToken, msg.sender); + } + + // ================================================================ + // │ Administrator config │ + // ================================================================ + + /// @notice Public getter to check for permissions of an administrator + function isAdministrator(address localToken, address administrator) external view returns (bool) { + return s_tokenConfig[localToken].administrator == administrator; + } + + /// @inheritdoc ITokenAdminRegistry + /// @dev Can only be called by a registry module. + function proposeAdministrator(address localToken, address administrator) external { + if (!isRegistryModule(msg.sender) && msg.sender != owner()) { + revert OnlyRegistryModuleOrOwner(msg.sender); + } + if (administrator == address(0)) { + revert ZeroAddress(); + } + TokenConfig storage config = s_tokenConfig[localToken]; + + if (config.administrator != address(0)) { + revert AlreadyRegistered(localToken); + } + + config.pendingAdministrator = administrator; + + // We don't care if it's already in the set, as it's a no-op. + s_tokens.add(localToken); + + emit AdministratorTransferRequested(localToken, address(0), administrator); + } + + // ================================================================ + // │ Registry Modules │ + // ================================================================ + + /// @notice Checks if an address is a registry module. + /// @param module The address to check. + /// @return True if the address is a registry module, false otherwise. + function isRegistryModule( + address module + ) public view returns (bool) { + return s_registryModules.contains(module); + } + + /// @notice Adds a new registry module to the list of allowed modules. + /// @param module The module to add. + function addRegistryModule( + address module + ) external onlyOwner { + if (s_registryModules.add(module)) { + emit RegistryModuleAdded(module); + } + } + + /// @notice Removes a registry module from the list of allowed modules. + /// @param module The module to remove. + function removeRegistryModule( + address module + ) external onlyOwner { + if (s_registryModules.remove(module)) { + emit RegistryModuleRemoved(module); + } + } + + // ================================================================ + // │ Access │ + // ================================================================ + + /// @notice Checks if an address is the administrator of the given token. + modifier onlyTokenAdmin( + address token + ) { + if (s_tokenConfig[token].administrator != msg.sender) { + revert OnlyAdministrator(msg.sender, token); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md new file mode 100644 index 0000000..ef0f55e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md @@ -0,0 +1,8 @@ +v1.5-CCIP-License-grants + +Additional Use Grant(s): + +You may make use of the Cross-Chain Interoperability Protocol v1.5 (which is available subject to the license here, the “Licensed Work ”) solely for purposes of + +1. importing client-side libraries or example clients to facilitate the integration of the Licensed Work into your application. +2. Developing, deploying and operating [the token pool contracts](./pools) solely for purposes of the integration and use of CCIP. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol new file mode 100644 index 0000000..75420fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {IFunctionsBilling, FunctionsBillingConfig} from "./interfaces/IFunctionsBilling.sol"; + +import {Routable} from "./Routable.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +import {ChainSpecificUtil} from "./libraries/ChainSpecificUtil.sol"; + +/// @title Functions Billing contract +/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsBilling is Routable, IFunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei + + event RequestBilled( + bytes32 indexed requestId, + uint96 juelsPerGas, + uint256 l1FeeShareWei, + uint96 callbackCostJuels, + uint72 donFeeJuels, + uint72 adminFeeJuels, + uint72 operationFeeJuels + ); + + // ================================================================ + // | Request Commitment state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; + + event CommitmentDeleted(bytes32 requestId); + + FunctionsBillingConfig private s_config; + + event ConfigUpdated(FunctionsBillingConfig config); + + error UnsupportedRequestDataVersion(); + error InsufficientBalance(); + error InvalidSubscription(); + error UnauthorizedSender(); + error MustBeSubOwner(address owner); + error InvalidLinkWeiPrice(int256 linkWei); + error InvalidUsdLinkPrice(int256 usdLink); + error PaymentTooLarge(); + error NoTransmittersSet(); + error InvalidCalldata(); + + // ================================================================ + // | Balance state | + // ================================================================ + + mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; + // Pool together collected DON fees + // Disperse them on withdrawal or change in OCR configuration + uint96 internal s_feePool; + + AggregatorV3Interface private s_linkToNativeFeed; + AggregatorV3Interface private s_linkToUsdFeed; + + // ================================================================ + // | Initialization | + // ================================================================ + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) Routable(router) { + s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); + s_linkToUsdFeed = AggregatorV3Interface(linkToUsdFeed); + + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the Chainlink Coordinator's billing configuration + /// @return config + function getConfig() external view returns (FunctionsBillingConfig memory) { + return s_config; + } + + /// @notice Sets the Chainlink Coordinator's billing configuration + /// @param config - See the contents of the FunctionsBillingConfig struct in IFunctionsBilling.sol for more information + function updateConfig(FunctionsBillingConfig memory config) public { + _onlyOwner(); + + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Fee Calculation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function getDONFeeJuels(bytes memory /* requestData */) public view override returns (uint72) { + // s_config.donFee is in cents of USD. Convert to dollars amount then get amount of Juels. + return SafeCast.toUint72(_getJuelsFromUsd(s_config.donFeeCentsUsd) / 100); + } + + /// @inheritdoc IFunctionsBilling + function getOperationFeeJuels() public view override returns (uint72) { + // s_config.donFee is in cents of USD. Convert to dollars then get amount of Juels. + return SafeCast.toUint72(_getJuelsFromUsd(s_config.operationFeeCentsUsd) / 100); + } + + /// @inheritdoc IFunctionsBilling + function getAdminFeeJuels() public view override returns (uint72) { + return _getRouter().getAdminFee(); + } + + /// @inheritdoc IFunctionsBilling + function getWeiPerUnitLink() public view returns (uint256) { + (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); + // Only fallback if feedStalenessSeconds is set + // solhint-disable-next-line not-rely-on-time + if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { + return s_config.fallbackNativePerUnitLink; + } + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + return uint256(weiPerUnitLink); + } + + function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { + // (1e18 juels/link) * wei / (wei/link) = juels + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); + } + + /// @inheritdoc IFunctionsBilling + function getUsdPerUnitLink() public view returns (uint256, uint8) { + (, int256 usdPerUnitLink, , uint256 timestamp, ) = s_linkToUsdFeed.latestRoundData(); + // Only fallback if feedStalenessSeconds is set + // solhint-disable-next-line not-rely-on-time + if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { + return (s_config.fallbackUsdPerUnitLink, s_config.fallbackUsdPerUnitLinkDecimals); + } + if (usdPerUnitLink <= 0) { + revert InvalidUsdLinkPrice(usdPerUnitLink); + } + return (uint256(usdPerUnitLink), s_linkToUsdFeed.decimals()); + } + + function _getJuelsFromUsd(uint256 amountUsd) private view returns (uint96) { + (uint256 usdPerLink, uint8 decimals) = getUsdPerUnitLink(); + // (usd) * (10**18 juels/link) * (10**decimals) / (link / usd) = juels + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((amountUsd * 10 ** (18 + decimals)) / usdPerLink); + } + + // ================================================================ + // | Cost Estimation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view override returns (uint96) { + _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + // Reasonable ceilings to prevent integer overflows + if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { + revert InvalidCalldata(); + } + uint72 adminFee = getAdminFeeJuels(); + uint72 donFee = getDONFeeJuels(data); + uint72 operationFee = getOperationFeeJuels(); + return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); + } + + /// @notice Estimate the cost in Juels of LINK + // that will be charged to a subscription to fulfill a Functions request + // Gas Price can be overestimated to account for flucuations between request and response time + function _calculateCostEstimate( + uint32 callbackGasLimit, + uint256 gasPriceWei, + uint72 donFeeJuels, + uint72 adminFeeJuels, + uint72 operationFeeJuels + ) internal view returns (uint96) { + // If gas price is less than the minimum fulfillment gas price, override to using the minimum + if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { + gasPriceWei = s_config.minimumEstimateGasPriceWei; + } + + uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit; + 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); + + return estimatedGasReimbursementJuels + feesJuels; + } + + // ================================================================ + // | Billing | + // ================================================================ + + /// @notice Initiate the billing process for an Functions request + /// @dev Only callable by the Functions Router + /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure + /// @return commitment - The parameters of the request that must be held consistent at response time + function _startBilling( + FunctionsResponse.RequestMeta memory request + ) internal returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { + // Nodes should support all past versions of the structure + if (request.dataVersion > s_config.maxSupportedRequestDataVersion) { + revert UnsupportedRequestDataVersion(); + } + + uint72 donFee = getDONFeeJuels(request.data); + operationFee = getOperationFeeJuels(); + uint96 estimatedTotalCostJuels = _calculateCostEstimate( + request.callbackGasLimit, + tx.gasprice, + donFee, + request.adminFee, + operationFee + ); + + // Check that subscription can afford the estimated cost + if ((request.availableBalance) < estimatedTotalCostJuels) { + revert InsufficientBalance(); + } + + uint32 timeoutTimestamp = uint32(block.timestamp + s_config.requestTimeoutSeconds); + bytes32 requestId = keccak256( + abi.encode( + address(this), + request.requestingContract, + request.subscriptionId, + request.initiatedRequests + 1, + keccak256(request.data), + request.dataVersion, + request.callbackGasLimit, + estimatedTotalCostJuels, + timeoutTimestamp, + // solhint-disable-next-line avoid-tx-origin + tx.origin + ) + ); + + commitment = FunctionsResponse.Commitment({ + adminFee: request.adminFee, + coordinator: address(this), + client: request.requestingContract, + subscriptionId: request.subscriptionId, + callbackGasLimit: request.callbackGasLimit, + estimatedTotalCostJuels: estimatedTotalCostJuels, + timeoutTimestamp: timeoutTimestamp, + requestId: requestId, + donFee: donFee, + gasOverheadBeforeCallback: s_config.gasOverheadBeforeCallback, + gasOverheadAfterCallback: s_config.gasOverheadAfterCallback + }); + + s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); + + return (commitment, operationFee); + } + + /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription + /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @param reportBatchSize the number of fulfillments in the transmitter's report + /// @return result fulfillment result + /// @dev Only callable by a node that has been approved on the Coordinator + /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request + function _fulfillAndBill( + bytes32 requestId, + bytes memory response, + bytes memory err, + bytes memory onchainMetadata, + bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, + uint8 reportBatchSize + ) internal returns (FunctionsResponse.FulfillResult) { + FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); + + uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; + uint256 l1FeeShareWei = ChainSpecificUtil._getL1FeeUpperLimit(msg.data.length) / reportBatchSize; + // Gas overhead without callback + uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); + uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); + + // The Functions Router will perform the callback to the client contract + (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( + response, + err, + juelsPerGas, + // The following line represents: "cost without callback or admin fee, those will be added by the Router" + // But because the _offchain_ Commitment is using operation fee in the place of the admin fee, this now adds admin fee (actually operation fee) + // Admin fee is configured to 0 in the Router + gasOverheadJuels + commitment.donFee + commitment.adminFee, + msg.sender, + FunctionsResponse.Commitment({ + adminFee: 0, // The Router should have adminFee set to 0. If it does not this will cause fulfillments to fail with INVALID_COMMITMENT instead of carrying out incorrect bookkeeping. + coordinator: commitment.coordinator, + client: commitment.client, + subscriptionId: commitment.subscriptionId, + callbackGasLimit: commitment.callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback + }) + ); + + // The router will only pay the DON on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the Coordinator should hold on to the request commitment + if ( + resultCode == FunctionsResponse.FulfillResult.FULFILLED || + resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + delete s_requestCommitments[requestId]; + // Reimburse the transmitter for the fulfillment gas cost + s_withdrawableTokens[msg.sender] += gasOverheadJuels + callbackCostJuels; + // Put donFee into the pool of fees, to be split later + // Saves on storage writes that would otherwise be charged to the user + s_feePool += commitment.donFee; + // Pay the operation fee to the Coordinator owner + s_withdrawableTokens[_owner()] += commitment.adminFee; // OperationFee is used in the slot for Admin Fee in the Offchain Commitment. Admin Fee is set to 0 in the Router (enforced by line 316 in FunctionsBilling.sol). + emit RequestBilled({ + requestId: requestId, + juelsPerGas: juelsPerGas, + l1FeeShareWei: l1FeeShareWei, + callbackCostJuels: callbackCostJuels, + donFeeJuels: commitment.donFee, + // The following two lines are because of OperationFee being used in the Offchain Commitment + adminFeeJuels: 0, + operationFeeJuels: commitment.adminFee + }); + } + return resultCode; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Router + /// @dev Used by FunctionsRouter.sol during timeout of a request + function deleteCommitment(bytes32 requestId) external override onlyRouter { + // Delete commitment + delete s_requestCommitments[requestId]; + emit CommitmentDeleted(requestId); + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function oracleWithdraw(address recipient, uint96 amount) external { + _disperseFeePool(); + + if (amount == 0) { + amount = s_withdrawableTokens[msg.sender]; + } else if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); + } + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Coordinator owner + function oracleWithdrawAll() external { + _onlyOwner(); + _disperseFeePool(); + + address[] memory transmitters = _getTransmitters(); + + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < transmitters.length; ++i) { + uint96 balance = s_withdrawableTokens[transmitters[i]]; + if (balance > 0) { + s_withdrawableTokens[transmitters[i]] = 0; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); + } + } + } + + // Overriden in FunctionsCoordinator, which has visibility into transmitters + function _getTransmitters() internal view virtual returns (address[] memory); + + // DON fees are collected into a pool s_feePool + // When OCR configuration changes, or any oracle withdraws, this must be dispersed + function _disperseFeePool() internal { + if (s_feePool == 0) { + return; + } + // All transmitters are assumed to also be observers + // Pay out the DON fee to all transmitters + address[] memory transmitters = _getTransmitters(); + uint256 numberOfTransmitters = transmitters.length; + if (numberOfTransmitters == 0) { + revert NoTransmittersSet(); + } + uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); + if (feePoolShare == 0) { + // Dust cannot be evenly distributed to all transmitters + return; + } + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < numberOfTransmitters; ++i) { + s_withdrawableTokens[transmitters[i]] += feePoolShare; + } + s_feePool -= feePoolShare * uint96(numberOfTransmitters); + } + + // Overriden in FunctionsCoordinator.sol + function _onlyOwner() internal view virtual; + + // Used in FunctionsCoordinator.sol + function _isExistingRequest(bytes32 requestId) internal view returns (bool) { + return s_requestCommitments[requestId] != bytes32(0); + } + + // Overriden in FunctionsCoordinator.sol + function _owner() internal view virtual returns (address owner); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol new file mode 100644 index 0000000..378714d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; +import {IFunctionsClient} from "./interfaces/IFunctionsClient.sol"; + +import {FunctionsRequest} from "./libraries/FunctionsRequest.sol"; + +/// @title The Chainlink Functions client contract +/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests +abstract contract FunctionsClient is IFunctionsClient { + using FunctionsRequest for FunctionsRequest.Request; + + IFunctionsRouter internal immutable i_functionsRouter; + + event RequestSent(bytes32 indexed id); + event RequestFulfilled(bytes32 indexed id); + + error OnlyRouterCanFulfill(); + + constructor(address router) { + i_functionsRouter = IFunctionsRouter(router); + } + + /// @notice Sends a Chainlink Functions request + /// @param data The CBOR encoded bytes data for a Functions request + /// @param subscriptionId The subscription ID that will be charged to service the request + /// @param callbackGasLimit - The amount of gas that will be available for the fulfillment callback + /// @param donId - An identifier used to determine which route to send the request along + /// @return requestId The generated request ID for this request + function _sendRequest( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) internal returns (bytes32) { + bytes32 requestId = i_functionsRouter.sendRequest( + subscriptionId, + data, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + donId + ); + emit RequestSent(requestId); + return requestId; + } + + /// @notice User defined function to handle a response from the DON + /// @param requestId The request ID, returned by sendRequest() + /// @param response Aggregated response from the execution of the user's source code + /// @param err Aggregated error from the execution of the user code or from the execution pipeline + /// @dev Either response or error parameter will be set, but never both + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; + + /// @inheritdoc IFunctionsClient + function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { + if (msg.sender != address(i_functionsRouter)) { + revert OnlyRouterCanFulfill(); + } + _fulfillRequest(requestId, response, err); + emit RequestFulfilled(requestId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol new file mode 100644 index 0000000..69d6f3a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {FunctionsBilling, FunctionsBillingConfig} from "./FunctionsBilling.sol"; +import {OCR2Base} from "./ocr/OCR2Base.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +/// @title Functions Coordinator contract +/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with +contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + /// @inheritdoc ITypeAndVersion + string public constant override typeAndVersion = "Functions Coordinator v1.3.1"; + + event OracleRequest( + bytes32 indexed requestId, + address indexed requestingContract, + address requestInitiator, + uint64 subscriptionId, + address subscriptionOwner, + bytes data, + uint16 dataVersion, + bytes32 flags, + uint64 callbackGasLimit, + FunctionsResponse.Commitment commitment + ); + event OracleResponse(bytes32 indexed requestId, address transmitter); + + error InconsistentReportData(); + error EmptyPublicKey(); + error UnauthorizedPublicKeyChange(); + + bytes private s_donPublicKey; + bytes private s_thresholdPublicKey; + + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed, linkToUsdFeed) {} + + /// @inheritdoc IFunctionsCoordinator + function getThresholdPublicKey() external view override returns (bytes memory) { + if (s_thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { + if (thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_thresholdPublicKey = thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function getDONPublicKey() external view override returns (bytes memory) { + if (s_donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_donPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { + if (donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_donPublicKey = donPublicKey; + } + + /// @dev check if node is in current transmitter list + function _isTransmitter(address node) internal view returns (bool) { + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < s_transmitters.length; ++i) { + if (s_transmitters[i] == node) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsCoordinator + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { + uint72 operationFee; + (commitment, operationFee) = _startBilling(request); + + emit OracleRequest( + commitment.requestId, + request.requestingContract, + // solhint-disable-next-line avoid-tx-origin + tx.origin, + request.subscriptionId, + request.subscriptionOwner, + request.data, + request.dataVersion, + request.flags, + request.callbackGasLimit, + FunctionsResponse.Commitment({ + coordinator: commitment.coordinator, + client: commitment.client, + subscriptionId: commitment.subscriptionId, + callbackGasLimit: commitment.callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, + // The following line is done to use the Coordinator's operationFee in place of the Router's operation fee + // With this in place the Router.adminFee must be set to 0 in the Router. + adminFee: operationFee + }) + ); + + return commitment; + } + + /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. + function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { + if (_getTransmitters().length > 0) { + _disperseFeePool(); + } + } + + /// @dev Used by FunctionsBilling.sol + function _getTransmitters() internal view override returns (address[] memory) { + return s_transmitters; + } + + function _beforeTransmit( + bytes calldata report + ) internal view override returns (bool shouldStop, DecodedReport memory decodedReport) { + ( + bytes32[] memory requestIds, + bytes[] memory results, + bytes[] memory errors, + bytes[] memory onchainMetadata, + bytes[] memory offchainMetadata + ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); + uint256 numberOfFulfillments = uint8(requestIds.length); + + if ( + numberOfFulfillments == 0 || + numberOfFulfillments != results.length || + numberOfFulfillments != errors.length || + numberOfFulfillments != onchainMetadata.length || + numberOfFulfillments != offchainMetadata.length + ) { + revert ReportInvalid("Fields must be equal length"); + } + + for (uint256 i = 0; i < numberOfFulfillments; ++i) { + if (_isExistingRequest(requestIds[i])) { + // If there is an existing request, validate report + // Leave shouldStop to default, false + break; + } + if (i == numberOfFulfillments - 1) { + // If the last fulfillment on the report does not exist, then all are duplicates + // Indicate that it's safe to stop to save on the gas of validating the report + shouldStop = true; + } + } + + return ( + shouldStop, + DecodedReport({ + requestIds: requestIds, + results: results, + errors: errors, + onchainMetadata: onchainMetadata, + offchainMetadata: offchainMetadata + }) + ); + } + + /// @dev Report hook called within OCR2Base.sol + function _report(DecodedReport memory decodedReport) internal override { + uint256 numberOfFulfillments = uint8(decodedReport.requestIds.length); + + // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig + for (uint256 i = 0; i < numberOfFulfillments; ++i) { + FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( + _fulfillAndBill( + decodedReport.requestIds[i], + decodedReport.results[i], + decodedReport.errors[i], + decodedReport.onchainMetadata[i], + decodedReport.offchainMetadata[i], + uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig + ) + ); + + // Emit on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the DON will re-try + if ( + result == FunctionsResponse.FulfillResult.FULFILLED || + result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + emit OracleResponse(decodedReport.requestIds[i], msg.sender); + } + } + } + + /// @dev Used in FunctionsBilling.sol + function _onlyOwner() internal view override { + _validateOwnership(); + } + + /// @dev Used in FunctionsBilling.sol + function _owner() internal view override returns (address owner) { + return this.owner(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol new file mode 100644 index 0000000..ec1ccbd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol @@ -0,0 +1,587 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; +import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; +import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; + +import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; + +import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {Pausable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; + +contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + string public constant override typeAndVersion = "Functions Router v2.0.0"; + + // We limit return data to a selector plus 4 words. This is to avoid + // malicious contracts from returning large amounts of data and causing + // repeated out-of-gas scenarios. + uint16 public constant MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32; + uint8 private constant MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + + event RequestProcessed( + bytes32 indexed requestId, + uint64 indexed subscriptionId, + uint96 totalCostJuels, + address transmitter, + FunctionsResponse.FulfillResult resultCode, + bytes response, + bytes err, + bytes callbackReturnData + ); + + event RequestNotProcessed( + bytes32 indexed requestId, + address coordinator, + address transmitter, + FunctionsResponse.FulfillResult resultCode + ); + + error EmptyRequestData(); + error OnlyCallableFromCoordinator(); + error SenderMustAcceptTermsOfService(address sender); + error InvalidGasFlagValue(uint8 value); + error GasLimitTooBig(uint32 limit); + error DuplicateRequestId(bytes32 requestId); + + struct CallbackResult { + bool success; // ══════╸ Whether the callback succeeded or not + uint256 gasUsed; // ═══╸ The amount of gas consumed during the callback + bytes returnData; // ══╸ The return of the callback function + } + + // ================================================================ + // | Route state | + // ================================================================ + + mapping(bytes32 id => address routableContract) private s_route; + + error RouteNotFound(bytes32 id); + + // Identifier for the route to the Terms of Service Allow List + bytes32 private s_allowListId; + + // ================================================================ + // | Configuration state | + // ================================================================ + // solhint-disable-next-line gas-struct-packing + struct Config { + uint16 maxConsumersPerSubscription; // ═════════╗ Maximum number of consumers which can be added to a single subscription. This bound ensures we are able to loop over all subscription consumers as needed, without exceeding gas limits. Should a user require more consumers, they can use multiple subscriptions. + uint72 adminFee; // ║ Flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network + bytes4 handleOracleFulfillmentSelector; // ║ The function selector that is used when calling back to the Client contract + uint16 gasForCallExactCheck; // ════════════════╝ Used during calling back to the client. Ensures we have at least enough gas to be able to revert if gasAmount > 63//64*gas available. + uint32[] maxCallbackGasLimits; // ══════════════╸ List of max callback gas limits used by flag with MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX + uint16 subscriptionDepositMinimumRequests; //═══╗ Amount of requests that must be completed before the full subscription balance will be released when closing a subscription account. + uint72 subscriptionDepositJuels; // ════════════╝ Amount of subscription funds that are held as a deposit until Config.subscriptionDepositMinimumRequests are made using the subscription. + } + + Config private s_config; + + event ConfigUpdated(Config); + + // ================================================================ + // | Proposal state | + // ================================================================ + + uint8 private constant MAX_PROPOSAL_SET_LENGTH = 8; + + struct ContractProposalSet { + bytes32[] ids; // ══╸ The IDs that key into the routes that will be modified if the update is applied + address[] to; // ═══╸ The address of the contracts that the route will point to if the updated is applied + } + ContractProposalSet private s_proposedContractSet; + + event ContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ); + + event ContractUpdated(bytes32 id, address from, address to); + + error InvalidProposal(); + error IdentifierIsReserved(bytes32 id); + + // ================================================================ + // | Initialization | + // ================================================================ + + constructor( + address linkToken, + Config memory config + ) FunctionsSubscriptions(linkToken) ConfirmedOwner(msg.sender) Pausable() { + // Set the intial configuration + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice The identifier of the route to retrieve the address of the access control contract + // The access control contract controls which accounts can manage subscriptions + /// @return id - bytes32 id that can be passed to the "getContractById" of the Router + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice The router configuration + function updateConfig(Config memory config) public onlyOwner { + s_config = config; + emit ConfigUpdated(config); + } + + /// @inheritdoc IFunctionsRouter + function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) public view { + uint8 callbackGasLimitsIndexSelector = uint8(getFlags(subscriptionId)[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + if (callbackGasLimitsIndexSelector >= s_config.maxCallbackGasLimits.length) { + revert InvalidGasFlagValue(callbackGasLimitsIndexSelector); + } + uint32 maxCallbackGasLimit = s_config.maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + if (callbackGasLimit > maxCallbackGasLimit) { + revert GasLimitTooBig(maxCallbackGasLimit); + } + } + + /// @inheritdoc IFunctionsRouter + function getAdminFee() external view override returns (uint72) { + return s_config.adminFee; + } + + /// @inheritdoc IFunctionsRouter + function getAllowListId() external view override returns (bytes32) { + return s_allowListId; + } + + /// @inheritdoc IFunctionsRouter + function setAllowListId(bytes32 allowListId) external override onlyOwner { + s_allowListId = allowListId; + } + + /// @dev Used within FunctionsSubscriptions.sol + function _getMaxConsumers() internal view override returns (uint16) { + return s_config.maxConsumersPerSubscription; + } + + /// @dev Used within FunctionsSubscriptions.sol + function _getSubscriptionDepositDetails() internal view override returns (uint16, uint72) { + return (s_config.subscriptionDepositMinimumRequests, s_config.subscriptionDepositJuels); + } + + // ================================================================ + // | Requests | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function sendRequest( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external override returns (bytes32) { + IFunctionsCoordinator coordinator = IFunctionsCoordinator(getContractById(donId)); + return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); + } + + /// @inheritdoc IFunctionsRouter + function sendRequestToProposed( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external override returns (bytes32) { + IFunctionsCoordinator coordinator = IFunctionsCoordinator(getProposedContractById(donId)); + return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); + } + + function _sendRequest( + bytes32 donId, + IFunctionsCoordinator coordinator, + uint64 subscriptionId, + bytes memory data, + uint16 dataVersion, + uint32 callbackGasLimit + ) private returns (bytes32) { + _whenNotPaused(); + _isExistingSubscription(subscriptionId); + _isAllowedConsumer(msg.sender, subscriptionId); + isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + + if (data.length == 0) { + revert EmptyRequestData(); + } + + Subscription memory subscription = getSubscription(subscriptionId); + Consumer memory consumer = getConsumer(msg.sender, subscriptionId); + uint72 adminFee = s_config.adminFee; + + // Forward request to DON + FunctionsResponse.Commitment memory commitment = coordinator.startRequest( + FunctionsResponse.RequestMeta({ + requestingContract: msg.sender, + data: data, + subscriptionId: subscriptionId, + dataVersion: dataVersion, + flags: getFlags(subscriptionId), + callbackGasLimit: callbackGasLimit, + adminFee: adminFee, + initiatedRequests: consumer.initiatedRequests, + completedRequests: consumer.completedRequests, + availableBalance: subscription.balance - subscription.blockedBalance, + subscriptionOwner: subscription.owner + }) + ); + + // Do not allow setting a comittment for a requestId that already exists + if (s_requestCommitments[commitment.requestId] != bytes32(0)) { + revert DuplicateRequestId(commitment.requestId); + } + + // Store a commitment about the request + s_requestCommitments[commitment.requestId] = keccak256( + abi.encode( + FunctionsResponse.Commitment({ + adminFee: adminFee, + coordinator: address(coordinator), + client: msg.sender, + subscriptionId: subscriptionId, + callbackGasLimit: callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback + }) + ) + ); + + _markRequestInFlight(msg.sender, subscriptionId, commitment.estimatedTotalCostJuels); + + emit RequestStart({ + requestId: commitment.requestId, + donId: donId, + subscriptionId: subscriptionId, + subscriptionOwner: subscription.owner, + requestingContract: msg.sender, + // solhint-disable-next-line avoid-tx-origin + requestInitiator: tx.origin, + data: data, + dataVersion: dataVersion, + callbackGasLimit: callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels + }); + + return commitment.requestId; + } + + // ================================================================ + // | Responses | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function fulfill( + bytes memory response, + bytes memory err, + uint96 juelsPerGas, + uint96 costWithoutFulfillment, + address transmitter, + FunctionsResponse.Commitment memory commitment + ) external override returns (FunctionsResponse.FulfillResult resultCode, uint96) { + _whenNotPaused(); + + if (msg.sender != commitment.coordinator) { + revert OnlyCallableFromCoordinator(); + } + + { + bytes32 commitmentHash = s_requestCommitments[commitment.requestId]; + + if (commitmentHash == bytes32(0)) { + resultCode = FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + if (keccak256(abi.encode(commitment)) != commitmentHash) { + resultCode = FunctionsResponse.FulfillResult.INVALID_COMMITMENT; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + // Check that the transmitter has supplied enough gas for the callback to succeed + if (gasleft() < commitment.callbackGasLimit + commitment.gasOverheadAfterCallback) { + resultCode = FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + } + + { + uint96 callbackCost = juelsPerGas * SafeCast.toUint96(commitment.callbackGasLimit); + uint96 totalCostJuels = commitment.adminFee + costWithoutFulfillment + callbackCost; + + // Check that the subscription can still afford to fulfill the request + if (totalCostJuels > getSubscription(commitment.subscriptionId).balance) { + resultCode = FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + // Check that the cost has not exceeded the quoted cost + if (totalCostJuels > commitment.estimatedTotalCostJuels) { + resultCode = FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + } + + delete s_requestCommitments[commitment.requestId]; + + CallbackResult memory result = _callback( + commitment.requestId, + response, + err, + commitment.callbackGasLimit, + commitment.client + ); + + resultCode = result.success + ? FunctionsResponse.FulfillResult.FULFILLED + : FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR; + + Receipt memory receipt = _pay( + commitment.subscriptionId, + commitment.estimatedTotalCostJuels, + commitment.client, + commitment.adminFee, + juelsPerGas, + SafeCast.toUint96(result.gasUsed), + costWithoutFulfillment + ); + + emit RequestProcessed({ + requestId: commitment.requestId, + subscriptionId: commitment.subscriptionId, + totalCostJuels: receipt.totalCostJuels, + transmitter: transmitter, + resultCode: resultCode, + response: response, + err: err, + callbackReturnData: result.returnData + }); + + return (resultCode, receipt.callbackGasCostJuels); + } + + function _callback( + bytes32 requestId, + bytes memory response, + bytes memory err, + uint32 callbackGasLimit, + address client + ) private returns (CallbackResult memory) { + bool destinationNoLongerExists; + assembly { + // solidity calls check that a contract actually exists at the destination, so we do the same + destinationNoLongerExists := iszero(extcodesize(client)) + } + if (destinationNoLongerExists) { + // Return without attempting callback + // The subscription will still be charged to reimburse transmitter's gas overhead + return CallbackResult({success: false, gasUsed: 0, returnData: new bytes(0)}); + } + + bytes memory encodedCallback = abi.encodeWithSelector( + s_config.handleOracleFulfillmentSelector, + requestId, + response, + err + ); + + uint16 gasForCallExactCheck = s_config.gasForCallExactCheck; + + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid payment. + // NOTE: that callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + + bool success; + uint256 gasUsed; + // allocate return data memory ahead of time + bytes memory returnData = new bytes(MAX_CALLBACK_RETURN_BYTES); + + assembly { + let g := gas() + // Compute g -= gasForCallExactCheck and check for underflow + // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. gasForCallExactCheck ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, gasForCallExactCheck) { + revert(0, 0) + } + g := sub(g, gasForCallExactCheck) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), callbackGasLimit)) { + revert(0, 0) + } + // call and report whether we succeeded + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + let gasBeforeCall := gas() + success := call(callbackGasLimit, client, 0, add(encodedCallback, 0x20), mload(encodedCallback), 0, 0) + gasUsed := sub(gasBeforeCall, gas()) + + // limit our copy to MAX_CALLBACK_RETURN_BYTES bytes + let toCopy := returndatasize() + if gt(toCopy, MAX_CALLBACK_RETURN_BYTES) { + toCopy := MAX_CALLBACK_RETURN_BYTES + } + // Store the length of the copied bytes + mstore(returnData, toCopy) + // copy the bytes from returnData[0:_toCopy] + returndatacopy(add(returnData, 0x20), 0, toCopy) + } + + return CallbackResult({success: success, gasUsed: gasUsed, returnData: returnData}); + } + + // ================================================================ + // | Route methods | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function getContractById(bytes32 id) public view override returns (address) { + address currentImplementation = s_route[id]; + if (currentImplementation == address(0)) { + revert RouteNotFound(id); + } + return currentImplementation; + } + + /// @inheritdoc IFunctionsRouter + function getProposedContractById(bytes32 id) public view override returns (address) { + // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint8 i = 0; i < s_proposedContractSet.ids.length; ++i) { + if (id == s_proposedContractSet.ids[i]) { + return s_proposedContractSet.to[i]; + } + } + revert RouteNotFound(id); + } + + // ================================================================ + // | Contract Proposal methods | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function getProposedContractSet() external view override returns (bytes32[] memory, address[] memory) { + return (s_proposedContractSet.ids, s_proposedContractSet.to); + } + + /// @inheritdoc IFunctionsRouter + function proposeContractsUpdate( + bytes32[] memory proposedContractSetIds, + address[] memory proposedContractSetAddresses + ) external override onlyOwner { + // IDs and addresses arrays must be of equal length and must not exceed the max proposal length + uint256 idsArrayLength = proposedContractSetIds.length; + if (idsArrayLength != proposedContractSetAddresses.length || idsArrayLength > MAX_PROPOSAL_SET_LENGTH) { + revert InvalidProposal(); + } + + // NOTE: iterations of this loop will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint256 i = 0; i < idsArrayLength; ++i) { + bytes32 id = proposedContractSetIds[i]; + address proposedContract = proposedContractSetAddresses[i]; + if ( + proposedContract == address(0) || // The Proposed address must be a valid address + s_route[id] == proposedContract // The Proposed address must point to a different address than what is currently set + ) { + revert InvalidProposal(); + } + + emit ContractProposed({ + proposedContractSetId: id, + proposedContractSetFromAddress: s_route[id], + proposedContractSetToAddress: proposedContract + }); + } + + s_proposedContractSet = ContractProposalSet({ids: proposedContractSetIds, to: proposedContractSetAddresses}); + } + + /// @inheritdoc IFunctionsRouter + function updateContracts() external override onlyOwner { + // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint256 i = 0; i < s_proposedContractSet.ids.length; ++i) { + bytes32 id = s_proposedContractSet.ids[i]; + address to = s_proposedContractSet.to[i]; + emit ContractUpdated({id: id, from: s_route[id], to: to}); + s_route[id] = to; + } + + delete s_proposedContractSet; + } + + // ================================================================ + // | Modifiers | + // ================================================================ + // Favoring internal functions over actual modifiers to reduce contract size + + /// @dev Used within FunctionsSubscriptions.sol + function _whenNotPaused() internal view override { + _requireNotPaused(); + } + + /// @dev Used within FunctionsSubscriptions.sol + function _onlyRouterOwner() internal view override { + _validateOwnership(); + } + + /// @dev Used within FunctionsSubscriptions.sol + function _onlySenderThatAcceptedToS() internal view override { + address currentImplementation = s_route[s_allowListId]; + if (currentImplementation == address(0)) { + // If not set, ignore this check, allow all access + return; + } + if (!IAccessController(currentImplementation).hasAccess(msg.sender, new bytes(0))) { + revert SenderMustAcceptTermsOfService(msg.sender); + } + } + + /// @inheritdoc IFunctionsRouter + function pause() external override onlyOwner { + _pause(); + } + + /// @inheritdoc IFunctionsRouter + function unpause() external override onlyOwner { + _unpause(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol new file mode 100644 index 0000000..bcd01c1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; +import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; +import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; + +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @title Functions Subscriptions contract +/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsSubscriptions is IFunctionsSubscriptions, IERC677Receiver { + using SafeERC20 for IERC20; + using FunctionsResponse for FunctionsResponse.Commitment; + + // ================================================================ + // | Balance state | + // ================================================================ + // link token address + IERC20 internal immutable i_linkToken; + + // s_totalLinkBalance tracks the total LINK sent to/from + // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. + // A discrepancy with this contract's LINK balance indicates that someone + // sent tokens using transfer and so we may need to use recoverFunds. + uint96 private s_totalLinkBalance; + + /// @dev NOP balances are held as a single amount. The breakdown is held by the Coordinator. + mapping(address coordinator => uint96 balanceJuelsLink) private s_withdrawableTokens; + + // ================================================================ + // | Subscription state | + // ================================================================ + // Keep a count of the number of subscriptions so that its possible to + // loop through all the current subscriptions via .getSubscription(). + uint64 private s_currentSubscriptionId; + + mapping(uint64 subscriptionId => Subscription) private s_subscriptions; + + // Maintains the list of keys in s_consumers. + // We do this for 2 reasons: + // 1. To be able to clean up all keys from s_consumers when canceling a subscription. + // 2. To be able to return the list of all consumers in getSubscription. + // Note that we need the s_consumers map to be able to directly check if a + // consumer is valid without reading all the consumers from storage. + mapping(address consumer => mapping(uint64 subscriptionId => Consumer)) private s_consumers; + + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); + + error TooManyConsumers(uint16 maximumConsumers); + error InsufficientBalance(uint96 currentBalanceJuels); + error InvalidConsumer(); + error CannotRemoveWithPendingRequests(); + error InvalidSubscription(); + error OnlyCallableFromLink(); + error InvalidCalldata(); + error MustBeSubscriptionOwner(); + error TimeoutNotExceeded(); + error MustBeProposedOwner(address proposedOwner); + event FundsRecovered(address to, uint256 amount); + + // ================================================================ + // | Request state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) internal s_requestCommitments; + + struct Receipt { + uint96 callbackGasCostJuels; + uint96 totalCostJuels; + } + + event RequestTimedOut(bytes32 indexed requestId); + + // ================================================================ + // | Initialization | + // ================================================================ + constructor(address link) { + i_linkToken = IERC20(link); + } + + // ================================================================ + // | Request/Response | + // ================================================================ + + /// @notice Sets a request as in-flight + /// @dev Only callable within the Router + function _markRequestInFlight(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) internal { + // Earmark subscription funds + s_subscriptions[subscriptionId].blockedBalance += estimatedTotalCostJuels; + + // Increment sent requests + s_consumers[client][subscriptionId].initiatedRequests += 1; + } + + /// @notice Moves funds from one subscription account to another. + /// @dev Only callable by the Coordinator contract that is saved in the request commitment + function _pay( + uint64 subscriptionId, + uint96 estimatedTotalCostJuels, + address client, + uint96 adminFee, + uint96 juelsPerGas, + uint96 gasUsed, + uint96 costWithoutCallbackJuels + ) internal returns (Receipt memory) { + uint96 callbackGasCostJuels = juelsPerGas * gasUsed; + uint96 totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels; + + if ( + s_subscriptions[subscriptionId].balance < totalCostJuels || + s_subscriptions[subscriptionId].blockedBalance < estimatedTotalCostJuels + ) { + revert InsufficientBalance(s_subscriptions[subscriptionId].balance); + } + + // Charge the subscription + s_subscriptions[subscriptionId].balance -= totalCostJuels; + + // Unblock earmarked funds + s_subscriptions[subscriptionId].blockedBalance -= estimatedTotalCostJuels; + + // Pay the DON's fees and gas reimbursement + s_withdrawableTokens[msg.sender] += costWithoutCallbackJuels + callbackGasCostJuels; + + // Pay out the administration fee + s_withdrawableTokens[address(this)] += adminFee; + + // Increment finished requests + s_consumers[client][subscriptionId].completedRequests += 1; + + return Receipt({callbackGasCostJuels: callbackGasCostJuels, totalCostJuels: totalCostJuels}); + } + + // ================================================================ + // | Owner methods | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function ownerCancelSubscription(uint64 subscriptionId) external override { + _onlyRouterOwner(); + _isExistingSubscription(subscriptionId); + _cancelSubscriptionHelper(subscriptionId, s_subscriptions[subscriptionId].owner, false); + } + + /// @inheritdoc IFunctionsSubscriptions + function recoverFunds(address to) external override { + _onlyRouterOwner(); + uint256 externalBalance = i_linkToken.balanceOf(address(this)); + uint256 internalBalance = uint256(s_totalLinkBalance); + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + i_linkToken.safeTransfer(to, amount); + emit FundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function oracleWithdraw(address recipient, uint96 amount) external override { + _whenNotPaused(); + + if (amount == 0) { + revert InvalidCalldata(); + } + uint96 currentBalance = s_withdrawableTokens[msg.sender]; + if (currentBalance < amount) { + revert InsufficientBalance(currentBalance); + } + s_withdrawableTokens[msg.sender] -= amount; + s_totalLinkBalance -= amount; + i_linkToken.safeTransfer(recipient, amount); + } + + /// @notice Owner withdraw LINK earned through admin fees + /// @notice If amount is 0 the full balance will be withdrawn + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function ownerWithdraw(address recipient, uint96 amount) external { + _onlyRouterOwner(); + if (amount == 0) { + amount = s_withdrawableTokens[address(this)]; + } + uint96 currentBalance = s_withdrawableTokens[address(this)]; + if (currentBalance < amount) { + revert InsufficientBalance(currentBalance); + } + s_withdrawableTokens[address(this)] -= amount; + s_totalLinkBalance -= amount; + + i_linkToken.safeTransfer(recipient, amount); + } + + // ================================================================ + // | TransferAndCall Deposit helper | + // ================================================================ + + // This function is to be invoked when using LINK.transferAndCall + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override { + _whenNotPaused(); + if (msg.sender != address(i_linkToken)) { + revert OnlyCallableFromLink(); + } + if (data.length != 32) { + revert InvalidCalldata(); + } + uint64 subscriptionId = abi.decode(data, (uint64)); + if (s_subscriptions[subscriptionId].owner == address(0)) { + revert InvalidSubscription(); + } + // We do not check that the msg.sender is the subscription owner, + // anyone can fund a subscription. + uint256 oldBalance = s_subscriptions[subscriptionId].balance; + s_subscriptions[subscriptionId].balance += uint96(amount); + s_totalLinkBalance += uint96(amount); + emit SubscriptionFunded(subscriptionId, oldBalance, oldBalance + amount); + } + + // ================================================================ + // | Subscription management | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function getTotalBalance() external view override returns (uint96) { + return s_totalLinkBalance; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscriptionCount() external view override returns (uint64) { + return s_currentSubscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscription(uint64 subscriptionId) public view override returns (Subscription memory) { + _isExistingSubscription(subscriptionId); + return s_subscriptions[subscriptionId]; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscriptionsInRange( + uint64 subscriptionIdStart, + uint64 subscriptionIdEnd + ) external view override returns (Subscription[] memory subscriptions) { + if ( + subscriptionIdStart > subscriptionIdEnd || + subscriptionIdEnd > s_currentSubscriptionId || + s_currentSubscriptionId == 0 + ) { + revert InvalidCalldata(); + } + + subscriptions = new Subscription[]((subscriptionIdEnd - subscriptionIdStart) + 1); + for (uint256 i = 0; i <= subscriptionIdEnd - subscriptionIdStart; ++i) { + subscriptions[i] = s_subscriptions[uint64(subscriptionIdStart + i)]; + } + + return subscriptions; + } + + /// @inheritdoc IFunctionsSubscriptions + function getConsumer(address client, uint64 subscriptionId) public view override returns (Consumer memory) { + return s_consumers[client][subscriptionId]; + } + + /// @dev Used within this file & FunctionsRouter.sol + function _isExistingSubscription(uint64 subscriptionId) internal view { + if (s_subscriptions[subscriptionId].owner == address(0)) { + revert InvalidSubscription(); + } + } + + /// @dev Used within FunctionsRouter.sol + function _isAllowedConsumer(address client, uint64 subscriptionId) internal view { + if (!s_consumers[client][subscriptionId].allowed) { + revert InvalidConsumer(); + } + } + + /// @inheritdoc IFunctionsSubscriptions + function createSubscription() external override returns (uint64 subscriptionId) { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + subscriptionId = ++s_currentSubscriptionId; + s_subscriptions[subscriptionId] = Subscription({ + balance: 0, + blockedBalance: 0, + owner: msg.sender, + proposedOwner: address(0), + consumers: new address[](0), + flags: bytes32(0) + }); + + emit SubscriptionCreated(subscriptionId, msg.sender); + + return subscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function createSubscriptionWithConsumer(address consumer) external override returns (uint64 subscriptionId) { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + subscriptionId = ++s_currentSubscriptionId; + s_subscriptions[subscriptionId] = Subscription({ + balance: 0, + blockedBalance: 0, + owner: msg.sender, + proposedOwner: address(0), + consumers: new address[](0), + flags: bytes32(0) + }); + + s_subscriptions[subscriptionId].consumers.push(consumer); + s_consumers[consumer][subscriptionId].allowed = true; + + emit SubscriptionCreated(subscriptionId, msg.sender); + emit SubscriptionConsumerAdded(subscriptionId, consumer); + + return subscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + if (newOwner == address(0) || s_subscriptions[subscriptionId].proposedOwner == newOwner) { + revert InvalidCalldata(); + } + + s_subscriptions[subscriptionId].proposedOwner = newOwner; + emit SubscriptionOwnerTransferRequested(subscriptionId, msg.sender, newOwner); + } + + /// @inheritdoc IFunctionsSubscriptions + function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external override { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + address previousOwner = s_subscriptions[subscriptionId].owner; + address proposedOwner = s_subscriptions[subscriptionId].proposedOwner; + if (proposedOwner != msg.sender) { + revert MustBeProposedOwner(proposedOwner); + } + s_subscriptions[subscriptionId].owner = msg.sender; + s_subscriptions[subscriptionId].proposedOwner = address(0); + emit SubscriptionOwnerTransferred(subscriptionId, previousOwner, msg.sender); + } + + /// @inheritdoc IFunctionsSubscriptions + function removeConsumer(uint64 subscriptionId, address consumer) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + Consumer memory consumerData = s_consumers[consumer][subscriptionId]; + _isAllowedConsumer(consumer, subscriptionId); + if (consumerData.initiatedRequests != consumerData.completedRequests) { + revert CannotRemoveWithPendingRequests(); + } + // Note bounded by config.maxConsumers + address[] memory consumers = s_subscriptions[subscriptionId].consumers; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == consumer) { + // Storage write to preserve last element + s_subscriptions[subscriptionId].consumers[i] = consumers[consumers.length - 1]; + // Storage remove last element + s_subscriptions[subscriptionId].consumers.pop(); + break; + } + } + delete s_consumers[consumer][subscriptionId]; + emit SubscriptionConsumerRemoved(subscriptionId, consumer); + } + + /// @dev Overriden in FunctionsRouter.sol + function _getMaxConsumers() internal view virtual returns (uint16); + + /// @inheritdoc IFunctionsSubscriptions + function addConsumer(uint64 subscriptionId, address consumer) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + // Already maxed, cannot add any more consumers. + uint16 maximumConsumers = _getMaxConsumers(); + if (s_subscriptions[subscriptionId].consumers.length >= maximumConsumers) { + revert TooManyConsumers(maximumConsumers); + } + if (s_consumers[consumer][subscriptionId].allowed) { + // Idempotence - do nothing if already added. + // Ensures uniqueness in s_subscriptions[subscriptionId].consumers. + return; + } + + s_consumers[consumer][subscriptionId].allowed = true; + s_subscriptions[subscriptionId].consumers.push(consumer); + + emit SubscriptionConsumerAdded(subscriptionId, consumer); + } + + /// @dev Overriden in FunctionsRouter.sol + function _getSubscriptionDepositDetails() internal virtual returns (uint16, uint72); + + function _cancelSubscriptionHelper(uint64 subscriptionId, address toAddress, bool checkDepositRefundability) private { + Subscription memory subscription = s_subscriptions[subscriptionId]; + uint96 balance = subscription.balance; + uint64 completedRequests = 0; + + // NOTE: loop iterations are bounded by config.maxConsumers + // If no consumers, does nothing. + for (uint256 i = 0; i < subscription.consumers.length; ++i) { + address consumer = subscription.consumers[i]; + completedRequests += s_consumers[consumer][subscriptionId].completedRequests; + delete s_consumers[consumer][subscriptionId]; + } + delete s_subscriptions[subscriptionId]; + + (uint16 subscriptionDepositMinimumRequests, uint72 subscriptionDepositJuels) = _getSubscriptionDepositDetails(); + + // If subscription has not made enough requests, deposit will be forfeited + if (checkDepositRefundability && completedRequests < subscriptionDepositMinimumRequests) { + uint96 deposit = subscriptionDepositJuels > balance ? balance : subscriptionDepositJuels; + if (deposit > 0) { + s_withdrawableTokens[address(this)] += deposit; + balance -= deposit; + } + } + + if (balance > 0) { + s_totalLinkBalance -= balance; + i_linkToken.safeTransfer(toAddress, uint256(balance)); + } + emit SubscriptionCanceled(subscriptionId, toAddress, balance); + } + + /// @inheritdoc IFunctionsSubscriptions + function cancelSubscription(uint64 subscriptionId, address to) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + if (pendingRequestExists(subscriptionId)) { + revert CannotRemoveWithPendingRequests(); + } + + _cancelSubscriptionHelper(subscriptionId, to, true); + } + + /// @inheritdoc IFunctionsSubscriptions + function pendingRequestExists(uint64 subscriptionId) public view override returns (bool) { + address[] memory consumers = s_subscriptions[subscriptionId].consumers; + // NOTE: loop iterations are bounded by config.maxConsumers + for (uint256 i = 0; i < consumers.length; ++i) { + Consumer memory consumer = s_consumers[consumers[i]][subscriptionId]; + if (consumer.initiatedRequests != consumer.completedRequests) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsSubscriptions + function setFlags(uint64 subscriptionId, bytes32 flags) external override { + _onlyRouterOwner(); + _isExistingSubscription(subscriptionId); + s_subscriptions[subscriptionId].flags = flags; + } + + /// @inheritdoc IFunctionsSubscriptions + function getFlags(uint64 subscriptionId) public view returns (bytes32) { + return s_subscriptions[subscriptionId].flags; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external override { + _whenNotPaused(); + + for (uint256 i = 0; i < requestsToTimeoutByCommitment.length; ++i) { + FunctionsResponse.Commitment memory request = requestsToTimeoutByCommitment[i]; + bytes32 requestId = request.requestId; + uint64 subscriptionId = request.subscriptionId; + + // Check that request ID is valid + if (keccak256(abi.encode(request)) != s_requestCommitments[requestId]) { + revert InvalidCalldata(); + } + + // Check that request has exceeded allowed request time + if (block.timestamp < request.timeoutTimestamp) { + revert TimeoutNotExceeded(); + } + + // Notify the Coordinator that the request should no longer be fulfilled + IFunctionsBilling(request.coordinator).deleteCommitment(requestId); + // Release the subscription's balance that had been earmarked for the request + s_subscriptions[subscriptionId].blockedBalance -= request.estimatedTotalCostJuels; + s_consumers[request.client][subscriptionId].completedRequests += 1; + // Delete commitment within Router state + delete s_requestCommitments[requestId]; + + emit RequestTimedOut(requestId); + } + } + + // ================================================================ + // | Modifiers | + // ================================================================ + + function _onlySubscriptionOwner(uint64 subscriptionId) internal view { + address owner = s_subscriptions[subscriptionId].owner; + if (owner == address(0)) { + revert InvalidSubscription(); + } + if (msg.sender != owner) { + revert MustBeSubscriptionOwner(); + } + } + + /// @dev Overriden in FunctionsRouter.sol + function _onlySenderThatAcceptedToS() internal virtual; + + /// @dev Overriden in FunctionsRouter.sol + function _onlyRouterOwner() internal virtual; + + /// @dev Overriden in FunctionsRouter.sol + function _whenNotPaused() internal virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol new file mode 100644 index 0000000..92e2336 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IOwnableFunctionsRouter} from "./interfaces/IOwnableFunctionsRouter.sol"; + +/// @title This abstract should be inherited by contracts that will be used +/// as the destinations to a route (id=>contract) on the Router. +/// It provides a Router getter and modifiers. +abstract contract Routable is ITypeAndVersion { + IOwnableFunctionsRouter private immutable i_functionsRouter; + + error RouterMustBeSet(); + error OnlyCallableByRouter(); + error OnlyCallableByRouterOwner(); + + /// @dev Initializes the contract. + constructor(address router) { + if (router == address(0)) { + revert RouterMustBeSet(); + } + i_functionsRouter = IOwnableFunctionsRouter(router); + } + + /// @notice Return the Router + function _getRouter() internal view returns (IOwnableFunctionsRouter router) { + return i_functionsRouter; + } + + /// @notice Reverts if called by anyone other than the router. + modifier onlyRouter() { + if (msg.sender != address(i_functionsRouter)) { + revert OnlyCallableByRouter(); + } + _; + } + + /// @notice Reverts if called by anyone other than the router owner. + modifier onlyRouterOwner() { + if (msg.sender != i_functionsRouter.owner()) { + revert OnlyCallableByRouterOwner(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol new file mode 100644 index 0000000..0ba8e5d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITermsOfServiceAllowList, TermsOfServiceAllowListConfig} from "./interfaces/ITermsOfServiceAllowList.sol"; +import {IAccessController} from "../../../../shared/interfaces/IAccessController.sol"; +import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol"; + +import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; + +import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.AddressSet; + + /// @inheritdoc ITypeAndVersion + string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.1"; + address private s_previousToSContract; + + EnumerableSet.AddressSet private s_allowedSenders; + EnumerableSet.AddressSet private s_blockedSenders; + + event AddedAccess(address user); + event BlockedAccess(address user); + event UnblockedAccess(address user); + + error InvalidSignature(); + error InvalidUsage(); + error RecipientIsBlocked(); + error InvalidCalldata(); + error NoPreviousToSContract(); + + TermsOfServiceAllowListConfig private s_config; + + event ConfigUpdated(TermsOfServiceAllowListConfig config); + + // ================================================================ + // | Initialization | + // ================================================================ + + constructor( + TermsOfServiceAllowListConfig memory config, + address[] memory initialAllowedSenders, + address[] memory initialBlockedSenders, + address previousToSContract + ) ConfirmedOwner(msg.sender) { + updateConfig(config); + + for (uint256 i = 0; i < initialAllowedSenders.length; ++i) { + s_allowedSenders.add(initialAllowedSenders[i]); + } + + for (uint256 j = 0; j < initialBlockedSenders.length; ++j) { + if (s_allowedSenders.contains(initialBlockedSenders[j])) { + // Allowed senders cannot also be blocked + revert InvalidCalldata(); + } + s_blockedSenders.add(initialBlockedSenders[j]); + } + + s_previousToSContract = previousToSContract; + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the contracts's configuration + /// @return config + function getConfig() external view returns (TermsOfServiceAllowListConfig memory) { + return s_config; + } + + /// @notice Sets the contracts's configuration + /// @param config - See the contents of the TermsOfServiceAllowListConfig struct in ITermsOfServiceAllowList.sol for more information + function updateConfig(TermsOfServiceAllowListConfig memory config) public onlyOwner { + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Allow methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { + return keccak256(abi.encodePacked(acceptor, recipient)); + } + + /// @inheritdoc ITermsOfServiceAllowList + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { + if (s_blockedSenders.contains(recipient)) { + revert RecipientIsBlocked(); + } + + // Validate that the signature is correct and the correct data has been signed + bytes32 prefixedMessage = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) + ); + if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { + revert InvalidSignature(); + } + + // If contract, validate that msg.sender == recipient + // This is to prevent EoAs from claiming contracts that they are not in control of + // If EoA, validate that msg.sender == acceptor == recipient + // This is to prevent EoAs from accepting for other EoAs + if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { + revert InvalidUsage(); + } + + // Add recipient to the allow list + if (s_allowedSenders.add(recipient)) { + emit AddedAccess(recipient); + } + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllAllowedSenders() external view override returns (address[] memory) { + return s_allowedSenders.values(); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllowedSendersCount() external view override returns (uint64) { + return uint64(s_allowedSenders.length()); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllowedSendersInRange( + uint64 allowedSenderIdxStart, + uint64 allowedSenderIdxEnd + ) external view override returns (address[] memory allowedSenders) { + if (allowedSenderIdxStart > allowedSenderIdxEnd || allowedSenderIdxEnd >= s_allowedSenders.length()) { + revert InvalidCalldata(); + } + + allowedSenders = new address[]((allowedSenderIdxEnd - allowedSenderIdxStart) + 1); + for (uint256 i = 0; i <= allowedSenderIdxEnd - allowedSenderIdxStart; ++i) { + allowedSenders[i] = s_allowedSenders.at(uint256(allowedSenderIdxStart + i)); + } + + return allowedSenders; + } + + /// @inheritdoc IAccessController + function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { + if (!s_config.enabled) { + return true; + } + return s_allowedSenders.contains(user); + } + + // ================================================================ + // | Block methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function isBlockedSender(address sender) external view override returns (bool) { + if (!s_config.enabled) { + return false; + } + return s_blockedSenders.contains(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function blockSender(address sender) external override onlyOwner { + s_allowedSenders.remove(sender); + s_blockedSenders.add(sender); + emit BlockedAccess(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function unblockSender(address sender) external override onlyOwner { + s_blockedSenders.remove(sender); + emit UnblockedAccess(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getBlockedSendersCount() external view override returns (uint64) { + return uint64(s_blockedSenders.length()); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getBlockedSendersInRange( + uint64 blockedSenderIdxStart, + uint64 blockedSenderIdxEnd + ) external view override returns (address[] memory blockedSenders) { + if ( + blockedSenderIdxStart > blockedSenderIdxEnd || + blockedSenderIdxEnd >= s_blockedSenders.length() || + s_blockedSenders.length() == 0 + ) { + revert InvalidCalldata(); + } + + blockedSenders = new address[]((blockedSenderIdxEnd - blockedSenderIdxStart) + 1); + for (uint256 i = 0; i <= blockedSenderIdxEnd - blockedSenderIdxStart; ++i) { + blockedSenders[i] = s_blockedSenders.at(uint256(blockedSenderIdxStart + i)); + } + + return blockedSenders; + } + + /// @inheritdoc ITermsOfServiceAllowList + function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external override onlyOwner { + if (s_previousToSContract == address(0)) { + revert NoPreviousToSContract(); + } + IAccessController previousToSContract = IAccessController(s_previousToSContract); + for (uint256 i = 0; i < previousSendersToAdd.length; ++i) { + if (previousToSContract.hasAccess(previousSendersToAdd[i], "")) { + if (!s_blockedSenders.contains(previousSendersToAdd[i])) { + s_allowedSenders.add(previousSendersToAdd[i]); + } + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol new file mode 100644 index 0000000..32a0ece --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +interface ITermsOfServiceAllowList { + /// @notice Return the message data for the proof given to accept the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @return Hash of the message data + function getMessage(address acceptor, address recipient) external pure returns (bytes32); + + /// @notice Check if the address is blocked for usage + /// @param sender The transaction sender's address + /// @return True or false + function isBlockedSender(address sender) external returns (bool); + + /// @notice Get a list of all allowed senders + /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + /// this function has an unbounded cost, and using it as part of a state-changing function may render the function + /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + /// @return addresses - all allowed addresses + function getAllAllowedSenders() external view returns (address[] memory); + + /// @notice Get details about the total number of allowed senders + /// @return count - total number of allowed senders in the system + function getAllowedSendersCount() external view returns (uint64); + + /// @notice Retrieve a list of allowed senders using an inclusive range + /// @dev WARNING: getAllowedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list + /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. + /// Evaluate if eventual consistency will satisfy your usecase before using it. + /// @param allowedSenderIdxStart - index of the allowed sender to start the range at + /// @param allowedSenderIdxEnd - index of the allowed sender to end the range at + /// @return allowedSenders - allowed addresses in the range provided + function getAllowedSendersInRange( + uint64 allowedSenderIdxStart, + uint64 allowedSenderIdxEnd + ) external view returns (address[] memory allowedSenders); + + /// @notice Allows access to the sender based on acceptance of the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI + /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI + /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; + + /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service + /// @param sender - Address of the sender to block + function blockSender(address sender) external; + + /// @notice Re-allows a previously blocked sender to accept the Terms of Service + /// @param sender - Address of the sender to unblock + function unblockSender(address sender) external; + + /// @notice Get details about the total number of blocked senders + /// @return count - total number of blocked senders in the system + function getBlockedSendersCount() external view returns (uint64); + + /// @notice Retrieve a list of blocked senders using an inclusive range + /// @dev WARNING: getBlockedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list + /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. + /// Evaluate if eventual consistency will satisfy your usecase before using it. + /// @param blockedSenderIdxStart - index of the blocked sender to start the range at + /// @param blockedSenderIdxEnd - index of the blocked sender to end the range at + /// @return blockedSenders - blocked addresses in the range provided + function getBlockedSendersInRange( + uint64 blockedSenderIdxStart, + uint64 blockedSenderIdxEnd + ) external view returns (address[] memory blockedSenders); + + /// @notice Enables migrating any previously allowed senders to the new contract + /// @param previousSendersToAdd - List of addresses to migrate. These address must be allowed on the previous ToS contract and not blocked + function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external; +} + +// ================================================================ +// | Configuration state | +// ================================================================ +struct TermsOfServiceAllowListConfig { + bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. + address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol new file mode 100644 index 0000000..abb8569 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsClient} from "../FunctionsClient.sol"; +import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; +import {FunctionsRequest} from "../libraries/FunctionsRequest.sol"; + +/// @title Chainlink Functions example Client contract implementation +contract FunctionsClientExample is FunctionsClient, ConfirmedOwner { + using FunctionsRequest for FunctionsRequest.Request; + + uint32 public constant MAX_CALLBACK_GAS = 70_000; + + bytes32 public s_lastRequestId; + bytes32 public s_lastResponse; + bytes32 public s_lastError; + uint32 public s_lastResponseLength; + uint32 public s_lastErrorLength; + + error UnexpectedRequestID(bytes32 requestId); + + constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} + + /// @notice Send a simple request + /// @param source JavaScript source code + /// @param encryptedSecretsReferences Encrypted secrets payload + /// @param args List of arguments accessible from within the source code + /// @param subscriptionId Billing ID + function sendRequest( + string calldata source, + bytes calldata encryptedSecretsReferences, + string[] calldata args, + uint64 subscriptionId, + bytes32 jobId + ) external onlyOwner { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + if (encryptedSecretsReferences.length > 0) req._addSecretsReference(encryptedSecretsReferences); + if (args.length > 0) req._setArgs(args); + s_lastRequestId = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); + } + + /// @notice Store latest result/error + /// @param requestId The request ID, returned by sendRequest() + /// @param response Aggregated response from the user code + /// @param err Aggregated error from the user code or from the execution pipeline + /// @dev Either response or error parameter will be set, but never both + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + if (s_lastRequestId != requestId) { + revert UnexpectedRequestID(requestId); + } + // Save only the first 32 bytes of response/error to always fit within MAX_CALLBACK_GAS + s_lastResponse = _bytesToBytes32(response); + s_lastResponseLength = uint32(response.length); + s_lastError = _bytesToBytes32(err); + s_lastErrorLength = uint32(err.length); + } + + function _bytesToBytes32(bytes memory b) private pure returns (bytes32 out) { + uint256 maxLen = 32; + if (b.length < 32) { + maxLen = b.length; + } + for (uint256 i = 0; i < maxLen; ++i) { + out |= bytes32(b[i]) >> (i * 8); + } + return out; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol new file mode 100644 index 0000000..0f31f7f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Chainlink Functions DON billing interface. +interface IFunctionsBilling { + /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed + /// @return weiPerUnitLink - The amount of WEI in one LINK + function getWeiPerUnitLink() external view returns (uint256); + + /// @notice Return the current conversion from LINK to USD from the configured Chainlink data feed + /// @return weiPerUnitLink - The amount of USD that one LINK is worth + /// @return decimals - The number of decimals that should be represented in the price feed's response + function getUsdPerUnitLink() external view returns (uint256, uint8); + + /// @notice Determine the fee that will be split between Node Operators for servicing a request + /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request + /// @return fee - Cost in Juels (1e18) of LINK + function getDONFeeJuels(bytes memory requestCBOR) external view returns (uint72); + + /// @notice Determine the fee that will be paid to the Coordinator owner for operating the network + /// @return fee - Cost in Juels (1e18) of LINK + function getOperationFeeJuels() external view returns (uint72); + + /// @notice Determine the fee that will be paid to the Router owner for operating the network + /// @return fee - Cost in Juels (1e18) of LINK + function getAdminFeeJuels() external view returns (uint72); + + /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee + /// @param - subscriptionId An identifier of the billing account + /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param - callbackGasLimit Gas limit for the fulfillment callback + /// @param - gasPriceWei The blockchain's gas price to estimate with + /// @return - billedCost Cost in Juels (1e18) of LINK + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view returns (uint96); + + /// @notice Remove a request commitment that the Router has determined to be stale + /// @param requestId - The request ID to remove + function deleteCommitment(bytes32 requestId) external; + + /// @notice Oracle withdraw LINK earned through fulfilling requests + /// @notice If amount is 0 the full balance will be withdrawn + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function oracleWithdraw(address recipient, uint96 amount) external; + + /// @notice Withdraw all LINK earned by Oracles through fulfilling requests + /// @dev transmitter addresses must support LINK tokens to avoid tokens from getting stuck as oracleWithdrawAll() calls will forward tokens directly to transmitters + function oracleWithdrawAll() external; +} + +// ================================================================ +// | Configuration state | +// ================================================================ + +struct FunctionsBillingConfig { + uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) + uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. Default of 0 means no fallback. + uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. + uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. + uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request + uint16 maxSupportedRequestDataVersion; // ║ The highest support request data version supported by the node. All lower versions should also be supported. + uint64 fallbackUsdPerUnitLink; // ║ Fallback LINK / USD conversion rate if the data feed is stale + uint8 fallbackUsdPerUnitLinkDecimals; // ════════╝ Fallback LINK / USD conversion rate decimal places if the data feed is stale + 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 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. +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol new file mode 100644 index 0000000..f28a416 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Chainlink Functions client interface. +interface IFunctionsClient { + /// @notice Chainlink Functions response handler called by the Functions Router + /// during fullilment from the designated transmitter node in an OCR round. + /// @param requestId The requestId returned by FunctionsClient.sendRequest(). + /// @param response Aggregated response from the request's source code. + /// @param err Aggregated error either from the request's source code or from the execution pipeline. + /// @dev Either response or error parameter will be set, but never both. + function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol new file mode 100644 index 0000000..4e2bd70 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions DON Coordinator interface. +interface IFunctionsCoordinator { + /// @notice Returns the DON's threshold encryption public key used to encrypt secrets + /// @dev All nodes on the DON have separate key shares of the threshold decryption key + /// and nodes must participate in a threshold decryption OCR round to decrypt secrets + /// @return thresholdPublicKey the DON's threshold encryption public key + function getThresholdPublicKey() external view returns (bytes memory); + + /// @notice Sets the DON's threshold encryption public key used to encrypt secrets + /// @dev Used to rotate the key + /// @param thresholdPublicKey The new public key + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external; + + /// @notice Returns the DON's secp256k1 public key that is used to encrypt secrets + /// @dev All nodes on the DON have the corresponding private key + /// needed to decrypt the secrets encrypted with the public key + /// @return publicKey the DON's public key + function getDONPublicKey() external view returns (bytes memory); + + /// @notice Sets DON's secp256k1 public key used to encrypt secrets + /// @dev Used to rotate the key + /// @param donPublicKey The new public key + function setDONPublicKey(bytes calldata donPublicKey) external; + + /// @notice Receives a request to be emitted to the DON for processing + /// @param request The request metadata + /// @dev see the struct for field descriptions + /// @return commitment - The parameters of the request that must be held consistent at response time + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external returns (FunctionsResponse.Commitment memory commitment); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol new file mode 100644 index 0000000..5f93aac --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions Router interface. +interface IFunctionsRouter { + /// @notice The identifier of the route to retrieve the address of the access control contract + /// The access control contract controls which accounts can manage subscriptions + /// @return id - bytes32 id that can be passed to the "getContractById" of the Router + function getAllowListId() external view returns (bytes32); + + /// @notice Set the identifier of the route to retrieve the address of the access control contract + /// The access control contract controls which accounts can manage subscriptions + function setAllowListId(bytes32 allowListId) external; + + /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network + /// @return adminFee + function getAdminFee() external view returns (uint72 adminFee); + + /// @notice Sends a request using the provided subscriptionId + /// @param subscriptionId - A unique subscription ID allocated by billing system, + /// a client can make requests from different contracts referencing the same subscription + /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param dataVersion - Gas limit for the fulfillment callback + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @param donId - An identifier used to determine which route to send the request along + /// @return requestId - A unique request identifier + function sendRequest( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external returns (bytes32); + + /// @notice Sends a request to the proposed contracts + /// @param subscriptionId - A unique subscription ID allocated by billing system, + /// a client can make requests from different contracts referencing the same subscription + /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param dataVersion - Gas limit for the fulfillment callback + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @param donId - An identifier used to determine which route to send the request along + /// @return requestId - A unique request identifier + function sendRequestToProposed( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external returns (bytes32); + + /// @notice Fulfill the request by: + /// - calling back the data that the Oracle returned to the client contract + /// - pay the DON for processing the request + /// @dev Only callable by the Coordinator contract that is saved in the commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @param juelsPerGas - current rate of juels/gas + /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment + /// @param transmitter - The Node that transmitted the OCR report + /// @param commitment - The parameters of the request that must be held consistent between request and response time + /// @return fulfillResult - + /// @return callbackGasCostJuels - + function fulfill( + bytes memory response, + bytes memory err, + uint96 juelsPerGas, + uint96 costWithoutFulfillment, + address transmitter, + FunctionsResponse.Commitment memory commitment + ) external returns (FunctionsResponse.FulfillResult, uint96); + + /// @notice Validate requested gas limit is below the subscription max. + /// @param subscriptionId subscription ID + /// @param callbackGasLimit desired callback gas limit + function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view; + + /// @notice Get the current contract given an ID + /// @param id A bytes32 identifier for the route + /// @return contract The current contract address + function getContractById(bytes32 id) external view returns (address); + + /// @notice Get the proposed next contract given an ID + /// @param id A bytes32 identifier for the route + /// @return contract The current or proposed contract address + function getProposedContractById(bytes32 id) external view returns (address); + + /// @notice Return the latest proprosal set + /// @return ids The identifiers of the contracts to update + /// @return to The addresses of the contracts that will be updated to + function getProposedContractSet() external view returns (bytes32[] memory, address[] memory); + + /// @notice Proposes one or more updates to the contract routes + /// @dev Only callable by owner + function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external; + + /// @notice Updates the current contract routes to the proposed contracts + /// @dev Only callable by owner + function updateContracts() external; + + /// @dev Puts the system into an emergency stopped state. + /// @dev Only callable by owner + function pause() external; + + /// @dev Takes the system out of an emergency stopped state. + /// @dev Only callable by owner + function unpause() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol new file mode 100644 index 0000000..eafd6f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions Subscription interface. +interface IFunctionsSubscriptions { + struct Subscription { + uint96 balance; // ═════════╗ Common LINK balance that is controlled by the Router to be used for all consumer requests. + address owner; // ══════════╝ The owner can fund/withdraw/cancel the subscription. + uint96 blockedBalance; // ══╗ LINK balance that is reserved to pay for pending consumer requests. + address proposedOwner; // ══╝ For safely transferring sub ownership. + address[] consumers; // ════╸ Client contracts that can use the subscription + bytes32 flags; // ══════════╸ Per-subscription flags + } + + struct Consumer { + bool allowed; // ══════════════╗ Owner can fund/withdraw/cancel the sub. + uint64 initiatedRequests; // ║ The number of requests that have been started + uint64 completedRequests; // ══╝ The number of requests that have successfully completed or timed out + } + + /// @notice Get details about a subscription. + /// @param subscriptionId - the ID of the subscription + /// @return subscription - see IFunctionsSubscriptions.Subscription for more information on the structure + function getSubscription(uint64 subscriptionId) external view returns (Subscription memory); + + /// @notice Retrieve details about multiple subscriptions using an inclusive range + /// @param subscriptionIdStart - the ID of the subscription to start the range at + /// @param subscriptionIdEnd - the ID of the subscription to end the range at + /// @return subscriptions - see IFunctionsSubscriptions.Subscription for more information on the structure + function getSubscriptionsInRange( + uint64 subscriptionIdStart, + uint64 subscriptionIdEnd + ) external view returns (Subscription[] memory); + + /// @notice Get details about a consumer of a subscription. + /// @param client - the consumer contract address + /// @param subscriptionId - the ID of the subscription + /// @return consumer - see IFunctionsSubscriptions.Consumer for more information on the structure + function getConsumer(address client, uint64 subscriptionId) external view returns (Consumer memory); + + /// @notice Get details about the total amount of LINK within the system + /// @return totalBalance - total Juels of LINK held by the contract + function getTotalBalance() external view returns (uint96); + + /// @notice Get details about the total number of subscription accounts + /// @return count - total number of subscriptions in the system + function getSubscriptionCount() external view returns (uint64); + + /// @notice Time out all expired requests: unlocks funds and removes the ability for the request to be fulfilled + /// @param requestsToTimeoutByCommitment - A list of request commitments to time out + /// @dev The commitment can be found on the "OracleRequest" event created when sending the request. + function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external; + + /// @notice Oracle withdraw LINK earned through fulfilling requests + /// @notice If amount is 0 the full balance will be withdrawn + /// @notice Both signing and transmitting wallets will have a balance to withdraw + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function oracleWithdraw(address recipient, uint96 amount) external; + + /// @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + /// @dev Only callable by the Router Owner + /// @param subscriptionId subscription id + /// @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + function ownerCancelSubscription(uint64 subscriptionId) external; + + /// @notice Recover link sent with transfer instead of transferAndCall. + /// @dev Only callable by the Router Owner + /// @param to address to send link to + function recoverFunds(address to) external; + + /// @notice Create a new subscription. + /// @return subscriptionId - A unique subscription id. + /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function createSubscription() external returns (uint64); + + /// @notice Create a new subscription and add a consumer. + /// @return subscriptionId - A unique subscription id. + /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function createSubscriptionWithConsumer(address consumer) external returns (uint64 subscriptionId); + + /// @notice Propose a new owner for a subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param newOwner - proposed new owner of the subscription + function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external; + + /// @notice Accept an ownership transfer. + /// @param subscriptionId - ID of the subscription + /// @dev will revert if original owner of subscriptionId has not requested that msg.sender become the new owner. + function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external; + + /// @notice Remove a consumer from a Chainlink Functions subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param consumer - Consumer to remove from the subscription + function removeConsumer(uint64 subscriptionId, address consumer) external; + + /// @notice Add a consumer to a Chainlink Functions subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param consumer - New consumer which can use the subscription + function addConsumer(uint64 subscriptionId, address consumer) external; + + /// @notice Cancel a subscription + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param to - Where to send the remaining LINK to + function cancelSubscription(uint64 subscriptionId, address to) external; + + /// @notice Check to see if there exists a request commitment for all consumers for a given sub. + /// @param subscriptionId - ID of the subscription + /// @return true if there exists at least one unfulfilled request for the subscription, false otherwise. + /// @dev Looping is bounded to MAX_CONSUMERS*(number of DONs). + /// @dev Used to disable subscription canceling while outstanding request are present. + function pendingRequestExists(uint64 subscriptionId) external view returns (bool); + + /// @notice Set subscription specific flags for a subscription. + /// Each byte of the flag is used to represent a resource tier that the subscription can utilize. + /// @param subscriptionId - ID of the subscription + /// @param flags - desired flag values + function setFlags(uint64 subscriptionId, bytes32 flags) external; + + /// @notice Get flags for a given subscription. + /// @param subscriptionId - ID of the subscription + /// @return flags - current flag values + function getFlags(uint64 subscriptionId) external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol new file mode 100644 index 0000000..f6d7880 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsRouter} from "./IFunctionsRouter.sol"; +import {IOwnable} from "../../../../shared/interfaces/IOwnable.sol"; + +/// @title Chainlink Functions Router interface with Ownability. +interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol new file mode 100644 index 0000000..d4c4b5f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +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.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; + uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; + + // ------------ End Arbitrum Constants ------------ + + // ------------ Start Optimism Constants ------------ + /// @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; + uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; + + /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. + uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; + uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; + uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; + + // ------------ End Optimism Constants ------------ + + /// @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)) { + // 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 GAS_PRICE_ORACLE.getL1FeeUpperBound(calldataSizeBytes); + } + return 0; + } + + /// @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. + function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == ARB_MAINNET_CHAIN_ID || + chainId == ARB_GOERLI_TESTNET_CHAIN_ID || + chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; + } + + /// @notice Return true if and only if the provided chain ID is an Optimism (or Base) chain ID. + /// @notice Note that optimism chain id's are also OP stack chain id's. + function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == OP_MAINNET_CHAIN_ID || + chainId == OP_GOERLI_CHAIN_ID || + chainId == OP_SEPOLIA_CHAIN_ID || + chainId == BASE_MAINNET_CHAIN_ID || + chainId == BASE_GOERLI_CHAIN_ID || + chainId == BASE_SEPOLIA_CHAIN_ID; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol new file mode 100644 index 0000000..4e3134d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {CBOR} from "../../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol"; + +/// @title Library for encoding the input data of a Functions request into CBOR +library FunctionsRequest { + using CBOR for CBOR.CBORBuffer; + + uint16 public constant REQUEST_DATA_VERSION = 1; + uint256 internal constant DEFAULT_BUFFER_SIZE = 256; + + enum Location { + Inline, // Provided within the Request + Remote, // Hosted through remote location that can be accessed through a provided URL + DONHosted // Hosted on the DON's storage + } + + enum CodeLanguage { + JavaScript + // In future version we may add other languages + } + + struct Request { + Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON + Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported + CodeLanguage language; // ════════════╸ The coding language that the source code is written in + string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted + bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) + string[] args; // ════════════════════╸ String arguments that will be passed into the source code + bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code + } + + error EmptySource(); + error EmptySecrets(); + error EmptyArgs(); + error NoInlineSecrets(); + + /// @notice Encodes a Request to CBOR encoded bytes + /// @param self The request to encode + /// @return CBOR encoded bytes + function _encodeCBOR(Request memory self) internal pure returns (bytes memory) { + CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); + + buffer.writeString("codeLocation"); + buffer.writeUInt256(uint256(self.codeLocation)); + + buffer.writeString("language"); + buffer.writeUInt256(uint256(self.language)); + + buffer.writeString("source"); + buffer.writeString(self.source); + + if (self.args.length > 0) { + buffer.writeString("args"); + buffer.startArray(); + for (uint256 i = 0; i < self.args.length; ++i) { + buffer.writeString(self.args[i]); + } + buffer.endSequence(); + } + + if (self.encryptedSecretsReference.length > 0) { + if (self.secretsLocation == Location.Inline) { + revert NoInlineSecrets(); + } + buffer.writeString("secretsLocation"); + buffer.writeUInt256(uint256(self.secretsLocation)); + buffer.writeString("secrets"); + buffer.writeBytes(self.encryptedSecretsReference); + } + + if (self.bytesArgs.length > 0) { + buffer.writeString("bytesArgs"); + buffer.startArray(); + for (uint256 i = 0; i < self.bytesArgs.length; ++i) { + buffer.writeBytes(self.bytesArgs[i]); + } + buffer.endSequence(); + } + + return buffer.buf.buf; + } + + /// @notice Initializes a Chainlink Functions Request + /// @dev Sets the codeLocation and code on the request + /// @param self The uninitialized request + /// @param codeLocation The user provided source code location + /// @param language The programming language of the user code + /// @param source The user provided source code or a url + function _initializeRequest( + Request memory self, + Location codeLocation, + CodeLanguage language, + string memory source + ) internal pure { + if (bytes(source).length == 0) revert EmptySource(); + + self.codeLocation = codeLocation; + self.language = language; + self.source = source; + } + + /// @notice Initializes a Chainlink Functions Request + /// @dev Simplified version of initializeRequest for PoC + /// @param self The uninitialized request + /// @param javaScriptSource The user provided JS code (must not be empty) + function _initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure { + _initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource); + } + + /// @notice Adds Remote user encrypted secrets to a Request + /// @param self The initialized request + /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets + function _addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure { + if (encryptedSecretsReference.length == 0) revert EmptySecrets(); + + self.secretsLocation = Location.Remote; + self.encryptedSecretsReference = encryptedSecretsReference; + } + + /// @notice Adds DON-hosted secrets reference to a Request + /// @param self The initialized request + /// @param slotID Slot ID of the user's secrets hosted on DON + /// @param version User data version (for the slotID) + function _addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure { + CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); + + buffer.writeString("slotID"); + buffer.writeUInt64(slotID); + buffer.writeString("version"); + buffer.writeUInt64(version); + + self.secretsLocation = Location.DONHosted; + self.encryptedSecretsReference = buffer.buf.buf; + } + + /// @notice Sets args for the user run function + /// @param self The initialized request + /// @param args The array of string args (must not be empty) + function _setArgs(Request memory self, string[] memory args) internal pure { + if (args.length == 0) revert EmptyArgs(); + + self.args = args; + } + + /// @notice Sets bytes args for the user run function + /// @param self The initialized request + /// @param args The array of bytes args (must not be empty) + function _setBytesArgs(Request memory self, bytes[] memory args) internal pure { + if (args.length == 0) revert EmptyArgs(); + + self.bytesArgs = args; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol new file mode 100644 index 0000000..65fad66 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Library of types that are used for fulfillment of a Functions request +library FunctionsResponse { + // Used to send request information from the Router to the Coordinator + struct RequestMeta { + bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request + bytes32 flags; // ═══════════════╸ Per-subscription flags + address requestingContract; // ══╗ The client contract that is sending the request + uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests. + uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network + uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request + uint64 initiatedRequests; // ║ The number of requests that have been started + uint32 callbackGasLimit; // ║ The amount of gas that the callback to the consuming contract will be given + uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data + uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out + address subscriptionOwner; // ═══╝ The owner of the billing subscription + } + + enum FulfillResult { + FULFILLED, // 0 + USER_CALLBACK_ERROR, // 1 + INVALID_REQUEST_ID, // 2 + COST_EXCEEDS_COMMITMENT, // 3 + INSUFFICIENT_GAS_PROVIDED, // 4 + SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5 + INVALID_COMMITMENT // 6 + } + + struct Commitment { + bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request + address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request + uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request + address client; // ════════════════════╗ The client contract that sent the request + uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request + uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given + uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network + uint72 donFee; // ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request + uint40 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. + uint40 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. + uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol new file mode 100644 index 0000000..ac040ad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.19; + +contract FunctionsV1EventsMock { + // solhint-disable-next-line gas-struct-packing + struct Config { + uint16 maxConsumersPerSubscription; + uint72 adminFee; + bytes4 handleOracleFulfillmentSelector; + uint16 gasForCallExactCheck; + uint32[] maxCallbackGasLimits; + } + + event ConfigUpdated(Config param1); + event ContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ); + event ContractUpdated(bytes32 id, address from, address to); + event FundsRecovered(address to, uint256 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event RequestNotProcessed(bytes32 indexed requestId, address coordinator, address transmitter, uint8 resultCode); + event RequestProcessed( + bytes32 indexed requestId, + uint64 indexed subscriptionId, + uint96 totalCostJuels, + address transmitter, + uint8 resultCode, + bytes response, + bytes err, + bytes callbackReturnData + ); + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + event RequestTimedOut(bytes32 indexed requestId); + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); + event Unpaused(address account); + + function emitConfigUpdated(Config memory param1) public { + emit ConfigUpdated(param1); + } + + function emitContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ) public { + emit ContractProposed(proposedContractSetId, proposedContractSetFromAddress, proposedContractSetToAddress); + } + + function emitContractUpdated(bytes32 id, address from, address to) public { + emit ContractUpdated(id, from, to); + } + + function emitFundsRecovered(address to, uint256 amount) public { + emit FundsRecovered(to, amount); + } + + function emitOwnershipTransferRequested(address from, address to) public { + emit OwnershipTransferRequested(from, to); + } + + function emitOwnershipTransferred(address from, address to) public { + emit OwnershipTransferred(from, to); + } + + function emitPaused(address account) public { + emit Paused(account); + } + + function emitRequestNotProcessed( + bytes32 requestId, + address coordinator, + address transmitter, + uint8 resultCode + ) public { + emit RequestNotProcessed(requestId, coordinator, transmitter, resultCode); + } + + function emitRequestProcessed( + bytes32 requestId, + uint64 subscriptionId, + uint96 totalCostJuels, + address transmitter, + uint8 resultCode, + bytes memory response, + bytes memory err, + bytes memory callbackReturnData + ) public { + emit RequestProcessed( + requestId, + subscriptionId, + totalCostJuels, + transmitter, + resultCode, + response, + err, + callbackReturnData + ); + } + + function emitRequestStart( + bytes32 requestId, + bytes32 donId, + uint64 subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes memory data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ) public { + emit RequestStart( + requestId, + donId, + subscriptionId, + subscriptionOwner, + requestingContract, + requestInitiator, + data, + dataVersion, + callbackGasLimit, + estimatedTotalCostJuels + ); + } + + function emitRequestTimedOut(bytes32 requestId) public { + emit RequestTimedOut(requestId); + } + + function emitSubscriptionCanceled(uint64 subscriptionId, address fundsRecipient, uint256 fundsAmount) public { + emit SubscriptionCanceled(subscriptionId, fundsRecipient, fundsAmount); + } + + function emitSubscriptionConsumerAdded(uint64 subscriptionId, address consumer) public { + emit SubscriptionConsumerAdded(subscriptionId, consumer); + } + + function emitSubscriptionConsumerRemoved(uint64 subscriptionId, address consumer) public { + emit SubscriptionConsumerRemoved(subscriptionId, consumer); + } + + function emitSubscriptionCreated(uint64 subscriptionId, address owner) public { + emit SubscriptionCreated(subscriptionId, owner); + } + + function emitSubscriptionFunded(uint64 subscriptionId, uint256 oldBalance, uint256 newBalance) public { + emit SubscriptionFunded(subscriptionId, oldBalance, newBalance); + } + + function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId, address from, address to) public { + emit SubscriptionOwnerTransferRequested(subscriptionId, from, to); + } + + function emitSubscriptionOwnerTransferred(uint64 subscriptionId, address from, address to) public { + emit SubscriptionOwnerTransferred(subscriptionId, from, to); + } + + function emitUnpaused(address account) public { + emit Unpaused(account); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol new file mode 100644 index 0000000..77cc950 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + /** + * @notice optionally emited to indicate the latest configDigest and epoch for + which a report was successfully transmited. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol new file mode 100644 index 0000000..28fa670 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/** + * @notice Onchain verification of reports from the offchain reporting protocol + * @dev For details on its operation, see the offchain reporting protocol design + * doc, which refers to this contract as simply the "contract". + */ +abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { + error ReportInvalid(string message); + error InvalidConfig(string message); + + constructor() ConfirmedOwner(msg.sender) {} + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems + // to extract config from logs. + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them into two SLOADs. If any further fields are + // added, make sure that storage of the struct still takes at most 64 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // ───╮ + uint8 n; // ───╯ + } + ConfigInfo internal s_configInfo; + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + mapping(address signerOrTransmitter => Oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + struct DecodedReport { + bytes32[] requestIds; + bytes[] results; + bytes[] errors; + bytes[] onchainMetadata; + bytes[] offchainMetadata; + } + + /* + * Config logic + */ + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + // solhint-disable-next-line gas-struct-packing + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param _signers addresses with which oracles sign the reports + * @param _transmitters addresses oracles use to transmit the reports + * @param _f number of faulty oracles the system can tolerate + * @param _onchainConfig encoded on-chain contract configuration + * @param _offchainConfigVersion version number for offchainEncoding schema + * @param _offchainConfig encoded off-chain oracle configuration + */ + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < args.signers.length; i++) { + if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); + if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signer/transmitter addresses + if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32(prefix | (h & ~prefixMask)); + } + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /** + * @return list of addresses permitted to transmit reports to this contract + * @dev The list will match the order used to specify the transmitter during setConfig + */ + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /** + * @dev hook called after the report has been fully validated + * for the extending contract to handle additional logic, such as oracle payment + * @param decodedReport decodedReport + */ + function _report(DecodedReport memory decodedReport) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function _requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); + } + + function _beforeTransmit( + bytes calldata report + ) internal virtual returns (bool shouldStop, DecodedReport memory decodedReport); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + (bool shouldStop, DecodedReport memory decodedReport) = _beforeTransmit(report); + + if (shouldStop) { + return; + } + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest + // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router + // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + _requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; + + if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); + if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); + + Oracle memory transmitter = s_oracles[msg.sender]; + if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) + revert ReportInvalid("unauthorized transmitter"); + } + + address[MAX_NUM_ORACLES] memory signed; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); + if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); + signed[o.index] = signer; + } + } + + _report(decodedReport); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol new file mode 100644 index 0000000..ffa684e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol @@ -0,0 +1,25 @@ +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + + uint256 internal OWNER_PRIVATE_KEY = 0x1; + address internal OWNER_ADDRESS = vm.addr(OWNER_PRIVATE_KEY); + + uint256 internal STRANGER_PRIVATE_KEY = 0x2; + address internal STRANGER_ADDRESS = vm.addr(STRANGER_PRIVATE_KEY); + + uint256 TX_GASPRICE_START = 3000000000; // 3 gwei + + uint72 constant JUELS_PER_LINK = 1e18; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + // Set msg.sender and tx.origin to OWNER until stopPrank is called + vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol new file mode 100644 index 0000000..d57d511 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol"; +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; + +import {FunctionsFulfillmentSetup} from "./Setup.t.sol"; + +import {ArbGasInfo} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {GasPriceOracle} from "../../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; + +/// @notice #_getL1FeeUpperLimit Arbitrum +/// @dev Arbitrum gas formula = L2 Gas Price * (Gas used on L2 + Extra Buffer for L1 cost) +/// @dev where Extra Buffer for L1 cost = (L1 Estimated Cost / L2 Gas Price) +contract ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum is FunctionsFulfillmentSetup { + address private constant ARBGAS_ADDR = address(0x000000000000000000000000000000000000006C); + uint256 private constant WEI_PER_L1_CALLDATA_BYTE = 2_243_708_528; + + uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = 6_408_031_555_968; + uint256 private constant L1_FEE_WEI = 3_697_631_654_144; + + uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); + uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); + + function setUp() public virtual override { + uint256 unused = 0; + vm.mockCall( + ARBGAS_ADDR, + abi.encodeWithSelector(ArbGasInfo.getPricesInWei.selector), + abi.encode(unused, WEI_PER_L1_CALLDATA_BYTE, unused, unused, unused, unused) + ); + } + + function test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() public { + // Set the chainID + vm.chainId(42161); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Arbitrum mainnet" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum mainnet"); + } + + function test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() public { + // Set the chainID + vm.chainId(421613); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Arbitrum Goerli" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum Goerli"); + } + + function test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() public { + // Set the chainID + vm.chainId(421614); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Arbitrum Sepolia" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum Sepolia"); + } +} + +/// @notice #_getL1FeeUpperLimit Optimism +/// @dev Optimism gas formula: https://docs.optimism.io/stack/transactions/fees#ecotone +/// @dev Note that the docs fail to mention the calculation also requires a division by 10^6 +/// @dev See here: https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/exec-engine.md#ecotone-l1-cost-fee-changes-eip-4844-da +/// @dev Also, we conservatively assume all non-zero bytes: tx_compressed_size = tx_data_size_bytes +contract ChainSpecificUtil__getL1FeeUpperLimit_Optimism is FunctionsFulfillmentSetup { + address private constant GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F); + GasPriceOracle private constant GAS_PRICE_ORACLE = GasPriceOracle(GAS_PRICE_ORACLE_ADDR); + + uint256 private constant L1_FEE_WEI = 1_648_118_885_618; + uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = (L1_FEE_WEI * (10_000 + 5_000)) / 10_000; + + uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); + uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); + + function setUp() public virtual override { + vm.mockCall( + GAS_PRICE_ORACLE_ADDR, + abi.encodeWithSelector(GAS_PRICE_ORACLE.getL1FeeUpperBound.selector), + abi.encode(L1_FEE_WEI) + ); + } + + function test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() public { + // Set the chainID + vm.chainId(10); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Optimism mainnet" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism mainnet"); + } + + function test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() public { + // Set the chainID + vm.chainId(420); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Optimism Goerli" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism Goerli"); + } + + function test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() public { + // Set the chainID + vm.chainId(11155420); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Optimism Sepolia" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism Sepolia"); + } +} + +/// @notice #_getL1FeeUpperLimit Base +/// @dev Base gas formula uses Optimism formula since it is build on the OP chain stack (See comments above for Optimism tests) +contract ChainSpecificUtil__getL1FeeUpperLimit_Base is FunctionsFulfillmentSetup { + address private constant GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F); + GasPriceOracle private constant GAS_PRICE_ORACLE = GasPriceOracle(GAS_PRICE_ORACLE_ADDR); + + uint256 private constant L1_FEE_WEI = 1_648_118_885_618; + uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = (L1_FEE_WEI * (10_000 + 5_000)) / 10_000; + + uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); + uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); + + function setUp() public virtual override { + vm.mockCall( + GAS_PRICE_ORACLE_ADDR, + abi.encodeWithSelector(GAS_PRICE_ORACLE.getL1FeeUpperBound.selector), + abi.encode(L1_FEE_WEI) + ); + } + + function test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() public { + // Set the chainID + vm.chainId(8453); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Base mainnet" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base mainnet"); + } + + function test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() public { + // Set the chainID + vm.chainId(84531); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Base Goerli" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base Goerli"); + } + + function test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() public { + // Set the chainID + vm.chainId(84532); + + // Setup sends and fulfills request #1 + FunctionsFulfillmentSetup.setUp(); + + // Check request cost estimate + uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + + l1FeeEstimateJuels; + assertEq( + s_requests[1].commitment.estimatedTotalCostJuels, + expectedEstimatedTotalCostJuels, + "Estimated cost mismatch for Base Sepolia" + ); + + // Check response actual cost + uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; + assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base Sepolia"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol new file mode 100644 index 0000000..b66c1e4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol @@ -0,0 +1,520 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; +import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {Routable} from "../../dev/v1_X/Routable.sol"; + +import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol"; + +import {FunctionsBillingConfig} from "../../dev/v1_X/interfaces/IFunctionsBilling.sol"; + +/// @notice #constructor +contract FunctionsBilling_Constructor is FunctionsSubscriptionSetup { + function test_Constructor_Success() public { + assertEq(address(s_functionsRouter), s_functionsCoordinator.getRouter_HARNESS()); + assertEq(address(s_linkEthFeed), s_functionsCoordinator.getLinkToNativeFeed_HARNESS()); + } +} + +/// @notice #getConfig +contract FunctionsBilling_GetConfig is FunctionsRouterSetup { + function test_GetConfig_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + FunctionsBillingConfig memory config = s_functionsCoordinator.getConfig(); + assertEq(config.feedStalenessSeconds, getCoordinatorConfig().feedStalenessSeconds); + assertEq(config.gasOverheadBeforeCallback, getCoordinatorConfig().gasOverheadBeforeCallback); + assertEq(config.gasOverheadAfterCallback, getCoordinatorConfig().gasOverheadAfterCallback); + assertEq(config.requestTimeoutSeconds, getCoordinatorConfig().requestTimeoutSeconds); + assertEq(config.donFeeCentsUsd, getCoordinatorConfig().donFeeCentsUsd); + assertEq(config.maxSupportedRequestDataVersion, getCoordinatorConfig().maxSupportedRequestDataVersion); + assertEq(config.fulfillmentGasPriceOverEstimationBP, getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP); + assertEq(config.fallbackNativePerUnitLink, getCoordinatorConfig().fallbackNativePerUnitLink); + } +} + +/// @notice #updateConfig +contract FunctionsBilling_UpdateConfig is FunctionsRouterSetup { + FunctionsBillingConfig internal configToSet; + + function setUp() public virtual override { + FunctionsRouterSetup.setUp(); + + // Multiply all config values by 2 to confirm that they change + configToSet = FunctionsBillingConfig({ + feedStalenessSeconds: getCoordinatorConfig().feedStalenessSeconds * 2, + gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback * 2, + gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback * 2, + requestTimeoutSeconds: getCoordinatorConfig().requestTimeoutSeconds * 2, + donFeeCentsUsd: getCoordinatorConfig().donFeeCentsUsd * 2, + operationFeeCentsUsd: getCoordinatorConfig().operationFeeCentsUsd * 2, + maxSupportedRequestDataVersion: getCoordinatorConfig().maxSupportedRequestDataVersion * 2, + fulfillmentGasPriceOverEstimationBP: getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP * 2, + fallbackNativePerUnitLink: getCoordinatorConfig().fallbackNativePerUnitLink * 2, + fallbackUsdPerUnitLink: getCoordinatorConfig().fallbackUsdPerUnitLink * 2, + fallbackUsdPerUnitLinkDecimals: getCoordinatorConfig().fallbackUsdPerUnitLinkDecimals * 2, + minimumEstimateGasPriceWei: getCoordinatorConfig().minimumEstimateGasPriceWei * 2, + transmitTxSizeBytes: getCoordinatorConfig().transmitTxSizeBytes * 2 + }); + } + + function test_UpdateConfig_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsCoordinator.updateConfig(configToSet); + } + + event ConfigUpdated(FunctionsBillingConfig config); + + function test_UpdateConfig_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ConfigUpdated(configToSet); + + s_functionsCoordinator.updateConfig(configToSet); + + FunctionsBillingConfig memory config = s_functionsCoordinator.getConfig(); + assertEq(config.feedStalenessSeconds, configToSet.feedStalenessSeconds); + assertEq(config.gasOverheadAfterCallback, configToSet.gasOverheadAfterCallback); + assertEq(config.gasOverheadBeforeCallback, configToSet.gasOverheadBeforeCallback); + assertEq(config.requestTimeoutSeconds, configToSet.requestTimeoutSeconds); + assertEq(config.donFeeCentsUsd, configToSet.donFeeCentsUsd); + assertEq(config.operationFeeCentsUsd, configToSet.operationFeeCentsUsd); + assertEq(config.maxSupportedRequestDataVersion, configToSet.maxSupportedRequestDataVersion); + assertEq(config.fulfillmentGasPriceOverEstimationBP, configToSet.fulfillmentGasPriceOverEstimationBP); + assertEq(config.fallbackNativePerUnitLink, configToSet.fallbackNativePerUnitLink); + assertEq(config.minimumEstimateGasPriceWei, configToSet.minimumEstimateGasPriceWei); + assertEq(config.fallbackUsdPerUnitLink, configToSet.fallbackUsdPerUnitLink); + assertEq(config.fallbackUsdPerUnitLinkDecimals, configToSet.fallbackUsdPerUnitLinkDecimals); + } +} + +/// @notice #getDONFee +contract FunctionsBilling_GetDONFeeJuels is FunctionsRouterSetup { + function test_GetDONFeeJuels_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint72 donFee = s_functionsCoordinator.getDONFeeJuels(new bytes(0)); + uint72 expectedDonFee = uint72(((s_donFee * 10 ** (18 + LINK_USD_DECIMALS)) / uint256(LINK_USD_RATE)) / 100); + assertEq(donFee, expectedDonFee); + } +} + +/// @notice #getOperationFee +contract FunctionsBilling_GetOperationFee is FunctionsRouterSetup { + function test_GetOperationFeeJuels_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint72 operationFee = s_functionsCoordinator.getOperationFeeJuels(); + uint72 expectedOperationFee = uint72( + ((s_operationFee * 10 ** (18 + LINK_USD_DECIMALS)) / uint256(LINK_USD_RATE)) / 100 + ); + assertEq(operationFee, expectedOperationFee); + } +} + +/// @notice #getAdminFee +contract FunctionsBilling_GetAdminFeeJuels is FunctionsRouterSetup { + function test_GetAdminFeeJuels_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint72 adminFee = s_functionsCoordinator.getAdminFeeJuels(); + assertEq(adminFee, s_adminFee); + } +} + +/// @notice #getWeiPerUnitLink +contract FunctionsBilling_GetWeiPerUnitLink is FunctionsRouterSetup { + function test_GetWeiPerUnitLink_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint256 weiPerUnitLink = s_functionsCoordinator.getWeiPerUnitLink(); + assertEq(weiPerUnitLink, uint256(LINK_ETH_RATE)); + } +} + +/// @notice #estimateCost +contract FunctionsBilling_EstimateCost is FunctionsSubscriptionSetup { + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Get cost estimate as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + } + + uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei + + function test_EstimateCost_RevertsIfGasPriceAboveCeiling() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5_500; + uint256 gasPriceWei = REASONABLE_GAS_PRICE_CEILING + 1; + + vm.expectRevert(FunctionsBilling.InvalidCalldata.selector); + + s_functionsCoordinator.estimateCost(s_subscriptionId, requestData, callbackGasLimit, gasPriceWei); + } + + function test_EstimateCost_SuccessLowGasPrice() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5_500; + uint256 gasPriceWei = 1; + + uint96 costEstimate = s_functionsCoordinator.estimateCost( + s_subscriptionId, + requestData, + callbackGasLimit, + gasPriceWei + ); + uint96 expectedCostEstimate = 51110500000000000 + + s_adminFee + + s_functionsCoordinator.getDONFeeJuels(requestData) + + s_functionsCoordinator.getOperationFeeJuels(); + assertEq(costEstimate, expectedCostEstimate); + } + + function test_EstimateCost_Success() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5_500; + uint256 gasPriceWei = 5000000000; // 5 gwei + + uint96 costEstimate = s_functionsCoordinator.estimateCost( + s_subscriptionId, + requestData, + callbackGasLimit, + gasPriceWei + ); + uint96 expectedCostEstimate = 255552500000000000 + + s_adminFee + + s_functionsCoordinator.getDONFeeJuels(requestData) + + s_functionsCoordinator.getOperationFeeJuels(); + assertEq(costEstimate, expectedCostEstimate); + } +} + +/// @notice #_calculateCostEstimate +contract FunctionsBilling__CalculateCostEstimate { + // TODO: make contract internal function helper +} + +/// @notice #_startBilling +contract FunctionsBilling__StartBilling is FunctionsFulfillmentSetup { + function test__FulfillAndBill_HasUniqueGlobalRequestId() public { + // Variables that go into a requestId: + // - Coordinator address + // - Consumer contract + // - Subscription ID, + // - Consumer initiated requests + // - Request data + // - Request data version + // - Request callback gas limit + // - Estimated total cost in Juels + // - Request timeout timestamp + // - tx.origin + + // Request #1 has already been fulfilled by the test setup + + // Reset the nonce (initiatedRequests) by removing and re-adding the consumer + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers.length, 0); + s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); + assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers[0], address(s_functionsClient)); + + // Make Request #2 + _sendAndStoreRequest( + 2, + s_requests[1].requestData.sourceCode, + s_requests[1].requestData.secrets, + s_requests[1].requestData.args, + s_requests[1].requestData.bytesArgs, + s_requests[1].requestData.callbackGasLimit + ); + + // Request #1 and #2 should have different request IDs, because the request timeout timestamp has advanced. + // A request cannot be fulfilled in the same block, which prevents removing a consumer in the same block + assertNotEq(s_requests[1].requestId, s_requests[2].requestId); + } +} + +/// @notice #_fulfillAndBill +contract FunctionsBilling__FulfillAndBill is FunctionsClientRequestSetup { + function test__FulfillAndBill_RevertIfInvalidCommitment() public { + vm.expectRevert(); + s_functionsCoordinator.fulfillAndBill_HARNESS( + s_requests[1].requestId, + new bytes(0), + new bytes(0), + new bytes(0), // malformed commitment data + new bytes(0), + 1 + ); + } + + event RequestBilled( + bytes32 indexed requestId, + uint96 juelsPerGas, + uint256 l1FeeShareWei, + uint96 callbackCostJuels, + uint72 donFee, + uint72 adminFee, + uint72 operationFee + ); + + function test__FulfillAndBill_Success() public { + uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE)); + uint96 callbackCostGas = 5072; // Taken manually + uint96 callbackCostJuels = juelsPerGas * callbackCostGas; + + // topic0 (function signature, always checked), check topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit RequestBilled( + s_requests[1].requestId, + juelsPerGas, + 0, + callbackCostJuels, + s_functionsCoordinator.getDONFeeJuels(new bytes(0)), + s_adminFee, + s_functionsCoordinator.getOperationFeeJuels() + ); + + FunctionsResponse.FulfillResult resultCode = s_functionsCoordinator.fulfillAndBill_HARNESS( + s_requests[1].requestId, + new bytes(0), + new bytes(0), + abi.encode(s_requests[1].commitment), + new bytes(0), + 1 + ); + + assertEq(uint256(resultCode), uint256(FunctionsResponse.FulfillResult.FULFILLED)); + } +} + +/// @notice #deleteCommitment +contract FunctionsBilling_DeleteCommitment is FunctionsClientRequestSetup { + function test_DeleteCommitment_RevertIfNotRouter() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(Routable.OnlyCallableByRouter.selector); + s_functionsCoordinator.deleteCommitment(s_requests[1].requestId); + } + + event CommitmentDeleted(bytes32 requestId); + + function test_DeleteCommitment_Success() public { + // Send as Router + vm.stopPrank(); + vm.startPrank(address(s_functionsRouter)); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit CommitmentDeleted(s_requests[1].requestId); + + s_functionsCoordinator.deleteCommitment(s_requests[1].requestId); + } +} + +/// @notice #oracleWithdraw +contract FunctionsBilling_OracleWithdraw is FunctionsMultipleFulfillmentsSetup { + function test_OracleWithdraw_RevertWithNoBalance() public { + uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); + _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); + + // Send as stranger, which has no balance + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + + // Attempt to withdraw with no amount, which would withdraw the full balance + s_functionsCoordinator.oracleWithdraw(STRANGER_ADDRESS, 0); + + uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); + _assertTransmittersAllHaveBalance(transmitterBalancesAfter, 0); + } + + function test_OracleWithdraw_RevertIfInsufficientBalance() public { + // Send as transmitter 1, which has transmitted 1 report + vm.stopPrank(); + vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); + + vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); + + // Attempt to withdraw more than the Coordinator has assigned + s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, s_fulfillmentCoordinatorBalance + 1); + } + + function test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() public { + uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); + _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); + + // Send as transmitter 1, which has transmitted 1 report + vm.stopPrank(); + vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); + + uint96 expectedTransmitterBalance = s_fulfillmentCoordinatorBalance / s_requestsFulfilled; + + // Attempt to withdraw half of balance + uint96 halfBalance = expectedTransmitterBalance / 2; + s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, halfBalance); + + uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); + assertEq(transmitterBalancesAfter[0], halfBalance); + assertEq(transmitterBalancesAfter[1], 0); + assertEq(transmitterBalancesAfter[2], 0); + assertEq(transmitterBalancesAfter[3], 0); + } + + function test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() public { + uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); + _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); + + // Send as transmitter 1, which has transmitted 2 reports + vm.stopPrank(); + vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); + + // Attempt to withdraw with no amount, which will withdraw the full balance + s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, 0); + + uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; + uint96 totalDonFees = s_functionsCoordinator.getDONFeeJuels(new bytes(0)) * s_requestsFulfilled; + uint96 donFeeShare = totalDonFees / uint8(s_transmitters.length); + uint96 expectedBalancePerFulfillment = ((s_fulfillmentCoordinatorBalance - totalOperationFees - totalDonFees) / + s_requestsFulfilled); + + uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); + // Transmitter 1 has transmitted twice + assertEq(transmitterBalancesAfter[0], (expectedBalancePerFulfillment * 2) + donFeeShare); + assertEq(transmitterBalancesAfter[1], 0); + assertEq(transmitterBalancesAfter[2], 0); + assertEq(transmitterBalancesAfter[3], 0); + } + + function test_OracleWithdraw_SuccessCoordinatorOwner() public { + // Send as Coordinator Owner + address coordinatorOwner = s_functionsCoordinator.owner(); + vm.stopPrank(); + vm.startPrank(coordinatorOwner); + + uint256 coordinatorOwnerBalanceBefore = s_linkToken.balanceOf(coordinatorOwner); + + // Attempt to withdraw with no amount, which will withdraw the full balance + s_functionsCoordinator.oracleWithdraw(coordinatorOwner, 0); + + // 4 report transmissions have been made + uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; + + uint256 coordinatorOwnerBalanceAfter = s_linkToken.balanceOf(coordinatorOwner); + assertEq(coordinatorOwnerBalanceBefore + totalOperationFees, coordinatorOwnerBalanceAfter); + } +} + +/// @notice #oracleWithdrawAll +contract FunctionsBilling_OracleWithdrawAll is FunctionsMultipleFulfillmentsSetup { + function setUp() public virtual override { + FunctionsMultipleFulfillmentsSetup.setUp(); + } + + function test_OracleWithdrawAll_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsCoordinator.oracleWithdrawAll(); + } + + function test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() public { + uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); + _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); + + s_functionsCoordinator.oracleWithdrawAll(); + + uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; + uint96 totalDonFees = s_functionsCoordinator.getDONFeeJuels(new bytes(0)) * s_requestsFulfilled; + uint96 donFeeShare = totalDonFees / uint8(s_transmitters.length); + uint96 expectedBalancePerFulfillment = ((s_fulfillmentCoordinatorBalance - totalOperationFees - totalDonFees) / + s_requestsFulfilled); + + uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); + // Transmitter 1 has transmitted twice + assertEq(transmitterBalancesAfter[0], (expectedBalancePerFulfillment * 2) + donFeeShare); + // Transmitter 2 and 3 have transmitted once + assertEq(transmitterBalancesAfter[1], expectedBalancePerFulfillment + donFeeShare); + assertEq(transmitterBalancesAfter[2], expectedBalancePerFulfillment + donFeeShare); + // Transmitter 4 only not transmitted, it only has its share of the DON fees + assertEq(transmitterBalancesAfter[3], donFeeShare); + } +} + +/// @notice #_disperseFeePool +contract FunctionsBilling__DisperseFeePool is FunctionsRouterSetup { + function test__DisperseFeePool_RevertIfNotSet() public { + // Manually set s_feePool (at slot 12) to 1 to get past first check in _disperseFeePool + vm.store(address(s_functionsCoordinator), bytes32(uint256(12)), bytes32(uint256(1))); + + vm.expectRevert(FunctionsBilling.NoTransmittersSet.selector); + s_functionsCoordinator.disperseFeePool_HARNESS(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol new file mode 100644 index 0000000..3638276 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol"; +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; + +import {FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; + +/// @notice #constructor +contract FunctionsClient_Constructor is FunctionsClientSetup { + function test_Constructor_Success() public { + assertEq(address(s_functionsRouter), s_functionsClient.getRouter_HARNESS()); + } +} + +/// @notice #_sendRequest +contract FunctionsClient__SendRequest is FunctionsSubscriptionSetup { + function test__SendRequest_RevertIfInvalidCallbackGasLimit() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); + uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; + uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); + s_functionsClient.sendRequestBytes(requestData, s_subscriptionId, 500_000, s_donId); + } +} + +/// @notice #handleOracleFulfillment +contract FunctionsClient_HandleOracleFulfillment is FunctionsClientRequestSetup { + function test_HandleOracleFulfillment_RevertIfNotRouter() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsClient.OnlyRouterCanFulfill.selector); + s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0)); + } + + event RequestFulfilled(bytes32 indexed id); + event ResponseReceived(bytes32 indexed requestId, bytes result, bytes err); + + function test_HandleOracleFulfillment_Success() public { + // Send as Router + vm.stopPrank(); + vm.startPrank(address(s_functionsRouter)); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ResponseReceived(s_requests[1].requestId, new bytes(0), new bytes(0)); + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit RequestFulfilled(s_requests[1].requestId); + + s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol new file mode 100644 index 0000000..03d9f64 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; +import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {Routable} from "../../dev/v1_X/Routable.sol"; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsRouterSetup, FunctionsDONSetup, FunctionsSubscriptionSetup} from "./Setup.t.sol"; + +/// @notice #constructor +contract FunctionsCoordinator_Constructor is FunctionsRouterSetup { + function test_Constructor_Success() public { + assertEq(s_functionsCoordinator.typeAndVersion(), "Functions Coordinator v1.3.1"); + assertEq(s_functionsCoordinator.owner(), OWNER_ADDRESS); + } +} + +/// @notice #getThresholdPublicKey +contract FunctionsCoordinator_GetThresholdPublicKey is FunctionsDONSetup { + function test_GetThresholdPublicKey_RevertIfEmpty() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Reverts when empty + vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector); + s_functionsCoordinator.getThresholdPublicKey(); + } + + function test_GetThresholdPublicKey_Success() public { + s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey(); + assertEq(thresholdKey, s_thresholdKey); + } +} + +/// @notice #setThresholdPublicKey +contract FunctionsCoordinator_SetThresholdPublicKey is FunctionsDONSetup { + function test_SetThresholdPublicKey_RevertNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + bytes memory newThresholdKey = new bytes(0); + s_functionsCoordinator.setThresholdPublicKey(newThresholdKey); + } + + function test_SetThresholdPublicKey_Success() public { + s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey); + + bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey(); + + assertEq(thresholdKey, s_thresholdKey); + } +} + +/// @notice #getDONPublicKey +contract FunctionsCoordinator_GetDONPublicKey is FunctionsDONSetup { + function test_GetDONPublicKey_RevertIfEmpty() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Reverts when empty + vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector); + s_functionsCoordinator.getDONPublicKey(); + } + + function test_GetDONPublicKey_Success() public { + s_functionsCoordinator.setDONPublicKey(s_donKey); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes memory donKey = s_functionsCoordinator.getDONPublicKey(); + assertEq(donKey, s_donKey); + } +} + +/// @notice #setDONPublicKey +contract FunctionsCoordinator_SetDONPublicKey is FunctionsDONSetup { + function test_SetDONPublicKey_RevertNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsCoordinator.setDONPublicKey(s_donKey); + } + + function test_SetDONPublicKey_Success() public { + s_functionsCoordinator.setDONPublicKey(s_donKey); + + bytes memory donKey = s_functionsCoordinator.getDONPublicKey(); + assertEq(donKey, s_donKey); + } +} + +/// @notice #_isTransmitter +contract FunctionsCoordinator__IsTransmitter is FunctionsDONSetup { + function test__IsTransmitter_SuccessFound() public { + bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(NOP_TRANSMITTER_ADDRESS_1); + assertEq(isTransmitter, true); + } + + function test__IsTransmitter_SuccessNotFound() public { + bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(STRANGER_ADDRESS); + assertEq(isTransmitter, false); + } +} + +/// @notice #startRequest +contract FunctionsCoordinator_StartRequest is FunctionsSubscriptionSetup { + function test_StartRequest_RevertIfNotRouter() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(Routable.OnlyCallableByRouter.selector); + + s_functionsCoordinator.startRequest( + FunctionsResponse.RequestMeta({ + requestingContract: address(s_functionsClient), + data: new bytes(0), + subscriptionId: s_subscriptionId, + dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, + flags: bytes32(0), + callbackGasLimit: 5_500, + adminFee: s_adminFee, + initiatedRequests: 0, + completedRequests: 0, + availableBalance: s_subscriptionInitialFunding, + subscriptionOwner: OWNER_ADDRESS + }) + ); + } + + event OracleRequest( + bytes32 indexed requestId, + address indexed requestingContract, + address requestInitiator, + uint64 subscriptionId, + address subscriptionOwner, + bytes data, + uint16 dataVersion, + bytes32 flags, + uint64 callbackGasLimit, + FunctionsResponse.Commitment commitment + ); + + function test_StartRequest_Success() public { + // Send as Router + vm.stopPrank(); + vm.startPrank(address(s_functionsRouter)); + (, , address txOrigin) = vm.readCallers(); + + bytes memory _requestData = new bytes(0); + uint32 _callbackGasLimit = 5_500; + uint96 costEstimate = s_functionsCoordinator.estimateCost( + s_subscriptionId, + _requestData, + _callbackGasLimit, + tx.gasprice + ); + uint32 timeoutTimestamp = uint32(block.timestamp + getCoordinatorConfig().requestTimeoutSeconds); + bytes32 expectedRequestId = keccak256( + abi.encode( + address(s_functionsCoordinator), + address(s_functionsClient), + s_subscriptionId, + 1, + keccak256(_requestData), + FunctionsRequest.REQUEST_DATA_VERSION, + _callbackGasLimit, + costEstimate, + timeoutTimestamp, + txOrigin + ) + ); + + // WARNING: Kludge in place. Remove in contracts v2.0.0 + FunctionsResponse.Commitment memory expectedComittment = FunctionsResponse.Commitment({ + adminFee: s_functionsCoordinator.getOperationFeeJuels(), + coordinator: address(s_functionsCoordinator), + client: address(s_functionsClient), + subscriptionId: s_subscriptionId, + callbackGasLimit: _callbackGasLimit, + estimatedTotalCostJuels: costEstimate, + timeoutTimestamp: timeoutTimestamp, + requestId: expectedRequestId, + donFee: s_functionsCoordinator.getDONFeeJuels(_requestData), + gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback, + gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback + }); + + // topic0 (function signature, always checked), topic1 (true), topic2 (true), NOT topic3 (false), and data (true). + vm.expectEmit(true, true, false, true); + emit OracleRequest({ + requestId: expectedRequestId, + requestingContract: address(s_functionsClient), + requestInitiator: txOrigin, + subscriptionId: s_subscriptionId, + subscriptionOwner: OWNER_ADDRESS, + data: _requestData, + dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, + flags: bytes32(0), + callbackGasLimit: _callbackGasLimit, + commitment: expectedComittment + }); + + s_functionsCoordinator.startRequest( + FunctionsResponse.RequestMeta({ + requestingContract: address(s_functionsClient), + data: _requestData, + subscriptionId: s_subscriptionId, + dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, + flags: bytes32(0), + callbackGasLimit: 5_500, + adminFee: s_adminFee, + initiatedRequests: 0, + completedRequests: 0, + availableBalance: s_subscriptionInitialFunding, + subscriptionOwner: OWNER_ADDRESS + }) + ); + } +} + +/// @notice #_beforeSetConfig +contract FunctionsCoordinator__BeforeSetConfig { + // TODO: make contract internal function helper +} + +/// @notice #_getTransmitters +contract FunctionsCoordinator__GetTransmitters { + // TODO: make contract internal function helper +} + +/// @notice #_report +contract FunctionsCoordinator__Report { + // TODO: make contract internal function helper +} + +/// @notice #_onlyOwner +contract FunctionsCoordinator__OnlyOwner { + // TODO: make contract internal function helper +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol new file mode 100644 index 0000000..e9684d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; + +import {Test} from "forge-std/Test.sol"; + +/// @notice #REQUEST_DATA_VERSION +contract FunctionsRequest_REQUEST_DATA_VERSION is Test { + function test_REQUEST_DATA_VERSION() public { + // Exposes REQUEST_DATA_VERSION + assertEq(FunctionsRequest.REQUEST_DATA_VERSION, 1); + } +} + +/// @notice #DEFAULT_BUFFER_SIZE +contract FunctionsRequest_DEFAULT_BUFFER_SIZE is Test { + function test_DEFAULT_BUFFER_SIZE() public { + // Exposes DEFAULT_BUFFER_SIZE + assertEq(FunctionsRequest.DEFAULT_BUFFER_SIZE, 256); + } +} + +/// @notice #encodeCBOR +contract FunctionsRequest_EncodeCBOR is Test { + function test_EncodeCBOR_Success() public { + // Exposes DEFAULT_BUFFER_SIZE + assertEq(FunctionsRequest.DEFAULT_BUFFER_SIZE, 256); + } +} + +/// @notice #initializeRequest +contract FunctionsRequest_InitializeRequest is Test {} + +/// @notice #initializeRequestForInlineJavaScript +contract FunctionsRequest_InitializeRequestForInlineJavaScript is Test {} + +/// @notice #addSecretsReference +contract FunctionsRequest_AddSecretsReference is Test {} + +/// @notice #addDONHostedSecrets +contract FunctionsRequest_AddDONHostedSecrets is Test {} + +/// @notice #setArgs +contract FunctionsRequest_SetArgs is Test {} + +/// @notice #setBytesArgs +contract FunctionsRequest_SetBytesArgs is Test {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol new file mode 100644 index 0000000..62db3e4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol @@ -0,0 +1,1603 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; +import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {FunctionsCoordinatorTestHelper} from "./testhelpers/FunctionsCoordinatorTestHelper.sol"; +import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; + +import {FunctionsRouterSetup, FunctionsRoutesSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; + +import "forge-std/Vm.sol"; + +// ================================================================ +// | Functions Router | +// ================================================================ + +/// @notice #constructor +contract FunctionsRouter_Constructor is FunctionsRouterSetup { + function test_Constructor_Success() public { + assertEq(s_functionsRouter.typeAndVersion(), "Functions Router v2.0.0"); + assertEq(s_functionsRouter.owner(), OWNER_ADDRESS); + } +} + +/// @notice #getConfig +contract FunctionsRouter_GetConfig is FunctionsRouterSetup { + function test_GetConfig_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + assertEq(config.maxConsumersPerSubscription, getRouterConfig().maxConsumersPerSubscription); + assertEq(config.adminFee, getRouterConfig().adminFee); + assertEq(config.handleOracleFulfillmentSelector, getRouterConfig().handleOracleFulfillmentSelector); + assertEq(config.maxCallbackGasLimits[0], getRouterConfig().maxCallbackGasLimits[0]); + assertEq(config.maxCallbackGasLimits[1], getRouterConfig().maxCallbackGasLimits[1]); + assertEq(config.maxCallbackGasLimits[2], getRouterConfig().maxCallbackGasLimits[2]); + assertEq(config.gasForCallExactCheck, getRouterConfig().gasForCallExactCheck); + assertEq(config.subscriptionDepositMinimumRequests, getRouterConfig().subscriptionDepositMinimumRequests); + assertEq(config.subscriptionDepositJuels, getRouterConfig().subscriptionDepositJuels); + } +} + +/// @notice #updateConfig +contract FunctionsRouter_UpdateConfig is FunctionsRouterSetup { + FunctionsRouter.Config internal configToSet; + + function setUp() public virtual override { + FunctionsRouterSetup.setUp(); + + uint32[] memory maxCallbackGasLimits = new uint32[](4); + maxCallbackGasLimits[0] = 300_000; + maxCallbackGasLimits[1] = 500_000; + maxCallbackGasLimits[2] = 1_000_000; + maxCallbackGasLimits[3] = 3_000_000; + + configToSet = FunctionsRouter.Config({ + maxConsumersPerSubscription: s_maxConsumersPerSubscription, + adminFee: s_adminFee, + handleOracleFulfillmentSelector: s_handleOracleFulfillmentSelector, + maxCallbackGasLimits: maxCallbackGasLimits, + gasForCallExactCheck: 5000, + subscriptionDepositMinimumRequests: 10, + subscriptionDepositJuels: 5 * 1e18 + }); + } + + function test_UpdateConfig_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.updateConfig(configToSet); + } + + event ConfigUpdated(FunctionsRouter.Config config); + + function test_UpdateConfig_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ConfigUpdated(configToSet); + + s_functionsRouter.updateConfig(configToSet); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + assertEq(config.maxConsumersPerSubscription, configToSet.maxConsumersPerSubscription); + assertEq(config.adminFee, configToSet.adminFee); + assertEq(config.handleOracleFulfillmentSelector, configToSet.handleOracleFulfillmentSelector); + assertEq(config.maxCallbackGasLimits[0], configToSet.maxCallbackGasLimits[0]); + assertEq(config.maxCallbackGasLimits[1], configToSet.maxCallbackGasLimits[1]); + assertEq(config.maxCallbackGasLimits[2], configToSet.maxCallbackGasLimits[2]); + assertEq(config.maxCallbackGasLimits[3], configToSet.maxCallbackGasLimits[3]); + assertEq(config.gasForCallExactCheck, configToSet.gasForCallExactCheck); + } +} + +/// @notice #isValidCallbackGasLimit +contract FunctionsRouter_IsValidCallbackGasLimit is FunctionsSubscriptionSetup { + function test_IsValidCallbackGasLimit_RevertInvalidConfig() public { + // Set an invalid maxCallbackGasLimit flag + bytes32 flagsToSet = 0x5a00000000000000000000000000000000000000000000000000000000000000; + s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.InvalidGasFlagValue.selector, 90)); + s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, 0); + } + + function test_IsValidCallbackGasLimit_RevertGasLimitTooBig() public { + uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); + uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; + uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); + s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, maxCallbackGasLimit + 1); + } + + function test_IsValidCallbackGasLimit_Success() public view { + uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); + uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; + uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + + s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, maxCallbackGasLimit); + } +} + +/// @notice #getAdminFee +contract FunctionsRouter_GetAdminFee is FunctionsRouterSetup { + function test_GetAdminFee_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint72 adminFee = s_functionsRouter.getAdminFee(); + assertEq(adminFee, getRouterConfig().adminFee); + } +} + +/// @notice #getAllowListId +contract FunctionsRouter_GetAllowListId is FunctionsRouterSetup { + function test_GetAllowListId_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 defaultAllowListId = bytes32(0); + + bytes32 allowListId = s_functionsRouter.getAllowListId(); + assertEq(allowListId, defaultAllowListId); + } +} + +/// @notice #setAllowListId +contract FunctionsRouter_SetAllowListId is FunctionsRouterSetup { + function test_UpdateConfig_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 routeIdToSet = bytes32("allowList"); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.setAllowListId(routeIdToSet); + } + + function test_SetAllowListId_Success() public { + bytes32 routeIdToSet = bytes32("allowList"); + s_functionsRouter.setAllowListId(routeIdToSet); + bytes32 allowListId = s_functionsRouter.getAllowListId(); + assertEq(allowListId, routeIdToSet); + } +} + +/// @notice #_getMaxConsumers +contract FunctionsRouter__GetMaxConsumers is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #sendRequest +contract FunctionsRouter_SendRequest is FunctionsSubscriptionSetup { + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Add sending wallet as a subscription consumer + s_functionsRouter.addConsumer(s_subscriptionId, OWNER_ADDRESS); + } + + function test_SendRequest_RevertIfInvalidDonId() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + bytes32 invalidDonId = bytes32("this does not exist"); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidDonId)); + s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + invalidDonId + ); + } + + function test_SendRequest_RevertIfIncorrectDonId() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + bytes32 incorrectDonId = s_functionsRouter.getAllowListId(); + + // Low level revert from incorrect call + vm.expectRevert(); + s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + incorrectDonId + ); + } + + function test_SendRequest_RevertIfPaused() public { + s_functionsRouter.pause(); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.sendRequest(s_subscriptionId, requestData, FunctionsRequest.REQUEST_DATA_VERSION, 5000, s_donId); + } + + function test_SendRequest_RevertIfNoSubscription() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint64 invalidSubscriptionId = 123456789; + + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.sendRequest( + invalidSubscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5000, + s_donId + ); + } + + function test_SendRequest_RevertIfConsumerNotAllowed() public { + // Remove sending wallet as a subscription consumer + s_functionsRouter.removeConsumer(s_subscriptionId, OWNER_ADDRESS); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); + s_functionsRouter.sendRequest(s_subscriptionId, requestData, FunctionsRequest.REQUEST_DATA_VERSION, 5000, s_donId); + } + + function test_SendRequest_RevertIfInvalidCallbackGasLimit() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); + uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; + uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); + s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 500_000, + s_donId + ); + } + + function test_SendRequest_RevertIfEmptyData() public { + // Build invalid request data + bytes memory emptyRequestData = new bytes(0); + + vm.expectRevert(FunctionsRouter.EmptyRequestData.selector); + s_functionsRouter.sendRequest( + s_subscriptionId, + emptyRequestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + s_donId + ); + } + + function test_SendRequest_RevertIfInsufficientSubscriptionBalance() public { + // Create new subscription that does not have any funding + uint64 subscriptionId = s_functionsRouter.createSubscription(); + s_functionsRouter.addConsumer(subscriptionId, address(OWNER_ADDRESS)); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5000; + vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); + + s_functionsRouter.sendRequest( + subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + } + + function test_SendRequest_RevertIfDuplicateRequestId() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + uint32 callbackGasLimit = 5_000; + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + // Send a first request that will remain pending + bytes32 requestId = s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + + // Mock the Coordinator to always give back the first requestId + FunctionsResponse.Commitment memory mockCommitment = FunctionsResponse.Commitment({ + adminFee: s_adminFee, + coordinator: address(s_functionsCoordinator), + client: OWNER_ADDRESS, + subscriptionId: s_subscriptionId, + callbackGasLimit: callbackGasLimit, + estimatedTotalCostJuels: 0, + timeoutTimestamp: uint32(block.timestamp + getCoordinatorConfig().requestTimeoutSeconds), + requestId: requestId, + donFee: s_donFee, + gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback, + gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback + }); + + vm.mockCall( + address(s_functionsCoordinator), + abi.encodeWithSelector(FunctionsCoordinator.startRequest.selector), + abi.encode(mockCommitment) + ); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.DuplicateRequestId.selector, requestId)); + s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + } + + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + + function test_SendRequest_Success() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5000; + + uint96 costEstimate = s_functionsCoordinator.estimateCost( + s_subscriptionId, + requestData, + callbackGasLimit, + tx.gasprice + ); + + vm.recordLogs(); + + bytes32 requestIdFromReturn = s_functionsRouter.sendRequest( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + + // Get requestId from RequestStart event log topic 1 + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 requestIdFromEvent = entries[1].topics[1]; + bytes32 donIdFromEvent = entries[1].topics[2]; + bytes32 subscriptionIdFromEvent = entries[1].topics[3]; + + bytes memory expectedRequestData = abi.encode( + OWNER_ADDRESS, + OWNER_ADDRESS, + OWNER_ADDRESS, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + costEstimate + ); + + assertEq(requestIdFromReturn, requestIdFromEvent); + assertEq(donIdFromEvent, s_donId); + assertEq(subscriptionIdFromEvent, bytes32(uint256(s_subscriptionId))); + assertEq(expectedRequestData, entries[1].data); + } +} + +/// @notice #sendRequestToProposed +contract FunctionsRouter_SendRequestToProposed is FunctionsSubscriptionSetup { + FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper + + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Add sending wallet as a subscription consumer + s_functionsRouter.addConsumer(s_subscriptionId, OWNER_ADDRESS); + + // Deploy new Coordinator contract + s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + + // Propose new Coordinator contract + bytes32[] memory proposedContractSetIds = new bytes32[](1); + proposedContractSetIds[0] = s_donId; + address[] memory proposedContractSetAddresses = new address[](1); + proposedContractSetAddresses[0] = address(s_functionsCoordinator2); + + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + function test_SendRequestToProposed_RevertIfInvalidDonId() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + bytes32 invalidDonId = bytes32("this does not exist"); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidDonId)); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + invalidDonId + ); + } + + function test_SendRequestToProposed_RevertIfIncorrectDonId() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + bytes32 incorrectDonId = s_functionsRouter.getAllowListId(); + + // Low level revert from incorrect call + vm.expectRevert(); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + incorrectDonId + ); + } + + function test_SendRequestToProposed_RevertIfPaused() public { + s_functionsRouter.pause(); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5000, + s_donId + ); + } + + function test_SendRequestToProposed_RevertIfNoSubscription() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint64 invalidSubscriptionId = 123456789; + + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.sendRequestToProposed( + invalidSubscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5000, + s_donId + ); + } + + function test_SendRequestToProposed_RevertIfConsumerNotAllowed() public { + // Remove sending wallet as a subscription consumer + s_functionsRouter.removeConsumer(s_subscriptionId, OWNER_ADDRESS); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5000, + s_donId + ); + } + + function test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); + uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + + FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); + uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; + uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 500_000, + s_donId + ); + } + + function test_SendRequestToProposed_RevertIfEmptyData() public { + // Build invalid request data + bytes memory emptyRequestData = new bytes(0); + + vm.expectRevert(FunctionsRouter.EmptyRequestData.selector); + s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + emptyRequestData, + FunctionsRequest.REQUEST_DATA_VERSION, + 5_000, + s_donId + ); + } + + function test_SendRequest_RevertIfInsufficientSubscriptionBalance() public { + // Create new subscription that does not have any funding + uint64 subscriptionId = s_functionsRouter.createSubscription(); + s_functionsRouter.addConsumer(subscriptionId, address(OWNER_ADDRESS)); + + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5000; + vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); + + s_functionsRouter.sendRequestToProposed( + subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + } + + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + + function test_SendRequestToProposed_Success() public { + // Build minimal valid request data + string memory sourceCode = "return 'hello world';"; + FunctionsRequest.Request memory request; + FunctionsRequest._initializeRequest( + request, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + sourceCode + ); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + + uint32 callbackGasLimit = 5000; + + uint96 costEstimate = s_functionsCoordinator2.estimateCost( + s_subscriptionId, + requestData, + callbackGasLimit, + tx.gasprice + ); + + vm.recordLogs(); + + bytes32 requestIdFromReturn = s_functionsRouter.sendRequestToProposed( + s_subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + s_donId + ); + + // Get requestId from RequestStart event log topic 1 + Vm.Log[] memory entries = vm.getRecordedLogs(); + bytes32 requestIdFromEvent = entries[1].topics[1]; + bytes32 donIdFromEvent = entries[1].topics[2]; + bytes32 subscriptionIdFromEvent = entries[1].topics[3]; + + bytes memory expectedRequestData = abi.encode( + OWNER_ADDRESS, + OWNER_ADDRESS, + OWNER_ADDRESS, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + costEstimate + ); + + assertEq(requestIdFromReturn, requestIdFromEvent); + assertEq(donIdFromEvent, s_donId); + assertEq(subscriptionIdFromEvent, bytes32(uint256(s_subscriptionId))); + assertEq(expectedRequestData, entries[1].data); + } +} + +/// @notice #_sendRequest +contract FunctionsRouter__SendRequest is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #fulfill +contract FunctionsRouter_Fulfill is FunctionsClientRequestSetup { + function test_Fulfill_RevertIfPaused() public { + s_functionsRouter.pause(); + + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + vm.expectRevert("Pausable: paused"); + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); + } + + function test_Fulfill_RevertIfNotCommittedCoordinator() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes memory response = bytes("hello world!"); + bytes memory err = new bytes(0); + uint96 juelsPerGas = 0; + uint96 costWithoutCallback = 0; + address transmitter = NOP_TRANSMITTER_ADDRESS_1; + FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; + + vm.expectRevert(FunctionsRouter.OnlyCallableFromCoordinator.selector); + s_functionsRouter.fulfill(response, err, juelsPerGas, costWithoutCallback, transmitter, commitment); + } + + event RequestNotProcessed( + bytes32 indexed requestId, + address coordinator, + address transmitter, + FunctionsResponse.FulfillResult resultCode + ); + + function test_Fulfill_RequestNotProcessedInvalidRequestId() public { + // Send as committed Coordinator + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + bytes memory response = bytes("hello world!"); + bytes memory err = new bytes(0); + uint96 juelsPerGas = 0; + uint96 costWithoutCallback = 0; + address transmitter = NOP_TRANSMITTER_ADDRESS_1; + FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; + // Modify request commitment to have a invalid requestId + bytes32 invalidRequestId = bytes32("this does not exist"); + commitment.requestId = invalidRequestId; + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit RequestNotProcessed({ + requestId: s_requests[1].requestId, + coordinator: address(s_functionsCoordinator), + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.INVALID_REQUEST_ID + }); + + (FunctionsResponse.FulfillResult resultCode, uint96 callbackGasCostJuels) = s_functionsRouter.fulfill( + response, + err, + juelsPerGas, + costWithoutCallback, + transmitter, + commitment + ); + + assertEq(uint(resultCode), uint(FunctionsResponse.FulfillResult.INVALID_REQUEST_ID)); + assertEq(callbackGasCostJuels, 0); + } + + function test_Fulfill_RequestNotProcessedInvalidCommitment() public { + // Send as committed Coordinator + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + bytes memory response = bytes("hello world!"); + bytes memory err = new bytes(0); + uint96 juelsPerGas = 0; + uint96 costWithoutCallback = 0; + address transmitter = NOP_TRANSMITTER_ADDRESS_1; + FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; + // Modify request commitment to have charge more than quoted + commitment.estimatedTotalCostJuels = 10 * JUELS_PER_LINK; // 10 LINK + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit RequestNotProcessed({ + requestId: s_requests[1].requestId, + coordinator: address(s_functionsCoordinator), + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.INVALID_COMMITMENT + }); + + (FunctionsResponse.FulfillResult resultCode, uint96 callbackGasCostJuels) = s_functionsRouter.fulfill( + response, + err, + juelsPerGas, + costWithoutCallback, + transmitter, + commitment + ); + + assertEq(uint(resultCode), uint(FunctionsResponse.FulfillResult.INVALID_COMMITMENT)); + assertEq(callbackGasCostJuels, 0); + } + + function test_Fulfill_RequestNotProcessedInsufficientGas() public { + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + uint32 callbackGasLimit = s_requests[requestToFulfill].requestData.callbackGasLimit; + // Coordinator sends enough gas that would get through callback and payment, but fail after + uint256 gasToUse = getCoordinatorConfig().gasOverheadBeforeCallback + callbackGasLimit + 10_000; + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); + emit RequestNotProcessed({ + requestId: s_requests[requestToFulfill].requestId, + coordinator: address(s_functionsCoordinator), + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false, 1, gasToUse); + } + + function test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() public { + // Find the storage slot that the Subscription is on + vm.record(); + s_functionsRouter.getSubscription(s_subscriptionId); + (bytes32[] memory reads, ) = vm.accesses(address(s_functionsRouter)); + // The first read is from '_isExistingSubscription' which checks Subscription.owner on slot 0 + // Slot 0 is shared with the Subscription.balance + uint256 slot = uint256(reads[0]); + + // The request has already been initiated, forcibly lower the subscription's balance by clearing out slot 0 + uint96 balance = 1; + address owner = address(0); + bytes32 data = bytes32(abi.encodePacked(balance, owner)); // TODO: make this more accurate + vm.store(address(s_functionsRouter), bytes32(uint256(slot)), data); + + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); + emit RequestNotProcessed({ + requestId: s_requests[requestToFulfill].requestId, + coordinator: address(s_functionsCoordinator), + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); + } + + function test_Fulfill_RequestNotProcessedCostExceedsCommitment() public { + // Use higher juelsPerGas than request time + // 10x the gas price + vm.txGasPrice(TX_GASPRICE_START * 10); + + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); + emit RequestNotProcessed({ + requestId: s_requests[requestToFulfill].requestId, + coordinator: address(s_functionsCoordinator), + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); + } + + event RequestProcessed( + bytes32 indexed requestId, + uint64 indexed subscriptionId, + uint96 totalCostJuels, + address transmitter, + FunctionsResponse.FulfillResult resultCode, + bytes response, + bytes err, + bytes callbackReturnData + ); + + FunctionsClientTestHelper internal s_clientWithFailingCallback; + + function test_Fulfill_SuccessUserCallbackReverts() public { + // Deploy Client with failing callback + s_clientWithFailingCallback = new FunctionsClientTestHelper(address(s_functionsRouter)); + s_clientWithFailingCallback.setRevertFulfillRequest(true); + + // Add Client as a subscription consumer + s_functionsRouter.addConsumer(s_subscriptionId, address(s_clientWithFailingCallback)); + + // Send a minimal request + uint256 requestKey = 99; + + string memory sourceCode = "return 'hello world';"; + uint32 callbackGasLimit = 5500; + + vm.recordLogs(); + bytes32 requestId = s_clientWithFailingCallback.sendSimpleRequestWithJavaScript( + sourceCode, + s_subscriptionId, + s_donId, + callbackGasLimit + ); + + // Get commitment data from OracleRequest event log + Vm.Log[] memory entries = vm.getRecordedLogs(); + (, , , , , , , FunctionsResponse.Commitment memory _commitment) = abi.decode( + entries[0].data, + (address, uint64, address, bytes, uint16, bytes32, uint64, FunctionsResponse.Commitment) + ); + + s_requests[requestKey] = Request({ + requestData: RequestData({ + sourceCode: sourceCode, + secrets: new bytes(0), + args: new string[](0), + bytesArgs: new bytes[](0), + callbackGasLimit: callbackGasLimit + }), + requestId: requestId, + commitment: _commitment, // This commitment contains the operationFee in place of adminFee + commitmentOnchain: FunctionsResponse.Commitment({ + coordinator: _commitment.coordinator, + client: _commitment.client, + subscriptionId: _commitment.subscriptionId, + callbackGasLimit: _commitment.callbackGasLimit, + estimatedTotalCostJuels: _commitment.estimatedTotalCostJuels, + timeoutTimestamp: _commitment.timeoutTimestamp, + requestId: _commitment.requestId, + donFee: _commitment.donFee, + gasOverheadBeforeCallback: _commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: _commitment.gasOverheadAfterCallback, + adminFee: s_adminFee + }) + }); + + // Fulfill + uint256 requestToFulfill = requestKey; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); + emit RequestProcessed({ + requestId: requestId, + subscriptionId: s_subscriptionId, + totalCostJuels: _getExpectedCost(1822), // gasUsed is manually taken + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, + response: bytes(response), + err: err, + callbackReturnData: vm.parseBytes( + "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f61736b656420746f207265766572740000000000000000000000000000000000" + ) // TODO: build this programatically + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); + } + + function test_Fulfill_SuccessUserCallbackRunsOutOfGas() public { + // Send request #2 with no callback gas + string memory sourceCode = "return 'hello world';"; + bytes memory secrets = new bytes(0); + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + uint32 callbackGasLimit = 0; + _sendAndStoreRequest(2, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + + uint256 requestToFulfill = 2; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1: request ID(true), NOT topic2 (false), NOT topic3 (false), and data (true). + vm.expectEmit(true, false, false, true); + emit RequestProcessed({ + requestId: s_requests[requestToFulfill].requestId, + subscriptionId: s_subscriptionId, + totalCostJuels: _getExpectedCost(137), // gasUsed is manually taken + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, + response: bytes(response), + err: err, + callbackReturnData: new bytes(0) + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); + } + + function test_Fulfill_SuccessClientNoLongerExists() public { + // Delete the Client contract in the time between request and fulfillment + vm.etch(address(s_functionsClient), new bytes(0)); + + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1 (true), topic2 (true), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = true; + bool checkTopic2SubscriptionId = true; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2SubscriptionId, checkTopic3, checkData); + emit RequestProcessed({ + requestId: s_requests[requestToFulfill].requestId, + subscriptionId: s_subscriptionId, + totalCostJuels: _getExpectedCost(0), // gasUsed is manually taken + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, + response: bytes(response), + err: err, + callbackReturnData: new bytes(0) + }); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); + } + + function test_Fulfill_SuccessFulfilled() public { + // Fulfill request 1 + uint256 requestToFulfill = 1; + + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestToFulfill; + string[] memory results = new string[](1); + string memory response = "hello world!"; + results[0] = response; + bytes[] memory errors = new bytes[](1); + bytes memory err = new bytes(0); + errors[0] = err; + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1RequestId = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); + emit RequestProcessed({ + requestId: s_requests[requestToFulfill].requestId, + subscriptionId: s_subscriptionId, + totalCostJuels: _getExpectedCost(5416), // gasUsed is manually taken + transmitter: NOP_TRANSMITTER_ADDRESS_1, + resultCode: FunctionsResponse.FulfillResult.FULFILLED, + response: bytes(response), + err: err, + callbackReturnData: new bytes(0) + }); + _reportAndStore(requestNumberKeys, results, errors); + } +} + +/// @notice #_callback +contract FunctionsRouter__Callback is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #getContractById +contract FunctionsRouter_GetContractById is FunctionsRoutesSetup { + function test_GetContractById_RevertIfRouteDoesNotExist() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 invalidRouteId = bytes32("this does not exist"); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidRouteId)); + s_functionsRouter.getContractById(invalidRouteId); + } + + function test_GetContractById_SuccessIfRouteExists() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + address routeDestination = s_functionsRouter.getContractById(s_donId); + assertEq(routeDestination, address(s_functionsCoordinator)); + } +} + +/// @notice #getProposedContractById +contract FunctionsRouter_GetProposedContractById is FunctionsRoutesSetup { + FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper + + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + // Deploy new Coordinator contract + s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + + // Propose new Coordinator contract + bytes32[] memory proposedContractSetIds = new bytes32[](1); + proposedContractSetIds[0] = s_donId; + address[] memory proposedContractSetAddresses = new address[](1); + proposedContractSetAddresses[0] = address(s_functionsCoordinator2); + + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + function test_GetProposedContractById_RevertIfRouteDoesNotExist() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 invalidRouteId = bytes32("this does not exist"); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidRouteId)); + s_functionsRouter.getProposedContractById(invalidRouteId); + } + + function test_GetProposedContractById_SuccessIfRouteExists() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + address routeDestination = s_functionsRouter.getProposedContractById(s_donId); + assertEq(routeDestination, address(s_functionsCoordinator2)); + } +} + +/// @notice #getProposedContractSet +contract FunctionsRouter_GetProposedContractSet is FunctionsRoutesSetup { + FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper + bytes32[] s_proposedContractSetIds; + address[] s_proposedContractSetAddresses; + + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + // Deploy new Coordinator contract + s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + + // Propose new Coordinator contract + s_proposedContractSetIds = new bytes32[](1); + s_proposedContractSetIds[0] = s_donId; + s_proposedContractSetAddresses = new address[](1); + s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); + + s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); + } + + function test_GetProposedContractSet_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + (bytes32[] memory proposedContractSetIds, address[] memory proposedContractSetAddresses) = s_functionsRouter + .getProposedContractSet(); + + assertEq(proposedContractSetIds.length, 1); + assertEq(proposedContractSetIds[0], s_donId); + assertEq(proposedContractSetIds.length, 1); + assertEq(proposedContractSetAddresses[0], address(s_functionsCoordinator2)); + } +} + +/// @notice #proposeContractsUpdate +contract FunctionsRouter_ProposeContractsUpdate is FunctionsRoutesSetup { + FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper + bytes32[] s_proposedContractSetIds; + address[] s_proposedContractSetAddresses; + + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + // Deploy new Coordinator contract + s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + + // Propose new Coordinator contract + s_proposedContractSetIds = new bytes32[](1); + s_proposedContractSetIds[0] = s_donId; + s_proposedContractSetAddresses = new address[](1); + s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); + } + + function test_ProposeContractsUpdate_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); + } + + function test_ProposeContractsUpdate_RevertIfLengthMismatch() public { + bytes32[] memory proposedContractSetIds = new bytes32[](1); + proposedContractSetIds[0] = s_donId; + address[] memory proposedContractSetAddresses = new address[](1); + + vm.expectRevert(FunctionsRouter.InvalidProposal.selector); + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + function test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() public { + uint8 MAX_PROPOSAL_SET_LENGTH = 8; + uint8 INVALID_PROPOSAL_SET_LENGTH = MAX_PROPOSAL_SET_LENGTH + 1; + + // Generate some mock data + bytes32[] memory proposedContractSetIds = new bytes32[](INVALID_PROPOSAL_SET_LENGTH); + for (uint256 i = 0; i < INVALID_PROPOSAL_SET_LENGTH; ++i) { + proposedContractSetIds[i] = bytes32(uint256(i + 111)); + } + address[] memory proposedContractSetAddresses = new address[](INVALID_PROPOSAL_SET_LENGTH); + for (uint256 i = 0; i < INVALID_PROPOSAL_SET_LENGTH; ++i) { + proposedContractSetAddresses[i] = address(uint160(uint(keccak256(abi.encodePacked(i + 111))))); + } + + vm.expectRevert(FunctionsRouter.InvalidProposal.selector); + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + function test_ProposeContractsUpdate_RevertIfEmptyAddress() public { + bytes32[] memory proposedContractSetIds = new bytes32[](1); + proposedContractSetIds[0] = s_donId; + address[] memory proposedContractSetAddresses = new address[](1); + proposedContractSetAddresses[0] = address(0); + + vm.expectRevert(FunctionsRouter.InvalidProposal.selector); + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + function test_ProposeContractsUpdate_RevertIfNotNewContract() public { + bytes32[] memory proposedContractSetIds = new bytes32[](1); + proposedContractSetIds[0] = s_donId; + address[] memory proposedContractSetAddresses = new address[](1); + proposedContractSetAddresses[0] = address(s_functionsCoordinator); + + vm.expectRevert(FunctionsRouter.InvalidProposal.selector); + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + } + + event ContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ); + + function test_ProposeContractsUpdate_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ContractProposed({ + proposedContractSetId: s_proposedContractSetIds[0], + proposedContractSetFromAddress: address(s_functionsCoordinator), + proposedContractSetToAddress: s_proposedContractSetAddresses[0] + }); + + s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); + } +} + +/// @notice #updateContracts +contract FunctionsRouter_UpdateContracts is FunctionsRoutesSetup { + FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper + bytes32[] s_proposedContractSetIds; + address[] s_proposedContractSetAddresses; + + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + // Deploy new Coordinator contract + s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + + // Propose new Coordinator contract + s_proposedContractSetIds = new bytes32[](1); + s_proposedContractSetIds[0] = s_donId; + s_proposedContractSetAddresses = new address[](1); + s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); + + s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); + } + + function test_UpdateContracts_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.updateContracts(); + } + + event ContractUpdated(bytes32 id, address from, address to); + + function test_UpdateContracts_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ContractUpdated({ + id: s_proposedContractSetIds[0], + from: address(s_functionsCoordinator), + to: s_proposedContractSetAddresses[0] + }); + + s_functionsRouter.updateContracts(); + + (bytes32[] memory proposedContractSetIds, address[] memory proposedContractSetAddresses) = s_functionsRouter + .getProposedContractSet(); + + assertEq(proposedContractSetIds.length, 0); + assertEq(proposedContractSetAddresses.length, 0); + } +} + +/// @notice #_whenNotPaused +contract FunctionsRouter__WhenNotPaused is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #_onlyRouterOwner +contract FunctionsRouter__OnlyRouterOwner is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #_onlySenderThatAcceptedToS +contract FunctionsRouter__OnlySenderThatAcceptedToS is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #pause +contract FunctionsRouter_Pause is FunctionsRouterSetup { + function setUp() public virtual override { + FunctionsRouterSetup.setUp(); + } + + event Paused(address account); + + function test_Pause_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.pause(); + } + + function test_Pause_Success() public { + // topic0 (always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + vm.expectEmit(false, false, false, true); + emit Paused(OWNER_ADDRESS); + + s_functionsRouter.pause(); + + bool isPaused = s_functionsRouter.paused(); + assertEq(isPaused, true); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.createSubscription(); + } +} + +/// @notice #unpause +contract FunctionsRouter_Unpause is FunctionsRouterSetup { + function setUp() public virtual override { + FunctionsRouterSetup.setUp(); + s_functionsRouter.pause(); + } + + event Unpaused(address account); + + function test_Unpause_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.unpause(); + } + + function test_Unpause_Success() public { + // topic0 (always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + vm.expectEmit(false, false, false, true); + emit Unpaused(OWNER_ADDRESS); + + s_functionsRouter.unpause(); + + bool isPaused = s_functionsRouter.paused(); + assertEq(isPaused, false); + + s_functionsRouter.createSubscription(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol new file mode 100644 index 0000000..a6dda5a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol @@ -0,0 +1,1291 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +import {FunctionsRouterSetup, FunctionsOwnerAcceptTermsOfServiceSetup, FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup} from "./Setup.t.sol"; + +import "forge-std/Vm.sol"; + +// ================================================================ +// | Functions Subscriptions | +// ================================================================ + +contract FunctionsSubscriptions_Constructor_Helper is FunctionsSubscriptions { + constructor(address link) FunctionsSubscriptions(link) {} + + function getLinkToken() public view returns (IERC20) { + return IERC20(i_linkToken); + } + + // overrides + function _getMaxConsumers() internal pure override returns (uint16) { + return 0; + } + + function _getSubscriptionDepositDetails() internal pure override returns (uint16, uint72) { + return (0, 0); + } + + function _onlySenderThatAcceptedToS() internal override {} + + function _onlyRouterOwner() internal override {} + + function _whenNotPaused() internal override {} +} + +/// @notice #constructor +contract FunctionsSubscriptions_Constructor is BaseTest { + FunctionsSubscriptions_Constructor_Helper s_subscriptionsHelper; + address internal s_linkToken = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; + + function setUp() public virtual override { + BaseTest.setUp(); + s_subscriptionsHelper = new FunctionsSubscriptions_Constructor_Helper(s_linkToken); + } + + function test_Constructor_Success() public { + assertEq(address(s_linkToken), address(s_subscriptionsHelper.getLinkToken())); + } +} + +/// @notice #_markRequestInFlight +contract FunctionsSubscriptions__MarkRequestInFlight { + // TODO: make contract internal function helper +} + +/// @notice #_pay +contract FunctionsSubscriptions__Pay { + // TODO: make contract internal function helper +} + +/// @notice #ownerCancelSubscription +contract FunctionsSubscriptions_OwnerCancelSubscription is FunctionsSubscriptionSetup { + function test_OwnerCancelSubscription_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.ownerCancelSubscription(s_subscriptionId); + } + + function test_OwnerCancelSubscription_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_functionsRouter.ownerCancelSubscription(invalidSubscriptionId); + } + + function test_OwnerCancelSubscription_SuccessSubOwnerRefunded() public { + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + s_functionsRouter.ownerCancelSubscription(s_subscriptionId); + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + s_subscriptionInitialFunding, subscriptionOwnerBalanceAfter); + } + + function test_OwnerCancelSubscription_SuccessWhenRequestInFlight() public { + // send request + string memory sourceCode = "return 'hello world';"; + bytes memory secrets; + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + + s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5500); + s_functionsRouter.ownerCancelSubscription(s_subscriptionId); + } + + function test_OwnerCancelSubscription_SuccessDeletesSubscription() public { + s_functionsRouter.ownerCancelSubscription(s_subscriptionId); + // Subscription should no longer exist + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.getSubscription(s_subscriptionId); + } + + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + + function test_OwnerCancelSubscription_Success() public { + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1SubscriptionId = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1SubscriptionId, checkTopic2, checkTopic3, checkData); + emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, s_subscriptionInitialFunding); + + s_functionsRouter.ownerCancelSubscription(s_subscriptionId); + + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + s_subscriptionInitialFunding, subscriptionOwnerBalanceAfter); + } +} + +/// @notice #recoverFunds +contract FunctionsSubscriptions_RecoverFunds is FunctionsRouterSetup { + event FundsRecovered(address to, uint256 amount); + + function test_RecoverFunds_Success() public { + uint256 fundsTransferred = 1 * 1e18; // 1 LINK + s_linkToken.transfer(address(s_functionsRouter), fundsTransferred); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit FundsRecovered(OWNER_ADDRESS, fundsTransferred); + + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + s_functionsRouter.recoverFunds(OWNER_ADDRESS); + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + fundsTransferred, subscriptionOwnerBalanceAfter); + } + + function test_OwnerCancelSubscription_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.recoverFunds(OWNER_ADDRESS); + } +} + +/// @notice #oracleWithdraw +contract FunctionsSubscriptions_OracleWithdraw is FunctionsFulfillmentSetup { + function test_OracleWithdraw_RevertIfPaused() public { + s_functionsRouter.pause(); + + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + vm.expectRevert("Pausable: paused"); + + uint96 amountToWithdraw = 1; // more than 0 + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + } + + function test_OracleWithdraw_RevertIfNoAmount() public { + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + + uint96 amountToWithdraw = 0; + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + } + + function test_OracleWithdraw_RevertIfAmountMoreThanBalance() public { + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + vm.expectRevert( + abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, s_fulfillmentCoordinatorBalance) + ); + + uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance + 1; + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + } + + function test_OracleWithdraw_RevertIfBalanceInvariant() public { + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + // vm.stopPrank(); + // vm.startPrank(address(s_functionsCoordinator)); + // TODO: Use internal function helper contract to modify s_totalLinkBalance + // uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; + // vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.TotalBalanceInvariantViolated.selector, 0, amountToWithdraw)); + // s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + } + + function test_OracleWithdraw_SuccessPaysRecipient() public { + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + uint256 transmitterBalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1); + + uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + + uint256 transmitterBalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1); + assertEq(transmitterBalanceBefore + s_fulfillmentCoordinatorBalance, transmitterBalanceAfter); + } + + function test_OracleWithdraw_SuccessSetsBalanceToZero() public { + // Subscription payable balances are set to the Coordinator + // Send as Coordinator contract + vm.stopPrank(); + vm.startPrank(address(s_functionsCoordinator)); + + uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); + + // Attempt to withdraw 1 Juel after withdrawing full balance + vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, 0)); + s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, 1); + } +} + +/// @notice #ownerWithdraw +contract FunctionsSubscriptions_OwnerWithdraw is FunctionsFulfillmentSetup { + function test_OwnerWithdraw_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_functionsRouter.recoverFunds(OWNER_ADDRESS); + } + + function test_OwnerWithdraw_RevertIfAmountMoreThanBalance() public { + vm.expectRevert( + abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, s_fulfillmentRouterOwnerBalance) + ); + + uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance + 1; + s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); + } + + function test_OwnerWithdraw_RevertIfBalanceInvariant() public { + // TODO: Use internal function helper contract to modify s_totalLinkBalance + // uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; + // vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.TotalBalanceInvariantViolated.selector, 0, amountToWithdraw)); + // s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); + } + + function test_OwnerWithdraw_SuccessIfRecipientAddressZero() public { + uint256 balanceBefore = s_linkToken.balanceOf(address(0)); + uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; + s_functionsRouter.ownerWithdraw(address(0), amountToWithdraw); + uint256 balanceAfter = s_linkToken.balanceOf(address(0)); + assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); + } + + function test_OwnerWithdraw_SuccessIfNoAmount() public { + uint256 balanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + uint96 amountToWithdraw = 0; + s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); + uint256 balanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); + } + + function test_OwnerWithdraw_SuccessPaysRecipient() public { + uint256 balanceBefore = s_linkToken.balanceOf(STRANGER_ADDRESS); + + uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; + s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, amountToWithdraw); + + uint256 balanceAfter = s_linkToken.balanceOf(STRANGER_ADDRESS); + assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); + } + + function test_OwnerWithdraw_SuccessSetsBalanceToZero() public { + uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; + s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); + + // Attempt to withdraw 1 Juel after withdrawing full balance + vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, 0)); + s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, 1); + } +} + +/// @notice #onTokenTransfer +contract FunctionsSubscriptions_OnTokenTransfer is FunctionsClientSetup { + uint64 s_subscriptionId; + + function setUp() public virtual override { + FunctionsClientSetup.setUp(); + + // Create subscription, but do not fund it + s_subscriptionId = s_functionsRouter.createSubscription(); + s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); + } + + function test_OnTokenTransfer_RevertIfPaused() public { + // Funding amount must be less than or equal to LINK total supply + uint256 totalSupplyJuels = 1_000_000_000 * 1e18; + s_functionsRouter.pause(); + vm.expectRevert("Pausable: paused"); + s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); + } + + function test_OnTokenTransfer_RevertIfCallerIsNotLink() public { + // Funding amount must be less than or equal to LINK total supply + uint256 totalSupplyJuels = 1_000_000_000 * 1e18; + vm.expectRevert(FunctionsSubscriptions.OnlyCallableFromLink.selector); + s_functionsRouter.onTokenTransfer(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); + } + + function test_OnTokenTransfer_RevertIfCallerIsNoCalldata() public { + // Funding amount must be less than or equal to LINK total supply + uint256 totalSupplyJuels = 1_000_000_000 * 1e18; + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, new bytes(0)); + } + + function test_OnTokenTransfer_RevertIfCallerIsNoSubscription() public { + // Funding amount must be less than or equal to LINK total supply + uint256 totalSupplyJuels = 1_000_000_000 * 1e18; + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(invalidSubscriptionId)); + } + + function test_OnTokenTransfer_Success() public { + // Funding amount must be less than LINK total supply + uint256 totalSupplyJuels = 1_000_000_000 * 1e18; + // Some of the total supply is already in the subscription account + s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); + uint96 subscriptionBalanceAfter = s_functionsRouter.getSubscription(s_subscriptionId).balance; + assertEq(totalSupplyJuels, subscriptionBalanceAfter); + } +} + +/// @notice #getTotalBalance +contract FunctionsSubscriptions_GetTotalBalance is FunctionsSubscriptionSetup { + function test_GetTotalBalance_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint96 totalBalance = s_functionsRouter.getTotalBalance(); + assertEq(totalBalance, s_subscriptionInitialFunding); + } +} + +/// @notice #getSubscriptionCount +contract FunctionsSubscriptions_GetSubscriptionCount is FunctionsSubscriptionSetup { + function test_GetSubscriptionCount_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint96 subscriptionCount = s_functionsRouter.getSubscriptionCount(); + // One subscription was made during setup + assertEq(subscriptionCount, 1); + } +} + +/// @notice #getSubscriptionsInRange +contract FunctionsSubscriptions_GetSubscriptionsInRange is FunctionsSubscriptionSetup { + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Create 2 more subscriptions + /* uint64 subscriptionId2 = */ s_functionsRouter.createSubscription(); + uint64 subscriptionId3 = s_functionsRouter.createSubscription(); + + // Give each one unique state + // #1 subscriptionId for requests, #2 empty, #3 proposedOwner of stranger + s_functionsRouter.proposeSubscriptionOwnerTransfer(subscriptionId3, STRANGER_ADDRESS); + } + + function test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + + s_functionsRouter.getSubscriptionsInRange(1, 0); + } + + function test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 lastSubscriptionId = s_functionsRouter.getSubscriptionCount(); + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + s_functionsRouter.getSubscriptionsInRange(1, lastSubscriptionId + 1); + } + + function test_GetSubscriptionsInRange_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 lastSubscriptionId = s_functionsRouter.getSubscriptionCount(); + FunctionsSubscriptions.Subscription[] memory subscriptions = s_functionsRouter.getSubscriptionsInRange( + s_subscriptionId, + lastSubscriptionId + ); + + assertEq(subscriptions.length, 3); + + // Check subscription 1 + assertEq(subscriptions[0].balance, s_subscriptionInitialFunding); + assertEq(subscriptions[0].owner, OWNER_ADDRESS); + assertEq(subscriptions[0].blockedBalance, 0); + assertEq(subscriptions[0].proposedOwner, address(0)); + assertEq(subscriptions[0].consumers[0], address(s_functionsClient)); + assertEq(subscriptions[0].flags, bytes32(0)); + + // Check subscription 2 + assertEq(subscriptions[1].balance, 0); + assertEq(subscriptions[1].owner, OWNER_ADDRESS); + assertEq(subscriptions[1].blockedBalance, 0); + assertEq(subscriptions[1].proposedOwner, address(0)); + assertEq(subscriptions[1].consumers.length, 0); + assertEq(subscriptions[1].flags, bytes32(0)); + + // Check subscription 3 + assertEq(subscriptions[2].balance, 0); + assertEq(subscriptions[2].owner, OWNER_ADDRESS); + assertEq(subscriptions[2].blockedBalance, 0); + assertEq(subscriptions[2].proposedOwner, address(STRANGER_ADDRESS)); + assertEq(subscriptions[2].consumers.length, 0); + assertEq(subscriptions[2].flags, bytes32(0)); + } +} + +/// @notice #getSubscription +contract FunctionsSubscriptions_GetSubscription is FunctionsSubscriptionSetup { + function test_GetSubscription_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); + + assertEq(subscription.balance, s_subscriptionInitialFunding); + assertEq(subscription.owner, OWNER_ADDRESS); + assertEq(subscription.blockedBalance, 0); + assertEq(subscription.proposedOwner, address(0)); + assertEq(subscription.consumers[0], address(s_functionsClient)); + assertEq(subscription.flags, bytes32(0)); + } +} + +/// @notice #getConsumer +contract FunctionsSubscriptions_GetConsumer is FunctionsSubscriptionSetup { + function test_GetConsumer_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + FunctionsSubscriptions.Consumer memory consumer = s_functionsRouter.getConsumer( + address(s_functionsClient), + s_subscriptionId + ); + + assertEq(consumer.allowed, true); + assertEq(consumer.initiatedRequests, 0); + assertEq(consumer.completedRequests, 0); + } +} + +/// @notice #_isExistingSubscription +contract FunctionsSubscriptions__IsExistingSubscription is FunctionsSubscriptionSetup { + // TODO: make contract internal function helper +} + +/// @notice #_isAllowedConsumer +contract FunctionsSubscriptions__IsAllowedConsumer { + // TODO: make contract internal function helper +} + +/// @notice #createSubscription +contract FunctionsSubscriptions_createSubscription is FunctionsOwnerAcceptTermsOfServiceSetup { + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + + function test_CreateSubscription_Success() public { + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(1, OWNER_ADDRESS); + uint64 firstCallSubscriptionId = s_functionsRouter.createSubscription(); + assertEq(firstCallSubscriptionId, 1); + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(2, OWNER_ADDRESS); + uint64 secondCallSubscriptionId = s_functionsRouter.createSubscription(); + assertEq(secondCallSubscriptionId, 2); + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(3, OWNER_ADDRESS); + uint64 thirdCallSubscriptionId = s_functionsRouter.createSubscription(); + assertEq(thirdCallSubscriptionId, 3); + } + + function test_CreateSubscription_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.createSubscription(); + } + + function test_CreateSubscription_RevertIfNotAllowedSender() public { + // Send as stranger, who has not accepted Terms of Service + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, STRANGER_ADDRESS)); + s_functionsRouter.createSubscription(); + } +} + +/// @notice #createSubscriptionWithConsumer +contract FunctionsSubscriptions_CreateSubscriptionWithConsumer is FunctionsClientSetup { + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + + function test_CreateSubscriptionWithConsumer_Success() public { + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(1, OWNER_ADDRESS); + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionConsumerAdded(1, address(s_functionsClient)); + uint64 firstCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); + assertEq(firstCallSubscriptionId, 1); + assertEq(s_functionsRouter.getSubscription(firstCallSubscriptionId).consumers[0], address(s_functionsClient)); + + // Consumer can be address(0) + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(2, OWNER_ADDRESS); + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionConsumerAdded(2, address(0)); + uint64 secondCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(0)); + assertEq(secondCallSubscriptionId, 2); + assertEq(s_functionsRouter.getSubscription(secondCallSubscriptionId).consumers[0], address(0)); + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCreated(3, OWNER_ADDRESS); + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionConsumerAdded(3, address(s_functionsClient)); + uint64 thirdCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); + assertEq(thirdCallSubscriptionId, 3); + assertEq(s_functionsRouter.getSubscription(thirdCallSubscriptionId).consumers[0], address(s_functionsClient)); + } + + function test_CreateSubscriptionWithConsumer_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); + } + + function test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() public { + // Send as stranger, who has not accepted Terms of Service + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, STRANGER_ADDRESS)); + s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); + } +} + +/// @notice #proposeSubscriptionOwnerTransfer +contract FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer is FunctionsSubscriptionSetup { + uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS = 0x3; + address internal NEW_OWNER_ADDRESS_WITH_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS); + uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS2 = 0x4; + address internal NEW_OWNER_ADDRESS_WITH_TOS2 = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS2); + uint256 internal NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS = 0x5; + address internal NEW_OWNER_ADDRESS_WITHOUT_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS); + + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Accept ToS as new owner #1 + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + bytes32 message = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS, r, s, v); + + // Accept ToS as new owner #2 + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS2); + bytes32 message2 = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS2, NEW_OWNER_ADDRESS_WITH_TOS2); + bytes32 prefixedMessage2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message2)); + (uint8 v2, bytes32 r2, bytes32 s2) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage2); + s_termsOfServiceAllowList.acceptTermsOfService( + NEW_OWNER_ADDRESS_WITH_TOS2, + NEW_OWNER_ADDRESS_WITH_TOS2, + r2, + s2, + v2 + ); + + vm.stopPrank(); + vm.startPrank(OWNER_ADDRESS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_functionsRouter.proposeSubscriptionOwnerTransfer(invalidSubscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() public { + // Send as non-owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + + vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() public { + // Remove owner from Allow List + s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() public { + address EMPTY_ADDRESS = address(0); + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, EMPTY_ADDRESS); + } + + function test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() public { + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + } + + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); + + function test_ProposeSubscriptionOwnerTransfer_Success() public { + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS); + } + + function test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() public { + // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = true; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS); + + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS2); + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS2); + assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS2); + } +} + +/// @notice #acceptSubscriptionOwnerTransfer +contract FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer is FunctionsSubscriptionSetup { + uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS = 0x3; + address internal NEW_OWNER_ADDRESS_WITH_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS); + uint256 internal NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS = 0x4; + address internal NEW_OWNER_ADDRESS_WITHOUT_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS); + + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Accept ToS as new owner + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + bytes32 message = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS, r, s, v); + + vm.stopPrank(); + vm.startPrank(OWNER_ADDRESS); + } + + function test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() public { + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + s_functionsRouter.pause(); + + // Send as new owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); + } + + function test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() public { + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITHOUT_TOS); + + // Send as new owner, who has NOT accepted Terms of Service + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITHOUT_TOS); + + vm.expectRevert( + abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, NEW_OWNER_ADDRESS_WITHOUT_TOS) + ); + s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); + } + + function test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() public { + // Propose an address that is allowed to accept ownership + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + bool hasAccess = s_termsOfServiceAllowList.hasAccess(NEW_OWNER_ADDRESS_WITH_TOS, new bytes(0)); + assertEq(hasAccess, true); + + // Revoke access + s_termsOfServiceAllowList.blockSender(NEW_OWNER_ADDRESS_WITH_TOS); + + // Send as blocked address + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + + vm.expectRevert( + abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, NEW_OWNER_ADDRESS_WITH_TOS) + ); + s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); + } + + function test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() public { + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, STRANGER_ADDRESS); + + // Send as someone who is not hte proposed new owner + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.MustBeProposedOwner.selector, STRANGER_ADDRESS)); + s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); + } + + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); + + function test_AcceptSubscriptionOwnerTransfer_Success() public { + // Can transfer ownership with a pending request + string memory sourceCode = "return 'hello world';"; + bytes memory secrets; + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5500); + + s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); + + // Send as new owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionOwnerTransferred(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); + + s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); + + FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); + assertEq(subscription.owner, NEW_OWNER_ADDRESS_WITH_TOS); + assertEq(subscription.proposedOwner, address(0)); + } +} + +/// @notice #removeConsumer +contract FunctionsSubscriptions_RemoveConsumer is FunctionsSubscriptionSetup { + function test_RemoveConsumer_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + } + + function test_RemoveConsumer_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_functionsRouter.removeConsumer(invalidSubscriptionId, address(s_functionsClient)); + } + + function test_RemoveConsumer_RevertIfNotSubscriptionOwner() public { + // Accept ToS as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + + // Send as non-subscription owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + } + + function test_RemoveConsumer_RevertIfNotAllowedSender() public { + // Remove owner from Allow List + s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + } + + function test_RemoveConsumer_RevertIfInvalidConsumer() public { + vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); + s_functionsRouter.removeConsumer(s_subscriptionId, address(0)); + } + + function test_RemoveConsumer_RevertIfPendingRequests() public { + // Send a minimal request + string memory sourceCode = "return 'hello world';"; + bytes memory secrets; + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + + s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); + + vm.expectRevert(FunctionsSubscriptions.CannotRemoveWithPendingRequests.selector); + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + } + + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); + + function test_RemoveConsumer_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionConsumerRemoved(s_subscriptionId, address(s_functionsClient)); + s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); + + FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); + assertEq(subscription.consumers, new address[](0)); + } +} + +/// @notice #_getMaxConsumers +contract FunctionsSubscriptions__GetMaxConsumers is FunctionsRouterSetup { + // TODO: make contract internal function helper +} + +/// @notice #addConsumer +contract FunctionsSubscriptions_AddConsumer is FunctionsSubscriptionSetup { + function test_AddConsumer_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + } + + function test_AddConsumer_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_functionsRouter.addConsumer(invalidSubscriptionId, address(1)); + } + + function test_AddConsumer_RevertIfNotSubscriptionOwner() public { + // Accept ToS as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + + // Send as non-subscription owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + } + + function test_AddConsumer_RevertIfNotAllowedSender() public { + // Remove owner from Allow List + s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + } + + function test_AddConsumer_RevertIfMaximumConsumers() public { + // Fill Consumers to s_maxConsumersPerSubscription + // Already has one from setup + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + s_functionsRouter.addConsumer(s_subscriptionId, address(2)); + + vm.expectRevert( + abi.encodeWithSelector(FunctionsSubscriptions.TooManyConsumers.selector, s_maxConsumersPerSubscription) + ); + s_functionsRouter.addConsumer(s_subscriptionId, address(3)); + } + + function test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() public { + // Fill Consumers to s_maxConsumersPerSubscription + // Already has one from setup + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + s_functionsRouter.addConsumer(s_subscriptionId, address(2)); + + // Lower maxConsumersPerSubscription + s_maxConsumersPerSubscription = 1; + FunctionsRouter.Config memory newRouterConfig = getRouterConfig(); + s_functionsRouter.updateConfig(newRouterConfig); + + // .AddConsumer should still revert + vm.expectRevert( + abi.encodeWithSelector(FunctionsSubscriptions.TooManyConsumers.selector, s_maxConsumersPerSubscription) + ); + s_functionsRouter.addConsumer(s_subscriptionId, address(3)); + } + + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + + function test_AddConsumer_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionConsumerAdded(s_subscriptionId, address(1)); + s_functionsRouter.addConsumer(s_subscriptionId, address(1)); + + FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); + assertEq(subscription.consumers[1], address(1)); + FunctionsSubscriptions.Consumer memory consumer = s_functionsRouter.getConsumer(address(1), s_subscriptionId); + assertEq(consumer.allowed, true); + } +} + +/// @notice #cancelSubscription +contract FunctionsSubscriptions_CancelSubscription is FunctionsSubscriptionSetup { + function test_CancelSubscription_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + } + + function test_CancelSubscription_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + s_functionsRouter.cancelSubscription(invalidSubscriptionId, OWNER_ADDRESS); + } + + function test_CancelSubscription_RevertIfNotSubscriptionOwner() public { + // Accept ToS as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + + // Send as non-subscription owner, who has accepted Terms of Service + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + } + + function test_CancelSubscription_RevertIfNotAllowedSender() public { + // Remove owner from Allow List + s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); + + vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + } + + function test_CancelSubscription_RevertIfPendingRequests() public { + // Send a minimal request + string memory sourceCode = "return 'hello world';"; + bytes memory secrets; + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + + s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); + + vm.expectRevert(FunctionsSubscriptions.CannotRemoveWithPendingRequests.selector); + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + } + + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + + function test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() public { + // No requests have been completed + assertEq(s_functionsRouter.getConsumer(address(s_functionsClient), s_subscriptionId).completedRequests, 0); + // Subscription balance is less than deposit amount + assertLe(s_functionsRouter.getSubscription(s_subscriptionId).balance, s_subscriptionDepositJuels); + + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + + uint96 expectedRefund = 0; + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); + + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); + + // Subscription should no longer exist + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.getSubscription(s_subscriptionId); + + // Router owner should have expectedDepositWithheld to withdraw + uint96 expectedDepositWithheld = s_subscriptionInitialFunding; + uint256 balanceBeforeWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); + s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, 0); + uint256 balanceAfterWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); + assertEq(balanceBeforeWithdraw + expectedDepositWithheld, balanceAfterWithdraw); + } + + function test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() public { + // No requests have been completed + assertEq(s_functionsRouter.getConsumer(address(s_functionsClient), s_subscriptionId).completedRequests, 0); + // Subscription balance is more than deposit amount, double fund the subscription + s_linkToken.transferAndCall(address(s_functionsRouter), s_subscriptionInitialFunding, abi.encode(s_subscriptionId)); + assertGe(s_functionsRouter.getSubscription(s_subscriptionId).balance, s_subscriptionDepositJuels); + + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + + uint96 expectedRefund = (s_subscriptionInitialFunding * 2) - s_subscriptionDepositJuels; + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); + + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); + + // Subscription should no longer exist + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.getSubscription(s_subscriptionId); + + // Router owner should have expectedDepositWithheld to withdraw + uint96 expectedDepositWithheld = s_subscriptionDepositJuels; + uint256 balanceBeforeWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); + s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, 0); + uint256 balanceAfterWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); + assertEq(balanceBeforeWithdraw + expectedDepositWithheld, balanceAfterWithdraw); + } +} + +/// @notice #cancelSubscription +contract FunctionsSubscriptions_CancelSubscription_ReceiveDeposit is FunctionsFulfillmentSetup { + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + + function test_CancelSubscription_SuccessRecieveDeposit() public { + uint96 totalCostJuels = s_fulfillmentRouterOwnerBalance + s_fulfillmentCoordinatorBalance; + + uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); + + uint96 expectedRefund = s_subscriptionInitialFunding - totalCostJuels; + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); + + s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); + + uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); + assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); + + // Subscription should no longer exist + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + s_functionsRouter.getSubscription(s_subscriptionId); + } +} + +/// @notice #_cancelSubscriptionHelper +contract FunctionsSubscriptions__CancelSubscriptionHelper { + // TODO: make contract internal function helper +} + +/// @notice #pendingRequestExists +contract FunctionsSubscriptions_PendingRequestExists is FunctionsFulfillmentSetup { + function test_PendingRequestExists_SuccessFalseIfNoPendingRequests() public { + bool hasPendingRequests = s_functionsRouter.pendingRequestExists(s_subscriptionId); + assertEq(hasPendingRequests, false); + } + + function test_PendingRequestExists_SuccessTrueIfPendingRequests() public { + // Send a minimal request + string memory sourceCode = "return 'hello world';"; + bytes memory secrets; + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + + s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); + + bool hasPendingRequests = s_functionsRouter.pendingRequestExists(s_subscriptionId); + assertEq(hasPendingRequests, true); + } +} + +/// @notice #setFlags +contract FunctionsSubscriptions_SetFlags is FunctionsSubscriptionSetup { + function test_SetFlags_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + bytes32 flagsToSet = bytes32("1"); + s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); + } + + function test_SetFlags_RevertIfNoSubscription() public { + vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); + uint64 invalidSubscriptionId = 123456789; + bytes32 flagsToSet = bytes32("1"); + s_functionsRouter.setFlags(invalidSubscriptionId, flagsToSet); + } + + function test_SetFlags_Success() public { + bytes32 flagsToSet = bytes32("1"); + s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); + bytes32 flags = s_functionsRouter.getFlags(s_subscriptionId); + assertEq(flags, flagsToSet); + } +} + +/// @notice #getFlags +contract FunctionsSubscriptions_GetFlags is FunctionsSubscriptionSetup { + function test_GetFlags_SuccessInvalidSubscription() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 invalidSubscriptionId = 999999; + + bytes32 flags = s_functionsRouter.getFlags(invalidSubscriptionId); + assertEq(flags, bytes32(0)); + } + + function test_GetFlags_SuccessValidSubscription() public { + // Set flags + bytes32 flagsToSet = bytes32("1"); + s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 flags = s_functionsRouter.getFlags(s_subscriptionId); + assertEq(flags, flagsToSet); + } +} + +/// @notice #timeoutRequests +contract FunctionsSubscriptions_TimeoutRequests is FunctionsClientRequestSetup { + function test_TimeoutRequests_RevertIfPaused() public { + s_functionsRouter.pause(); + + vm.expectRevert("Pausable: paused"); + FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); + commitments[0] = s_requests[1].commitmentOnchain; + s_functionsRouter.timeoutRequests(commitments); + } + + function test_TimeoutRequests_RevertInvalidRequest() public { + // Modify the commitment so that it doesn't match + s_requests[1].commitmentOnchain.donFee = 123456789; + FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); + commitments[0] = s_requests[1].commitmentOnchain; + vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); + s_functionsRouter.timeoutRequests(commitments); + } + + function test_TimeoutRequests_RevertIfTimeoutNotExceeded() public { + vm.expectRevert(FunctionsSubscriptions.TimeoutNotExceeded.selector); + FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); + commitments[0] = s_requests[1].commitmentOnchain; + s_functionsRouter.timeoutRequests(commitments); + } + + event RequestTimedOut(bytes32 indexed requestId); + + function test_TimeoutRequests_Success() public { + uint64 consumerCompletedRequestsBefore = s_functionsRouter + .getConsumer(address(s_functionsClient), s_subscriptionId) + .completedRequests; + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit RequestTimedOut(s_requests[1].requestId); + + // Jump ahead in time past timeout timestamp + vm.warp(s_requests[1].commitmentOnchain.timeoutTimestamp + 1); + + FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); + commitments[0] = s_requests[1].commitmentOnchain; + s_functionsRouter.timeoutRequests(commitments); + + // Releases blocked balance and increments completed requests + uint96 subscriptionBlockedBalanceAfter = s_functionsRouter.getSubscription(s_subscriptionId).blockedBalance; + assertEq(0, subscriptionBlockedBalanceAfter); + uint64 consumerCompletedRequestsAfter = s_functionsRouter + .getConsumer(address(s_functionsClient), s_subscriptionId) + .completedRequests; + assertEq(consumerCompletedRequestsBefore + 1, consumerCompletedRequestsAfter); + } +} + +// @notice #_onlySubscriptionOwner +contract FunctionsSubscriptions__OnlySubscriptionOwner { + // TODO: make contract internal function helper +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol new file mode 100644 index 0000000..9bf0974 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol @@ -0,0 +1,557 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol"; +import {TermsOfServiceAllowListConfig} from "../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; +import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; + +import {FunctionsRoutesSetup, FunctionsOwnerAcceptTermsOfServiceSetup} from "./Setup.t.sol"; +import "forge-std/Vm.sol"; + +/// @notice #constructor +contract FunctionsTermsOfServiceAllowList_Constructor is FunctionsRoutesSetup { + function test_Constructor_Success() public { + assertEq(s_termsOfServiceAllowList.typeAndVersion(), "Functions Terms of Service Allow List v1.1.1"); + assertEq(s_termsOfServiceAllowList.owner(), OWNER_ADDRESS); + } +} + +/// @notice #getConfig +contract FunctionsTermsOfServiceAllowList_GetConfig is FunctionsRoutesSetup { + function test_GetConfig_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + TermsOfServiceAllowListConfig memory config = s_termsOfServiceAllowList.getConfig(); + assertEq(config.enabled, getTermsOfServiceConfig().enabled); + assertEq(config.signerPublicKey, getTermsOfServiceConfig().signerPublicKey); + } +} + +/// @notice #updateConfig +contract FunctionsTermsOfServiceAllowList_UpdateConfig is FunctionsRoutesSetup { + function test_UpdateConfig_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_termsOfServiceAllowList.updateConfig( + TermsOfServiceAllowListConfig({enabled: true, signerPublicKey: STRANGER_ADDRESS}) + ); + } + + event ConfigUpdated(TermsOfServiceAllowListConfig config); + + function test_UpdateConfig_Success() public { + TermsOfServiceAllowListConfig memory configToSet = TermsOfServiceAllowListConfig({ + enabled: false, + signerPublicKey: TOS_SIGNER + }); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit ConfigUpdated(configToSet); + + s_termsOfServiceAllowList.updateConfig(configToSet); + + TermsOfServiceAllowListConfig memory config = s_termsOfServiceAllowList.getConfig(); + assertEq(config.enabled, configToSet.enabled); + assertEq(config.signerPublicKey, configToSet.signerPublicKey); + } +} + +/// @notice #getMessage +contract FunctionsTermsOfServiceAllowList_GetMessage is FunctionsRoutesSetup { + function test_GetMessage_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + + assertEq(message, keccak256(abi.encodePacked(STRANGER_ADDRESS, STRANGER_ADDRESS))); + } +} + +/// @notice #acceptTermsOfService +contract FunctionsTermsOfServiceAllowList_AcceptTermsOfService is FunctionsRoutesSetup { + function test_AcceptTermsOfService_RevertIfBlockedSender() public { + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + vm.expectRevert(TermsOfServiceAllowList.RecipientIsBlocked.selector); + + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } + + function test_AcceptTermsOfService_RevertIfInvalidSigner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(STRANGER_PRIVATE_KEY, prefixedMessage); + + vm.expectRevert(TermsOfServiceAllowList.InvalidSignature.selector); + + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } + + function test_AcceptTermsOfService_RevertIfRecipientIsNotSender() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); + + s_termsOfServiceAllowList.acceptTermsOfService(OWNER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } + + function test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, OWNER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); + + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, OWNER_ADDRESS, r, s, v); + } + + function test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() public { + FunctionsClientTestHelper s_functionsClientHelper = new FunctionsClientTestHelper(address(s_functionsRouter)); + + // Send as externally owned account + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Attempt to accept for a contract account + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, address(s_functionsClientHelper)); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); + + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, address(s_functionsClientHelper), r, s, v); + } + + function testAcceptTermsOfService_InvalidSigner_vuln() public { + // Set the signer as the zero address + TermsOfServiceAllowListConfig memory allowListConfig; + allowListConfig.enabled = true; + allowListConfig.signerPublicKey = address(0); + s_termsOfServiceAllowList.updateConfig(allowListConfig); + + // Provide garbage data (v cannot be 29) to generate an invalid signature + uint8 v = 29; + bytes32 r = 0x0101010000000000000000000000000000000000000000000000000000000000; + bytes32 s = 0x0101010000000000000000000000000000000000000000000000000000000000; + + // Expect a revert on invalid signature but the call is successful + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + // vm.expectRevert(TermsOfServiceAllowList.InvalidSignature.selector); + // TODO: Add validation to setConfig to prevent empty signer + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } + + event AddedAccess(address user); + + function test_AcceptTermsOfService_SuccessIfAcceptingForSelf() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit AddedAccess(STRANGER_ADDRESS); + + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + + assertTrue(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); + + // Check the addedAccess is not emitted, given the recipient was already in the list + vm.recordLogs(); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + Vm.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries.length, 0); + + assertTrue(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); + } + + function test_AcceptTermsOfService_SuccessIfAcceptingForContract() public { + FunctionsClientTestHelper s_functionsClientHelper = new FunctionsClientTestHelper(address(s_functionsRouter)); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, address(s_functionsClientHelper)); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit AddedAccess(address(s_functionsClientHelper)); + + s_functionsClientHelper.acceptTermsOfService(STRANGER_ADDRESS, address(s_functionsClientHelper), r, s, v); + + assertEq(s_termsOfServiceAllowList.hasAccess(address(s_functionsClientHelper), new bytes(0)), true); + } +} + +/// @notice #getAllAllowedSenders +contract FunctionsTermsOfServiceAllowList_GetAllAllowedSenders is FunctionsOwnerAcceptTermsOfServiceSetup { + function test_GetAllAllowedSenders_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + address[] memory expectedSenders = new address[](1); + expectedSenders[0] = OWNER_ADDRESS; + + assertEq(s_termsOfServiceAllowList.getAllAllowedSenders(), expectedSenders); + } +} + +/// @notice #getAllowedSendersCount +contract FunctionsTermsOfServiceAllowList_GetAllowedSendersCount is FunctionsOwnerAcceptTermsOfServiceSetup { + function test_GetAllowedSendersCount_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint96 allowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); + // One allowed sender was made during setup + assertEq(allowedSendersCount, 1); + } +} + +/// @notice #getAllowedSendersInRange +contract FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange is FunctionsOwnerAcceptTermsOfServiceSetup { + function test_GetAllowedSendersInRange_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + address[] memory expectedSenders = new address[](1); + expectedSenders[0] = OWNER_ADDRESS; + + assertEq(s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0), expectedSenders); + } + + function test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() public { + // setup a new empty s_termsOfServiceAllowList + FunctionsRoutesSetup.setUp(); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); + uint64 expected = 0; + assertEq(AllowedSendersCount, expected); + + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0); + } + + function test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + + s_termsOfServiceAllowList.getAllowedSendersInRange(1, 0); + } + + function test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + s_termsOfServiceAllowList.getAllowedSendersInRange(1, AllowedSendersCount + 1); + } +} + +/// @notice #hasAccess +contract FunctionsTermsOfServiceAllowList_HasAccess is FunctionsRoutesSetup { + function test_HasAccess_FalseWhenEnabled() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Check access of account that is not on the allow list + assertEq(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0)), false); + } + + function test_HasAccess_TrueWhenDisabled() public { + // Disable allow list, which opens all access + s_termsOfServiceAllowList.updateConfig( + TermsOfServiceAllowListConfig({enabled: false, signerPublicKey: TOS_SIGNER}) + ); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Check access of account that is not on the allow list + assertEq(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0)), true); + } +} + +/// @notice #isBlockedSender +contract FunctionsTermsOfServiceAllowList_IsBlockedSender is FunctionsRoutesSetup { + function test_IsBlockedSender_SuccessFalse() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + assertEq(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS), false); + } + + function test_IsBlockedSender_SuccessTrue() public { + // Block sender + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + assertEq(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS), true); + } +} + +/// @notice #blockSender +contract FunctionsTermsOfServiceAllowList_BlockSender is FunctionsRoutesSetup { + function test_BlockSender_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); + } + + event BlockedAccess(address user); + + function test_BlockSender_Success() public { + assertFalse(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS)); + + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit BlockedAccess(STRANGER_ADDRESS); + + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + assertFalse(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); + assertTrue(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS)); + + // Account can no longer accept Terms of Service + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + vm.expectRevert(TermsOfServiceAllowList.RecipientIsBlocked.selector); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } +} + +/// @notice #unblockSender +contract FunctionsTermsOfServiceAllowList_UnblockSender is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + } + + function test_UnblockSender_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + s_termsOfServiceAllowList.unblockSender(STRANGER_ADDRESS); + } + + event UnblockedAccess(address user); + + function test_UnblockSender_Success() public { + // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). + bool checkTopic1 = false; + bool checkTopic2 = false; + bool checkTopic3 = false; + bool checkData = true; + vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); + emit UnblockedAccess(STRANGER_ADDRESS); + + s_termsOfServiceAllowList.unblockSender(STRANGER_ADDRESS); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + // Account can now accept the Terms of Service + bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); + } +} + +/// @notice #getBlockedSendersCount +contract FunctionsTermsOfServiceAllowList_GetBlockedSendersCount is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + } + + function test_GetBlockedSendersCount_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint96 blockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); + // One blocked sender was made during setup + assertEq(blockedSendersCount, 1); + } +} + +/// @notice #getBlockedSendersInRange +contract FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); + } + + function test_GetBlockedSendersInRange_Success() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + address[] memory expectedBlockedSenders = new address[](1); + expectedBlockedSenders[0] = STRANGER_ADDRESS; + + assertEq(s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0), expectedBlockedSenders); + } + + function test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() public { + // setup a new empty s_termsOfServiceBlockList + FunctionsRoutesSetup.setUp(); + + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); + uint64 expected = 0; + assertEq(BlockedSendersCount, expected); + + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0); + } + + function test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + + s_termsOfServiceAllowList.getBlockedSendersInRange(1, 0); + } + + function test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); + vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); + s_termsOfServiceAllowList.getBlockedSendersInRange(1, BlockedSendersCount + 1); + } +} + +/// @notice #migratePreviouslyAllowedSenders +contract FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + } + + function test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + address[] memory empty = new address[](0); + s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(empty); + } + + function test_MigratePreviouslyAllowedSenders_Success() public { + address previouslyAllowedSender1 = 0x1000000000000000000000000000000000000000; + address previouslyAllowedSender2 = 0x2000000000000000000000000000000000000000; + address currentlyBlockedSender = 0xB000000000000000000000000000000000000000; + + address[] memory mockPreviousAllowlist = new address[](3); + mockPreviousAllowlist[0] = previouslyAllowedSender1; + mockPreviousAllowlist[1] = currentlyBlockedSender; + mockPreviousAllowlist[2] = previouslyAllowedSender2; + + s_termsOfServiceAllowList.blockSender(currentlyBlockedSender); + + vm.mockCall( + MOCK_PREVIOUS_TOS_ADDRESS, + abi.encodeWithSelector(TermsOfServiceAllowList.hasAccess.selector), + abi.encode(true) + ); + s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(mockPreviousAllowlist); + + address[] memory currentlyAllowedSenders = s_termsOfServiceAllowList.getAllAllowedSenders(); + + address[] memory expectedAllowedSenders = new address[](2); + expectedAllowedSenders[0] = previouslyAllowedSender1; + expectedAllowedSenders[1] = previouslyAllowedSender2; + assertEq(currentlyAllowedSenders, expectedAllowedSenders); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol new file mode 100644 index 0000000..1ecc0fb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; +import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; +import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; + +import {FunctionsRoutesSetup, FunctionsOwnerAcceptTermsOfServiceSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; + +import "forge-std/Vm.sol"; + +/// @notice #acceptTermsOfService +contract Gas_AcceptTermsOfService is FunctionsRoutesSetup { + bytes32 s_sigR; + bytes32 s_sigS; + uint8 s_sigV; + + function setUp() public virtual override { + vm.pauseGasMetering(); + + FunctionsRoutesSetup.setUp(); + + bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, OWNER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (s_sigV, s_sigR, s_sigS) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + } + + function test_AcceptTermsOfService_Gas() public { + // Pull storage variables into memory + address ownerAddress = OWNER_ADDRESS; + bytes32 sigR = s_sigR; + bytes32 sigS = s_sigS; + uint8 sigV = s_sigV; + vm.resumeGasMetering(); + + s_termsOfServiceAllowList.acceptTermsOfService(ownerAddress, ownerAddress, sigR, sigS, sigV); + } +} + +/// @notice #createSubscription +contract Gas_CreateSubscription is FunctionsOwnerAcceptTermsOfServiceSetup { + function test_CreateSubscription_Gas() public { + s_functionsRouter.createSubscription(); + } +} + +/// @notice #addConsumer +contract Gas_AddConsumer is FunctionsSubscriptionSetup { + function setUp() public virtual override { + vm.pauseGasMetering(); + + FunctionsSubscriptionSetup.setUp(); + } + + function test_AddConsumer_Gas() public { + // Keep input data in memory + uint64 subscriptionId = s_subscriptionId; + address consumerAddress = address(s_functionsCoordinator); // use garbage address + vm.resumeGasMetering(); + + s_functionsRouter.addConsumer(subscriptionId, consumerAddress); + } +} + +/// @notice #fundSubscription +contract Gas_FundSubscription is FunctionsSubscriptionSetup { + function setUp() public virtual override { + vm.pauseGasMetering(); + + FunctionsSubscriptionSetup.setUp(); + } + + function test_FundSubscription_Gas() public { + // Keep input data in memory + address routerAddress = address(s_functionsRouter); + uint96 s_subscriptionFunding = 10 * JUELS_PER_LINK; // 10 LINK + bytes memory data = abi.encode(s_subscriptionId); + vm.resumeGasMetering(); + + s_linkToken.transferAndCall(routerAddress, s_subscriptionFunding, data); + } +} + +/// @notice #sendRequest +contract Gas_SendRequest is FunctionsSubscriptionSetup { + bytes s_minimalRequestData; + bytes s_maximalRequestData; + + function _makeStringOfBytesSize(uint16 bytesSize) internal pure returns (string memory) { + return vm.toString(new bytes((bytesSize - 2) / 2)); + } + + function setUp() public virtual override { + vm.pauseGasMetering(); + + FunctionsSubscriptionSetup.setUp(); + + { + // Create minimum viable request data + FunctionsRequest.Request memory minimalRequest; + string memory minimalSourceCode = "return Functions.encodeString('hello world');"; + FunctionsRequest._initializeRequest( + minimalRequest, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + minimalSourceCode + ); + s_minimalRequestData = FunctionsRequest._encodeCBOR(minimalRequest); + } + + { + // Create maximum viable request data - 30 KB encoded data + FunctionsRequest.Request memory maxmimalRequest; + + // Create maximum viable request data - 30 KB encoded data + string memory maximalSourceCode = _makeStringOfBytesSize(29_898); // CBOR size without source code is 102 bytes + FunctionsRequest._initializeRequest( + maxmimalRequest, + FunctionsRequest.Location.Inline, + FunctionsRequest.CodeLanguage.JavaScript, + maximalSourceCode + ); + s_maximalRequestData = FunctionsRequest._encodeCBOR(maxmimalRequest); + assertEq(s_maximalRequestData.length, 30_000); + } + } + + /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values + function test_SendRequest_MaximumGas() public { + // Pull storage variables into memory + bytes memory maximalRequestData = s_maximalRequestData; + uint64 subscriptionId = s_subscriptionId; + uint32 callbackGasLimit = 300_000; + bytes32 donId = s_donId; + vm.resumeGasMetering(); + + s_functionsClient.sendRequestBytes(maximalRequestData, subscriptionId, callbackGasLimit, donId); + } + + function test_SendRequest_MinimumGas() public { + // Pull storage variables into memory + bytes memory minimalRequestData = s_minimalRequestData; + uint64 subscriptionId = s_subscriptionId; + uint32 callbackGasLimit = 5_500; + bytes32 donId = s_donId; + vm.resumeGasMetering(); + + s_functionsClient.sendRequestBytes(minimalRequestData, subscriptionId, callbackGasLimit, donId); + } +} + +// Setup Fulfill Gas tests +contract Gas_FulfillRequest_Setup is FunctionsClientRequestSetup { + mapping(uint256 reportNumber => Report) s_reports; + + FunctionsClientTestHelper s_functionsClientWithMaximumReturnData; + + function _makeStringOfBytesSize(uint16 bytesSize) internal pure returns (string memory) { + return vm.toString(new bytes((bytesSize - 2) / 2)); + } + + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + { + // Deploy consumer that has large revert return data + s_functionsClientWithMaximumReturnData = new FunctionsClientTestHelper(address(s_functionsRouter)); + s_functionsClientWithMaximumReturnData.setRevertFulfillRequest(true); + string memory revertMessage = _makeStringOfBytesSize(30_000); // 30kb - FunctionsRouter cuts off response at MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32 = 132bytes, go well above that + s_functionsClientWithMaximumReturnData.setRevertFulfillRequestMessage(revertMessage); + s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClientWithMaximumReturnData)); + } + + // Set up maximum gas test + { + // Send request #2 for maximum gas test + uint8 requestNumber = 2; + + bytes memory secrets = new bytes(0); + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + uint32 callbackGasLimit = 300_000; + + // Create maximum viable request data - 30 KB encoded data + string memory maximalSourceCode = _makeStringOfBytesSize(29_898); // CBOR size without source code is 102 bytes + + _sendAndStoreRequest( + requestNumber, + maximalSourceCode, + secrets, + args, + bytesArgs, + callbackGasLimit, + address(s_functionsClientWithMaximumReturnData) + ); + + // Build the report transmission data + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = requestNumber; + string[] memory results = new string[](1); + // Build a 256 byte response size + results[0] = _makeStringOfBytesSize(256); + bytes[] memory errors = new bytes[](1); + errors[0] = new bytes(0); // No error + + (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); + + uint256[] memory signerPrivateKeys = new uint256[](3); + signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; + signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; + signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; + + (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( + report, + reportContext, + signerPrivateKeys + ); + + // Store the report data + s_reports[1] = Report({rs: rawRs, ss: rawSs, vs: rawVs, report: report, reportContext: reportContext}); + } + + // Set up minimum gas test + { + // Send requests minimum gas test + uint8 requestsToSend = 1; + uint8 requestNumberOffset = 3; // the setup already has request #1 sent, and the previous test case uses request #2, start from request #3 + + string memory sourceCode = "return Functions.encodeString('hello world');"; + bytes memory secrets = new bytes(0); + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + uint32 callbackGasLimit = 5_500; + + for (uint256 i = 0; i < requestsToSend; ++i) { + _sendAndStoreRequest(i + requestNumberOffset, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + } + + // Build the report transmission data + uint256[] memory requestNumberKeys = new uint256[](requestsToSend); + string[] memory results = new string[](requestsToSend); + bytes[] memory errors = new bytes[](requestsToSend); + for (uint256 i = 0; i < requestsToSend; ++i) { + requestNumberKeys[i] = i + requestNumberOffset; + results[i] = "hello world"; + errors[i] = new bytes(0); // no error + } + + (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); + + uint256[] memory signerPrivateKeys = new uint256[](3); + signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; + signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; + signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; + + (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( + report, + reportContext, + signerPrivateKeys + ); + + // Store the report data + s_reports[2] = Report({rs: rawRs, ss: rawSs, vs: rawVs, report: report, reportContext: reportContext}); + } + + vm.stopPrank(); + vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); + } +} + +/// @notice #fulfillRequest +contract Gas_FulfillRequest_Success is Gas_FulfillRequest_Setup { + function setUp() public virtual override { + vm.pauseGasMetering(); + + Gas_FulfillRequest_Setup.setUp(); + } + + /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values + function test_FulfillRequest_Success_MaximumGas() public { + // Pull storage variables into memory + uint8 reportNumber = 1; + bytes32[] memory rs = s_reports[reportNumber].rs; + bytes32[] memory ss = s_reports[reportNumber].ss; + bytes32 vs = s_reports[reportNumber].vs; + bytes memory report = s_reports[reportNumber].report; + bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; + vm.resumeGasMetering(); + + // 1 fulfillment in the report, single request takes on all report validation cost + // maximum request + // maximum NOPs + // maximum return data + // first storage write to change default values + s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); + } + + function test_FulfillRequest_Success_MinimumGas() public { + // Pull storage variables into memory + uint8 reportNumber = 2; + bytes32[] memory rs = s_reports[reportNumber].rs; + bytes32[] memory ss = s_reports[reportNumber].ss; + bytes32 vs = s_reports[reportNumber].vs; + bytes memory report = s_reports[reportNumber].report; + bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; + vm.resumeGasMetering(); + + // max fulfillments in the report, cost of validation split between all + // minimal request + // minimum NOPs + // no return data + // not storage writing default values + s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); + } +} + +/// @notice #fulfillRequest +contract Gas_FulfillRequest_DuplicateRequestID is Gas_FulfillRequest_Setup { + function setUp() public virtual override { + vm.pauseGasMetering(); + + // Send requests + Gas_FulfillRequest_Setup.setUp(); + // Fulfill request #1 & #2 + for (uint256 i = 1; i < 3; i++) { + uint256 reportNumber = i; + bytes32[] memory rs = s_reports[reportNumber].rs; + bytes32[] memory ss = s_reports[reportNumber].ss; + bytes32 vs = s_reports[reportNumber].vs; + bytes memory report = s_reports[reportNumber].report; + bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; + s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); + } + + // Now tests will attempt to transmit reports with respones to requests that have already been fulfilled + } + + /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values + function test_FulfillRequest_DuplicateRequestID_MaximumGas() public { + // Pull storage variables into memory + uint8 reportNumber = 1; + bytes32[] memory rs = s_reports[reportNumber].rs; + bytes32[] memory ss = s_reports[reportNumber].ss; + bytes32 vs = s_reports[reportNumber].vs; + bytes memory report = s_reports[reportNumber].report; + bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; + vm.resumeGasMetering(); + + // 1 fulfillment in the report, single request takes on all report validation cost + // maximum request + // maximum NOPs + // maximum return data + // first storage write to change default values + s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); + } + + function test_FulfillRequest_DuplicateRequestID_MinimumGas() public { + // Pull storage variables into memory + uint8 reportNumber = 2; + bytes32[] memory rs = s_reports[reportNumber].rs; + bytes32[] memory ss = s_reports[reportNumber].ss; + bytes32 vs = s_reports[reportNumber].vs; + bytes memory report = s_reports[reportNumber].report; + bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; + vm.resumeGasMetering(); + + // max fulfillments in the report, cost of validation split between all + // minimal request + // minimum NOPs + // no return data + // not storage writing default values + s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol new file mode 100644 index 0000000..3dc0db8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +// ================================================================ +// | OCR2Base | +// ================================================================ + +/// @notice #constructor +contract OCR2Base_Constructor {} + +/// @notice #checkConfigValid +contract OCR2Base_CheckConfigValid {} + +/// @notice #latestConfigDigestAndEpoch +contract OCR2Base_LatestConfigDigestAndEpoch {} + +/// @notice #setConfig +contract OCR2Base_SetConfig {} + +/// @notice #configDigestFromConfigData +contract OCR2Base_ConfigDigestFromConfigData {} + +/// @notice #latestConfigDetails +contract OCR2Base_LatestConfigDetails {} + +/// @notice #transmitters +contract OCR2Base_Transmitters {} + +/// @notice #_report +contract OCR2Base__Report { + // TODO: make contract internal function helper +} + +/// @notice #requireExpectedMsgDataLength +contract OCR2Base_RequireExpectedMsgDataLength {} + +/// @notice #transmit +contract OCR2Base_Transmit {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md new file mode 100644 index 0000000..5f96532 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md @@ -0,0 +1,25 @@ +## Usage + +First set the foundry profile to Functions: +``` +export FOUNDRY_PROFILE=functions +``` + +**To run tests use**: + +All Functions test files: +``` +forge test -vvv +``` + +To run a specific file use: +``` +forge test -vvv --mp src/v0.8/functions/tests/v1_X/[File Name].t.sol +``` + +**To see coverage**: +First ensure that the correct files are being evaluated. For example, if only v0 contracts are, then temporarily change the Functions profile in `./foundry.toml`. + +``` +forge coverage --ir-minimum +``` \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol new file mode 100644 index 0000000..444fc18 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol @@ -0,0 +1,721 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {FunctionsClientHarness} from "./testhelpers/FunctionsClientHarness.sol"; +import {FunctionsRouterHarness, FunctionsRouter} from "./testhelpers/FunctionsRouterHarness.sol"; +import {FunctionsCoordinatorHarness} from "./testhelpers/FunctionsCoordinatorHarness.sol"; +import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; +import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol"; +import {TermsOfServiceAllowListConfig} from "../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; +import {MockLinkToken} from "../../../mocks/MockLinkToken.sol"; +import {FunctionsBillingConfig} from "../../dev/v1_X/interfaces/IFunctionsBilling.sol"; + +import "forge-std/Vm.sol"; + +/// @notice Set up to deploy the following contracts: FunctionsRouter, FunctionsCoordinator, LINK/ETH Feed, ToS Allow List, and LINK token +contract FunctionsRouterSetup is BaseTest { + FunctionsRouterHarness internal s_functionsRouter; + FunctionsCoordinatorHarness internal s_functionsCoordinator; + MockV3Aggregator internal s_linkEthFeed; + MockV3Aggregator internal s_linkUsdFeed; + TermsOfServiceAllowList internal s_termsOfServiceAllowList; + MockLinkToken internal s_linkToken; + + uint16 internal s_maxConsumersPerSubscription = 3; + uint72 internal s_adminFee = 0; // Keep as 0. Setting this to anything else will cause fulfillments to fail with INVALID_COMMITMENT + uint16 internal s_donFee = 100; // $1 + uint16 internal s_operationFee = 100; // $1 + bytes4 internal s_handleOracleFulfillmentSelector = 0x0ca76175; + uint16 s_subscriptionDepositMinimumRequests = 1; + uint72 s_subscriptionDepositJuels = 11 * JUELS_PER_LINK; + + int256 internal LINK_ETH_RATE = 6_000_000_000_000_000; + uint8 internal LINK_ETH_DECIMALS = 18; + int256 internal LINK_USD_RATE = 1_500_000_000; + uint8 internal LINK_USD_DECIMALS = 8; + + address public MOCK_PREVIOUS_TOS_ADDRESS = 0x746f730000000000000000000000000000000000; + uint256 internal TOS_SIGNER_PRIVATE_KEY = 0x3; + address internal TOS_SIGNER = vm.addr(TOS_SIGNER_PRIVATE_KEY); + + function setUp() public virtual override { + BaseTest.setUp(); + s_linkToken = new MockLinkToken(); + s_functionsRouter = new FunctionsRouterHarness(address(s_linkToken), getRouterConfig()); + s_linkEthFeed = new MockV3Aggregator(LINK_ETH_DECIMALS, LINK_ETH_RATE); + s_linkUsdFeed = new MockV3Aggregator(LINK_USD_DECIMALS, LINK_USD_RATE); + s_functionsCoordinator = new FunctionsCoordinatorHarness( + address(s_functionsRouter), + getCoordinatorConfig(), + address(s_linkEthFeed), + address(s_linkUsdFeed) + ); + address[] memory initialAllowedSenders; + address[] memory initialBlockedSenders; + s_termsOfServiceAllowList = new TermsOfServiceAllowList( + getTermsOfServiceConfig(), + initialAllowedSenders, + initialBlockedSenders, + MOCK_PREVIOUS_TOS_ADDRESS + ); + } + + function getRouterConfig() public view returns (FunctionsRouter.Config memory) { + uint32[] memory maxCallbackGasLimits = new uint32[](3); + maxCallbackGasLimits[0] = 300_000; + maxCallbackGasLimits[1] = 500_000; + maxCallbackGasLimits[2] = 1_000_000; + + return + FunctionsRouter.Config({ + maxConsumersPerSubscription: s_maxConsumersPerSubscription, + adminFee: s_adminFee, + handleOracleFulfillmentSelector: s_handleOracleFulfillmentSelector, + maxCallbackGasLimits: maxCallbackGasLimits, + gasForCallExactCheck: 5000, + subscriptionDepositMinimumRequests: s_subscriptionDepositMinimumRequests, + subscriptionDepositJuels: s_subscriptionDepositJuels + }); + } + + function getCoordinatorConfig() public view returns (FunctionsBillingConfig memory) { + return + FunctionsBillingConfig({ + feedStalenessSeconds: 24 * 60 * 60, // 1 day + gasOverheadAfterCallback: 93_942, + gasOverheadBeforeCallback: 105_000, + requestTimeoutSeconds: 60 * 5, // 5 minutes + donFeeCentsUsd: s_donFee, + operationFeeCentsUsd: s_operationFee, + maxSupportedRequestDataVersion: 1, + fulfillmentGasPriceOverEstimationBP: 5000, + fallbackNativePerUnitLink: 5000000000000000, + fallbackUsdPerUnitLink: 1400000000, + fallbackUsdPerUnitLinkDecimals: 8, + minimumEstimateGasPriceWei: 1000000000, // 1 gwei + transmitTxSizeBytes: 1764 + }); + } + + function getTermsOfServiceConfig() public view returns (TermsOfServiceAllowListConfig memory) { + return TermsOfServiceAllowListConfig({enabled: true, signerPublicKey: TOS_SIGNER}); + } +} + +/// @notice Set up to set the OCR configuration of the Coordinator contract +contract FunctionsDONSetup is FunctionsRouterSetup { + uint256 internal NOP_SIGNER_PRIVATE_KEY_1 = 0x400; + address internal NOP_SIGNER_ADDRESS_1 = vm.addr(NOP_SIGNER_PRIVATE_KEY_1); + uint256 internal NOP_SIGNER_PRIVATE_KEY_2 = 0x401; + address internal NOP_SIGNER_ADDRESS_2 = vm.addr(NOP_SIGNER_PRIVATE_KEY_2); + uint256 internal NOP_SIGNER_PRIVATE_KEY_3 = 0x402; + address internal NOP_SIGNER_ADDRESS_3 = vm.addr(NOP_SIGNER_PRIVATE_KEY_3); + uint256 internal NOP_SIGNER_PRIVATE_KEY_4 = 0x403; + address internal NOP_SIGNER_ADDRESS_4 = vm.addr(NOP_SIGNER_PRIVATE_KEY_4); + + uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_1 = 0x404; + address internal NOP_TRANSMITTER_ADDRESS_1 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_1); + uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_2 = 0x405; + address internal NOP_TRANSMITTER_ADDRESS_2 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_2); + uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_3 = 0x406; + address internal NOP_TRANSMITTER_ADDRESS_3 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_3); + uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_4 = 0x407; + address internal NOP_TRANSMITTER_ADDRESS_4 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_4); + + address[] internal s_signers; + address[] internal s_transmitters; + uint8 s_f = 1; + bytes internal s_onchainConfig = new bytes(0); + uint64 internal s_offchainConfigVersion = 1; + bytes internal s_offchainConfig = new bytes(0); + + bytes s_thresholdKey = + vm.parseBytes( + "0x7b2247726f7570223a2250323536222c22475f626172223a22424f2f344358424575792f64547a436a612b614e774d666c2b645a77346d325036533246536b4966472f6633527547327337392b494e79642b4639326a346f586e67433657427561556a752b4a637a32377834484251343d222c2248223a224250532f72485065377941467232416c447a79395549466258776d46384666756632596d514177666e3342373844336f474845643247474536466e616f34552b4c6a4d4d5756792b464f7075686e77554f6a75427a64773d222c22484172726179223a5b22424d75546862414473337768316e67764e56792f6e3841316d42674b5a4b4c475259385937796a39695769337242502f316a32347571695869534531437554384c6f51446a386248466d384345477667517158494e62383d222c224248687974716d6e34314373322f4658416f43737548687151486236382f597930524b2b41354c6647654f645a78466f4e386c442b45656e4b587a544943784f6d3231636d535447364864484a6e336342645663714c673d222c22424d794e7a4534616e596258474d72694f52664c52634e7239766c347878654279316432452f4464335a744630546372386267567435582b2b42355967552b4b7875726e512f4d656b6857335845782b79506e4e4f584d3d222c22424d6a753272375a657a4a45545539413938746a6b6d547966796a79493735345742555835505174724a6578346d6766366130787373426d50325a7472412b55576d504e592b6d4664526b46674f7944694c53614e59453d225d7d" + ); + bytes s_donKey = + vm.parseBytes( + "0xf2f9c47363202d89aa9fa70baf783d70006fe493471ac8cfa82f1426fd09f16a5f6b32b7c4b5d5165cd147a6e513ba4c0efd39d969d6b20a8a21126f0411b9c6" + ); + + function setUp() public virtual override { + FunctionsRouterSetup.setUp(); + + s_signers = new address[](4); + s_signers[0] = NOP_SIGNER_ADDRESS_1; + s_signers[1] = NOP_SIGNER_ADDRESS_2; + s_signers[2] = NOP_SIGNER_ADDRESS_3; + s_signers[3] = NOP_SIGNER_ADDRESS_4; + + s_transmitters = new address[](4); + s_transmitters[0] = NOP_TRANSMITTER_ADDRESS_1; + s_transmitters[1] = NOP_TRANSMITTER_ADDRESS_2; + s_transmitters[2] = NOP_TRANSMITTER_ADDRESS_3; + s_transmitters[3] = NOP_TRANSMITTER_ADDRESS_4; + + // set OCR config + s_functionsCoordinator.setConfig( + s_signers, + s_transmitters, + s_f, + s_onchainConfig, + s_offchainConfigVersion, + s_offchainConfig + ); + } + + function _getTransmitterBalances() internal view returns (uint256[4] memory balances) { + return [ + s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1), + s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_2), + s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_3), + s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_4) + ]; + } + + function _assertTransmittersAllHaveBalance(uint256[4] memory balances, uint256 expectedBalance) internal { + assertEq(balances[0], expectedBalance); + assertEq(balances[1], expectedBalance); + assertEq(balances[2], expectedBalance); + assertEq(balances[3], expectedBalance); + } +} + +/// @notice Set up to add the Coordinator and ToS Allow Contract as routes on the Router contract +contract FunctionsRoutesSetup is FunctionsDONSetup { + bytes32 s_donId = bytes32("1"); + + function setUp() public virtual override { + FunctionsDONSetup.setUp(); + + bytes32 allowListId = s_functionsRouter.getAllowListId(); + bytes32[] memory proposedContractSetIds = new bytes32[](2); + proposedContractSetIds[0] = s_donId; + proposedContractSetIds[1] = allowListId; + address[] memory proposedContractSetAddresses = new address[](2); + proposedContractSetAddresses[0] = address(s_functionsCoordinator); + proposedContractSetAddresses[1] = address(s_termsOfServiceAllowList); + + s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); + s_functionsRouter.updateContracts(); + } +} + +/// @notice Set up for the OWNER_ADDRESS to accept the Terms of Service +contract FunctionsOwnerAcceptTermsOfServiceSetup is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + + bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, OWNER_ADDRESS); + bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); + s_termsOfServiceAllowList.acceptTermsOfService(OWNER_ADDRESS, OWNER_ADDRESS, r, s, v); + } +} + +/// @notice Set up to deploy a consumer contract +contract FunctionsClientSetup is FunctionsOwnerAcceptTermsOfServiceSetup { + FunctionsClientHarness internal s_functionsClient; + + function setUp() public virtual override { + FunctionsOwnerAcceptTermsOfServiceSetup.setUp(); + + s_functionsClient = new FunctionsClientHarness(address(s_functionsRouter)); + } +} + +/// @notice Set up to create a subscription, add the consumer contract as a consumer of the subscription, and fund the subscription with 's_subscriptionInitialFunding' +contract FunctionsSubscriptionSetup is FunctionsClientSetup { + uint64 s_subscriptionId; + uint96 s_subscriptionInitialFunding = 10 * JUELS_PER_LINK; // 10 LINK + + function setUp() public virtual override { + FunctionsClientSetup.setUp(); + + // Create subscription + s_subscriptionId = s_functionsRouter.createSubscription(); + s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); + + // Fund subscription + s_linkToken.transferAndCall(address(s_functionsRouter), s_subscriptionInitialFunding, abi.encode(s_subscriptionId)); + } +} + +/// @notice Set up to initate a minimal request and store it in s_requests[1] +contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup { + struct Report { + bytes32[] rs; + bytes32[] ss; + bytes32 vs; + bytes report; + bytes32[3] reportContext; + } + + struct RequestData { + string sourceCode; + bytes secrets; + string[] args; + bytes[] bytesArgs; + uint32 callbackGasLimit; + } + struct Request { + RequestData requestData; + bytes32 requestId; + FunctionsResponse.Commitment commitment; // Offchain commitment that contains operation fee in the place of admin fee + FunctionsResponse.Commitment commitmentOnchain; // Commitment that is persisted as a hash in the Router + } + + mapping(uint256 requestNumber => Request) s_requests; + + struct Response { + uint96 totalCostJuels; + } + + mapping(uint256 requestNumber => Response) s_responses; + + uint96 s_fulfillmentRouterOwnerBalance = 0; + uint96 s_fulfillmentCoordinatorBalance = 0; + uint8 s_requestsSent = 0; + uint8 s_requestsFulfilled = 0; + + function setUp() public virtual override { + FunctionsSubscriptionSetup.setUp(); + + // Send request #1 + string memory sourceCode = "return 'hello world';"; + bytes memory secrets = new bytes(0); + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + uint32 callbackGasLimit = 5500; + _sendAndStoreRequest(1, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + } + + /// @notice Predicts the estimated cost (maximum cost) of a request + /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee + function _getExpectedCostEstimate(uint256 callbackGas) internal view returns (uint96) { + uint256 gasPrice = TX_GASPRICE_START < getCoordinatorConfig().minimumEstimateGasPriceWei + ? getCoordinatorConfig().minimumEstimateGasPriceWei + : TX_GASPRICE_START; + uint256 gasPriceWithOverestimation = gasPrice + + ((gasPrice * getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP) / 10_000); + uint96 juelsPerGas = uint96((1e18 * gasPriceWithOverestimation) / uint256(LINK_ETH_RATE)); + uint96 gasOverheadJuels = juelsPerGas * + ((getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback)); + uint96 callbackGasCostJuels = uint96(juelsPerGas * callbackGas); + bytes memory emptyData = new bytes(0); + return + gasOverheadJuels + + s_functionsCoordinator.getDONFeeJuels(emptyData) + + s_adminFee + + s_functionsCoordinator.getOperationFeeJuels() + + callbackGasCostJuels; + } + + /// @notice Predicts the actual cost of a request + /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee + function _getExpectedCost(uint256 gasUsed) internal view returns (uint96) { + uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE)); + uint96 gasOverheadJuels = juelsPerGas * + (getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback); + uint96 callbackGasCostJuels = uint96(juelsPerGas * gasUsed); + bytes memory emptyData = new bytes(0); + return + gasOverheadJuels + + s_functionsCoordinator.getDONFeeJuels(emptyData) + + s_adminFee + + s_functionsCoordinator.getOperationFeeJuels() + + callbackGasCostJuels; + } + + /// @notice Send a request and store information about it in s_requests + /// @param requestNumberKey - the key that the request will be stored in `s_requests` in + /// @param sourceCode - Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted + /// @param secrets - Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) + /// @param args - String arguments that will be passed into the source code + /// @param bytesArgs - Bytes arguments that will be passed into the source code + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @param client - The consumer contract to send the request from + function _sendAndStoreRequest( + uint256 requestNumberKey, + string memory sourceCode, + bytes memory secrets, + string[] memory args, + bytes[] memory bytesArgs, + uint32 callbackGasLimit, + address client + ) internal { + if (s_requests[requestNumberKey].requestId != bytes32(0)) { + revert("Request already written"); + } + + vm.recordLogs(); + + bytes32 requestId = FunctionsClientHarness(client).sendRequest( + s_donId, + sourceCode, + secrets, + args, + bytesArgs, + s_subscriptionId, + callbackGasLimit + ); + + // Get commitment data from OracleRequest event log + Vm.Log[] memory entries = vm.getRecordedLogs(); + (, , , , , , , FunctionsResponse.Commitment memory commitment) = abi.decode( + entries[0].data, + (address, uint64, address, bytes, uint16, bytes32, uint64, FunctionsResponse.Commitment) + ); + s_requests[requestNumberKey] = Request({ + requestData: RequestData({ + sourceCode: sourceCode, + secrets: secrets, + args: args, + bytesArgs: bytesArgs, + callbackGasLimit: callbackGasLimit + }), + requestId: requestId, + commitment: commitment, // Has operationFee in place of adminFee + commitmentOnchain: FunctionsResponse.Commitment({ + coordinator: commitment.coordinator, + client: commitment.client, + subscriptionId: commitment.subscriptionId, + callbackGasLimit: commitment.callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, + adminFee: s_adminFee + }) + }); + s_requestsSent += 1; + } + + /// @notice Send a request and store information about it in s_requests + /// @param requestNumberKey - the key that the request will be stored in `s_requests` in + /// @param sourceCode - Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted + /// @param secrets - Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) + /// @param args - String arguments that will be passed into the source code + /// @param bytesArgs - Bytes arguments that will be passed into the source code + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @dev @param client - The consumer contract to send the request from (overloaded to fill client with s_functionsClient) + function _sendAndStoreRequest( + uint256 requestNumberKey, + string memory sourceCode, + bytes memory secrets, + string[] memory args, + bytes[] memory bytesArgs, + uint32 callbackGasLimit + ) internal { + _sendAndStoreRequest( + requestNumberKey, + sourceCode, + secrets, + args, + bytesArgs, + callbackGasLimit, + address(s_functionsClient) + ); + } + + function _buildReport( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors + ) internal view returns (bytes memory report, bytes32[3] memory reportContext) { + // Build report + bytes32[] memory _requestIds = new bytes32[](requestNumberKeys.length); + bytes[] memory _results = new bytes[](requestNumberKeys.length); + bytes[] memory _errors = new bytes[](requestNumberKeys.length); + bytes[] memory _onchainMetadata = new bytes[](requestNumberKeys.length); + bytes[] memory _offchainMetadata = new bytes[](requestNumberKeys.length); + for (uint256 i = 0; i < requestNumberKeys.length; ++i) { + if (keccak256(bytes(results[i])) != keccak256(new bytes(0)) && keccak256(errors[i]) != keccak256(new bytes(0))) { + revert("Report can only contain a result OR an error, one must remain empty."); + } + _requestIds[i] = s_requests[requestNumberKeys[i]].requestId; + _results[i] = bytes(results[i]); + _errors[i] = errors[i]; + _onchainMetadata[i] = abi.encode(s_requests[requestNumberKeys[i]].commitment); + _offchainMetadata[i] = new bytes(0); // No off-chain metadata + } + report = abi.encode(_requestIds, _results, _errors, _onchainMetadata, _offchainMetadata); + + // Build report context + uint256 h = uint256( + keccak256( + abi.encode( + block.chainid, + address(s_functionsCoordinator), + 1, + s_signers, + s_transmitters, + s_f, + s_onchainConfig, + s_offchainConfigVersion, + s_offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + bytes32 configDigest = bytes32((prefix & prefixMask) | (h & ~prefixMask)); + reportContext = [configDigest, configDigest, configDigest]; + + return (report, reportContext); + } + + /// @notice Gather signatures on report data + /// @param report - Report bytes generated from `_buildReport` + /// @param reportContext - Report context bytes32 generated from `_buildReport` + /// @param signerPrivateKeys - One or more addresses that will sign the report data + /// @return rawRs - Signature rs + /// @return rawSs - Signature ss + /// @return rawVs - Signature vs + function _signReport( + bytes memory report, + bytes32[3] memory reportContext, + uint256[] memory signerPrivateKeys + ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { + bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); + bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); + bytes memory vs = new bytes(signerPrivateKeys.length); + + bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signerPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + + return (rs, ss, bytes32(vs)); + } + + function _buildAndSignReport( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors + ) internal view returns (Report memory) { + (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); + + // Sign the report + // Need at least 3 signers to fulfill minimum number of: (configInfo.n + configInfo.f) / 2 + 1 + uint256[] memory signerPrivateKeys = new uint256[](3); + signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; + signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; + signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; + (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( + report, + reportContext, + signerPrivateKeys + ); + + return Report({report: report, reportContext: reportContext, rs: rawRs, ss: rawSs, vs: rawVs}); + } + + /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin + /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report + /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param transmitter - The address that will send the `.report` transaction + /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. + /// @param requestProcessedStartIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) + /// @param transmitterGasToUse - Override the default amount of gas that the transmitter sends the `.report` transaction with + function _reportAndStore( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors, + address transmitter, + bool expectedToSucceed, + uint8 requestProcessedStartIndex, + uint256 transmitterGasToUse + ) internal { + { + if (requestNumberKeys.length != results.length || requestNumberKeys.length != errors.length) { + revert("_reportAndStore arguments length mismatch"); + } + } + + Report memory r = _buildAndSignReport(requestNumberKeys, results, errors); + + // Send as transmitter + vm.stopPrank(); + vm.startPrank(transmitter, transmitter); + + // Send report + vm.recordLogs(); + if (transmitterGasToUse > 0) { + s_functionsCoordinator.transmit{gas: transmitterGasToUse}(r.reportContext, r.report, r.rs, r.ss, r.vs); + } else { + s_functionsCoordinator.transmit(r.reportContext, r.report, r.rs, r.ss, r.vs); + } + + if (expectedToSucceed) { + // Get actual cost from RequestProcessed event log + (uint96 totalCostJuels, , , , , ) = abi.decode( + vm.getRecordedLogs()[requestProcessedStartIndex].data, + (uint96, address, FunctionsResponse.FulfillResult, bytes, bytes, bytes) + ); + // Store response of first request + // TODO: handle multiple requests + s_responses[requestNumberKeys[0]] = Response({totalCostJuels: totalCostJuels}); + // Store profit amounts + s_fulfillmentRouterOwnerBalance += s_adminFee * uint96(requestNumberKeys.length); + // totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels + // TODO: handle multiple requests + s_fulfillmentCoordinatorBalance += totalCostJuels - s_adminFee; + } + s_requestsFulfilled += 1; + + // Return prank to Owner + vm.stopPrank(); + vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS); + } + + /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin + /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report + /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param transmitter - The address that will send the `.report` transaction + /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. + /// @param requestProcessedIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) + /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas + function _reportAndStore( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors, + address transmitter, + bool expectedToSucceed, + uint8 requestProcessedIndex + ) internal { + _reportAndStore(requestNumberKeys, results, errors, transmitter, expectedToSucceed, requestProcessedIndex, 0); + } + + /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin + /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report + /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param transmitter - The address that will send the `.report` transaction + /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. + /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) + /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas + function _reportAndStore( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors, + address transmitter, + bool expectedToSucceed + ) internal { + _reportAndStore(requestNumberKeys, results, errors, transmitter, expectedToSucceed, 3); + } + + /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin + /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report + /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param transmitter - The address that will send the `.report` transaction + /// @dev @param expectedToSucceed is overloaded to give the value as true - The report transmission is expected to produce a RequestProcessed event for every fulfillment + /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) + /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas + function _reportAndStore( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors, + address transmitter + ) internal { + _reportAndStore(requestNumberKeys, results, errors, transmitter, true); + } + + /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin + /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report + /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. + /// @dev @param transmitter is overloaded to give the value of transmitter #1 - The address that will send the `.report` transaction + /// @dev @param expectedToSucceed is overloaded to give the value as true - The report transmission is expected to produce a RequestProcessed event for every fulfillment + /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) + /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas + function _reportAndStore( + uint256[] memory requestNumberKeys, + string[] memory results, + bytes[] memory errors + ) internal { + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1); + } +} + +/// @notice Set up to have transmitter #1 send a report that fulfills request #1 +contract FunctionsFulfillmentSetup is FunctionsClientRequestSetup { + function setUp() public virtual override { + FunctionsClientRequestSetup.setUp(); + + // Fast forward time by 30 seconds to simulate the DON executing the computation + vm.warp(block.timestamp + 30); + + // Fulfill request 1 + uint256[] memory requestNumberKeys = new uint256[](1); + requestNumberKeys[0] = 1; + string[] memory results = new string[](1); + results[0] = "hello world!"; + bytes[] memory errors = new bytes[](1); + errors[0] = new bytes(0); + + _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true); + } +} + +/// @notice Set up to send and fulfill two more requests, s_request[2] reported by transmitter #2 and s_request[3] reported by transmitter #3 +contract FunctionsMultipleFulfillmentsSetup is FunctionsFulfillmentSetup { + function setUp() public virtual override { + FunctionsFulfillmentSetup.setUp(); + + // Make 3 additional requests (1 already complete) + + // *** Request #2 *** + // Send + string memory sourceCode = "return 'hello world';"; + bytes memory secrets = new bytes(0); + string[] memory args = new string[](0); + bytes[] memory bytesArgs = new bytes[](0); + uint32 callbackGasLimit = 5500; + _sendAndStoreRequest(2, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + // Fulfill as transmitter #2 + uint256[] memory requestNumberKeys1 = new uint256[](1); + requestNumberKeys1[0] = 2; + string[] memory results1 = new string[](1); + results1[0] = "hello world!"; + bytes[] memory errors1 = new bytes[](1); + errors1[0] = new bytes(0); + _reportAndStore(requestNumberKeys1, results1, errors1, NOP_TRANSMITTER_ADDRESS_2, true); + + // *** Request #3 *** + // Send + _sendAndStoreRequest(3, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + // Fulfill as transmitter #3 + uint256[] memory requestNumberKeys2 = new uint256[](1); + requestNumberKeys2[0] = 3; + string[] memory results2 = new string[](1); + results2[0] = "hello world!"; + bytes[] memory errors2 = new bytes[](1); + errors2[0] = new bytes(0); + _reportAndStore(requestNumberKeys2, results2, errors2, NOP_TRANSMITTER_ADDRESS_3, true); + + // *** Request #4 *** + // Send + _sendAndStoreRequest(4, sourceCode, secrets, args, bytesArgs, callbackGasLimit); + // Fulfill as transmitter #1 + uint256[] memory requestNumberKeys3 = new uint256[](1); + requestNumberKeys3[0] = 4; + string[] memory results3 = new string[](1); + results3[0] = "hello world!"; + bytes[] memory errors3 = new bytes[](1); + errors3[0] = new bytes(0); + _reportAndStore(requestNumberKeys3, results3, errors3, NOP_TRANSMITTER_ADDRESS_1, true); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol new file mode 100644 index 0000000..f0cb396 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsClientUpgradeHelper} from "./FunctionsClientUpgradeHelper.sol"; +import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol"; + +/// @title Functions Client Test Harness +/// @notice Contract to expose internal functions for testing purposes +contract FunctionsClientHarness is FunctionsClientUpgradeHelper { + constructor(address router) FunctionsClientUpgradeHelper(router) {} + + function getRouter_HARNESS() external view returns (address) { + return address(i_functionsRouter); + } + + function sendRequest_HARNESS( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) external returns (bytes32) { + return super._sendRequest(data, subscriptionId, callbackGasLimit, donId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol new file mode 100644 index 0000000..c300f4d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITermsOfServiceAllowList} from "../../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; +import {IFunctionsSubscriptions} from "../../../dev/v1_X/interfaces/IFunctionsSubscriptions.sol"; + +import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; + +contract FunctionsClientTestHelper is FunctionsClient { + using FunctionsRequest for FunctionsRequest.Request; + + event SendRequestInvoked(bytes32 requestId, string sourceCode, uint64 subscriptionId); + event FulfillRequestInvoked(bytes32 requestId, bytes response, bytes err); + + bool private s_revertFulfillRequest; + string private s_revertFulfillRequestMessage = "asked to revert"; + bool private s_doInvalidOperation; + bool private s_doInvalidReentrantOperation; + bool private s_doValidReentrantOperation; + + uint64 private s_subscriptionId; + bytes32 private s_donId; + + constructor(address router) FunctionsClient(router) {} + + function sendRequest( + bytes32 donId, + string calldata source, + bytes calldata secrets, + string[] calldata args, + bytes[] memory bytesArgs, + uint64 subscriptionId, + uint32 callbackGasLimit + ) public returns (bytes32 requestId) { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + if (secrets.length > 0) req._addSecretsReference(secrets); + if (args.length > 0) req._setArgs(args); + if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); + + return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); + } + + function sendSimpleRequestWithJavaScript( + string memory sourceCode, + uint64 subscriptionId, + bytes32 donId, + uint32 callbackGasLimit + ) public returns (bytes32 requestId) { + FunctionsRequest.Request memory request; + request._initializeRequestForInlineJavaScript(sourceCode); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + requestId = _sendRequest(requestData, subscriptionId, callbackGasLimit, donId); + emit SendRequestInvoked(requestId, sourceCode, subscriptionId); + } + + function sendRequestProposed( + string memory sourceCode, + uint64 subscriptionId, + bytes32 donId + ) public returns (bytes32 requestId) { + FunctionsRequest.Request memory request; + uint32 callbackGasLimit = 20_000; + request._initializeRequestForInlineJavaScript(sourceCode); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + requestId = i_functionsRouter.sendRequestToProposed( + subscriptionId, + requestData, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + donId + ); + emit RequestSent(requestId); + emit SendRequestInvoked(requestId, sourceCode, subscriptionId); + } + + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external { + bytes32 allowListId = i_functionsRouter.getAllowListId(); + ITermsOfServiceAllowList allowList = ITermsOfServiceAllowList(i_functionsRouter.getContractById(allowListId)); + allowList.acceptTermsOfService(acceptor, recipient, r, s, v); + } + + function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external { + IFunctionsSubscriptions(address(i_functionsRouter)).acceptSubscriptionOwnerTransfer(subscriptionId); + } + + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + if (s_revertFulfillRequest) { + revert(s_revertFulfillRequestMessage); + } + if (s_doInvalidOperation) { + uint256 x = 1; + uint256 y = 0; + x = x / y; + } + if (s_doValidReentrantOperation) { + sendSimpleRequestWithJavaScript("somedata", s_subscriptionId, s_donId, 20_000); + } + if (s_doInvalidReentrantOperation) { + IFunctionsSubscriptions(address(i_functionsRouter)).cancelSubscription(s_subscriptionId, msg.sender); + } + emit FulfillRequestInvoked(requestId, response, err); + } + + function setRevertFulfillRequest(bool on) external { + s_revertFulfillRequest = on; + } + + function setRevertFulfillRequestMessage(string memory message) external { + s_revertFulfillRequestMessage = message; + } + + function setDoInvalidOperation(bool on) external { + s_doInvalidOperation = on; + } + + function setDoInvalidReentrantOperation(bool on, uint64 subscriptionId) external { + s_doInvalidReentrantOperation = on; + s_subscriptionId = subscriptionId; + } + + function setDoValidReentrantOperation(bool on, uint64 subscriptionId, bytes32 donId) external { + s_doValidReentrantOperation = on; + s_subscriptionId = subscriptionId; + s_donId = donId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol new file mode 100644 index 0000000..e0f636e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; +import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; + +contract FunctionsClientUpgradeHelper is FunctionsClient, ConfirmedOwner { + using FunctionsRequest for FunctionsRequest.Request; + + constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} + + event ResponseReceived(bytes32 indexed requestId, bytes result, bytes err); + + /** + * @notice Send a simple request + * + * @param donId DON ID + * @param source JavaScript source code + * @param secrets Encrypted secrets payload + * @param args List of arguments accessible from within the source code + * @param subscriptionId Funtions billing subscription ID + * @param callbackGasLimit Maximum amount of gas used to call the client contract's `handleOracleFulfillment` function + * @return Functions request ID + */ + function sendRequest( + bytes32 donId, + string calldata source, + bytes calldata secrets, + string[] calldata args, + bytes[] memory bytesArgs, + uint64 subscriptionId, + uint32 callbackGasLimit + ) public onlyOwner returns (bytes32) { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + if (secrets.length > 0) req._addSecretsReference(secrets); + if (args.length > 0) req._setArgs(args); + if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); + + return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); + } + + function sendRequestBytes( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) public returns (bytes32 requestId) { + return _sendRequest(data, subscriptionId, callbackGasLimit, donId); + } + + /** + * @notice Same as sendRequest but for DONHosted secrets + */ + function sendRequestWithDONHostedSecrets( + bytes32 donId, + string calldata source, + uint8 slotId, + uint64 slotVersion, + string[] calldata args, + uint64 subscriptionId, + uint32 callbackGasLimit + ) public onlyOwner returns (bytes32) { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + req._addDONHostedSecrets(slotId, slotVersion); + + if (args.length > 0) req._setArgs(args); + + return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); + } + + // @notice Sends a Chainlink Functions request + // @param data The CBOR encoded bytes data for a Functions request + // @param subscriptionId The subscription ID that will be charged to service the request + // @param callbackGasLimit the amount of gas that will be available for the fulfillment callback + // @return requestId The generated request ID for this request + function _sendRequestToProposed( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) internal returns (bytes32) { + bytes32 requestId = i_functionsRouter.sendRequestToProposed( + subscriptionId, + data, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + donId + ); + emit RequestSent(requestId); + return requestId; + } + + /** + * @notice Send a simple request to the proposed contract + * + * @param donId DON ID + * @param source JavaScript source code + * @param secrets Encrypted secrets payload + * @param args List of arguments accessible from within the source code + * @param subscriptionId Funtions billing subscription ID + * @param callbackGasLimit Maximum amount of gas used to call the client contract's `handleOracleFulfillment` function + * @return Functions request ID + */ + function sendRequestToProposed( + bytes32 donId, + string calldata source, + bytes calldata secrets, + string[] calldata args, + bytes[] memory bytesArgs, + uint64 subscriptionId, + uint32 callbackGasLimit + ) public onlyOwner returns (bytes32) { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + if (secrets.length > 0) req._addSecretsReference(secrets); + if (args.length > 0) req._setArgs(args); + if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); + + return _sendRequestToProposed(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); + } + + /** + * @notice Same as sendRequestToProposed but for DONHosted secrets + */ + function sendRequestToProposedWithDONHostedSecrets( + bytes32 donId, + string calldata source, + uint8 slotId, + uint64 slotVersion, + string[] calldata args, + uint64 subscriptionId, + uint32 callbackGasLimit + ) public onlyOwner returns (bytes32) { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + req._addDONHostedSecrets(slotId, slotVersion); + + if (args.length > 0) req._setArgs(args); + + return _sendRequestToProposed(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); + } + + /** + * @notice Callback that is invoked once the DON has resolved the request or hit an error + * + * @param requestId The request ID, returned by sendRequest() + * @param response Aggregated response from the user code + * @param err Aggregated error from the user code or from the execution pipeline + * Either response or error parameter will be set, but never both + */ + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + emit ResponseReceived(requestId, response, err); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol new file mode 100644 index 0000000..e567471 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; +import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; + +contract FunctionsClientWithEmptyCallback is FunctionsClient { + using FunctionsRequest for FunctionsRequest.Request; + + event SendRequestInvoked(bytes32 requestId, string sourceCode, uint64 subscriptionId); + event FulfillRequestInvoked(bytes32 requestId, bytes response, bytes err); + + constructor(address router) FunctionsClient(router) {} + + function sendSimpleRequestWithJavaScript( + string memory sourceCode, + uint64 subscriptionId, + bytes32 donId, + uint32 callbackGasLimit + ) public returns (bytes32 requestId) { + FunctionsRequest.Request memory request; + request._initializeRequestForInlineJavaScript(sourceCode); + bytes memory requestData = FunctionsRequest._encodeCBOR(request); + requestId = _sendRequest(requestData, subscriptionId, callbackGasLimit, donId); + emit SendRequestInvoked(requestId, sourceCode, subscriptionId); + } + + function _fulfillRequest(bytes32 /*requestId*/, bytes memory /*response*/, bytes memory /*err*/) internal override { + // Do nothing + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol new file mode 100644 index 0000000..0de449f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol"; +import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol"; +import {FunctionsBillingConfig} from "../../../dev/v1_X/interfaces/IFunctionsBilling.sol"; + +/// @title Functions Coordinator Test Harness +/// @notice Contract to expose internal functions for testing purposes +contract FunctionsCoordinatorHarness is FunctionsCoordinator { + address s_linkToNativeFeed_HARNESS; + address s_linkToUsdFeed_HARNESS; + address s_router_HARNESS; + + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) FunctionsCoordinator(router, config, linkToNativeFeed, linkToUsdFeed) { + s_linkToNativeFeed_HARNESS = linkToNativeFeed; + s_linkToUsdFeed_HARNESS = linkToUsdFeed; + s_router_HARNESS = router; + } + + function isTransmitter_HARNESS(address node) external view returns (bool) { + return super._isTransmitter(node); + } + + function beforeSetConfig_HARNESS(uint8 _f, bytes memory _onchainConfig) external { + return super._beforeSetConfig(_f, _onchainConfig); + } + + /// @dev Used by FunctionsBilling.sol + function getTransmitters_HARNESS() external view returns (address[] memory) { + return super._getTransmitters(); + } + + function report_HARNESS(DecodedReport memory decodedReport) external { + return super._report(decodedReport); + } + + function onlyOwner_HARNESS() external view { + return super._onlyOwner(); + } + + // ================================================================ + // | Functions Billing | + // ================================================================ + + function getLinkToNativeFeed_HARNESS() external view returns (address) { + return s_linkToNativeFeed_HARNESS; + } + + function getLinkToUsdFeed_HARNESS() external view returns (address) { + return s_linkToUsdFeed_HARNESS; + } + + function getRouter_HARNESS() external view returns (address) { + return s_router_HARNESS; + } + + function calculateCostEstimate_HARNESS( + uint32 callbackGasLimit, + uint256 gasPriceWei, + uint72 donFee, + uint72 adminFee, + uint72 operationFee + ) external view returns (uint96) { + return super._calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); + } + + function startBilling_HARNESS( + FunctionsResponse.RequestMeta memory request + ) external returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { + return super._startBilling(request); + } + + function fulfillAndBill_HARNESS( + bytes32 requestId, + bytes memory response, + bytes memory err, + bytes memory onchainMetadata, + bytes memory offchainMetadata, + uint8 reportBatchSize + ) external returns (FunctionsResponse.FulfillResult) { + return super._fulfillAndBill(requestId, response, err, onchainMetadata, offchainMetadata, reportBatchSize); + } + + function disperseFeePool_HARNESS() external { + return super._disperseFeePool(); + } + + function owner_HARNESS() external view returns (address owner) { + return super._owner(); + } + + // ================================================================ + // | OCR2 | + // ================================================================ + + function configDigestFromConfigData_HARNESS( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + return + super._configDigestFromConfigData( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol new file mode 100644 index 0000000..8703d2b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol"; +import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol"; +import {FunctionsBillingConfig} from "../../../dev/v1_X/interfaces/IFunctionsBilling.sol"; + +contract FunctionsCoordinatorTestHelper is FunctionsCoordinator { + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) FunctionsCoordinator(router, config, linkToNativeFeed, linkToUsdFeed) {} + + function callReport(bytes calldata report) external { + address[MAX_NUM_ORACLES] memory signers; + signers[0] = msg.sender; + ( + bytes32[] memory requestIds, + bytes[] memory results, + bytes[] memory errors, + bytes[] memory onchainMetadata, + bytes[] memory offchainMetadata + ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); + _report( + DecodedReport({ + requestIds: requestIds, + results: results, + errors: errors, + onchainMetadata: onchainMetadata, + offchainMetadata: offchainMetadata + }) + ); + } + + function callReportMultipleSigners(bytes calldata report, address secondSigner) external { + address[MAX_NUM_ORACLES] memory signers; + signers[0] = msg.sender; + signers[1] = secondSigner; + ( + bytes32[] memory requestIds, + bytes[] memory results, + bytes[] memory errors, + bytes[] memory onchainMetadata, + bytes[] memory offchainMetadata + ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); + _report( + DecodedReport({ + requestIds: requestIds, + results: results, + errors: errors, + onchainMetadata: onchainMetadata, + offchainMetadata: offchainMetadata + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol new file mode 100644 index 0000000..1623fc5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; +import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; +import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; + +/** + * @title Chainlink Functions load test client implementation + */ +contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { + using FunctionsRequest for FunctionsRequest.Request; + + uint32 public constant MAX_CALLBACK_GAS = 250_000; + + bytes32 public lastRequestID; + bytes public lastResponse; + bytes public lastError; + uint32 public totalRequests; + uint32 public totalEmptyResponses; + uint32 public totalSucceededResponses; + uint32 public totalFailedResponses; + + constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} + + /** + * @notice Send a simple request + * @param times Number of times to send the request + * @param source JavaScript source code + * @param encryptedSecretsReferences Encrypted secrets payload + * @param args List of arguments accessible from within the source code + * @param subscriptionId Billing ID + * @param donId DON ID + */ + function sendRequest( + uint32 times, + string calldata source, + bytes calldata encryptedSecretsReferences, + string[] calldata args, + uint64 subscriptionId, + bytes32 donId + ) external onlyOwner { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + if (encryptedSecretsReferences.length > 0) req._addSecretsReference(encryptedSecretsReferences); + if (args.length > 0) req._setArgs(args); + uint i = 0; + for (i = 0; i < times; i++) { + lastRequestID = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, donId); + totalRequests += 1; + } + } + + /** + * @notice Same as sendRequest but for DONHosted secrets + * @param times Number of times to send the request + * @param source JavaScript source code + * @param slotId DON hosted secrets slot ID + * @param slotVersion DON hosted secrets slot version + * @param args List of arguments accessible from within the source code + * @param subscriptionId Billing ID + * @param donId DON ID + */ + function sendRequestWithDONHostedSecrets( + uint32 times, + string calldata source, + uint8 slotId, + uint64 slotVersion, + string[] calldata args, + uint64 subscriptionId, + bytes32 donId + ) public onlyOwner { + FunctionsRequest.Request memory req; + req._initializeRequestForInlineJavaScript(source); + req._addDONHostedSecrets(slotId, slotVersion); + if (args.length > 0) req._setArgs(args); + uint i = 0; + for (i = 0; i < times; i++) { + lastRequestID = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, donId); + totalRequests += 1; + } + } + + /** + * @notice Sends a Chainlink Functions request that has already been CBOR encoded + * @param times Number of times to send the request + * @param cborEncodedRequest The CBOR encoded bytes data for a Functions request + * @param subscriptionId The subscription ID that will be charged to service the request + * @param donId DON ID + */ + function sendEncodedRequest( + uint32 times, + bytes memory cborEncodedRequest, + uint64 subscriptionId, + bytes32 donId + ) public onlyOwner { + uint i = 0; + for (i = 0; i < times; i++) { + lastRequestID = _sendRequest(cborEncodedRequest, subscriptionId, MAX_CALLBACK_GAS, donId); + totalRequests += 1; + } + } + + function resetStats() external onlyOwner { + lastRequestID = ""; + lastResponse = ""; + lastError = ""; + totalRequests = 0; + totalSucceededResponses = 0; + totalFailedResponses = 0; + totalEmptyResponses = 0; + } + + function getStats() + public + view + onlyOwner + returns (bytes32, bytes memory, bytes memory, uint32, uint32, uint32, uint32) + { + return ( + lastRequestID, + lastResponse, + lastError, + totalRequests, + totalSucceededResponses, + totalFailedResponses, + totalEmptyResponses + ); + } + + /** + * @notice Store latest result/error + * @param requestId The request ID, returned by sendRequest() + * @param response Aggregated response from the user code + * @param err Aggregated error from the user code or from the execution pipeline + * Either response or error parameter will be set, but never both + */ + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + lastRequestID = requestId; + lastResponse = response; + lastError = err; + if (response.length == 0) { + totalEmptyResponses += 1; + } + if (err.length != 0) { + totalFailedResponses += 1; + } + if (response.length != 0 && err.length == 0) { + totalSucceededResponses += 1; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol new file mode 100644 index 0000000..7caeff4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRouter} from "../../../dev/v1_X/FunctionsRouter.sol"; + +/// @title Functions Router Test Harness +/// @notice Contract to expose internal functions for testing purposes +contract FunctionsRouterHarness is FunctionsRouter { + constructor(address linkToken, Config memory config) FunctionsRouter(linkToken, config) {} + + function getMaxConsumers_HARNESS() external view returns (uint16) { + return super._getMaxConsumers(); + } + + function getSubscriptionDepositDetails_HARNESS() external view returns (uint16, uint72) { + return super._getSubscriptionDepositDetails(); + } + + function whenNotPaused_HARNESS() external view { + return super._whenNotPaused(); + } + + function onlyRouterOwner_HARNESS() external view { + return super._onlyRouterOwner(); + } + + function onlySenderThatAcceptedToS_HARNESS() external view { + return super._onlySenderThatAcceptedToS(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol new file mode 100644 index 0000000..2e2427f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsSubscriptions} from "../../../dev/v1_X/FunctionsSubscriptions.sol"; + +/// @title Functions Subscriptions Test Harness +/// @notice Contract to expose internal functions for testing purposes +contract FunctionsSubscriptionsHarness is FunctionsSubscriptions { + constructor(address link) FunctionsSubscriptions(link) {} + + function markRequestInFlight_HARNESS(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) external { + return super._markRequestInFlight(client, subscriptionId, estimatedTotalCostJuels); + } + + function pay_HARNESS( + uint64 subscriptionId, + uint96 estimatedTotalCostJuels, + address client, + uint96 adminFee, + uint96 juelsPerGas, + uint96 gasUsed, + uint96 costWithoutCallbackJuels + ) external returns (Receipt memory) { + return + super._pay( + subscriptionId, + estimatedTotalCostJuels, + client, + adminFee, + juelsPerGas, + gasUsed, + costWithoutCallbackJuels + ); + } + + function isExistingSubscription_HARNESS(uint64 subscriptionId) external view { + return super._isExistingSubscription(subscriptionId); + } + + function isAllowedConsumer_HARNESS(address client, uint64 subscriptionId) external view { + return super._isAllowedConsumer(client, subscriptionId); + } + + // Overrides + function _getMaxConsumers() internal view override returns (uint16) {} + + function _getSubscriptionDepositDetails() internal override returns (uint16, uint72) {} + + function _onlySenderThatAcceptedToS() internal override {} + + function _onlyRouterOwner() internal override {} + + function _whenNotPaused() internal override {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol new file mode 100644 index 0000000..50e90c4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; + +contract FunctionsTestHelper { + using FunctionsRequest for FunctionsRequest.Request; + + FunctionsRequest.Request private s_req; + + event RequestData(bytes data); + + function closeEvent() public { + emit RequestData(s_req._encodeCBOR()); + } + + function initializeRequestForInlineJavaScript(string memory sourceCode) public { + FunctionsRequest.Request memory r; + r._initializeRequestForInlineJavaScript(sourceCode); + storeRequest(r); + } + + function addSecretsReference(bytes memory secrets) public { + FunctionsRequest.Request memory r = s_req; + r._addSecretsReference(secrets); + storeRequest(r); + } + + function addEmptyArgs() public pure { + FunctionsRequest.Request memory r; + string[] memory args; + r._setArgs(args); + } + + function addTwoArgs(string memory arg1, string memory arg2) public { + string[] memory args = new string[](2); + args[0] = arg1; + args[1] = arg2; + FunctionsRequest.Request memory r = s_req; + r._setArgs(args); + storeRequest(r); + } + + function storeRequest(FunctionsRequest.Request memory r) private { + s_req.codeLocation = r.codeLocation; + s_req.language = r.language; + s_req.source = r.source; + s_req.args = r.args; + s_req.secretsLocation = r.secretsLocation; + s_req.encryptedSecretsReference = r.encryptedSecretsReference; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol new file mode 100644 index 0000000..8de53dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; + +import {Routable} from "./Routable.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +/// @title Functions Billing contract +/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsBilling is Routable, IFunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei + // ================================================================ + // | Request Commitment state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; + + event CommitmentDeleted(bytes32 requestId); + + // ================================================================ + // | Configuration state | + // ================================================================ + + struct Config { + uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) + uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. + uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. + uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. + uint32 requestTimeoutSeconds; // ║ How many seconds it takes before we consider a request to be timed out + uint72 donFee; // ║ Additional flat fee (in Juels of LINK) that will be split between Node Operators. Max value is 2^80 - 1 == 1.2m LINK. + uint16 maxSupportedRequestDataVersion; // ═══════╝ The highest support request data version supported by the node. All lower versions should also be supported. + uint224 fallbackNativePerUnitLink; // ═══════════╸ fallback NATIVE CURRENCY / LINK conversion rate if the data feed is stale + } + + Config private s_config; + + event ConfigUpdated(Config config); + + error UnsupportedRequestDataVersion(); + error InsufficientBalance(); + error InvalidSubscription(); + error UnauthorizedSender(); + error MustBeSubOwner(address owner); + error InvalidLinkWeiPrice(int256 linkWei); + error PaymentTooLarge(); + error NoTransmittersSet(); + error InvalidCalldata(); + + // ================================================================ + // | Balance state | + // ================================================================ + + mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; + // Pool together collected DON fees + // Disperse them on withdrawal or change in OCR configuration + uint96 internal s_feePool; + + AggregatorV3Interface private s_linkToNativeFeed; + + // ================================================================ + // | Initialization | + // ================================================================ + constructor(address router, Config memory config, address linkToNativeFeed) Routable(router) { + s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); + + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the Chainlink Coordinator's billing configuration + /// @return config + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice Sets the Chainlink Coordinator's billing configuration + /// @param config - See the contents of the Config struct in IFunctionsBilling.Config for more information + function updateConfig(Config memory config) public { + _onlyOwner(); + + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Fee Calculation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function getDONFee(bytes memory /* requestData */) public view override returns (uint72) { + return s_config.donFee; + } + + /// @inheritdoc IFunctionsBilling + function getAdminFee() public view override returns (uint72) { + return _getRouter().getAdminFee(); + } + + /// @inheritdoc IFunctionsBilling + function getWeiPerUnitLink() public view returns (uint256) { + Config memory config = s_config; + (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (config.feedStalenessSeconds < block.timestamp - timestamp && config.feedStalenessSeconds > 0) { + return config.fallbackNativePerUnitLink; + } + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + return uint256(weiPerUnitLink); + } + + function _getJuelsPerGas(uint256 gasPriceWei) private view returns (uint96) { + // (1e18 juels/link) * (wei/gas) / (wei/link) = juels per gas + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((1e18 * gasPriceWei) / getWeiPerUnitLink()); + } + + // ================================================================ + // | Cost Estimation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view override returns (uint96) { + _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + // Reasonable ceilings to prevent integer overflows + if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { + revert InvalidCalldata(); + } + uint72 adminFee = getAdminFee(); + uint72 donFee = getDONFee(data); + return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee); + } + + /// @notice Estimate the cost in Juels of LINK + // that will be charged to a subscription to fulfill a Functions request + // Gas Price can be overestimated to account for flucuations between request and response time + function _calculateCostEstimate( + uint32 callbackGasLimit, + uint256 gasPriceWei, + uint72 donFee, + uint72 adminFee + ) internal view returns (uint96) { + uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit; + + 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 + + uint96 juelsPerGas = _getJuelsPerGas(gasPriceWithOverestimation); + uint256 estimatedGasReimbursement = juelsPerGas * executionGas; + uint96 fees = uint96(donFee) + uint96(adminFee); + + return SafeCast.toUint96(estimatedGasReimbursement + fees); + } + + // ================================================================ + // | Billing | + // ================================================================ + + /// @notice Initiate the billing process for an Functions request + /// @dev Only callable by the Functions Router + /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure + /// @return commitment - The parameters of the request that must be held consistent at response time + function _startBilling( + FunctionsResponse.RequestMeta memory request + ) internal returns (FunctionsResponse.Commitment memory commitment) { + Config memory config = s_config; + + // Nodes should support all past versions of the structure + if (request.dataVersion > config.maxSupportedRequestDataVersion) { + revert UnsupportedRequestDataVersion(); + } + + uint72 donFee = getDONFee(request.data); + uint96 estimatedTotalCostJuels = _calculateCostEstimate( + request.callbackGasLimit, + tx.gasprice, + donFee, + request.adminFee + ); + + // Check that subscription can afford the estimated cost + if ((request.availableBalance) < estimatedTotalCostJuels) { + revert InsufficientBalance(); + } + + bytes32 requestId = _computeRequestId( + address(this), + request.requestingContract, + request.subscriptionId, + request.initiatedRequests + 1 + ); + + commitment = FunctionsResponse.Commitment({ + adminFee: request.adminFee, + coordinator: address(this), + client: request.requestingContract, + subscriptionId: request.subscriptionId, + callbackGasLimit: request.callbackGasLimit, + estimatedTotalCostJuels: estimatedTotalCostJuels, + timeoutTimestamp: uint32(block.timestamp + config.requestTimeoutSeconds), + requestId: requestId, + donFee: donFee, + gasOverheadBeforeCallback: config.gasOverheadBeforeCallback, + gasOverheadAfterCallback: config.gasOverheadAfterCallback + }); + + s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); + + return commitment; + } + + /// @notice Generate a keccak hash request ID + /// @dev uses the number of requests that the consumer of a subscription has sent as a nonce + function _computeRequestId( + address don, + address client, + uint64 subscriptionId, + uint64 nonce + ) private pure returns (bytes32) { + return keccak256(abi.encode(don, client, subscriptionId, nonce)); + } + + /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription + /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @return result fulfillment result + /// @dev Only callable by a node that has been approved on the Coordinator + /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request + function _fulfillAndBill( + bytes32 requestId, + bytes memory response, + bytes memory err, + bytes memory onchainMetadata, + bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */ + ) internal returns (FunctionsResponse.FulfillResult) { + FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); + + if (s_requestCommitments[requestId] == bytes32(0)) { + return FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; + } + + if (s_requestCommitments[requestId] != keccak256(abi.encode(commitment))) { + return FunctionsResponse.FulfillResult.INVALID_COMMITMENT; + } + + uint96 juelsPerGas = _getJuelsPerGas(tx.gasprice); + // Gas overhead without callback + uint96 gasOverheadJuels = juelsPerGas * + (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback); + + // The Functions Router will perform the callback to the client contract + (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( + response, + err, + juelsPerGas, + gasOverheadJuels + commitment.donFee, // costWithoutFulfillment + msg.sender, + commitment + ); + + // The router will only pay the DON on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the Coordinator should hold on to the request commitment + if ( + resultCode == FunctionsResponse.FulfillResult.FULFILLED || + resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + delete s_requestCommitments[requestId]; + // Reimburse the transmitter for the fulfillment gas cost + s_withdrawableTokens[msg.sender] = gasOverheadJuels + callbackCostJuels; + // Put donFee into the pool of fees, to be split later + // Saves on storage writes that would otherwise be charged to the user + s_feePool += commitment.donFee; + } + + return resultCode; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Router + /// @dev Used by FunctionsRouter.sol during timeout of a request + function deleteCommitment(bytes32 requestId) external override onlyRouter { + // Delete commitment + delete s_requestCommitments[requestId]; + emit CommitmentDeleted(requestId); + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function oracleWithdraw(address recipient, uint96 amount) external { + _disperseFeePool(); + + if (amount == 0) { + amount = s_withdrawableTokens[msg.sender]; + } else if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); + } + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Coordinator owner + function oracleWithdrawAll() external { + _onlyOwner(); + _disperseFeePool(); + + address[] memory transmitters = _getTransmitters(); + + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < transmitters.length; ++i) { + uint96 balance = s_withdrawableTokens[transmitters[i]]; + if (balance > 0) { + s_withdrawableTokens[transmitters[i]] = 0; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); + } + } + } + + // Overriden in FunctionsCoordinator, which has visibility into transmitters + function _getTransmitters() internal view virtual returns (address[] memory); + + // DON fees are collected into a pool s_feePool + // When OCR configuration changes, or any oracle withdraws, this must be dispersed + function _disperseFeePool() internal { + if (s_feePool == 0) { + return; + } + // All transmitters are assumed to also be observers + // Pay out the DON fee to all transmitters + address[] memory transmitters = _getTransmitters(); + if (transmitters.length == 0) { + revert NoTransmittersSet(); + } + uint96 feePoolShare = s_feePool / uint96(transmitters.length); + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < transmitters.length; ++i) { + s_withdrawableTokens[transmitters[i]] += feePoolShare; + } + s_feePool -= feePoolShare * uint96(transmitters.length); + } + + // Overriden in FunctionsCoordinator.sol + function _onlyOwner() internal view virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol new file mode 100644 index 0000000..ecbbbd9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; +import {IFunctionsClient} from "./interfaces/IFunctionsClient.sol"; + +import {FunctionsRequest} from "./libraries/FunctionsRequest.sol"; + +/// @title The Chainlink Functions client contract +/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests +abstract contract FunctionsClient is IFunctionsClient { + using FunctionsRequest for FunctionsRequest.Request; + + IFunctionsRouter internal immutable i_router; + + event RequestSent(bytes32 indexed id); + event RequestFulfilled(bytes32 indexed id); + + error OnlyRouterCanFulfill(); + + constructor(address router) { + i_router = IFunctionsRouter(router); + } + + /// @notice Sends a Chainlink Functions request + /// @param data The CBOR encoded bytes data for a Functions request + /// @param subscriptionId The subscription ID that will be charged to service the request + /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback + /// @return requestId The generated request ID for this request + function _sendRequest( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) internal returns (bytes32) { + bytes32 requestId = i_router.sendRequest( + subscriptionId, + data, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + donId + ); + emit RequestSent(requestId); + return requestId; + } + + /// @notice User defined function to handle a response from the DON + /// @param requestId The request ID, returned by sendRequest() + /// @param response Aggregated response from the execution of the user's source code + /// @param err Aggregated error from the execution of the user code or from the execution pipeline + /// @dev Either response or error parameter will be set, but never both + function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; + + /// @inheritdoc IFunctionsClient + function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { + if (msg.sender != address(i_router)) { + revert OnlyRouterCanFulfill(); + } + fulfillRequest(requestId, response, err); + emit RequestFulfilled(requestId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol new file mode 100644 index 0000000..1488bc4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {FunctionsBilling} from "./FunctionsBilling.sol"; +import {OCR2Base} from "./ocr/OCR2Base.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +/// @title Functions Coordinator contract +/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with +contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + /// @inheritdoc ITypeAndVersion + string public constant override typeAndVersion = "Functions Coordinator v1.0.0"; + + event OracleRequest( + bytes32 indexed requestId, + address indexed requestingContract, + address requestInitiator, + uint64 subscriptionId, + address subscriptionOwner, + bytes data, + uint16 dataVersion, + bytes32 flags, + uint64 callbackGasLimit, + FunctionsResponse.Commitment commitment + ); + event OracleResponse(bytes32 indexed requestId, address transmitter); + + error InconsistentReportData(); + error EmptyPublicKey(); + error UnauthorizedPublicKeyChange(); + + bytes private s_donPublicKey; + bytes private s_thresholdPublicKey; + + constructor( + address router, + Config memory config, + address linkToNativeFeed + ) OCR2Base(true) FunctionsBilling(router, config, linkToNativeFeed) {} + + /// @inheritdoc IFunctionsCoordinator + function getThresholdPublicKey() external view override returns (bytes memory) { + if (s_thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { + if (thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_thresholdPublicKey = thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function getDONPublicKey() external view override returns (bytes memory) { + if (s_donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_donPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { + if (donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_donPublicKey = donPublicKey; + } + + /// @dev check if node is in current transmitter list + function _isTransmitter(address node) internal view returns (bool) { + address[] memory nodes = s_transmitters; + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < nodes.length; ++i) { + if (nodes[i] == node) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsCoordinator + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { + commitment = _startBilling(request); + + emit OracleRequest( + commitment.requestId, + request.requestingContract, + tx.origin, + request.subscriptionId, + request.subscriptionOwner, + request.data, + request.dataVersion, + request.flags, + request.callbackGasLimit, + commitment + ); + + return commitment; + } + + /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. + function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { + if (_getTransmitters().length > 0) { + _disperseFeePool(); + } + } + + /// @dev Used by FunctionsBilling.sol + function _getTransmitters() internal view override returns (address[] memory) { + return s_transmitters; + } + + /// @dev Report hook called within OCR2Base.sol + function _report( + uint256 /*initialGas*/, + address /*transmitter*/, + uint8 /*signerCount*/, + address[MAX_NUM_ORACLES] memory /*signers*/, + bytes calldata report + ) internal override { + bytes32[] memory requestIds; + bytes[] memory results; + bytes[] memory errors; + bytes[] memory onchainMetadata; + bytes[] memory offchainMetadata; + (requestIds, results, errors, onchainMetadata, offchainMetadata) = abi.decode( + report, + (bytes32[], bytes[], bytes[], bytes[], bytes[]) + ); + + if ( + requestIds.length == 0 || + requestIds.length != results.length || + requestIds.length != errors.length || + requestIds.length != onchainMetadata.length || + requestIds.length != offchainMetadata.length + ) { + revert ReportInvalid(); + } + + // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig + for (uint256 i = 0; i < requestIds.length; ++i) { + FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( + _fulfillAndBill(requestIds[i], results[i], errors[i], onchainMetadata[i], offchainMetadata[i]) + ); + + // Emit on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the DON will re-try + if ( + result == FunctionsResponse.FulfillResult.FULFILLED || + result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + emit OracleResponse(requestIds[i], msg.sender); + } + } + } + + /// @dev Used in FunctionsBilling.sol + function _onlyOwner() internal view override { + _validateOwnership(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol new file mode 100644 index 0000000..9f35c4d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol @@ -0,0 +1,585 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; +import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; +import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; + +import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol"; +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; +import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; + +contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + string public constant override typeAndVersion = "Functions Router v1.0.0"; + + // We limit return data to a selector plus 4 words. This is to avoid + // malicious contracts from returning large amounts of data and causing + // repeated out-of-gas scenarios. + uint16 public constant MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32; + uint8 private constant MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; + + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + + event RequestProcessed( + bytes32 indexed requestId, + uint64 indexed subscriptionId, + uint96 totalCostJuels, + address transmitter, + FunctionsResponse.FulfillResult resultCode, + bytes response, + bytes err, + bytes callbackReturnData + ); + + event RequestNotProcessed( + bytes32 indexed requestId, + address coordinator, + address transmitter, + FunctionsResponse.FulfillResult resultCode + ); + + error EmptyRequestData(); + error OnlyCallableFromCoordinator(); + error SenderMustAcceptTermsOfService(address sender); + error InvalidGasFlagValue(uint8 value); + error GasLimitTooBig(uint32 limit); + error DuplicateRequestId(bytes32 requestId); + + struct CallbackResult { + bool success; // ══════╸ Whether the callback succeeded or not + uint256 gasUsed; // ═══╸ The amount of gas consumed during the callback + bytes returnData; // ══╸ The return of the callback function + } + + // ================================================================ + // | Route state | + // ================================================================ + + mapping(bytes32 id => address routableContract) private s_route; + + error RouteNotFound(bytes32 id); + + // Identifier for the route to the Terms of Service Allow List + bytes32 private s_allowListId; + + // ================================================================ + // | Configuration state | + // ================================================================ + struct Config { + uint16 maxConsumersPerSubscription; // ═════════╗ Maximum number of consumers which can be added to a single subscription. This bound ensures we are able to loop over all subscription consumers as needed, without exceeding gas limits. Should a user require more consumers, they can use multiple subscriptions. + uint72 adminFee; // ║ Flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network + bytes4 handleOracleFulfillmentSelector; // ║ The function selector that is used when calling back to the Client contract + uint16 gasForCallExactCheck; // ════════════════╝ Used during calling back to the client. Ensures we have at least enough gas to be able to revert if gasAmount > 63//64*gas available. + uint32[] maxCallbackGasLimits; // ══════════════╸ List of max callback gas limits used by flag with GAS_FLAG_INDEX + uint16 subscriptionDepositMinimumRequests; //═══╗ Amount of requests that must be completed before the full subscription balance will be released when closing a subscription account. + uint72 subscriptionDepositJuels; // ════════════╝ Amount of subscription funds that are held as a deposit until Config.subscriptionDepositMinimumRequests are made using the subscription. + } + + Config private s_config; + + event ConfigUpdated(Config); + + // ================================================================ + // | Proposal state | + // ================================================================ + + uint8 private constant MAX_PROPOSAL_SET_LENGTH = 8; + + struct ContractProposalSet { + bytes32[] ids; // ══╸ The IDs that key into the routes that will be modified if the update is applied + address[] to; // ═══╸ The address of the contracts that the route will point to if the updated is applied + } + ContractProposalSet private s_proposedContractSet; + + event ContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ); + + event ContractUpdated(bytes32 id, address from, address to); + + error InvalidProposal(); + error IdentifierIsReserved(bytes32 id); + + // ================================================================ + // | Initialization | + // ================================================================ + + constructor( + address linkToken, + Config memory config + ) FunctionsSubscriptions(linkToken) ConfirmedOwner(msg.sender) Pausable() { + // Set the intial configuration + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice The identifier of the route to retrieve the address of the access control contract + // The access control contract controls which accounts can manage subscriptions + /// @return id - bytes32 id that can be passed to the "getContractById" of the Router + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice The router configuration + function updateConfig(Config memory config) public onlyOwner { + s_config = config; + emit ConfigUpdated(config); + } + + /// @inheritdoc IFunctionsRouter + function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) public view { + uint8 callbackGasLimitsIndexSelector = uint8(getFlags(subscriptionId)[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); + if (callbackGasLimitsIndexSelector >= s_config.maxCallbackGasLimits.length) { + revert InvalidGasFlagValue(callbackGasLimitsIndexSelector); + } + uint32 maxCallbackGasLimit = s_config.maxCallbackGasLimits[callbackGasLimitsIndexSelector]; + if (callbackGasLimit > maxCallbackGasLimit) { + revert GasLimitTooBig(maxCallbackGasLimit); + } + } + + /// @inheritdoc IFunctionsRouter + function getAdminFee() external view override returns (uint72) { + return s_config.adminFee; + } + + /// @inheritdoc IFunctionsRouter + function getAllowListId() external view override returns (bytes32) { + return s_allowListId; + } + + /// @inheritdoc IFunctionsRouter + function setAllowListId(bytes32 allowListId) external override onlyOwner { + s_allowListId = allowListId; + } + + /// @dev Used within FunctionsSubscriptions.sol + function _getMaxConsumers() internal view override returns (uint16) { + return s_config.maxConsumersPerSubscription; + } + + /// @dev Used within FunctionsSubscriptions.sol + function _getSubscriptionDepositDetails() internal view override returns (uint16, uint72) { + return (s_config.subscriptionDepositMinimumRequests, s_config.subscriptionDepositJuels); + } + + // ================================================================ + // | Requests | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function sendRequest( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external override returns (bytes32) { + IFunctionsCoordinator coordinator = IFunctionsCoordinator(getContractById(donId)); + return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); + } + + /// @inheritdoc IFunctionsRouter + function sendRequestToProposed( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external override returns (bytes32) { + IFunctionsCoordinator coordinator = IFunctionsCoordinator(getProposedContractById(donId)); + return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); + } + + function _sendRequest( + bytes32 donId, + IFunctionsCoordinator coordinator, + uint64 subscriptionId, + bytes memory data, + uint16 dataVersion, + uint32 callbackGasLimit + ) private returns (bytes32) { + _whenNotPaused(); + _isExistingSubscription(subscriptionId); + _isAllowedConsumer(msg.sender, subscriptionId); + isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + + if (data.length == 0) { + revert EmptyRequestData(); + } + + Subscription memory subscription = getSubscription(subscriptionId); + Consumer memory consumer = getConsumer(msg.sender, subscriptionId); + uint72 adminFee = s_config.adminFee; + + // Forward request to DON + FunctionsResponse.Commitment memory commitment = coordinator.startRequest( + FunctionsResponse.RequestMeta({ + requestingContract: msg.sender, + data: data, + subscriptionId: subscriptionId, + dataVersion: dataVersion, + flags: getFlags(subscriptionId), + callbackGasLimit: callbackGasLimit, + adminFee: adminFee, + initiatedRequests: consumer.initiatedRequests, + completedRequests: consumer.completedRequests, + availableBalance: subscription.balance - subscription.blockedBalance, + subscriptionOwner: subscription.owner + }) + ); + + // Do not allow setting a comittment for a requestId that already exists + if (s_requestCommitments[commitment.requestId] != bytes32(0)) { + revert DuplicateRequestId(commitment.requestId); + } + + // Store a commitment about the request + s_requestCommitments[commitment.requestId] = keccak256( + abi.encode( + FunctionsResponse.Commitment({ + adminFee: adminFee, + coordinator: address(coordinator), + client: msg.sender, + subscriptionId: subscriptionId, + callbackGasLimit: callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback + }) + ) + ); + + _markRequestInFlight(msg.sender, subscriptionId, commitment.estimatedTotalCostJuels); + + emit RequestStart({ + requestId: commitment.requestId, + donId: donId, + subscriptionId: subscriptionId, + subscriptionOwner: subscription.owner, + requestingContract: msg.sender, + requestInitiator: tx.origin, + data: data, + dataVersion: dataVersion, + callbackGasLimit: callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels + }); + + return commitment.requestId; + } + + // ================================================================ + // | Responses | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function fulfill( + bytes memory response, + bytes memory err, + uint96 juelsPerGas, + uint96 costWithoutCallback, + address transmitter, + FunctionsResponse.Commitment memory commitment + ) external override returns (FunctionsResponse.FulfillResult resultCode, uint96) { + _whenNotPaused(); + + if (msg.sender != commitment.coordinator) { + revert OnlyCallableFromCoordinator(); + } + + { + bytes32 commitmentHash = s_requestCommitments[commitment.requestId]; + + if (commitmentHash == bytes32(0)) { + resultCode = FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + if (keccak256(abi.encode(commitment)) != commitmentHash) { + resultCode = FunctionsResponse.FulfillResult.INVALID_COMMITMENT; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + // Check that the transmitter has supplied enough gas for the callback to succeed + if (gasleft() < commitment.callbackGasLimit + commitment.gasOverheadAfterCallback) { + resultCode = FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + } + + { + uint96 callbackCost = juelsPerGas * SafeCast.toUint96(commitment.callbackGasLimit); + uint96 totalCostJuels = commitment.adminFee + costWithoutCallback + callbackCost; + + // Check that the subscription can still afford to fulfill the request + if (totalCostJuels > getSubscription(commitment.subscriptionId).balance) { + resultCode = FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + + // Check that the cost has not exceeded the quoted cost + if (totalCostJuels > commitment.estimatedTotalCostJuels) { + resultCode = FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT; + emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); + return (resultCode, 0); + } + } + + delete s_requestCommitments[commitment.requestId]; + + CallbackResult memory result = _callback( + commitment.requestId, + response, + err, + commitment.callbackGasLimit, + commitment.client + ); + + resultCode = result.success + ? FunctionsResponse.FulfillResult.FULFILLED + : FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR; + + Receipt memory receipt = _pay( + commitment.subscriptionId, + commitment.estimatedTotalCostJuels, + commitment.client, + commitment.adminFee, + juelsPerGas, + SafeCast.toUint96(result.gasUsed), + costWithoutCallback + ); + + emit RequestProcessed({ + requestId: commitment.requestId, + subscriptionId: commitment.subscriptionId, + totalCostJuels: receipt.totalCostJuels, + transmitter: transmitter, + resultCode: resultCode, + response: response, + err: err, + callbackReturnData: result.returnData + }); + + return (resultCode, receipt.callbackGasCostJuels); + } + + function _callback( + bytes32 requestId, + bytes memory response, + bytes memory err, + uint32 callbackGasLimit, + address client + ) private returns (CallbackResult memory) { + bool destinationNoLongerExists; + assembly { + // solidity calls check that a contract actually exists at the destination, so we do the same + destinationNoLongerExists := iszero(extcodesize(client)) + } + if (destinationNoLongerExists) { + // Return without attempting callback + // The subscription will still be charged to reimburse transmitter's gas overhead + return CallbackResult({success: false, gasUsed: 0, returnData: new bytes(0)}); + } + + bytes memory encodedCallback = abi.encodeWithSelector( + s_config.handleOracleFulfillmentSelector, + requestId, + response, + err + ); + + uint16 gasForCallExactCheck = s_config.gasForCallExactCheck; + + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid payment. + // NOTE: that callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + + bool success; + uint256 gasUsed; + // allocate return data memory ahead of time + bytes memory returnData = new bytes(MAX_CALLBACK_RETURN_BYTES); + + assembly { + let g := gas() + // Compute g -= gasForCallExactCheck and check for underflow + // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. gasForCallExactCheck ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, gasForCallExactCheck) { + revert(0, 0) + } + g := sub(g, gasForCallExactCheck) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), callbackGasLimit)) { + revert(0, 0) + } + // call and report whether we succeeded + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + let gasBeforeCall := gas() + success := call(callbackGasLimit, client, 0, add(encodedCallback, 0x20), mload(encodedCallback), 0, 0) + gasUsed := sub(gasBeforeCall, gas()) + + // limit our copy to MAX_CALLBACK_RETURN_BYTES bytes + let toCopy := returndatasize() + if gt(toCopy, MAX_CALLBACK_RETURN_BYTES) { + toCopy := MAX_CALLBACK_RETURN_BYTES + } + // Store the length of the copied bytes + mstore(returnData, toCopy) + // copy the bytes from returnData[0:_toCopy] + returndatacopy(add(returnData, 0x20), 0, toCopy) + } + + return CallbackResult({success: success, gasUsed: gasUsed, returnData: returnData}); + } + + // ================================================================ + // | Route methods | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function getContractById(bytes32 id) public view override returns (address) { + address currentImplementation = s_route[id]; + if (currentImplementation == address(0)) { + revert RouteNotFound(id); + } + return currentImplementation; + } + + /// @inheritdoc IFunctionsRouter + function getProposedContractById(bytes32 id) public view override returns (address) { + // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint8 i = 0; i < s_proposedContractSet.ids.length; ++i) { + if (id == s_proposedContractSet.ids[i]) { + return s_proposedContractSet.to[i]; + } + } + revert RouteNotFound(id); + } + + // ================================================================ + // | Contract Proposal methods | + // ================================================================ + + /// @inheritdoc IFunctionsRouter + function getProposedContractSet() external view override returns (bytes32[] memory, address[] memory) { + return (s_proposedContractSet.ids, s_proposedContractSet.to); + } + + /// @inheritdoc IFunctionsRouter + function proposeContractsUpdate( + bytes32[] memory proposedContractSetIds, + address[] memory proposedContractSetAddresses + ) external override onlyOwner { + // IDs and addresses arrays must be of equal length and must not exceed the max proposal length + uint256 idsArrayLength = proposedContractSetIds.length; + if (idsArrayLength != proposedContractSetAddresses.length || idsArrayLength > MAX_PROPOSAL_SET_LENGTH) { + revert InvalidProposal(); + } + + // NOTE: iterations of this loop will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint256 i = 0; i < idsArrayLength; ++i) { + bytes32 id = proposedContractSetIds[i]; + address proposedContract = proposedContractSetAddresses[i]; + if ( + proposedContract == address(0) || // The Proposed address must be a valid address + s_route[id] == proposedContract // The Proposed address must point to a different address than what is currently set + ) { + revert InvalidProposal(); + } + + emit ContractProposed({ + proposedContractSetId: id, + proposedContractSetFromAddress: s_route[id], + proposedContractSetToAddress: proposedContract + }); + } + + s_proposedContractSet = ContractProposalSet({ids: proposedContractSetIds, to: proposedContractSetAddresses}); + } + + /// @inheritdoc IFunctionsRouter + function updateContracts() external override onlyOwner { + // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH + for (uint256 i = 0; i < s_proposedContractSet.ids.length; ++i) { + bytes32 id = s_proposedContractSet.ids[i]; + address to = s_proposedContractSet.to[i]; + emit ContractUpdated({id: id, from: s_route[id], to: to}); + s_route[id] = to; + } + + delete s_proposedContractSet; + } + + // ================================================================ + // | Modifiers | + // ================================================================ + // Favoring internal functions over actual modifiers to reduce contract size + + /// @dev Used within FunctionsSubscriptions.sol + function _whenNotPaused() internal view override { + _requireNotPaused(); + } + + /// @dev Used within FunctionsSubscriptions.sol + function _onlyRouterOwner() internal view override { + _validateOwnership(); + } + + /// @dev Used within FunctionsSubscriptions.sol + function _onlySenderThatAcceptedToS() internal view override { + address currentImplementation = s_route[s_allowListId]; + if (currentImplementation == address(0)) { + // If not set, ignore this check, allow all access + return; + } + if (!IAccessController(currentImplementation).hasAccess(msg.sender, new bytes(0))) { + revert SenderMustAcceptTermsOfService(msg.sender); + } + } + + /// @inheritdoc IFunctionsRouter + function pause() external override onlyOwner { + _pause(); + } + + /// @inheritdoc IFunctionsRouter + function unpause() external override onlyOwner { + _unpause(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol new file mode 100644 index 0000000..b93d217 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol @@ -0,0 +1,552 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; + +import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @title Functions Subscriptions contract +/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsSubscriptions is IFunctionsSubscriptions, IERC677Receiver { + using SafeERC20 for IERC20; + using FunctionsResponse for FunctionsResponse.Commitment; + + // ================================================================ + // | Balance state | + // ================================================================ + // link token address + IERC20 internal immutable i_linkToken; + + // s_totalLinkBalance tracks the total LINK sent to/from + // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. + // A discrepancy with this contract's LINK balance indicates that someone + // sent tokens using transfer and so we may need to use recoverFunds. + uint96 private s_totalLinkBalance; + + /// @dev NOP balances are held as a single amount. The breakdown is held by the Coordinator. + mapping(address coordinator => uint96 balanceJuelsLink) private s_withdrawableTokens; + + // ================================================================ + // | Subscription state | + // ================================================================ + // Keep a count of the number of subscriptions so that its possible to + // loop through all the current subscriptions via .getSubscription(). + uint64 private s_currentSubscriptionId; + + mapping(uint64 subscriptionId => Subscription) private s_subscriptions; + + // Maintains the list of keys in s_consumers. + // We do this for 2 reasons: + // 1. To be able to clean up all keys from s_consumers when canceling a subscription. + // 2. To be able to return the list of all consumers in getSubscription. + // Note that we need the s_consumers map to be able to directly check if a + // consumer is valid without reading all the consumers from storage. + mapping(address consumer => mapping(uint64 subscriptionId => Consumer)) private s_consumers; + + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); + + error TooManyConsumers(uint16 maximumConsumers); + error InsufficientBalance(uint96 currentBalanceJuels); + error InvalidConsumer(); + error CannotRemoveWithPendingRequests(); + error InvalidSubscription(); + error OnlyCallableFromLink(); + error InvalidCalldata(); + error MustBeSubscriptionOwner(); + error TimeoutNotExceeded(); + error MustBeProposedOwner(address proposedOwner); + event FundsRecovered(address to, uint256 amount); + + // ================================================================ + // | Request state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) internal s_requestCommitments; + + struct Receipt { + uint96 callbackGasCostJuels; + uint96 totalCostJuels; + } + + event RequestTimedOut(bytes32 indexed requestId); + + // ================================================================ + // | Initialization | + // ================================================================ + constructor(address link) { + i_linkToken = IERC20(link); + } + + // ================================================================ + // | Request/Response | + // ================================================================ + + /// @notice Sets a request as in-flight + /// @dev Only callable within the Router + function _markRequestInFlight(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) internal { + // Earmark subscription funds + s_subscriptions[subscriptionId].blockedBalance += estimatedTotalCostJuels; + + // Increment sent requests + s_consumers[client][subscriptionId].initiatedRequests += 1; + } + + /// @notice Moves funds from one subscription account to another. + /// @dev Only callable by the Coordinator contract that is saved in the request commitment + function _pay( + uint64 subscriptionId, + uint96 estimatedTotalCostJuels, + address client, + uint96 adminFee, + uint96 juelsPerGas, + uint96 gasUsed, + uint96 costWithoutCallbackJuels + ) internal returns (Receipt memory) { + uint96 callbackGasCostJuels = juelsPerGas * gasUsed; + uint96 totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels; + + if ( + s_subscriptions[subscriptionId].balance < totalCostJuels || + s_subscriptions[subscriptionId].blockedBalance < estimatedTotalCostJuels + ) { + revert InsufficientBalance(s_subscriptions[subscriptionId].balance); + } + + // Charge the subscription + s_subscriptions[subscriptionId].balance -= totalCostJuels; + + // Unblock earmarked funds + s_subscriptions[subscriptionId].blockedBalance -= estimatedTotalCostJuels; + + // Pay the DON's fees and gas reimbursement + s_withdrawableTokens[msg.sender] += costWithoutCallbackJuels + callbackGasCostJuels; + + // Pay out the administration fee + s_withdrawableTokens[address(this)] += adminFee; + + // Increment finished requests + s_consumers[client][subscriptionId].completedRequests += 1; + + return Receipt({callbackGasCostJuels: callbackGasCostJuels, totalCostJuels: totalCostJuels}); + } + + // ================================================================ + // | Owner methods | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function ownerCancelSubscription(uint64 subscriptionId) external override { + _onlyRouterOwner(); + _isExistingSubscription(subscriptionId); + _cancelSubscriptionHelper(subscriptionId, s_subscriptions[subscriptionId].owner, false); + } + + /// @inheritdoc IFunctionsSubscriptions + function recoverFunds(address to) external override { + _onlyRouterOwner(); + uint256 externalBalance = i_linkToken.balanceOf(address(this)); + uint256 internalBalance = uint256(s_totalLinkBalance); + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + i_linkToken.safeTransfer(to, amount); + emit FundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function oracleWithdraw(address recipient, uint96 amount) external override { + _whenNotPaused(); + + if (amount == 0) { + revert InvalidCalldata(); + } + uint96 currentBalance = s_withdrawableTokens[msg.sender]; + if (currentBalance < amount) { + revert InsufficientBalance(currentBalance); + } + s_withdrawableTokens[msg.sender] -= amount; + s_totalLinkBalance -= amount; + i_linkToken.safeTransfer(recipient, amount); + } + + /// @notice Owner withdraw LINK earned through admin fees + /// @notice If amount is 0 the full balance will be withdrawn + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function ownerWithdraw(address recipient, uint96 amount) external { + _onlyRouterOwner(); + if (amount == 0) { + amount = s_withdrawableTokens[address(this)]; + } + uint96 currentBalance = s_withdrawableTokens[address(this)]; + if (currentBalance < amount) { + revert InsufficientBalance(currentBalance); + } + s_withdrawableTokens[address(this)] -= amount; + s_totalLinkBalance -= amount; + + i_linkToken.safeTransfer(recipient, amount); + } + + // ================================================================ + // | TransferAndCall Deposit helper | + // ================================================================ + + // This function is to be invoked when using LINK.transferAndCall + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override { + _whenNotPaused(); + if (msg.sender != address(i_linkToken)) { + revert OnlyCallableFromLink(); + } + if (data.length != 32) { + revert InvalidCalldata(); + } + uint64 subscriptionId = abi.decode(data, (uint64)); + if (s_subscriptions[subscriptionId].owner == address(0)) { + revert InvalidSubscription(); + } + // We do not check that the msg.sender is the subscription owner, + // anyone can fund a subscription. + uint256 oldBalance = s_subscriptions[subscriptionId].balance; + s_subscriptions[subscriptionId].balance += uint96(amount); + s_totalLinkBalance += uint96(amount); + emit SubscriptionFunded(subscriptionId, oldBalance, oldBalance + amount); + } + + // ================================================================ + // | Subscription management | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function getTotalBalance() external view override returns (uint96) { + return s_totalLinkBalance; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscriptionCount() external view override returns (uint64) { + return s_currentSubscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscription(uint64 subscriptionId) public view override returns (Subscription memory) { + _isExistingSubscription(subscriptionId); + return s_subscriptions[subscriptionId]; + } + + /// @inheritdoc IFunctionsSubscriptions + function getSubscriptionsInRange( + uint64 subscriptionIdStart, + uint64 subscriptionIdEnd + ) external view override returns (Subscription[] memory subscriptions) { + if ( + subscriptionIdStart > subscriptionIdEnd || + subscriptionIdEnd > s_currentSubscriptionId || + s_currentSubscriptionId == 0 + ) { + revert InvalidCalldata(); + } + + subscriptions = new Subscription[]((subscriptionIdEnd - subscriptionIdStart) + 1); + for (uint256 i = 0; i <= subscriptionIdEnd - subscriptionIdStart; ++i) { + subscriptions[i] = s_subscriptions[uint64(subscriptionIdStart + i)]; + } + + return subscriptions; + } + + /// @inheritdoc IFunctionsSubscriptions + function getConsumer(address client, uint64 subscriptionId) public view override returns (Consumer memory) { + return s_consumers[client][subscriptionId]; + } + + /// @dev Used within this file & FunctionsRouter.sol + function _isExistingSubscription(uint64 subscriptionId) internal view { + if (s_subscriptions[subscriptionId].owner == address(0)) { + revert InvalidSubscription(); + } + } + + /// @dev Used within FunctionsRouter.sol + function _isAllowedConsumer(address client, uint64 subscriptionId) internal view { + if (!s_consumers[client][subscriptionId].allowed) { + revert InvalidConsumer(); + } + } + + /// @inheritdoc IFunctionsSubscriptions + function createSubscription() external override returns (uint64 subscriptionId) { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + subscriptionId = ++s_currentSubscriptionId; + s_subscriptions[subscriptionId] = Subscription({ + balance: 0, + blockedBalance: 0, + owner: msg.sender, + proposedOwner: address(0), + consumers: new address[](0), + flags: bytes32(0) + }); + + emit SubscriptionCreated(subscriptionId, msg.sender); + + return subscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function createSubscriptionWithConsumer(address consumer) external override returns (uint64 subscriptionId) { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + subscriptionId = ++s_currentSubscriptionId; + s_subscriptions[subscriptionId] = Subscription({ + balance: 0, + blockedBalance: 0, + owner: msg.sender, + proposedOwner: address(0), + consumers: new address[](0), + flags: bytes32(0) + }); + + s_subscriptions[subscriptionId].consumers.push(consumer); + s_consumers[consumer][subscriptionId].allowed = true; + + emit SubscriptionCreated(subscriptionId, msg.sender); + emit SubscriptionConsumerAdded(subscriptionId, consumer); + + return subscriptionId; + } + + /// @inheritdoc IFunctionsSubscriptions + function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + if (newOwner == address(0) || s_subscriptions[subscriptionId].proposedOwner == newOwner) { + revert InvalidCalldata(); + } + + s_subscriptions[subscriptionId].proposedOwner = newOwner; + emit SubscriptionOwnerTransferRequested(subscriptionId, msg.sender, newOwner); + } + + /// @inheritdoc IFunctionsSubscriptions + function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external override { + _whenNotPaused(); + _onlySenderThatAcceptedToS(); + + address previousOwner = s_subscriptions[subscriptionId].owner; + address proposedOwner = s_subscriptions[subscriptionId].proposedOwner; + if (proposedOwner != msg.sender) { + revert MustBeProposedOwner(proposedOwner); + } + s_subscriptions[subscriptionId].owner = msg.sender; + s_subscriptions[subscriptionId].proposedOwner = address(0); + emit SubscriptionOwnerTransferred(subscriptionId, previousOwner, msg.sender); + } + + /// @inheritdoc IFunctionsSubscriptions + function removeConsumer(uint64 subscriptionId, address consumer) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + Consumer memory consumerData = s_consumers[consumer][subscriptionId]; + _isAllowedConsumer(consumer, subscriptionId); + if (consumerData.initiatedRequests != consumerData.completedRequests) { + revert CannotRemoveWithPendingRequests(); + } + // Note bounded by config.maxConsumers + address[] memory consumers = s_subscriptions[subscriptionId].consumers; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == consumer) { + // Storage write to preserve last element + s_subscriptions[subscriptionId].consumers[i] = consumers[consumers.length - 1]; + // Storage remove last element + s_subscriptions[subscriptionId].consumers.pop(); + break; + } + } + delete s_consumers[consumer][subscriptionId]; + emit SubscriptionConsumerRemoved(subscriptionId, consumer); + } + + /// @dev Overriden in FunctionsRouter.sol + function _getMaxConsumers() internal view virtual returns (uint16); + + /// @inheritdoc IFunctionsSubscriptions + function addConsumer(uint64 subscriptionId, address consumer) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + // Already maxed, cannot add any more consumers. + uint16 maximumConsumers = _getMaxConsumers(); + if (s_subscriptions[subscriptionId].consumers.length >= maximumConsumers) { + revert TooManyConsumers(maximumConsumers); + } + if (s_consumers[consumer][subscriptionId].allowed) { + // Idempotence - do nothing if already added. + // Ensures uniqueness in s_subscriptions[subscriptionId].consumers. + return; + } + + s_consumers[consumer][subscriptionId].allowed = true; + s_subscriptions[subscriptionId].consumers.push(consumer); + + emit SubscriptionConsumerAdded(subscriptionId, consumer); + } + + /// @dev Overriden in FunctionsRouter.sol + function _getSubscriptionDepositDetails() internal virtual returns (uint16, uint72); + + function _cancelSubscriptionHelper(uint64 subscriptionId, address toAddress, bool checkDepositRefundability) private { + Subscription memory subscription = s_subscriptions[subscriptionId]; + uint96 balance = subscription.balance; + uint64 completedRequests = 0; + + // NOTE: loop iterations are bounded by config.maxConsumers + // If no consumers, does nothing. + for (uint256 i = 0; i < subscription.consumers.length; ++i) { + address consumer = subscription.consumers[i]; + completedRequests += s_consumers[consumer][subscriptionId].completedRequests; + delete s_consumers[consumer][subscriptionId]; + } + delete s_subscriptions[subscriptionId]; + + (uint16 subscriptionDepositMinimumRequests, uint72 subscriptionDepositJuels) = _getSubscriptionDepositDetails(); + + // If subscription has not made enough requests, deposit will be forfeited + if (checkDepositRefundability && completedRequests < subscriptionDepositMinimumRequests) { + uint96 deposit = subscriptionDepositJuels > balance ? balance : subscriptionDepositJuels; + if (deposit > 0) { + s_withdrawableTokens[address(this)] += deposit; + balance -= deposit; + } + } + + if (balance > 0) { + s_totalLinkBalance -= balance; + i_linkToken.safeTransfer(toAddress, uint256(balance)); + } + emit SubscriptionCanceled(subscriptionId, toAddress, balance); + } + + /// @inheritdoc IFunctionsSubscriptions + function cancelSubscription(uint64 subscriptionId, address to) external override { + _whenNotPaused(); + _onlySubscriptionOwner(subscriptionId); + _onlySenderThatAcceptedToS(); + + if (pendingRequestExists(subscriptionId)) { + revert CannotRemoveWithPendingRequests(); + } + + _cancelSubscriptionHelper(subscriptionId, to, true); + } + + /// @inheritdoc IFunctionsSubscriptions + function pendingRequestExists(uint64 subscriptionId) public view override returns (bool) { + address[] memory consumers = s_subscriptions[subscriptionId].consumers; + // NOTE: loop iterations are bounded by config.maxConsumers + for (uint256 i = 0; i < consumers.length; ++i) { + Consumer memory consumer = s_consumers[consumers[i]][subscriptionId]; + if (consumer.initiatedRequests != consumer.completedRequests) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsSubscriptions + function setFlags(uint64 subscriptionId, bytes32 flags) external override { + _onlyRouterOwner(); + _isExistingSubscription(subscriptionId); + s_subscriptions[subscriptionId].flags = flags; + } + + /// @inheritdoc IFunctionsSubscriptions + function getFlags(uint64 subscriptionId) public view returns (bytes32) { + return s_subscriptions[subscriptionId].flags; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsSubscriptions + function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external override { + _whenNotPaused(); + + for (uint256 i = 0; i < requestsToTimeoutByCommitment.length; ++i) { + FunctionsResponse.Commitment memory request = requestsToTimeoutByCommitment[i]; + bytes32 requestId = request.requestId; + uint64 subscriptionId = request.subscriptionId; + + // Check that request ID is valid + if (keccak256(abi.encode(request)) != s_requestCommitments[requestId]) { + revert InvalidCalldata(); + } + + // Check that request has exceeded allowed request time + if (block.timestamp < request.timeoutTimestamp) { + revert TimeoutNotExceeded(); + } + + // Notify the Coordinator that the request should no longer be fulfilled + IFunctionsBilling(request.coordinator).deleteCommitment(requestId); + // Release the subscription's balance that had been earmarked for the request + s_subscriptions[subscriptionId].blockedBalance -= request.estimatedTotalCostJuels; + s_consumers[request.client][subscriptionId].completedRequests += 1; + // Delete commitment within Router state + delete s_requestCommitments[requestId]; + + emit RequestTimedOut(requestId); + } + } + + // ================================================================ + // | Modifiers | + // ================================================================ + + function _onlySubscriptionOwner(uint64 subscriptionId) internal view { + address owner = s_subscriptions[subscriptionId].owner; + if (owner == address(0)) { + revert InvalidSubscription(); + } + if (msg.sender != owner) { + revert MustBeSubscriptionOwner(); + } + } + + /// @dev Overriden in FunctionsRouter.sol + function _onlySenderThatAcceptedToS() internal virtual; + + /// @dev Overriden in FunctionsRouter.sol + function _onlyRouterOwner() internal virtual; + + /// @dev Overriden in FunctionsRouter.sol + function _whenNotPaused() internal virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol new file mode 100644 index 0000000..6c11d4d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IOwnableFunctionsRouter} from "./interfaces/IOwnableFunctionsRouter.sol"; + +/// @title This abstract should be inherited by contracts that will be used +/// as the destinations to a route (id=>contract) on the Router. +/// It provides a Router getter and modifiers. +abstract contract Routable is ITypeAndVersion { + IOwnableFunctionsRouter private immutable i_router; + + error RouterMustBeSet(); + error OnlyCallableByRouter(); + error OnlyCallableByRouterOwner(); + + /// @dev Initializes the contract. + constructor(address router) { + if (router == address(0)) { + revert RouterMustBeSet(); + } + i_router = IOwnableFunctionsRouter(router); + } + + /// @notice Return the Router + function _getRouter() internal view returns (IOwnableFunctionsRouter router) { + return i_router; + } + + /// @notice Reverts if called by anyone other than the router. + modifier onlyRouter() { + if (msg.sender != address(i_router)) { + revert OnlyCallableByRouter(); + } + _; + } + + /// @notice Reverts if called by anyone other than the router owner. + modifier onlyRouterOwner() { + if (msg.sender != i_router.owner()) { + revert OnlyCallableByRouterOwner(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol new file mode 100644 index 0000000..8a42e34 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITermsOfServiceAllowList} from "./interfaces/ITermsOfServiceAllowList.sol"; +import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; + +import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.AddressSet; + + /// @inheritdoc ITypeAndVersion + string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.0.0"; + + EnumerableSet.AddressSet private s_allowedSenders; + mapping(address => bool) private s_blockedSenders; + + event AddedAccess(address user); + event BlockedAccess(address user); + event UnblockedAccess(address user); + + error InvalidSignature(); + error InvalidUsage(); + error RecipientIsBlocked(); + + // ================================================================ + // | Configuration state | + // ================================================================ + struct Config { + bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. + address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data + } + + Config private s_config; + + event ConfigUpdated(Config config); + + // ================================================================ + // | Initialization | + // ================================================================ + + constructor(Config memory config) ConfirmedOwner(msg.sender) { + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the contracts's configuration + /// @return config + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice Sets the contracts's configuration + /// @param config - See the contents of the TermsOfServiceAllowList.Config struct for more information + function updateConfig(Config memory config) public onlyOwner { + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Allow methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { + return keccak256(abi.encodePacked(acceptor, recipient)); + } + + /// @inheritdoc ITermsOfServiceAllowList + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { + if (s_blockedSenders[recipient]) { + revert RecipientIsBlocked(); + } + + // Validate that the signature is correct and the correct data has been signed + bytes32 prefixedMessage = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) + ); + if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { + revert InvalidSignature(); + } + + // If contract, validate that msg.sender == recipient + // This is to prevent EoAs from claiming contracts that they are not in control of + // If EoA, validate that msg.sender == acceptor == recipient + // This is to prevent EoAs from accepting for other EoAs + if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { + revert InvalidUsage(); + } + + // Add recipient to the allow list + s_allowedSenders.add(recipient); + emit AddedAccess(recipient); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllAllowedSenders() external view override returns (address[] memory) { + return s_allowedSenders.values(); + } + + /// @inheritdoc IAccessController + function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { + if (!s_config.enabled) { + return true; + } + return s_allowedSenders.contains(user); + } + + // ================================================================ + // | Block methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function isBlockedSender(address sender) external view override returns (bool) { + if (!s_config.enabled) { + return false; + } + return s_blockedSenders[sender]; + } + + /// @inheritdoc ITermsOfServiceAllowList + function blockSender(address sender) external override onlyOwner { + s_allowedSenders.remove(sender); + s_blockedSenders[sender] = true; + emit BlockedAccess(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function unblockSender(address sender) external override onlyOwner { + s_blockedSenders[sender] = false; + emit UnblockedAccess(sender); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol new file mode 100644 index 0000000..af4daa1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +interface ITermsOfServiceAllowList { + /// @notice Return the message data for the proof given to accept the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @return Hash of the message data + function getMessage(address acceptor, address recipient) external pure returns (bytes32); + + /// @notice Check if the address is blocked for usage + /// @param sender The transaction sender's address + /// @return True or false + function isBlockedSender(address sender) external returns (bool); + + /// @notice Get a list of all allowed senders + /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + /// this function has an unbounded cost, and using it as part of a state-changing function may render the function + /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + /// @return addresses - all allowed addresses + function getAllAllowedSenders() external view returns (address[] memory); + + /// @notice Allows access to the sender based on acceptance of the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI + /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI + /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; + + /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service + /// @param sender - Address of the sender to block + function blockSender(address sender) external; + + /// @notice Re-allows a previously blocked sender to accept the Terms of Service + /// @param sender - Address of the sender to unblock + function unblockSender(address sender) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol new file mode 100644 index 0000000..8d1cf36 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsClient} from "../FunctionsClient.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {FunctionsRequest} from "../libraries/FunctionsRequest.sol"; + +/// @title Chainlink Functions example Client contract implementation +contract FunctionsClientExample is FunctionsClient, ConfirmedOwner { + using FunctionsRequest for FunctionsRequest.Request; + + uint32 public constant MAX_CALLBACK_GAS = 70_000; + + bytes32 public s_lastRequestId; + bytes32 public s_lastResponse; + bytes32 public s_lastError; + uint32 public s_lastResponseLength; + uint32 public s_lastErrorLength; + + error UnexpectedRequestID(bytes32 requestId); + + constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} + + /// @notice Send a simple request + /// @param source JavaScript source code + /// @param encryptedSecretsReferences Encrypted secrets payload + /// @param args List of arguments accessible from within the source code + /// @param subscriptionId Billing ID + function sendRequest( + string calldata source, + bytes calldata encryptedSecretsReferences, + string[] calldata args, + uint64 subscriptionId, + bytes32 jobId + ) external onlyOwner { + FunctionsRequest.Request memory req; + req.initializeRequestForInlineJavaScript(source); + if (encryptedSecretsReferences.length > 0) req.addSecretsReference(encryptedSecretsReferences); + if (args.length > 0) req.setArgs(args); + s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); + } + + /// @notice Store latest result/error + /// @param requestId The request ID, returned by sendRequest() + /// @param response Aggregated response from the user code + /// @param err Aggregated error from the user code or from the execution pipeline + /// @dev Either response or error parameter will be set, but never both + function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { + if (s_lastRequestId != requestId) { + revert UnexpectedRequestID(requestId); + } + // Save only the first 32 bytes of response/error to always fit within MAX_CALLBACK_GAS + s_lastResponse = bytesToBytes32(response); + s_lastResponseLength = uint32(response.length); + s_lastError = bytesToBytes32(err); + s_lastErrorLength = uint32(err.length); + } + + function bytesToBytes32(bytes memory b) private pure returns (bytes32 out) { + uint256 maxLen = 32; + if (b.length < 32) { + maxLen = b.length; + } + for (uint256 i = 0; i < maxLen; ++i) { + out |= bytes32(b[i]) >> (i * 8); + } + return out; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol new file mode 100644 index 0000000..6291d05 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Chainlink Functions DON billing interface. +interface IFunctionsBilling { + /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed + /// @return weiPerUnitLink - The amount of WEI in one LINK + function getWeiPerUnitLink() external view returns (uint256); + + /// @notice Determine the fee that will be split between Node Operators for servicing a request + /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request + /// @return fee - Cost in Juels (1e18) of LINK + function getDONFee(bytes memory requestCBOR) external view returns (uint72); + + /// @notice Determine the fee that will be paid to the Router owner for operating the network + /// @return fee - Cost in Juels (1e18) of LINK + function getAdminFee() external view returns (uint72); + + /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee + /// @param - subscriptionId An identifier of the billing account + /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param - callbackGasLimit Gas limit for the fulfillment callback + /// @param - gasPriceWei The blockchain's gas price to estimate with + /// @return - billedCost Cost in Juels (1e18) of LINK + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view returns (uint96); + + /// @notice Remove a request commitment that the Router has determined to be stale + /// @param requestId - The request ID to remove + function deleteCommitment(bytes32 requestId) external; + + /// @notice Oracle withdraw LINK earned through fulfilling requests + /// @notice If amount is 0 the full balance will be withdrawn + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function oracleWithdraw(address recipient, uint96 amount) external; + + /// @notice Withdraw all LINK earned by Oracles through fulfilling requests + function oracleWithdrawAll() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol new file mode 100644 index 0000000..f28a416 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Chainlink Functions client interface. +interface IFunctionsClient { + /// @notice Chainlink Functions response handler called by the Functions Router + /// during fullilment from the designated transmitter node in an OCR round. + /// @param requestId The requestId returned by FunctionsClient.sendRequest(). + /// @param response Aggregated response from the request's source code. + /// @param err Aggregated error either from the request's source code or from the execution pipeline. + /// @dev Either response or error parameter will be set, but never both. + function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol new file mode 100644 index 0000000..4e2bd70 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions DON Coordinator interface. +interface IFunctionsCoordinator { + /// @notice Returns the DON's threshold encryption public key used to encrypt secrets + /// @dev All nodes on the DON have separate key shares of the threshold decryption key + /// and nodes must participate in a threshold decryption OCR round to decrypt secrets + /// @return thresholdPublicKey the DON's threshold encryption public key + function getThresholdPublicKey() external view returns (bytes memory); + + /// @notice Sets the DON's threshold encryption public key used to encrypt secrets + /// @dev Used to rotate the key + /// @param thresholdPublicKey The new public key + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external; + + /// @notice Returns the DON's secp256k1 public key that is used to encrypt secrets + /// @dev All nodes on the DON have the corresponding private key + /// needed to decrypt the secrets encrypted with the public key + /// @return publicKey the DON's public key + function getDONPublicKey() external view returns (bytes memory); + + /// @notice Sets DON's secp256k1 public key used to encrypt secrets + /// @dev Used to rotate the key + /// @param donPublicKey The new public key + function setDONPublicKey(bytes calldata donPublicKey) external; + + /// @notice Receives a request to be emitted to the DON for processing + /// @param request The request metadata + /// @dev see the struct for field descriptions + /// @return commitment - The parameters of the request that must be held consistent at response time + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external returns (FunctionsResponse.Commitment memory commitment); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol new file mode 100644 index 0000000..5f93aac --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions Router interface. +interface IFunctionsRouter { + /// @notice The identifier of the route to retrieve the address of the access control contract + /// The access control contract controls which accounts can manage subscriptions + /// @return id - bytes32 id that can be passed to the "getContractById" of the Router + function getAllowListId() external view returns (bytes32); + + /// @notice Set the identifier of the route to retrieve the address of the access control contract + /// The access control contract controls which accounts can manage subscriptions + function setAllowListId(bytes32 allowListId) external; + + /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network + /// @return adminFee + function getAdminFee() external view returns (uint72 adminFee); + + /// @notice Sends a request using the provided subscriptionId + /// @param subscriptionId - A unique subscription ID allocated by billing system, + /// a client can make requests from different contracts referencing the same subscription + /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param dataVersion - Gas limit for the fulfillment callback + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @param donId - An identifier used to determine which route to send the request along + /// @return requestId - A unique request identifier + function sendRequest( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external returns (bytes32); + + /// @notice Sends a request to the proposed contracts + /// @param subscriptionId - A unique subscription ID allocated by billing system, + /// a client can make requests from different contracts referencing the same subscription + /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param dataVersion - Gas limit for the fulfillment callback + /// @param callbackGasLimit - Gas limit for the fulfillment callback + /// @param donId - An identifier used to determine which route to send the request along + /// @return requestId - A unique request identifier + function sendRequestToProposed( + uint64 subscriptionId, + bytes calldata data, + uint16 dataVersion, + uint32 callbackGasLimit, + bytes32 donId + ) external returns (bytes32); + + /// @notice Fulfill the request by: + /// - calling back the data that the Oracle returned to the client contract + /// - pay the DON for processing the request + /// @dev Only callable by the Coordinator contract that is saved in the commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @param juelsPerGas - current rate of juels/gas + /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment + /// @param transmitter - The Node that transmitted the OCR report + /// @param commitment - The parameters of the request that must be held consistent between request and response time + /// @return fulfillResult - + /// @return callbackGasCostJuels - + function fulfill( + bytes memory response, + bytes memory err, + uint96 juelsPerGas, + uint96 costWithoutFulfillment, + address transmitter, + FunctionsResponse.Commitment memory commitment + ) external returns (FunctionsResponse.FulfillResult, uint96); + + /// @notice Validate requested gas limit is below the subscription max. + /// @param subscriptionId subscription ID + /// @param callbackGasLimit desired callback gas limit + function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view; + + /// @notice Get the current contract given an ID + /// @param id A bytes32 identifier for the route + /// @return contract The current contract address + function getContractById(bytes32 id) external view returns (address); + + /// @notice Get the proposed next contract given an ID + /// @param id A bytes32 identifier for the route + /// @return contract The current or proposed contract address + function getProposedContractById(bytes32 id) external view returns (address); + + /// @notice Return the latest proprosal set + /// @return ids The identifiers of the contracts to update + /// @return to The addresses of the contracts that will be updated to + function getProposedContractSet() external view returns (bytes32[] memory, address[] memory); + + /// @notice Proposes one or more updates to the contract routes + /// @dev Only callable by owner + function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external; + + /// @notice Updates the current contract routes to the proposed contracts + /// @dev Only callable by owner + function updateContracts() external; + + /// @dev Puts the system into an emergency stopped state. + /// @dev Only callable by owner + function pause() external; + + /// @dev Takes the system out of an emergency stopped state. + /// @dev Only callable by owner + function unpause() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol new file mode 100644 index 0000000..eafd6f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; + +/// @title Chainlink Functions Subscription interface. +interface IFunctionsSubscriptions { + struct Subscription { + uint96 balance; // ═════════╗ Common LINK balance that is controlled by the Router to be used for all consumer requests. + address owner; // ══════════╝ The owner can fund/withdraw/cancel the subscription. + uint96 blockedBalance; // ══╗ LINK balance that is reserved to pay for pending consumer requests. + address proposedOwner; // ══╝ For safely transferring sub ownership. + address[] consumers; // ════╸ Client contracts that can use the subscription + bytes32 flags; // ══════════╸ Per-subscription flags + } + + struct Consumer { + bool allowed; // ══════════════╗ Owner can fund/withdraw/cancel the sub. + uint64 initiatedRequests; // ║ The number of requests that have been started + uint64 completedRequests; // ══╝ The number of requests that have successfully completed or timed out + } + + /// @notice Get details about a subscription. + /// @param subscriptionId - the ID of the subscription + /// @return subscription - see IFunctionsSubscriptions.Subscription for more information on the structure + function getSubscription(uint64 subscriptionId) external view returns (Subscription memory); + + /// @notice Retrieve details about multiple subscriptions using an inclusive range + /// @param subscriptionIdStart - the ID of the subscription to start the range at + /// @param subscriptionIdEnd - the ID of the subscription to end the range at + /// @return subscriptions - see IFunctionsSubscriptions.Subscription for more information on the structure + function getSubscriptionsInRange( + uint64 subscriptionIdStart, + uint64 subscriptionIdEnd + ) external view returns (Subscription[] memory); + + /// @notice Get details about a consumer of a subscription. + /// @param client - the consumer contract address + /// @param subscriptionId - the ID of the subscription + /// @return consumer - see IFunctionsSubscriptions.Consumer for more information on the structure + function getConsumer(address client, uint64 subscriptionId) external view returns (Consumer memory); + + /// @notice Get details about the total amount of LINK within the system + /// @return totalBalance - total Juels of LINK held by the contract + function getTotalBalance() external view returns (uint96); + + /// @notice Get details about the total number of subscription accounts + /// @return count - total number of subscriptions in the system + function getSubscriptionCount() external view returns (uint64); + + /// @notice Time out all expired requests: unlocks funds and removes the ability for the request to be fulfilled + /// @param requestsToTimeoutByCommitment - A list of request commitments to time out + /// @dev The commitment can be found on the "OracleRequest" event created when sending the request. + function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external; + + /// @notice Oracle withdraw LINK earned through fulfilling requests + /// @notice If amount is 0 the full balance will be withdrawn + /// @notice Both signing and transmitting wallets will have a balance to withdraw + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function oracleWithdraw(address recipient, uint96 amount) external; + + /// @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + /// @dev Only callable by the Router Owner + /// @param subscriptionId subscription id + /// @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + function ownerCancelSubscription(uint64 subscriptionId) external; + + /// @notice Recover link sent with transfer instead of transferAndCall. + /// @dev Only callable by the Router Owner + /// @param to address to send link to + function recoverFunds(address to) external; + + /// @notice Create a new subscription. + /// @return subscriptionId - A unique subscription id. + /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function createSubscription() external returns (uint64); + + /// @notice Create a new subscription and add a consumer. + /// @return subscriptionId - A unique subscription id. + /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + /// @dev Note to fund the subscription, use transferAndCall. For example + /// @dev LINKTOKEN.transferAndCall( + /// @dev address(ROUTER), + /// @dev amount, + /// @dev abi.encode(subscriptionId)); + function createSubscriptionWithConsumer(address consumer) external returns (uint64 subscriptionId); + + /// @notice Propose a new owner for a subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param newOwner - proposed new owner of the subscription + function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external; + + /// @notice Accept an ownership transfer. + /// @param subscriptionId - ID of the subscription + /// @dev will revert if original owner of subscriptionId has not requested that msg.sender become the new owner. + function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external; + + /// @notice Remove a consumer from a Chainlink Functions subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param consumer - Consumer to remove from the subscription + function removeConsumer(uint64 subscriptionId, address consumer) external; + + /// @notice Add a consumer to a Chainlink Functions subscription. + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param consumer - New consumer which can use the subscription + function addConsumer(uint64 subscriptionId, address consumer) external; + + /// @notice Cancel a subscription + /// @dev Only callable by the Subscription's owner + /// @param subscriptionId - ID of the subscription + /// @param to - Where to send the remaining LINK to + function cancelSubscription(uint64 subscriptionId, address to) external; + + /// @notice Check to see if there exists a request commitment for all consumers for a given sub. + /// @param subscriptionId - ID of the subscription + /// @return true if there exists at least one unfulfilled request for the subscription, false otherwise. + /// @dev Looping is bounded to MAX_CONSUMERS*(number of DONs). + /// @dev Used to disable subscription canceling while outstanding request are present. + function pendingRequestExists(uint64 subscriptionId) external view returns (bool); + + /// @notice Set subscription specific flags for a subscription. + /// Each byte of the flag is used to represent a resource tier that the subscription can utilize. + /// @param subscriptionId - ID of the subscription + /// @param flags - desired flag values + function setFlags(uint64 subscriptionId, bytes32 flags) external; + + /// @notice Get flags for a given subscription. + /// @param subscriptionId - ID of the subscription + /// @return flags - current flag values + function getFlags(uint64 subscriptionId) external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol new file mode 100644 index 0000000..c5f3d82 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsRouter} from "./IFunctionsRouter.sol"; +import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; + +/// @title Chainlink Functions Router interface with Ownability. +interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol new file mode 100644 index 0000000..ef697b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {CBOR} from "../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol"; + +/// @title Library for encoding the input data of a Functions request into CBOR +library FunctionsRequest { + using CBOR for CBOR.CBORBuffer; + + uint16 public constant REQUEST_DATA_VERSION = 1; + uint256 internal constant DEFAULT_BUFFER_SIZE = 256; + + enum Location { + Inline, // Provided within the Request + Remote, // Hosted through remote location that can be accessed through a provided URL + DONHosted // Hosted on the DON's storage + } + + enum CodeLanguage { + JavaScript + // In future version we may add other languages + } + + struct Request { + Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON + Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported + CodeLanguage language; // ════════════╸ The coding language that the source code is written in + string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted + bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) + string[] args; // ════════════════════╸ String arguments that will be passed into the source code + bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code + } + + error EmptySource(); + error EmptySecrets(); + error EmptyArgs(); + error NoInlineSecrets(); + + /// @notice Encodes a Request to CBOR encoded bytes + /// @param self The request to encode + /// @return CBOR encoded bytes + function encodeCBOR(Request memory self) internal pure returns (bytes memory) { + CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); + + buffer.writeString("codeLocation"); + buffer.writeUInt256(uint256(self.codeLocation)); + + buffer.writeString("language"); + buffer.writeUInt256(uint256(self.language)); + + buffer.writeString("source"); + buffer.writeString(self.source); + + if (self.args.length > 0) { + buffer.writeString("args"); + buffer.startArray(); + for (uint256 i = 0; i < self.args.length; ++i) { + buffer.writeString(self.args[i]); + } + buffer.endSequence(); + } + + if (self.encryptedSecretsReference.length > 0) { + if (self.secretsLocation == Location.Inline) { + revert NoInlineSecrets(); + } + buffer.writeString("secretsLocation"); + buffer.writeUInt256(uint256(self.secretsLocation)); + buffer.writeString("secrets"); + buffer.writeBytes(self.encryptedSecretsReference); + } + + if (self.bytesArgs.length > 0) { + buffer.writeString("bytesArgs"); + buffer.startArray(); + for (uint256 i = 0; i < self.bytesArgs.length; ++i) { + buffer.writeBytes(self.bytesArgs[i]); + } + buffer.endSequence(); + } + + return buffer.buf.buf; + } + + /// @notice Initializes a Chainlink Functions Request + /// @dev Sets the codeLocation and code on the request + /// @param self The uninitialized request + /// @param codeLocation The user provided source code location + /// @param language The programming language of the user code + /// @param source The user provided source code or a url + function initializeRequest( + Request memory self, + Location codeLocation, + CodeLanguage language, + string memory source + ) internal pure { + if (bytes(source).length == 0) revert EmptySource(); + + self.codeLocation = codeLocation; + self.language = language; + self.source = source; + } + + /// @notice Initializes a Chainlink Functions Request + /// @dev Simplified version of initializeRequest for PoC + /// @param self The uninitialized request + /// @param javaScriptSource The user provided JS code (must not be empty) + function initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure { + initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource); + } + + /// @notice Adds Remote user encrypted secrets to a Request + /// @param self The initialized request + /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets + function addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure { + if (encryptedSecretsReference.length == 0) revert EmptySecrets(); + + self.secretsLocation = Location.Remote; + self.encryptedSecretsReference = encryptedSecretsReference; + } + + /// @notice Adds DON-hosted secrets reference to a Request + /// @param self The initialized request + /// @param slotID Slot ID of the user's secrets hosted on DON + /// @param version User data version (for the slotID) + function addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure { + CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); + + buffer.writeString("slotID"); + buffer.writeUInt64(slotID); + buffer.writeString("version"); + buffer.writeUInt64(version); + + self.secretsLocation = Location.DONHosted; + self.encryptedSecretsReference = buffer.buf.buf; + } + + /// @notice Sets args for the user run function + /// @param self The initialized request + /// @param args The array of string args (must not be empty) + function setArgs(Request memory self, string[] memory args) internal pure { + if (args.length == 0) revert EmptyArgs(); + + self.args = args; + } + + /// @notice Sets bytes args for the user run function + /// @param self The initialized request + /// @param args The array of bytes args (must not be empty) + function setBytesArgs(Request memory self, bytes[] memory args) internal pure { + if (args.length == 0) revert EmptyArgs(); + + self.bytesArgs = args; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol new file mode 100644 index 0000000..65fad66 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Library of types that are used for fulfillment of a Functions request +library FunctionsResponse { + // Used to send request information from the Router to the Coordinator + struct RequestMeta { + bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request + bytes32 flags; // ═══════════════╸ Per-subscription flags + address requestingContract; // ══╗ The client contract that is sending the request + uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests. + uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network + uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request + uint64 initiatedRequests; // ║ The number of requests that have been started + uint32 callbackGasLimit; // ║ The amount of gas that the callback to the consuming contract will be given + uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data + uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out + address subscriptionOwner; // ═══╝ The owner of the billing subscription + } + + enum FulfillResult { + FULFILLED, // 0 + USER_CALLBACK_ERROR, // 1 + INVALID_REQUEST_ID, // 2 + COST_EXCEEDS_COMMITMENT, // 3 + INSUFFICIENT_GAS_PROVIDED, // 4 + SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5 + INVALID_COMMITMENT // 6 + } + + struct Commitment { + bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request + address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request + uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request + address client; // ════════════════════╗ The client contract that sent the request + uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request + uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given + uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network + uint72 donFee; // ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request + uint40 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. + uint40 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. + uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol new file mode 100644 index 0000000..68b51f8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.19; + +contract FunctionsV1EventsMock { + struct Config { + uint16 maxConsumersPerSubscription; + uint72 adminFee; + bytes4 handleOracleFulfillmentSelector; + uint16 gasForCallExactCheck; + uint32[] maxCallbackGasLimits; + } + event ConfigUpdated(Config param1); + event ContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ); + event ContractUpdated(bytes32 id, address from, address to); + event FundsRecovered(address to, uint256 amount); + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + event Paused(address account); + event RequestNotProcessed(bytes32 indexed requestId, address coordinator, address transmitter, uint8 resultCode); + event RequestProcessed( + bytes32 indexed requestId, + uint64 indexed subscriptionId, + uint96 totalCostJuels, + address transmitter, + uint8 resultCode, + bytes response, + bytes err, + bytes callbackReturnData + ); + event RequestStart( + bytes32 indexed requestId, + bytes32 indexed donId, + uint64 indexed subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ); + event RequestTimedOut(bytes32 indexed requestId); + event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); + event SubscriptionCreated(uint64 indexed subscriptionId, address owner); + event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); + event Unpaused(address account); + + function emitConfigUpdated(Config memory param1) public { + emit ConfigUpdated(param1); + } + + function emitContractProposed( + bytes32 proposedContractSetId, + address proposedContractSetFromAddress, + address proposedContractSetToAddress + ) public { + emit ContractProposed(proposedContractSetId, proposedContractSetFromAddress, proposedContractSetToAddress); + } + + function emitContractUpdated(bytes32 id, address from, address to) public { + emit ContractUpdated(id, from, to); + } + + function emitFundsRecovered(address to, uint256 amount) public { + emit FundsRecovered(to, amount); + } + + function emitOwnershipTransferRequested(address from, address to) public { + emit OwnershipTransferRequested(from, to); + } + + function emitOwnershipTransferred(address from, address to) public { + emit OwnershipTransferred(from, to); + } + + function emitPaused(address account) public { + emit Paused(account); + } + + function emitRequestNotProcessed( + bytes32 requestId, + address coordinator, + address transmitter, + uint8 resultCode + ) public { + emit RequestNotProcessed(requestId, coordinator, transmitter, resultCode); + } + + function emitRequestProcessed( + bytes32 requestId, + uint64 subscriptionId, + uint96 totalCostJuels, + address transmitter, + uint8 resultCode, + bytes memory response, + bytes memory err, + bytes memory callbackReturnData + ) public { + emit RequestProcessed( + requestId, + subscriptionId, + totalCostJuels, + transmitter, + resultCode, + response, + err, + callbackReturnData + ); + } + + function emitRequestStart( + bytes32 requestId, + bytes32 donId, + uint64 subscriptionId, + address subscriptionOwner, + address requestingContract, + address requestInitiator, + bytes memory data, + uint16 dataVersion, + uint32 callbackGasLimit, + uint96 estimatedTotalCostJuels + ) public { + emit RequestStart( + requestId, + donId, + subscriptionId, + subscriptionOwner, + requestingContract, + requestInitiator, + data, + dataVersion, + callbackGasLimit, + estimatedTotalCostJuels + ); + } + + function emitRequestTimedOut(bytes32 requestId) public { + emit RequestTimedOut(requestId); + } + + function emitSubscriptionCanceled(uint64 subscriptionId, address fundsRecipient, uint256 fundsAmount) public { + emit SubscriptionCanceled(subscriptionId, fundsRecipient, fundsAmount); + } + + function emitSubscriptionConsumerAdded(uint64 subscriptionId, address consumer) public { + emit SubscriptionConsumerAdded(subscriptionId, consumer); + } + + function emitSubscriptionConsumerRemoved(uint64 subscriptionId, address consumer) public { + emit SubscriptionConsumerRemoved(subscriptionId, consumer); + } + + function emitSubscriptionCreated(uint64 subscriptionId, address owner) public { + emit SubscriptionCreated(subscriptionId, owner); + } + + function emitSubscriptionFunded(uint64 subscriptionId, uint256 oldBalance, uint256 newBalance) public { + emit SubscriptionFunded(subscriptionId, oldBalance, newBalance); + } + + function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId, address from, address to) public { + emit SubscriptionOwnerTransferRequested(subscriptionId, from, to); + } + + function emitSubscriptionOwnerTransferred(uint64 subscriptionId, address from, address to) public { + emit SubscriptionOwnerTransferred(subscriptionId, from, to); + } + + function emitUnpaused(address account) public { + emit Unpaused(account); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol new file mode 100644 index 0000000..09c4a82 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /** + * @notice optionally emited to indicate the latest configDigest and epoch for + which a report was successfully transmited. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol new file mode 100644 index 0000000..b7c3f03 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/** + * @notice Onchain verification of reports from the offchain reporting protocol + * @dev For details on its operation, see the offchain reporting protocol design + * doc, which refers to this contract as simply the "contract". + */ +abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { + error ReportInvalid(); + error InvalidConfig(string message); + + bool internal immutable i_uniqueReports; + + constructor(bool uniqueReports) ConfirmedOwner(msg.sender) { + i_uniqueReports = uniqueReports; + } + + uint256 private constant maxUint32 = (1 << 32) - 1; + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems + // to extract config from logs. + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + mapping(address signerOrTransmitter => Oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + /* + * Config logic + */ + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param _signers addresses with which oracles sign the reports + * @param _transmitters addresses oracles use to transmit the reports + * @param _f number of faulty oracles the system can tolerate + * @param _onchainConfig encoded on-chain contract configuration + * @param _offchainConfigVersion version number for offchainEncoding schema + * @param _offchainConfig encoded off-chain oracle configuration + */ + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < args.signers.length; i++) { + // add new signer/transmitter addresses + require(s_oracles[args.signers[i]].role == Role.Unset, "repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + require(s_oracles[args.transmitters[i]].role == Role.Unset, "repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + + function configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /** + * @return list of addresses permitted to transmit reports to this contract + * @dev The list will match the order used to specify the transmitter during setConfig + */ + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /** + * @dev hook called after the report has been fully validated + * for the extending contract to handle additional logic, such as oracle payment + * @param initialGas the amount of gas before validation + * @param transmitter the address of the account that submitted the report + * @param signers the addresses of all signing accounts + * @param report serialized report + */ + function _report( + uint256 initialGas, + address transmitter, + uint8 signerCount, + address[MAX_NUM_ORACLES] memory signers, + bytes calldata report + ) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + require(msg.data.length == expected, "calldata length mismatch"); + } + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + uint256 initialGas = gasleft(); // This line must come first + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + ConfigInfo memory configInfo = s_configInfo; + require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures; + if (i_uniqueReports) { + expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1; + } else { + expectedNumSignatures = configInfo.f + 1; + } + + require(rs.length == expectedNumSignatures, "wrong number of signatures"); + require(rs.length == ss.length, "signatures out of registration"); + + Oracle memory transmitter = s_oracles[msg.sender]; + require( // Check that sender is authorized to report + transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index], + "unauthorized transmitter" + ); + } + + address[MAX_NUM_ORACLES] memory signed; + uint8 signerCount = 0; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + require(o.role == Role.Signer, "address not authorized to sign"); + require(signed[o.index] == address(0), "non-unique signature"); + signed[o.index] = signer; + signerCount += 1; + } + } + + _report(initialGas, msg.sender, signerCount, signed, report); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol new file mode 100644 index 0000000..ff34500 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol @@ -0,0 +1,391 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "../v1_0_0/interfaces/IFunctionsSubscriptions.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {IFunctionsBilling} from "../v1_0_0/interfaces/IFunctionsBilling.sol"; + +import {Routable} from "../v1_0_0/Routable.sol"; +import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; + +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +import {ChainSpecificUtil} from "./libraries/ChainSpecificUtil.sol"; + +/// @title Functions Billing contract +/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsBilling is Routable, IFunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei + + event RequestBilled( + bytes32 indexed requestId, + uint96 juelsPerGas, + uint256 l1FeeShareWei, + uint96 callbackCostJuels, + uint96 totalCostJuels + ); + + // ================================================================ + // | Request Commitment state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; + + event CommitmentDeleted(bytes32 requestId); + + // ================================================================ + // | Configuration state | + // ================================================================ + + struct Config { + uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) + uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. + uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. + uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. + uint72 donFee; // ║ Additional flat fee (in Juels of LINK) that will be split between Node Operators. Max value is 2^80 - 1 == 1.2m LINK. + uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request + uint16 maxSupportedRequestDataVersion; // ═══════╝ The highest support request data version supported by the node. All lower versions should also be supported. + 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 + } + + Config private s_config; + + event ConfigUpdated(Config config); + + error UnsupportedRequestDataVersion(); + error InsufficientBalance(); + error InvalidSubscription(); + error UnauthorizedSender(); + error MustBeSubOwner(address owner); + error InvalidLinkWeiPrice(int256 linkWei); + error PaymentTooLarge(); + error NoTransmittersSet(); + error InvalidCalldata(); + + // ================================================================ + // | Balance state | + // ================================================================ + + mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; + // Pool together collected DON fees + // Disperse them on withdrawal or change in OCR configuration + uint96 internal s_feePool; + + AggregatorV3Interface private s_linkToNativeFeed; + + // ================================================================ + // | Initialization | + // ================================================================ + constructor(address router, Config memory config, address linkToNativeFeed) Routable(router) { + s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); + + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the Chainlink Coordinator's billing configuration + /// @return config + function getConfig() external view returns (Config memory) { + return s_config; + } + + /// @notice Sets the Chainlink Coordinator's billing configuration + /// @param config - See the contents of the Config struct in IFunctionsBilling.Config for more information + function updateConfig(Config memory config) public { + _onlyOwner(); + + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Fee Calculation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function getDONFee(bytes memory /* requestData */) public view override returns (uint72) { + return s_config.donFee; + } + + /// @inheritdoc IFunctionsBilling + function getAdminFee() public view override returns (uint72) { + return _getRouter().getAdminFee(); + } + + /// @inheritdoc IFunctionsBilling + function getWeiPerUnitLink() public view returns (uint256) { + Config memory config = s_config; + (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (config.feedStalenessSeconds < block.timestamp - timestamp && config.feedStalenessSeconds > 0) { + return config.fallbackNativePerUnitLink; + } + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + return uint256(weiPerUnitLink); + } + + function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { + // (1e18 juels/link) * wei / (wei/link) = juels + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); + } + + // ================================================================ + // | Cost Estimation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view override returns (uint96) { + _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + // Reasonable ceilings to prevent integer overflows + if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { + revert InvalidCalldata(); + } + uint72 adminFee = getAdminFee(); + uint72 donFee = getDONFee(data); + return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee); + } + + /// @notice Estimate the cost in Juels of LINK + // that will be charged to a subscription to fulfill a Functions request + // Gas Price can be overestimated to account for flucuations between request and response time + function _calculateCostEstimate( + uint32 callbackGasLimit, + uint256 gasPriceWei, + uint72 donFee, + uint72 adminFee + ) internal view returns (uint96) { + // If gas price is less than the minimum fulfillment gas price, override to using the minimum + if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { + 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); + + uint96 feesJuels = uint96(donFee) + uint96(adminFee); + + return estimatedGasReimbursementJuels + feesJuels; + } + + // ================================================================ + // | Billing | + // ================================================================ + + /// @notice Initiate the billing process for an Functions request + /// @dev Only callable by the Functions Router + /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure + /// @return commitment - The parameters of the request that must be held consistent at response time + function _startBilling( + FunctionsResponse.RequestMeta memory request + ) internal returns (FunctionsResponse.Commitment memory commitment) { + Config memory config = s_config; + + // Nodes should support all past versions of the structure + if (request.dataVersion > config.maxSupportedRequestDataVersion) { + revert UnsupportedRequestDataVersion(); + } + + uint72 donFee = getDONFee(request.data); + uint96 estimatedTotalCostJuels = _calculateCostEstimate( + request.callbackGasLimit, + tx.gasprice, + donFee, + request.adminFee + ); + + // Check that subscription can afford the estimated cost + if ((request.availableBalance) < estimatedTotalCostJuels) { + revert InsufficientBalance(); + } + + uint32 timeoutTimestamp = uint32(block.timestamp + config.requestTimeoutSeconds); + bytes32 requestId = keccak256( + abi.encode( + address(this), + request.requestingContract, + request.subscriptionId, + request.initiatedRequests + 1, + keccak256(request.data), + request.dataVersion, + request.callbackGasLimit, + estimatedTotalCostJuels, + timeoutTimestamp, + // solhint-disable-next-line avoid-tx-origin + tx.origin + ) + ); + + commitment = FunctionsResponse.Commitment({ + adminFee: request.adminFee, + coordinator: address(this), + client: request.requestingContract, + subscriptionId: request.subscriptionId, + callbackGasLimit: request.callbackGasLimit, + estimatedTotalCostJuels: estimatedTotalCostJuels, + timeoutTimestamp: timeoutTimestamp, + requestId: requestId, + donFee: donFee, + gasOverheadBeforeCallback: config.gasOverheadBeforeCallback, + gasOverheadAfterCallback: config.gasOverheadAfterCallback + }); + + s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); + + return commitment; + } + + /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription + /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @param reportBatchSize the number of fulfillments in the transmitter's report + /// @return result fulfillment result + /// @dev Only callable by a node that has been approved on the Coordinator + /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request + function _fulfillAndBill( + bytes32 requestId, + bytes memory response, + bytes memory err, + bytes memory onchainMetadata, + bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, + uint8 reportBatchSize + ) internal returns (FunctionsResponse.FulfillResult) { + FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); + + uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; + uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize; + // Gas overhead without callback + uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); + uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); + + // The Functions Router will perform the callback to the client contract + (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( + response, + err, + juelsPerGas, + gasOverheadJuels + commitment.donFee, // cost without callback or admin fee, those will be added by the Router + msg.sender, + commitment + ); + + // The router will only pay the DON on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the Coordinator should hold on to the request commitment + if ( + resultCode == FunctionsResponse.FulfillResult.FULFILLED || + resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + delete s_requestCommitments[requestId]; + // Reimburse the transmitter for the fulfillment gas cost + s_withdrawableTokens[msg.sender] = gasOverheadJuels + callbackCostJuels; + // Put donFee into the pool of fees, to be split later + // Saves on storage writes that would otherwise be charged to the user + s_feePool += commitment.donFee; + emit RequestBilled({ + requestId: requestId, + juelsPerGas: juelsPerGas, + l1FeeShareWei: l1FeeShareWei, + callbackCostJuels: callbackCostJuels, + totalCostJuels: gasOverheadJuels + callbackCostJuels + commitment.donFee + commitment.adminFee + }); + } + + return resultCode; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Router + /// @dev Used by FunctionsRouter.sol during timeout of a request + function deleteCommitment(bytes32 requestId) external override onlyRouter { + // Delete commitment + delete s_requestCommitments[requestId]; + emit CommitmentDeleted(requestId); + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function oracleWithdraw(address recipient, uint96 amount) external { + _disperseFeePool(); + + if (amount == 0) { + amount = s_withdrawableTokens[msg.sender]; + } else if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); + } + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Coordinator owner + function oracleWithdrawAll() external { + _onlyOwner(); + _disperseFeePool(); + + address[] memory transmitters = _getTransmitters(); + + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < transmitters.length; ++i) { + uint96 balance = s_withdrawableTokens[transmitters[i]]; + if (balance > 0) { + s_withdrawableTokens[transmitters[i]] = 0; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); + } + } + } + + // Overriden in FunctionsCoordinator, which has visibility into transmitters + function _getTransmitters() internal view virtual returns (address[] memory); + + // DON fees are collected into a pool s_feePool + // When OCR configuration changes, or any oracle withdraws, this must be dispersed + function _disperseFeePool() internal { + if (s_feePool == 0) { + return; + } + // All transmitters are assumed to also be observers + // Pay out the DON fee to all transmitters + address[] memory transmitters = _getTransmitters(); + uint256 numberOfTransmitters = transmitters.length; + if (numberOfTransmitters == 0) { + revert NoTransmittersSet(); + } + uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < numberOfTransmitters; ++i) { + s_withdrawableTokens[transmitters[i]] += feePoolShare; + } + s_feePool -= feePoolShare * uint96(numberOfTransmitters); + } + + // Overriden in FunctionsCoordinator.sol + function _onlyOwner() internal view virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol new file mode 100644 index 0000000..188e217 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsCoordinator} from "../v1_0_0/interfaces/IFunctionsCoordinator.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {FunctionsBilling} from "./FunctionsBilling.sol"; +import {OCR2Base} from "./ocr/OCR2Base.sol"; +import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; + +/// @title Functions Coordinator contract +/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with +contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + /// @inheritdoc ITypeAndVersion + string public constant override typeAndVersion = "Functions Coordinator v1.1.0"; + + event OracleRequest( + bytes32 indexed requestId, + address indexed requestingContract, + address requestInitiator, + uint64 subscriptionId, + address subscriptionOwner, + bytes data, + uint16 dataVersion, + bytes32 flags, + uint64 callbackGasLimit, + FunctionsResponse.Commitment commitment + ); + event OracleResponse(bytes32 indexed requestId, address transmitter); + + error InconsistentReportData(); + error EmptyPublicKey(); + error UnauthorizedPublicKeyChange(); + + bytes private s_donPublicKey; + bytes private s_thresholdPublicKey; + + constructor( + address router, + Config memory config, + address linkToNativeFeed + ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed) {} + + /// @inheritdoc IFunctionsCoordinator + function getThresholdPublicKey() external view override returns (bytes memory) { + if (s_thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { + if (thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_thresholdPublicKey = thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function getDONPublicKey() external view override returns (bytes memory) { + if (s_donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_donPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { + if (donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_donPublicKey = donPublicKey; + } + + /// @dev check if node is in current transmitter list + function _isTransmitter(address node) internal view returns (bool) { + address[] memory nodes = s_transmitters; + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < nodes.length; ++i) { + if (nodes[i] == node) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsCoordinator + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { + commitment = _startBilling(request); + + emit OracleRequest( + commitment.requestId, + request.requestingContract, + // solhint-disable-next-line avoid-tx-origin + tx.origin, + request.subscriptionId, + request.subscriptionOwner, + request.data, + request.dataVersion, + request.flags, + request.callbackGasLimit, + commitment + ); + + return commitment; + } + + /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. + function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { + if (_getTransmitters().length > 0) { + _disperseFeePool(); + } + } + + /// @dev Used by FunctionsBilling.sol + function _getTransmitters() internal view override returns (address[] memory) { + return s_transmitters; + } + + /// @dev Report hook called within OCR2Base.sol + function _report( + uint256 /*initialGas*/, + address /*transmitter*/, + uint8 /*signerCount*/, + address[MAX_NUM_ORACLES] memory /*signers*/, + bytes calldata report + ) internal override { + ( + bytes32[] memory requestIds, + bytes[] memory results, + bytes[] memory errors, + bytes[] memory onchainMetadata, + bytes[] memory offchainMetadata + ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); + uint256 numberOfFulfillments = uint8(requestIds.length); + + if ( + numberOfFulfillments == 0 || + numberOfFulfillments != results.length || + numberOfFulfillments != errors.length || + numberOfFulfillments != onchainMetadata.length || + numberOfFulfillments != offchainMetadata.length + ) { + revert ReportInvalid("Fields must be equal length"); + } + + // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig + for (uint256 i = 0; i < numberOfFulfillments; ++i) { + FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( + _fulfillAndBill( + requestIds[i], + results[i], + errors[i], + onchainMetadata[i], + offchainMetadata[i], + uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig + ) + ); + + // Emit on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the DON will re-try + if ( + result == FunctionsResponse.FulfillResult.FULFILLED || + result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + emit OracleResponse(requestIds[i], msg.sender); + } + } + } + + /// @dev Used in FunctionsBilling.sol + function _onlyOwner() internal view override { + _validateOwnership(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol new file mode 100644 index 0000000..68d346e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +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"; + +/// @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); + + uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; + uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; + uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; + + // ------------ 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); + + uint256 private constant OP_MAINNET_CHAIN_ID = 10; + uint256 private constant OP_GOERLI_CHAIN_ID = 420; + uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; + + /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. + uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; + uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; + uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; + + // ------------ 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) { + uint256 chainid = block.chainid; + if (_isArbitrumChainId(chainid)) { + return ARBGAS.getCurrentTxL1GasFees(); + } else if (_isOptimismChainId(chainid)) { + return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); + } + return 0; + } + + /// @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. + function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == ARB_MAINNET_CHAIN_ID || + chainId == ARB_GOERLI_TESTNET_CHAIN_ID || + chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; + } + + /// @notice Return true if and only if the provided chain ID is an Optimism (or Base) chain ID. + /// @notice Note that optimism chain id's are also OP stack chain id's. + function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { + return + chainId == OP_MAINNET_CHAIN_ID || + chainId == OP_GOERLI_CHAIN_ID || + chainId == OP_SEPOLIA_CHAIN_ID || + chainId == BASE_MAINNET_CHAIN_ID || + chainId == BASE_GOERLI_CHAIN_ID || + chainId == BASE_SEPOLIA_CHAIN_ID; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol new file mode 100644 index 0000000..4182227 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + /** + * @notice optionally emited to indicate the latest configDigest and epoch for + which a report was successfully transmited. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol new file mode 100644 index 0000000..a4fd2bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/** + * @notice Onchain verification of reports from the offchain reporting protocol + * @dev For details on its operation, see the offchain reporting protocol design + * doc, which refers to this contract as simply the "contract". + */ +abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { + error ReportInvalid(string message); + error InvalidConfig(string message); + + constructor() ConfirmedOwner(msg.sender) {} + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems + // to extract config from logs. + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + mapping(address signerOrTransmitter => Oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + /* + * Config logic + */ + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + // solhint-disable-next-line gas-struct-packing + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param _signers addresses with which oracles sign the reports + * @param _transmitters addresses oracles use to transmit the reports + * @param _f number of faulty oracles the system can tolerate + * @param _onchainConfig encoded on-chain contract configuration + * @param _offchainConfigVersion version number for offchainEncoding schema + * @param _offchainConfig encoded off-chain oracle configuration + */ + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < args.signers.length; i++) { + if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); + if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signer/transmitter addresses + if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /** + * @return list of addresses permitted to transmit reports to this contract + * @dev The list will match the order used to specify the transmitter during setConfig + */ + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /** + * @dev hook called after the report has been fully validated + * for the extending contract to handle additional logic, such as oracle payment + * @param initialGas the amount of gas before validation + * @param transmitter the address of the account that submitted the report + * @param signers the addresses of all signing accounts + * @param report serialized report + */ + function _report( + uint256 initialGas, + address transmitter, + uint8 signerCount, + address[MAX_NUM_ORACLES] memory signers, + bytes calldata report + ) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function _requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); + } + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + uint256 initialGas = gasleft(); // This line must come first + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest + // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router + // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + _requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; + + if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); + if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); + + Oracle memory transmitter = s_oracles[msg.sender]; + if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) + revert ReportInvalid("unauthorized transmitter"); + } + + address[MAX_NUM_ORACLES] memory signed; + uint8 signerCount = 0; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); + if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); + signed[o.index] = signer; + signerCount += 1; + } + } + + _report(initialGas, msg.sender, signerCount, signed, report); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol new file mode 100644 index 0000000..49ecf3d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsSubscriptions} from "../v1_0_0/interfaces/IFunctionsSubscriptions.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {IFunctionsBilling, FunctionsBillingConfig} from "./interfaces/IFunctionsBilling.sol"; + +import {Routable} from "../v1_0_0/Routable.sol"; +import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; + +import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +import {ChainSpecificUtil} from "../v1_1_0/libraries/ChainSpecificUtil.sol"; + +/// @title Functions Billing contract +/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). +abstract contract FunctionsBilling is Routable, IFunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei + + event RequestBilled( + bytes32 indexed requestId, + uint96 juelsPerGas, + uint256 l1FeeShareWei, + uint96 callbackCostJuels, + uint72 donFeeJuels, + uint72 adminFeeJuels, + uint72 operationFeeJuels + ); + + // ================================================================ + // | Request Commitment state | + // ================================================================ + + mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; + + event CommitmentDeleted(bytes32 requestId); + + FunctionsBillingConfig private s_config; + + event ConfigUpdated(FunctionsBillingConfig config); + + error UnsupportedRequestDataVersion(); + error InsufficientBalance(); + error InvalidSubscription(); + error UnauthorizedSender(); + error MustBeSubOwner(address owner); + error InvalidLinkWeiPrice(int256 linkWei); + error InvalidUsdLinkPrice(int256 usdLink); + error PaymentTooLarge(); + error NoTransmittersSet(); + error InvalidCalldata(); + + // ================================================================ + // | Balance state | + // ================================================================ + + mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; + // Pool together collected DON fees + // Disperse them on withdrawal or change in OCR configuration + uint96 internal s_feePool; + + AggregatorV3Interface private s_linkToNativeFeed; + AggregatorV3Interface private s_linkToUsdFeed; + + // ================================================================ + // | Initialization | + // ================================================================ + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) Routable(router) { + s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); + s_linkToUsdFeed = AggregatorV3Interface(linkToUsdFeed); + + updateConfig(config); + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the Chainlink Coordinator's billing configuration + /// @return config + function getConfig() external view returns (FunctionsBillingConfig memory) { + return s_config; + } + + /// @notice Sets the Chainlink Coordinator's billing configuration + /// @param config - See the contents of the FunctionsBillingConfig struct in IFunctionsBilling.sol for more information + function updateConfig(FunctionsBillingConfig memory config) public { + _onlyOwner(); + + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Fee Calculation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function getDONFeeJuels(bytes memory /* requestData */) public view override returns (uint72) { + // s_config.donFee is in cents of USD. Get Juel amount then convert to dollars. + return SafeCast.toUint72(_getJuelsFromUsd(s_config.donFeeCentsUsd) / 100); + } + + /// @inheritdoc IFunctionsBilling + function getOperationFeeJuels() public view override returns (uint72) { + // s_config.donFee is in cents of USD. Get Juel amount then convert to dollars. + return SafeCast.toUint72(_getJuelsFromUsd(s_config.operationFeeCentsUsd) / 100); + } + + /// @inheritdoc IFunctionsBilling + function getAdminFeeJuels() public view override returns (uint72) { + return _getRouter().getAdminFee(); + } + + /// @inheritdoc IFunctionsBilling + function getWeiPerUnitLink() public view returns (uint256) { + (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { + return s_config.fallbackNativePerUnitLink; + } + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + return uint256(weiPerUnitLink); + } + + function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { + // (1e18 juels/link) * wei / (wei/link) = juels + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); + } + + /// @inheritdoc IFunctionsBilling + function getUsdPerUnitLink() public view returns (uint256, uint8) { + (, int256 usdPerUnitLink, , uint256 timestamp, ) = s_linkToUsdFeed.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { + return (s_config.fallbackUsdPerUnitLink, s_config.fallbackUsdPerUnitLinkDecimals); + } + if (usdPerUnitLink <= 0) { + revert InvalidUsdLinkPrice(usdPerUnitLink); + } + return (uint256(usdPerUnitLink), s_linkToUsdFeed.decimals()); + } + + function _getJuelsFromUsd(uint256 amountUsd) private view returns (uint96) { + (uint256 usdPerLink, uint8 decimals) = getUsdPerUnitLink(); + // (usd) * (10**18 juels/link) * (10**decimals) / (link / usd) = juels + // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) + return SafeCast.toUint96((amountUsd * 10 ** (18 + decimals)) / usdPerLink); + } + + // ================================================================ + // | Cost Estimation | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view override returns (uint96) { + _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); + // Reasonable ceilings to prevent integer overflows + if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { + revert InvalidCalldata(); + } + uint72 adminFee = getAdminFeeJuels(); + uint72 donFee = getDONFeeJuels(data); + uint72 operationFee = getOperationFeeJuels(); + return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); + } + + /// @notice Estimate the cost in Juels of LINK + // that will be charged to a subscription to fulfill a Functions request + // Gas Price can be overestimated to account for flucuations between request and response time + function _calculateCostEstimate( + uint32 callbackGasLimit, + uint256 gasPriceWei, + uint72 donFeeJuels, + uint72 adminFeeJuels, + uint72 operationFeeJuels + ) internal view returns (uint96) { + // If gas price is less than the minimum fulfillment gas price, override to using the minimum + if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { + 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); + + uint96 feesJuels = uint96(donFeeJuels) + uint96(adminFeeJuels) + uint96(operationFeeJuels); + + return estimatedGasReimbursementJuels + feesJuels; + } + + // ================================================================ + // | Billing | + // ================================================================ + + /// @notice Initiate the billing process for an Functions request + /// @dev Only callable by the Functions Router + /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure + /// @return commitment - The parameters of the request that must be held consistent at response time + function _startBilling( + FunctionsResponse.RequestMeta memory request + ) internal returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { + // Nodes should support all past versions of the structure + if (request.dataVersion > s_config.maxSupportedRequestDataVersion) { + revert UnsupportedRequestDataVersion(); + } + + uint72 donFee = getDONFeeJuels(request.data); + operationFee = getOperationFeeJuels(); + uint96 estimatedTotalCostJuels = _calculateCostEstimate( + request.callbackGasLimit, + tx.gasprice, + donFee, + request.adminFee, + operationFee + ); + + // Check that subscription can afford the estimated cost + if ((request.availableBalance) < estimatedTotalCostJuels) { + revert InsufficientBalance(); + } + + uint32 timeoutTimestamp = uint32(block.timestamp + s_config.requestTimeoutSeconds); + bytes32 requestId = keccak256( + abi.encode( + address(this), + request.requestingContract, + request.subscriptionId, + request.initiatedRequests + 1, + keccak256(request.data), + request.dataVersion, + request.callbackGasLimit, + estimatedTotalCostJuels, + timeoutTimestamp, + // solhint-disable-next-line avoid-tx-origin + tx.origin + ) + ); + + commitment = FunctionsResponse.Commitment({ + adminFee: request.adminFee, + coordinator: address(this), + client: request.requestingContract, + subscriptionId: request.subscriptionId, + callbackGasLimit: request.callbackGasLimit, + estimatedTotalCostJuels: estimatedTotalCostJuels, + timeoutTimestamp: timeoutTimestamp, + requestId: requestId, + donFee: donFee, + gasOverheadBeforeCallback: s_config.gasOverheadBeforeCallback, + gasOverheadAfterCallback: s_config.gasOverheadAfterCallback + }); + + s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); + + return (commitment, operationFee); + } + + /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription + /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment + /// @param response response data from DON consensus + /// @param err error from DON consensus + /// @param reportBatchSize the number of fulfillments in the transmitter's report + /// @return result fulfillment result + /// @dev Only callable by a node that has been approved on the Coordinator + /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request + function _fulfillAndBill( + bytes32 requestId, + bytes memory response, + bytes memory err, + bytes memory onchainMetadata, + bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, + uint8 reportBatchSize + ) internal returns (FunctionsResponse.FulfillResult) { + FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); + + uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; + uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize; + // Gas overhead without callback + uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); + uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); + + // The Functions Router will perform the callback to the client contract + (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( + response, + err, + juelsPerGas, + // The following line represents: "cost without callback or admin fee, those will be added by the Router" + // But because the _offchain_ Commitment is using operation fee in the place of the admin fee, this now adds admin fee (actually operation fee) + // Admin fee is configured to 0 in the Router + gasOverheadJuels + commitment.donFee + commitment.adminFee, + msg.sender, + FunctionsResponse.Commitment({ + adminFee: 0, // The Router should have adminFee set to 0. If it does not this will cause fulfillments to fail with INVALID_COMMITMENT instead of carrying out incorrect bookkeeping. + coordinator: commitment.coordinator, + client: commitment.client, + subscriptionId: commitment.subscriptionId, + callbackGasLimit: commitment.callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback + }) + ); + + // The router will only pay the DON on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the Coordinator should hold on to the request commitment + if ( + resultCode == FunctionsResponse.FulfillResult.FULFILLED || + resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + delete s_requestCommitments[requestId]; + // Reimburse the transmitter for the fulfillment gas cost + s_withdrawableTokens[msg.sender] += gasOverheadJuels + callbackCostJuels; + // Put donFee into the pool of fees, to be split later + // Saves on storage writes that would otherwise be charged to the user + s_feePool += commitment.donFee; + // Pay the operation fee to the Coordinator owner + s_withdrawableTokens[_owner()] += commitment.adminFee; // OperationFee is used in the slot for Admin Fee in the Offchain Commitment. Admin Fee is set to 0 in the Router (enforced by line 316 in FunctionsBilling.sol). + emit RequestBilled({ + requestId: requestId, + juelsPerGas: juelsPerGas, + l1FeeShareWei: l1FeeShareWei, + callbackCostJuels: callbackCostJuels, + donFeeJuels: commitment.donFee, + // The following two lines are because of OperationFee being used in the Offchain Commitment + adminFeeJuels: 0, + operationFeeJuels: commitment.adminFee + }); + } + return resultCode; + } + + // ================================================================ + // | Request Timeout | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Router + /// @dev Used by FunctionsRouter.sol during timeout of a request + function deleteCommitment(bytes32 requestId) external override onlyRouter { + // Delete commitment + delete s_requestCommitments[requestId]; + emit CommitmentDeleted(requestId); + } + + // ================================================================ + // | Fund withdrawal | + // ================================================================ + + /// @inheritdoc IFunctionsBilling + function oracleWithdraw(address recipient, uint96 amount) external { + _disperseFeePool(); + + if (amount == 0) { + amount = s_withdrawableTokens[msg.sender]; + } else if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); + } + + /// @inheritdoc IFunctionsBilling + /// @dev Only callable by the Coordinator owner + function oracleWithdrawAll() external { + _onlyOwner(); + _disperseFeePool(); + + address[] memory transmitters = _getTransmitters(); + + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < transmitters.length; ++i) { + uint96 balance = s_withdrawableTokens[transmitters[i]]; + if (balance > 0) { + s_withdrawableTokens[transmitters[i]] = 0; + IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); + } + } + } + + // Overriden in FunctionsCoordinator, which has visibility into transmitters + function _getTransmitters() internal view virtual returns (address[] memory); + + // DON fees are collected into a pool s_feePool + // When OCR configuration changes, or any oracle withdraws, this must be dispersed + function _disperseFeePool() internal { + if (s_feePool == 0) { + return; + } + // All transmitters are assumed to also be observers + // Pay out the DON fee to all transmitters + address[] memory transmitters = _getTransmitters(); + uint256 numberOfTransmitters = transmitters.length; + if (numberOfTransmitters == 0) { + revert NoTransmittersSet(); + } + uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < numberOfTransmitters; ++i) { + s_withdrawableTokens[transmitters[i]] += feePoolShare; + } + s_feePool -= feePoolShare * uint96(numberOfTransmitters); + } + + // Overriden in FunctionsCoordinator.sol + function _onlyOwner() internal view virtual; + + // Used in FunctionsCoordinator.sol + function _isExistingRequest(bytes32 requestId) internal view returns (bool) { + return s_requestCommitments[requestId] != bytes32(0); + } + + // Overriden in FunctionsCoordinator.sol + function _owner() internal view virtual returns (address owner); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol new file mode 100644 index 0000000..84b6414 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsRouter} from "../v1_0_0/interfaces/IFunctionsRouter.sol"; +import {IFunctionsClient} from "../v1_0_0/interfaces/IFunctionsClient.sol"; + +import {FunctionsRequest} from "../v1_0_0/libraries/FunctionsRequest.sol"; + +/// @title The Chainlink Functions client contract +/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests +abstract contract FunctionsClient is IFunctionsClient { + using FunctionsRequest for FunctionsRequest.Request; + + IFunctionsRouter internal immutable i_functionsRouter; + + event RequestSent(bytes32 indexed id); + event RequestFulfilled(bytes32 indexed id); + + error OnlyRouterCanFulfill(); + + constructor(address router) { + i_functionsRouter = IFunctionsRouter(router); + } + + /// @notice Sends a Chainlink Functions request + /// @param data The CBOR encoded bytes data for a Functions request + /// @param subscriptionId The subscription ID that will be charged to service the request + /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback + /// @return requestId The generated request ID for this request + function _sendRequest( + bytes memory data, + uint64 subscriptionId, + uint32 callbackGasLimit, + bytes32 donId + ) internal returns (bytes32) { + bytes32 requestId = i_functionsRouter.sendRequest( + subscriptionId, + data, + FunctionsRequest.REQUEST_DATA_VERSION, + callbackGasLimit, + donId + ); + emit RequestSent(requestId); + return requestId; + } + + /// @notice User defined function to handle a response from the DON + /// @param requestId The request ID, returned by sendRequest() + /// @param response Aggregated response from the execution of the user's source code + /// @param err Aggregated error from the execution of the user code or from the execution pipeline + /// @dev Either response or error parameter will be set, but never both + function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; + + /// @inheritdoc IFunctionsClient + function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { + if (msg.sender != address(i_functionsRouter)) { + revert OnlyRouterCanFulfill(); + } + _fulfillRequest(requestId, response, err); + emit RequestFulfilled(requestId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol new file mode 100644 index 0000000..9c7f359 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IFunctionsCoordinator} from "../v1_0_0/interfaces/IFunctionsCoordinator.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +import {FunctionsBilling, FunctionsBillingConfig} from "./FunctionsBilling.sol"; +import {OCR2Base} from "./ocr/OCR2Base.sol"; +import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; + +/// @title Functions Coordinator contract +/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with +contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { + using FunctionsResponse for FunctionsResponse.RequestMeta; + using FunctionsResponse for FunctionsResponse.Commitment; + using FunctionsResponse for FunctionsResponse.FulfillResult; + + /// @inheritdoc ITypeAndVersion + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "Functions Coordinator v1.3.0"; + + event OracleRequest( + bytes32 indexed requestId, + address indexed requestingContract, + address requestInitiator, + uint64 subscriptionId, + address subscriptionOwner, + bytes data, + uint16 dataVersion, + bytes32 flags, + uint64 callbackGasLimit, + FunctionsResponse.Commitment commitment + ); + event OracleResponse(bytes32 indexed requestId, address transmitter); + + error InconsistentReportData(); + error EmptyPublicKey(); + error UnauthorizedPublicKeyChange(); + + bytes private s_donPublicKey; + bytes private s_thresholdPublicKey; + + constructor( + address router, + FunctionsBillingConfig memory config, + address linkToNativeFeed, + address linkToUsdFeed + ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed, linkToUsdFeed) {} + + /// @inheritdoc IFunctionsCoordinator + function getThresholdPublicKey() external view override returns (bytes memory) { + if (s_thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { + if (thresholdPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_thresholdPublicKey = thresholdPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function getDONPublicKey() external view override returns (bytes memory) { + if (s_donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + return s_donPublicKey; + } + + /// @inheritdoc IFunctionsCoordinator + function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { + if (donPublicKey.length == 0) { + revert EmptyPublicKey(); + } + s_donPublicKey = donPublicKey; + } + + /// @dev check if node is in current transmitter list + function _isTransmitter(address node) internal view returns (bool) { + // Bounded by "maxNumOracles" on OCR2Abstract.sol + for (uint256 i = 0; i < s_transmitters.length; ++i) { + if (s_transmitters[i] == node) { + return true; + } + } + return false; + } + + /// @inheritdoc IFunctionsCoordinator + function startRequest( + FunctionsResponse.RequestMeta calldata request + ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { + uint72 operationFee; + (commitment, operationFee) = _startBilling(request); + + emit OracleRequest( + commitment.requestId, + request.requestingContract, + // solhint-disable-next-line avoid-tx-origin + tx.origin, + request.subscriptionId, + request.subscriptionOwner, + request.data, + request.dataVersion, + request.flags, + request.callbackGasLimit, + FunctionsResponse.Commitment({ + coordinator: commitment.coordinator, + client: commitment.client, + subscriptionId: commitment.subscriptionId, + callbackGasLimit: commitment.callbackGasLimit, + estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, + timeoutTimestamp: commitment.timeoutTimestamp, + requestId: commitment.requestId, + donFee: commitment.donFee, + gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, + gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, + // The following line is done to use the Coordinator's operationFee in place of the Router's operation fee + // With this in place the Router.adminFee must be set to 0 in the Router. + adminFee: operationFee + }) + ); + + return commitment; + } + + /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. + function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { + if (_getTransmitters().length > 0) { + _disperseFeePool(); + } + } + + /// @dev Used by FunctionsBilling.sol + function _getTransmitters() internal view override returns (address[] memory) { + return s_transmitters; + } + + function _beforeTransmit( + bytes calldata report + ) internal view override returns (bool shouldStop, DecodedReport memory decodedReport) { + ( + bytes32[] memory requestIds, + bytes[] memory results, + bytes[] memory errors, + bytes[] memory onchainMetadata, + bytes[] memory offchainMetadata + ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); + uint256 numberOfFulfillments = uint8(requestIds.length); + + if ( + numberOfFulfillments == 0 || + numberOfFulfillments != results.length || + numberOfFulfillments != errors.length || + numberOfFulfillments != onchainMetadata.length || + numberOfFulfillments != offchainMetadata.length + ) { + revert ReportInvalid("Fields must be equal length"); + } + + for (uint256 i = 0; i < numberOfFulfillments; ++i) { + if (_isExistingRequest(requestIds[i])) { + // If there is an existing request, validate report + // Leave shouldStop to default, false + break; + } + if (i == numberOfFulfillments - 1) { + // If the last fulfillment on the report does not exist, then all are duplicates + // Indicate that it's safe to stop to save on the gas of validating the report + shouldStop = true; + } + } + + return ( + shouldStop, + DecodedReport({ + requestIds: requestIds, + results: results, + errors: errors, + onchainMetadata: onchainMetadata, + offchainMetadata: offchainMetadata + }) + ); + } + + /// @dev Report hook called within OCR2Base.sol + function _report(DecodedReport memory decodedReport) internal override { + uint256 numberOfFulfillments = uint8(decodedReport.requestIds.length); + + // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig + for (uint256 i = 0; i < numberOfFulfillments; ++i) { + FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( + _fulfillAndBill( + decodedReport.requestIds[i], + decodedReport.results[i], + decodedReport.errors[i], + decodedReport.onchainMetadata[i], + decodedReport.offchainMetadata[i], + uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig + ) + ); + + // Emit on successfully processing the fulfillment + // In these two fulfillment results the user has been charged + // Otherwise, the DON will re-try + if ( + result == FunctionsResponse.FulfillResult.FULFILLED || + result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR + ) { + emit OracleResponse(decodedReport.requestIds[i], msg.sender); + } + } + } + + /// @dev Used in FunctionsBilling.sol + function _onlyOwner() internal view override { + _validateOwnership(); + } + + /// @dev Used in FunctionsBilling.sol + function _owner() internal view override returns (address owner) { + return this.owner(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol new file mode 100644 index 0000000..1d9a3b9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITermsOfServiceAllowList, TermsOfServiceAllowListConfig} from "./interfaces/ITermsOfServiceAllowList.sol"; +import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; + +import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { + using Address for address; + using EnumerableSet for EnumerableSet.AddressSet; + + /// @inheritdoc ITypeAndVersion + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.0"; + + EnumerableSet.AddressSet private s_allowedSenders; + EnumerableSet.AddressSet private s_blockedSenders; + + event AddedAccess(address user); + event BlockedAccess(address user); + event UnblockedAccess(address user); + + error InvalidSignature(); + error InvalidUsage(); + error RecipientIsBlocked(); + error InvalidCalldata(); + + TermsOfServiceAllowListConfig private s_config; + + event ConfigUpdated(TermsOfServiceAllowListConfig config); + + // ================================================================ + // | Initialization | + // ================================================================ + + constructor( + TermsOfServiceAllowListConfig memory config, + address[] memory initialAllowedSenders, + address[] memory initialBlockedSenders + ) ConfirmedOwner(msg.sender) { + updateConfig(config); + + for (uint256 i = 0; i < initialAllowedSenders.length; ++i) { + s_allowedSenders.add(initialAllowedSenders[i]); + } + + for (uint256 j = 0; j < initialBlockedSenders.length; ++j) { + if (s_allowedSenders.contains(initialBlockedSenders[j])) { + // Allowed senders cannot also be blocked + revert InvalidCalldata(); + } + s_blockedSenders.add(initialBlockedSenders[j]); + } + } + + // ================================================================ + // | Configuration | + // ================================================================ + + /// @notice Gets the contracts's configuration + /// @return config + function getConfig() external view returns (TermsOfServiceAllowListConfig memory) { + return s_config; + } + + /// @notice Sets the contracts's configuration + /// @param config - See the contents of the TermsOfServiceAllowListConfig struct in ITermsOfServiceAllowList.sol for more information + function updateConfig(TermsOfServiceAllowListConfig memory config) public onlyOwner { + s_config = config; + emit ConfigUpdated(config); + } + + // ================================================================ + // | Allow methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { + return keccak256(abi.encodePacked(acceptor, recipient)); + } + + /// @inheritdoc ITermsOfServiceAllowList + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { + if (s_blockedSenders.contains(recipient)) { + revert RecipientIsBlocked(); + } + + // Validate that the signature is correct and the correct data has been signed + bytes32 prefixedMessage = keccak256( + abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) + ); + if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { + revert InvalidSignature(); + } + + // If contract, validate that msg.sender == recipient + // This is to prevent EoAs from claiming contracts that they are not in control of + // If EoA, validate that msg.sender == acceptor == recipient + // This is to prevent EoAs from accepting for other EoAs + if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { + revert InvalidUsage(); + } + + // Add recipient to the allow list + if (s_allowedSenders.add(recipient)) { + emit AddedAccess(recipient); + } + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllAllowedSenders() external view override returns (address[] memory) { + return s_allowedSenders.values(); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllowedSendersCount() external view override returns (uint64) { + return uint64(s_allowedSenders.length()); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getAllowedSendersInRange( + uint64 allowedSenderIdxStart, + uint64 allowedSenderIdxEnd + ) external view override returns (address[] memory allowedSenders) { + if ( + allowedSenderIdxStart > allowedSenderIdxEnd || + allowedSenderIdxEnd >= s_allowedSenders.length() || + s_allowedSenders.length() == 0 + ) { + revert InvalidCalldata(); + } + + allowedSenders = new address[]((allowedSenderIdxEnd - allowedSenderIdxStart) + 1); + for (uint256 i = 0; i <= allowedSenderIdxEnd - allowedSenderIdxStart; ++i) { + allowedSenders[i] = s_allowedSenders.at(uint256(allowedSenderIdxStart + i)); + } + + return allowedSenders; + } + + /// @inheritdoc IAccessController + function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { + if (!s_config.enabled) { + return true; + } + return s_allowedSenders.contains(user); + } + + // ================================================================ + // | Block methods | + // ================================================================ + + /// @inheritdoc ITermsOfServiceAllowList + function isBlockedSender(address sender) external view override returns (bool) { + if (!s_config.enabled) { + return false; + } + return s_blockedSenders.contains(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function blockSender(address sender) external override onlyOwner { + s_allowedSenders.remove(sender); + s_blockedSenders.add(sender); + emit BlockedAccess(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function unblockSender(address sender) external override onlyOwner { + s_blockedSenders.remove(sender); + emit UnblockedAccess(sender); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getBlockedSendersCount() external view override returns (uint64) { + return uint64(s_blockedSenders.length()); + } + + /// @inheritdoc ITermsOfServiceAllowList + function getBlockedSendersInRange( + uint64 blockedSenderIdxStart, + uint64 blockedSenderIdxEnd + ) external view override returns (address[] memory blockedSenders) { + if ( + blockedSenderIdxStart > blockedSenderIdxEnd || + blockedSenderIdxEnd >= s_blockedSenders.length() || + s_blockedSenders.length() == 0 + ) { + revert InvalidCalldata(); + } + + blockedSenders = new address[]((blockedSenderIdxEnd - blockedSenderIdxStart) + 1); + for (uint256 i = 0; i <= blockedSenderIdxEnd - blockedSenderIdxStart; ++i) { + blockedSenders[i] = s_blockedSenders.at(uint256(blockedSenderIdxStart + i)); + } + + return blockedSenders; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol new file mode 100644 index 0000000..65db9c4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service +interface ITermsOfServiceAllowList { + /// @notice Return the message data for the proof given to accept the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @return Hash of the message data + function getMessage(address acceptor, address recipient) external pure returns (bytes32); + + /// @notice Check if the address is blocked for usage + /// @param sender The transaction sender's address + /// @return True or false + function isBlockedSender(address sender) external returns (bool); + + /// @notice Get a list of all allowed senders + /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + /// this function has an unbounded cost, and using it as part of a state-changing function may render the function + /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + /// @return addresses - all allowed addresses + function getAllAllowedSenders() external view returns (address[] memory); + + /// @notice Get details about the total number of allowed senders + /// @return count - total number of allowed senders in the system + function getAllowedSendersCount() external view returns (uint64); + + /// @notice Retrieve a list of allowed senders using an inclusive range + /// @dev WARNING: getAllowedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list + /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. + /// Evaluate if eventual consistency will satisfy your usecase before using it. + /// @param allowedSenderIdxStart - index of the allowed sender to start the range at + /// @param allowedSenderIdxEnd - index of the allowed sender to end the range at + /// @return allowedSenders - allowed addresses in the range provided + function getAllowedSendersInRange( + uint64 allowedSenderIdxStart, + uint64 allowedSenderIdxEnd + ) external view returns (address[] memory allowedSenders); + + /// @notice Allows access to the sender based on acceptance of the Terms of Service + /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI + /// @param recipient - The recipient address that the acceptor is taking responsibility for + /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI + /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI + /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI + function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; + + /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service + /// @param sender - Address of the sender to block + function blockSender(address sender) external; + + /// @notice Re-allows a previously blocked sender to accept the Terms of Service + /// @param sender - Address of the sender to unblock + function unblockSender(address sender) external; + + /// @notice Get details about the total number of blocked senders + /// @return count - total number of blocked senders in the system + function getBlockedSendersCount() external view returns (uint64); + + /// @notice Retrieve a list of blocked senders using an inclusive range + /// @dev WARNING: getBlockedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list + /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. + /// Evaluate if eventual consistency will satisfy your usecase before using it. + /// @param blockedSenderIdxStart - index of the blocked sender to start the range at + /// @param blockedSenderIdxEnd - index of the blocked sender to end the range at + /// @return blockedSenders - blocked addresses in the range provided + function getBlockedSendersInRange( + uint64 blockedSenderIdxStart, + uint64 blockedSenderIdxEnd + ) external view returns (address[] memory blockedSenders); +} + +// ================================================================ +// | Configuration state | +// ================================================================ +struct TermsOfServiceAllowListConfig { + bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. + address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol new file mode 100644 index 0000000..79806f1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @title Chainlink Functions DON billing interface. +interface IFunctionsBilling { + /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed + /// @return weiPerUnitLink - The amount of WEI in one LINK + function getWeiPerUnitLink() external view returns (uint256); + + /// @notice Return the current conversion from LINK to USD from the configured Chainlink data feed + /// @return weiPerUnitLink - The amount of USD that one LINK is worth + /// @return decimals - The number of decimals that should be represented in the price feed's response + function getUsdPerUnitLink() external view returns (uint256, uint8); + + /// @notice Determine the fee that will be split between Node Operators for servicing a request + /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request + /// @return fee - Cost in Juels (1e18) of LINK + function getDONFeeJuels(bytes memory requestCBOR) external view returns (uint72); + + /// @notice Determine the fee that will be paid to the Coordinator owner for operating the network + /// @return fee - Cost in Juels (1e18) of LINK + function getOperationFeeJuels() external view returns (uint72); + + /// @notice Determine the fee that will be paid to the Router owner for operating the network + /// @return fee - Cost in Juels (1e18) of LINK + function getAdminFeeJuels() external view returns (uint72); + + /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee + /// @param - subscriptionId An identifier of the billing account + /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request + /// @param - callbackGasLimit Gas limit for the fulfillment callback + /// @param - gasPriceWei The blockchain's gas price to estimate with + /// @return - billedCost Cost in Juels (1e18) of LINK + function estimateCost( + uint64 subscriptionId, + bytes calldata data, + uint32 callbackGasLimit, + uint256 gasPriceWei + ) external view returns (uint96); + + /// @notice Remove a request commitment that the Router has determined to be stale + /// @param requestId - The request ID to remove + function deleteCommitment(bytes32 requestId) external; + + /// @notice Oracle withdraw LINK earned through fulfilling requests + /// @notice If amount is 0 the full balance will be withdrawn + /// @param recipient where to send the funds + /// @param amount amount to withdraw + function oracleWithdraw(address recipient, uint96 amount) external; + + /// @notice Withdraw all LINK earned by Oracles through fulfilling requests + /// @dev transmitter addresses must support LINK tokens to avoid tokens from getting stuck as oracleWithdrawAll() calls will forward tokens directly to transmitters + function oracleWithdrawAll() external; +} + +// ================================================================ +// | Configuration state | +// ================================================================ + +struct FunctionsBillingConfig { + uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) + uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. + uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. + uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. + uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request + uint16 maxSupportedRequestDataVersion; // ║ The highest support request data version supported by the node. All lower versions should also be supported. + uint64 fallbackUsdPerUnitLink; // ║ Fallback LINK / USD conversion rate if the data feed is stale + uint8 fallbackUsdPerUnitLinkDecimals; // ════════╝ Fallback LINK / USD conversion rate decimal places if the data feed is stale + 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. +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol new file mode 100644 index 0000000..4182227 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + /** + * @notice optionally emited to indicate the latest configDigest and epoch for + which a report was successfully transmited. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol new file mode 100644 index 0000000..565e7d8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/** + * @notice Onchain verification of reports from the offchain reporting protocol + * @dev For details on its operation, see the offchain reporting protocol design + * doc, which refers to this contract as simply the "contract". + */ +abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { + error ReportInvalid(string message); + error InvalidConfig(string message); + + constructor() ConfirmedOwner(msg.sender) {} + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems + // to extract config from logs. + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + mapping(address signerOrTransmitter => Oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + struct DecodedReport { + bytes32[] requestIds; + bytes[] results; + bytes[] errors; + bytes[] onchainMetadata; + bytes[] offchainMetadata; + } + + /* + * Config logic + */ + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + // solhint-disable-next-line gas-struct-packing + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param _signers addresses with which oracles sign the reports + * @param _transmitters addresses oracles use to transmit the reports + * @param _f number of faulty oracles the system can tolerate + * @param _onchainConfig encoded on-chain contract configuration + * @param _offchainConfigVersion version number for offchainEncoding schema + * @param _offchainConfig encoded off-chain oracle configuration + */ + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < args.signers.length; i++) { + if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); + if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signer/transmitter addresses + if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /** + * @return list of addresses permitted to transmit reports to this contract + * @dev The list will match the order used to specify the transmitter during setConfig + */ + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /** + * @dev hook called after the report has been fully validated + * for the extending contract to handle additional logic, such as oracle payment + * @param decodedReport decodedReport + */ + function _report(DecodedReport memory decodedReport) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function _requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); + } + + function _beforeTransmit( + bytes calldata report + ) internal virtual returns (bool shouldStop, DecodedReport memory decodedReport); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + (bool shouldStop, DecodedReport memory decodedReport) = _beforeTransmit(report); + + if (shouldStop) { + return; + } + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest + // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router + // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + _requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; + + if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); + if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); + + Oracle memory transmitter = s_oracles[msg.sender]; + if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) + revert ReportInvalid("unauthorized transmitter"); + } + + address[MAX_NUM_ORACLES] memory signed; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); + if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); + signed[o.index] = signer; + } + } + + _report(decodedReport); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol new file mode 100644 index 0000000..5ee9cbb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface ChainlinkRequestInterface { + function oracleRequest( + address sender, + uint256 requestPrice, + bytes32 serviceAgreementID, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 nonce, + uint256 dataVersion, + bytes calldata data + ) external; + + function cancelOracleRequest( + bytes32 requestId, + uint256 payment, + bytes4 callbackFunctionId, + uint256 expiration + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol new file mode 100644 index 0000000..2592b69 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface ENSInterface { + // Logged when the owner of a node assigns a new owner to a subnode. + event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); + + // Logged when the owner of a node transfers ownership to a new account. + event Transfer(bytes32 indexed node, address owner); + + // Logged when the resolver for a node changes. + event NewResolver(bytes32 indexed node, address resolver); + + // Logged when the TTL of a node changes + event NewTTL(bytes32 indexed node, uint64 ttl); + + function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external; + + function setResolver(bytes32 node, address resolver) external; + + function setOwner(bytes32 node, address owner) external; + + function setTTL(bytes32 node, uint64 ttl) external; + + function owner(bytes32 node) external view returns (address); + + function resolver(bytes32 node) external view returns (address); + + function ttl(bytes32 node) external view returns (uint64); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol new file mode 100644 index 0000000..6e353a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; +pragma abicoder v2; + +import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; + +// solhint-disable-next-line interface-starts-with-i +interface FeedRegistryInterface { + struct Phase { + uint16 phaseId; + uint80 startingAggregatorRoundId; + uint80 endingAggregatorRoundId; + } + + event FeedProposed( + address indexed asset, + address indexed denomination, + address indexed proposedAggregator, + address currentAggregator, + address sender + ); + event FeedConfirmed( + address indexed asset, + address indexed denomination, + address indexed latestAggregator, + address previousAggregator, + uint16 nextPhaseId, + address sender + ); + + // V3 AggregatorV3Interface + + function decimals(address base, address quote) external view returns (uint8); + + function description(address base, address quote) external view returns (string memory); + + function version(address base, address quote) external view returns (uint256); + + function latestRoundData( + address base, + address quote + ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + function getRoundData( + address base, + address quote, + uint80 _roundId + ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + // V2 AggregatorInterface + + function latestAnswer(address base, address quote) external view returns (int256 answer); + + function latestTimestamp(address base, address quote) external view returns (uint256 timestamp); + + function latestRound(address base, address quote) external view returns (uint256 roundId); + + function getAnswer(address base, address quote, uint256 roundId) external view returns (int256 answer); + + function getTimestamp(address base, address quote, uint256 roundId) external view returns (uint256 timestamp); + + // Registry getters + + function getFeed(address base, address quote) external view returns (AggregatorV2V3Interface aggregator); + + function getPhaseFeed( + address base, + address quote, + uint16 phaseId + ) external view returns (AggregatorV2V3Interface aggregator); + + function isFeedEnabled(address aggregator) external view returns (bool); + + function getPhase(address base, address quote, uint16 phaseId) external view returns (Phase memory phase); + + // Round helpers + + function getRoundFeed( + address base, + address quote, + uint80 roundId + ) external view returns (AggregatorV2V3Interface aggregator); + + function getPhaseRange( + address base, + address quote, + uint16 phaseId + ) external view returns (uint80 startingRoundId, uint80 endingRoundId); + + function getPreviousRoundId( + address base, + address quote, + uint80 roundId + ) external view returns (uint80 previousRoundId); + + function getNextRoundId(address base, address quote, uint80 roundId) external view returns (uint80 nextRoundId); + + // Feed management + + function proposeFeed(address base, address quote, address aggregator) external; + + function confirmFeed(address base, address quote, address aggregator) external; + + // Proposed aggregator + + function getProposedFeed( + address base, + address quote + ) external view returns (AggregatorV2V3Interface proposedAggregator); + + function proposedGetRoundData( + address base, + address quote, + uint80 roundId + ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + function proposedLatestRoundData( + address base, + address quote + ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + // Phases + function getCurrentPhaseId(address base, address quote) external view returns (uint16 currentPhaseId); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol new file mode 100644 index 0000000..beb2b58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface FlagsInterface { + function getFlag(address) external view returns (bool); + + function getFlags(address[] calldata) external view returns (bool[] memory); + + function raiseFlag(address) external; + + function raiseFlags(address[] calldata) external; + + function lowerFlags(address[] calldata) external; + + function setRaisingAccessController(address) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol new file mode 100644 index 0000000..b457a50 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {OracleInterface} from "./OracleInterface.sol"; +import {ChainlinkRequestInterface} from "./ChainlinkRequestInterface.sol"; + +// solhint-disable-next-line interface-starts-with-i +interface OperatorInterface is OracleInterface, ChainlinkRequestInterface { + function operatorRequest( + address sender, + uint256 payment, + bytes32 specId, + bytes4 callbackFunctionId, + uint256 nonce, + uint256 dataVersion, + bytes calldata data + ) external; + + function fulfillOracleRequest2( + bytes32 requestId, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration, + bytes calldata data + ) external returns (bool); + + function ownerTransferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); + + function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol new file mode 100644 index 0000000..6e7aa29 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface OracleInterface { + function fulfillOracleRequest( + bytes32 requestId, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration, + bytes32 data + ) external returns (bool); + + function withdraw(address recipient, uint256 amount) external; + + function withdrawable() external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol new file mode 100644 index 0000000..af06e29 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @title Chainlink Proof-of-Reserve address list interface. + * @notice This interface enables Chainlink nodes to get the list addresses to be used in a PoR feed. A single + * contract that implements this interface can only store an address list for a single PoR feed. + * @dev All functions in this interface are expected to be called off-chain, so gas usage is not a big concern. + * This makes it possible to store addresses in optimized data types and convert them to human-readable strings + * in `getPoRAddressList()`. + */ +// solhint-disable-next-line interface-starts-with-i +interface PoRAddressList { + /// @notice Get total number of addresses in the list. + function getPoRAddressListLength() external view returns (uint256); + + /** + * @notice Get a batch of human-readable addresses from the address list. The requested batch size can be greater + * than the actual address list size, in which the full address list will be returned. + * @dev Due to limitations of gas usage in off-chain calls, we need to support fetching the addresses in batches. + * EVM addresses need to be converted to human-readable strings. The address strings need to be in the same format + * that would be used when querying the balance of that address. + * @param startIndex The index of the first address in the batch. + * @param endIndex The index of the last address in the batch. If `endIndex > getPoRAddressListLength()-1`, + * endIndex need to default to `getPoRAddressListLength()-1`. + * @return Array of addresses as strings. + */ + function getPoRAddressList(uint256 startIndex, uint256 endIndex) external view returns (string[] memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol new file mode 100644 index 0000000..ca0b1de --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface PointerInterface { + function getAddress() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol new file mode 100644 index 0000000..786f275 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +abstract contract TypeAndVersionInterface { + function typeAndVersion() external pure virtual returns (string memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol new file mode 100644 index 0000000..2e9211f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol @@ -0,0 +1,1055 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; + +/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node Operators), Capabilities, +/// and DONs (Decentralized Oracle Networks) which are sets of nodes that support those Capabilities. +/// @dev The contract currently stores the entire state of Node Operators, Nodes, Capabilities and DONs in the +/// contract and requires a full state migration if an upgrade is ever required. The team acknowledges this and is +/// fine reconfiguring the upgraded contract in the future so as to not add extra complexity to this current version. +contract CapabilitiesRegistry is OwnerIsCreator, ITypeAndVersion { + // Add the library methods + using EnumerableSet for EnumerableSet.Bytes32Set; + using EnumerableSet for EnumerableSet.UintSet; + + struct NodeOperator { + /// @notice The address of the admin that can manage a node operator + address admin; + /// @notice Human readable name of a Node Operator managing the node + /// @dev The contract does not validate the length or characters of the node operator name because + /// a trusted admin will supply these names. We reduce gas costs by omitting these checks on-chain. + string name; + } + + struct NodeParams { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed to + /// be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + } + + struct NodeInfo { + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The number of times the node's configuration has been updated + uint32 configCount; + /// @notice The ID of the Workflow DON that the node belongs to. A node can + /// only belong to one DON that accepts Workflows. + uint32 workflowDONId; + /// @notice The signer address for application-layer message verification. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed + /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; + /// @notice The list of hashed capability IDs supported by the node + bytes32[] hashedCapabilityIds; + /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple + /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one. + uint256[] capabilitiesDONIds; + } + + struct Node { + /// @notice The node's parameters + /// @notice The id of the node operator that manages this node + uint32 nodeOperatorId; + /// @notice The number of times the node's configuration has been updated + uint32 configCount; + /// @notice The ID of the Workflow DON that the node belongs to. A node can + /// only belong to one DON that accepts Workflows. + uint32 workflowDONId; + /// @notice The signer address for application-layer message verification. + /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry as a signer + /// address can only belong to one node. + /// @dev This should be the ABI encoded version of the node's address. I.e 0x0000address. The Capability Registry + /// does not store it as an address so that non EVM chains with addresses greater than 20 bytes can be supported + /// in the future. + bytes32 signer; + /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed + /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. + bytes32 p2pId; + /// @notice Public key used to encrypt secrets for this node + bytes32 encryptionPublicKey; + /// @notice The node's supported capabilities + /// @dev This is stored as a map so that we can easily update to a set of new capabilities by + /// incrementing the configCount and creating a new set of supported capability IDs + mapping(uint32 configCount => EnumerableSet.Bytes32Set capabilityId) supportedHashedCapabilityIds; + /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple + /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one. + EnumerableSet.UintSet capabilitiesDONIds; + } + + /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is + /// an already aggregated report. There are multiple possible ways to aggregate. + /// @dev REPORT response type receives signatures together with the response that is used to verify the data. + /// OBSERVATION_IDENTICAL just receives data without signatures and waits for some number of observations before + /// proceeding to the next step + enum CapabilityResponseType { + // No additional aggregation is needed on the remote response. + REPORT, + // A number of identical observations need to be aggregated. + OBSERVATION_IDENTICAL + } + + /// @notice CapabilityType indicates the type of capability which determines + /// where the capability can be used in a Workflow Spec. + enum CapabilityType { + TRIGGER, + ACTION, + CONSENSUS, + TARGET + } + + struct Capability { + /// @notice The partially qualified ID for the capability. + /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} + /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` + /// portion of the ID. + /// + /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" + /// labelledName = "data-streams-reports:chain:ethereum" + string labelledName; + /// @notice Semver, e.g., "1.2.3" + /// @dev must be valid Semver + max 32 characters. + string version; + /// @notice CapabilityType indicates the type of capability which determines + /// where the capability can be used in a Workflow Spec. + CapabilityType capabilityType; + /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is an + /// already aggregated report. There are multiple possible ways to aggregate. + CapabilityResponseType responseType; + /// @notice An address to the capability configuration contract. Having this defined on a capability enforces + /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement + /// CapabilityConfigurationContractInterface. + /// + /// @dev The main use cases are: + /// 1) Sharing capability configuration across DON instances + /// 2) Inspect and modify on-chain configuration without off-chain capability code. + /// + /// It is not recommended to store configuration which requires knowledge of the DON membership. + address configurationContract; + } + + struct CapabilityInfo { + /// @notice A hashed ID created by the `getHashedCapabilityId` function. + bytes32 hashedId; + /// @notice The partially qualified ID for the capability. + /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} + /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` + /// portion of the ID. + /// + /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" + /// labelledName = "data-streams-reports:chain:ethereum" + string labelledName; + /// @notice Semver, e.g., "1.2.3" + /// @dev must be valid Semver + max 32 characters. + string version; + /// @notice CapabilityType indicates the type of capability which determines + /// where the capability can be used in a Workflow Spec. + CapabilityType capabilityType; + /// @notice CapabilityResponseType indicates whether remote response requires aggregation + /// or is an already aggregated report. There are multiple possible ways to aggregate. + CapabilityResponseType responseType; + /// @notice An address to the capability configuration contract. Having this defined on a capability enforces + /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement + /// CapabilityConfigurationContractInterface. + /// + /// @dev The main use cases are: + /// 1) Sharing capability configuration across DON instances + /// 2) Inspect and modify on-chain configuration without off-chain capability code. + /// + /// It is not recommended to store configuration which requires knowledge of the DON membership. + address configurationContract; + /// @notice True if the capability is deprecated + bool isDeprecated; + } + + /// @notice CapabilityConfiguration is a struct that holds the capability configuration + /// for a specific DON + struct CapabilityConfiguration { + /// @notice The capability Id + bytes32 capabilityId; + /// @notice The capability config specific to a DON. This will be decoded offchain + bytes config; + } + + struct DONCapabilityConfig { + /// @notice The set of p2pIds of nodes that belong to this DON. A node (the same p2pId) can belong to multiple DONs. + EnumerableSet.Bytes32Set nodes; + /// @notice The set of capabilityIds + bytes32[] capabilityIds; + /// @notice Mapping from hashed capability IDs to configs + mapping(bytes32 capabilityId => bytes config) capabilityConfigs; + } + + /// @notice DON (Decentralized Oracle Network) is a grouping of nodes that support + // the same capabilities. + struct DON { + /// @notice Computed. Auto-increment. + uint32 id; + /// @notice The number of times the DON was configured + uint32 configCount; + /// @notice The f value for the DON. This is the number of faulty nodes + /// that the DON can tolerate. This can be different from the f value of + /// the OCR instances that capabilities spawn. + uint8 f; + /// @notice True if the DON is public. A public DON means that it accepts + /// external capability requests + bool isPublic; + /// @notice True if the DON accepts Workflows. A DON that accepts Workflows + /// is called Workflow DON and it can process Workflow Specs. A Workflow + /// DON also support one or more capabilities as well. + bool acceptsWorkflows; + /// @notice Mapping of config counts to configurations + mapping(uint32 configCount => DONCapabilityConfig donConfig) config; + } + + struct DONInfo { + /// @notice Computed. Auto-increment. + uint32 id; + /// @notice The number of times the DON was configured + uint32 configCount; + /// @notice The f value for the DON. This is the number of faulty nodes + /// that the DON can tolerate. This can be different from the f value of + /// the OCR instances that capabilities spawn. + uint8 f; + /// @notice True if the DON is public. A public DON means that it accepts + /// external capability requests + bool isPublic; + /// @notice True if the DON accepts Workflows. + bool acceptsWorkflows; + /// @notice List of member node P2P Ids + bytes32[] nodeP2PIds; + /// @notice List of capability configurations + CapabilityConfiguration[] capabilityConfigurations; + } + + /// @notice DONParams is a struct that holds the parameters for a DON. + /// @dev This is needed to avoid "stack too deep" errors in _setDONConfig. + struct DONParams { + uint32 id; + uint32 configCount; + bool isPublic; + bool acceptsWorkflows; + uint8 f; + } + + /// @notice This error is thrown when a caller is not allowed + /// to execute the transaction + /// @param sender The address that tried to execute the transaction + error AccessForbidden(address sender); + + /// @notice This error is thrown when there is a mismatch between + /// array arguments + /// @param lengthOne The length of the first array argument + /// @param lengthTwo The length of the second array argument + error LengthMismatch(uint256 lengthOne, uint256 lengthTwo); + + /// @notice This error is thrown when trying to set a node operator's + /// admin address to the zero address + error InvalidNodeOperatorAdmin(); + + /// @notice This error is thrown when trying to add a node with P2P ID that + /// is empty bytes + /// @param p2pId The provided P2P ID + error InvalidNodeP2PId(bytes32 p2pId); + + /// @notice This error is thrown when trying to add a node without + /// including the encryption public key bytes. + /// @param encryptionPublicKey The encryption public key bytes + error InvalidNodeEncryptionPublicKey(bytes32 encryptionPublicKey); + + /// @notice This error is thrown when trying to add a node without + /// capabilities or with capabilities that do not exist. + /// @param hashedCapabilityIds The IDs of the capabilities that are being added. + error InvalidNodeCapabilities(bytes32[] hashedCapabilityIds); + + /// @notice This error is emitted when a DON does not exist + /// @param donId The ID of the nonexistent DON + error DONDoesNotExist(uint32 donId); + + /// @notice This error is thrown when trying to set the node's + /// signer address to zero or if the signer address has already + /// been used by another node + error InvalidNodeSigner(); + + /// @notice This error is thrown when trying to add a capability that already + /// exists. + /// @param hashedCapabilityId The hashed capability ID of the capability + /// that already exists + error CapabilityAlreadyExists(bytes32 hashedCapabilityId); + + /// @notice This error is thrown when trying to add a node that already + /// exists. + /// @param nodeP2PId The P2P ID of the node that already exists + error NodeAlreadyExists(bytes32 nodeP2PId); + + /// @notice This error is thrown when trying to add a node to a DON where + /// the node does not support the capability + /// @param nodeP2PId The P2P ID of the node + /// @param capabilityId The ID of the capability + error NodeDoesNotSupportCapability(bytes32 nodeP2PId, bytes32 capabilityId); + + /// @notice This error is thrown when trying to add a capability configuration + /// for a capability that was already configured on a DON + /// @param donId The ID of the DON that the capability was configured for + /// @param capabilityId The ID of the capability that was configured + error DuplicateDONCapability(uint32 donId, bytes32 capabilityId); + + /// @notice This error is thrown when trying to add a duplicate node to a DON + /// @param donId The ID of the DON that the node was added for + /// @param nodeP2PId The P2P ID of the node + error DuplicateDONNode(uint32 donId, bytes32 nodeP2PId); + + /// @notice This error is thrown when trying to configure a DON with invalid + /// fault tolerance value. + /// @param f The proposed fault tolerance value + /// @param nodeCount The proposed number of nodes in the DON + error InvalidFaultTolerance(uint8 f, uint256 nodeCount); + + /// @notice This error is thrown when a capability with the provided hashed ID is + /// not found. + /// @param hashedCapabilityId The hashed ID used for the lookup. + error CapabilityDoesNotExist(bytes32 hashedCapabilityId); + + /// @notice This error is thrown when trying to deprecate a capability that + /// is deprecated. + /// @param hashedCapabilityId The hashed ID of the capability that is deprecated. + error CapabilityIsDeprecated(bytes32 hashedCapabilityId); + + /// @notice This error is thrown when a node with the provided P2P ID is + /// not found. + /// @param nodeP2PId The node P2P ID used for the lookup. + error NodeDoesNotExist(bytes32 nodeP2PId); + + /// @notice This error is thrown when a node operator does not exist + /// @param nodeOperatorId The ID of the node operator that does not exist + error NodeOperatorDoesNotExist(uint32 nodeOperatorId); + + /// @notice This error is thrown when trying to remove a node that is still + /// part of a capabilities DON + /// @param donId The Id of the DON the node belongs to + /// @param nodeP2PId The P2P Id of the node being removed + error NodePartOfCapabilitiesDON(uint32 donId, bytes32 nodeP2PId); + + /// @notice This error is thrown when attempting to add a node to a second + /// Workflow DON or when trying to remove a node that belongs to a Workflow + /// DON + /// @param donId The Id of the DON the node belongs to + /// @param nodeP2PId The P2P Id of the node + error NodePartOfWorkflowDON(uint32 donId, bytes32 nodeP2PId); + + /// @notice This error is thrown when removing a capability from the node + /// when that capability is still required by one of the DONs the node + /// belongs to. + /// @param hashedCapabilityId The hashed ID of the capability + /// @param donId The ID of the DON that requires the capability + error CapabilityRequiredByDON(bytes32 hashedCapabilityId, uint32 donId); + + /// @notice This error is thrown when trying to add a capability with a + /// configuration contract that does not implement the required interface. + /// @param proposedConfigurationContract The address of the proposed + /// configuration contract. + error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract); + + /// @notice This event is emitted when a new node is added + /// @param p2pId The P2P ID of the node + /// @param nodeOperatorId The ID of the node operator that manages this node + /// @param signer The encoded node's signer address + event NodeAdded(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); + + /// @notice This event is emitted when a node is removed + /// @param p2pId The P2P ID of the node that was removed + event NodeRemoved(bytes32 p2pId); + + /// @notice This event is emitted when a node is updated + /// @param p2pId The P2P ID of the node + /// @param nodeOperatorId The ID of the node operator that manages this node + /// @param signer The node's signer address + event NodeUpdated(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); + + /// @notice This event is emitted when a DON's config is set + /// @param donId The ID of the DON the config was set for + /// @param configCount The number of times the DON has been + /// configured + event ConfigSet(uint32 indexed donId, uint32 configCount); + + /// @notice This event is emitted when a new node operator is added + /// @param nodeOperatorId The ID of the newly added node operator + /// @param admin The address of the admin that can manage the node + /// operator + /// @param name The human readable name of the node operator + event NodeOperatorAdded(uint32 indexed nodeOperatorId, address indexed admin, string name); + + /// @notice This event is emitted when a node operator is removed + /// @param nodeOperatorId The ID of the node operator that was removed + event NodeOperatorRemoved(uint32 indexed nodeOperatorId); + + /// @notice This event is emitted when a node operator is updated + /// @param nodeOperatorId The ID of the node operator that was updated + /// @param admin The address of the node operator's admin + /// @param name The node operator's human readable name + event NodeOperatorUpdated(uint32 indexed nodeOperatorId, address indexed admin, string name); + + /// @notice This event is emitted when a new capability is added + /// @param hashedCapabilityId The hashed ID of the newly added capability + event CapabilityConfigured(bytes32 indexed hashedCapabilityId); + + /// @notice This event is emitted when a capability is deprecated + /// @param hashedCapabilityId The hashed ID of the deprecated capability + event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); + + string public constant override typeAndVersion = "CapabilitiesRegistry 1.0.0"; + + /// @notice Mapping of capabilities + mapping(bytes32 hashedCapabilityId => Capability capability) private s_capabilities; + + /// @notice Set of hashed capability IDs. + /// A hashed ID is created by the function `getHashedCapabilityId`. + EnumerableSet.Bytes32Set private s_hashedCapabilityIds; + + /// @notice Set of deprecated hashed capability IDs, + /// A hashed ID is created by the function `getHashedCapabilityId`. + EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds; + + /// @notice Encoded node signer addresses + EnumerableSet.Bytes32Set private s_nodeSigners; + + /// @notice Set of node P2P IDs + EnumerableSet.Bytes32Set private s_nodeP2PIds; + + /// @notice Mapping of node operators + mapping(uint32 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators; + + /// @notice Mapping of nodes + mapping(bytes32 p2pId => Node node) private s_nodes; + + /// @notice Mapping of DON IDs to DONs + mapping(uint32 donId => DON don) private s_dons; + + /// @notice The next ID to assign a new node operator to + /// @dev Starting with 1 to avoid confusion with the zero value + /// @dev No getter for this as this is an implementation detail + uint32 private s_nextNodeOperatorId = 1; + + /// @notice The next ID to assign a new DON to + /// @dev Starting with 1 to avoid confusion with the zero value + /// @dev No getter for this as this is an implementation detail + uint32 private s_nextDONId = 1; + + /// @notice Adds a list of node operators + /// @param nodeOperators List of node operators to add + function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { + for (uint256 i; i < nodeOperators.length; ++i) { + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + uint32 nodeOperatorId = s_nextNodeOperatorId; + s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name}); + ++s_nextNodeOperatorId; + emit NodeOperatorAdded(nodeOperatorId, nodeOperator.admin, nodeOperator.name); + } + } + + /// @notice Removes a node operator + /// @param nodeOperatorIds The IDs of the node operators to remove + function removeNodeOperators(uint32[] calldata nodeOperatorIds) external onlyOwner { + for (uint32 i; i < nodeOperatorIds.length; ++i) { + uint32 nodeOperatorId = nodeOperatorIds[i]; + delete s_nodeOperators[nodeOperatorId]; + emit NodeOperatorRemoved(nodeOperatorId); + } + } + + /// @notice Updates a node operator + /// @param nodeOperatorIds The ID of the node operator being updated + /// @param nodeOperators The updated node operator params + function updateNodeOperators(uint32[] calldata nodeOperatorIds, NodeOperator[] calldata nodeOperators) external { + if (nodeOperatorIds.length != nodeOperators.length) + revert LengthMismatch(nodeOperatorIds.length, nodeOperators.length); + + address owner = owner(); + for (uint256 i; i < nodeOperatorIds.length; ++i) { + uint32 nodeOperatorId = nodeOperatorIds[i]; + + NodeOperator storage currentNodeOperator = s_nodeOperators[nodeOperatorId]; + if (currentNodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(nodeOperatorId); + + NodeOperator memory nodeOperator = nodeOperators[i]; + if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); + if (msg.sender != currentNodeOperator.admin && msg.sender != owner) revert AccessForbidden(msg.sender); + + if ( + currentNodeOperator.admin != nodeOperator.admin || + keccak256(abi.encode(currentNodeOperator.name)) != keccak256(abi.encode(nodeOperator.name)) + ) { + currentNodeOperator.admin = nodeOperator.admin; + currentNodeOperator.name = nodeOperator.name; + emit NodeOperatorUpdated(nodeOperatorId, nodeOperator.admin, nodeOperator.name); + } + } + } + + /// @notice Gets a node operator's data + /// @param nodeOperatorId The ID of the node operator to query for + /// @return NodeOperator The node operator data + function getNodeOperator(uint32 nodeOperatorId) external view returns (NodeOperator memory) { + return s_nodeOperators[nodeOperatorId]; + } + + /// @notice Gets all node operators + /// @return NodeOperator[] All node operators + function getNodeOperators() external view returns (NodeOperator[] memory) { + uint32 nodeOperatorId = s_nextNodeOperatorId; + /// Minus one to account for s_nextNodeOperatorId starting at index 1 + NodeOperator[] memory nodeOperators = new NodeOperator[](s_nextNodeOperatorId - 1); + uint256 idx; + for (uint32 i = 1; i < nodeOperatorId; ++i) { + if (s_nodeOperators[i].admin != address(0)) { + nodeOperators[idx] = s_nodeOperators[i]; + ++idx; + } + } + if (idx != s_nextNodeOperatorId - 1) { + assembly { + mstore(nodeOperators, idx) + } + } + return nodeOperators; + } + + /// @notice Adds nodes. Nodes can be added with deprecated capabilities to + /// avoid breaking changes when deprecating capabilities. + /// @param nodes The nodes to add + function addNodes(NodeParams[] calldata nodes) external { + bool isOwner = msg.sender == owner(); + for (uint256 i; i < nodes.length; ++i) { + NodeParams memory node = nodes[i]; + + NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; + if (nodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(node.nodeOperatorId); + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); + + Node storage storedNode = s_nodes[node.p2pId]; + if (storedNode.signer != bytes32("")) revert NodeAlreadyExists(node.p2pId); + if (node.p2pId == bytes32("")) revert InvalidNodeP2PId(node.p2pId); + + if (node.signer == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); + + if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); + + bytes32[] memory capabilityIds = node.hashedCapabilityIds; + if (capabilityIds.length == 0) revert InvalidNodeCapabilities(capabilityIds); + + ++storedNode.configCount; + + uint32 capabilityConfigCount = storedNode.configCount; + for (uint256 j; j < capabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(capabilityIds[j])) revert InvalidNodeCapabilities(capabilityIds); + storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(capabilityIds[j]); + } + + storedNode.encryptionPublicKey = node.encryptionPublicKey; + storedNode.nodeOperatorId = node.nodeOperatorId; + storedNode.p2pId = node.p2pId; + storedNode.signer = node.signer; + s_nodeSigners.add(node.signer); + s_nodeP2PIds.add(node.p2pId); + emit NodeAdded(node.p2pId, node.nodeOperatorId, node.signer); + } + } + + /// @notice Removes nodes. The node operator admin or contract owner + /// can remove nodes + /// @param removedNodeP2PIds The P2P Ids of the nodes to remove + function removeNodes(bytes32[] calldata removedNodeP2PIds) external { + bool isOwner = msg.sender == owner(); + for (uint256 i; i < removedNodeP2PIds.length; ++i) { + bytes32 p2pId = removedNodeP2PIds[i]; + + Node storage node = s_nodes[p2pId]; + + if (node.signer == bytes32("")) revert NodeDoesNotExist(p2pId); + if (node.capabilitiesDONIds.length() > 0) + revert NodePartOfCapabilitiesDON(uint32(node.capabilitiesDONIds.at(i)), p2pId); + if (node.workflowDONId != 0) revert NodePartOfWorkflowDON(node.workflowDONId, p2pId); + + if (!isOwner && msg.sender != s_nodeOperators[node.nodeOperatorId].admin) revert AccessForbidden(msg.sender); + s_nodeSigners.remove(node.signer); + s_nodeP2PIds.remove(node.p2pId); + delete s_nodes[p2pId]; + emit NodeRemoved(p2pId); + } + } + + /// @notice Updates nodes. The node admin can update the node's signer address + /// and reconfigure its supported capabilities + /// @param nodes The nodes to update + function updateNodes(NodeParams[] calldata nodes) external { + bool isOwner = msg.sender == owner(); + for (uint256 i; i < nodes.length; ++i) { + NodeParams memory node = nodes[i]; + Node storage storedNode = s_nodes[node.p2pId]; + NodeOperator memory nodeOperator = s_nodeOperators[storedNode.nodeOperatorId]; + + if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId); + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); + + if (node.signer == bytes32("")) revert InvalidNodeSigner(); + + bytes32 previousSigner = storedNode.signer; + if (previousSigner != node.signer) { + if (s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); + storedNode.signer = node.signer; + s_nodeSigners.remove(previousSigner); + s_nodeSigners.add(node.signer); + } + + if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); + + bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds; + if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); + + uint32 capabilityConfigCount = ++storedNode.configCount; + for (uint256 j; j < supportedHashedCapabilityIds.length; ++j) { + if (!s_hashedCapabilityIds.contains(supportedHashedCapabilityIds[j])) + revert InvalidNodeCapabilities(supportedHashedCapabilityIds); + storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(supportedHashedCapabilityIds[j]); + } + + // Validate that capabilities required by a Workflow DON are still supported + uint32 nodeWorkflowDONId = storedNode.workflowDONId; + if (nodeWorkflowDONId != 0) { + bytes32[] memory workflowDonCapabilityIds = s_dons[nodeWorkflowDONId] + .config[s_dons[nodeWorkflowDONId].configCount] + .capabilityIds; + + for (uint256 j; j < workflowDonCapabilityIds.length; ++j) { + if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(workflowDonCapabilityIds[j])) + revert CapabilityRequiredByDON(workflowDonCapabilityIds[j], nodeWorkflowDONId); + } + } + + // Validate that capabilities required by capabilities DONs are still supported + uint256[] memory capabilitiesDONIds = storedNode.capabilitiesDONIds.values(); + for (uint32 j; j < capabilitiesDONIds.length; ++j) { + uint32 donId = uint32(capabilitiesDONIds[j]); + bytes32[] memory donCapabilityIds = s_dons[donId].config[s_dons[donId].configCount].capabilityIds; + + for (uint256 k; k < donCapabilityIds.length; ++k) { + if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(donCapabilityIds[k])) + revert CapabilityRequiredByDON(donCapabilityIds[k], donId); + } + } + + storedNode.nodeOperatorId = node.nodeOperatorId; + storedNode.p2pId = node.p2pId; + storedNode.encryptionPublicKey = node.encryptionPublicKey; + + emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); + } + } + + /// @notice Gets a node's data + /// @param p2pId The P2P ID of the node to query for + /// @return nodeInfo NodeInfo The node data + function getNode(bytes32 p2pId) public view returns (NodeInfo memory nodeInfo) { + return ( + NodeInfo({ + nodeOperatorId: s_nodes[p2pId].nodeOperatorId, + p2pId: s_nodes[p2pId].p2pId, + signer: s_nodes[p2pId].signer, + encryptionPublicKey: s_nodes[p2pId].encryptionPublicKey, + hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values(), + configCount: s_nodes[p2pId].configCount, + workflowDONId: s_nodes[p2pId].workflowDONId, + capabilitiesDONIds: s_nodes[p2pId].capabilitiesDONIds.values() + }) + ); + } + + /// @notice Gets all nodes + /// @return NodeInfo[] All nodes in the capability registry + function getNodes() external view returns (NodeInfo[] memory) { + bytes32[] memory p2pIds = s_nodeP2PIds.values(); + NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length); + + for (uint256 i; i < p2pIds.length; ++i) { + nodesInfo[i] = getNode(p2pIds[i]); + } + return nodesInfo; + } + + /// @notice Adds a new capability to the capability registry + /// @param capabilities The capabilities being added + /// @dev There is no function to update capabilities as this would require + /// nodes to trust that the capabilities they support are not updated by the + /// admin + function addCapabilities(Capability[] calldata capabilities) external onlyOwner { + for (uint256 i; i < capabilities.length; ++i) { + Capability memory capability = capabilities[i]; + bytes32 hashedCapabilityId = getHashedCapabilityId(capability.labelledName, capability.version); + if (!s_hashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityAlreadyExists(hashedCapabilityId); + _setCapability(hashedCapabilityId, capability); + } + } + + /// @notice Deprecates a capability + /// @param hashedCapabilityIds[] The IDs of the capabilities to deprecate + function deprecateCapabilities(bytes32[] calldata hashedCapabilityIds) external onlyOwner { + for (uint256 i; i < hashedCapabilityIds.length; ++i) { + bytes32 hashedCapabilityId = hashedCapabilityIds[i]; + if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId); + if (!s_deprecatedHashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityIsDeprecated(hashedCapabilityId); + + emit CapabilityDeprecated(hashedCapabilityId); + } + } + + /// @notice Returns a Capability by its hashed ID. + /// @dev Use `getHashedCapabilityId` to get the hashed ID. + function getCapability(bytes32 hashedId) public view returns (CapabilityInfo memory) { + return ( + CapabilityInfo({ + hashedId: hashedId, + labelledName: s_capabilities[hashedId].labelledName, + version: s_capabilities[hashedId].version, + capabilityType: s_capabilities[hashedId].capabilityType, + responseType: s_capabilities[hashedId].responseType, + configurationContract: s_capabilities[hashedId].configurationContract, + isDeprecated: s_deprecatedHashedCapabilityIds.contains(hashedId) + }) + ); + } + + /// @notice Returns all capabilities. This operation will copy capabilities + /// to memory, which can be quite expensive. This is designed to mostly be + /// used by view accessors that are queried without any gas fees. + /// @return CapabilityInfo[] List of capabilities + function getCapabilities() external view returns (CapabilityInfo[] memory) { + bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); + CapabilityInfo[] memory capabilitiesInfo = new CapabilityInfo[](hashedCapabilityIds.length); + + for (uint256 i; i < hashedCapabilityIds.length; ++i) { + capabilitiesInfo[i] = getCapability(hashedCapabilityIds[i]); + } + return capabilitiesInfo; + } + + /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access + /// @param labelledName The name of the capability + /// @param version The capability's version number + /// @return bytes32 A unique identifier for the capability + /// @dev The hash of the encoded labelledName and version + function getHashedCapabilityId(string memory labelledName, string memory version) public pure returns (bytes32) { + return keccak256(abi.encode(labelledName, version)); + } + + /// @notice Returns whether a capability is deprecated + /// @param hashedCapabilityId The hashed ID of the capability to check + /// @return bool True if the capability is deprecated, false otherwise + function isCapabilityDeprecated(bytes32 hashedCapabilityId) external view returns (bool) { + return s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId); + } + + /// @notice Adds a DON made up by a group of nodes that support a list + /// of capability configurations + /// @param nodes The nodes making up the DON + /// @param capabilityConfigurations The list of configurations for the + /// capabilities supported by the DON + /// @param isPublic True if the DON is can accept external capability requests + /// @param acceptsWorkflows True if the DON can accept workflows + /// @param f The maximum number of faulty nodes the DON can tolerate + function addDON( + bytes32[] calldata nodes, + CapabilityConfiguration[] calldata capabilityConfigurations, + bool isPublic, + bool acceptsWorkflows, + uint8 f + ) external onlyOwner { + uint32 id = s_nextDONId++; + s_dons[id].id = id; + + _setDONConfig( + nodes, + capabilityConfigurations, + DONParams({id: id, configCount: 1, isPublic: isPublic, acceptsWorkflows: acceptsWorkflows, f: f}) + ); + } + + /// @notice Updates a DON's configuration. This allows + /// the admin to reconfigure the list of capabilities supported + /// by the DON, the list of nodes that make up the DON as well + /// as whether or not the DON can accept external workflows + /// @param donId The ID of the DON to update + /// @param nodes The nodes making up the DON + /// @param capabilityConfigurations The list of configurations for the + /// capabilities supported by the DON + /// @param isPublic True if the DON is can accept external capability requests + /// @param f The maximum number of nodes that can fail + function updateDON( + uint32 donId, + bytes32[] calldata nodes, + CapabilityConfiguration[] calldata capabilityConfigurations, + bool isPublic, + uint8 f + ) external onlyOwner { + DON storage don = s_dons[donId]; + uint32 configCount = don.configCount; + if (configCount == 0) revert DONDoesNotExist(donId); + _setDONConfig( + nodes, + capabilityConfigurations, + DONParams({ + id: donId, + configCount: ++configCount, + isPublic: isPublic, + acceptsWorkflows: don.acceptsWorkflows, + f: f + }) + ); + } + + /// @notice Removes DONs from the Capability Registry + /// @param donIds The IDs of the DON to be removed + function removeDONs(uint32[] calldata donIds) external onlyOwner { + for (uint256 i; i < donIds.length; ++i) { + uint32 donId = donIds[i]; + DON storage don = s_dons[donId]; + + uint32 configCount = don.configCount; + EnumerableSet.Bytes32Set storage nodeP2PIds = don.config[configCount].nodes; + + bool isWorkflowDON = don.acceptsWorkflows; + for (uint256 j; j < nodeP2PIds.length(); ++j) { + if (isWorkflowDON) { + delete s_nodes[nodeP2PIds.at(j)].workflowDONId; + } else { + s_nodes[nodeP2PIds.at(j)].capabilitiesDONIds.remove(donId); + } + } + + // DON config count starts at index 1 + if (don.configCount == 0) revert DONDoesNotExist(donId); + delete s_dons[donId]; + emit ConfigSet(donId, 0); + } + } + + /// @notice Gets DON's data + /// @param donId The DON ID + /// @return DONInfo The DON's parameters + function getDON(uint32 donId) external view returns (DONInfo memory) { + return _getDON(donId); + } + + /// @notice Returns the list of configured DONs + /// @return DONInfo[] The list of configured DONs + function getDONs() external view returns (DONInfo[] memory) { + /// Minus one to account for s_nextDONId starting at index 1 + uint32 donId = s_nextDONId; + DONInfo[] memory dons = new DONInfo[](donId - 1); + uint256 idx; + /// + for (uint32 i = 1; i < donId; ++i) { + if (s_dons[i].id != 0) { + dons[idx] = _getDON(i); + ++idx; + } + } + if (idx != donId - 1) { + assembly { + mstore(dons, idx) + } + } + return dons; + } + + /// @notice Returns the DON specific configuration for a capability + /// @param donId The DON's ID + /// @param capabilityId The Capability ID + /// @return bytes The DON specific configuration for the capability stored on the capability registry + /// @return bytes The DON specific configuration stored on the capability's configuration contract + function getCapabilityConfigs(uint32 donId, bytes32 capabilityId) external view returns (bytes memory, bytes memory) { + uint32 configCount = s_dons[donId].configCount; + + bytes memory donCapabilityConfig = s_dons[donId].config[configCount].capabilityConfigs[capabilityId]; + bytes memory globalCapabilityConfig; + + if (s_capabilities[capabilityId].configurationContract != address(0)) { + globalCapabilityConfig = ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract) + .getCapabilityConfiguration(donId); + } + + return (donCapabilityConfig, globalCapabilityConfig); + } + + /// @notice Sets the configuration for a DON + /// @param nodes The nodes making up the DON + /// @param capabilityConfigurations The list of configurations for the capabilities supported by the DON + /// @param donParams The DON's parameters + function _setDONConfig( + bytes32[] calldata nodes, + CapabilityConfiguration[] calldata capabilityConfigurations, + DONParams memory donParams + ) internal { + DONCapabilityConfig storage donCapabilityConfig = s_dons[donParams.id].config[donParams.configCount]; + + // Validate the f value. We are intentionally relaxing the 3f+1 requirement + // as not all DONs will run OCR instances. + if (donParams.f == 0 || donParams.f + 1 > nodes.length) revert InvalidFaultTolerance(donParams.f, nodes.length); + + // Skip removing supported DON Ids from previously configured nodes in DON if + // we are adding the DON for the first time + if (donParams.configCount > 1) { + DONCapabilityConfig storage prevDONCapabilityConfig = s_dons[donParams.id].config[donParams.configCount - 1]; + + // We acknowledge that this may result in an out of gas error if the number of configured + // nodes is large. This is mitigated by ensuring that there will not be a large number + // of nodes configured to a DON. + // We also do not remove the nodes from the previous DON capability config. This is not + // needed as the previous config will be overwritten by storing the latest config + // at configCount + for (uint256 i; i < prevDONCapabilityConfig.nodes.length(); ++i) { + s_nodes[prevDONCapabilityConfig.nodes.at(i)].capabilitiesDONIds.remove(donParams.id); + delete s_nodes[prevDONCapabilityConfig.nodes.at(i)].workflowDONId; + } + } + + for (uint256 i; i < nodes.length; ++i) { + if (!donCapabilityConfig.nodes.add(nodes[i])) revert DuplicateDONNode(donParams.id, nodes[i]); + + if (donParams.acceptsWorkflows) { + if (s_nodes[nodes[i]].workflowDONId != donParams.id && s_nodes[nodes[i]].workflowDONId != 0) + revert NodePartOfWorkflowDON(donParams.id, nodes[i]); + s_nodes[nodes[i]].workflowDONId = donParams.id; + } else { + /// Fine to add a duplicate DON ID to the set of supported DON IDs again as the set + /// will only store unique DON IDs + s_nodes[nodes[i]].capabilitiesDONIds.add(donParams.id); + } + } + + for (uint256 i; i < capabilityConfigurations.length; ++i) { + CapabilityConfiguration calldata configuration = capabilityConfigurations[i]; + + if (!s_hashedCapabilityIds.contains(configuration.capabilityId)) + revert CapabilityDoesNotExist(configuration.capabilityId); + if (s_deprecatedHashedCapabilityIds.contains(configuration.capabilityId)) + revert CapabilityIsDeprecated(configuration.capabilityId); + + if (donCapabilityConfig.capabilityConfigs[configuration.capabilityId].length > 0) + revert DuplicateDONCapability(donParams.id, configuration.capabilityId); + + for (uint256 j; j < nodes.length; ++j) { + if ( + !s_nodes[nodes[j]].supportedHashedCapabilityIds[s_nodes[nodes[j]].configCount].contains( + configuration.capabilityId + ) + ) revert NodeDoesNotSupportCapability(nodes[j], configuration.capabilityId); + } + + donCapabilityConfig.capabilityIds.push(configuration.capabilityId); + donCapabilityConfig.capabilityConfigs[configuration.capabilityId] = configuration.config; + + s_dons[donParams.id].isPublic = donParams.isPublic; + s_dons[donParams.id].acceptsWorkflows = donParams.acceptsWorkflows; + s_dons[donParams.id].f = donParams.f; + s_dons[donParams.id].configCount = donParams.configCount; + + _setDONCapabilityConfig( + donParams.id, + donParams.configCount, + configuration.capabilityId, + nodes, + configuration.config + ); + } + emit ConfigSet(donParams.id, donParams.configCount); + } + + /// @notice Sets the capability's config on the config contract + /// @param donId The ID of the DON the capability is being configured for + /// @param configCount The number of times the DON has been configured + /// @param capabilityId The capability's ID + /// @param nodes The nodes in the DON + /// @param config The DON's capability config + /// @dev Helper function used to resolve stack too deep errors in _setDONConfig + function _setDONCapabilityConfig( + uint32 donId, + uint32 configCount, + bytes32 capabilityId, + bytes32[] calldata nodes, + bytes memory config + ) internal { + if (s_capabilities[capabilityId].configurationContract != address(0)) { + ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract).beforeCapabilityConfigSet( + nodes, + config, + configCount, + donId + ); + } + } + + /// @notice Sets a capability's data + /// @param hashedCapabilityId The ID of the capability being set + /// @param capability The capability's data + function _setCapability(bytes32 hashedCapabilityId, Capability memory capability) internal { + if (capability.configurationContract != address(0)) { + /// Check that the configuration contract being assigned + /// correctly supports the ICapabilityConfiguration interface + /// by implementing both getCapabilityConfiguration and + /// beforeCapabilityConfigSet + if ( + !ERC165Checker.supportsInterface(capability.configurationContract, type(ICapabilityConfiguration).interfaceId) + ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); + } + s_capabilities[hashedCapabilityId] = capability; + emit CapabilityConfigured(hashedCapabilityId); + } + + /// @notice Gets DON's data + /// @param donId The DON ID + /// @return DONInfo The DON's parameters + function _getDON(uint32 donId) internal view returns (DONInfo memory) { + uint32 configCount = s_dons[donId].configCount; + + DONCapabilityConfig storage donCapabilityConfig = s_dons[donId].config[configCount]; + + bytes32[] memory capabilityIds = donCapabilityConfig.capabilityIds; + CapabilityConfiguration[] memory capabilityConfigurations = new CapabilityConfiguration[](capabilityIds.length); + + for (uint256 i; i < capabilityConfigurations.length; ++i) { + capabilityConfigurations[i] = CapabilityConfiguration({ + capabilityId: capabilityIds[i], + config: donCapabilityConfig.capabilityConfigs[capabilityIds[i]] + }); + } + + return + DONInfo({ + id: s_dons[donId].id, + configCount: configCount, + f: s_dons[donId].f, + isPublic: s_dons[donId].isPublic, + acceptsWorkflows: s_dons[donId].acceptsWorkflows, + nodeP2PIds: donCapabilityConfig.nodes.values(), + capabilityConfigurations: capabilityConfigurations + }); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol new file mode 100644 index 0000000..447c979 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IReceiver} from "./interfaces/IReceiver.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { + event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); + + error UnauthorizedSender(address sender); + error UnauthorizedWorkflowOwner(address workflowOwner); + error UnauthorizedWorkflowName(bytes10 workflowName); + + struct ReceivedFeedReport { + bytes32 FeedId; + uint224 Price; + uint32 Timestamp; + } + + struct StoredFeedReport { + uint224 Price; + uint32 Timestamp; + } + + mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports; + address[] internal s_allowedSendersList; + mapping(address sender => bool) internal s_allowedSenders; + address[] internal s_allowedWorkflowOwnersList; + mapping(address owner => bool) internal s_allowedWorkflowOwners; + bytes10[] internal s_allowedWorkflowNamesList; + mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames; + + function setConfig( + address[] calldata _allowedSendersList, + address[] calldata _allowedWorkflowOwnersList, + bytes10[] calldata _allowedWorkflowNamesList + ) external onlyOwner { + for (uint32 i = 0; i < s_allowedSendersList.length; ++i) { + s_allowedSenders[s_allowedSendersList[i]] = false; + } + for (uint32 i = 0; i < _allowedSendersList.length; ++i) { + s_allowedSenders[_allowedSendersList[i]] = true; + } + s_allowedSendersList = _allowedSendersList; + for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) { + s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false; + } + for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) { + s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true; + } + s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList; + for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) { + s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false; + } + for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) { + s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true; + } + s_allowedWorkflowNamesList = _allowedWorkflowNamesList; + } + + function onReport(bytes calldata metadata, bytes calldata rawReport) external { + if (!s_allowedSenders[msg.sender]) { + revert UnauthorizedSender(msg.sender); + } + + (bytes10 workflowName, address workflowOwner) = _getInfo(metadata); + if (!s_allowedWorkflowNames[workflowName]) { + revert UnauthorizedWorkflowName(workflowName); + } + if (!s_allowedWorkflowOwners[workflowOwner]) { + revert UnauthorizedWorkflowOwner(workflowOwner); + } + + ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[])); + for (uint256 i = 0; i < feeds.length; ++i) { + s_feedReports[feeds[i].FeedId] = StoredFeedReport(feeds[i].Price, feeds[i].Timestamp); + emit FeedReceived(feeds[i].FeedId, feeds[i].Price, feeds[i].Timestamp); + } + } + + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _getInfo(bytes memory metadata) internal pure returns (bytes10 workflowName, address workflowOwner) { + // (first 32 bytes contain length of the byte array) + // workflow_cid // offset 32, size 32 + // workflow_name // offset 64, size 10 + // workflow_owner // offset 74, size 20 + // report_name // offset 94, size 2 + assembly { + // no shifting needed for bytes10 type + workflowName := mload(add(metadata, 64)) + // shift right by 12 bytes to get the actual value + workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) + } + } + + function getPrice(bytes32 feedId) external view returns (uint224, uint32) { + StoredFeedReport memory report = s_feedReports[feedId]; + return (report.Price, report.Timestamp); + } + + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol new file mode 100644 index 0000000..5a28aa5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +/// @title Keystone Feeds Permission Handler +/// @notice This contract is designed to manage and validate permissions for accessing specific reports within a decentralized system. +/// @dev The contract uses mappings to keep track of report permissions associated with a unique report ID. +abstract contract KeystoneFeedsPermissionHandler is OwnerIsCreator { + /// @notice Holds the details for permissions of a report + /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. + struct Permission { + address forwarder; // ──────╮ The address of the forwarder (20 bytes) + bytes10 workflowName; // │ The name of the workflow in bytes10 + bytes2 reportName; // ──────╯ The name of the report in bytes2 + address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) + bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) + } + + /// @notice Event emitted when report permissions are set + event ReportPermissionSet(bytes32 indexed reportId, Permission permission); + + /// @notice Error to be thrown when an unauthorized access attempt is made + error ReportForwarderUnauthorized(address forwarder, address workflowOwner, bytes10 workflowName, bytes2 reportName); + + /// @dev Mapping from a report ID to a boolean indicating whether the report is allowed or not + mapping(bytes32 reportId => bool isAllowed) internal s_allowedReports; + + /// @notice Sets permissions for multiple reports + /// @param permissions An array of Permission structs for which to set permissions + /// @dev Emits a ReportPermissionSet event for each permission set + function setReportPermissions(Permission[] memory permissions) external onlyOwner { + for (uint256 i; i < permissions.length; ++i) { + _setReportPermission(permissions[i]); + } + } + + /// @dev Internal function to set a single report permission + /// @param permission The Permission struct containing details about the permission to set + /// @dev Emits a ReportPermissionSet event + function _setReportPermission(Permission memory permission) internal { + bytes32 reportId = _createReportId( + permission.forwarder, + permission.workflowOwner, + permission.workflowName, + permission.reportName + ); + s_allowedReports[reportId] = permission.isAllowed; + emit ReportPermissionSet(reportId, permission); + } + + /// @dev Internal view function to validate if a report is allowed for a given set of details + /// @param forwarder The address of the forwarder + /// @param workflowOwner The address of the workflow owner + /// @param workflowName The name of the workflow in bytes10 + /// @param reportName The name of the report in bytes2 + /// @dev Reverts with Unauthorized if the report is not allowed + function _validateReportPermission( + address forwarder, + address workflowOwner, + bytes10 workflowName, + bytes2 reportName + ) internal view { + bytes32 reportId = _createReportId(forwarder, workflowOwner, workflowName, reportName); + if (!s_allowedReports[reportId]) { + revert ReportForwarderUnauthorized(forwarder, workflowOwner, workflowName, reportName); + } + } + + /// @notice Generates a unique report ID based on the provided parameters. + /// @dev The report ID is computed using the Keccak-256 hash function over the encoded parameters. + /// @param forwarder The address of the forwarder associated with the report. + /// @param workflowOwner The address of the owner of the workflow. + /// @param workflowName The name of the workflow, represented as a 10-byte value. + /// @param reportName The name of the report, represented as a 2-byte value. + /// @return reportId The computed unique report ID as a bytes32 value. + function _createReportId( + address forwarder, + address workflowOwner, + bytes10 workflowName, + bytes2 reportName + ) internal pure returns (bytes32 reportId) { + return keccak256(abi.encode(forwarder, workflowOwner, workflowName, reportName)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol new file mode 100644 index 0000000..3616667 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IReceiver} from "./interfaces/IReceiver.sol"; +import {IRouter} from "./interfaces/IRouter.sol"; +import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; + +/// @notice This is an entry point for `write_${chain}` Target capability. It allows nodes to +/// determine if reports have been processed (successfully or not) in a decentralized and +/// product-agnostic way by recording processed reports. +contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { + /// @notice This error is returned when the report is shorter than REPORT_METADATA_LENGTH, + /// which is the minimum length of a report. + error InvalidReport(); + + /// @notice This error is thrown whenever trying to set a config with a fault tolerance of 0. + error FaultToleranceMustBePositive(); + + /// @notice This error is thrown whenever configuration provides more signers than the maximum allowed number. + /// @param numSigners The number of signers who have signed the report + /// @param maxSigners The maximum number of signers that can sign a report + error ExcessSigners(uint256 numSigners, uint256 maxSigners); + + /// @notice This error is thrown whenever a configuration is provided with less than the minimum number of signers. + /// @param numSigners The number of signers provided + /// @param minSigners The minimum number of signers expected + error InsufficientSigners(uint256 numSigners, uint256 minSigners); + + /// @notice This error is thrown whenever a duplicate signer address is provided in the configuration. + /// @param signer The signer address that was duplicated. + error DuplicateSigner(address signer); + + /// @notice This error is thrown whenever a report has an incorrect number of signatures. + /// @param expected The number of signatures expected, F + 1 + /// @param received The number of signatures received + error InvalidSignatureCount(uint256 expected, uint256 received); + + /// @notice This error is thrown whenever a report specifies a configuration that does not exist. + /// @param configId (uint64(donId) << 32) | configVersion + error InvalidConfig(uint64 configId); + + /// @notice This error is thrown whenever a signer address is not in the configuration or + /// when trying to set a zero address as a signer. + /// @param signer The signer address that was not in the configuration + error InvalidSigner(address signer); + + /// @notice This error is thrown whenever a signature is invalid. + /// @param signature The signature that was invalid + error InvalidSignature(bytes signature); + + /// @notice Contains the signing address of each oracle + struct OracleSet { + uint8 f; // Number of faulty nodes allowed + address[] signers; + mapping(address signer => uint256 position) _positions; // 1-indexed to detect unset values + } + + struct Transmission { + address transmitter; + // This is true if the receiver is not a contract or does not implement the `IReceiver` interface. + bool invalidReceiver; + // Whether the transmission attempt was successful. If `false`, the transmission can be retried + // with an increased gas limit. + bool success; + // The amount of gas allocated for the `IReceiver.onReport` call. uint80 allows storing gas for known EVM block + // gas limits. Ensures that the minimum gas requested by the user is available during the transmission attempt. + // If the transmission fails (indicated by a `false` success state), it can be retried with an increased gas limit. + uint80 gasLimit; + } + + /// @notice Emitted when a report is processed + /// @param result The result of the attempted delivery. True if successful. + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); + + /// @notice Contains the configuration for each DON ID + /// configId (uint64(donId) << 32) | configVersion + mapping(uint64 configId => OracleSet oracleSet) internal s_configs; + + event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); + + string public constant override typeAndVersion = "Forwarder and Router 1.0.0"; + + constructor() OwnerIsCreator() { + s_forwarders[address(this)] = true; + } + + uint256 internal constant MAX_ORACLES = 31; + uint256 internal constant METADATA_LENGTH = 109; + uint256 internal constant FORWARDER_METADATA_LENGTH = 45; + uint256 internal constant SIGNATURE_LENGTH = 65; + + /// @dev This is the gas required to store `success` after the report is processed. + /// It is a warm storage write because of the packed struct. In practice it will cost less. + uint256 internal constant INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT = 5_000; + /// @dev This is the gas required to store the transmission struct and perform other checks. + uint256 internal constant INTERNAL_GAS_REQUIREMENTS = 25_000 + INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; + /// @dev This is the minimum gas required to route a report. This includes internal gas requirements + /// as well as the minimum gas that the user contract will receive. 30k * 3 gas is to account for + /// cases where consumers need close to the 30k limit provided in the supportsInterface check. + uint256 internal constant MINIMUM_GAS_LIMIT = INTERNAL_GAS_REQUIREMENTS + 30_000 * 3 + 10_000; + + // ================================================================ + // │ Router │ + // ================================================================ + + mapping(address forwarder => bool isForwarder) internal s_forwarders; + mapping(bytes32 transmissionId => Transmission transmission) internal s_transmissions; + + function addForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = true; + emit ForwarderAdded(forwarder); + } + + function removeForwarder(address forwarder) external onlyOwner { + s_forwarders[forwarder] = false; + emit ForwarderRemoved(forwarder); + } + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata validatedReport + ) public returns (bool) { + if (!s_forwarders[msg.sender]) revert UnauthorizedForwarder(); + + uint256 gasLimit = gasleft() - INTERNAL_GAS_REQUIREMENTS; + if (gasLimit < MINIMUM_GAS_LIMIT) revert InsufficientGasForRouting(transmissionId); + + Transmission memory transmission = s_transmissions[transmissionId]; + if (transmission.success || transmission.invalidReceiver) revert AlreadyAttempted(transmissionId); + + s_transmissions[transmissionId].transmitter = transmitter; + s_transmissions[transmissionId].gasLimit = uint80(gasLimit); + + // This call can consume up to 90k gas. + if (!ERC165Checker.supportsInterface(receiver, type(IReceiver).interfaceId)) { + s_transmissions[transmissionId].invalidReceiver = true; + return false; + } + + bool success; + bytes memory payload = abi.encodeCall(IReceiver.onReport, (metadata, validatedReport)); + + uint256 remainingGas = gasleft() - INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; + assembly { + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(remainingGas, receiver, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) + } + + if (success) { + s_transmissions[transmissionId].success = true; + } + return success; + } + + function getTransmissionId( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) public pure returns (bytes32) { + // This is slightly cheaper compared to `keccak256(abi.encode(receiver, workflowExecutionId, reportId));` + return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); + } + + function getTransmissionInfo( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (TransmissionInfo memory) { + bytes32 transmissionId = getTransmissionId(receiver, workflowExecutionId, reportId); + + Transmission memory transmission = s_transmissions[transmissionId]; + + TransmissionState state; + + if (transmission.transmitter == address(0)) { + state = IRouter.TransmissionState.NOT_ATTEMPTED; + } else if (transmission.invalidReceiver) { + state = IRouter.TransmissionState.INVALID_RECEIVER; + } else { + state = transmission.success ? IRouter.TransmissionState.SUCCEEDED : IRouter.TransmissionState.FAILED; + } + + return + TransmissionInfo({ + gasLimit: transmission.gasLimit, + invalidReceiver: transmission.invalidReceiver, + state: state, + success: transmission.success, + transmissionId: transmissionId, + transmitter: transmission.transmitter + }); + } + + /// @notice Get transmitter of a given report or 0x0 if it wasn't transmitted yet + function getTransmitter( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (address) { + return s_transmissions[getTransmissionId(receiver, workflowExecutionId, reportId)].transmitter; + } + + function isForwarder(address forwarder) external view returns (bool) { + return s_forwarders[forwarder]; + } + + // ================================================================ + // │ Forwarder │ + // ================================================================ + + function setConfig(uint32 donId, uint32 configVersion, uint8 f, address[] calldata signers) external onlyOwner { + if (f == 0) revert FaultToleranceMustBePositive(); + if (signers.length > MAX_ORACLES) revert ExcessSigners(signers.length, MAX_ORACLES); + if (signers.length <= 3 * f) revert InsufficientSigners(signers.length, 3 * f + 1); + + uint64 configId = (uint64(donId) << 32) | configVersion; + + // remove any old signer addresses + for (uint256 i = 0; i < s_configs[configId].signers.length; ++i) { + delete s_configs[configId]._positions[s_configs[configId].signers[i]]; + } + + // add new signer addresses + for (uint256 i = 0; i < signers.length; ++i) { + // assign indices, detect duplicates + address signer = signers[i]; + if (signer == address(0)) revert InvalidSigner(signer); + if (s_configs[configId]._positions[signer] != 0) revert DuplicateSigner(signer); + s_configs[configId]._positions[signer] = i + 1; + } + s_configs[configId].signers = signers; + s_configs[configId].f = f; + + emit ConfigSet(donId, configVersion, f, signers); + } + + function clearConfig(uint32 donId, uint32 configVersion) external onlyOwner { + // We are not removing old signer positions, because it is sufficient to + // clear the f value for `report` function. If we decide to restore + // the configId in the future, the setConfig function clears the positions. + s_configs[(uint64(donId) << 32) | configVersion].f = 0; + + emit ConfigSet(donId, configVersion, 0, new address[](0)); + } + + // send a report to receiver + function report( + address receiver, + bytes calldata rawReport, + bytes calldata reportContext, + bytes[] calldata signatures + ) external { + if (rawReport.length < METADATA_LENGTH) { + revert InvalidReport(); + } + + bytes32 workflowExecutionId; + bytes2 reportId; + { + uint64 configId; + (workflowExecutionId, configId, reportId) = _getMetadata(rawReport); + OracleSet storage config = s_configs[configId]; + + uint8 f = config.f; + // f can never be 0, so this means the config doesn't actually exist + if (f == 0) revert InvalidConfig(configId); + if (f + 1 != signatures.length) revert InvalidSignatureCount(f + 1, signatures.length); + + // validate signatures + bytes32 completeHash = keccak256(abi.encodePacked(keccak256(rawReport), reportContext)); + address[MAX_ORACLES + 1] memory signed; + for (uint256 i = 0; i < signatures.length; ++i) { + bytes calldata signature = signatures[i]; + if (signature.length != SIGNATURE_LENGTH) revert InvalidSignature(signature); + address signer = ecrecover( + completeHash, + uint8(signature[64]) + 27, + bytes32(signature[0:32]), + bytes32(signature[32:64]) + ); + + // validate signer is trusted and signature is unique + uint256 index = config._positions[signer]; + if (index == 0) revert InvalidSigner(signer); // index is 1-indexed so we can detect unset signers + if (signed[index] != address(0)) revert DuplicateSigner(signer); + signed[index] = signer; + } + } + + bool success = this.route( + getTransmissionId(receiver, workflowExecutionId, reportId), + msg.sender, + receiver, + rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], + rawReport[METADATA_LENGTH:] + ); + + emit ReportProcessed(receiver, workflowExecutionId, reportId, success); + } + + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _getMetadata( + bytes memory rawReport + ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { + // (first 32 bytes of memory contain length of the report) + // version // offset 32, size 1 + // workflow_execution_id // offset 33, size 32 + // timestamp // offset 65, size 4 + // don_id // offset 69, size 4 + // don_config_version, // offset 73, size 4 + // workflow_cid // offset 77, size 32 + // workflow_name // offset 109, size 10 + // workflow_owner // offset 119, size 20 + // report_id // offset 139, size 2 + assembly { + workflowExecutionId := mload(add(rawReport, 33)) + // shift right by 24 bytes to get the combined don_id and don_config_version + configId := shr(mul(24, 8), mload(add(rawReport, 69))) + reportId := mload(add(rawReport, 139)) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol new file mode 100644 index 0000000..d054434 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; +import {OCR2Abstract} from "./ocr/OCR2Abstract.sol"; + +/// @notice OCR2Base provides config management compatible with OCR3 +contract OCR3Capability is OwnerIsCreator, OCR2Abstract { + error InvalidConfig(string message); + error ReportingUnsupported(); + + string public constant override typeAndVersion = "Keystone 1.0.0"; + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + // makes it easier for offchain systems to extract config from logs. + uint32 internal s_latestConfigBlockNumber; + + // Storing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a single SLOAD. If any further fields are + // added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // TODO: could be optimized by squeezing into one slot + uint8 n; + } + ConfigInfo internal s_configInfo; + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param _signers addresses with which oracles sign the reports + /// @param _transmitters addresses oracles use to transmit the reports + /// @param _f number of faulty oracles the system can tolerate + /// @param _onchainConfig encoded on-chain contract configuration + /// @param _offchainConfigVersion version number for offchainEncoding schema + /// @param _offchainConfig encoded off-chain oracle configuration + /// @dev signer = [ 1 byte type | 2 byte len | n byte value ]... + function setConfig( + bytes[] calldata _signers, + address[] calldata _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol + for (uint256 i = 0; i < _signers.length; ++i) { + if (_transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); + // add new signers + bytes calldata publicKeys = _signers[i]; + uint256 offset = 0; + uint256 publicKeysLength = uint16(publicKeys.length); + // scan through public keys to validate encoded format + while (offset < publicKeysLength) { + if (offset + 3 > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); + uint256 keyLen = uint256(uint8(publicKeys[offset + 1])) + (uint256(uint8(publicKeys[offset + 2])) << 8); + if (offset + 3 + keyLen > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); + offset += 3 + keyLen; + } + } + s_configInfo.f = _f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _offchainConfigVersion, + _offchainConfig + ); + } + s_configInfo.n = uint8(_signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _offchainConfigVersion, + _offchainConfig + ); + } + + function _configDigestFromConfigData( + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + bytes[] calldata _signers, + address[] calldata _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + _chainId, + _contractAddress, + _configCount, + _signers, + _transmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x000e << (256 - 16); // 0x000e00..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata /* reportContext */, + bytes calldata /* report */, + bytes32[] calldata /* rs */, + bytes32[] calldata /* ss */, + bytes32 /* rawVs */ // signatures + ) external pure override { + revert ReportingUnsupported(); + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol new file mode 100644 index 0000000..6c14447 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice Interface for capability configuration contract. It MUST be +/// implemented for a contract to be used as a capability configuration. +/// The contract MAY store configuration that is shared across multiple +/// DON instances and capability versions. +/// @dev This interface does not guarantee the configuration contract's +/// correctness. It is the responsibility of the contract owner to ensure +/// that the configuration contract emits the CapabilityConfigurationSet +/// event when the configuration is set. +interface ICapabilityConfiguration { + /// @notice Emitted when a capability configuration is set. + event CapabilityConfigurationSet(); + + /// @notice Returns the capability configuration for a particular DON instance. + /// @dev donId is required to get DON-specific configuration. It avoids a + /// situation where configuration size grows too large. + /// @param donId The DON instance ID. These are stored in the CapabilitiesRegistry. + /// @return configuration DON's configuration for the capability. + function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration); + + /// @notice Called by the registry prior to the config being set for a particular DON. + /// @param nodes The nodes that the configuration is being set for. + /// @param donCapabilityConfig The configuration being set on the capability registry. + /// @param donCapabilityConfigCount The number of times the DON has been configured, tracked on the capability registry. + /// @param donId The DON ID on the capability registry. + function beforeCapabilityConfigSet( + bytes32[] calldata nodes, + bytes calldata donCapabilityConfig, + uint64 donCapabilityConfigCount, + uint32 donId + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol new file mode 100644 index 0000000..9afa1d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IReceiver - receives keystone reports +interface IReceiver { + /// @notice Handles incoming keystone reports. + /// @dev If this function call reverts, it can be retried with a higher gas + /// limit. The receiver is responsible for discarding stale reports. + /// @param metadata Report's metadata. + /// @param report Workflow report. + function onReport(bytes calldata metadata, bytes calldata report) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol new file mode 100644 index 0000000..3d2e24f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @title IRouter - delivers keystone reports to receiver +interface IRouter { + error UnauthorizedForwarder(); + /// @dev Thrown when the gas limit is insufficient for handling state after + /// calling the receiver function. + error InsufficientGasForRouting(bytes32 transmissionId); + error AlreadyAttempted(bytes32 transmissionId); + + event ForwarderAdded(address indexed forwarder); + event ForwarderRemoved(address indexed forwarder); + + enum TransmissionState { + NOT_ATTEMPTED, + SUCCEEDED, + INVALID_RECEIVER, + FAILED + } + + struct TransmissionInfo { + bytes32 transmissionId; + TransmissionState state; + address transmitter; + // This is true if the receiver is not a contract or does not implement the + // `IReceiver` interface. + bool invalidReceiver; + // Whether the transmission attempt was successful. If `false`, the + // transmission can be retried with an increased gas limit. + bool success; + // The amount of gas allocated for the `IReceiver.onReport` call. uint80 + // allows storing gas for known EVM block gas limits. + // Ensures that the minimum gas requested by the user is available during + // the transmission attempt. If the transmission fails (indicated by a + // `false` success state), it can be retried with an increased gas limit. + uint80 gasLimit; + } + + function addForwarder(address forwarder) external; + function removeForwarder(address forwarder) external; + + function route( + bytes32 transmissionId, + address transmitter, + address receiver, + bytes calldata metadata, + bytes calldata report + ) external returns (bool); + + function getTransmissionId( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external pure returns (bytes32); + function getTransmissionInfo( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (TransmissionInfo memory); + function getTransmitter( + address receiver, + bytes32 workflowExecutionId, + bytes2 reportId + ) external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol new file mode 100644 index 0000000..2eb9b55 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library KeystoneFeedDefaultMetadataLib { + /** + * Metadata Layout: + * + * +-------------------------------+--------------------+---------------------+---------------+ + * | 32 bytes (length prefix) | 32 bytes | 10 bytes | 20 bytes | 2 bytes | + * | (Not used in function) | workflow_cid | workflow_name | workflow_owner| report_name | + * +-------------------------------+--------------------+---------------------+---------------+----------------+ + * | | | | | | + * | (Offset 0) | (Offset 32) | (Offset 64) | (Offset 74) | (Offset 94) | + * +-------------------------------+--------------------+---------------------+---------------+----------------+ + * @dev used to slice metadata bytes into workflowName, workflowOwner and report name + */ + function _extractMetadataInfo( + bytes memory metadata + ) internal pure returns (bytes10 workflowName, address workflowOwner, bytes2 reportName) { + // (first 32 bytes contain length of the byte array) + // workflow_cid // offset 32, size 32 + // workflow_name // offset 64, size 10 + // workflow_owner // offset 74, size 20 + // report_name // offset 94, size 2 + assembly { + // no shifting needed for bytes10 type + workflowName := mload(add(metadata, 64)) + // shift right by 12 bytes to get the actual value + workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) + // no shifting needed for bytes2 type + reportName := mload(add(metadata, 94)) + } + return (workflowName, workflowOwner, reportName); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol new file mode 100644 index 0000000..af822a6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /** + * @notice triggers a new run of the offchain reporting protocol + * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + * @param configDigest configDigest of this configuration + * @param configCount ordinal number of this config setting among all config settings over the life of this contract + * @param signers ith element is address ith oracle uses to sign a report + * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + bytes[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param transmitters addresses oracles use to transmit the reports + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + */ + function setConfig( + bytes[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /** + * @notice information about current offchain reporting protocol configuration + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + */ + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + /** + * @notice optionally emitted to indicate the latest configDigest and epoch for + which a report was successfully transmitted. Alternatively, the contract may + use latestConfigDigestAndEpoch with scanLogs set to false. + */ + event Transmitted(bytes32 configDigest, uint32 epoch); + + /** + * @notice optionally returns the latest configDigest and epoch for which a + report was successfully transmitted. Alternatively, the contract may return + scanLogs set to true and use Transmitted events to provide this information + to offchain watchers. + * @return scanLogs indicates whether to rely on the configDigest and epoch + returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice transmit is called to post a new report to the contract + * @param report serialized report, which the signatures are signing. + * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + * @param rawVs ith element is the the V component of the ith signature + */ + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol new file mode 100644 index 0000000..64dc018 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {Constants} from "./Constants.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract BaseTest is Test, Constants { + CapabilitiesRegistry internal s_CapabilitiesRegistry; + CapabilityConfigurationContract internal s_capabilityConfigurationContract; + CapabilitiesRegistry.Capability internal s_basicCapability; + CapabilitiesRegistry.Capability internal s_capabilityWithConfigurationContract; + bytes32 internal s_basicHashedCapabilityId; + bytes32 internal s_capabilityWithConfigurationContractId; + bytes32 internal s_nonExistentHashedCapabilityId; + + function setUp() public virtual { + vm.startPrank(ADMIN); + s_CapabilitiesRegistry = new CapabilitiesRegistry(); + s_capabilityConfigurationContract = new CapabilityConfigurationContract(); + + s_basicCapability = CapabilitiesRegistry.Capability({ + labelledName: "data-streams-reports", + version: "1.0.0", + responseType: CapabilitiesRegistry.CapabilityResponseType.REPORT, + configurationContract: address(0), + capabilityType: CapabilitiesRegistry.CapabilityType.TRIGGER + }); + s_capabilityWithConfigurationContract = CapabilitiesRegistry.Capability({ + labelledName: "read-ethereum-mainnet-gas-price", + version: "1.0.2", + responseType: CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, + configurationContract: address(s_capabilityConfigurationContract), + capabilityType: CapabilitiesRegistry.CapabilityType.ACTION + }); + + s_basicHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + s_capabilityWithConfigurationContractId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_capabilityWithConfigurationContract.labelledName, + s_capabilityWithConfigurationContract.version + ); + s_nonExistentHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); + } + + function _getNodeOperators() internal pure returns (CapabilitiesRegistry.NodeOperator[] memory) { + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](3); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NODE_OPERATOR_ONE_ADMIN, + name: NODE_OPERATOR_ONE_NAME + }); + nodeOperators[1] = CapabilitiesRegistry.NodeOperator({ + admin: NODE_OPERATOR_TWO_ADMIN, + name: NODE_OPERATOR_TWO_NAME + }); + nodeOperators[2] = CapabilitiesRegistry.NodeOperator({admin: NODE_OPERATOR_THREE, name: NODE_OPERATOR_THREE_NAME}); + return nodeOperators; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol new file mode 100644 index 0000000..7bee2b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; +import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +contract CapabilitiesRegistry_AddCapabilitiesTest is BaseTest { + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_basicCapability; + + vm.expectRevert("Only callable by owner"); + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_RevertWhen_CapabilityExists() public { + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_basicCapability; + + // Successfully add the capability the first time + s_CapabilitiesRegistry.addCapabilities(capabilities); + + // Try to add the same capability again + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityAlreadyExists.selector, s_basicHashedCapabilityId) + ); + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_RevertWhen_ConfigurationContractNotDeployed() public { + address nonExistentContract = address(1); + s_capabilityWithConfigurationContract.configurationContract = nonExistentContract; + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_capabilityWithConfigurationContract; + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, + nonExistentContract + ) + ); + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { + address contractWithoutERC165 = address(9999); + vm.mockCall( + contractWithoutERC165, + abi.encodeWithSelector( + IERC165.supportsInterface.selector, + ICapabilityConfiguration.getCapabilityConfiguration.selector ^ + ICapabilityConfiguration.beforeCapabilityConfigSet.selector + ), + abi.encode(false) + ); + s_capabilityWithConfigurationContract.configurationContract = contractWithoutERC165; + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_capabilityWithConfigurationContract; + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, + contractWithoutERC165 + ) + ); + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_AddCapability_NoConfigurationContract() public { + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_basicCapability; + + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("data-streams-reports", "1.0.0"); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); + s_CapabilitiesRegistry.addCapabilities(capabilities); + CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( + hashedCapabilityId + ); + + assertEq(storedCapability.labelledName, s_basicCapability.labelledName); + assertEq(storedCapability.version, s_basicCapability.version); + assertEq(uint256(storedCapability.responseType), uint256(s_basicCapability.responseType)); + assertEq(storedCapability.configurationContract, s_basicCapability.configurationContract); + } + + function test_AddCapability_WithConfiguration() public { + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); + capabilities[0] = s_capabilityWithConfigurationContract; + + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_capabilityWithConfigurationContract.labelledName, + s_capabilityWithConfigurationContract.version + ); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( + hashedCapabilityId + ); + + assertEq(storedCapability.labelledName, s_capabilityWithConfigurationContract.labelledName); + assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); + assertEq(uint256(storedCapability.responseType), uint256(s_capabilityWithConfigurationContract.responseType)); + assertEq(storedCapability.configurationContract, s_capabilityWithConfigurationContract.configurationContract); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol new file mode 100644 index 0000000..4e8725a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; +import {MaliciousConfigurationContract} from "./mocks/MaliciousConfigurationContract.sol"; + +contract CapabilitiesRegistry_AddDONTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + hashedCapabilityIds: capabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + changePrank(ADMIN); + } + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + bytes32[] memory nodes = new bytes32[](1); + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_NodeDoesNotSupportCapability() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, + P2P_ID_TWO, + s_capabilityWithConfigurationContractId + ) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_CapabilityDoesNotExist() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_nonExistentHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_FaultToleranceIsZero() public { + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidFaultTolerance.selector, 0, 1)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, 0); + } + + function test_RevertWhen_DuplicateCapabilityAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_DeprecatedCapabilityAdded() public { + bytes32 capabilityId = s_basicHashedCapabilityId; + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = capabilityId; + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: capabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_DuplicateNodeAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 2, P2P_ID)); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_AddDON() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, 1); + vm.expectCall( + address(s_capabilityConfigurationContract), + abi.encodeWithSelector( + ICapabilityConfiguration.beforeCapabilityConfigSet.selector, + nodes, + CONFIG_CAPABILITY_CONFIG, + 1, + DON_ID + ), + 1 + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); + assertEq(donInfo.id, DON_ID); + assertEq(donInfo.configCount, 1); + assertEq(donInfo.isPublic, true); + assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); + assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry + .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); + assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); + assertEq(capabilityConfigContractConfig, bytes("")); + + ( + bytes memory CapabilitiesRegistryDONConfigTwo, + bytes memory capabilityConfigContractConfigTwo + ) = s_CapabilitiesRegistry.getCapabilityConfigs(DON_ID, s_capabilityWithConfigurationContractId); + assertEq(CapabilitiesRegistryDONConfigTwo, CONFIG_CAPABILITY_CONFIG); + assertEq(capabilityConfigContractConfigTwo, CONFIG_CAPABILITY_CONFIG); + + assertEq(donInfo.nodeP2PIds.length, nodes.length); + assertEq(donInfo.nodeP2PIds[0], P2P_ID); + assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); + } +} + +contract CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationConfigured is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + + address maliciousConfigContractAddr = address( + new MaliciousConfigurationContract(s_capabilityWithConfigurationContractId) + ); + s_basicCapability.configurationContract = maliciousConfigContractAddr; + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = maliciousConfigContractAddr; + nodeOperators[1].admin = maliciousConfigContractAddr; + nodeOperators[2].admin = maliciousConfigContractAddr; + + s_CapabilitiesRegistry.addNodeOperators(nodeOperators); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory capabilityIds = new bytes32[](1); + capabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + hashedCapabilityIds: capabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + changePrank(ADMIN); + } + + function test_RevertWhen_MaliciousCapabilitiesConfigContractTriesToRemoveCapabilitiesFromDONNodes() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityRequiredByDON.selector, s_basicHashedCapabilityId, DON_ID) + ); + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol new file mode 100644 index 0000000..b4f7be9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_AddNodeOperatorsTest is BaseTest { + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_NodeOperatorAdminAddressZero() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); + nodeOperators[0].admin = address(0); + vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); + s_CapabilitiesRegistry.addNodeOperators(nodeOperators); + } + + function test_AddNodeOperators() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorAdded( + TEST_NODE_OPERATOR_ONE_ID, + NODE_OPERATOR_ONE_ADMIN, + NODE_OPERATOR_ONE_NAME + ); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorAdded( + TEST_NODE_OPERATOR_TWO_ID, + NODE_OPERATOR_TWO_ADMIN, + NODE_OPERATOR_TWO_NAME + ); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_ONE_ID + ); + assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_TWO_ID + ); + assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol new file mode 100644 index 0000000..aa6cca4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_AddNodesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + changePrank(ADMIN); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidNodeOperator() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + uint32 invalidNodeOperatorId = 10000; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: invalidNodeOperatorId, // Invalid NOP + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) + ); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: bytes32(""), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_EncryptionPublicKeyEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: bytes32(""), + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_SignerAddressNotUnique() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + changePrank(NODE_OPERATOR_TWO_ADMIN); + + // Try adding another node with the same signer address + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingDuplicateP2PId() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeAlreadyExists.selector, P2P_ID)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeP2PId.selector, bytes32(""))); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](0); + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_AddsNodeParams() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + s_CapabilitiesRegistry.addNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.hashedCapabilityIds.length, 2); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(node.configCount, 1); + } + + function test_OwnerCanAddNodes() public { + changePrank(ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + s_CapabilitiesRegistry.addNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.hashedCapabilityIds.length, 2); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(node.configCount, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol new file mode 100644 index 0000000..e06fa4a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_DeprecateCapabilitiesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + + vm.expectRevert("Only callable by owner"); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + } + + function test_RevertWhen_CapabilityDoesNotExist() public { + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = s_nonExistentHashedCapabilityId; + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + ); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + } + + function test_RevertWhen_CapabilityIsDeprecated() public { + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, hashedCapabilityId)); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + } + + function test_DeprecatesCapability() public { + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + assertEq(s_CapabilitiesRegistry.isCapabilityDeprecated(hashedCapabilityId), true); + } + + function test_EmitsEvent() public { + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.CapabilityDeprecated(hashedCapabilityId); + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol new file mode 100644 index 0000000..8f39183 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetCapabilitiesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + s_CapabilitiesRegistry.addCapabilities(capabilities); + } + + function test_ReturnsCapabilities() public { + bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( + s_basicCapability.labelledName, + s_basicCapability.version + ); + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = hashedCapabilityId; + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + + CapabilitiesRegistry.CapabilityInfo[] memory capabilities = s_CapabilitiesRegistry.getCapabilities(); + + assertEq(capabilities.length, 2); + + assertEq(capabilities[0].labelledName, "data-streams-reports"); + assertEq(capabilities[0].version, "1.0.0"); + assertEq(uint256(capabilities[0].responseType), uint256(CapabilitiesRegistry.CapabilityResponseType.REPORT)); + assertEq(uint256(capabilities[0].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.TRIGGER)); + assertEq(capabilities[0].configurationContract, address(0)); + assertEq(capabilities[0].hashedId, keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); + assertEq(capabilities[0].isDeprecated, true); + + assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); + assertEq(capabilities[1].version, "1.0.2"); + assertEq( + uint256(capabilities[1].responseType), + uint256(CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) + ); + assertEq(uint256(capabilities[1].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.ACTION)); + assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); + assertEq(capabilities[1].hashedId, keccak256(abi.encode(capabilities[1].labelledName, capabilities[1].version))); + assertEq(capabilities[1].isDeprecated, false); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol new file mode 100644 index 0000000..6d8dd13 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; + +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetDONsTest is BaseTest { + CapabilitiesRegistry.CapabilityConfiguration[] private s_capabilityConfigs; + + function setUp() public override { + BaseTest.setUp(); + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + + s_capabilityConfigs.push( + CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }) + ); + + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, true, true, 1); + s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, false, false, 1); + } + + function test_CorrectlyFetchesDONs() public view { + CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); + assertEq(dons.length, 2); + assertEq(dons[0].id, DON_ID); + assertEq(dons[0].configCount, 1); + assertEq(dons[0].isPublic, true); + assertEq(dons[0].acceptsWorkflows, true); + assertEq(dons[0].f, 1); + assertEq(dons[0].capabilityConfigurations.length, s_capabilityConfigs.length); + assertEq(dons[0].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + + assertEq(dons[1].id, DON_ID_TWO); + assertEq(dons[1].configCount, 1); + assertEq(dons[1].isPublic, false); + assertEq(dons[1].capabilityConfigurations.length, s_capabilityConfigs.length); + assertEq(dons[1].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + } + + function test_DoesNotIncludeRemovedDONs() public { + uint32[] memory removedDONIDs = new uint32[](1); + removedDONIDs[0] = DON_ID; + s_CapabilitiesRegistry.removeDONs(removedDONIDs); + + CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); + assertEq(dons.length, 1); + assertEq(dons[0].id, DON_ID_TWO); + assertEq(dons[0].configCount, 1); + assertEq(dons[0].isPublic, false); + assertEq(dons[0].acceptsWorkflows, false); + assertEq(dons[0].f, 1); + assertEq(dons[0].capabilityConfigurations.length, s_capabilityConfigs.length); + assertEq(dons[0].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol new file mode 100644 index 0000000..cdfb0eb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; + +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetHashedCapabilityTest is BaseTest { + string constant CAPABILITY_LABELLED_NAME = "ccip1"; + string constant CAPABILITY_VERSION = "1.0.0"; + + function test_CorrectlyGeneratesHashedCapabilityId() public view { + bytes32 expectedHashedCapabilityId = keccak256(abi.encode(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION)); + + assertEq( + s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), + expectedHashedCapabilityId + ); + } + + function test_DoesNotCauseIncorrectClashes() public view { + assertNotEq( + s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), + s_CapabilitiesRegistry.getHashedCapabilityId("ccip", "11.0.0") + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol new file mode 100644 index 0000000..471f4a8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetNodeOperatorsTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_CorrectlyFetchesNodeOperators() public view { + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); + assertEq(nodeOperators.length, 3); + + assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperators[0].name, NODE_OPERATOR_ONE_NAME); + + assertEq(nodeOperators[1].admin, NODE_OPERATOR_TWO_ADMIN); + assertEq(nodeOperators[1].name, NODE_OPERATOR_TWO_NAME); + + assertEq(nodeOperators[2].admin, NODE_OPERATOR_THREE); + assertEq(nodeOperators[2].name, NODE_OPERATOR_THREE_NAME); + } + + function test_DoesNotIncludeRemovedNodeOperators() public { + changePrank(ADMIN); + uint32[] memory nodeOperatorsToRemove = new uint32[](1); + nodeOperatorsToRemove[0] = 2; + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); + assertEq(nodeOperators.length, 2); + + assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); + assertEq(nodeOperators[0].name, NODE_OPERATOR_ONE_NAME); + assertEq(nodeOperators[1].admin, NODE_OPERATOR_THREE); + assertEq(nodeOperators[1].name, NODE_OPERATOR_THREE_NAME); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol new file mode 100644 index 0000000..4fc150e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_GetNodesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_CorrectlyFetchesNodes() public view { + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); + assertEq(nodes.length, 2); + + assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(nodes[0].signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + assertEq(nodes[0].p2pId, P2P_ID); + assertEq(nodes[0].hashedCapabilityIds.length, 2); + assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(nodes[0].configCount, 1); + + assertEq(nodes[1].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(nodes[1].signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); + assertEq(nodes[1].p2pId, P2P_ID_TWO); + assertEq(nodes[1].hashedCapabilityIds.length, 2); + assertEq(nodes[1].hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(nodes[1].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(nodes[1].configCount, 1); + } + + function test_DoesNotIncludeRemovedNodes() public { + changePrank(ADMIN); + bytes32[] memory nodesToRemove = new bytes32[](1); + nodesToRemove[0] = P2P_ID_TWO; + s_CapabilitiesRegistry.removeNodes(nodesToRemove); + + CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); + assertEq(nodes.length, 1); + + assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(nodes[0].signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + assertEq(nodes[0].p2pId, P2P_ID); + assertEq(nodes[0].hashedCapabilityIds.length, 2); + assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(nodes[0].configCount, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol new file mode 100644 index 0000000..c3a8dc1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; + +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_RemoveDONsTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); + } + + function test_RevertWhen_CalledByNonAdmin() public { + uint32[] memory donIDs = new uint32[](1); + donIDs[0] = 1; + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + s_CapabilitiesRegistry.removeDONs(donIDs); + } + + function test_RevertWhen_DONDoesNotExist() public { + uint32 invalidDONId = 10; + uint32[] memory donIDs = new uint32[](1); + donIDs[0] = invalidDONId; + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, invalidDONId)); + s_CapabilitiesRegistry.removeDONs(donIDs); + } + + function test_RemovesDON() public { + uint32[] memory donIDs = new uint32[](1); + donIDs[0] = DON_ID; + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, 0); + s_CapabilitiesRegistry.removeDONs(donIDs); + + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); + assertEq(donInfo.id, 0); + assertEq(donInfo.configCount, 0); + assertEq(donInfo.isPublic, false); + assertEq(donInfo.capabilityConfigurations.length, 0); + + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry + .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); + + assertEq(CapabilitiesRegistryDONConfig, bytes("")); + assertEq(capabilityConfigContractConfig, bytes("")); + assertEq(donInfo.nodeP2PIds.length, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol new file mode 100644 index 0000000..1f70bc8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_RemoveNodeOperatorsTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonOwner() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + uint32[] memory nodeOperatorsToRemove = new uint32[](2); + nodeOperatorsToRemove[1] = 1; + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); + } + + function test_RemovesNodeOperator() public { + changePrank(ADMIN); + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); + uint32[] memory nodeOperatorsToRemove = new uint32[](2); + nodeOperatorsToRemove[0] = TEST_NODE_OPERATOR_ONE_ID; + nodeOperatorsToRemove[1] = TEST_NODE_OPERATOR_TWO_ID; + s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_ONE_ID + ); + assertEq(nodeOperatorOne.admin, address(0)); + assertEq(nodeOperatorOne.name, ""); + + CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_TWO_ID + ); + assertEq(nodeOperatorTwo.admin, address(0)); + assertEq(nodeOperatorTwo.name, ""); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol new file mode 100644 index 0000000..dfe63e2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(ADMIN); + + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.removeNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = INVALID_P2P_ID; + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + s_CapabilitiesRegistry.removeNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = bytes32(""); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + s_CapabilitiesRegistry.removeNodes(nodes); + } + + function test_RevertWhen_NodePartOfCapabilitiesDON() public { + changePrank(ADMIN); + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, false, F_VALUE); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfCapabilitiesDON.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.removeNodes(nodes); + } + + function test_CanRemoveWhenDONDeleted() public { + changePrank(ADMIN); + + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + // Add DON + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + // Try remove nodes + bytes32[] memory removedNodes = new bytes32[](1); + removedNodes[0] = P2P_ID; + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.removeNodes(removedNodes); + + // Remove DON + uint32[] memory donIds = new uint32[](1); + donIds[0] = DON_ID; + s_CapabilitiesRegistry.removeDONs(donIds); + + // Remove node + s_CapabilitiesRegistry.removeNodes(removedNodes); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, bytes32("")); + assertEq(node.hashedCapabilityIds.length, 0); + assertEq(node.configCount, 0); + } + + function test_CanRemoveWhenNodeNoLongerPartOfDON() public { + changePrank(ADMIN); + + bytes32[] memory nodes = new bytes32[](3); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + nodes[2] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + // Add DON + s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); + + // Try remove nodes + bytes32[] memory removedNodes = new bytes32[](1); + removedNodes[0] = P2P_ID_TWO; + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID_TWO)); + s_CapabilitiesRegistry.removeNodes(removedNodes); + + // Update nodes in DON + bytes32[] memory updatedNodes = new bytes32[](2); + updatedNodes[0] = P2P_ID; + updatedNodes[1] = P2P_ID_THREE; + s_CapabilitiesRegistry.updateDON(DON_ID, updatedNodes, capabilityConfigs, true, F_VALUE); + + // Remove node + s_CapabilitiesRegistry.removeNodes(removedNodes); + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, bytes32("")); + assertEq(node.hashedCapabilityIds.length, 0); + assertEq(node.configCount, 0); + } + + function test_RemovesNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeRemoved(P2P_ID); + s_CapabilitiesRegistry.removeNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, bytes32("")); + assertEq(node.hashedCapabilityIds.length, 0); + assertEq(node.configCount, 0); + } + + function test_CanAddNodeWithSameSignerAddressAfterRemoving() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + s_CapabilitiesRegistry.removeNodes(nodes); + + CapabilitiesRegistry.NodeParams[] memory nodeParams = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodeParams[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodeParams); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.hashedCapabilityIds.length, 2); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); + assertEq(node.configCount, 1); + } + + function test_OwnerCanRemoveNodes() public { + changePrank(ADMIN); + + bytes32[] memory nodes = new bytes32[](1); + nodes[0] = P2P_ID; + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeRemoved(P2P_ID); + s_CapabilitiesRegistry.removeNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, 0); + assertEq(node.p2pId, bytes32("")); + assertEq(node.signer, bytes32("")); + assertEq(node.hashedCapabilityIds.length, 0); + assertEq(node.configCount, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol new file mode 100644 index 0000000..00ce88f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; + +contract CapabilitiesRegistry_TypeAndVersionTest is BaseTest { + function test_TypeAndVersion() public view { + assertEq(s_CapabilitiesRegistry.typeAndVersion(), "CapabilitiesRegistry 1.0.0"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol new file mode 100644 index 0000000..52b496d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_UpdateDONTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); + bytes32[] memory capabilityIds = new bytes32[](2); + capabilityIds[0] = s_basicHashedCapabilityId; + capabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: capabilityIds + }); + + bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); + nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: nodeTwoCapabilityIds + }); + + nodes[2] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + hashedCapabilityIds: capabilityIds + }); + + s_CapabilitiesRegistry.addNodes(nodes); + + bytes32[] memory donNodes = new bytes32[](2); + donNodes[0] = P2P_ID; + donNodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + s_CapabilitiesRegistry.addDON(donNodes, capabilityConfigs, true, true, F_VALUE); + } + + function test_RevertWhen_CalledByNonAdmin() public { + changePrank(STRANGER); + vm.expectRevert("Only callable by owner"); + bytes32[] memory nodes = new bytes32[](1); + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_NodeDoesNotSupportCapability() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, + P2P_ID_TWO, + s_capabilityWithConfigurationContractId + ) + ); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_DONDoesNotExist() public { + uint32 nonExistentDONId = 10; + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, nonExistentDONId)); + s_CapabilitiesRegistry.updateDON(nonExistentDONId, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_CapabilityDoesNotExist() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_nonExistentHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) + ); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_DuplicateCapabilityAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) + ); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_DeprecatedCapabilityAdded() public { + bytes32 capabilityId = s_basicHashedCapabilityId; + bytes32[] memory deprecatedCapabilities = new bytes32[](1); + deprecatedCapabilities[0] = capabilityId; + s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); + + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_TWO; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: capabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_RevertWhen_DuplicateNodeAdded() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); + } + + function test_UpdatesDON() public { + bytes32[] memory nodes = new bytes32[](2); + nodes[0] = P2P_ID; + nodes[1] = P2P_ID_THREE; + + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_capabilityWithConfigurationContractId, + config: CONFIG_CAPABILITY_CONFIG + }); + + CapabilitiesRegistry.DONInfo memory oldDONInfo = s_CapabilitiesRegistry.getDON(DON_ID); + + bool expectedDONIsPublic = false; + uint32 expectedConfigCount = oldDONInfo.configCount + 1; + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.ConfigSet(DON_ID, expectedConfigCount); + vm.expectCall( + address(s_capabilityConfigurationContract), + abi.encodeWithSelector( + ICapabilityConfiguration.beforeCapabilityConfigSet.selector, + nodes, + CONFIG_CAPABILITY_CONFIG, + expectedConfigCount, + DON_ID + ), + 1 + ); + s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, expectedDONIsPublic, F_VALUE); + + CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); + assertEq(donInfo.id, DON_ID); + assertEq(donInfo.configCount, expectedConfigCount); + assertEq(donInfo.isPublic, false); + assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); + assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); + + (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry + .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); + assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); + assertEq(capabilityConfigContractConfig, bytes("")); + + assertEq(donInfo.nodeP2PIds.length, nodes.length); + assertEq(donInfo.nodeP2PIds[0], P2P_ID); + assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol new file mode 100644 index 0000000..8f6be58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_UpdateNodeOperatorTest is BaseTest { + uint32 private constant TEST_NODE_OPERATOR_ID = 1; + address private constant NEW_NODE_OPERATOR_ADMIN = address(3); + string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; + + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + } + + function test_RevertWhen_CalledByNonAdminAndNonOwner() public { + changePrank(STRANGER); + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: ADMIN, name: NEW_NODE_OPERATOR_NAME}); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32 invalidNodeOperatorId = 10000; + uint32[] memory nodeOperatorIds = new uint32[](2); + nodeOperatorIds[0] = invalidNodeOperatorId; + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.LengthMismatch.selector, nodeOperatorIds.length, nodeOperators.length) + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_RevertWhen_NodeOperatorDoesNotExist() public { + changePrank(ADMIN); + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32 invalidNodeOperatorId = 10000; + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = invalidNodeOperatorId; + vm.expectRevert( + abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + } + + function test_UpdatesNodeOperator() public { + changePrank(ADMIN); + + CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ + admin: NEW_NODE_OPERATOR_ADMIN, + name: NEW_NODE_OPERATOR_NAME + }); + + uint32[] memory nodeOperatorIds = new uint32[](1); + nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; + + vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeOperatorUpdated( + TEST_NODE_OPERATOR_ID, + NEW_NODE_OPERATOR_ADMIN, + NEW_NODE_OPERATOR_NAME + ); + s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); + + CapabilitiesRegistry.NodeOperator memory nodeOperator = s_CapabilitiesRegistry.getNodeOperator( + TEST_NODE_OPERATOR_ID + ); + assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); + assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol new file mode 100644 index 0000000..218161f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./BaseTest.t.sol"; +import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; + +contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { + function setUp() public override { + BaseTest.setUp(); + changePrank(ADMIN); + CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); + capabilities[0] = s_basicCapability; + capabilities[1] = s_capabilityWithConfigurationContract; + + s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); + s_CapabilitiesRegistry.addCapabilities(capabilities); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](2); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_ONE_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + changePrank(NODE_OPERATOR_TWO_ADMIN); + s_CapabilitiesRegistry.addNodes(nodes); + } + + function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { + changePrank(STRANGER); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_CalledByAnotherNodeOperatorAdmin() public { + changePrank(NODE_OPERATOR_TWO_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, NODE_OPERATOR_TWO_ADMIN)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeDoesNotExist() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: INVALID_P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_P2PIDEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: bytes32(""), + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_SignerAddressEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: bytes32(""), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_EncryptionPublicKeyEmpty() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: bytes32(""), + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(CapabilitiesRegistry.InvalidNodeSigner.selector); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](0); + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_AddingNodeWithInvalidCapability() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() public { + // SETUP: addDON + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + // SETUP: updateNodes + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + // DON requires s_basicHashedCapabilityId but we are swapping for + // s_capabilityWithConfigurationContractId + hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + uint32 workflowDonId = 1; + + // Operations + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.CapabilityRequiredByDON.selector, + s_basicHashedCapabilityId, + workflowDonId + ) + ); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() public { + // SETUP: addDON + CapabilitiesRegistry.CapabilityConfiguration[] + memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); + capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ + capabilityId: s_basicHashedCapabilityId, + config: BASIC_CAPABILITY_CONFIG + }); + bytes32[] memory nodeIds = new bytes32[](2); + nodeIds[0] = P2P_ID; + nodeIds[1] = P2P_ID_TWO; + + // SETUP: updateNodes + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + // DON requires s_basicHashedCapabilityId but we are swapping for + // s_capabilityWithConfigurationContractId + hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + uint32 capabilitiesDonId = 1; + + // Operations + changePrank(ADMIN); + s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, false, 1); + + vm.expectRevert( + abi.encodeWithSelector( + CapabilitiesRegistry.CapabilityRequiredByDON.selector, + s_basicHashedCapabilityId, + capabilitiesDonId + ) + ); + s_CapabilitiesRegistry.updateNodes(nodes); + } + + function test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + // Set node one's signer to another address + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: bytes32(abi.encodePacked(address(6666))), + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + s_CapabilitiesRegistry.updateNodes(nodes); + + // Set node two's signer to node one's signer + changePrank(NODE_OPERATOR_TWO_ADMIN); + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID_TWO, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, + hashedCapabilityIds: hashedCapabilityIds + }); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); + assertEq(node.signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); + } + + function test_UpdatesNodeParams() public { + changePrank(NODE_OPERATOR_ONE_ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NEW_NODE_SIGNER); + assertEq(node.hashedCapabilityIds.length, 1); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.configCount, 2); + } + + function test_OwnerCanUpdateNodes() public { + changePrank(ADMIN); + + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectEmit(address(s_CapabilitiesRegistry)); + emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); + s_CapabilitiesRegistry.updateNodes(nodes); + + CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); + assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); + assertEq(node.p2pId, P2P_ID); + assertEq(node.signer, NEW_NODE_SIGNER); + assertEq(node.hashedCapabilityIds.length, 1); + assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); + assertEq(node.configCount, 2); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol new file mode 100644 index 0000000..a0501a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +contract Constants { + address internal constant ADMIN = address(1); + address internal constant STRANGER = address(2); + + uint32 internal constant TEST_NODE_OPERATOR_ONE_ID = 1; + address internal constant NODE_OPERATOR_ONE_ADMIN = address(3); + string internal constant NODE_OPERATOR_ONE_NAME = "node-operator-one"; + bytes32 internal constant NODE_OPERATOR_ONE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(3333))); + bytes32 internal constant P2P_ID = hex"e42415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY = bytes32("test-encryption-public-key"); + + uint32 internal constant TEST_NODE_OPERATOR_TWO_ID = 2; + address internal constant NODE_OPERATOR_TWO_ADMIN = address(4); + string internal constant NODE_OPERATOR_TWO_NAME = "node-operator-two"; + bytes32 internal constant NODE_OPERATOR_TWO_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(4444))); + bytes32 internal constant P2P_ID_TWO = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_TWO = bytes32("test-encryption-public-key-2"); + + uint32 internal constant TEST_NODE_OPERATOR_THREE_ID = 3; + address internal constant NODE_OPERATOR_THREE = address(4); + string internal constant NODE_OPERATOR_THREE_NAME = "node-operator-three"; + bytes32 internal constant NODE_OPERATOR_THREE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(5555))); + bytes32 internal constant P2P_ID_THREE = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a06"; + bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_THREE = bytes32("test-encryption-public-key-3"); + + uint8 internal constant F_VALUE = 1; + uint32 internal constant DON_ID = 1; + uint32 internal constant DON_ID_TWO = 2; + + bytes32 internal constant INVALID_P2P_ID = bytes32("fake-p2p"); + bytes32 internal constant NEW_NODE_SIGNER = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a07"; + + bytes internal constant BASIC_CAPABILITY_CONFIG = bytes("basic-capability-config"); + bytes internal constant CONFIG_CAPABILITY_CONFIG = bytes("config-capability-config"); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol new file mode 100644 index 0000000..0dd480a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {Receiver} from "./mocks/Receiver.sol"; +import {KeystoneForwarder} from "../KeystoneForwarder.sol"; + +contract BaseTest is Test { + address internal ADMIN = address(1); + address internal constant TRANSMITTER = address(50); + uint256 internal constant MAX_ORACLES = 31; + uint32 internal DON_ID = 0x01020304; + uint8 internal F = 1; + uint32 internal CONFIG_VERSION = 1; + + struct Signer { + uint256 mockPrivateKey; + address signerAddress; + } + + Signer[MAX_ORACLES] internal s_signers; + KeystoneForwarder internal s_forwarder; + KeystoneForwarder internal s_router; + Receiver internal s_receiver; + + function setUp() public virtual { + vm.startPrank(ADMIN); + s_router = new KeystoneForwarder(); + s_forwarder = new KeystoneForwarder(); + s_router.addForwarder(address(s_forwarder)); + s_receiver = new Receiver(); + + uint256 seed = 0; + + for (uint256 i; i < MAX_ORACLES; ++i) { + uint256 mockPK = seed + i + 1; + s_signers[i].mockPrivateKey = mockPK; + s_signers[i].signerAddress = vm.addr(mockPK); + } + } + + function _getSignerAddresses() internal view returns (address[] memory) { + address[] memory signerAddrs = new address[](s_signers.length); + for (uint256 i = 0; i < signerAddrs.length; ++i) { + signerAddrs[i] = s_signers[i].signerAddress; + } + return signerAddrs; + } + + function _getSignerAddresses(uint256 limit) internal view returns (address[] memory) { + address[] memory signerAddrs = new address[](limit); + for (uint256 i = 0; i < limit; ++i) { + signerAddrs[i] = s_signers[i].signerAddress; + } + return signerAddrs; + } + + function _signReport( + bytes memory report, + bytes memory reportContext, + uint256 requiredSignatures + ) internal view returns (bytes[] memory signatures) { + signatures = new bytes[](requiredSignatures); + for (uint256 i = 0; i < requiredSignatures; ++i) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + s_signers[i].mockPrivateKey, + keccak256(abi.encodePacked(keccak256(report), reportContext)) + ); + signatures[i] = bytes.concat(r, s, bytes1(v - 27)); + } + return signatures; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol new file mode 100644 index 0000000..c6dc7fc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol @@ -0,0 +1,326 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {MaliciousReportReceiver} from "./mocks/MaliciousReportReceiver.sol"; +import {MaliciousRevertingReceiver} from "./mocks/MaliciousRevertingReceiver.sol"; +import {KeystoneForwarder} from "../KeystoneForwarder.sol"; + +contract KeystoneForwarder_ReportTest is BaseTest { + event MessageReceived(bytes metadata, bytes[] mercuryReports); + event ReportProcessed( + address indexed receiver, + bytes32 indexed workflowExecutionId, + bytes2 indexed reportId, + bool result + ); + + uint8 internal version = 1; + uint32 internal timestamp = 0; + bytes32 internal workflowId = hex"6d795f6964000000000000000000000000000000000000000000000000000000"; + bytes10 internal workflowName = hex"000000000000DEADBEEF"; + address internal workflowOwner = address(51); + bytes32 internal executionId = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + bytes2 internal reportId = hex"0001"; + bytes[] internal mercuryReports = new bytes[](2); + bytes internal rawReports; + bytes internal header; + bytes internal metadata; + bytes internal report; + bytes internal reportContext = new bytes(96); + uint256 internal requiredSignaturesNum = F + 1; + bytes[] internal signatures = new bytes[](2); + + function setUp() public override { + BaseTest.setUp(); + + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + s_router.addForwarder(address(s_forwarder)); + + mercuryReports[0] = hex"010203"; + mercuryReports[1] = hex"aabbccdd"; + + rawReports = abi.encode(mercuryReports); + metadata = abi.encodePacked(workflowId, workflowName, workflowOwner, reportId); + header = abi.encodePacked(version, executionId, timestamp, DON_ID, CONFIG_VERSION, metadata); + report = abi.encodePacked(header, rawReports); + + signatures = _signReport(report, reportContext, requiredSignaturesNum); + + vm.startPrank(TRANSMITTER); + } + + function test_RevertWhen_ReportHasIncorrectDON() public { + uint32 invalidDONId = 111; + bytes memory reportWithInvalidDONId = abi.encodePacked( + version, + executionId, + timestamp, + invalidDONId, + CONFIG_VERSION, + workflowId, + workflowName, + workflowOwner, + reportId, + rawReports + ); + + uint64 configId = (uint64(invalidDONId) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); + s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); + } + + function test_RevertWhen_ReportHasInexistentConfigVersion() public { + bytes memory reportWithInvalidDONId = abi.encodePacked( + version, + executionId, + timestamp, + DON_ID, + CONFIG_VERSION + 1, + workflowId, + workflowName, + workflowOwner, + reportId, + rawReports + ); + + uint64 configId = (uint64(DON_ID) << 32) | (CONFIG_VERSION + 1); + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); + s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); + } + + function test_RevertWhen_ReportIsMalformed() public { + bytes memory shortenedReport = abi.encode(bytes32(report)); + + vm.expectRevert(KeystoneForwarder.InvalidReport.selector); + s_forwarder.report(address(s_receiver), shortenedReport, reportContext, signatures); + } + + function test_RevertWhen_TooFewSignatures() public { + bytes[] memory fewerSignatures = new bytes[](F); + + vm.expectRevert( + abi.encodeWithSelector(KeystoneForwarder.InvalidSignatureCount.selector, F + 1, fewerSignatures.length) + ); + s_forwarder.report(address(s_receiver), report, reportContext, fewerSignatures); + } + + function test_RevertWhen_TooManySignatures() public { + bytes[] memory moreSignatures = new bytes[](F + 2); + + vm.expectRevert( + abi.encodeWithSelector(KeystoneForwarder.InvalidSignatureCount.selector, F + 1, moreSignatures.length) + ); + s_forwarder.report(address(s_receiver), report, reportContext, moreSignatures); + } + + function test_RevertWhen_AnySignatureIsInvalid() public { + signatures[1] = abi.encode(1234); // invalid signature + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSignature.selector, signatures[1])); + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + } + + function test_RevertWhen_AnySignerIsInvalid() public { + uint256 mockPK = 999; + + Signer memory maliciousSigner = Signer({mockPrivateKey: mockPK, signerAddress: vm.addr(mockPK)}); + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + maliciousSigner.mockPrivateKey, + keccak256(abi.encodePacked(keccak256(report), reportContext)) + ); + signatures[1] = bytes.concat(r, s, bytes1(v - 27)); + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSigner.selector, maliciousSigner.signerAddress)); + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + } + + function test_RevertWhen_ReportHasDuplicateSignatures() public { + signatures[1] = signatures[0]; // repeat a signature + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.DuplicateSigner.selector, s_signers[0].signerAddress)); + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + } + + function test_RevertWhen_RetryingSuccessfulTransmission() public { + s_forwarder.report{gas: 400_000}(address(s_receiver), report, reportContext, signatures); + + bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); + vm.expectRevert(abi.encodeWithSelector(IRouter.AlreadyAttempted.selector, transmissionId)); + // Retyring with more gas + s_forwarder.report{gas: 450_000}(address(s_receiver), report, reportContext, signatures); + } + + function test_RevertWhen_RetryingInvalidContractTransmission() public { + // Receiver is not a contract + address receiver = address(404); + s_forwarder.report{gas: 400_000}(receiver, report, reportContext, signatures); + + bytes32 transmissionId = s_forwarder.getTransmissionId(receiver, executionId, reportId); + vm.expectRevert(abi.encodeWithSelector(IRouter.AlreadyAttempted.selector, transmissionId)); + // Retyring with more gas + s_forwarder.report{gas: 450_000}(receiver, report, reportContext, signatures); + } + + function test_RevertWhen_AttemptingTransmissionWithInsufficientGas() public { + bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); + vm.expectRevert(abi.encodeWithSelector(IRouter.InsufficientGasForRouting.selector, transmissionId)); + s_forwarder.report{gas: 150_000}(address(s_receiver), report, reportContext, signatures); + } + + function test_Report_SuccessfulDelivery() public { + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(s_receiver), + executionId, + reportId + ); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.NOT_ATTEMPTED), "state mismatch"); + + vm.expectEmit(address(s_receiver)); + emit MessageReceived(metadata, mercuryReports); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); + + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + + transmissionInfo = s_forwarder.getTransmissionInfo(address(s_receiver), executionId, reportId); + + assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); + assertGt(transmissionInfo.gasLimit, 100_000, "gas limit mismatch"); + } + + function test_Report_SuccessfulRetryWithMoreGas() public { + s_forwarder.report{gas: 200_000}(address(s_receiver), report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(s_receiver), + executionId, + reportId + ); + // Expect to fail with the receiver running out of gas + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.FAILED), "state mismatch"); + assertGt(transmissionInfo.gasLimit, 100_000, "gas limit mismatch"); + + // Should succeed with more gas + s_forwarder.report{gas: 300_000}(address(s_receiver), report, reportContext, signatures); + + transmissionInfo = s_forwarder.getTransmissionInfo(address(s_receiver), executionId, reportId); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); + assertGt(transmissionInfo.gasLimit, 200_000, "gas limit mismatch"); + } + + function test_Report_FailedDeliveryWhenReceiverNotContract() public { + // Receiver is not a contract + address receiver = address(404); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo(receiver, executionId, reportId); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.INVALID_RECEIVER), "state mismatch"); + } + + function test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() public { + // Receiver is a contract but doesn't implement the required interface + address receiver = address(s_forwarder); + + vm.expectEmit(true, true, true, false); + emit ReportProcessed(receiver, executionId, reportId, false); + + s_forwarder.report(receiver, report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo(receiver, executionId, reportId); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.INVALID_RECEIVER), "state mismatch"); + } + + function test_Report_FailedDeliveryWhenReportReceiverConsumesAllGasAndInterfaceCheckUsesMax() public { + MaliciousRevertingReceiver maliciousReceiver = new MaliciousRevertingReceiver(); + // This should not revert if gas tracking is effective + // It may revert if it fails to reserve sufficient gas for routing + // This POC requires pretty specific initial gas, so that 1/64 of gas passed to `onReport()` is insufficient to store the success + s_forwarder.report{gas: 200_000}(address(maliciousReceiver), report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(maliciousReceiver), + executionId, + reportId + ); + + assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); + } + + function test_Report_FailedDelieryWhenReportReceiverConsumesAllGas() public { + MaliciousReportReceiver s_maliciousReceiver = new MaliciousReportReceiver(); + s_forwarder.report{gas: 500_000}(address(s_maliciousReceiver), report, reportContext, signatures); + + IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( + address(s_maliciousReceiver), + executionId, + reportId + ); + + assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); + assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.FAILED), "state mismatch"); + assertGt(transmissionInfo.gasLimit, 410_000, "gas limit mismatch"); + } + + function test_Report_ConfigVersion() public { + vm.stopPrank(); + // configure a new configVersion + vm.prank(ADMIN); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION + 1, F, _getSignerAddresses()); + + // old version still works + vm.expectEmit(address(s_receiver)); + emit MessageReceived(metadata, mercuryReports); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(address(s_receiver), executionId, reportId, true); + + vm.prank(TRANSMITTER); + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + + // after clear the old version doesn't work anymore + vm.prank(ADMIN); + s_forwarder.clearConfig(DON_ID, CONFIG_VERSION); + + uint64 configId = (uint64(DON_ID) << 32) | CONFIG_VERSION; + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); + vm.prank(TRANSMITTER); + s_forwarder.report(address(s_receiver), report, reportContext, signatures); + + // but new config does + bytes32 newExecutionId = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000001"; + bytes memory newMetadata = abi.encodePacked(workflowId, workflowName, workflowOwner, reportId); + bytes memory newHeader = abi.encodePacked( + version, + newExecutionId, + timestamp, + DON_ID, + CONFIG_VERSION + 1, + newMetadata + ); + bytes memory newReport = abi.encodePacked(newHeader, rawReports); + // resign the new report + bytes[] memory newSignatures = _signReport(newReport, reportContext, requiredSignaturesNum); + + vm.expectEmit(address(s_receiver)); + emit MessageReceived(newMetadata, mercuryReports); + + vm.expectEmit(address(s_forwarder)); + emit ReportProcessed(address(s_receiver), newExecutionId, reportId, true); + + vm.prank(TRANSMITTER); + s_forwarder.report(address(s_receiver), newReport, reportContext, newSignatures); + + // validate transmitter was recorded + address transmitter = s_forwarder.getTransmitter(address(s_receiver), newExecutionId, reportId); + assertEq(transmitter, TRANSMITTER, "transmitter mismatch"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol new file mode 100644 index 0000000..5dcf79b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; +import {KeystoneForwarder} from "../KeystoneForwarder.sol"; + +contract KeystoneForwarder_SetConfigTest is BaseTest { + address internal constant STRANGER = address(2); + + function test_RevertWhen_NotOwner() public { + vm.stopPrank(); // BaseTest sets ADMIN + vm.prank(STRANGER); + vm.expectRevert(); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + } + + function test_RevertWhen_FaultToleranceIsZero() public { + vm.expectRevert(KeystoneForwarder.FaultToleranceMustBePositive.selector); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, 0, _getSignerAddresses()); + } + + function test_RevertWhen_InsufficientSigners() public { + address[] memory signers = new address[](1); + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InsufficientSigners.selector, 1, 4)); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); + } + + function test_RevertWhen_ExcessSigners() public { + address[] memory signers = new address[](64); + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.ExcessSigners.selector, 64, 31)); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); + } + + function test_RevertWhen_ProvidingDuplicateSigners() public { + address[] memory signers = _getSignerAddresses(); + signers[1] = signers[0]; + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.DuplicateSigner.selector, signers[0])); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); + } + + function test_RevertWhen_ProvidingZeroAddressSigner() public { + address[] memory signers = _getSignerAddresses(); + signers[1] = address(0); + + vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSigner.selector, signers[1])); + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); + } + + function test_SetConfig_FirstTime() public { + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + } + + function test_SetConfig_WhenSignersAreRemoved() public { + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); + + s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses(16)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol new file mode 100644 index 0000000..5a5cc70 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; + +contract KeystoneForwarder_TypeAndVersionTest is BaseTest { + function test_TypeAndVersion() public view { + assertEq(s_forwarder.typeAndVersion(), "Forwarder and Router 1.0.0"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol new file mode 100644 index 0000000..0e43b72 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {IReceiver} from "../interfaces/IReceiver.sol"; +import {IRouter} from "../interfaces/IRouter.sol"; +import {KeystoneForwarder} from "../KeystoneForwarder.sol"; +import {Receiver} from "./mocks/Receiver.sol"; + +contract KeystoneRouter_SetConfigTest is Test { + address internal ADMIN = address(1); + address internal constant STRANGER = address(2); + address internal constant FORWARDER = address(99); + address internal constant TRANSMITTER = address(50); + address internal constant RECEIVER = address(51); + + bytes internal metadata = hex"01020304"; + bytes internal report = hex"9998"; + bytes32 internal id = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; + + KeystoneForwarder internal s_router; + Receiver internal s_receiver; + + function setUp() public virtual { + vm.prank(ADMIN); + s_router = new KeystoneForwarder(); + s_receiver = new Receiver(); + } + + function test_AddForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.addForwarder(FORWARDER); + } + + function test_RemoveForwarder_RevertWhen_NotOwner() public { + vm.prank(STRANGER); + vm.expectRevert(); + s_router.removeForwarder(FORWARDER); + } + + function test_RemoveForwarder_Success() public { + vm.prank(ADMIN); + vm.expectEmit(true, false, false, false); + emit IRouter.ForwarderRemoved(FORWARDER); + s_router.removeForwarder(FORWARDER); + } + + function test_Route_RevertWhen_UnauthorizedForwarder() public { + vm.prank(STRANGER); + vm.expectRevert(IRouter.UnauthorizedForwarder.selector); + s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); + } + + function test_Route_Success() public { + assertEq(s_router.isForwarder(FORWARDER), false); + + vm.prank(ADMIN); + s_router.addForwarder(FORWARDER); + assertEq(s_router.isForwarder(FORWARDER), true); + + vm.prank(FORWARDER); + vm.mockCall(address(s_receiver), abi.encodeCall(IReceiver.onReport, (metadata, report)), abi.encode()); + vm.expectCall(address(s_receiver), abi.encodeCall(IReceiver.onReport, (metadata, report))); + s_router.route(id, TRANSMITTER, address(s_receiver), metadata, report); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol new file mode 100644 index 0000000..105c890 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +contract CapabilityConfigurationContract is ICapabilityConfiguration, IERC165 { + mapping(uint256 => bytes) private s_donConfiguration; + + function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration) { + return s_donConfiguration[donId]; + } + + function beforeCapabilityConfigSet(bytes32[] calldata, bytes calldata config, uint64, uint32 donId) external { + // In practice a real capability configuration contract will do more than just store + // the config for a DON + s_donConfiguration[donId] = config; + } + + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol new file mode 100644 index 0000000..9325014 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; +import {CapabilitiesRegistry} from "../../CapabilitiesRegistry.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Constants} from "../Constants.t.sol"; + +contract MaliciousConfigurationContract is ICapabilityConfiguration, IERC165, Constants { + bytes32 internal s_capabilityWithConfigurationContractId; + + constructor(bytes32 capabilityWithConfigContractId) { + s_capabilityWithConfigurationContractId = capabilityWithConfigContractId; + } + + function getCapabilityConfiguration(uint32) external pure returns (bytes memory configuration) { + return bytes(""); + } + + function beforeCapabilityConfigSet(bytes32[] calldata, bytes calldata, uint64, uint32) external { + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + + hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; + + // Set node one's signer to another address + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID, + signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, + hashedCapabilityIds: hashedCapabilityIds + }); + + nodes[1] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, + p2pId: P2P_ID_THREE, + signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, + encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, + hashedCapabilityIds: hashedCapabilityIds + }); + + CapabilitiesRegistry(msg.sender).updateNodes(nodes); + } + + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol new file mode 100644 index 0000000..8f039b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IReceiver} from "../../interfaces/IReceiver.sol"; + +contract MaliciousReportReceiver is IReceiver, IERC165 { + event MessageReceived(bytes metadata, bytes[] mercuryReports); + bytes public latestReport; + + function onReport(bytes calldata metadata, bytes calldata rawReport) external { + // Exhaust all gas that was provided + for (uint256 i = 0; i < 1_000_000_000; ++i) { + bytes[] memory mercuryReports = abi.decode(rawReport, (bytes[])); + latestReport = rawReport; + emit MessageReceived(metadata, mercuryReports); + } + } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol new file mode 100644 index 0000000..f45e95a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IReceiver} from "../../interfaces/IReceiver.sol"; + +/// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` +/// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately +contract MaliciousRevertingReceiver is IReceiver, IERC165 { + function onReport(bytes calldata, bytes calldata) external view override { + // consumes about 63/64 of all gas available + uint256 targetGasRemaining = 200; + for (uint256 i = 0; gasleft() > targetGasRemaining; ++i) {} + } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + // Consume up to the maximum amount of gas that can be consumed in this check + for (uint256 i = 0; i < 500; ++i) {} + + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol new file mode 100644 index 0000000..d400595 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IReceiver} from "../../interfaces/IReceiver.sol"; + +contract Receiver is IReceiver, IERC165 { + event MessageReceived(bytes metadata, bytes[] mercuryReports); + bytes public latestReport; + + constructor() {} + + function onReport(bytes calldata metadata, bytes calldata rawReport) external { + latestReport = rawReport; + + // parse actual report + bytes[] memory mercuryReports = abi.decode(rawReport, (bytes[])); + emit MessageReceived(metadata, mercuryReports); + } + + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md new file mode 100644 index 0000000..21a537c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md @@ -0,0 +1,148 @@ +# Overview + +This folder contains the source code and tests for the Layer 2 +Emergency Protocol (L2EP) contracts. It is organized as follows: + +```text +. +├─/dev (stores the latest source code for L2EP) +├─/test (stores the Foundry tests for L2EP) +``` + +## The `/dev` Folder + +The `/dev` folder contains subfolders for each chain that +has an L2EP solution implemented for it (e.g. `/scroll`, `/arbitrum`, +`/optimism`). It also contains a subfolder named `/interfaces`, +which stores shared interface types between all the supported +contracts. The top-level contracts (e.g. `CrossDomainOwnable.sol`) +serve as either abstract or parent contracts that are meant +to be reused for each indiviudal chain. + +## The `/test` Folder + +This folder is arranged as follows: + +- `/mocks`: used for both Foundry test cases and Hardhat test cases (NOTE: +Hardhat test cases should be considered deprecated at this point) + +- `/[version]`: test cases for a specific version of the L2EP contracts + +### Testing Conventions and Methodology + +By convention, each testing file should end in `.t.sol` (this is a standard +that other projects have also adopted). Each testing file in this folder +follows a similar structure. + +```text +TestFile.t.sol + | + |--- Base Contract (inherits L2EPTest contract) + | + |--- Child Contract 1 (inherits base contract) + | | + | |--- Test Function + | | + | |--- ... + | + | + |--- Child Contract 2 (inherits base contract) + | | + | |--- Test Function + | | + | |--- ... + | + | + ... +``` + +All test files contain a base contract defined at the top of the file. This +base contract inherits from a contract called `L2EPTest`. The `L2EPTest` +contract and base contracts have no test cases. Instead, the `L2EPTest` +contract is meant to store data/functions that will be reused among all +the base contracts. Similarly, the base contract is meant to store data +and/or functions that will be reused by any contracts that inherit it. +As such, each test file will define separate child contracts, and each +will inherit from the base contract + define its own set of tests. + +The base contract defines a `setUp` function which is automatically called +exactly once before ***each*** of the tests are run in an inheriting contract. +The `setUp` function typically deploys a fresh set of test contracts so that +tests can run independently of each other. Alongside the `setUp` function, +the base contract can also define variables, constants, events, etc. that +are meant to be reused per test. + +The name of the base contract follows the following convention: + +```text +Test +``` + +The child contract names follow a similar convention: + +```text +_ +``` + +Each test function within the child contract complies +with the following naming pattern: + +```text +test_ +``` + +### Running Foundry Tests + +#### Usage + +First make sure you are in the contracts directory: + +```sh +# Assuming you are currently in the /chainlink directory +cd ./contracts +``` + +If you already have foundry installed, you can use the following command +to run all L2EP tests: + +```sh +FOUNDRY_PROFILE=l2ep forge test -vvv +``` + +To run a specific L2EP test, you can use a variation of the following command: + +```sh +FOUNDRY_PROFILE=l2ep forge test -vvv --match-path ./src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +``` + +Or alternatively: + +```sh +FOUNDRY_PROFILE=l2ep forge test -vvv --match-contract ScrollSequencerUptimeFeed +``` + +If you prefer, you can also export `FOUNDRY_PROFILE` so that it doesn't need +to be provided before every command: + +```sh +# Export foundry profile +export FOUNDRY_PROFILE=l2ep + +# Run all tests +forge test -vvv + +# Run all tests and generate a gas snapshot +make snapshot +``` + +A full list of flags for `forge test` can be found [here](https://book.getfoundry.sh/reference/forge/forge-test). + +#### Coverage + +First ensure that the correct files are being evaluated. For example, if only +v1 contracts are, being evaluated then temporarily change the L2EP profile in +`./foundry.toml`. + +```sh +forge coverage +``` diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol new file mode 100644 index 0000000..859c6f0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; +import {IDelegateForwarder} from "./interfaces/IDelegateForwarder.sol"; + +/** + * @title CrossDomainDelegateForwarder - L1 xDomain account representation (with delegatecall support) + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can consider that position to be held by the `l1Owner` + */ +abstract contract CrossDomainDelegateForwarder is IDelegateForwarder, CrossDomainOwnable {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol new file mode 100644 index 0000000..c097057 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; +import {IForwarder} from "./interfaces/IForwarder.sol"; + +/** + * @title CrossDomainForwarder - L1 xDomain account representation + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can consider that position to be held by the `l1Owner` + */ +abstract contract CrossDomainForwarder is IForwarder, CrossDomainOwnable {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol new file mode 100644 index 0000000..c85762b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {ICrossDomainOwnable} from "./interfaces/ICrossDomainOwnable.sol"; + +/** + * @title The CrossDomainOwnable contract + * @notice A contract with helpers for cross-domain contract ownership. + */ +contract CrossDomainOwnable is ICrossDomainOwnable, ConfirmedOwner { + address internal s_l1Owner; + address internal s_l1PendingOwner; + + constructor(address newl1Owner) ConfirmedOwner(msg.sender) { + _setL1Owner(newl1Owner); + } + + /** + * @notice transfer ownership of this account to a new L1 owner + * @param to new L1 owner that will be allowed to call the forward fn + */ + function transferL1Ownership(address to) public virtual override onlyL1Owner { + _transferL1Ownership(to); + } + + /** + * @notice accept ownership of this account to a new L1 owner + */ + function acceptL1Ownership() public virtual override onlyProposedL1Owner { + _setL1Owner(s_l1PendingOwner); + } + + /** + * @notice Get the current owner + */ + function l1Owner() public view override returns (address) { + return s_l1Owner; + } + + /** + * @notice validate, transfer ownership, and emit relevant events + */ + function _transferL1Ownership(address to) internal { + // solhint-disable-next-line gas-custom-errors + require(to != msg.sender, "Cannot transfer to self"); + + s_l1PendingOwner = to; + + emit L1OwnershipTransferRequested(s_l1Owner, to); + } + + /** + * @notice set ownership, emit relevant events. Used in acceptOwnership() + */ + function _setL1Owner(address to) internal { + address oldOwner = s_l1Owner; + s_l1Owner = to; + s_l1PendingOwner = address(0); + + emit L1OwnershipTransferred(oldOwner, to); + } + + /** + * @notice Reverts if called by anyone other than the L1 owner. + */ + modifier onlyL1Owner() virtual { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == s_l1Owner, "Only callable by L1 owner"); + _; + } + + /** + * @notice Reverts if called by anyone other than the L1 owner. + */ + modifier onlyProposedL1Owner() virtual { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == s_l1PendingOwner, "Only callable by proposed L1 owner"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol new file mode 100644 index 0000000..2dc030d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; +import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +/* dev dependencies - to be re/moved after audit */ +import {IFlags} from "./interfaces/IFlags.sol"; + +/** + * @title The Flags contract + * @notice Allows flags to signal to any reader on the access control list. + * The owner can set flags, or designate other addresses to set flags. + * Raise flag actions are controlled by its own access controller. + * Lower flag actions are controlled by its own access controller. + * An expected pattern is to allow addresses to raise flags on themselves, so if you are subscribing to + * FlagOn events you should filter for addresses you care about. + */ +// solhint-disable gas-custom-errors +contract Flags is ITypeAndVersion, IFlags, SimpleReadAccessController { + AccessControllerInterface public raisingAccessController; + AccessControllerInterface public loweringAccessController; + + mapping(address => bool) private s_flags; + + event FlagRaised(address indexed subject); + event FlagLowered(address indexed subject); + event RaisingAccessControllerUpdated(address indexed previous, address indexed current); + event LoweringAccessControllerUpdated(address indexed previous, address indexed current); + + /** + * @param racAddress address for the raising access controller. + * @param lacAddress address for the lowering access controller. + */ + constructor(address racAddress, address lacAddress) { + setRaisingAccessController(racAddress); + setLoweringAccessController(lacAddress); + } + + /** + * @notice versions: + * + * - Flags 1.1.0: upgraded to solc 0.8, added lowering access controller + * - Flags 1.0.0: initial release + * + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "Flags 1.1.0"; + } + + /** + * @notice read the warning flag status of a contract address. + * @param subject The contract address being checked for a flag. + * @return A true value indicates that a flag was raised and a + * false value indicates that no flag was raised. + */ + function getFlag(address subject) external view override checkAccess returns (bool) { + return s_flags[subject]; + } + + /** + * @notice read the warning flag status of a contract address. + * @param subjects An array of addresses being checked for a flag. + * @return An array of bools where a true value for any flag indicates that + * a flag was raised and a false value indicates that no flag was raised. + */ + function getFlags(address[] calldata subjects) external view override checkAccess returns (bool[] memory) { + bool[] memory responses = new bool[](subjects.length); + for (uint256 i = 0; i < subjects.length; i++) { + responses[i] = s_flags[subjects[i]]; + } + return responses; + } + + /** + * @notice enable the warning flag for an address. + * Access is controlled by raisingAccessController, except for owner + * who always has access. + * @param subject The contract address whose flag is being raised + */ + function raiseFlag(address subject) external override { + require(_allowedToRaiseFlags(), "Not allowed to raise flags"); + + _tryToRaiseFlag(subject); + } + + /** + * @notice enable the warning flags for multiple addresses. + * Access is controlled by raisingAccessController, except for owner + * who always has access. + * @param subjects List of the contract addresses whose flag is being raised + */ + function raiseFlags(address[] calldata subjects) external override { + require(_allowedToRaiseFlags(), "Not allowed to raise flags"); + + for (uint256 i = 0; i < subjects.length; i++) { + _tryToRaiseFlag(subjects[i]); + } + } + + /** + * @notice allows owner to disable the warning flags for an addresses. + * Access is controlled by loweringAccessController, except for owner + * who always has access. + * @param subject The contract address whose flag is being lowered + */ + function lowerFlag(address subject) external override { + require(_allowedToLowerFlags(), "Not allowed to lower flags"); + + _tryToLowerFlag(subject); + } + + /** + * @notice allows owner to disable the warning flags for multiple addresses. + * Access is controlled by loweringAccessController, except for owner + * who always has access. + * @param subjects List of the contract addresses whose flag is being lowered + */ + function lowerFlags(address[] calldata subjects) external override { + require(_allowedToLowerFlags(), "Not allowed to lower flags"); + + for (uint256 i = 0; i < subjects.length; i++) { + address subject = subjects[i]; + + _tryToLowerFlag(subject); + } + } + + /** + * @notice allows owner to change the access controller for raising flags. + * @param racAddress new address for the raising access controller. + */ + function setRaisingAccessController(address racAddress) public override onlyOwner { + address previous = address(raisingAccessController); + + if (previous != racAddress) { + raisingAccessController = AccessControllerInterface(racAddress); + + emit RaisingAccessControllerUpdated(previous, racAddress); + } + } + + function setLoweringAccessController(address lacAddress) public override onlyOwner { + address previous = address(loweringAccessController); + + if (previous != lacAddress) { + loweringAccessController = AccessControllerInterface(lacAddress); + + emit LoweringAccessControllerUpdated(previous, lacAddress); + } + } + + // PRIVATE + function _allowedToRaiseFlags() private view returns (bool) { + return msg.sender == owner() || raisingAccessController.hasAccess(msg.sender, msg.data); + } + + function _allowedToLowerFlags() private view returns (bool) { + return msg.sender == owner() || loweringAccessController.hasAccess(msg.sender, msg.data); + } + + function _tryToRaiseFlag(address subject) private { + if (!s_flags[subject]) { + s_flags[subject] = true; + emit FlagRaised(subject); + } + } + + function _tryToLowerFlag(address subject) private { + if (s_flags[subject]) { + s_flags[subject] = false; + emit FlagLowered(subject); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol new file mode 100644 index 0000000..0db657e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +// solhint-disable-next-line no-unused-import +import {IForwarder} from "../interfaces/IForwarder.sol"; + +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/** + * @title ArbitrumCrossDomainForwarder - L1 xDomain account representation + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can be considered to be owned by the `l1Owner` + */ +contract ArbitrumCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { + /** + * @notice creates a new Arbitrum xDomain Forwarder contract + * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder + */ + constructor(address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) {} + + /** + * @notice versions: + * + * - ArbitrumCrossDomainForwarder 0.1.0: initial release + * - ArbitrumCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable + * + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "ArbitrumCrossDomainForwarder 1.0.0"; + } + + /** + * @notice The L2 xDomain `msg.sender`, generated from L1 sender address + */ + function crossDomainMessenger() public view returns (address) { + return AddressAliasHelper.applyL1ToL2Alias(l1Owner()); + } + + /** + * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address + * @inheritdoc IForwarder + */ + function forward(address target, bytes memory data) external virtual override onlyL1Owner { + Address.functionCall(target, data, "Forwarder call reverted"); + } + + /** + * @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + */ + modifier onlyL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == crossDomainMessenger(), "Sender is not the L2 messenger"); + _; + } + + /** + * @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + */ + modifier onlyProposedL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == AddressAliasHelper.applyL1ToL2Alias(s_l1PendingOwner), "Must be proposed L1 owner"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol new file mode 100644 index 0000000..60d9cc5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line no-unused-import +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +// solhint-disable-next-line no-unused-import +import {IForwarder} from "../interfaces/IForwarder.sol"; +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; + +import {ArbitrumCrossDomainForwarder} from "./ArbitrumCrossDomainForwarder.sol"; + +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/** + * @title ArbitrumCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Arbitrum + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` + */ +contract ArbitrumCrossDomainGovernor is IDelegateForwarder, ArbitrumCrossDomainForwarder { + /** + * @notice creates a new Arbitrum xDomain Forwarder contract + * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder + */ + constructor(address l1OwnerAddr) ArbitrumCrossDomainForwarder(l1OwnerAddr) {} + + /** + * @notice versions: + * + * - ArbitrumCrossDomainGovernor 1.0.0: initial release + * + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "ArbitrumCrossDomainGovernor 1.0.0"; + } + + /** + * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + * @inheritdoc IForwarder + */ + function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionCall(target, data, "Governor call reverted"); + } + + /** + * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + * @inheritdoc IDelegateForwarder + */ + function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); + } + + /** + * @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. + */ + modifier onlyLocalOrCrossDomainOwner() { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == crossDomainMessenger() || msg.sender == owner(), "Sender is not the L2 messenger or owner"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol new file mode 100644 index 0000000..678bef3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IFlags} from "../interfaces/IFlags.sol"; +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; + +/** + * @title ArbitrumSequencerUptimeFeed - L2 sequencer uptime status aggregator + * @notice L2 contract that receives status updates from a specific L1 address, + * records a new answer if the status changed, and raises or lowers the flag on the + * stored Flags contract. + */ +contract ArbitrumSequencerUptimeFeed is + AggregatorV2V3Interface, + ISequencerUptimeFeed, + ITypeAndVersion, + SimpleReadAccessController +{ + /// @dev Round info (for uptime history) + struct Round { + bool status; + uint64 timestamp; + } + + /// @dev Packed state struct to save sloads + struct FeedState { + uint80 latestRoundId; + bool latestStatus; + uint64 latestTimestamp; + } + + /// @notice Contract is not yet initialized + error Uninitialized(); + /// @notice Contract is already initialized + error AlreadyInitialized(); + /// @notice Sender is not the L2 messenger + error InvalidSender(); + /// @notice Replacement for AggregatorV3Interface "No data present" + error NoDataPresent(); + + event Initialized(); + event L1SenderTransferred(address indexed from, address indexed to); + /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + + /// @dev Follows: https://eips.ethereum.org/EIPS/eip-1967 + address public constant FLAG_L2_SEQ_OFFLINE = + address(bytes20(bytes32(uint256(keccak256("chainlink.flags.arbitrum-seq-offline")) - 1))); + + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint8 public constant override decimals = 0; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override description = "L2 Sequencer Uptime Status Feed"; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint256 public constant override version = 1; + + /// @dev Flags contract to raise/lower flags on, during status transitions + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + IFlags public immutable FLAGS; + /// @dev L1 address + address private s_l1Sender; + /// @dev s_latestRoundId == 0 means this contract is uninitialized. + FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, latestTimestamp: 0}); + mapping(uint80 => Round) private s_rounds; + + /** + * @param flagsAddress Address of the Flags contract on L2 + * @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + */ + constructor(address flagsAddress, address l1SenderAddress) { + _setL1Sender(l1SenderAddress); + + FLAGS = IFlags(flagsAddress); + } + + /** + * @notice Check if a roundId is valid in this current contract state + * @dev Mainly used for AggregatorV2V3Interface functions + * @param roundId Round ID to check + */ + function _isValidRound(uint256 roundId) private view returns (bool) { + return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; + } + + /// @notice Check that this contract is initialised, otherwise throw + function _requireInitialized(uint80 latestRoundId) private pure { + if (latestRoundId == 0) { + revert Uninitialized(); + } + } + + /** + * @notice Initialise the first round. Can't be done in the constructor, + * because this contract's address must be permissioned by the the Flags contract + * (The Flags contract itself is a SimpleReadAccessController). + */ + function initialize() external onlyOwner { + FeedState memory feedState = s_feedState; + if (feedState.latestRoundId != 0) { + revert AlreadyInitialized(); + } + + uint64 timestamp = uint64(block.timestamp); + bool currentStatus = FLAGS.getFlag(FLAG_L2_SEQ_OFFLINE); + + // Initialise roundId == 1 as the first round + _recordRound(1, currentStatus, timestamp); + + emit Initialized(); + } + + /** + * @notice versions: + * + * - ArbitrumSequencerUptimeFeed 1.0.0: initial release + * + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "ArbitrumSequencerUptimeFeed 1.0.0"; + } + + /// @return L1 sender address + function l1Sender() public view virtual returns (address) { + return s_l1Sender; + } + + /** + * @notice Set the allowed L1 sender for this contract to a new L1 sender + * @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. + * @param to new L1 sender that will be allowed to call `updateStatus` on this contract + */ + function transferL1Sender(address to) external virtual onlyOwner { + _setL1Sender(to); + } + + /// @notice internal method that stores the L1 sender + function _setL1Sender(address to) private { + address from = s_l1Sender; + if (from != to) { + s_l1Sender = to; + emit L1SenderTransferred(from, to); + } + } + + /** + * @notice Messages sent by the stored L1 sender will arrive on L2 with this + * address as the `msg.sender` + * @return L2-aliased form of the L1 sender address + */ + function aliasedL1MessageSender() public view returns (address) { + return AddressAliasHelper.applyL1ToL2Alias(l1Sender()); + } + + /** + * @dev Returns an AggregatorV2V3Interface compatible answer from status flag + * + * @param status The status flag to convert to an aggregator-compatible answer + */ + function _getStatusAnswer(bool status) private pure returns (int256) { + return status ? int256(1) : int256(0); + } + + /** + * @notice Raise or lower the flag on the stored Flags contract. + */ + function _forwardStatusToFlags(bool status) private { + if (status) { + FLAGS.raiseFlag(FLAG_L2_SEQ_OFFLINE); + } else { + FLAGS.lowerFlag(FLAG_L2_SEQ_OFFLINE); + } + } + + /** + * @notice Helper function to record a round and set the latest feed state. + * + * @param roundId The round ID to record + * @param status Sequencer status + * @param timestamp Block timestamp of status update + */ + function _recordRound(uint80 roundId, bool status, uint64 timestamp) private { + Round memory nextRound = Round(status, timestamp); + FeedState memory feedState = FeedState(roundId, status, timestamp); + + s_rounds[roundId] = nextRound; + s_feedState = feedState; + + emit NewRound(roundId, msg.sender, timestamp); + emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); + } + + /** + * @notice Record a new status and timestamp if it has changed since the last round. + * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + * + * @param status Sequencer status + * @param timestamp Block timestamp of status update + */ + function updateStatus(bool status, uint64 timestamp) external override { + FeedState memory feedState = s_feedState; + _requireInitialized(feedState.latestRoundId); + if (msg.sender != aliasedL1MessageSender()) { + revert InvalidSender(); + } + + // Ignore if status did not change or latest recorded timestamp is newer + if (feedState.latestStatus == status || feedState.latestTimestamp > timestamp) { + emit UpdateIgnored(feedState.latestStatus, feedState.latestTimestamp, status, timestamp); + return; + } + + // Prepare a new round with updated status + feedState.latestRoundId += 1; + _recordRound(feedState.latestRoundId, status, timestamp); + + _forwardStatusToFlags(status); + } + + /// @inheritdoc AggregatorInterface + function latestAnswer() external view override checkAccess returns (int256) { + FeedState memory feedState = s_feedState; + _requireInitialized(feedState.latestRoundId); + return _getStatusAnswer(feedState.latestStatus); + } + + /// @inheritdoc AggregatorInterface + function latestTimestamp() external view override checkAccess returns (uint256) { + FeedState memory feedState = s_feedState; + _requireInitialized(feedState.latestRoundId); + return feedState.latestTimestamp; + } + + /// @inheritdoc AggregatorInterface + function latestRound() external view override checkAccess returns (uint256) { + FeedState memory feedState = s_feedState; + _requireInitialized(feedState.latestRoundId); + return feedState.latestRoundId; + } + + /// @inheritdoc AggregatorInterface + function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { + _requireInitialized(s_feedState.latestRoundId); + if (_isValidRound(roundId)) { + return _getStatusAnswer(s_rounds[uint80(roundId)].status); + } + + return 0; + } + + /// @inheritdoc AggregatorInterface + function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { + _requireInitialized(s_feedState.latestRoundId); + if (_isValidRound(roundId)) { + return s_rounds[uint80(roundId)].timestamp; + } + + return 0; + } + + /// @inheritdoc AggregatorV3Interface + function getRoundData( + uint80 _roundId + ) + public + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + _requireInitialized(s_feedState.latestRoundId); + + if (_isValidRound(_roundId)) { + Round memory round = s_rounds[_roundId]; + answer = _getStatusAnswer(round.status); + startedAt = uint256(round.timestamp); + } else { + answer = 0; + startedAt = 0; + } + roundId = _roundId; + updatedAt = startedAt; + answeredInRound = roundId; + + return (roundId, answer, startedAt, updatedAt, answeredInRound); + } + + /// @inheritdoc AggregatorV3Interface + function latestRoundData() + external + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + FeedState memory feedState = s_feedState; + _requireInitialized(feedState.latestRoundId); + + roundId = feedState.latestRoundId; + answer = _getStatusAnswer(feedState.latestStatus); + startedAt = feedState.latestTimestamp; + updatedAt = startedAt; + answeredInRound = roundId; + + return (roundId, answer, startedAt, updatedAt, answeredInRound); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol new file mode 100644 index 0000000..05f9349 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; + +/* ./dev dependencies - to be moved from ./dev after audit */ +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; +import {IArbitrumDelayedInbox} from "../interfaces/IArbitrumDelayedInbox.sol"; +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/** + * @title ArbitrumValidator - makes xDomain L2 Flags contract call (using L2 xDomain Forwarder contract) + * @notice Allows to raise and lower Flags on the Arbitrum L2 network through L1 bridge + * - The internal AccessController controls the access of the validate method + * - Gas configuration is controlled by a configurable external SimpleWriteAccessController + * - Funds on the contract are managed by the owner + */ +contract ArbitrumValidator is ITypeAndVersion, AggregatorValidatorInterface, SimpleWriteAccessController { + enum PaymentStrategy { + L1, + L2 + } + // Config for L1 -> L2 Arbitrum retryable ticket message + struct GasConfig { + uint256 maxGas; + uint256 gasPriceBid; + uint256 baseFee; // Will use block.baseFee if set to 0 + address gasPriceL1FeedAddr; + } + + /// @dev Precompiled contract that exists in every Arbitrum chain at address(100). Exposes a variety of system-level functionality. + address internal constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + + int256 private constant ANSWER_SEQ_OFFLINE = 1; + + /// @notice The address of Arbitrum's DelayedInbox + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable CROSS_DOMAIN_MESSENGER; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L2_SEQ_STATUS_RECORDER; + // L2 xDomain alias address of this contract + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L2_ALIAS = AddressAliasHelper.applyL1ToL2Alias(address(this)); + + PaymentStrategy private s_paymentStrategy; + GasConfig private s_gasConfig; + AccessControllerInterface private s_configAC; + + /** + * @notice emitted when a new payment strategy is set + * @param paymentStrategy strategy describing how the contract pays for xDomain calls + */ + event PaymentStrategySet(PaymentStrategy indexed paymentStrategy); + + /** + * @notice emitted when a new gas configuration is set + * @param maxGas gas limit for immediate L2 execution attempt. + * @param gasPriceBid maximum L2 gas price to pay + * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) + */ + event GasConfigSet(uint256 maxGas, uint256 gasPriceBid, address indexed gasPriceL1FeedAddr); + + /** + * @notice emitted when a new gas access-control contract is set + * @param previous the address prior to the current setting + * @param current the address of the new access-control contract + */ + event ConfigACSet(address indexed previous, address indexed current); + + /** + * @notice emitted when a new ETH withdrawal from L2 was requested + * @param id unique id of the published retryable transaction (keccak256(requestID, uint(0)) + * @param amount of funds to withdraw + */ + event L2WithdrawalRequested(uint256 indexed id, uint256 amount, address indexed refundAddr); + + /** + * @param crossDomainMessengerAddr address the xDomain bridge messenger (Arbitrum Inbox L1) contract address + * @param l2ArbitrumSequencerUptimeFeedAddr the L2 Flags contract address + * @param configACAddr address of the access controller for managing gas price on Arbitrum + * @param maxGas gas limit for immediate L2 execution attempt. A value around 1M should be sufficient + * @param gasPriceBid maximum L2 gas price to pay + * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) + * @param _paymentStrategy strategy describing how the contract pays for xDomain calls + */ + constructor( + address crossDomainMessengerAddr, + address l2ArbitrumSequencerUptimeFeedAddr, + address configACAddr, + uint256 maxGas, + uint256 gasPriceBid, + uint256 baseFee, + address gasPriceL1FeedAddr, + PaymentStrategy _paymentStrategy + ) { + // solhint-disable-next-line gas-custom-errors + require(crossDomainMessengerAddr != address(0), "Invalid xDomain Messenger address"); + // solhint-disable-next-line gas-custom-errors + require(l2ArbitrumSequencerUptimeFeedAddr != address(0), "Invalid ArbitrumSequencerUptimeFeed contract address"); + CROSS_DOMAIN_MESSENGER = crossDomainMessengerAddr; + L2_SEQ_STATUS_RECORDER = l2ArbitrumSequencerUptimeFeedAddr; + // Additional L2 payment configuration + _setConfigAC(configACAddr); + _setGasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); + _setPaymentStrategy(_paymentStrategy); + } + + /** + * @notice versions: + * + * - ArbitrumValidator 0.1.0: initial release + * - ArbitrumValidator 0.2.0: critical Arbitrum network update + * - xDomain `msg.sender` backwards incompatible change (now an alias address) + * - new `withdrawFundsFromL2` fn that withdraws from L2 xDomain alias address + * - approximation of `maxSubmissionCost` using a L1 gas price feed + * - ArbitrumValidator 1.0.0: change target of L2 sequencer status update + * - now calls `updateStatus` on an L2 ArbitrumSequencerUptimeFeed contract instead of + * directly calling the Flags contract + * - ArbitrumValidator 2.0.0: change how maxSubmissionCost is calculated when sending cross chain messages + * - now calls `calculateRetryableSubmissionFee` instead of inlining equation to estimate + * the maxSubmissionCost required to send the message to L2 + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "ArbitrumValidator 2.0.0"; + } + + /// @return stored PaymentStrategy + function paymentStrategy() external view virtual returns (PaymentStrategy) { + return s_paymentStrategy; + } + + /// @return stored GasConfig + function gasConfig() external view virtual returns (GasConfig memory) { + return s_gasConfig; + } + + /// @return config AccessControllerInterface contract address + function configAC() external view virtual returns (address) { + return address(s_configAC); + } + + /** + * @notice makes this contract payable + * @dev receives funds: + * - to use them (if configured) to pay for L2 execution on L1 + * - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) + */ + receive() external payable {} + + /** + * @notice withdraws all funds available in this contract to the msg.sender + * @dev only owner can call this + */ + function withdrawFunds() external onlyOwner { + address payable recipient = payable(msg.sender); + uint256 amount = address(this).balance; + Address.sendValue(recipient, amount); + } + + /** + * @notice withdraws all funds available in this contract to the address specified + * @dev only owner can call this + * @param recipient address where to send the funds + */ + function withdrawFundsTo(address payable recipient) external onlyOwner { + uint256 amount = address(this).balance; + Address.sendValue(recipient, amount); + } + + /** + * @notice withdraws funds from L2 xDomain alias address (representing this L1 contract) + * @dev only owner can call this + * @param amount of funds to withdraws + * @param refundAddr address where gas excess on L2 will be sent + * WARNING: `refundAddr` is not aliased! Make sure you can recover the refunded funds on L2. + * @return id unique id of the published retryable transaction (keccak256(requestID, uint(0)) + */ + function withdrawFundsFromL2(uint256 amount, address refundAddr) external onlyOwner returns (uint256 id) { + // Build an xDomain message to trigger the ArbSys precompile, which will create a L2 -> L1 tx transferring `amount` + bytes memory message = abi.encodeWithSelector(ArbSys.withdrawEth.selector, address(this)); + // Make the xDomain call + // NOTICE: We approximate the max submission cost of sending a retryable tx with specific calldata length. + uint256 maxSubmissionCost = _approximateMaxSubmissionCost(message.length); + uint256 maxGas = 120_000; // static `maxGas` for L2 -> L1 transfer + uint256 gasPriceBid = s_gasConfig.gasPriceBid; + uint256 l1PaymentValue = s_paymentStrategy == PaymentStrategy.L1 + ? _maxRetryableTicketCost(maxSubmissionCost, maxGas, gasPriceBid) + : 0; + // NOTICE: In the case of PaymentStrategy.L2 the L2 xDomain alias address needs to be funded, as it will be paying the fee. + id = IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).createRetryableTicketNoRefundAliasRewrite{value: l1PaymentValue}( + ARBSYS_ADDR, // target + amount, // L2 call value (requested) + maxSubmissionCost, + refundAddr, // excessFeeRefundAddress + refundAddr, // callValueRefundAddress + maxGas, + gasPriceBid, + message + ); + emit L2WithdrawalRequested(id, amount, refundAddr); + + return id; + } + + /** + * @notice sets config AccessControllerInterface contract + * @dev only owner can call this + * @param accessController new AccessControllerInterface contract address + */ + function setConfigAC(address accessController) external onlyOwner { + _setConfigAC(accessController); + } + + /** + * @notice sets Arbitrum gas configuration + * @dev access control provided by `configAC` + * @param maxGas gas limit for immediate L2 execution attempt. A value around 1M should be sufficient + * @param gasPriceBid maximum L2 gas price to pay + * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) + */ + function setGasConfig( + uint256 maxGas, + uint256 gasPriceBid, + uint256 baseFee, + address gasPriceL1FeedAddr + ) external onlyOwnerOrConfigAccess { + _setGasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); + } + + /** + * @notice sets the payment strategy + * @dev access control provided by `configAC` + * @param _paymentStrategy strategy describing how the contract pays for xDomain calls + */ + function setPaymentStrategy(PaymentStrategy _paymentStrategy) external onlyOwnerOrConfigAccess { + _setPaymentStrategy(_paymentStrategy); + } + + /** + * @notice validate method sends an xDomain L2 tx to update Flags contract, in case of change from `previousAnswer`. + * @dev A retryable ticket is created on the Arbitrum L1 Inbox contract. The tx gas fee can be paid from this + * contract providing a value, or if no L1 value is sent with the xDomain message the gas will be paid by + * the L2 xDomain alias account (generated from `address(this)`). This method is accessed controlled. + * @param previousAnswer previous aggregator answer + * @param currentAnswer new aggregator answer - value of 1 considers the service offline. + */ + function validate( + uint256 /* previousRoundId */, + int256 previousAnswer, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + // Avoids resending to L2 the same tx on every call + if (previousAnswer == currentAnswer) { + return true; + } + + // Excess gas on L2 will be sent to the L2 xDomain alias address of this contract + address refundAddr = L2_ALIAS; + // Encode the ArbitrumSequencerUptimeFeed call + bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; + bool status = currentAnswer == ANSWER_SEQ_OFFLINE; + uint64 timestamp = uint64(block.timestamp); + // Encode `status` and `timestamp` + bytes memory message = abi.encodeWithSelector(selector, status, timestamp); + // Make the xDomain call + // NOTICE: We approximate the max submission cost of sending a retryable tx with specific calldata length. + uint256 maxSubmissionCost = _approximateMaxSubmissionCost(message.length); + uint256 maxGas = s_gasConfig.maxGas; + uint256 gasPriceBid = s_gasConfig.gasPriceBid; + uint256 l1PaymentValue = s_paymentStrategy == PaymentStrategy.L1 + ? _maxRetryableTicketCost(maxSubmissionCost, maxGas, gasPriceBid) + : 0; + // NOTICE: In the case of PaymentStrategy.L2 the L2 xDomain alias address needs to be funded, as it will be paying the fee. + // We also ignore the returned msg number, that can be queried via the `InboxMessageDelivered` event. + IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).createRetryableTicketNoRefundAliasRewrite{value: l1PaymentValue}( + L2_SEQ_STATUS_RECORDER, // target + 0, // L2 call value + maxSubmissionCost, + refundAddr, // excessFeeRefundAddress + refundAddr, // callValueRefundAddress + maxGas, + gasPriceBid, + message + ); + // return success + return true; + } + + /// @notice internal method that stores the payment strategy + function _setPaymentStrategy(PaymentStrategy _paymentStrategy) internal { + s_paymentStrategy = _paymentStrategy; + emit PaymentStrategySet(_paymentStrategy); + } + + /// @notice internal method that stores the gas configuration + function _setGasConfig(uint256 maxGas, uint256 gasPriceBid, uint256 baseFee, address gasPriceL1FeedAddr) internal { + // solhint-disable-next-line gas-custom-errors + require(maxGas > 0, "Max gas is zero"); + // solhint-disable-next-line gas-custom-errors + require(gasPriceBid > 0, "Gas price bid is zero"); + // solhint-disable-next-line gas-custom-errors + require(gasPriceL1FeedAddr != address(0), "Gas price Aggregator is zero address"); + s_gasConfig = GasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); + emit GasConfigSet(maxGas, gasPriceBid, gasPriceL1FeedAddr); + } + + /// @notice Internal method that stores the configuration access controller + function _setConfigAC(address accessController) internal { + address previousAccessController = address(s_configAC); + if (accessController != previousAccessController) { + s_configAC = AccessControllerInterface(accessController); + emit ConfigACSet(previousAccessController, accessController); + } + } + + /** + * @notice Internal method that approximates the `maxSubmissionCost` + * @dev This function estimates the max submission cost using the formula + * implemented in Arbitrum DelayedInbox's calculateRetryableSubmissionFee function + * @param calldataSizeInBytes xDomain message size in bytes + */ + function _approximateMaxSubmissionCost(uint256 calldataSizeInBytes) internal view returns (uint256) { + return + IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).calculateRetryableSubmissionFee( + calldataSizeInBytes, + s_gasConfig.baseFee + ); + } + + /// @notice Internal helper method that calculates the total cost of the xDomain retryable ticket call + function _maxRetryableTicketCost( + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal pure returns (uint256) { + return maxSubmissionCost + maxGas * gasPriceBid; + } + + /// @dev reverts if the caller does not have access to change the configuration + modifier onlyOwnerOrConfigAccess() { + // solhint-disable-next-line gas-custom-errors + require( + msg.sender == owner() || (address(s_configAC) != address(0) && s_configAC.hasAccess(msg.sender, msg.data)), + "No access" + ); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol new file mode 100644 index 0000000..e18efd6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IInbox} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; + +/** + * @notice This interface extends Arbitrum's IInbox interface to include + * the calculateRetryableSubmissionFee. This new function was added as part + * of Arbitrum's Nitro migration but was excluded from the IInbox interface. This setup + * works for us as the team has added it as a public function to the IInbox proxy + * contract's implementation + */ +interface IArbitrumDelayedInbox is IInbox { + function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol new file mode 100644 index 0000000..d5a0138 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title A contract with helpers for cross-domain contract ownership +interface ICrossDomainOwnable { + event L1OwnershipTransferRequested(address indexed from, address indexed to); + + event L1OwnershipTransferred(address indexed from, address indexed to); + + function l1Owner() external returns (address); + + function transferL1Ownership(address recipient) external; + + function acceptL1Ownership() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol new file mode 100644 index 0000000..3df532b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title Forwards a delegatecall to a target, under some conditions +interface IDelegateForwarder { + /// @notice forward delegatecalls the `target` with `data` + /// @param target contract address to be delegatecalled + /// @param data to send to target contract + function forwardDelegate(address target, bytes memory data) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol new file mode 100644 index 0000000..6ae5a3a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IFlags { + function getFlag(address) external view returns (bool); + + function getFlags(address[] calldata) external view returns (bool[] memory); + + function raiseFlag(address) external; + + function raiseFlags(address[] calldata) external; + + function lowerFlag(address) external; + + function lowerFlags(address[] calldata) external; + + function setRaisingAccessController(address) external; + + function setLoweringAccessController(address) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol new file mode 100644 index 0000000..374e381 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title Forwards a call to a target, under some conditions +interface IForwarder { + /// @notice forward calls the `target` with `data` + /// @param target contract address to be called + /// @param data to send to target contract + function forward(address target, bytes memory data) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol new file mode 100644 index 0000000..879dc06 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ISequencerUptimeFeed { + function updateStatus(bool status, uint64 timestamp) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol new file mode 100644 index 0000000..1d03788 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +// solhint-disable-next-line no-unused-import +import {IForwarder} from "../interfaces/IForwarder.sol"; + +/* ./dev dependencies - to be moved from ./dev after audit */ +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/** + * @title OptimismCrossDomainForwarder - L1 xDomain account representation + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can be considered to be owned by the `l1Owner` + */ +contract OptimismCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { + // OVM_L2CrossDomainMessenger is a precompile usually deployed to 0x4200000000000000000000000000000000000007 + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + iOVM_CrossDomainMessenger private immutable OVM_CROSS_DOMAIN_MESSENGER; + + /** + * @notice creates a new Optimism xDomain Forwarder contract + * @param crossDomainMessengerAddr the xDomain bridge messenger (Optimism bridge L2) contract address + * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + */ + constructor(iOVM_CrossDomainMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { + // solhint-disable-next-line gas-custom-errors + require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); + OVM_CROSS_DOMAIN_MESSENGER = crossDomainMessengerAddr; + } + + /** + * @notice versions: + * + * - OptimismCrossDomainForwarder 0.1.0: initial release + * - OptimismCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable + * + * @inheritdoc ITypeAndVersion + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "OptimismCrossDomainForwarder 1.0.0"; + } + + /** + * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address + * @inheritdoc IForwarder + */ + function forward(address target, bytes memory data) external virtual override onlyL1Owner { + Address.functionCall(target, data, "Forwarder call reverted"); + } + + /** + * @notice This is always the address of the OVM_L2CrossDomainMessenger contract + */ + function crossDomainMessenger() public view returns (address) { + return address(OVM_CROSS_DOMAIN_MESSENGER); + } + + /** + * @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + */ + modifier onlyL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == crossDomainMessenger(), "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + iOVM_CrossDomainMessenger(crossDomainMessenger()).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + _; + } + + /** + * @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + */ + modifier onlyProposedL1Owner() override { + address messenger = crossDomainMessenger(); + // solhint-disable-next-line gas-custom-errors + require(msg.sender == messenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + iOVM_CrossDomainMessenger(messenger).xDomainMessageSender() == s_l1PendingOwner, + "Must be proposed L1 owner" + ); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol new file mode 100644 index 0000000..6a41bd9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; +// solhint-disable-next-line no-unused-import +import {IForwarder} from "../interfaces/IForwarder.sol"; + +import {OptimismCrossDomainForwarder} from "./OptimismCrossDomainForwarder.sol"; + +import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/** + * @title OptimismCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Optimism + * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. + * @dev Any other L2 contract which uses this contract's address as a privileged position, + * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` + */ +contract OptimismCrossDomainGovernor is IDelegateForwarder, OptimismCrossDomainForwarder { + /** + * @notice creates a new Optimism xDomain Forwarder contract + * @param crossDomainMessengerAddr the xDomain bridge messenger (Optimism bridge L2) contract address + * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder + */ + constructor( + iOVM_CrossDomainMessenger crossDomainMessengerAddr, + address l1OwnerAddr + ) OptimismCrossDomainForwarder(crossDomainMessengerAddr, l1OwnerAddr) {} + + /** + * @notice versions: + * + * - OptimismCrossDomainForwarder 1.0.0: initial release + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "OptimismCrossDomainGovernor 1.0.0"; + } + + /** + * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + * @inheritdoc IForwarder + */ + function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionCall(target, data, "Governor call reverted"); + } + + /** + * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + * @inheritdoc IDelegateForwarder + */ + function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); + } + + /** + * @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. + */ + modifier onlyLocalOrCrossDomainOwner() { + address messenger = crossDomainMessenger(); + // 1. The delegatecall MUST come from either the L1 owner (via cross-chain message) or the L2 owner + // solhint-disable-next-line gas-custom-errors + require(msg.sender == messenger || msg.sender == owner(), "Sender is not the L2 messenger or owner"); + // 2. The L2 Messenger's caller MUST be the L1 Owner + if (msg.sender == messenger) { + // solhint-disable-next-line gas-custom-errors + require( + iOVM_CrossDomainMessenger(messenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol new file mode 100644 index 0000000..0e6f9c5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; + +import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; + +/** + * @title OptimismSequencerUptimeFeed - L2 sequencer uptime status aggregator + * @notice L2 contract that receives status updates from a specific L1 address, + * records a new answer if the status changed + */ +contract OptimismSequencerUptimeFeed is BaseSequencerUptimeFeed { + string public constant override typeAndVersion = "OptimismSequencerUptimeFeed 1.1.0-dev"; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + IL2CrossDomainMessenger private immutable s_l2CrossDomainMessenger; + + /** + * @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + * @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract + * @param initialStatus The initial status of the feed + */ + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { + s_l2CrossDomainMessenger = IL2CrossDomainMessenger(l2CrossDomainMessengerAddr); + } + + function _validateSender(address l1Sender) internal view override { + if ( + msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender + ) { + revert InvalidSender(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol new file mode 100644 index 0000000..cf5222f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; + +import {BaseValidator} from "../shared/BaseValidator.sol"; + +import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; + +/// @title OptimismValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract OptimismValidator is BaseValidator { + string public constant override typeAndVersion = "OptimismValidator 1.1.0-dev"; + + /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address + /// @param l2UptimeFeedAddr the address of the OptimismSequencerUptimeFeed contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + uint32 gasLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {} + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + // Encode the OptimismSequencerUptimeFeed call + bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; + bool status = currentAnswer == ANSWER_SEQ_OFFLINE; + uint64 timestamp = uint64(block.timestamp); + // Encode `status` and `timestamp` + bytes memory message = abi.encodeWithSelector(selector, status, timestamp); + // Make the xDomain call + IL1CrossDomainMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage( + L2_UPTIME_FEED_ADDR, // target + message, + s_gasLimit + ); + // return success + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol new file mode 100644 index 0000000..c70bc79 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IForwarder} from "../interfaces/IForwarder.sol"; + +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/// @title ScrollCrossDomainForwarder - L1 xDomain account representation +/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. +/// @dev Any other L2 contract which uses this contract's address as a privileged position, +/// can be considered to be owned by the `l1Owner` +contract ScrollCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { + string public constant override typeAndVersion = "ScrollCrossDomainForwarder 1.0.0"; + + address internal immutable i_scrollCrossDomainMessenger; + + /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address + /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { + // solhint-disable-next-line gas-custom-errors + require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); + i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); + } + + /// @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address + /// @inheritdoc IForwarder + function forward(address target, bytes memory data) external override onlyL1Owner { + Address.functionCall(target, data, "Forwarder call reverted"); + } + + /// @notice This is always the address of the Scroll Cross Domain Messenger contract + function crossDomainMessenger() external view returns (address) { + return address(i_scrollCrossDomainMessenger); + } + + /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + _; + } + + /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyProposedL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, + "Must be proposed L1 owner" + ); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol new file mode 100644 index 0000000..dae621e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; +// solhint-disable-next-line no-unused-import +import {IForwarder} from "../interfaces/IForwarder.sol"; + +import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; +import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; + +import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; + +/// @title ScrollCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Scroll +/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. +/// @dev Any other L2 contract which uses this contract's address as a privileged position, +/// can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` +contract ScrollCrossDomainGovernor is IDelegateForwarder, ITypeAndVersion, CrossDomainForwarder { + string public constant override typeAndVersion = "ScrollCrossDomainGovernor 1.0.0"; + + address internal immutable i_scrollCrossDomainMessenger; + + /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address + /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn + constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { + // solhint-disable-next-line gas-custom-errors + require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); + i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); + } + + /// @inheritdoc IForwarder + /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionCall(target, data, "Governor call reverted"); + } + + /// @inheritdoc IDelegateForwarder + /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner + function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { + Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); + } + + /// @notice The address of the Scroll Cross Domain Messenger contract + function crossDomainMessenger() external view returns (address) { + return address(i_scrollCrossDomainMessenger); + } + + /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + _; + } + + /// @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. + modifier onlyLocalOrCrossDomainOwner() { + // 1. The delegatecall MUST come from either the L1 owner (via cross-chain message) or the L2 owner + // solhint-disable-next-line gas-custom-errors + require( + msg.sender == i_scrollCrossDomainMessenger || msg.sender == owner(), + "Sender is not the L2 messenger or owner" + ); + // 2. The L2 Messenger's caller MUST be the L1 Owner + if (msg.sender == i_scrollCrossDomainMessenger) { + // solhint-disable-next-line gas-custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), + "xDomain sender is not the L1 owner" + ); + } + _; + } + + /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. + modifier onlyProposedL1Owner() override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); + // solhint-disable-next-line gas-custom-errors + require( + IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, + "Must be proposed L1 owner" + ); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol new file mode 100644 index 0000000..40f2941 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; + +import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; + +/// @title ScrollSequencerUptimeFeed - L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates, and records a new answer if the status changed +contract ScrollSequencerUptimeFeed is BaseSequencerUptimeFeed { + error ZeroAddress(); + + string public constant override typeAndVersion = "ScrollSequencerUptimeFeed 1.1.0-dev"; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + IL2ScrollMessenger private immutable s_l2CrossDomainMessenger; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract + /// @param initialStatus The initial status of the feed + constructor( + address l1SenderAddress, + address l2CrossDomainMessengerAddr, + bool initialStatus + ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { + if (l2CrossDomainMessengerAddr == address(0)) { + revert ZeroAddress(); + } + + s_l2CrossDomainMessenger = IL2ScrollMessenger(l2CrossDomainMessengerAddr); + } + + function _validateSender(address l1Sender) internal view override { + if ( + msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender + ) { + revert InvalidSender(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol new file mode 100644 index 0000000..b009c80 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; + +import {BaseValidator} from "../shared/BaseValidator.sol"; + +import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; +import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; + +/// @title ScrollValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract ScrollValidator is BaseValidator { + string public constant override typeAndVersion = "ScrollValidator 1.1.0-dev"; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L1_MSG_QUEUE_ADDR; + + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + address l1MessageQueueAddr, + uint32 gasLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { + // solhint-disable-next-line gas-custom-errors + require(l1MessageQueueAddr != address(0), "Invalid L1 message queue address"); + L1_MSG_QUEUE_ADDR = l1MessageQueueAddr; + } + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + // Make the xDomain call + IL1ScrollMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage{ + value: IL1MessageQueue(L1_MSG_QUEUE_ADDR).estimateCrossDomainMessageFee(s_gasLimit) + }( + L2_UPTIME_FEED_ADDR, + 0, + abi.encodeWithSelector( + ISequencerUptimeFeed.updateStatus.selector, + currentAnswer == ANSWER_SEQ_OFFLINE, + uint64(block.timestamp) + ), + s_gasLimit + ); + + // return success + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol new file mode 100644 index 0000000..15c2050 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; + +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; + +/// @title L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates from a specific L1 address, +/// records a new answer if the status changed +abstract contract BaseSequencerUptimeFeed is + ITypeAndVersion, + AggregatorV2V3Interface, + ISequencerUptimeFeed, + SimpleReadAccessController +{ + /// @dev Round info for uptime history + struct Round { + uint64 startedAt; // ─╮ The timestamp at which the round started + uint64 updatedAt; // │ The timestamp at which the round was updated + bool status; // ──────╯ The sequencer status for the round + } + + struct FeedState { + uint80 latestRoundId; // ─╮ The ID of the latest round + uint64 startedAt; // │ The date at which the latest round started + uint64 updatedAt; // │ The date at which the latest round was updated + bool latestStatus; // ────╯ The status of the latest round + } + + /// @notice Sender is not the L2 messenger + error InvalidSender(); + /// @notice Replacement for AggregatorV3Interface "No data present" + error NoDataPresent(); + + event L1SenderTransferred(address indexed from, address indexed to); + /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + /// @dev Emitted when a updateStatus is called without the status changing + event RoundUpdated(int256 status, uint64 updatedAt); + + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint8 public constant override decimals = 0; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override description = "L2 Sequencer Uptime Status Feed"; + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + uint256 public constant override version = 1; + + /// @dev L1 address + address private s_l1Sender; + /// @dev s_latestRoundId == 0 means this contract is uninitialized. + FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); + mapping(uint80 roundId => Round round) private s_rounds; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param initialStatus The initial status of the feed + constructor(address l1SenderAddress, bool initialStatus) { + // We neet to allow l1SenderAddress to be zero because this contract is deployed first + // After deploying the validator contract, this contract will be updated with the correct L1 sender address + _setL1Sender(l1SenderAddress); + + // Initialise roundId == 1 as the first round + _recordRound(1, initialStatus, uint64(block.timestamp)); + } + + /// @notice Check if a roundId is valid in this current contract state + /// @dev Mainly used for AggregatorV2V3Interface functions + /// @param roundId Round ID to check + function _isValidRound(uint256 roundId) private view returns (bool) { + return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; + } + + /// @return L1 sender address + function l1Sender() public view virtual returns (address) { + return s_l1Sender; + } + + /// @notice Set the allowed L1 sender for this contract to a new L1 sender + /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. + /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract + function transferL1Sender(address to) external virtual onlyOwner { + _setL1Sender(to); + } + + /// @notice internal method that stores the L1 sender + function _setL1Sender(address newSender) internal { + address oldSender = s_l1Sender; + if (oldSender != newSender) { + s_l1Sender = newSender; + emit L1SenderTransferred(oldSender, newSender); + } + } + + /// @dev Returns an AggregatorV2V3Interface compatible answer from status flag + /// @param status The status flag to convert to an aggregator-compatible answer + function _getStatusAnswer(bool status) internal pure returns (int256) { + return status ? int256(1) : int256(0); + } + + /// @notice Helper function to record a round and set the latest feed state. + /// @param roundId The round ID to record + /// @param status Sequencer status + /// @param timestamp The L1 block timestamp of status update + function _recordRound(uint80 roundId, bool status, uint64 timestamp) internal { + s_rounds[roundId] = Round({status: status, startedAt: timestamp, updatedAt: uint64(block.timestamp)}); + s_feedState = FeedState({ + latestRoundId: roundId, + latestStatus: status, + startedAt: timestamp, + updatedAt: uint64(block.timestamp) + }); + + emit NewRound(roundId, msg.sender, timestamp); + emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); + } + + /// @notice Helper function to update when a round was last updated + /// @param roundId The round ID to update + /// @param status Sequencer status + function _updateRound(uint80 roundId, bool status) internal { + s_rounds[roundId].updatedAt = uint64(block.timestamp); + s_feedState.updatedAt = uint64(block.timestamp); + emit RoundUpdated(_getStatusAnswer(status), uint64(block.timestamp)); + } + + function _getFeedState() internal view returns (FeedState memory) { + return s_feedState; + } + + /// @inheritdoc AggregatorInterface + function latestAnswer() external view override checkAccess returns (int256) { + return _getStatusAnswer(s_feedState.latestStatus); + } + + /// @inheritdoc AggregatorInterface + function latestTimestamp() external view override checkAccess returns (uint256) { + return s_feedState.startedAt; + } + + /// @inheritdoc AggregatorInterface + function latestRound() external view override checkAccess returns (uint256) { + return s_feedState.latestRoundId; + } + + /// @inheritdoc AggregatorInterface + function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return _getStatusAnswer(s_rounds[uint80(roundId)].status); + } + + /// @inheritdoc AggregatorInterface + function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { + if (!_isValidRound(roundId)) { + revert NoDataPresent(); + } + + return s_rounds[uint80(roundId)].startedAt; + } + + /** + * @notice Record a new status and timestamp if it has changed since the last round. + * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + * + * @param status Sequencer status + * @param timestamp Block timestamp of status update + */ + function updateStatus(bool status, uint64 timestamp) external override { + _validateSender(s_l1Sender); + + FeedState memory feedState = _getFeedState(); + // Ignore if latest recorded timestamp is newer + if (feedState.startedAt > timestamp) { + emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); + return; + } + + if (feedState.latestStatus == status) { + _updateRound(feedState.latestRoundId, status); + } else { + feedState.latestRoundId += 1; + _recordRound(feedState.latestRoundId, status, timestamp); + } + } + + function _validateSender(address l1Sender) internal virtual; + + /// @inheritdoc AggregatorV3Interface + function getRoundData( + uint80 _roundId + ) + public + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + if (!_isValidRound(_roundId)) { + revert NoDataPresent(); + } + + Round storage round = s_rounds[_roundId]; + + return (_roundId, _getStatusAnswer(round.status), uint256(round.startedAt), uint256(round.updatedAt), _roundId); + } + + /// @inheritdoc AggregatorV3Interface + function latestRoundData() + external + view + override + checkAccess + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + FeedState storage feedState = s_feedState; + + return ( + feedState.latestRoundId, + _getStatusAnswer(feedState.latestStatus), + feedState.startedAt, + feedState.updatedAt, + feedState.latestRoundId + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol new file mode 100644 index 0000000..33df388 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; + +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; + +abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValidatorInterface, ITypeAndVersion { + /// @notice emitted when gas cost to spend on L2 is updated + /// @param gasLimit updated gas cost + event GasLimitUpdated(uint32 gasLimit); + + error L1CrossDomainMessengerAddressZero(); + error L2UptimeFeedAddrZero(); + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable L2_UPTIME_FEED_ADDR; + + int256 internal constant ANSWER_SEQ_OFFLINE = 1; + + uint32 internal s_gasLimit; + + /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address + /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { + if (l1CrossDomainMessengerAddress == address(0)) { + revert L1CrossDomainMessengerAddressZero(); + } + if (l2UptimeFeedAddr == address(0)) { + revert L2UptimeFeedAddrZero(); + } + + L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; + L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; + s_gasLimit = gasLimit; + } + + /// @notice fetches the gas cost of sending a cross chain message + function getGasLimit() external view returns (uint32) { + return s_gasLimit; + } + + /// @notice sets the new gas cost to spend when sending cross chain message + /// @param gasLimit the updated gas cost + function setGasLimit(uint32 gasLimit) external onlyOwner { + s_gasLimit = gasLimit; + emit GasLimitUpdated(gasLimit); + } + + /// @notice makes this contract payable + /// @dev receives funds: + /// - to use them (if configured) to pay for L2 execution on L1 + /// - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) + receive() external payable {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol new file mode 100644 index 0000000..0074a02 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; + +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; + +/// @title ZKSyncSequencerUptimeFeed - L2 sequencer uptime status aggregator +/// @notice L2 contract that receives status updates from a specific L1 address, +/// records a new answer if the status changed +contract ZKSyncSequencerUptimeFeed is BaseSequencerUptimeFeed { + string public constant override typeAndVersion = "ZKSyncSequencerUptimeFeed 1.1.0-dev"; + + /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract + /// @param initialStatus The initial status of the feed + constructor(address l1SenderAddress, bool initialStatus) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) {} + + function _validateSender(address l1Sender) internal view override { + address aliasedL1Sender = AddressAliasHelper.applyL1ToL2Alias(l1Sender); + + if (msg.sender != aliasedL1Sender) { + revert InvalidSender(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol new file mode 100644 index 0000000..10f68ce --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; + +import {BaseValidator} from "../shared/BaseValidator.sol"; + +import {IBridgehub, L2TransactionRequestDirect} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; + +/// @title ZKSyncValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 +contract ZKSyncValidator is BaseValidator { + /// Contract state variables + string public constant override typeAndVersion = "ZKSyncValidator 1.1.0-dev"; + uint32 private constant ZKSYNC_TEST_NET_CHAIN_ID = 300; + uint32 private constant ZKSYNC_MAIN_NET_CHAIN_ID = 324; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + uint32 private immutable CHAIN_ID; + /// @dev how much l2 gas each byte of pubdata costs + uint32 private s_l2GasPerPubdataByteLimit; + + /// @notice emitted when the gas per pubdata byte limit is updated + /// @param l2GasPerPubdataByteLimit updated gas per pubdata byte limit + event GasPerPubdataByteLimitUpdated(uint32 l2GasPerPubdataByteLimit); + + /// @notice ChainID is not a valid value + error InvalidChainID(); + + /// @param l1CrossDomainMessengerAddress address the Bridgehub contract address + /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeedInterface contract address + /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 + constructor( + address l1CrossDomainMessengerAddress, + address l2UptimeFeedAddr, + uint32 gasLimit, + uint32 chainId, + uint32 l2GasPerPubdataByteLimit + ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { + if (chainId != ZKSYNC_TEST_NET_CHAIN_ID && chainId != ZKSYNC_MAIN_NET_CHAIN_ID) { + revert InvalidChainID(); + } + + s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; + CHAIN_ID = chainId; + } + + /// @notice sets the l2GasPerPubdataByteLimit for the L2 transaction request + /// @param l2GasPerPubdataByteLimit the updated l2GasPerPubdataByteLimit + function setL2GasPerPubdataByteLimit(uint32 l2GasPerPubdataByteLimit) external onlyOwner { + if (s_l2GasPerPubdataByteLimit != l2GasPerPubdataByteLimit) { + s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; + emit GasPerPubdataByteLimitUpdated(l2GasPerPubdataByteLimit); + } + } + + /// @notice fetches the l2GasPerPubdataByteLimit for the L2 transaction request + function getL2GasPerPubdataByteLimit() external view returns (uint32) { + return s_l2GasPerPubdataByteLimit; + } + + /// @notice fetches the chain id + function getChainId() external view returns (uint32) { + return CHAIN_ID; + } + + /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. + /// @dev A message is sent using the Bridgehub. This method is accessed controlled. + /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. + function validate( + uint256 /* previousRoundId */, + int256 /* previousAnswer */, + uint256 /* currentRoundId */, + int256 currentAnswer + ) external override checkAccess returns (bool) { + IBridgehub bridgeHub = IBridgehub(L1_CROSS_DOMAIN_MESSENGER_ADDRESS); + + uint256 transactionBaseCostEstimate = bridgeHub.l2TransactionBaseCost( + CHAIN_ID, + tx.gasprice, + s_gasLimit, + s_l2GasPerPubdataByteLimit + ); + + L2TransactionRequestDirect memory l2TransactionRequestDirect = L2TransactionRequestDirect({ + chainId: CHAIN_ID, + mintValue: transactionBaseCostEstimate, + l2Contract: L2_UPTIME_FEED_ADDR, + l2Value: 0, + l2Calldata: abi.encodeWithSelector( + ISequencerUptimeFeed.updateStatus.selector, + currentAnswer == ANSWER_SEQ_OFFLINE, + uint64(block.timestamp) + ), + l2GasLimit: s_gasLimit, + l2GasPerPubdataByteLimit: s_l2GasPerPubdataByteLimit, + factoryDeps: new bytes[](0), + refundRecipient: msg.sender + }); + + // Make the xDomain call + bridgeHub.requestL2TransactionDirect{value: transactionBaseCostEstimate}(l2TransactionRequestDirect); + + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol new file mode 100644 index 0000000..5201932 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; + +contract MockAggregatorV2V3 is AggregatorV2V3Interface { + function latestAnswer() external pure returns (int256) { + return 0; + } + + function latestTimestamp() external pure returns (uint256) { + return 0; + } + + function latestRound() external pure returns (uint256) { + return 0; + } + + function getAnswer(uint256) external pure returns (int256) { + return 0; + } + + function getTimestamp(uint256 roundId) external pure returns (uint256) { + return roundId; + } + + function decimals() external pure returns (uint8) { + return 0; + } + + function description() external pure returns (string memory) { + return ""; + } + + function version() external pure returns (uint256) { + return 0; + } + + function getRoundData( + uint80 + ) + external + pure + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (0, 0, 0, 0, 0); + } + + function latestRoundData() + external + pure + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (73786976294838220258, 96800000000, 163826896, 1638268960, 73786976294838220258); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol new file mode 100644 index 0000000..0c4193a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {iOVM_CrossDomainMessenger} from "../../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; + +import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; + +contract MockOVMCrossDomainMessenger is iOVM_CrossDomainMessenger { + address internal s_mockMessageSender; + + constructor(address sender) { + s_mockMessageSender = sender; + } + + function xDomainMessageSender() external view override returns (address) { + return s_mockMessageSender; + } + + function _setMockMessageSender(address sender) external { + s_mockMessageSender = sender; + } + + /** + * Sends a cross domain message to the target messenger. + * @param _target Target contract address. + * @param _message Message to send to the target. + */ + function sendMessage(address _target, bytes calldata _message, uint32) external override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol new file mode 100644 index 0000000..3724491 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; + +import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; + +contract MockScrollCrossDomainMessenger is IScrollMessenger { + address internal s_mockMessageSender; + + constructor(address sender) { + s_mockMessageSender = sender; + } + + function xDomainMessageSender() external view override returns (address) { + return s_mockMessageSender; + } + + function _setMockMessageSender(address sender) external { + s_mockMessageSender = sender; + } + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256, address) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol new file mode 100644 index 0000000..42147fb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; + +contract MockScrollL1CrossDomainMessenger is IL1ScrollMessenger { + uint256 private s_nonce; + + function xDomainMessageSender() public pure returns (address) { + return address(0); + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit, + address + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function relayMessageWithProof( + address from, + address to, + uint256 value, + uint256 nonce, + bytes memory message, + L2MessageProof memory proof + ) external override {} + + function replayMessage( + address from, + address to, + uint256 value, + uint256 messageNonce, + bytes memory message, + uint32 newGasLimit, + address refundAddress + ) external payable override {} + + function dropMessage( + address from, + address to, + uint256 value, + uint256 messageNonce, + bytes memory message + ) external override {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol new file mode 100644 index 0000000..e43f1bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; + +contract MockScrollL1MessageQueue is IL1MessageQueue { + /// @notice The start index of all pending inclusion messages. + function pendingQueueIndex() external pure returns (uint256) { + return 0; + } + + /// @notice Return the index of next appended message. + function nextCrossDomainMessageIndex() external pure returns (uint256) { + return 0; + } + + /// @notice Return the message of in `queueIndex`. + function getCrossDomainMessage(uint256 /* queueIndex */) external pure returns (bytes32) { + return ""; + } + + /// @notice Return the amount of ETH should pay for cross domain message. + function estimateCrossDomainMessageFee(uint256 /* gasLimit */) external pure returns (uint256) { + return 0; + } + + /// @notice Return the amount of intrinsic gas fee should pay for cross domain message. + function calculateIntrinsicGasFee(bytes memory /* _calldata */) external pure returns (uint256) { + return 0; + } + + /// @notice Return the hash of a L1 message. + function computeTransactionHash( + address /* sender */, + uint256 /* queueIndex */, + uint256 /* value */, + address /* target */, + uint256 /* gasLimit */, + bytes calldata /* data */ + ) external pure returns (bytes32) { + return 0; + } + + /// @notice Append a L1 to L2 message into this contract. + /// @param target The address of target contract to call in L2. + /// @param gasLimit The maximum gas should be used for relay this message in L2. + /// @param data The calldata passed to target contract. + function appendCrossDomainMessage(address target, uint256 gasLimit, bytes calldata data) external {} + + /// @notice Append an enforced transaction to this contract. + /// @dev The address of sender should be an EOA. + /// @param sender The address of sender who will initiate this transaction in L2. + /// @param target The address of target contract to call in L2. + /// @param value The value passed + /// @param gasLimit The maximum gas should be used for this transaction in L2. + /// @param data The calldata passed to target contract. + function appendEnforcedTransaction( + address sender, + address target, + uint256 value, + uint256 gasLimit, + bytes calldata data + ) external {} + + /// @notice Pop finalized messages from queue. + /// + /// @dev We can pop at most 256 messages each time. And if the message is not skipped, + /// the corresponding entry will be cleared. + /// + /// @param startIndex The start index to pop. + /// @param count The number of messages to pop. + /// @param skippedBitmap A bitmap indicates whether a message is skipped. + function popCrossDomainMessage(uint256 startIndex, uint256 count, uint256 skippedBitmap) external {} + + /// @notice Drop a skipped message from the queue. + function dropCrossDomainMessage(uint256 index) external {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol new file mode 100644 index 0000000..af0e0b5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; + +contract MockScrollL2CrossDomainMessenger is IL2ScrollMessenger { + uint256 private s_nonce; + address private s_sender; + + function xDomainMessageSender() public view returns (address) { + return s_sender; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function sendMessage( + address _target, + uint256 _value, + bytes calldata _message, + uint256 _gasLimit, + address + ) external payable override { + emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); + s_nonce++; + } + + function relayMessage( + address from, + address to, + uint256 value, + uint256 nonce, + bytes calldata message + ) external override {} + + /// Needed for backwards compatibility in Hardhat tests + function setSender(address newSender) external { + s_sender = newSender; + } + + /// Needed for backwards compatibility in Hardhat tests + receive() external payable {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol new file mode 100644 index 0000000..b46b9d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; +import {IL1SharedBridge} from "@zksync/contracts/l1-contracts/contracts/bridge/interfaces/IL1SharedBridge.sol"; +import {L2Message, L2Log, TxStatus} from "@zksync/contracts/l1-contracts/contracts/common/Messaging.sol"; + +contract MockBridgehub is IBridgehub { + address public pendingAdmin; + address public admin; + address public sharedBridgeAddr; + + mapping(address stateTransitionManager => bool stateTransitionManagerIsRegistered) + public registeredStateTransitionManagers; + mapping(uint256 chainId => address stateTransitionManagerAddress) public stateTransitionManagers; + mapping(address baseToken => bool tokenIsRegistered) public registeredTokens; + mapping(uint256 chainId => address baseToken) public baseTokens; + mapping(uint256 chainId => address hyperChain) public hyperchains; + + /// Generic error for unauthorized actions + error NotAuthorized(string msg); + + /// Fake event that will get emitted when `requestL2TransactionDirect` is called + event SentMessage(address indexed sender, bytes message); + + /// Admin functions + function setPendingAdmin(address _newPendingAdmin) external override { + emit NewPendingAdmin(pendingAdmin, _newPendingAdmin); + pendingAdmin = _newPendingAdmin; + } + + function acceptAdmin() external override { + if (msg.sender != pendingAdmin) { + revert NotAuthorized("Only pending admin can accept"); + } + + emit NewAdmin(admin, pendingAdmin); + admin = pendingAdmin; + pendingAdmin = address(0); + } + + /// Getters + function stateTransitionManagerIsRegistered(address _stateTransitionManager) external view override returns (bool) { + return registeredStateTransitionManagers[_stateTransitionManager]; + } + + function stateTransitionManager(uint256 _chainId) external view override returns (address) { + return stateTransitionManagers[_chainId]; + } + + function tokenIsRegistered(address _baseToken) external view override returns (bool) { + return registeredTokens[_baseToken]; + } + + function baseToken(uint256 _chainId) external view override returns (address) { + return baseTokens[_chainId]; + } + + function sharedBridge() external view override returns (IL1SharedBridge) { + return IL1SharedBridge(sharedBridgeAddr); + } + + function getHyperchain(uint256 _chainId) external view override returns (address) { + return hyperchains[_chainId]; + } + + /// Mailbox forwarder + function proveL2MessageInclusion( + uint256, + uint256, + uint256, + L2Message calldata, + bytes32[] calldata + ) external pure override returns (bool) { + return true; + } + + function proveL2LogInclusion( + uint256, + uint256, + uint256, + L2Log memory, + bytes32[] calldata + ) external pure override returns (bool) { + return true; + } + + function proveL1ToL2TransactionStatus( + uint256, + bytes32, + uint256, + uint256, + uint16, + bytes32[] calldata, + TxStatus + ) external pure override returns (bool) { + return true; + } + + function requestL2TransactionDirect( + L2TransactionRequestDirect calldata txRequest + ) external payable override returns (bytes32) { + emit SentMessage(msg.sender, txRequest.l2Calldata); + return keccak256(abi.encodePacked("L2TransactionDirect")); + } + + function requestL2TransactionTwoBridges( + L2TransactionRequestTwoBridgesOuter calldata + ) external payable override returns (bytes32) { + return keccak256(abi.encodePacked("L2TransactionTwoBridges")); + } + + function l2TransactionBaseCost(uint256, uint256, uint256, uint256) external pure override returns (uint256) { + return 0; + } + + /// Registry + function createNewChain( + uint256 _chainId, + address _stateTransitionManager, + address _baseToken, + uint256, + address, + bytes calldata + ) external override returns (uint256 chainId) { + hyperchains[_chainId] = _stateTransitionManager; + baseTokens[_chainId] = _baseToken; + emit NewChain(_chainId, _stateTransitionManager, address(this)); + return _chainId; + } + + function addStateTransitionManager(address _stateTransitionManager) external override { + registeredStateTransitionManagers[_stateTransitionManager] = true; + } + + function removeStateTransitionManager(address _stateTransitionManager) external override { + registeredStateTransitionManagers[_stateTransitionManager] = false; + } + + function addToken(address _token) external override { + registeredTokens[_token] = true; + } + + function setSharedBridge(address _sharedBridgeAddr) external override { + sharedBridgeAddr = _sharedBridgeAddr; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol new file mode 100644 index 0000000..93640f4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {Greeter} from "../../../tests/Greeter.sol"; + +import {MultiSend} from "../../../vendor/MultiSend.sol"; +import {Test} from "forge-std/Test.sol"; + +contract L2EPTest is Test { + /// Helper variable(s) + address internal s_strangerAddr = vm.addr(0x1); + address internal s_l1OwnerAddr = vm.addr(0x2); + address internal s_eoaValidator = vm.addr(0x3); + address internal s_deployerAddr = vm.addr(0x4); + + /// @param selector - the function selector + /// @param greeterAddr - the address of the Greeter contract + /// @param message - the new greeting message, which will be passed as an argument to Greeter#setGreeting + /// @return a 2-layer encoding such that decoding the first layer provides the CrossDomainForwarder#forward + /// function selector and the corresponding arguments to the forward function, and decoding the + /// second layer provides the Greeter#setGreeting function selector and the corresponding + /// arguments to the set greeting function (which in this case is the input message) + function encodeCrossDomainSetGreetingMsg( + bytes4 selector, + address greeterAddr, + string memory message + ) public pure returns (bytes memory) { + return abi.encodeWithSelector(selector, greeterAddr, abi.encodeWithSelector(Greeter.setGreeting.selector, message)); + } + + /// @param selector - the function selector + /// @param multiSendAddr - the address of the MultiSend contract + /// @param encodedTxs - an encoded list of transactions (e.g. abi.encodePacked(encodeMultiSendTx("some data"), ...)) + /// @return a 2-layer encoding such that decoding the first layer provides the CrossDomainGoverner#forwardDelegate + /// function selector and the corresponding arguments to the forwardDelegate function, and decoding the + /// second layer provides the MultiSend#multiSend function selector and the corresponding + /// arguments to the multiSend function (which in this case is the input encodedTxs) + function encodeCrossDomainMultiSendMsg( + bytes4 selector, + address multiSendAddr, + bytes memory encodedTxs + ) public pure returns (bytes memory) { + return + abi.encodeWithSelector(selector, multiSendAddr, abi.encodeWithSelector(MultiSend.multiSend.selector, encodedTxs)); + } + + /// @param greeterAddr - the address of the greeter contract + /// @param data - the transaction data string + /// @return an encoded transaction structured as specified in the MultiSend#multiSend comments + function encodeMultiSendTx(address greeterAddr, bytes memory data) public pure returns (bytes memory) { + bytes memory txData = abi.encodeWithSelector(Greeter.setGreeting.selector, data); + return + abi.encodePacked( + uint8(0), // operation + greeterAddr, // to + uint256(0), // value + uint256(txData.length), // data length + txData // data as bytes + ); + } + + /// @param l1Address - Address on L1 + /// @return an Arbitrum L2 address + function toArbitrumL2AliasAddress(address l1Address) public pure returns (address) { + return address(uint160(l1Address) + uint160(0x1111000000000000000000000000000000001111)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol new file mode 100644 index 0000000..cff9b95 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ArbitrumCrossDomainForwarder} from "../../../dev/arbitrum/ArbitrumCrossDomainForwarder.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ArbitrumCrossDomainForwarderTest is L2EPTest { + /// Helper variable(s) + address internal s_crossDomainMessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); + address internal s_newOwnerCrossDomainMessengerAddr = toArbitrumL2AliasAddress(s_strangerAddr); + + /// Contracts + ArbitrumCrossDomainForwarder internal s_arbitrumCrossDomainForwarder; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_arbitrumCrossDomainForwarder = new ArbitrumCrossDomainForwarder(s_l1OwnerAddr); + s_greeter = new Greeter(address(s_arbitrumCrossDomainForwarder)); + vm.stopPrank(); + } +} + +contract ArbitrumCrossDomainForwarder_Constructor is ArbitrumCrossDomainForwarderTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_arbitrumCrossDomainForwarder.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_arbitrumCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_arbitrumCrossDomainForwarder.crossDomainMessenger(), s_crossDomainMessengerAddr); + + // it should set the typeAndVersion correctly + assertEq(s_arbitrumCrossDomainForwarder.typeAndVersion(), "ArbitrumCrossDomainForwarder 1.0.0"); + } +} + +contract ArbitrumCrossDomainForwarder_Forward is ArbitrumCrossDomainForwarderTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_arbitrumCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_arbitrumCrossDomainForwarder.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_arbitrumCrossDomainForwarder.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, "") + ); + } +} + +contract ArbitrumCrossDomainForwarder_TransferL1Ownership is ArbitrumCrossDomainForwarderTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_arbitrumCrossDomainForwarder.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_arbitrumCrossDomainForwarder.l1Owner(), s_strangerAddr); + + // Sends the message + s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_arbitrumCrossDomainForwarder.l1Owner(), address(0)); + + // Sends the message + s_arbitrumCrossDomainForwarder.transferL1Ownership(address(0)); + } +} + +contract ArbitrumCrossDomainForwarder_AcceptL1Ownership is ArbitrumCrossDomainForwarderTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_arbitrumCrossDomainForwarder.acceptL1Ownership(); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Request ownership transfer + vm.startPrank(s_crossDomainMessengerAddr); + s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + vm.startPrank(s_newOwnerCrossDomainMessengerAddr); + s_arbitrumCrossDomainForwarder.acceptL1Ownership(); + + // Asserts that the ownership was actually transferred + assertEq(s_arbitrumCrossDomainForwarder.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol new file mode 100644 index 0000000..610f49f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ArbitrumCrossDomainGovernor} from "../../../dev/arbitrum/ArbitrumCrossDomainGovernor.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +import {MultiSend} from "../../../../vendor/MultiSend.sol"; + +contract ArbitrumCrossDomainGovernorTest is L2EPTest { + /// Helper variable(s) + address internal s_crossDomainMessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); + address internal s_newOwnerCrossDomainMessengerAddr = toArbitrumL2AliasAddress(s_strangerAddr); + + /// Contracts + ArbitrumCrossDomainGovernor internal s_arbitrumCrossDomainGovernor; + MultiSend internal s_multiSend; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_arbitrumCrossDomainGovernor = new ArbitrumCrossDomainGovernor(s_l1OwnerAddr); + s_greeter = new Greeter(address(s_arbitrumCrossDomainGovernor)); + s_multiSend = new MultiSend(); + vm.stopPrank(); + } +} + +contract ArbitrumCrossDomainGovernor_Constructor is ArbitrumCrossDomainGovernorTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_arbitrumCrossDomainGovernor.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_arbitrumCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_arbitrumCrossDomainGovernor.crossDomainMessenger(), s_crossDomainMessengerAddr); + + // it should set the typeAndVersion correctly + assertEq(s_arbitrumCrossDomainGovernor.typeAndVersion(), "ArbitrumCrossDomainGovernor 1.0.0"); + } +} + +contract ArbitrumCrossDomainGovernor_Forward is ArbitrumCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_arbitrumCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_arbitrumCrossDomainGovernor.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_arbitrumCrossDomainGovernor.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_arbitrumCrossDomainGovernor.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, "") + ); + } +} + +contract ArbitrumCrossDomainGovernor_ForwardDelegate is ArbitrumCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_arbitrumCrossDomainGovernor.forwardDelegate(address(s_multiSend), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends the message + s_arbitrumCrossDomainGovernor.forwardDelegate( + address(s_multiSend), + abi.encodeWithSelector( + MultiSend.multiSend.selector, + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ) + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Sends the message + s_arbitrumCrossDomainGovernor.forwardDelegate( + address(s_multiSend), + abi.encodeWithSelector( + MultiSend.multiSend.selector, + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ) + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should revert batch when one call fails + function test_RevertsBatchWhenOneCallFails() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Governor delegatecall reverted"); + s_arbitrumCrossDomainGovernor.forwardDelegate( + address(s_multiSend), + abi.encodeWithSelector( + MultiSend.multiSend.selector, + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) + ) + ); + + // Checks that the greeter message is unchanged + assertEq(s_greeter.greeting(), ""); + } + + /// @notice it should bubble up revert when contract call reverts + function test_BubbleUpRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Greeter: revert triggered"); + s_arbitrumCrossDomainGovernor.forwardDelegate( + address(s_greeter), + abi.encodeWithSelector(Greeter.triggerRevert.selector) + ); + } +} + +contract ArbitrumCrossDomainGovernor_TransferL1Ownership is ArbitrumCrossDomainGovernorTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_arbitrumCrossDomainGovernor.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_arbitrumCrossDomainGovernor.l1Owner(), s_strangerAddr); + + // Sends the message + s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_arbitrumCrossDomainGovernor.l1Owner(), address(0)); + + // Sends the message + s_arbitrumCrossDomainGovernor.transferL1Ownership(address(0)); + } +} + +contract ArbitrumCrossDomainGovernor_AcceptL1Ownership is ArbitrumCrossDomainGovernorTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_crossDomainMessengerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_arbitrumCrossDomainGovernor.acceptL1Ownership(); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Request ownership transfer + vm.startPrank(s_crossDomainMessengerAddr); + s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + vm.startPrank(s_newOwnerCrossDomainMessengerAddr); + s_arbitrumCrossDomainGovernor.acceptL1Ownership(); + + // Asserts that the ownership was actually transferred + assertEq(s_arbitrumCrossDomainGovernor.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol new file mode 100644 index 0000000..e308ead --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {Flags} from "../../../dev/Flags.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ArbitrumSequencerUptimeFeedTest is L2EPTest { + /// Constants + uint256 internal constant GAS_USED_DEVIATION = 100; + + /// Helper variable(s) + address internal s_l2MessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); + + /// L2EP contracts + ArbitrumSequencerUptimeFeed internal s_arbitrumSequencerUptimeFeed; + SimpleWriteAccessController internal s_accessController; + MockAggregatorV2V3 internal s_l1GasFeed; + Flags internal s_flags; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + event Initialized(); + + /// Setup + function setUp() public { + vm.startPrank(s_deployerAddr, s_deployerAddr); + + s_accessController = new SimpleWriteAccessController(); + s_flags = new Flags(address(s_accessController), address(s_accessController)); + s_arbitrumSequencerUptimeFeed = new ArbitrumSequencerUptimeFeed(address(s_flags), s_l1OwnerAddr); + + s_accessController.addAccess(address(s_arbitrumSequencerUptimeFeed)); + s_accessController.addAccess(address(s_flags)); + s_accessController.addAccess(s_deployerAddr); + s_flags.addAccess(address(s_arbitrumSequencerUptimeFeed)); + + vm.expectEmit(); + emit Initialized(); + s_arbitrumSequencerUptimeFeed.initialize(); + + vm.stopPrank(); + } +} + +contract ArbitrumSequencerUptimeFeed_Constants is ArbitrumSequencerUptimeFeedTest { + /// @notice it should have the correct value for FLAG_L2_SEQ_OFFLINE' + function test_InitialState() public { + assertEq(s_arbitrumSequencerUptimeFeed.FLAG_L2_SEQ_OFFLINE(), 0xa438451D6458044c3c8CD2f6f31c91ac882A6d91); + } +} + +contract ArbitrumSequencerUptimeFeed_UpdateStatus is ArbitrumSequencerUptimeFeedTest { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(ArbitrumSequencerUptimeFeed.InvalidSender.selector); + s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract ArbitrumSequencerUptimeFeed_AggregatorV3Interface is ArbitrumSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_Return0WhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) = s_arbitrumSequencerUptimeFeed.getRoundData(2); + + // Validates round data + assertEq(roundId, 2); + assertEq(answer, 0); + assertEq(startedAt, 0); + assertEq(updatedAt, 0); + assertEq(answeredInRound, 2); + } +} + +contract ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ArbitrumSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_arbitrumSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_arbitrumSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_arbitrumSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_arbitrumSequencerUptimeFeed)); + + // Whitelist consumer + vm.startPrank(s_deployerAddr, s_deployerAddr); + s_arbitrumSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_arbitrumSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_arbitrumSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol new file mode 100644 index 0000000..ab87299 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; + +import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {ArbitrumValidator} from "../../../dev/arbitrum/ArbitrumValidator.sol"; +import {MockArbitrumInbox} from "../../../../tests/MockArbitrumInbox.sol"; +import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ArbitrumValidatorTest is L2EPTest { + /// Helper constants + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; + uint256 internal constant GAS_PRICE_BID = 1000000; + uint256 internal constant BASE_FEE = 14000000000; + uint256 internal constant MAX_GAS = 1000000; + + /// L2EP contracts + AccessControllerInterface internal s_accessController; + MockArbitrumInbox internal s_mockArbitrumInbox; + ArbitrumValidator internal s_arbitrumValidator; + MockAggregatorV2V3 internal s_l1GasFeed; + + /// Events + event RetryableTicketNoRefundAliasRewriteCreated( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes data + ); + + /// Setup + function setUp() public { + s_accessController = new SimpleWriteAccessController(); + s_mockArbitrumInbox = new MockArbitrumInbox(); + s_l1GasFeed = new MockAggregatorV2V3(); + s_arbitrumValidator = new ArbitrumValidator( + address(s_mockArbitrumInbox), + L2_SEQ_STATUS_RECORDER_ADDRESS, + address(s_accessController), + MAX_GAS, + GAS_PRICE_BID, + BASE_FEE, + address(s_l1GasFeed), + ArbitrumValidator.PaymentStrategy.L1 + ); + } +} + +contract ArbitrumValidator_Validate is ArbitrumValidatorTest { + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { + // Gives access to the s_eoaValidator + s_arbitrumValidator.addAccess(s_eoaValidator); + + // Gets the ArbitrumValidator L2 address + address arbitrumValidatorL2Addr = toArbitrumL2AliasAddress(address(s_arbitrumValidator)); + + // Sets block.timestamp to a later date, funds the ArbitrumValidator contract, and sets msg.sender and tx.origin + uint256 futureTimestampInSeconds = block.timestamp + 5000; + vm.warp(futureTimestampInSeconds); + vm.deal(address(s_arbitrumValidator), 1 ether); + vm.startPrank(s_eoaValidator); + + // Sets up the expected event data + vm.expectEmit(); + emit RetryableTicketNoRefundAliasRewriteCreated( + L2_SEQ_STATUS_RECORDER_ADDRESS, // destAddr + 0, // arbTxCallValue + 25312000000000, // maxSubmissionCost + arbitrumValidatorL2Addr, // submissionRefundAddress + arbitrumValidatorL2Addr, // valueRefundAddress + MAX_GAS, // maxGas + GAS_PRICE_BID, // gasPriceBid + abi.encodeWithSelector(ArbitrumSequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // data + ); + + // Runs the function (which produces the event to test) + s_arbitrumValidator.validate(0, 0, 1, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol new file mode 100644 index 0000000..c0e82ab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol @@ -0,0 +1,187 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {OptimismCrossDomainForwarder} from "../../../dev/optimism/OptimismCrossDomainForwarder.sol"; +import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract OptimismCrossDomainForwarderTest is L2EPTest { + /// Contracts + MockOVMCrossDomainMessenger internal s_mockOptimismCrossDomainMessenger; + OptimismCrossDomainForwarder internal s_optimismCrossDomainForwarder; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_mockOptimismCrossDomainMessenger = new MockOVMCrossDomainMessenger(s_l1OwnerAddr); + s_optimismCrossDomainForwarder = new OptimismCrossDomainForwarder( + s_mockOptimismCrossDomainMessenger, + s_l1OwnerAddr + ); + s_greeter = new Greeter(address(s_optimismCrossDomainForwarder)); + vm.stopPrank(); + } +} + +contract OptimismCrossDomainForwarder_Constructor is OptimismCrossDomainForwarderTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_optimismCrossDomainForwarder.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_optimismCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_optimismCrossDomainForwarder.crossDomainMessenger(), address(s_mockOptimismCrossDomainMessenger)); + + // it should set the typeAndVersion correctly + assertEq(s_optimismCrossDomainForwarder.typeAndVersion(), "OptimismCrossDomainForwarder 1.0.0"); + } +} + +contract OptimismCrossDomainForwarder_Forward is OptimismCrossDomainForwarderTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_optimismCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainForwarder.forward.selector, address(s_greeter), greeting), // message + 0 // gas limit + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainForwarder.forward.selector, address(s_greeter), ""), // message + 0 // gas limit + ); + } +} + +contract OptimismCrossDomainForwarder_TransferL1Ownership is OptimismCrossDomainForwarderTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_optimismCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_optimismCrossDomainForwarder.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_optimismCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_optimismCrossDomainForwarder.l1Owner(), s_strangerAddr); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_optimismCrossDomainForwarder.l1Owner(), address(0)); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, address(0)), // message + 0 // gas limit + ); + } +} + +contract OptimismCrossDomainForwarder_AcceptL1Ownership is OptimismCrossDomainForwarderTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + abi.encodeWithSelector(s_optimismCrossDomainForwarder.acceptL1Ownership.selector), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Request ownership transfer + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Sets a mock message sender + s_mockOptimismCrossDomainMessenger._setMockMessageSender(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainForwarder), // target + abi.encodeWithSelector(s_optimismCrossDomainForwarder.acceptL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Asserts that the ownership was actually transferred + assertEq(s_optimismCrossDomainForwarder.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol new file mode 100644 index 0000000..8f8fb9d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {OptimismCrossDomainGovernor} from "../../../dev/optimism/OptimismCrossDomainGovernor.sol"; +import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +import {MultiSend} from "../../../../vendor/MultiSend.sol"; + +contract OptimismCrossDomainGovernorTest is L2EPTest { + /// Contracts + MockOVMCrossDomainMessenger internal s_mockOptimismCrossDomainMessenger; + OptimismCrossDomainGovernor internal s_optimismCrossDomainGovernor; + MultiSend internal s_multiSend; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_mockOptimismCrossDomainMessenger = new MockOVMCrossDomainMessenger(s_l1OwnerAddr); + s_optimismCrossDomainGovernor = new OptimismCrossDomainGovernor(s_mockOptimismCrossDomainMessenger, s_l1OwnerAddr); + s_greeter = new Greeter(address(s_optimismCrossDomainGovernor)); + s_multiSend = new MultiSend(); + vm.stopPrank(); + } +} + +contract OptimismCrossDomainGovernor_Constructor is OptimismCrossDomainGovernorTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_optimismCrossDomainGovernor.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_optimismCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_optimismCrossDomainGovernor.crossDomainMessenger(), address(s_mockOptimismCrossDomainMessenger)); + + // it should set the typeAndVersion correctly + assertEq(s_optimismCrossDomainGovernor.typeAndVersion(), "OptimismCrossDomainGovernor 1.0.0"); + } +} + +contract OptimismCrossDomainGovernor_Forward is OptimismCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_optimismCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainGovernor.forward.selector, address(s_greeter), greeting), // message + 0 // gas limit + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainGovernor.forward.selector, address(s_greeter), ""), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_optimismCrossDomainGovernor.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), greeting); + } +} + +contract OptimismCrossDomainGovernor_ForwardDelegate is OptimismCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_optimismCrossDomainGovernor.forwardDelegate(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + encodeCrossDomainMultiSendMsg( + s_optimismCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + encodeCrossDomainMultiSendMsg( + s_optimismCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should revert batch when one call fails + function test_RevertsBatchWhenOneCallFails() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Governor delegatecall reverted"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + encodeCrossDomainMultiSendMsg( + s_optimismCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message is unchanged + assertEq(s_greeter.greeting(), ""); + } + + /// @notice it should bubble up revert when contract call reverts + function test_BubbleUpRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Greeter: revert triggered"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector( + OptimismCrossDomainGovernor.forwardDelegate.selector, + address(s_greeter), + abi.encodeWithSelector(Greeter.triggerRevert.selector) + ), // message + 0 // gas limit + ); + } +} + +contract OptimismCrossDomainGovernor_TransferL1Ownership is OptimismCrossDomainGovernorTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_optimismCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_optimismCrossDomainGovernor.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_optimismCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_optimismCrossDomainGovernor.l1Owner(), s_strangerAddr); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_optimismCrossDomainGovernor.l1Owner(), address(0)); + + // Sends the message + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, address(0)), // message + 0 // gas limit + ); + } +} + +contract OptimismCrossDomainGovernor_AcceptL1Ownership is OptimismCrossDomainGovernorTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector(s_optimismCrossDomainGovernor.acceptL1Ownership.selector), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Request ownership transfer + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Sets a mock message sender + s_mockOptimismCrossDomainMessenger._setMockMessageSender(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + s_mockOptimismCrossDomainMessenger.sendMessage( + address(s_optimismCrossDomainGovernor), // target + abi.encodeWithSelector(s_optimismCrossDomainGovernor.acceptL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Asserts that the ownership was actually transferred + assertEq(s_optimismCrossDomainGovernor.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol new file mode 100644 index 0000000..eec9657 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; +import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; +import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract OptimismSequencerUptimeFeedTest is L2EPTest { + /// Constants + uint256 internal constant GAS_USED_DEVIATION = 100; + + /// L2EP contracts + MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; + MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; + OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + + /// Setup + function setUp() public { + // Deploys contracts + s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); + s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); + s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( + s_l1OwnerAddr, + address(s_mockOptimismL2CrossDomainMessenger), + false + ); + + // Sets mock sender in mock L2 messenger contract + s_mockOptimismL2CrossDomainMessenger.setSender(s_l1OwnerAddr); + } +} + +contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_optimismSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_optimismSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} + +contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeedTest { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender + function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Sets mock sender in mock L2 messenger contract + s_mockOptimismL2CrossDomainMessenger.setSender(s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_optimismSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_optimismSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getTimestamp(2); + } +} + +contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is OptimismSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); + + // Whitelist consumer + s_optimismSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol new file mode 100644 index 0000000..59395bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; + +import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; +import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; +import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; +import {OptimismValidator} from "../../../dev/optimism/OptimismValidator.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract OptimismValidatorTest is L2EPTest { + /// Helper constants + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; + uint32 internal constant INIT_GAS_LIMIT = 1900000; + + /// L2EP contracts + MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; + MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; + OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; + OptimismValidator internal s_optimismValidator; + + /// Events + event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); + + /// Setup + function setUp() public { + s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); + s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); + + s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( + address(s_mockOptimismL1CrossDomainMessenger), + address(s_mockOptimismL2CrossDomainMessenger), + true + ); + + s_optimismValidator = new OptimismValidator( + address(s_mockOptimismL1CrossDomainMessenger), + address(s_optimismSequencerUptimeFeed), + INIT_GAS_LIMIT + ); + } +} + +contract OptimismValidator_SetGasLimit is OptimismValidatorTest { + /// @notice it correctly updates the gas limit + function test_CorrectlyUpdatesTheGasLimit() public { + uint32 newGasLimit = 2000000; + assertEq(s_optimismValidator.getGasLimit(), INIT_GAS_LIMIT); + s_optimismValidator.setGasLimit(newGasLimit); + assertEq(s_optimismValidator.getGasLimit(), newGasLimit); + } +} + +contract OptimismValidator_Validate is OptimismValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("No access"); + s_optimismValidator.validate(0, 0, 1, 1); + } + + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + // Gives access to the s_eoaValidator + s_optimismValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 5000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + address(s_optimismValidator), // sender + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds), // message + 0, // nonce + INIT_GAS_LIMIT // gas limit + ); + + // Runs the function (which produces the event to test) + s_optimismValidator.validate(0, 0, 0, 0); + } + + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { + // Gives access to the s_eoaValidator + s_optimismValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 10000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + address(s_optimismValidator), // sender + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds), // message + 0, // nonce + INIT_GAS_LIMIT // gas limit + ); + + // Runs the function (which produces the event to test) + s_optimismValidator.validate(0, 0, 1, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol new file mode 100644 index 0000000..e34e84f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; +import {ScrollCrossDomainForwarder} from "../../../dev/scroll/ScrollCrossDomainForwarder.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ScrollCrossDomainForwarderTest is L2EPTest { + /// Contracts + MockScrollCrossDomainMessenger internal s_mockScrollCrossDomainMessenger; + ScrollCrossDomainForwarder internal s_scrollCrossDomainForwarder; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_mockScrollCrossDomainMessenger = new MockScrollCrossDomainMessenger(s_l1OwnerAddr); + s_scrollCrossDomainForwarder = new ScrollCrossDomainForwarder(s_mockScrollCrossDomainMessenger, s_l1OwnerAddr); + s_greeter = new Greeter(address(s_scrollCrossDomainForwarder)); + vm.stopPrank(); + } +} + +contract ScrollCrossDomainForwarder_Constructor is ScrollCrossDomainForwarderTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_scrollCrossDomainForwarder.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_scrollCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_scrollCrossDomainForwarder.crossDomainMessenger(), address(s_mockScrollCrossDomainMessenger)); + + // it should set the typeAndVersion correctly + assertEq(s_scrollCrossDomainForwarder.typeAndVersion(), "ScrollCrossDomainForwarder 1.0.0"); + } +} + +contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_scrollCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainForwarder.forward.selector, address(s_greeter), greeting), // message + 0 // gas limit + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainForwarder.forward.selector, address(s_greeter), ""), // message + 0 // gas limit + ); + } +} + +contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForwarderTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_scrollCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_scrollCrossDomainForwarder.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_scrollCrossDomainForwarder.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_scrollCrossDomainForwarder.l1Owner(), s_strangerAddr); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_scrollCrossDomainForwarder.l1Owner(), address(0)); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, address(0)), // message + 0 // gas limit + ); + } +} + +contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwarderTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainForwarder.acceptL1Ownership.selector), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Request ownership transfer + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Sets a mock message sender + s_mockScrollCrossDomainMessenger._setMockMessageSender(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainForwarder), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainForwarder.acceptL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Asserts that the ownership was actually transferred + assertEq(s_scrollCrossDomainForwarder.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol new file mode 100644 index 0000000..8c3d56d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; +import {ScrollCrossDomainGovernor} from "../../../dev/scroll/ScrollCrossDomainGovernor.sol"; +import {Greeter} from "../../../../tests/Greeter.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +import {MultiSend} from "../../../../vendor/MultiSend.sol"; + +contract ScrollCrossDomainGovernorTest is L2EPTest { + /// Contracts + MockScrollCrossDomainMessenger internal s_mockScrollCrossDomainMessenger; + ScrollCrossDomainGovernor internal s_scrollCrossDomainGovernor; + MultiSend internal s_multiSend; + Greeter internal s_greeter; + + /// Events + event L1OwnershipTransferRequested(address indexed from, address indexed to); + event L1OwnershipTransferred(address indexed from, address indexed to); + + /// Setup + function setUp() public { + // Deploys contracts + vm.startPrank(s_l1OwnerAddr); + s_mockScrollCrossDomainMessenger = new MockScrollCrossDomainMessenger(s_l1OwnerAddr); + s_scrollCrossDomainGovernor = new ScrollCrossDomainGovernor(s_mockScrollCrossDomainMessenger, s_l1OwnerAddr); + s_greeter = new Greeter(address(s_scrollCrossDomainGovernor)); + s_multiSend = new MultiSend(); + vm.stopPrank(); + } +} + +contract ScrollCrossDomainGovernor_Constructor is ScrollCrossDomainGovernorTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // it should set the owner correctly + assertEq(s_scrollCrossDomainGovernor.owner(), s_l1OwnerAddr); + + // it should set the l1Owner correctly + assertEq(s_scrollCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); + + // it should set the crossdomain messenger correctly + assertEq(s_scrollCrossDomainGovernor.crossDomainMessenger(), address(s_mockScrollCrossDomainMessenger)); + + // it should set the typeAndVersion correctly + assertEq(s_scrollCrossDomainGovernor.typeAndVersion(), "ScrollCrossDomainGovernor 1.0.0"); + } +} + +contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_scrollCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_Forward() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainGovernor.forward.selector, address(s_greeter), greeting), // message + 0 // gas limit + ); + + // Checks that the greeter got the message + assertEq(s_greeter.greeting(), greeting); + } + + /// @notice it should revert when contract call reverts + function test_ForwardRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message + vm.expectRevert("Invalid greeting length"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainGovernor.forward.selector, address(s_greeter), ""), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Defines the cross domain message to send + string memory greeting = "hello"; + + // Sends the message + s_scrollCrossDomainGovernor.forward( + address(s_greeter), + abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), greeting); + } +} + +contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorTest { + /// @notice it should not be callable by unknown address + function test_NotCallableByUnknownAddress() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger or owner"); + s_scrollCrossDomainGovernor.forwardDelegate(address(s_greeter), abi.encode("")); + } + + /// @notice it should be callable by crossdomain messenger address / L1 owner + function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + encodeCrossDomainMultiSendMsg( + s_scrollCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should be callable by L2 owner + function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_l1OwnerAddr); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + encodeCrossDomainMultiSendMsg( + s_scrollCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message was updated + assertEq(s_greeter.greeting(), "bar"); + } + + /// @notice it should revert batch when one call fails + function test_RevertsBatchWhenOneCallFails() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Governor delegatecall reverted"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + encodeCrossDomainMultiSendMsg( + s_scrollCrossDomainGovernor.forwardDelegate.selector, + address(s_multiSend), + abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) + ), // message + 0 // gas limit + ); + + // Checks that the greeter message is unchanged + assertEq(s_greeter.greeting(), ""); + } + + /// @notice it should bubble up revert when contract call reverts + function test_BubbleUpRevert() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends an invalid message (empty transaction data is not allowed) + vm.expectRevert("Greeter: revert triggered"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector( + ScrollCrossDomainGovernor.forwardDelegate.selector, + address(s_greeter), + abi.encodeWithSelector(Greeter.triggerRevert.selector) + ), // message + 0 // gas limit + ); + } +} + +contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGovernorTest { + /// @notice it should not be callable by non-owners + function test_NotCallableByNonOwners() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_scrollCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should not be callable by L2 owner + function test_NotCallableByL2Owner() public { + vm.startPrank(s_l1OwnerAddr); + assertEq(s_scrollCrossDomainGovernor.owner(), s_l1OwnerAddr); + vm.expectRevert("Sender is not the L2 messenger"); + s_scrollCrossDomainGovernor.transferL1Ownership(s_strangerAddr); + } + + /// @notice it should be callable by current L1 owner + function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_scrollCrossDomainGovernor.l1Owner(), s_strangerAddr); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by current L1 owner to zero address + function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Defines the cross domain message to send + vm.expectEmit(); + emit L1OwnershipTransferRequested(s_scrollCrossDomainGovernor.l1Owner(), address(0)); + + // Sends the message + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, address(0)), // message + 0 // gas limit + ); + } +} + +contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGovernorTest { + /// @notice it should not be callable by non pending-owners + function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Sends the message + vm.expectRevert("Must be proposed L1 owner"); + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainGovernor.acceptL1Ownership.selector), // message + 0 // gas limit + ); + } + + /// @notice it should be callable by pending L1 owner + function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin + vm.startPrank(s_strangerAddr); + + // Request ownership transfer + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Sets a mock message sender + s_mockScrollCrossDomainMessenger._setMockMessageSender(s_strangerAddr); + + // Prepares expected event payload + vm.expectEmit(); + emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); + + // Accepts ownership transfer request + s_mockScrollCrossDomainMessenger.sendMessage( + address(s_scrollCrossDomainGovernor), // target + 0, // value + abi.encodeWithSelector(s_scrollCrossDomainGovernor.acceptL1Ownership.selector, s_strangerAddr), // message + 0 // gas limit + ); + + // Asserts that the ownership was actually transferred + assertEq(s_scrollCrossDomainGovernor.l1Owner(), s_strangerAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol new file mode 100644 index 0000000..0968c69 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; +import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; +import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ScrollSequencerUptimeFeedTest is L2EPTest { + /// Constants + uint256 internal constant GAS_USED_DEVIATION = 100; + + /// L2EP contracts + MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; + MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; + ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + + /// Setup + function setUp() public { + // Deploys contracts + s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); + s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); + s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( + s_l1OwnerAddr, + address(s_mockScrollL2CrossDomainMessenger), + false + ); + + // Sets mock sender in mock L2 messenger contract + s_mockScrollL2CrossDomainMessenger.setSender(s_l1OwnerAddr); + } +} + +contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // L2 cross domain messenger address must not be the zero address + vm.expectRevert(ScrollSequencerUptimeFeed.ZeroAddress.selector); + new ScrollSequencerUptimeFeed(s_l1OwnerAddr, address(0), false); + + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_scrollSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_scrollSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} + +contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender + function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Sets mock sender in mock L2 messenger contract + s_mockScrollL2CrossDomainMessenger.setSender(s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_scrollSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_scrollSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getTimestamp(2); + } +} + +contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ScrollSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); + + // Whitelist consumer + s_scrollSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol new file mode 100644 index 0000000..3d5298d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; + +import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; +import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; +import {MockScrollL1MessageQueue} from "../../mocks/scroll/MockScrollL1MessageQueue.sol"; +import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; +import {ScrollValidator} from "../../../dev/scroll/ScrollValidator.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ScrollValidatorTest is L2EPTest { + /// Helper constants + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; + uint32 internal constant INIT_GAS_LIMIT = 1900000; + + /// L2EP contracts + MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; + MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; + MockScrollL1MessageQueue internal s_mockScrollL1MessageQueue; + ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; + ScrollValidator internal s_scrollValidator; + + /// https://github.com/scroll-tech/scroll/blob/03089eaeee1193ff44c532c7038611ae123e7ef3/contracts/src/libraries/IScrollMessenger.sol#L22 + event SentMessage( + address indexed sender, + address indexed target, + uint256 value, + uint256 messageNonce, + uint256 gasLimit, + bytes message + ); + + /// Setup + function setUp() public { + s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); + s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); + s_mockScrollL1MessageQueue = new MockScrollL1MessageQueue(); + + s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( + address(s_mockScrollL1CrossDomainMessenger), + address(s_mockScrollL2CrossDomainMessenger), + true + ); + + s_scrollValidator = new ScrollValidator( + address(s_mockScrollL1CrossDomainMessenger), + address(s_scrollSequencerUptimeFeed), + address(s_mockScrollL1MessageQueue), + INIT_GAS_LIMIT + ); + } +} + +contract ScrollValidator_SetGasLimit is ScrollValidatorTest { + /// @notice it correctly updates the gas limit + function test_CorrectlyUpdatesTheGasLimit() public { + uint32 newGasLimit = 2000000; + assertEq(s_scrollValidator.getGasLimit(), INIT_GAS_LIMIT); + s_scrollValidator.setGasLimit(newGasLimit); + assertEq(s_scrollValidator.getGasLimit(), newGasLimit); + } +} + +contract ScrollValidator_Validate is ScrollValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("No access"); + s_scrollValidator.validate(0, 0, 1, 1); + } + + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + // Gives access to the s_eoaValidator + s_scrollValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 5000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + address(s_scrollValidator), // sender + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + 0, // value + 0, // nonce + INIT_GAS_LIMIT, // gas limit + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds) // message + ); + + // Runs the function (which produces the event to test) + s_scrollValidator.validate(0, 0, 0, 0); + } + + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { + // Gives access to the s_eoaValidator + s_scrollValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 10000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + address(s_scrollValidator), // sender + L2_SEQ_STATUS_RECORDER_ADDRESS, // target + 0, // value + 0, // nonce + INIT_GAS_LIMIT, // gas limit + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // message + ); + + // Runs the function (which produces the event to test) + s_scrollValidator.validate(0, 0, 1, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol new file mode 100644 index 0000000..6d90b39 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {ZKSyncSequencerUptimeFeed} from "../../../dev/zksync/ZKSyncSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ZKSyncSequencerUptimeFeedTest is L2EPTest { + /// Helper Variables + address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); + + /// L2EP contracts + ZKSyncSequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); + + /// Setup + function setUp() public { + // Deploys contracts + s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed(s_l1OwnerAddr, false); + } +} + +contract ZKSyncSequencerUptimeFeed_Constructor is ZKSyncSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_zksyncSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} + +contract ZKSyncSequencerUptimeFeed_UpdateStatus is ZKSyncSequencerUptimeFeedTest { + /// @notice it should revert if called by an unauthorized account + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract ZKSyncSequencerUptimeFeed_AggregatorV3Interface is ZKSyncSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getTimestamp(2); + } +} + +contract ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ZKSyncSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Whitelist consumer + s_zksyncSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol new file mode 100644 index 0000000..0bea147 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; +import {ZKSyncValidator} from "../../../dev/zksync/ZKSyncValidator.sol"; +import {BaseValidator} from "../../../dev/shared/BaseValidator.sol"; +import {L2EPTest} from "../L2EPTest.t.sol"; + +contract ZKSyncValidatorTest is L2EPTest { + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = address(0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b); + address internal constant DUMMY_L1_XDOMAIN_MSNGR_ADDR = address(0xa04Fc18f012B1a5A8231c7Ee4b916Dd6dbd271b6); + address internal constant DUMMY_L2_UPTIME_FEED_ADDR = address(0xFe31891940A2e5f04B76eD8bD1038E44127d1512); + uint32 internal constant INIT_GAS_PER_PUBDATA_BYTE_LIMIT = 800; + uint32 internal constant INIT_GAS_LIMIT = 1900000; + uint32 internal constant MAIN_NET_CHAIN_ID = 300; + uint32 internal constant BAD_CHAIN_ID = 0; + + ISequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; + MockBridgehub internal s_mockZKSyncL1Bridge; + ZKSyncValidator internal s_zksyncValidator; + + /// Fake event that will get emitted when `requestL2TransactionDirect` is called + /// Definition is taken from MockZKSyncL1Bridge + event SentMessage(address indexed sender, bytes message); + + /// Setup + function setUp() public { + s_mockZKSyncL1Bridge = new MockBridgehub(); + + s_zksyncValidator = new ZKSyncValidator( + address(s_mockZKSyncL1Bridge), + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } +} + +contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { + /// @notice it correctly validates that the chain id is valid + function test_ConstructingRevertedWithInvalidChainId() public { + vm.expectRevert(ZKSyncValidator.InvalidChainID.selector); + new ZKSyncValidator( + DUMMY_L1_XDOMAIN_MSNGR_ADDR, + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + BAD_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } + + /// @notice it correctly validates that the L1 bridge address is not zero + function test_ConstructingRevertedWithZeroL1BridgeAddress() public { + vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); + new ZKSyncValidator( + address(0), + DUMMY_L2_UPTIME_FEED_ADDR, + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } + + /// @notice it correctly validates that the L2 Uptime feed address is not zero + function test_ConstructingRevertedWithZeroL2UpdateFeedAddress() public { + vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); + new ZKSyncValidator( + DUMMY_L1_XDOMAIN_MSNGR_ADDR, + address(0), + INIT_GAS_LIMIT, + MAIN_NET_CHAIN_ID, + INIT_GAS_PER_PUBDATA_BYTE_LIMIT + ); + } +} + +contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { + /// @notice it correctly updates the gas limit per pubdata byte + function test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() public { + assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), INIT_GAS_PER_PUBDATA_BYTE_LIMIT); + + uint32 newGasPerPubDataByteLimit = 2000000; + s_zksyncValidator.setL2GasPerPubdataByteLimit(newGasPerPubDataByteLimit); + assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), newGasPerPubDataByteLimit); + } +} + +contract ZKSyncValidator_GetChainId is ZKSyncValidatorTest { + /// @notice it correctly gets the chain id + function test_CorrectlyGetsTheChainId() public { + assertEq(s_zksyncValidator.getChainId(), MAIN_NET_CHAIN_ID); + } +} + +contract ZKSyncValidator_Validate is ZKSyncValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { + vm.startPrank(s_strangerAddr); + vm.expectRevert("No access"); + s_zksyncValidator.validate(0, 0, 1, 1); + } + + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { + // Gives access to the s_eoaValidator + s_zksyncValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 5000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + bytes memory message = abi.encodeWithSelector( + ISequencerUptimeFeed.updateStatus.selector, + false, + futureTimestampInSeconds + ); + + vm.expectEmit(false, false, false, true); + emit SentMessage(address(s_zksyncValidator), message); + + // Runs the function (which produces the event to test) + s_zksyncValidator.validate(0, 0, 0, 0); + } + + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { + // Gives access to the s_eoaValidator + s_zksyncValidator.addAccess(s_eoaValidator); + + // Sets block.timestamp to a later date + uint256 futureTimestampInSeconds = block.timestamp + 10000; + vm.startPrank(s_eoaValidator); + vm.warp(futureTimestampInSeconds); + + // Sets up the expected event data + vm.expectEmit(false, false, false, true); + emit SentMessage( + address(s_zksyncValidator), + abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) + ); + + // Runs the function (which produces the event to test) + s_zksyncValidator.validate(0, 0, 1, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol new file mode 100644 index 0000000..070930b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol @@ -0,0 +1,575 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBridgeAdapter} from "./interfaces/IBridge.sol"; +import {ILiquidityManager} from "./interfaces/ILiquidityManager.sol"; +import {ILiquidityContainer} from "./interfaces/ILiquidityContainer.sol"; +import {IWrappedNative} from "../ccip/interfaces/IWrappedNative.sol"; + +import {OCR3Base} from "./ocr/OCR3Base.sol"; + +import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice LiquidityManager for a single token over multiple chains. +/// @dev This contract is designed to be used with the LockReleaseTokenPool contract but +/// isn't constrained to it. It can be used with any contract that implements the ILiquidityContainer +/// interface. +/// @dev The OCR3 DON should only be able to transfer funds to other pre-approved contracts +/// on other chains. Under no circumstances should it be able to transfer funds to arbitrary +/// addresses. The owner is therefore in full control of the funds in this contract, not the DON. +/// This is a security feature. The worst that can happen is that the DON can lock up funds in +/// bridges, but it can't steal them. +/// @dev References to local mean logic on the same chain as this contract is deployed on. +/// References to remote mean logic on other chains. +contract LiquidityManager is ILiquidityManager, OCR3Base { + using SafeERC20 for IERC20; + + error ZeroAddress(); + error InvalidRemoteChain(uint64 chainSelector); + error ZeroChainSelector(); + error InsufficientLiquidity(uint256 requested, uint256 available, uint256 reserve); + error EmptyReport(); + error TransferFailed(); + error OnlyFinanceRole(); + + /// @notice Emitted when a finalization step is completed without funds being available. + /// @param ocrSeqNum The OCR sequence number of the report. + /// @param remoteChainSelector The chain selector of the remote chain funds are coming from. + /// @param bridgeSpecificData The bridge specific data that was used to finalize the transfer. + event FinalizationStepCompleted( + uint64 indexed ocrSeqNum, + uint64 indexed remoteChainSelector, + bytes bridgeSpecificData + ); + + /// @notice Emitted when the CLL finance role is set. + /// @param financeRole The address of the new finance role. + event FinanceRoleSet(address financeRole); + + /// @notice Emitted when liquidity is transferred to another chain, or received from another chain. + /// @param ocrSeqNum The OCR sequence number of the report. + /// @param fromChainSelector The chain selector of the chain the funds are coming from. + /// In the event fromChainSelector == i_localChainSelector, this is an outgoing transfer. + /// Otherwise, it is an incoming transfer. + /// @param toChainSelector The chain selector of the chain the funds are going to. + /// In the event toChainSelector == i_localChainSelector, this is an incoming transfer. + /// Otherwise, it is an outgoing transfer. + /// @param to The address the funds are going to. + /// If this is address(this), the funds are arriving in this contract. + /// @param amount The amount of tokens being transferred. + /// @param bridgeSpecificData The bridge specific data that was passed to the local bridge adapter + /// when transferring the funds. + /// @param bridgeReturnData The return data from the local bridge adapter when transferring the funds. + event LiquidityTransferred( + uint64 indexed ocrSeqNum, + uint64 indexed fromChainSelector, + uint64 indexed toChainSelector, + address to, + uint256 amount, + bytes bridgeSpecificData, + bytes bridgeReturnData + ); + + /// @notice Emitted when liquidity is added to the local liquidity container. + /// @param provider The address of the provider that added the liquidity. + /// @param amount The amount of liquidity that was added. + event LiquidityAddedToContainer(address indexed provider, uint256 indexed amount); + + /// @notice Emitted when liquidity is removed from the local liquidity container. + /// @param remover The address of the remover that removed the liquidity. + /// @param amount The amount of liquidity that was removed. + event LiquidityRemovedFromContainer(address indexed remover, uint256 indexed amount); + + /// @notice Emitted when the local liquidity container is set. + /// @param newLiquidityContainer The address of the new liquidity container. + event LiquidityContainerSet(address indexed newLiquidityContainer); + + /// @notice Emitted when the minimum liquidity is set. + /// @param oldBalance The old minimum liquidity. + /// @param newBalance The new minimum liquidity. + event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); + + /// @notice Emitted when someone sends native to this contract + /// @param amount The amount of native deposited + /// @param depositor The address that deposited the native + event NativeDeposited(uint256 amount, address depositor); + + /// @notice Emitted when native balance is withdrawn by contract owner + /// @param amount The amount of native withdrawn + /// @param destination The address the native is sent to + event NativeWithdrawn(uint256 amount, address destination); + + /// @notice Emitted when a cross chain rebalancer is set. + /// @param remoteChainSelector The chain selector of the remote chain. + /// @param localBridge The local bridge adapter that will be used to transfer funds. + /// @param remoteToken The address of the token on the remote chain. + /// @param remoteRebalancer The address of the remote rebalancer contract. + /// @param enabled Whether the rebalancer is enabled. + event CrossChainRebalancerSet( + uint64 indexed remoteChainSelector, + IBridgeAdapter localBridge, + address remoteToken, + address remoteRebalancer, + bool enabled + ); + + /// @notice Emitted when a finalization step fails. + /// @param ocrSeqNum The OCR sequence number of the report. + /// @param remoteChainSelector The chain selector of the remote chain funds are coming from. + /// @param bridgeSpecificData The bridge specific data that was used to finalize the transfer. + /// @param reason The reason the finalization failed. + event FinalizationFailed( + uint64 indexed ocrSeqNum, + uint64 indexed remoteChainSelector, + bytes bridgeSpecificData, + bytes reason + ); + + struct CrossChainRebalancer { + address remoteRebalancer; + IBridgeAdapter localBridge; + address remoteToken; + bool enabled; + } + + string public constant override typeAndVersion = "LiquidityManager 1.0.0-dev"; + + /// @notice The token that this pool manages liquidity for. + IERC20 public immutable i_localToken; + + /// @notice The chain selector belonging to the chain this pool is deployed on. + uint64 internal immutable i_localChainSelector; + + /// @notice The target balance defines the expected amount of tokens for this network. + /// Setting the balance to 0 will disable any automated rebalancing operations. + uint256 internal s_minimumLiquidity; + + /// @notice Mapping of chain selector to liquidity container on other chains + mapping(uint64 chainSelector => CrossChainRebalancer) private s_crossChainRebalancer; + + uint64[] private s_supportedDestChains; + + /// @notice The liquidity container on the local chain + /// @dev In the case of CCIP, this would be the token pool. + ILiquidityContainer private s_localLiquidityContainer; + + /// @notice The CLL finance team multisig + address private s_finance; + + constructor( + IERC20 token, + uint64 localChainSelector, + ILiquidityContainer localLiquidityContainer, + uint256 minimumLiquidity, + address finance + ) OCR3Base() { + if (localChainSelector == 0) { + revert ZeroChainSelector(); + } + + if (address(token) == address(0) || address(localLiquidityContainer) == address(0)) { + revert ZeroAddress(); + } + i_localToken = token; + i_localChainSelector = localChainSelector; + s_localLiquidityContainer = localLiquidityContainer; + s_minimumLiquidity = minimumLiquidity; + s_finance = finance; + } + + // ================================================================ + // │ Native Management │ + // ================================================================ + + receive() external payable { + emit NativeDeposited(msg.value, msg.sender); + } + + /// @notice withdraw native balance + function withdrawNative(uint256 amount, address payable destination) external onlyFinance { + (bool success, ) = destination.call{value: amount}(""); + if (!success) revert TransferFailed(); + + emit NativeWithdrawn(amount, destination); + } + + // ================================================================ + // │ Liquidity Management │ + // ================================================================ + + /// @inheritdoc ILiquidityManager + function getLiquidity() public view returns (uint256 currentLiquidity) { + return i_localToken.balanceOf(address(s_localLiquidityContainer)); + } + + /// @notice Adds liquidity to the multi-chain system. + /// @dev Anyone can call this function, but anyone other than the owner should regard + /// adding liquidity as a donation to the system, as there is no way to get it out. + /// This function is open to anyone to be able to quickly add funds to the system + /// without having to go through potentially complicated multisig schemes to do it from + /// the owner address. + function addLiquidity(uint256 amount) external { + i_localToken.safeTransferFrom(msg.sender, address(this), amount); + + // Make sure this is tether compatible, as they have strange approval requirements + // Should be good since all approvals are always immediately used. + i_localToken.safeApprove(address(s_localLiquidityContainer), amount); + s_localLiquidityContainer.provideLiquidity(amount); + + emit LiquidityAddedToContainer(msg.sender, amount); + } + + /// @notice Removes liquidity from the system and sends it to the caller, so the owner. + /// @dev Only the owner can call this function. + function removeLiquidity(uint256 amount) external onlyFinance { + uint256 currentBalance = getLiquidity(); + if (currentBalance < amount) { + revert InsufficientLiquidity(amount, currentBalance, 0); + } + + s_localLiquidityContainer.withdrawLiquidity(amount); + i_localToken.safeTransfer(msg.sender, amount); + + emit LiquidityRemovedFromContainer(msg.sender, amount); + } + + /// @notice escape hatch to manually withdraw any ERC20 token from the LM contract + /// @param token The address of the token to withdraw + /// @param amount The amount of tokens to withdraw + /// @param destination The address to send the tokens to + function withdrawERC20(address token, uint256 amount, address destination) external onlyFinance { + IERC20(token).safeTransfer(destination, amount); + } + + /// @notice Transfers liquidity to another chain. + /// @dev This function is a public version of the internal _rebalanceLiquidity function. + /// to allow the owner to also initiate a rebalancing when needed. + function rebalanceLiquidity( + uint64 chainSelector, + uint256 amount, + uint256 nativeBridgeFee, + bytes calldata bridgeSpecificPayload + ) external onlyFinance { + _rebalanceLiquidity(chainSelector, amount, nativeBridgeFee, type(uint64).max, bridgeSpecificPayload); + } + + /// @notice Finalizes liquidity from another chain. + /// @dev This function is a public version of the internal _receiveLiquidity function. + /// to allow the owner to also initiate a finalization when needed. + function receiveLiquidity( + uint64 remoteChainSelector, + uint256 amount, + bool shouldWrapNative, + bytes calldata bridgeSpecificPayload + ) external onlyFinance { + _receiveLiquidity(remoteChainSelector, amount, bridgeSpecificPayload, shouldWrapNative, type(uint64).max); + } + + /// @notice Transfers liquidity to another chain. + /// @dev Called by both the owner and the DON. + /// @param chainSelector The chain selector of the chain to transfer liquidity to. + /// @param tokenAmount The amount of tokens to transfer. + /// @param nativeBridgeFee The fee to pay to the bridge. + /// @param ocrSeqNum The OCR sequence number of the report. + /// @param bridgeSpecificPayload The bridge specific data to pass to the bridge adapter. + function _rebalanceLiquidity( + uint64 chainSelector, + uint256 tokenAmount, + uint256 nativeBridgeFee, + uint64 ocrSeqNum, + bytes memory bridgeSpecificPayload + ) internal { + uint256 currentBalance = getLiquidity(); + uint256 minBalance = s_minimumLiquidity; + if (currentBalance < minBalance || currentBalance - minBalance < tokenAmount) { + revert InsufficientLiquidity(tokenAmount, currentBalance, minBalance); + } + + CrossChainRebalancer memory remoteLiqManager = s_crossChainRebalancer[chainSelector]; + + if (!remoteLiqManager.enabled) { + revert InvalidRemoteChain(chainSelector); + } + + // XXX: Could be optimized by withdrawing once and then sending to all destinations + s_localLiquidityContainer.withdrawLiquidity(tokenAmount); + i_localToken.safeApprove(address(remoteLiqManager.localBridge), tokenAmount); + + bytes memory bridgeReturnData = remoteLiqManager.localBridge.sendERC20{value: nativeBridgeFee}( + address(i_localToken), + remoteLiqManager.remoteToken, + remoteLiqManager.remoteRebalancer, + tokenAmount, + bridgeSpecificPayload + ); + + emit LiquidityTransferred( + ocrSeqNum, + i_localChainSelector, + chainSelector, + remoteLiqManager.remoteRebalancer, + tokenAmount, + bridgeSpecificPayload, + bridgeReturnData + ); + } + + /// @notice Receives liquidity from another chain. + /// @dev Called by both the owner and the DON. + /// @param remoteChainSelector The chain selector of the chain to receive liquidity from. + /// @param amount The amount of tokens to receive. + /// @param bridgeSpecificPayload The bridge specific data to pass to the bridge adapter finalizeWithdrawERC20 call. + /// @param shouldWrapNative Whether the token should be wrapped before injecting it into the liquidity container. + /// This only applies to native tokens wrapper contracts, e.g WETH. + /// @param ocrSeqNum The OCR sequence number of the report. + function _receiveLiquidity( + uint64 remoteChainSelector, + uint256 amount, + bytes memory bridgeSpecificPayload, + bool shouldWrapNative, + uint64 ocrSeqNum + ) internal { + // check if the remote chain is supported + CrossChainRebalancer memory remoteRebalancer = s_crossChainRebalancer[remoteChainSelector]; + if (!remoteRebalancer.enabled) { + revert InvalidRemoteChain(remoteChainSelector); + } + + // finalize the withdrawal through the bridge adapter + try + remoteRebalancer.localBridge.finalizeWithdrawERC20( + remoteRebalancer.remoteRebalancer, // remoteSender: the remote rebalancer + address(this), // localReceiver: this contract + bridgeSpecificPayload + ) + returns (bool fundsAvailable) { + if (fundsAvailable) { + // finalization was successful and we can inject the liquidity into the container. + // approve and liquidity container should transferFrom. + _injectLiquidity(amount, ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, shouldWrapNative); + } else { + // a finalization step was completed, but funds are not available. + // hence, we cannot inject any liquidity yet. + emit FinalizationStepCompleted(ocrSeqNum, remoteChainSelector, bridgeSpecificPayload); + } + + // return here on the happy path. + // sad path is when finalizeWithdrawERC20 reverts, which is handled after the catch block. + return; + } catch (bytes memory lowLevelData) { + // failed to finalize the withdrawal. + // this could mean that the withdrawal was already finalized + // or that the withdrawal failed. + // we assume the former and continue + emit FinalizationFailed(ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, lowLevelData); + } + + // if we reach this point, the finalization failed. + // since we don't have enough information to know why it failed, + // we assume that it failed because the withdrawal was already finalized, + // and that the funds are available. + _injectLiquidity(amount, ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, shouldWrapNative); + } + + /// @notice Injects liquidity into the local liquidity container. + /// @param amount The amount of tokens to inject. + /// @param ocrSeqNum The OCR sequence number of the report. + /// @param remoteChainSelector The chain selector of the remote chain. + /// @param bridgeSpecificPayload The bridge specific data passed to the bridge adapter finalizeWithdrawERC20 call. + /// @param shouldWrapNative Whether the token should be wrapped before injecting it into the liquidity container. + function _injectLiquidity( + uint256 amount, + uint64 ocrSeqNum, + uint64 remoteChainSelector, + bytes memory bridgeSpecificPayload, + bool shouldWrapNative + ) private { + // We trust the DON or the owner (the only two actors who can end up calling this function) + // to correctly set the shouldWrapNative flag. + // Some bridges only bridge native and not wrapped native. + // In such a case we need to re-wrap the native in order to inject it into the liquidity container. + // TODO: escape hatch in case of bug? + if (shouldWrapNative) { + IWrappedNative(address(i_localToken)).deposit{value: amount}(); + } + + i_localToken.safeIncreaseAllowance(address(s_localLiquidityContainer), amount); + s_localLiquidityContainer.provideLiquidity(amount); + + emit LiquidityTransferred( + ocrSeqNum, + remoteChainSelector, + i_localChainSelector, + address(this), + amount, + bridgeSpecificPayload, + bytes("") // no bridge return data when receiving + ); + } + + /// @notice Process the OCR report. + /// @dev Called by OCR3Base's transmit() function. + function _report(bytes calldata report, uint64 ocrSeqNum) internal override { + ILiquidityManager.LiquidityInstructions memory instructions = abi.decode( + report, + (ILiquidityManager.LiquidityInstructions) + ); + + uint256 sendInstructions = instructions.sendLiquidityParams.length; + uint256 receiveInstructions = instructions.receiveLiquidityParams.length; + + // There should always be instructions to send or receive, if not, the report is invalid + // and we revert to save the gas of the signature validation of OCR. + if (sendInstructions == 0 && receiveInstructions == 0) { + revert EmptyReport(); + } + + for (uint256 i = 0; i < sendInstructions; ++i) { + _rebalanceLiquidity( + instructions.sendLiquidityParams[i].remoteChainSelector, + instructions.sendLiquidityParams[i].amount, + instructions.sendLiquidityParams[i].nativeBridgeFee, + ocrSeqNum, + instructions.sendLiquidityParams[i].bridgeData + ); + } + + for (uint256 i = 0; i < receiveInstructions; ++i) { + _receiveLiquidity( + instructions.receiveLiquidityParams[i].remoteChainSelector, + instructions.receiveLiquidityParams[i].amount, + instructions.receiveLiquidityParams[i].bridgeData, + instructions.receiveLiquidityParams[i].shouldWrapNative, + ocrSeqNum + ); + } + } + + // ================================================================ + // │ Config │ + // ================================================================ + + function getSupportedDestChains() external view returns (uint64[] memory) { + return s_supportedDestChains; + } + + /// @notice Gets the cross chain liquidity manager + function getCrossChainRebalancer(uint64 chainSelector) external view returns (CrossChainRebalancer memory) { + return s_crossChainRebalancer[chainSelector]; + } + + /// @notice Gets all cross chain liquidity managers + /// @dev We don't care too much about gas since this function is intended for offchain usage. + function getAllCrossChainRebalancers() external view returns (CrossChainRebalancerArgs[] memory) { + uint256 numChains = s_supportedDestChains.length; + CrossChainRebalancerArgs[] memory managers = new CrossChainRebalancerArgs[](numChains); + for (uint256 i = 0; i < numChains; ++i) { + uint64 chainSelector = s_supportedDestChains[i]; + CrossChainRebalancer memory currentManager = s_crossChainRebalancer[chainSelector]; + managers[i] = CrossChainRebalancerArgs({ + remoteRebalancer: currentManager.remoteRebalancer, + localBridge: currentManager.localBridge, + remoteToken: currentManager.remoteToken, + remoteChainSelector: chainSelector, + enabled: currentManager.enabled + }); + } + + return managers; + } + + /// @notice Sets a list of cross chain liquidity managers. + /// @dev Will update the list of supported dest chains if the chain is new. + function setCrossChainRebalancers(CrossChainRebalancerArgs[] calldata crossChainRebalancers) external onlyOwner { + for (uint256 i = 0; i < crossChainRebalancers.length; ++i) { + _setCrossChainRebalancer(crossChainRebalancers[i]); + } + } + + function setCrossChainRebalancer(CrossChainRebalancerArgs calldata crossChainLiqManager) external onlyOwner { + _setCrossChainRebalancer(crossChainLiqManager); + } + + /// @notice Sets a single cross chain liquidity manager. + /// @dev Will update the list of supported dest chains if the chain is new. + function _setCrossChainRebalancer(CrossChainRebalancerArgs calldata crossChainLiqManager) internal { + if (crossChainLiqManager.remoteChainSelector == 0) { + revert ZeroChainSelector(); + } + + if ( + crossChainLiqManager.remoteRebalancer == address(0) || + address(crossChainLiqManager.localBridge) == address(0) || + crossChainLiqManager.remoteToken == address(0) + ) { + revert ZeroAddress(); + } + + // If the destination chain is new, add it to the list of supported chains + if (s_crossChainRebalancer[crossChainLiqManager.remoteChainSelector].remoteToken == address(0)) { + s_supportedDestChains.push(crossChainLiqManager.remoteChainSelector); + } + + s_crossChainRebalancer[crossChainLiqManager.remoteChainSelector] = CrossChainRebalancer({ + remoteRebalancer: crossChainLiqManager.remoteRebalancer, + localBridge: crossChainLiqManager.localBridge, + remoteToken: crossChainLiqManager.remoteToken, + enabled: crossChainLiqManager.enabled + }); + + emit CrossChainRebalancerSet( + crossChainLiqManager.remoteChainSelector, + crossChainLiqManager.localBridge, + crossChainLiqManager.remoteToken, + crossChainLiqManager.remoteRebalancer, + crossChainLiqManager.enabled + ); + } + + /// @notice Gets the local liquidity container. + function getLocalLiquidityContainer() external view returns (address) { + return address(s_localLiquidityContainer); + } + + /// @notice Sets the local liquidity container. + /// @dev Only the owner can call this function. + function setLocalLiquidityContainer(ILiquidityContainer localLiquidityContainer) external onlyOwner { + if (address(localLiquidityContainer) == address(0)) { + revert ZeroAddress(); + } + s_localLiquidityContainer = localLiquidityContainer; + + emit LiquidityContainerSet(address(localLiquidityContainer)); + } + + /// @notice Gets the target tokens balance. + function getMinimumLiquidity() external view returns (uint256) { + return s_minimumLiquidity; + } + + /// @notice Sets the target tokens balance. + /// @dev Only the owner can call this function. + function setMinimumLiquidity(uint256 minimumLiquidity) external onlyOwner { + uint256 oldLiquidity = s_minimumLiquidity; + s_minimumLiquidity = minimumLiquidity; + emit MinimumLiquiditySet(oldLiquidity, s_minimumLiquidity); + } + + /// @notice Gets the CLL finance team multisig address + function getFinanceRole() external view returns (address) { + return s_finance; + } + + /// @notice Sets the finance team multisig address + /// @dev Only the owner can call this function. + function setFinanceRole(address finance) external onlyOwner { + s_finance = finance; + emit FinanceRoleSet(finance); + } + + modifier onlyFinance() { + if (msg.sender != s_finance) revert OnlyFinanceRole(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol new file mode 100644 index 0000000..9ab7376 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBridgeAdapter} from "../interfaces/IBridge.sol"; + +import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; +import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +interface IOutbox { + /** + * @notice Executes a messages in an Outbox entry. + * @dev Reverts if dispute period hasn't expired, since the outbox entry + * is only created once the rollup confirms the respective assertion. + * @dev it is not possible to execute any L2-to-L1 transaction which contains data + * to a contract address without any code (as enforced by the Bridge contract). + * @param proof Merkle proof of message inclusion in send root + * @param index Merkle path to message + * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) + * @param to destination address for L1 contract call + * @param l2Block l2 block number at which sendTxToL1 call was made + * @param l1Block l1 block number at which sendTxToL1 call was made + * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made + * @param value wei in L1 message + * @param data abi-encoded L1 message data + */ + function executeTransaction( + bytes32[] calldata proof, + uint256 index, + address l2Sender, + address to, + uint256 l2Block, + uint256 l1Block, + uint256 l2Timestamp, + uint256 value, + bytes calldata data + ) external; +} + +/// @notice Arbitrum L1 Bridge adapter +/// @dev Auto unwraps and re-wraps wrapped eth in the bridge. +contract ArbitrumL1BridgeAdapter is IBridgeAdapter { + using SafeERC20 for IERC20; + + IL1GatewayRouter internal immutable i_l1GatewayRouter; + IOutbox internal immutable i_l1Outbox; + + error NoGatewayForToken(address token); + error Unimplemented(); + + constructor(IL1GatewayRouter l1GatewayRouter, IOutbox l1Outbox) { + if (address(l1GatewayRouter) == address(0) || address(l1Outbox) == address(0)) { + revert BridgeAddressCannotBeZero(); + } + i_l1GatewayRouter = l1GatewayRouter; + i_l1Outbox = l1Outbox; + } + + /// @dev these are parameters provided by the caller of the sendERC20 function + /// and must be determined offchain. + struct SendERC20Params { + uint256 gasLimit; + uint256 maxSubmissionCost; + uint256 maxFeePerGas; + } + + /// @inheritdoc IBridgeAdapter + function sendERC20( + address localToken, + address /* remoteToken */, + address recipient, + uint256 amount, + bytes calldata bridgeSpecificPayload + ) external payable override returns (bytes memory) { + // receive the token transfer from the msg.sender + IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); + + // Note: the gateway router could return 0x0 for the gateway address + // if that token is not yet registered + address gateway = IGatewayRouter(address(i_l1GatewayRouter)).getGateway(localToken); + if (gateway == address(0)) { + revert NoGatewayForToken(localToken); + } + + // approve the gateway to transfer the token amount sent to the adapter + IERC20(localToken).safeApprove(gateway, amount); + + SendERC20Params memory params = abi.decode(bridgeSpecificPayload, (SendERC20Params)); + + uint256 expectedMsgValue = (params.gasLimit * params.maxFeePerGas) + params.maxSubmissionCost; + if (msg.value < expectedMsgValue) { + revert MsgValueDoesNotMatchAmount(msg.value, expectedMsgValue); + } + + // The router will route the call to the gateway that we approved + // above. The gateway will then transfer the tokens to the L2. + // outboundTransferCustomRefund will return the abi encoded inbox sequence number + // which is 256 bits, so we can cap the return data to 256 bits. + bytes memory inboxSequenceNumber = i_l1GatewayRouter.outboundTransferCustomRefund{value: msg.value}( + localToken, + recipient, + recipient, + amount, + params.gasLimit, + params.maxFeePerGas, + abi.encode(params.maxSubmissionCost, bytes("")) + ); + + return inboxSequenceNumber; + } + + /// @dev This function is so that we can easily abi-encode the arbitrum-specific payload for the sendERC20 function. + function exposeSendERC20Params(SendERC20Params memory params) public pure {} + + /// @dev fees have to be determined offchain for arbitrum, therefore revert here to discourage usage. + function getBridgeFeeInNative() public pure override returns (uint256) { + revert Unimplemented(); + } + + /// @param proof Merkle proof of message inclusion in send root + /// @param index Merkle path to message + /// @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) + /// @param to destination address for L1 contract call + /// @param l2Block l2 block number at which sendTxToL1 call was made + /// @param l1Block l1 block number at which sendTxToL1 call was made + /// @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made + /// @param value wei in L1 message + /// @param data abi-encoded L1 message data + struct ArbitrumFinalizationPayload { + bytes32[] proof; + uint256 index; + address l2Sender; + address to; + uint256 l2Block; + uint256 l1Block; + uint256 l2Timestamp; + uint256 value; + bytes data; + } + + /// @dev This function is so that we can easily abi-encode the arbitrum-specific payload for the finalizeWithdrawERC20 function. + function exposeArbitrumFinalizationPayload(ArbitrumFinalizationPayload memory payload) public pure {} + + /// @notice Finalize an L2 -> L1 transfer. + /// Arbitrum finalizations are single-step, so we always return true. + /// Calls to this function will revert in two cases, 1) if the finalization payload is wrong, + /// i.e incorrect merkle proof, or index and 2) if the withdrawal was already finalized. + /// @return true iff the finalization does not revert. + function finalizeWithdrawERC20( + address /* remoteSender */, + address /* localReceiver */, + bytes calldata arbitrumFinalizationPayload + ) external override returns (bool) { + ArbitrumFinalizationPayload memory payload = abi.decode(arbitrumFinalizationPayload, (ArbitrumFinalizationPayload)); + i_l1Outbox.executeTransaction( + payload.proof, + payload.index, + payload.l2Sender, + payload.to, + payload.l2Block, + payload.l1Block, + payload.l2Timestamp, + payload.value, + payload.data + ); + return true; + } + + /// @notice Convenience function to get the L2 token address from the L1 token address. + /// @return The L2 token address for the given L1 token address. + function getL2Token(address l1Token) external view returns (address) { + return i_l1GatewayRouter.calculateL2TokenAddress(l1Token); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol new file mode 100644 index 0000000..6ee9716 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBridgeAdapter} from "../interfaces/IBridge.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +interface IArbSys { + function withdrawEth(address destination) external payable returns (uint256); +} + +interface IL2GatewayRouter { + function outboundTransfer( + address l1Token, + address to, + uint256 amount, + bytes calldata data + ) external payable returns (bytes memory); +} + +/// @notice Arbitrum L2 Bridge adapter +/// @dev Auto unwraps and re-wraps wrapped eth in the bridge. +contract ArbitrumL2BridgeAdapter is IBridgeAdapter { + using SafeERC20 for IERC20; + + IL2GatewayRouter internal immutable i_l2GatewayRouter; + // address internal immutable i_l1ERC20Gateway; + IArbSys internal constant ARB_SYS = IArbSys(address(0x64)); + + constructor(IL2GatewayRouter l2GatewayRouter) { + if (address(l2GatewayRouter) == address(0)) { + revert BridgeAddressCannotBeZero(); + } + i_l2GatewayRouter = l2GatewayRouter; + } + + /// @inheritdoc IBridgeAdapter + function sendERC20( + address localToken, + address remoteToken, + address recipient, + uint256 amount, + bytes calldata /* bridgeSpecificPayload */ + ) external payable override returns (bytes memory) { + if (msg.value != 0) { + revert MsgShouldNotContainValue(msg.value); + } + + IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); + + // the data returned is the unique id of the L2 to L1 transfer + // see https://github.com/OffchainLabs/token-bridge-contracts/blob/bf9ad3d7f25c0eaf0a5f89eec7a0a370833cea16/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol#L169-L191 + // No approval needed, the bridge will burn the tokens from this contract. + bytes memory l2ToL1TxId = i_l2GatewayRouter.outboundTransfer(remoteToken, recipient, amount, bytes("")); + + return l2ToL1TxId; + } + + /// @notice No-op since L1 -> L2 transfers do not need finalization. + /// @return true always. + function finalizeWithdrawERC20( + address /* remoteSender */, + address /* localReceiver */, + bytes calldata /* bridgeSpecificPayload */ + ) external pure override returns (bool) { + return true; + } + + /// @notice There are no fees to bridge back to L1 + function getBridgeFeeInNative() external pure returns (uint256) { + return 0; + } + + function depositNativeToL1(address recipient) external payable { + ARB_SYS.withdrawEth{value: msg.value}(recipient); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol new file mode 100644 index 0000000..6734c74 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBridgeAdapter} from "../interfaces/IBridge.sol"; +import {IWrappedNative} from "../../ccip/interfaces/IWrappedNative.sol"; +import {Types} from "../interfaces/optimism/Types.sol"; +import {IOptimismPortal} from "../interfaces/optimism/IOptimismPortal.sol"; + +import {IL1StandardBridge} from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice OptimismL1BridgeAdapter implements IBridgeAdapter for the Optimism L1<=>L2 bridge. +/// @dev L1 -> L2 deposits are done via the depositERC20To and depositETHTo functions on the L1StandardBridge. +/// The amount of gas provided for the transaction must be buffered - the Optimism SDK recommends a 20% buffer. +/// The Optimism Bridge implements 2-step withdrawals from L2 to L1. Once a withdrawal transaction is included +/// in the L2 chain, it must be proven on L1 before it can be finalized. There is a buffer between the transaction +/// being posted on L2 before it can be proven, and similarly, there is a buffer in the time it takes to prove +/// the transaction before it can be finalized. +/// See https://blog.oplabs.co/two-step-withdrawals/ for more details on this mechanism. +/// @dev We have to unwrap WETH into ether before depositing it to L2. Therefore this bridge adapter bridges +/// WETH to ether. The receiver on L2 must wrap the ether back into WETH. +contract OptimismL1BridgeAdapter is IBridgeAdapter { + using SafeERC20 for IERC20; + + /// @notice used when the action in the payload is invalid. + error InvalidFinalizationAction(); + + /// @notice Payload for proving a withdrawal from L2 on L1 via finalizeWithdrawERC20. + /// @param withdrawalTransaction The withdrawal transaction, see its docstring for more details. + /// @param l2OutputIndex The index of the output in the L2 block, or the dispute game index post fault proof upgrade. + /// @param outputRootProof The inclusion proof of the L2ToL1MessagePasser contract's storage root. + /// @param withdrawalProof The Merkle proof of the withdrawal key presence in the L2ToL1MessagePasser contract's state trie. + struct OptimismProveWithdrawalPayload { + Types.WithdrawalTransaction withdrawalTransaction; + uint256 l2OutputIndex; + Types.OutputRootProof outputRootProof; + bytes[] withdrawalProof; + } + + /// @notice Payload for finalizing a withdrawal from L2 on L1. + /// Note that the withdrawal must be proven first before it can be finalized. + /// @param withdrawalTransaction The withdrawal transaction, see its docstring for more details. + struct OptimismFinalizationPayload { + Types.WithdrawalTransaction withdrawalTransaction; + } + + /// @notice The action to take when finalizing a withdrawal. + /// Optimism implements two-step withdrawals, so we need to specify the action to take + /// each time the finalizeWithdrawERC20 function is called. + enum FinalizationAction { + ProveWithdrawal, + FinalizeWithdrawal + } + + /// @notice Payload for interacting with the finalizeWithdrawERC20 function. + /// Since Optimism has 2-step withdrawals, we cannot finalize and get the funds on L1 in the same transaction. + /// @param action The action to take; either ProveWithdrawal or FinalizeWithdrawal. + /// @param data The payload for the action. If ProveWithdrawal, it must be an abi-encoded OptimismProveWithdrawalPayload. + /// If FinalizeWithdrawal, it must be an abi-encoded OptimismFinalizationPayload. + struct FinalizeWithdrawERC20Payload { + FinalizationAction action; + bytes data; + } + + /// @dev Reference to the L1StandardBridge contract. Deposits to L2 go through this contract. + IL1StandardBridge internal immutable i_L1Bridge; + + /// @dev Reference to the WrappedNative contract. Optimism bridges ether directly rather than WETH, + /// so we need to unwrap WETH into ether before depositing it to L2. + IWrappedNative internal immutable i_wrappedNative; + + /// @dev Reference to the OptimismPortal contract, which is used to prove and finalize withdrawals. + IOptimismPortal internal immutable i_optimismPortal; + + /// @dev Nonce to use for L2 deposits to allow for better tracking offchain. + uint64 private s_nonce = 0; + + constructor(IL1StandardBridge l1Bridge, IWrappedNative wrappedNative, IOptimismPortal optimismPortal) { + if ( + address(l1Bridge) == address(0) || address(wrappedNative) == address(0) || address(optimismPortal) == address(0) + ) { + revert BridgeAddressCannotBeZero(); + } + i_L1Bridge = l1Bridge; + i_wrappedNative = wrappedNative; + i_optimismPortal = optimismPortal; + } + + /// @notice The WETH withdraw requires this be present otherwise withdraws will fail. + receive() external payable {} + + /// @inheritdoc IBridgeAdapter + function sendERC20( + address localToken, + address remoteToken, + address recipient, + uint256 amount, + bytes calldata /* bridgeSpecificPayload */ + ) external payable override returns (bytes memory) { + IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); + + if (msg.value != 0) { + revert MsgShouldNotContainValue(msg.value); + } + + // Extra data for the L2 deposit. + // We encode the nonce in the extra data so that we can track the L2 deposit offchain. + bytes memory extraData = abi.encode(s_nonce++); + + // If the token is the wrapped native, we unwrap it and deposit native + if (localToken == address(i_wrappedNative)) { + i_wrappedNative.withdraw(amount); + i_L1Bridge.depositETHTo{value: amount}(recipient, 0, extraData); + return extraData; + } + + // Token is a normal ERC20. + IERC20(localToken).safeApprove(address(i_L1Bridge), amount); + i_L1Bridge.depositERC20To(localToken, remoteToken, recipient, amount, 0, extraData); + + return extraData; + } + + /// @notice Bridging to Optimism is paid for with gas + /// @dev Since the gas amount charged is dynamic, the gas burn can change from block to block. + /// You should always add a buffer of at least 20% to the gas limit for your L1 to L2 transaction + /// to avoid running out of gas. + function getBridgeFeeInNative() public pure returns (uint256) { + return 0; + } + + /// @notice Prove or finalize an ERC20 withdrawal from L2. + /// The action to take is specified in the payload. See the docstring of FinalizeWithdrawERC20Payload for more details. + /// @param data The payload for the action. This is an abi.encode'd FinalizeWithdrawERC20Payload with the appropriate data. + /// @return true iff finalization is successful, and false for proving a withdrawal. If either of these fail, + /// the call to this function will revert. + function finalizeWithdrawERC20( + address /* remoteSender */, + address /* localReceiver */, + bytes calldata data + ) external override returns (bool) { + // decode the data into FinalizeWithdrawERC20Payload first and extract the action. + FinalizeWithdrawERC20Payload memory payload = abi.decode(data, (FinalizeWithdrawERC20Payload)); + if (payload.action == FinalizationAction.ProveWithdrawal) { + // The action being ProveWithdrawal indicates that this is a withdrawal proof payload. + // Decode the data into OptimismProveWithdrawalPayload and call the proveWithdrawal function. + OptimismProveWithdrawalPayload memory provePayload = abi.decode(payload.data, (OptimismProveWithdrawalPayload)); + _proveWithdrawal(provePayload); + return false; + } else if (payload.action == FinalizationAction.FinalizeWithdrawal) { + // decode the data into OptimismFinalizationPayload and call the finalizeWithdrawal function. + OptimismFinalizationPayload memory finalizePayload = abi.decode(payload.data, (OptimismFinalizationPayload)); + // NOTE: finalizing ether withdrawals will currently send ether to the receiver address as indicated by the + // withdrawal tx. However, this is problematic because we need to re-wrap it into WETH. + // However, we can't do that from within this adapter because it doesn't actually have the ether. + // So its up to the caller to rectify this by re-wrapping the ether. + _finalizeWithdrawal(finalizePayload); + return true; + } else { + revert InvalidFinalizationAction(); + } + } + + function _proveWithdrawal(OptimismProveWithdrawalPayload memory payload) internal { + // will revert if the proof is invalid or the output index is not yet included on L1. + i_optimismPortal.proveWithdrawalTransaction( + payload.withdrawalTransaction, + payload.l2OutputIndex, + payload.outputRootProof, + payload.withdrawalProof + ); + } + + function _finalizeWithdrawal(OptimismFinalizationPayload memory payload) internal { + i_optimismPortal.finalizeWithdrawalTransaction(payload.withdrawalTransaction); + } + + /// @notice returns the address of the WETH token used by this adapter. + /// @return the address of the WETH token used by this adapter. + function getWrappedNative() external view returns (address) { + return address(i_wrappedNative); + } + + /// @notice returns the address of the Optimism portal contract. + /// @return the address of the Optimism portal contract. + function getOptimismPortal() external view returns (address) { + return address(i_optimismPortal); + } + + /// @notice returns the address of the Optimism L1StandardBridge bridge contract. + /// @return the address of the Optimism L1StandardBridge bridge contract. + function getL1Bridge() external view returns (address) { + return address(i_L1Bridge); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol new file mode 100644 index 0000000..fd1218f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBridgeAdapter} from "../interfaces/IBridge.sol"; +import {IWrappedNative} from "../../ccip/interfaces/IWrappedNative.sol"; + +import {Lib_PredeployAddresses} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @dev copy/pasted from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L2/L2StandardBridge.sol#L114-L122. +/// We can't import it because of hard pin solidity version in the pragma (0.8.15). +interface IL2StandardBridge { + /// @custom:legacy + /// @notice Initiates a withdrawal from L2 to L1 to a target account on L1. + /// Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will + /// be locked in the L1StandardBridge. ETH may be recoverable if the call can be + /// successfully replayed by increasing the amount of gas supplied to the call. If the + /// call will fail for any amount of gas, then the ETH will be locked permanently. + /// This function only works with OptimismMintableERC20 tokens or ether. Use the + /// `bridgeERC20To` function to bridge native L2 tokens to L1. + /// @param _l2Token Address of the L2 token to withdraw. + /// @param _to Recipient account on L1. + /// @param _amount Amount of the L2 token to withdraw. + /// @param _minGasLimit Minimum gas limit to use for the transaction. + /// @param _extraData Extra data attached to the withdrawal. + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes calldata _extraData + ) external payable; +} + +/// @notice OptimismL2BridgeAdapter implements IBridgeAdapter for the Optimism L2<=>L1 bridge. +/// @dev We have to unwrap WETH into ether before withdrawing it to L1. Therefore this bridge adapter bridges +/// WETH to ether. The receiver on L1 must wrap the ether back into WETH. +contract OptimismL2BridgeAdapter is IBridgeAdapter { + using SafeERC20 for IERC20; + + IL2StandardBridge internal immutable i_L2Bridge = IL2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE); + IWrappedNative internal immutable i_wrappedNative; + + // Nonce to use for L1 withdrawals to allow for better tracking offchain. + uint64 private s_nonce = 0; + + constructor(IWrappedNative wrappedNative) { + // Wrapped native can be address zero, this means that auto-wrapping is disabled. + i_wrappedNative = wrappedNative; + } + + /// @notice The WETH withdraw requires this be present otherwise withdraws will fail. + receive() external payable {} + + /// @inheritdoc IBridgeAdapter + function sendERC20( + address localToken, + address /* remoteToken */, + address recipient, + uint256 amount, + bytes calldata /* bridgeSpecificPayload */ + ) external payable override returns (bytes memory) { + if (msg.value != 0) { + revert MsgShouldNotContainValue(msg.value); + } + + IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); + + // Extra data for the L2 withdraw. + // We encode the nonce in the extra data so that we can track the L2 withdraw offchain. + bytes memory extraData = abi.encode(s_nonce++); + + // If the token is the wrapped native, we unwrap it and withdraw native + if (localToken == address(i_wrappedNative)) { + i_wrappedNative.withdraw(amount); + // XXX: Lib_PredeployAddresses.OVM_ETH is actually 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000. + // This code path still works because the L2 bridge is hardcoded to handle this specific address. + // The better approach might be to use the bridgeEthTo function, which is on the StandardBridge + // abstract contract, inherited by both L1StandardBridge and L2StandardBridge. + // This is also marked as legacy, so it might mean that this will be deprecated soon. + i_L2Bridge.withdrawTo{value: amount}(Lib_PredeployAddresses.OVM_ETH, recipient, amount, 0, extraData); + return extraData; + } + + // Token is normal ERC20 + IERC20(localToken).approve(address(i_L2Bridge), amount); + i_L2Bridge.withdrawTo(localToken, recipient, amount, 0, extraData); + return extraData; + } + + /// @notice No-op since L1 -> L2 transfers do not need finalization. + /// @return true always. + function finalizeWithdrawERC20( + address /* remoteSender */, + address /* localReceiver */, + bytes calldata /* bridgeSpecificPayload */ + ) external pure override returns (bool) { + return true; + } + + /// @notice There are no fees to bridge back to L1 + function getBridgeFeeInNative() external pure returns (uint256) { + return 0; + } + + /// @notice returns the address of the WETH token used by this adapter. + /// @return the address of the WETH token used by this adapter. + function getWrappedNative() external view returns (address) { + return address(i_wrappedNative); + } + + /// @notice returns the address of the L2 bridge used by this adapter. + /// @return the address of the L2 bridge used by this adapter. + function getL2Bridge() external view returns (address) { + return address(i_L2Bridge); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol new file mode 100644 index 0000000..888b487 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {OptimismL1BridgeAdapter} from "../bridge-adapters/OptimismL1BridgeAdapter.sol"; + +/// @dev to generate abi's for the OptimismL1BridgeAdapter's various payload types. +/// @dev for usage examples see core/scripts/ccip/liquiditymanager/opstack/prove_withdrawal.go +/// @dev or core/scripts/ccip/liquiditymanager/opstack/finalize.go. +abstract contract OptimismL1BridgeAdapterEncoder { + function encodeFinalizeWithdrawalERC20Payload( + OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload + ) public pure {} + + function encodeOptimismProveWithdrawalPayload( + OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload memory payload + ) public pure {} + + function encodeOptimismFinalizationPayload( + OptimismL1BridgeAdapter.OptimismFinalizationPayload memory payload + ) public pure {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol new file mode 100644 index 0000000..83e64ed --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/// @dev IBridgeAdapter provides a common interface to interact with the native bridge. +interface IBridgeAdapter { + error BridgeAddressCannotBeZero(); + error MsgValueDoesNotMatchAmount(uint256 msgValue, uint256 amount); + error InsufficientEthValue(uint256 wanted, uint256 got); + error MsgShouldNotContainValue(uint256 value); + + /// @notice Send the specified amount of the local token cross-chain to the remote chain. + /// The tokens on the remote chain will then be sourced from the remoteToken address. + /// The amount to be sent must be approved by the caller beforehand on the localToken contract. + /// The caller must provide the bridging fee in native currency, i.e msg.value. + /// @param localToken The address of the local ERC-20 token. + /// @param remoteToken The address of the remote ERC-20 token. + /// @param recipient The address of the recipient on the remote chain. + /// @param amount The amount of the local token to send. + /// @param bridgeSpecificPayload The payload of the cross-chain transfer. Bridge-specific. + function sendERC20( + address localToken, + address remoteToken, + address recipient, + uint256 amount, + bytes calldata bridgeSpecificPayload + ) external payable returns (bytes memory); + + /// @notice Get the bridging fee in native currency. This fee must be provided upon sending tokens via + /// the sendERC20 function. + /// @return The bridging fee in native currency. + function getBridgeFeeInNative() external view returns (uint256); + + /// @notice Finalize the withdrawal of a cross-chain transfer. + /// Not all implementations will finalize a transfer in a single call to this function. + /// Optimism, for example, requires a two-step process to finalize a transfer. The first + /// step requires proving the withdrawal that occurred on L2 on L1. The second step is then + /// the finalization, whereby funds become available to the recipient. So, in that particular + /// scenario, `false` is returned from `finalizeWithdrawERC20` when the first step is completed, + /// and `true` is returned when the second step is completed. + /// @param remoteSender The address of the sender on the remote chain. + /// @param localReceiver The address of the receiver on the local chain. + /// @param bridgeSpecificPayload The payload of the cross-chain transfer, bridge-specific, i.e a proof of some kind. + /// @return true iff the funds are available, false otherwise. + function finalizeWithdrawERC20( + address remoteSender, + address localReceiver, + bytes calldata bridgeSpecificPayload + ) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol new file mode 100644 index 0000000..062325d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/// @notice Interface for a liquidity container, this can be a CCIP token pool. +interface ILiquidityContainer { + event LiquidityAdded(address indexed provider, uint256 indexed amount); + event LiquidityRemoved(address indexed provider, uint256 indexed amount); + + /// @notice Provide additional liquidity to the container. + /// @dev Should emit LiquidityAdded + function provideLiquidity(uint256 amount) external; + + /// @notice Withdraws liquidity from the container to the msg sender + /// @dev Should emit LiquidityRemoved + function withdrawLiquidity(uint256 amount) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol new file mode 100644 index 0000000..19fd101 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IBridgeAdapter} from "./IBridge.sol"; + +interface ILiquidityManager { + /// @notice Parameters for sending liquidity to a remote chain. + /// @param amount The amount of tokens to be sent to the remote chain. + /// @param nativeBridgeFee The amount of native that should be sent by the liquiditymanager in the sendERC20 call. + /// Used to pay for the bridge fees. + /// @param remoteChainSelector The selector of the remote chain. + /// @param bridgeData The bridge data that should be passed to the sendERC20 call. + struct SendLiquidityParams { + uint256 amount; + uint256 nativeBridgeFee; + uint64 remoteChainSelector; + bytes bridgeData; + } + + /// @notice Parameters for receiving liquidity from a remote chain. + /// @param amount The amount of tokens to be received from the remote chain. + /// @param remoteChainSelector The selector of the remote chain. + /// @param bridgeData The bridge data that should be passed to the finalizeWithdrawERC20 call. + /// @param shouldWrapNative Whether the received native token should be wrapped into wrapped native. + /// This is needed for when the bridge being used doesn't bridge wrapped native but native directly. + struct ReceiveLiquidityParams { + uint256 amount; + uint64 remoteChainSelector; + bool shouldWrapNative; + bytes bridgeData; + } + + /// @notice Instructions for the rebalancer on what to do with the available liquidity. + /// @param sendLiquidityParams The parameters for sending liquidity to a remote chain. + /// @param receiveLiquidityParams The parameters for receiving liquidity from a remote chain. + struct LiquidityInstructions { + SendLiquidityParams[] sendLiquidityParams; + ReceiveLiquidityParams[] receiveLiquidityParams; + } + + /// @notice Parameters for adding a cross-chain rebalancer. + /// @param remoteRebalancer The address of the remote rebalancer. + /// @param localBridge The local bridge adapter address. + /// @param remoteToken The address of the remote token. + /// @param remoteChainSelector The selector of the remote chain. + /// @param enabled Whether the rebalancer is enabled. + struct CrossChainRebalancerArgs { + address remoteRebalancer; + IBridgeAdapter localBridge; + address remoteToken; + uint64 remoteChainSelector; + bool enabled; + } + + /// @notice Returns the current liquidity in the liquidity container. + /// @return currentLiquidity The current liquidity in the liquidity container. + function getLiquidity() external view returns (uint256 currentLiquidity); + + /// @notice Returns all the cross-chain rebalancers. + /// @return All the cross-chain rebalancers. + function getAllCrossChainRebalancers() external view returns (CrossChainRebalancerArgs[] memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol new file mode 100644 index 0000000..c695729 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {TokenGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/TokenGateway.sol"; + +/// @dev to generate gethwrappers +abstract contract IAbstractArbitrumTokenGateway is TokenGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol new file mode 100644 index 0000000..a5d0e5e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IRollupCore} from "@arbitrum/nitro-contracts/src/rollup/IRollupCore.sol"; + +/// @dev to generate gethwrappers +interface IArbRollupCore is IRollupCore {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol new file mode 100644 index 0000000..7d6afbc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; + +/// @dev to generate gethwrappers +interface IArbSys is ArbSys {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol new file mode 100644 index 0000000..81fc2cb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; + +/// @dev to generate gethwrappers +interface IArbitrumGatewayRouter is IGatewayRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol new file mode 100644 index 0000000..a306ef2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IInboxBase} from "@arbitrum/nitro-contracts/src/bridge/IInboxBase.sol"; + +/// @dev to generate gethwrappers +interface IArbitrumInbox is IInboxBase {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol new file mode 100644 index 0000000..49e7e45 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; + +/// @dev to generate gethwrappers +interface IArbitrumL1GatewayRouter is IL1GatewayRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol new file mode 100644 index 0000000..0c1f228 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ITokenGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/ITokenGateway.sol"; + +/// @dev to generate gethwrappers +interface IArbitrumTokenGateway is ITokenGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol new file mode 100644 index 0000000..96a63a0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {L2ArbitrumGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol"; + +/// @dev to generate gethwrappers +abstract contract IL2ArbitrumGateway is L2ArbitrumGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol new file mode 100644 index 0000000..115882a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {L2ArbitrumMessenger} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol"; + +/// @dev to generate gethwrappers +abstract contract IL2ArbitrumMessenger is L2ArbitrumMessenger {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol new file mode 100644 index 0000000..79475cd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {NodeInterface} from "@arbitrum/nitro-contracts/src/node-interface/NodeInterface.sol"; + +/// @dev to generate gethwrappers +interface INodeInterface is NodeInterface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol new file mode 100644 index 0000000..f0bd99f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/libraries/DisputeTypes.sol +pragma solidity ^0.8.0; + +/// @notice A `GameType` represents the type of game being played. +type GameType is uint32; + +/// @notice A `GameId` represents a packed 1 byte game ID, an 11 byte timestamp, and a 20 byte address. +/// @dev The packed layout of this type is as follows: +/// ┌───────────┬───────────┐ +/// │ Bits │ Value │ +/// ├───────────┼───────────┤ +/// │ [0, 8) │ Game Type │ +/// │ [8, 96) │ Timestamp │ +/// │ [96, 256) │ Address │ +/// └───────────┴───────────┘ +type GameId is bytes32; + +/// @notice A dedicated timestamp type. +type Timestamp is uint64; + +/// @notice A claim represents an MPT root representing the state of the fault proof program. +type Claim is bytes32; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol new file mode 100644 index 0000000..2b5cc65 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol#L153 +pragma solidity ^0.8.0; + +interface IOptimismCrossDomainMessenger { + /// @notice Emitted whenever a message is sent to the other chain. + /// @param target Address of the recipient of the message. + /// @param sender Address of the sender of the message. + /// @param message Message to trigger the recipient address with. + /// @param messageNonce Unique nonce attached to the message. + /// @param gasLimit Minimum gas limit that the message can be executed with. + event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); + + /// @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only + /// be executed via cross-chain call from the other messenger OR if the message was + /// already received once and is currently being replayed. + /// @param _nonce Nonce of the message being relayed. + /// @param _sender Address of the user who sent the message. + /// @param _target Address that the message is targeted at. + /// @param _value ETH value to send with the message. + /// @param _minGasLimit Minimum amount of gas that the message can be executed with. + /// @param _message Message to send to the target. + function relayMessage( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _minGasLimit, + bytes calldata _message + ) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol new file mode 100644 index 0000000..f72e645 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol +pragma solidity ^0.8.0; + +import {GameType, GameId, Timestamp, Claim} from "./DisputeTypes.sol"; + +interface IOptimismDisputeGameFactory { + /// @notice Information about a dispute game found in a `findLatestGames` search. + struct GameSearchResult { + uint256 index; + GameId metadata; + Timestamp timestamp; + Claim rootClaim; + bytes extraData; + } + + /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than + /// `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`. + /// @param _gameType The type of game to find. + /// @param _start The index to start the reverse search from. + /// @param _n The number of games to find. + function findLatestGames( + GameType _gameType, + uint256 _start, + uint256 _n + ) external view returns (GameSearchResult[] memory games_); + + /// @notice The total number of dispute games created by this factory. + /// @return gameCount_ The total number of dispute games created by this factory. + function gameCount() external view returns (uint256 gameCount_); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol new file mode 100644 index 0000000..3a518fc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +pragma solidity ^0.8.0; + +interface IOptimismL1StandardBridge { + /// @custom:legacy + /// @notice Deposits some amount of ETH into a target account on L2. + /// Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will + /// be locked in the L2StandardBridge. ETH may be recoverable if the call can be + /// successfully replayed by increasing the amount of gas supplied to the call. If the + /// call will fail for any amount of gas, then the ETH will be locked permanently. + /// @param _to Address of the recipient on L2. + /// @param _minGasLimit Minimum gas limit for the deposit message on L2. + /// @param _extraData Optional data to forward to L2. + /// Data supplied here will not be used to execute any code on L2 and is + /// only emitted as extra data for the convenience of off-chain tooling. + function depositETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol new file mode 100644 index 0000000..fa36863 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/L2OutputOracle.sol +pragma solidity ^0.8.0; + +import {Types} from "./Types.sol"; + +interface IOptimismL2OutputOracle { + /// @notice Returns the index of the L2 output that checkpoints a given L2 block number. + /// Uses a binary search to find the first output greater than or equal to the given + /// block. + /// @param _l2BlockNumber L2 block number to find a checkpoint for. + /// @return Index of the first checkpoint that commits to the given L2 block number. + function getL2OutputIndexAfter(uint256 _l2BlockNumber) external view returns (uint256); + + /// @notice Returns an output by index. Needed to return a struct instead of a tuple. + /// @param _l2OutputIndex Index of the output to return. + /// @return The output at the given index. + function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol new file mode 100644 index 0000000..9ac6aeb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol +pragma solidity ^0.8.0; + +interface IOptimismL2ToL1MessagePasser { + /// @notice Emitted any time a withdrawal is initiated. + /// @param nonce Unique value corresponding to each withdrawal. + /// @param sender The L2 account address which initiated the withdrawal. + /// @param target The L1 account address the call will be send to. + /// @param value The ETH value submitted for withdrawal, to be forwarded to the target. + /// @param gasLimit The minimum amount of gas that must be provided when withdrawing. + /// @param data The data to be forwarded to the target on L1. + /// @param withdrawalHash The hash of the withdrawal. + event MessagePassed( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data, + bytes32 withdrawalHash + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol new file mode 100644 index 0000000..887025b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/OptimismPortal.sol +pragma solidity ^0.8.0; + +import {Types} from "./Types.sol"; + +interface IOptimismPortal { + /// @notice Semantic version. + function version() external view returns (string memory); + + /// @notice Proves a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. + /// @param _l2OutputIndex L2 output index to prove against. + /// @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. + /// @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx, + uint256 _l2OutputIndex, + Types.OutputRootProof calldata _outputRootProof, + bytes[] calldata _withdrawalProof + ) external; + + /// @notice Finalizes a withdrawal transaction. + /// @param _tx Withdrawal transaction to finalize. + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol new file mode 100644 index 0000000..165922b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +pragma solidity ^0.8.0; +import {GameType} from "./DisputeTypes.sol"; + +interface IOptimismPortal2 { + /// @notice The dispute game factory address. + /// @dev See https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L1/OptimismPortal2.sol#L79. + function disputeGameFactory() external view returns (address); + /// @notice The game type that the OptimismPortal consults for output proposals. + function respectedGameType() external view returns (GameType); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol new file mode 100644 index 0000000..2f9ef91 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/universal/StandardBridge.sol#L88 +pragma solidity ^0.8.0; + +interface IOptimismStandardBridge { + /// @notice Emitted when an ERC20 bridge is finalized on this chain. + /// @param localToken Address of the ERC20 on this chain. + /// @param remoteToken Address of the ERC20 on the remote chain. + /// @param from Address of the sender. + /// @param to Address of the receiver. + /// @param amount Amount of the ERC20 sent. + /// @param extraData Extra data sent with the transaction. + event ERC20BridgeFinalized( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + + /// @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other + /// StandardBridge contract on the remote chain. + /// @param _localToken Address of the ERC20 on this chain. + /// @param _remoteToken Address of the corresponding token on the remote chain. + /// @param _from Address of the sender. + /// @param _to Address of the receiver. + /// @param _amount Amount of the ERC20 being bridged. + /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will + /// not be triggered with this data, but it will be emitted and can be used + /// to identify the transaction. + function finalizeBridgeERC20( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + bytes calldata _extraData + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol new file mode 100644 index 0000000..bd8d5d3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/libraries/Types.sol +pragma solidity ^0.8.0; + +/// @title Types +/// @notice Contains various types used throughout the Optimism contract system. +library Types { + /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1 + /// timestamp that the output root is posted. This timestamp is used to verify that the + /// finalization period has passed since the output root was submitted. + /// @custom:field outputRoot Hash of the L2 output. + /// @custom:field timestamp Timestamp of the L1 block that the output root was submitted in. + /// @custom:field l2BlockNumber L2 block number that the output corresponds to. + struct OutputProposal { + bytes32 outputRoot; + uint128 timestamp; + uint128 l2BlockNumber; + } + + /// @notice Struct representing the elements that are hashed together to generate an output root + /// which itself represents a snapshot of the L2 state. + /// @custom:field version Version of the output root. + /// @custom:field stateRoot Root of the state trie at the block of this output. + /// @custom:field messagePasserStorageRoot Root of the message passer storage trie. + /// @custom:field latestBlockhash Hash of the block this output was generated from. + struct OutputRootProof { + bytes32 version; + bytes32 stateRoot; + bytes32 messagePasserStorageRoot; + bytes32 latestBlockhash; + } + + /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end + /// user (as opposed to a system deposit transaction generated by the system). + /// @custom:field from Address of the sender of the transaction. + /// @custom:field to Address of the recipient of the transaction. + /// @custom:field isCreation True if the transaction is a contract creation. + /// @custom:field value Value to send to the recipient. + /// @custom:field mint Amount of ETH to mint. + /// @custom:field gasLimit Gas limit of the transaction. + /// @custom:field data Data of the transaction. + /// @custom:field l1BlockHash Hash of the block the transaction was submitted in. + /// @custom:field logIndex Index of the log in the block the transaction was submitted in. + //solhint-disable gas-struct-packing + struct UserDepositTransaction { + address from; + address to; + bool isCreation; + uint256 value; + uint256 mint; + uint64 gasLimit; + bytes data; + bytes32 l1BlockHash; + uint256 logIndex; + } + + /// @notice Struct representing a withdrawal transaction. + /// @custom:field nonce Nonce of the withdrawal transaction + /// @custom:field sender Address of the sender of the transaction. + /// @custom:field target Address of the recipient of the transaction. + /// @custom:field value Value to send to the recipient. + /// @custom:field gasLimit Gas limit of the transaction. + /// @custom:field data Data of the transaction. + struct WithdrawalTransaction { + uint256 nonce; + address sender; + address target; + uint256 value; + uint256 gasLimit; + bytes data; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol new file mode 100644 index 0000000..44e5d89 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; + +abstract contract OCR3Abstract is ITypeAndVersion { + // Maximum number of oracles the offchain reporting protocol is designed for + uint256 internal constant MAX_NUM_ORACLES = 31; + + /// @notice triggers a new run of the offchain reporting protocol + /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + /// @param configDigest configDigest of this configuration + /// @param configCount ordinal number of this config setting among all config settings over the life of this contract + /// @param signers ith element is address ith oracle uses to sign a report + /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param signers addresses with which oracles sign the reports + /// @param transmitters addresses oracles use to transmit the reports + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + function setOCR3Config( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /// @notice optionally emitted to indicate the latest configDigest and sequence number + /// for which a report was successfully transmitted. Alternatively, the contract may + /// use latestConfigDigestAndEpoch with scanLogs set to false. + event Transmitted(bytes32 configDigest, uint64 sequenceNumber); + + /// @notice transmit is called to post a new report to the contract + /// @param report serialized report, which the signatures are signing. + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param rawVs ith element is the the V component of the ith signature + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol new file mode 100644 index 0000000..8c31ba5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {OCR3Abstract} from "./OCR3Abstract.sol"; + +/// @notice Onchain verification of reports from the offchain reporting protocol +/// @dev For details on its operation, see the offchain reporting protocol design +/// doc, which refers to this contract as simply the "contract". +abstract contract OCR3Base is OwnerIsCreator, OCR3Abstract { + error InvalidConfig(string message); + error WrongMessageLength(uint256 expected, uint256 actual); + error ConfigDigestMismatch(bytes32 expected, bytes32 actual); + error ForkedChain(uint256 expected, uint256 actual); + error WrongNumberOfSignatures(); + error SignaturesOutOfRegistration(); + error UnauthorizedTransmitter(); + error UnauthorizedSigner(); + error NonUniqueSignatures(); + error OracleCannotBeZeroAddress(); + error NonIncreasingSequenceNumber(uint64 sequenceNumber, uint64 latestSequenceNumber); + + // Packing these fields used on the hot path in a ConfigInfo variable reduces the + // retrieval of all of them to a minimum number of SLOADs. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; + uint8 n; + } + + // Used for s_oracles[a].role, where a is an address, to track the purpose + // of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR3Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // Index of oracle in s_signers/s_transmitters + Role role; // Role of the address which mapped to this struct + } + + // The current config + ConfigInfo internal s_configInfo; + + // incremented each time a new config is posted. This count is incorporated + // into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + // makes it easier for offchain systems to extract config from logs. + uint32 internal s_latestConfigBlockNumber; + + uint64 internal s_latestSequenceNumber; + + // signer OR transmitter address + mapping(address signerOrTransmitter => Oracle oracle) internal s_oracles; + + // s_signers contains the signing address of each oracle + address[] internal s_signers; + + // s_transmitters contains the transmission address of each oracle, + // i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32; // word containing length of ss + + uint256 internal immutable i_chainID; + + constructor() { + i_chainID = block.chainid; + } + + // Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { + if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); + if (f == 0) revert InvalidConfig("f must be positive"); + if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); + if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); + _; + } + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param signers addresses with which oracles sign the reports + /// @param transmitters addresses oracles use to transmit the reports + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig encoded on-chain contract configuration + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig encoded off-chain oracle configuration + function setOCR3Config( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override checkConfigValid(signers.length, transmitters.length, f) onlyOwner { + _beforeSetConfig(onchainConfig); + uint256 oldSignerLength = s_signers.length; + for (uint256 i = 0; i < oldSignerLength; ++i) { + delete s_oracles[s_signers[i]]; + delete s_oracles[s_transmitters[i]]; + } + + uint256 newSignersLength = signers.length; + for (uint256 i = 0; i < newSignersLength; ++i) { + // add new signer/transmitter addresses + address signer = signers[i]; + if (s_oracles[signer].role != Role.Unset) revert InvalidConfig("repeated signer address"); + if (signer == address(0)) revert OracleCannotBeZeroAddress(); + s_oracles[signer] = Oracle(uint8(i), Role.Signer); + + address transmitter = transmitters[i]; + if (s_oracles[transmitter].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); + if (transmitter == address(0)) revert OracleCannotBeZeroAddress(); + s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter); + } + + s_signers = signers; + s_transmitters = transmitters; + + s_configInfo.f = f; + s_configInfo.n = uint8(newSignersLength); + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + ++s_configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_latestSequenceNumber = 0; + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + } + + /// @dev Hook that is run from setOCR3Config() right after validating configuration. + /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing + function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {} + + /// @return list of addresses permitted to transmit reports to this contract + /// @dev The list will match the order used to specify the transmitter during setConfig + function getTransmitters() external view returns (address[] memory) { + return s_transmitters; + } + + /// @notice transmit is called to post a new report to the contract + /// @param report serialized report, which the signatures are signing. + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param rawVs ith element is the the V component of the ith signature + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + uint64 sequenceNumber = uint64(uint256(reportContext[1])); + if (sequenceNumber <= s_latestSequenceNumber) { + revert NonIncreasingSequenceNumber(sequenceNumber, s_latestSequenceNumber); + } + + // Scoping this reduces stack pressure and gas usage + { + _report(report, sequenceNumber); + } + + s_latestSequenceNumber = sequenceNumber; + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 24 byte padding, 8 byte sequence number + bytes32 configDigest = reportContext[0]; + ConfigInfo memory configInfo = s_configInfo; + + if (configInfo.latestConfigDigest != configDigest) { + revert ConfigDigestMismatch(configInfo.latestConfigDigest, configDigest); + } + // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. + // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest + // calculated from chain A and so OCR reports will be valid on both forks. + if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); + + emit Transmitted(configDigest, sequenceNumber); + + if (rs.length != configInfo.f + 1) revert WrongNumberOfSignatures(); + if (rs.length != ss.length) revert SignaturesOutOfRegistration(); + + // Scoping this reduces stack pressure and gas usage + { + Oracle memory transmitter = s_oracles[msg.sender]; + // Check that sender is authorized to report + if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index])) + revert UnauthorizedTransmitter(); + } + // Scoping this reduces stack pressure and gas usage + { + uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32; // 32 bytes per entry in _ss) + if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); + } + + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + bool[MAX_NUM_ORACLES] memory signed; + + uint256 numberOfSignatures = rs.length; + for (uint256 i = 0; i < numberOfSignatures; ++i) { + // Safe from ECDSA malleability here since we check for duplicate signers. + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + // Since we disallow address(0) as a valid signer address, it can + // never have a signer role. + Oracle memory oracle = s_oracles[signer]; + if (oracle.role != Role.Signer) revert UnauthorizedSigner(); + if (signed[oracle.index]) revert NonUniqueSignatures(); + signed[oracle.index] = true; + } + } + + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /// @notice gets the latest sequence number accepted by the contract + /// @return sequenceNumber the monotomically incremenenting number associated with OCR reports + function latestSequenceNumber() external view virtual returns (uint64 sequenceNumber) { + return s_latestSequenceNumber; + } + + function _report(bytes calldata report, uint64 sequenceNumber) internal virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol new file mode 100644 index 0000000..73c9ba7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol @@ -0,0 +1,945 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityManager} from "../interfaces/ILiquidityManager.sol"; +import {IBridgeAdapter} from "../interfaces/IBridge.sol"; + +import {LockReleaseTokenPool} from "../../ccip/pools/LockReleaseTokenPool.sol"; +import {LiquidityManager} from "../LiquidityManager.sol"; +import {MockL1BridgeAdapter} from "./mocks/MockBridgeAdapter.sol"; +import {LiquidityManagerBaseTest} from "./LiquidityManagerBaseTest.t.sol"; +import {LiquidityManagerHelper} from "./helpers/LiquidityManagerHelper.sol"; + +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +// FOUNDRY_PROFILE=liquiditymanager forge test --match-path src/v0.8/liquiditymanager/test/LiquidityManager.t.sol + +contract LiquidityManagerSetup is LiquidityManagerBaseTest { + event FinalizationStepCompleted( + uint64 indexed ocrSeqNum, + uint64 indexed remoteChainSelector, + bytes bridgeSpecificData + ); + event LiquidityTransferred( + uint64 indexed ocrSeqNum, + uint64 indexed fromChainSelector, + uint64 indexed toChainSelector, + address to, + uint256 amount, + bytes bridgeSpecificPayload, + bytes bridgeReturnData + ); + event FinalizationFailed( + uint64 indexed ocrSeqNum, + uint64 indexed remoteChainSelector, + bytes bridgeSpecificData, + bytes reason + ); + event FinanceRoleSet(address financeRole); + event LiquidityAddedToContainer(address indexed provider, uint256 indexed amount); + event LiquidityRemovedFromContainer(address indexed remover, uint256 indexed amount); + // Liquidity container event + event LiquidityAdded(address indexed provider, uint256 indexed amount); + event LiquidityRemoved(address indexed remover, uint256 indexed amount); + + error NonceAlreadyUsed(uint256 nonce); + + LiquidityManagerHelper internal s_liquidityManager; + LockReleaseTokenPool internal s_lockReleaseTokenPool; + MockL1BridgeAdapter internal s_bridgeAdapter; + + // LiquidityManager that rebalances weth. + LiquidityManagerHelper internal s_wethRebalancer; + LockReleaseTokenPool internal s_wethLockReleaseTokenPool; + MockL1BridgeAdapter internal s_wethBridgeAdapter; + + function setUp() public virtual override { + LiquidityManagerBaseTest.setUp(); + + s_bridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); + s_lockReleaseTokenPool = new LockReleaseTokenPool(s_l1Token, new address[](0), address(1), true, address(123)); + s_liquidityManager = new LiquidityManagerHelper( + s_l1Token, + i_localChainSelector, + s_lockReleaseTokenPool, + 0, + FINANCE + ); + + s_lockReleaseTokenPool.setRebalancer(address(s_liquidityManager)); + + s_wethBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l1Weth)), true); + s_wethLockReleaseTokenPool = new LockReleaseTokenPool( + IERC20(address(s_l1Weth)), + new address[](0), + address(1), + true, + address(123) + ); + s_wethRebalancer = new LiquidityManagerHelper( + IERC20(address(s_l1Weth)), + i_localChainSelector, + s_wethLockReleaseTokenPool, + 0, + FINANCE + ); + + s_wethLockReleaseTokenPool.setRebalancer(address(s_wethRebalancer)); + } +} + +contract LiquidityManager_addLiquidity is LiquidityManagerSetup { + function test_addLiquiditySuccess() external { + address caller = STRANGER; + vm.startPrank(caller); + + uint256 amount = 12345679; + deal(address(s_l1Token), caller, amount); + + s_l1Token.approve(address(s_liquidityManager), amount); + + vm.expectEmit(); + emit LiquidityAddedToContainer(caller, amount); + + s_liquidityManager.addLiquidity(amount); + + assertEq(s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), amount); + } +} + +contract LiquidityManager_removeLiquidity is LiquidityManagerSetup { + function test_removeLiquiditySuccess() external { + uint256 amount = 12345679; + deal(address(s_l1Token), address(s_lockReleaseTokenPool), amount); + + vm.expectEmit(); + emit LiquidityRemovedFromContainer(FINANCE, amount); + + vm.startPrank(FINANCE); + s_liquidityManager.removeLiquidity(amount); + + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0); + } + + function test_InsufficientLiquidityReverts() external { + uint256 balance = 923; + uint256 requested = balance + 1; + + deal(address(s_l1Token), address(s_lockReleaseTokenPool), balance); + + vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InsufficientLiquidity.selector, requested, balance, 0)); + + vm.startPrank(FINANCE); + s_liquidityManager.removeLiquidity(requested); + } + + function test_OnlyFinanceRoleReverts() external { + vm.stopPrank(); + + vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); + + s_liquidityManager.removeLiquidity(123); + } +} + +contract LiquidityManager__report is LiquidityManagerSetup { + function test_EmptyReportReverts() external { + ILiquidityManager.LiquidityInstructions memory instructions = ILiquidityManager.LiquidityInstructions({ + sendLiquidityParams: new ILiquidityManager.SendLiquidityParams[](0), + receiveLiquidityParams: new ILiquidityManager.ReceiveLiquidityParams[](0) + }); + + vm.expectRevert(LiquidityManager.EmptyReport.selector); + + s_liquidityManager.report(abi.encode(instructions), 123); + } +} + +contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { + uint256 internal constant AMOUNT = 12345679; + + function test_rebalanceLiquiditySuccess() external { + deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); + + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(s_liquidityManager), + localBridge: s_bridgeAdapter, + remoteToken: address(s_l2Token), + remoteChainSelector: i_remoteChainSelector, + enabled: true + }); + s_liquidityManager.setCrossChainRebalancers(args); + + vm.expectEmit(); + emit Transfer(address(s_lockReleaseTokenPool), address(s_liquidityManager), AMOUNT); + + vm.expectEmit(); + emit Approval(address(s_liquidityManager), address(s_bridgeAdapter), AMOUNT); + + vm.expectEmit(); + emit Transfer(address(s_liquidityManager), address(s_bridgeAdapter), AMOUNT); + + vm.expectEmit(); + bytes memory encodedNonce = abi.encode(uint256(1)); + emit LiquidityTransferred( + type(uint64).max, + i_localChainSelector, + i_remoteChainSelector, + address(s_liquidityManager), + AMOUNT, + bytes(""), + encodedNonce + ); + + vm.startPrank(FINANCE); + s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, AMOUNT, 0, bytes("")); + + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0); + assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), AMOUNT); + assertEq(s_l1Token.allowance(address(s_liquidityManager), address(s_bridgeAdapter)), 0); + } + + /// @notice this test sets up a circular system where the liquidity container of + /// the local Liquidity manager is the bridge adapter of the remote liquidity manager + /// and the other way around for the remote liquidity manager. This allows us to + /// rebalance funds between the two liquidity managers on the same chain. + function test_rebalanceBetweenPoolsSuccess() external { + uint256 amount = 12345670; + + s_liquidityManager = new LiquidityManagerHelper(s_l1Token, i_localChainSelector, s_bridgeAdapter, 0, FINANCE); + + MockL1BridgeAdapter mockRemoteBridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); + LiquidityManager mockRemoteRebalancer = new LiquidityManager( + s_l1Token, + i_remoteChainSelector, + mockRemoteBridgeAdapter, + 0, + FINANCE + ); + + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(mockRemoteRebalancer), + localBridge: mockRemoteBridgeAdapter, + remoteToken: address(s_l1Token), + remoteChainSelector: i_remoteChainSelector, + enabled: true + }); + + s_liquidityManager.setCrossChainRebalancers(args); + + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(s_liquidityManager), + localBridge: s_bridgeAdapter, + remoteToken: address(s_l1Token), + remoteChainSelector: i_localChainSelector, + enabled: true + }); + + mockRemoteRebalancer.setCrossChainRebalancers(args); + + deal(address(s_l1Token), address(s_bridgeAdapter), amount); + + vm.startPrank(FINANCE); + s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, amount, 0, bytes("")); + + assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), 0); + assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), amount); + assertEq(s_l1Token.allowance(address(s_liquidityManager), address(s_bridgeAdapter)), 0); + + // attach a bridge fee and see the relevant adapter's ether balance change. + // the bridge fee is sent along with the sendERC20 call. + uint256 bridgeFee = 123; + vm.deal(address(mockRemoteRebalancer), bridgeFee); + mockRemoteRebalancer.rebalanceLiquidity(i_localChainSelector, amount, bridgeFee, bytes("")); + + assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), amount); + assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), 0); + assertEq(address(s_bridgeAdapter).balance, bridgeFee); + + // Assert partial rebalancing works correctly + s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, amount / 2, 0, bytes("")); + + assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), amount / 2); + assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), amount / 2); + } + + function test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() external { + // set up a rebalancer on another chain, an "L2". + // note we use the L1 bridge adapter because it has the reverting logic + // when finalization is already done. + MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); + LockReleaseTokenPool remotePool = new LockReleaseTokenPool( + s_l2Token, + new address[](0), + address(1), + true, + address(123) + ); + LiquidityManager remoteRebalancer = new LiquidityManager(s_l2Token, i_remoteChainSelector, remotePool, 0, FINANCE); + + // set rebalancer role on the pool. + remotePool.setRebalancer(address(remoteRebalancer)); + + // set up the cross chain rebalancer on "L1". + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(remoteRebalancer), + localBridge: s_bridgeAdapter, + remoteToken: address(s_l2Token), + remoteChainSelector: i_remoteChainSelector, + enabled: true + }); + + s_liquidityManager.setCrossChainRebalancers(args); + + // set up the cross chain rebalancer on "L2". + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(s_liquidityManager), + localBridge: remoteBridgeAdapter, + remoteToken: address(s_l1Token), + remoteChainSelector: i_localChainSelector, + enabled: true + }); + + remoteRebalancer.setCrossChainRebalancers(args); + + // deal some L1 tokens to the L1 bridge adapter so that it can send them to the rebalancer + // when the withdrawal gets finalized. + deal(address(s_l1Token), address(s_bridgeAdapter), AMOUNT); + // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. + deal(address(s_l2Token), address(remotePool), AMOUNT); + + uint256 nonce = 1; + uint64 maxSeqNum = type(uint64).max; + bytes memory bridgeSendReturnData = abi.encode(nonce); + bytes memory bridgeSpecificPayload = bytes(""); + vm.expectEmit(); + emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_liquidityManager), + AMOUNT, + bridgeSpecificPayload, + bridgeSendReturnData + ); + vm.startPrank(FINANCE); + remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); + + // available liquidity has been moved to the remote bridge adapter from the token pool. + assertEq(s_l2Token.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); + assertEq(s_l2Token.balanceOf(address(remotePool)), 0, "remotePool balance"); + + // prove and finalize manually on the L1 bridge adapter. + // this should transfer the funds to the rebalancer. + MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); + MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, + data: abi.encode(provePayload) + }); + bool fundsAvailable = s_bridgeAdapter.finalizeWithdrawERC20( + address(0), + address(s_liquidityManager), + abi.encode(payload) + ); + assertFalse(fundsAvailable, "fundsAvailable must be false"); + MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ + nonce: nonce, + amount: AMOUNT + }); + payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, + data: abi.encode(finalizePayload) + }); + fundsAvailable = s_bridgeAdapter.finalizeWithdrawERC20( + address(0), + address(s_liquidityManager), + abi.encode(payload) + ); + assertTrue(fundsAvailable, "fundsAvailable must be true"); + + // available balance on the L1 bridge adapter has been moved to the rebalancer. + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), AMOUNT, "rebalancer balance 1"); + assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), 0, "bridgeAdapter balance"); + + // try to finalize on L1 again + // bytes memory revertData = abi.encodeWithSelector(NonceAlreadyUsed.selector, nonce); + vm.expectEmit(); + emit FinalizationFailed( + maxSeqNum, + i_remoteChainSelector, + abi.encode(payload), + abi.encodeWithSelector(NonceAlreadyUsed.selector, nonce) + ); + vm.expectEmit(); + emit LiquidityAdded(address(s_liquidityManager), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_liquidityManager), + AMOUNT, + abi.encode(payload), + bytes("") + ); + s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); + + // available balance on the rebalancer has been injected into the token pool. + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 2"); + assertEq(s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), AMOUNT, "lockReleaseTokenPool balance"); + } + + function test_rebalanceBetweenPools_MultiStageFinalization() external { + // set up a rebalancer on another chain, an "L2". + // note we use the L1 bridge adapter because it has the reverting logic + // when finalization is already done. + MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); + LockReleaseTokenPool remotePool = new LockReleaseTokenPool( + s_l2Token, + new address[](0), + address(1), + true, + address(123) + ); + LiquidityManager remoteRebalancer = new LiquidityManager(s_l2Token, i_remoteChainSelector, remotePool, 0, FINANCE); + + // set rebalancer role on the pool. + remotePool.setRebalancer(address(remoteRebalancer)); + + // set up the cross chain rebalancer on "L1". + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(remoteRebalancer), + localBridge: s_bridgeAdapter, + remoteToken: address(s_l2Token), + remoteChainSelector: i_remoteChainSelector, + enabled: true + }); + + s_liquidityManager.setCrossChainRebalancers(args); + + // set up the cross chain rebalancer on "L2". + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(s_liquidityManager), + localBridge: remoteBridgeAdapter, + remoteToken: address(s_l1Token), + remoteChainSelector: i_localChainSelector, + enabled: true + }); + + remoteRebalancer.setCrossChainRebalancers(args); + + // deal some L1 tokens to the L1 bridge adapter so that it can send them to the rebalancer + // when the withdrawal gets finalized. + deal(address(s_l1Token), address(s_bridgeAdapter), AMOUNT); + // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. + deal(address(s_l2Token), address(remotePool), AMOUNT); + + // initiate a send from remote rebalancer to s_liquidityManager. + uint256 nonce = 1; + uint64 maxSeqNum = type(uint64).max; + bytes memory bridgeSendReturnData = abi.encode(nonce); + bytes memory bridgeSpecificPayload = bytes(""); + vm.expectEmit(); + emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_liquidityManager), + AMOUNT, + bridgeSpecificPayload, + bridgeSendReturnData + ); + vm.startPrank(FINANCE); + remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); + + // available liquidity has been moved to the remote bridge adapter from the token pool. + assertEq(s_l2Token.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); + assertEq(s_l2Token.balanceOf(address(remotePool)), 0, "remotePool balance"); + + // prove withdrawal on the L1 bridge adapter, through the rebalancer. + uint256 balanceBeforeProve = s_l1Token.balanceOf(address(s_lockReleaseTokenPool)); + MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); + MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, + data: abi.encode(provePayload) + }); + vm.expectEmit(); + emit FinalizationStepCompleted(maxSeqNum, i_remoteChainSelector, abi.encode(payload)); + s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); + + // s_liquidityManager should have no tokens. + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 1"); + // balance of s_lockReleaseTokenPool should be unchanged since no liquidity got added yet. + assertEq( + s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), + balanceBeforeProve, + "s_lockReleaseTokenPool balance should be unchanged" + ); + + // finalize withdrawal on the L1 bridge adapter, through the rebalancer. + MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ + nonce: nonce, + amount: AMOUNT + }); + payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, + data: abi.encode(finalizePayload) + }); + vm.expectEmit(); + emit LiquidityAdded(address(s_liquidityManager), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_liquidityManager), + AMOUNT, + abi.encode(payload), + bytes("") + ); + s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); + + // s_liquidityManager should have no tokens. + assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 2"); + // balance of s_lockReleaseTokenPool should be updated + assertEq( + s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), + balanceBeforeProve + AMOUNT, + "s_lockReleaseTokenPool balance should be updated" + ); + } + + function test_rebalanceBetweenPools_NativeRewrap() external { + // set up a rebalancer similar to the above on another chain, an "L2". + MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l2Weth)), true); + LockReleaseTokenPool remotePool = new LockReleaseTokenPool( + IERC20(address(s_l2Weth)), + new address[](0), + address(1), + true, + address(123) + ); + LiquidityManager remoteRebalancer = new LiquidityManager( + IERC20(address(s_l2Weth)), + i_remoteChainSelector, + remotePool, + 0, + FINANCE + ); + + // set rebalancer role on the pool. + remotePool.setRebalancer(address(remoteRebalancer)); + + // set up the cross chain rebalancer on "L1". + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(remoteRebalancer), + localBridge: s_wethBridgeAdapter, + remoteToken: address(s_l2Weth), + remoteChainSelector: i_remoteChainSelector, + enabled: true + }); + + s_wethRebalancer.setCrossChainRebalancers(args); + + // set up the cross chain rebalancer on "L2". + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(s_wethRebalancer), + localBridge: remoteBridgeAdapter, + remoteToken: address(s_l1Weth), + remoteChainSelector: i_localChainSelector, + enabled: true + }); + + remoteRebalancer.setCrossChainRebalancers(args); + + // deal some ether to the L1 bridge adapter so that it can send them to the rebalancer + // when the withdrawal gets finalized. + vm.deal(address(s_wethBridgeAdapter), AMOUNT); + // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. + deal(address(s_l2Weth), address(remotePool), AMOUNT); + // deposit some eth to the weth contract on L2 from the remote bridge adapter + // so that the withdraw() call succeeds. + vm.deal(address(remoteBridgeAdapter), AMOUNT); + vm.startPrank(address(remoteBridgeAdapter)); + s_l2Weth.deposit{value: AMOUNT}(); + vm.stopPrank(); + + // switch to finance for the rest of the test to avoid reverts. + vm.startPrank(FINANCE); + + // initiate a send from remote rebalancer to s_wethRebalancer. + uint256 nonce = 1; + uint64 maxSeqNum = type(uint64).max; + bytes memory bridgeSendReturnData = abi.encode(nonce); + bytes memory bridgeSpecificPayload = bytes(""); + vm.expectEmit(); + emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_wethRebalancer), + AMOUNT, + bridgeSpecificPayload, + bridgeSendReturnData + ); + remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); + + // available liquidity has been moved to the remote bridge adapter from the token pool. + assertEq(s_l2Weth.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); + assertEq(s_l2Weth.balanceOf(address(remotePool)), 0, "remotePool balance"); + + // prove withdrawal on the L1 bridge adapter, through the rebalancer. + uint256 balanceBeforeProve = s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)); + MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); + MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, + data: abi.encode(provePayload) + }); + vm.expectEmit(); + emit FinalizationStepCompleted(maxSeqNum, i_remoteChainSelector, abi.encode(payload)); + s_wethRebalancer.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); + + // s_wethRebalancer should have no tokens. + assertEq(s_l1Weth.balanceOf(address(s_wethRebalancer)), 0, "rebalancer balance 1"); + // balance of s_wethLockReleaseTokenPool should be unchanged since no liquidity got added yet. + assertEq( + s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)), + balanceBeforeProve, + "s_wethLockReleaseTokenPool balance should be unchanged" + ); + + // finalize withdrawal on the L1 bridge adapter, through the rebalancer. + MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ + nonce: nonce, + amount: AMOUNT + }); + payload = MockL1BridgeAdapter.Payload({ + action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, + data: abi.encode(finalizePayload) + }); + vm.expectEmit(); + emit LiquidityAdded(address(s_wethRebalancer), AMOUNT); + vm.expectEmit(); + emit LiquidityTransferred( + maxSeqNum, + i_remoteChainSelector, + i_localChainSelector, + address(s_wethRebalancer), + AMOUNT, + abi.encode(payload), + bytes("") + ); + s_wethRebalancer.receiveLiquidity(i_remoteChainSelector, AMOUNT, true, abi.encode(payload)); + + // s_wethRebalancer should have no tokens. + assertEq(s_l1Weth.balanceOf(address(s_wethRebalancer)), 0, "rebalancer balance 2"); + // s_wethRebalancer should have no native tokens. + assertEq(address(s_wethRebalancer).balance, 0, "rebalancer native balance should be zero"); + // balance of s_wethLockReleaseTokenPool should be updated + assertEq( + s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)), + balanceBeforeProve + AMOUNT, + "s_wethLockReleaseTokenPool balance should be updated" + ); + } + + // Reverts + + function test_InsufficientLiquidityReverts() external { + s_liquidityManager.setMinimumLiquidity(3); + deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); + vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InsufficientLiquidity.selector, AMOUNT, AMOUNT, 3)); + + vm.startPrank(FINANCE); + s_liquidityManager.rebalanceLiquidity(0, AMOUNT, 0, bytes("")); + } + + function test_InvalidRemoteChainReverts() external { + deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); + + vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InvalidRemoteChain.selector, i_remoteChainSelector)); + + vm.startPrank(FINANCE); + s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, AMOUNT, 0, bytes("")); + } +} + +contract LiquidityManager_setCrossChainRebalancer is LiquidityManagerSetup { + event CrossChainRebalancerSet( + uint64 indexed remoteChainSelector, + IBridgeAdapter localBridge, + address remoteToken, + address remoteRebalancer, + bool enabled + ); + + function test_setCrossChainRebalancerSuccess() external { + address newRebalancer = address(23892423); + uint64 remoteChainSelector = 12301293; + + uint64[] memory supportedChains = s_liquidityManager.getSupportedDestChains(); + assertEq(supportedChains.length, 0); + + LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); + args[0] = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: newRebalancer, + localBridge: s_bridgeAdapter, + remoteToken: address(190490124908), + remoteChainSelector: remoteChainSelector, + enabled: true + }); + + vm.expectEmit(); + emit CrossChainRebalancerSet( + remoteChainSelector, + args[0].localBridge, + args[0].remoteToken, + newRebalancer, + args[0].enabled + ); + + s_liquidityManager.setCrossChainRebalancers(args); + + assertEq(s_liquidityManager.getCrossChainRebalancer(remoteChainSelector).remoteRebalancer, newRebalancer); + + LiquidityManager.CrossChainRebalancerArgs[] memory got = s_liquidityManager.getAllCrossChainRebalancers(); + assertEq(got.length, 1); + assertEq(got[0].remoteRebalancer, args[0].remoteRebalancer); + assertEq(address(got[0].localBridge), address(args[0].localBridge)); + assertEq(got[0].remoteToken, args[0].remoteToken); + assertEq(got[0].remoteChainSelector, args[0].remoteChainSelector); + assertEq(got[0].enabled, args[0].enabled); + + supportedChains = s_liquidityManager.getSupportedDestChains(); + assertEq(supportedChains.length, 1); + assertEq(supportedChains[0], remoteChainSelector); + + address anotherRebalancer = address(123); + args[0].remoteRebalancer = anotherRebalancer; + + vm.expectEmit(); + emit CrossChainRebalancerSet( + remoteChainSelector, + args[0].localBridge, + args[0].remoteToken, + anotherRebalancer, + args[0].enabled + ); + + s_liquidityManager.setCrossChainRebalancer(args[0]); + + assertEq(s_liquidityManager.getCrossChainRebalancer(remoteChainSelector).remoteRebalancer, anotherRebalancer); + + supportedChains = s_liquidityManager.getSupportedDestChains(); + assertEq(supportedChains.length, 1); + assertEq(supportedChains[0], remoteChainSelector); + } + + function test_ZeroChainSelectorReverts() external { + LiquidityManager.CrossChainRebalancerArgs memory arg = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(9), + localBridge: s_bridgeAdapter, + remoteToken: address(190490124908), + remoteChainSelector: 0, + enabled: true + }); + + vm.expectRevert(LiquidityManager.ZeroChainSelector.selector); + + s_liquidityManager.setCrossChainRebalancer(arg); + } + + function test_ZeroAddressReverts() external { + LiquidityManager.CrossChainRebalancerArgs memory arg = ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(0), + localBridge: s_bridgeAdapter, + remoteToken: address(190490124908), + remoteChainSelector: 123, + enabled: true + }); + + vm.expectRevert(LiquidityManager.ZeroAddress.selector); + + s_liquidityManager.setCrossChainRebalancer(arg); + + arg.remoteRebalancer = address(9); + arg.localBridge = IBridgeAdapter(address(0)); + + vm.expectRevert(LiquidityManager.ZeroAddress.selector); + + s_liquidityManager.setCrossChainRebalancer(arg); + + arg.localBridge = s_bridgeAdapter; + arg.remoteToken = address(0); + + vm.expectRevert(LiquidityManager.ZeroAddress.selector); + + s_liquidityManager.setCrossChainRebalancer(arg); + } + + function test_OnlyOwnerReverts() external { + vm.stopPrank(); + + vm.expectRevert("Only callable by owner"); + + // Test the entrypoint that takes a list + s_liquidityManager.setCrossChainRebalancers(new LiquidityManager.CrossChainRebalancerArgs[](0)); + + vm.expectRevert("Only callable by owner"); + + // Test the entrypoint that takes a single item + s_liquidityManager.setCrossChainRebalancer( + ILiquidityManager.CrossChainRebalancerArgs({ + remoteRebalancer: address(9), + localBridge: s_bridgeAdapter, + remoteToken: address(190490124908), + remoteChainSelector: 124, + enabled: true + }) + ); + } +} + +contract LiquidityManager_setLocalLiquidityContainer is LiquidityManagerSetup { + event LiquidityContainerSet(address indexed newLiquidityContainer); + + function test_setLocalLiquidityContainerSuccess() external { + LockReleaseTokenPool newPool = new LockReleaseTokenPool( + s_l1Token, + new address[](0), + address(1), + true, + address(123) + ); + + vm.expectEmit(); + emit LiquidityContainerSet(address(newPool)); + + s_liquidityManager.setLocalLiquidityContainer(newPool); + + assertEq(s_liquidityManager.getLocalLiquidityContainer(), address(newPool)); + } + + function test_OnlyOwnerReverts() external { + vm.stopPrank(); + + vm.expectRevert("Only callable by owner"); + + s_liquidityManager.setLocalLiquidityContainer(LockReleaseTokenPool(address(1))); + } + + function test_ReverstWhen_CalledWithTheZeroAddress() external { + vm.expectRevert(LiquidityManager.ZeroAddress.selector); + s_liquidityManager.setLocalLiquidityContainer(LockReleaseTokenPool(address(0))); + } +} + +contract LiquidityManager_setMinimumLiquidity is LiquidityManagerSetup { + event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); + + function test_setMinimumLiquiditySuccess() external { + vm.expectEmit(); + emit MinimumLiquiditySet(uint256(0), uint256(1000)); + s_liquidityManager.setMinimumLiquidity(1000); + assertEq(s_liquidityManager.getMinimumLiquidity(), uint256(1000)); + } + + function test_OnlyOwnerReverts() external { + vm.stopPrank(); + vm.expectRevert("Only callable by owner"); + s_liquidityManager.setMinimumLiquidity(uint256(1000)); + } +} + +contract LiquidityManager_setFinanceRole is LiquidityManagerSetup { + event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); + + function test_setFinanceRoleSuccess() external { + vm.expectEmit(); + address newFinanceRole = makeAddr("newFinanceRole"); + assertEq(s_liquidityManager.getFinanceRole(), FINANCE); + emit FinanceRoleSet(newFinanceRole); + s_liquidityManager.setFinanceRole(newFinanceRole); + assertEq(s_liquidityManager.getFinanceRole(), newFinanceRole); + } + + function test_OnlyOwnerReverts() external { + vm.stopPrank(); + vm.expectRevert("Only callable by owner"); + s_liquidityManager.setFinanceRole(address(1)); + } +} + +contract LiquidityManager_withdrawNative is LiquidityManagerSetup { + event NativeWithdrawn(uint256 amount, address destination); + + address private receiver = makeAddr("receiver"); + + function setUp() public override { + super.setUp(); + vm.deal(address(s_liquidityManager), 1); + } + + function test_withdrawNative_success() external { + assertEq(receiver.balance, 0); + vm.expectEmit(); + emit NativeWithdrawn(1, receiver); + vm.startPrank(FINANCE); + s_liquidityManager.withdrawNative(1, payable(receiver)); + assertEq(receiver.balance, 1); + } + + function test_OnlyFinanceRoleReverts() external { + vm.stopPrank(); + vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); + s_liquidityManager.withdrawNative(1, payable(receiver)); + } +} + +contract LiquidityManager_receive is LiquidityManagerSetup { + event NativeDeposited(uint256 amount, address depositor); + + address private depositor = makeAddr("depositor"); + + function test_receive_success() external { + vm.deal(depositor, 100); + uint256 before = address(s_liquidityManager).balance; + vm.expectEmit(); + emit NativeDeposited(100, depositor); + vm.startPrank(depositor); + payable(address(s_liquidityManager)).transfer(100); + assertEq(address(s_liquidityManager).balance, before + 100); + } +} + +contract LiquidityManager_withdrawERC20 is LiquidityManagerSetup { + function test_withdrawERC20Success() external { + uint256 amount = 100; + deal(address(s_otherToken), address(s_liquidityManager), amount); + assertEq(s_otherToken.balanceOf(address(1)), 0); + assertEq(s_otherToken.balanceOf(address(s_liquidityManager)), amount); + vm.startPrank(FINANCE); + s_liquidityManager.withdrawERC20(address(s_otherToken), amount, address(1)); + assertEq(s_otherToken.balanceOf(address(1)), amount); + assertEq(s_otherToken.balanceOf(address(s_liquidityManager)), 0); + } + + function test_withdrawERC20Reverts() external { + uint256 amount = 100; + deal(address(s_otherToken), address(s_liquidityManager), amount); + vm.startPrank(STRANGER); + vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); + s_liquidityManager.withdrawERC20(address(s_otherToken), amount, address(1)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol new file mode 100644 index 0000000..128a03f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; + +import {WETH9} from "../../ccip/test/WETH9.sol"; + +import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract LiquidityManagerBaseTest is Test { + // ERC20 events + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + + IERC20 internal s_l1Token; + IERC20 internal s_l2Token; + IERC20 internal s_otherToken; + WETH9 internal s_l1Weth; + WETH9 internal s_l2Weth; + + uint64 internal immutable i_localChainSelector = 1234; + uint64 internal immutable i_remoteChainSelector = 9876; + + address internal constant FINANCE = address(0x00000fffffffffffffffffffff); + address internal constant OWNER = address(0x00000078772732723782873283); + address internal constant STRANGER = address(0x00000999999911111111222222); + + function setUp() public virtual { + s_l1Token = new ERC20("l1", "L1"); + s_l2Token = new ERC20("l2", "L2"); + s_otherToken = new ERC20("other", "OTHER"); + + s_l1Weth = new WETH9(); + s_l2Weth = new WETH9(); + + vm.startPrank(OWNER); + + vm.label(FINANCE, "FINANCE"); + vm.label(OWNER, "OWNER"); + vm.label(STRANGER, "STRANGER"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol new file mode 100644 index 0000000..8afea2d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; + +import {ArbitrumL1BridgeAdapter, IOutbox} from "../../bridge-adapters/ArbitrumL1BridgeAdapter.sol"; +import "forge-std/Test.sol"; + +import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; +import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +//contract ArbitrumL1BridgeAdapterSetup is Test { +// uint256 internal mainnetFork; +// uint256 internal arbitrumFork; +// +// string internal constant MAINNET_RPC_URL = ""; +// +// address internal constant L1_GATEWAY_ROUTER = 0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef; +// address internal constant L1_ERC20_GATEWAY = 0xa3A7B6F88361F48403514059F1F16C8E78d60EeC; +// address internal constant L1_INBOX = 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f; +// // inbox 0x5aED5f8A1e3607476F1f81c3d8fe126deB0aFE94? +// address internal constant L1_OUTBOX = 0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840; +// +// IERC20 internal constant L1_LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); +// IWrappedNative internal constant L1_WRAPPED_NATIVE = IWrappedNative(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); +// +// address internal constant L2_GATEWAY_ROUTER = 0x5288c571Fd7aD117beA99bF60FE0846C4E84F933; +// address internal constant L2_ETH_WITHDRAWAL_PRECOMPILE = 0x0000000000000000000000000000000000000064; +// +// IERC20 internal constant L2_LINK = IERC20(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4); +// IWrappedNative internal constant L2_WRAPPED_NATIVE = IWrappedNative(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); +// +// ArbitrumL1BridgeAdapter internal s_l1BridgeAdapter; +// +// uint256 internal constant TOKEN_BALANCE = 10e18; +// address internal constant OWNER = address(0xdead); +// +// function setUp() public { +// vm.startPrank(OWNER); +// +// mainnetFork = vm.createFork(MAINNET_RPC_URL); +// vm.selectFork(mainnetFork); +// +// s_l1BridgeAdapter = new ArbitrumL1BridgeAdapter( +// IL1GatewayRouter(L1_GATEWAY_ROUTER), +// IOutbox(L1_OUTBOX), +// L1_ERC20_GATEWAY +// ); +// +// deal(address(L1_LINK), OWNER, TOKEN_BALANCE); +// deal(address(L1_WRAPPED_NATIVE), OWNER, TOKEN_BALANCE); +// +// vm.label(OWNER, "Owner"); +// vm.label(L1_GATEWAY_ROUTER, "L1GatewayRouter"); +// vm.label(L1_ERC20_GATEWAY, "L1 ERC20 Gateway"); +// } +//} +// +//contract ArbitrumL1BridgeAdapter_sendERC20 is ArbitrumL1BridgeAdapterSetup { +// event TransferRouted(address indexed token, address indexed _userFrom, address indexed _userTo, address gateway); +// +// function test_sendERC20Success() public { +// L1_LINK.approve(address(s_l1BridgeAdapter), TOKEN_BALANCE); +// +// vm.expectEmit(); +// emit TransferRouted(address(L1_LINK), address(s_l1BridgeAdapter), OWNER, L1_ERC20_GATEWAY); +// +// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * +// s_l1BridgeAdapter.GAS_PRICE_BID() + +// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); +// +// s_l1BridgeAdapter.sendERC20{value: expectedCost}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); +// } +// +// function test_BridgeFeeTooLowReverts() public { +// L1_LINK.approve(address(s_l1BridgeAdapter), TOKEN_BALANCE); +// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * +// s_l1BridgeAdapter.GAS_PRICE_BID() + +// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); +// +// vm.expectRevert( +// abi.encodeWithSelector(ArbitrumL1BridgeAdapter.InsufficientEthValue.selector, expectedCost, expectedCost - 1) +// ); +// +// s_l1BridgeAdapter.sendERC20{value: expectedCost - 1}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); +// } +// +// function test_noApprovalReverts() public { +// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * +// s_l1BridgeAdapter.GAS_PRICE_BID() + +// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); +// +// vm.expectRevert("SafeERC20: low-level call failed"); +// +// s_l1BridgeAdapter.sendERC20{value: expectedCost}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); +// } +//} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol new file mode 100644 index 0000000..e34ff04 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; + +import {ArbitrumL2BridgeAdapter, IL2GatewayRouter} from "../../bridge-adapters/ArbitrumL2BridgeAdapter.sol"; +import "forge-std/Test.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +//contract ArbitrumL2BridgeAdapterSetup is Test { +// uint256 internal arbitrumFork; +// +// string internal constant ARBITRUM_RPC_URL = ""; +// +// address internal constant L2_GATEWAY_ROUTER = 0x5288c571Fd7aD117beA99bF60FE0846C4E84F933; +// address internal constant L2_ETH_WITHDRAWAL_PRECOMPILE = 0x0000000000000000000000000000000000000064; +// +// IERC20 internal constant L1_LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); +// IERC20 internal constant L2_LINK = IERC20(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4); +// IWrappedNative internal constant L2_WRAPPED_NATIVE = IWrappedNative(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); +// +// uint256 internal constant TOKEN_BALANCE = 10e18; +// address internal constant OWNER = address(0xdead); +// +// ArbitrumL2BridgeAdapter internal s_l2BridgeAdapter; +// +// function setUp() public { +// vm.startPrank(OWNER); +// +// arbitrumFork = vm.createFork(ARBITRUM_RPC_URL); +// +// vm.selectFork(arbitrumFork); +// s_l2BridgeAdapter = new ArbitrumL2BridgeAdapter(IL2GatewayRouter(L2_GATEWAY_ROUTER)); +// deal(address(L2_LINK), OWNER, TOKEN_BALANCE); +// deal(address(L2_WRAPPED_NATIVE), OWNER, TOKEN_BALANCE); +// +// vm.label(OWNER, "Owner"); +// vm.label(L2_GATEWAY_ROUTER, "L2GatewayRouterProxy"); +// vm.label(0xe80eb0238029333e368e0bDDB7acDf1b9cb28278, "L2GatewayRouter"); +// vm.label(L2_ETH_WITHDRAWAL_PRECOMPILE, "Precompile: ArbSys"); +// } +//} +// +//contract ArbitrumL2BridgeAdapter_sendERC20 is ArbitrumL2BridgeAdapterSetup { +// function test_sendERC20Success() public { +// L2_LINK.approve(address(s_l2BridgeAdapter), TOKEN_BALANCE); +// +// s_l2BridgeAdapter.sendERC20(address(L1_LINK), address(L2_LINK), OWNER, TOKEN_BALANCE); +// } +//} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol new file mode 100644 index 0000000..cface1d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import "forge-std/Test.sol"; + +import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; +import {WETH9} from "../../../ccip/test/WETH9.sol"; +import {OptimismL1BridgeAdapter} from "../../bridge-adapters/OptimismL1BridgeAdapter.sol"; +import {Types} from "../../interfaces/optimism/Types.sol"; +import {IOptimismPortal} from "../../interfaces/optimism/IOptimismPortal.sol"; + +import {IL1StandardBridge} from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract OptimismL1BridgeAdapterSetup is Test { + // addresses below are fake + address internal constant L1_STANDARD_BRIDGE = address(1234); + address internal constant OP_PORTAL = address(4567); + address internal constant OWNER = address(0xdead); + + OptimismL1BridgeAdapter internal s_adapter; + + function setUp() public { + vm.startPrank(OWNER); + + // deploy wrapped native + WETH9 weth = new WETH9(); + + // deploy bridge adapter + s_adapter = new OptimismL1BridgeAdapter( + IL1StandardBridge(L1_STANDARD_BRIDGE), + IWrappedNative(address(weth)), + IOptimismPortal(OP_PORTAL) + ); + } +} + +contract OptimismL1BridgeAdapter_finalizeWithdrawERC20 is OptimismL1BridgeAdapterSetup { + function testfinalizeWithdrawERC20proveWithdrawalSuccess() public { + // prepare payload + OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload memory provePayload = OptimismL1BridgeAdapter + .OptimismProveWithdrawalPayload({ + withdrawalTransaction: Types.WithdrawalTransaction({ + nonce: 1, + sender: address(0xdead), + target: address(0xbeef), + value: 1234, + gasLimit: 4567, + data: hex"deadbeef" + }), + l2OutputIndex: 1234, + outputRootProof: Types.OutputRootProof({ + version: bytes32(0), + stateRoot: bytes32(uint256(500)), + messagePasserStorageRoot: bytes32(uint256(600)), + latestBlockhash: bytes32(uint256(700)) + }), + withdrawalProof: new bytes[](0) + }); + OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload; + payload.action = OptimismL1BridgeAdapter.FinalizationAction.ProveWithdrawal; + payload.data = abi.encode(provePayload); + + bytes memory encodedPayload = abi.encode(payload); + + // mock out call to optimism portal + vm.mockCall( + OP_PORTAL, + abi.encodeWithSelector( + IOptimismPortal.proveWithdrawalTransaction.selector, + provePayload.withdrawalTransaction, + provePayload.l2OutputIndex, + provePayload.outputRootProof, + provePayload.withdrawalProof + ), + "" + ); + + // call finalizeWithdrawERC20 + s_adapter.finalizeWithdrawERC20(address(0), address(0), encodedPayload); + } + + function testfinalizeWithdrawERC20FinalizeSuccess() public { + // prepare payload + OptimismL1BridgeAdapter.OptimismFinalizationPayload memory finalizePayload = OptimismL1BridgeAdapter + .OptimismFinalizationPayload({ + withdrawalTransaction: Types.WithdrawalTransaction({ + nonce: 1, + sender: address(0xdead), + target: address(0xbeef), + value: 1234, + gasLimit: 4567, + data: hex"deadbeef" + }) + }); + OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload; + payload.action = OptimismL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal; + payload.data = abi.encode(finalizePayload); + + bytes memory encodedPayload = abi.encode(payload); + + // mock out call to optimism portal + vm.mockCall( + OP_PORTAL, + abi.encodeWithSelector( + IOptimismPortal.finalizeWithdrawalTransaction.selector, + finalizePayload.withdrawalTransaction + ), + "" + ); + + // call finalizeWithdrawERC20 + s_adapter.finalizeWithdrawERC20(address(0), address(0), encodedPayload); + } + + function testFinalizeWithdrawERC20Reverts() public { + // case 1: badly encoded payload + bytes memory payload = abi.encode(1, 2, 3); + vm.expectRevert(); + s_adapter.finalizeWithdrawERC20(address(0), address(0), payload); + + // case 2: invalid action + // can't prepare the payload in solidity + payload = hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"; + vm.expectRevert(); + s_adapter.finalizeWithdrawERC20(address(0), address(0), payload); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol new file mode 100644 index 0000000..9b4654a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ILiquidityContainer} from "../../interfaces/ILiquidityContainer.sol"; + +import {LiquidityManager} from "../../LiquidityManager.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract LiquidityManagerHelper is LiquidityManager { + constructor( + IERC20 token, + uint64 localChainSelector, + ILiquidityContainer localLiquidityContainer, + uint256 targetTokens, + address finance + ) LiquidityManager(token, localChainSelector, localLiquidityContainer, targetTokens, finance) {} + + function report(bytes calldata rep, uint64 ocrSeqNum) external { + _report(rep, ocrSeqNum); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol new file mode 100644 index 0000000..b2cd2ef --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {OCR3Base} from "../../ocr/OCR3Base.sol"; + +contract OCR3Helper is OCR3Base { + function configDigestFromConfigData( + uint256 chainSelector, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) public pure returns (bytes32) { + return + _configDigestFromConfigData( + chainSelector, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + } + + function _report(bytes calldata report, uint64 sequenceNumber) internal override {} + + function typeAndVersion() public pure override returns (string memory) { + return "OCR3BaseHelper 1.0.0"; + } + + function setLatestSeqNum(uint64 newSeqNum) external { + s_latestSequenceNumber = newSeqNum; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol new file mode 100644 index 0000000..ff5e21f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {ILiquidityManager} from "../../interfaces/ILiquidityManager.sol"; + +/// @dev this is needed to generate the types to help encode the report offchain +abstract contract ReportEncoder is ILiquidityManager { + /// @dev exposed so that we can encode the report for OCR offchain + function exposeForEncoding(ILiquidityManager.LiquidityInstructions memory instructions) public pure {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol new file mode 100644 index 0000000..f51c60f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol @@ -0,0 +1,191 @@ +// SPDX-License-Identifier: BUSL-1.1 +// solhint-disable one-contract-per-file +pragma solidity ^0.8.0; + +import {IBridgeAdapter} from "../../interfaces/IBridge.sol"; +import {ILiquidityContainer} from "../../interfaces/ILiquidityContainer.sol"; +import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/// @notice Mock multiple-stage finalization bridge adapter implementation. +/// @dev Funds are only made available after both the prove and finalization steps are completed. +/// Sends the L1 tokens from the msg sender to address(this). +contract MockL1BridgeAdapter is IBridgeAdapter, ILiquidityContainer { + using SafeERC20 for IERC20; + + error InsufficientLiquidity(); + error NonceAlreadyUsed(uint256 nonce); + error InvalidFinalizationAction(); + error NonceNotProven(uint256 nonce); + error NativeSendFailed(); + + /// @notice Payload to "prove" the withdrawal. + /// @dev This is just a mock setup, there's no real proving. This is so that + /// we can test the multi-step finalization code path. + /// @param nonce the nonce emitted on the remote chain. + struct ProvePayload { + uint256 nonce; + } + + /// @notice Payload to "finalize" the withdrawal. + /// @dev This is just a mock setup, there's no real finalization. This is so that + /// we can test the multi-step finalization code path. + /// @param nonce the nonce emitted on the remote chain. + struct FinalizePayload { + uint256 nonce; + uint256 amount; + } + + /// @notice The finalization action to take. + /// @dev This emulates Optimism's two-step withdrawal process. + enum FinalizationAction { + ProveWithdrawal, + FinalizeWithdrawal + } + + /// @notice The payload to use for the bridgeSpecificPayload in the finalizeWithdrawERC20 function. + struct Payload { + FinalizationAction action; + bytes data; + } + + IERC20 internal immutable i_token; + uint256 internal s_nonce = 1; + mapping(uint256 => bool) internal s_nonceProven; + mapping(uint256 => bool) internal s_nonceFinalized; + + /// @dev For test cases where we want to send pure native upon finalizeWithdrawERC20 being called. + /// This is to emulate the behavior of bridges that do not bridge wrapped native. + bool internal immutable i_holdNative; + + constructor(IERC20 token, bool holdNative) { + i_token = token; + i_holdNative = holdNative; + } + + /// @dev The receive function is needed for IWrappedNative.withdraw() to work. + receive() external payable {} + + /// @notice Simply transferFrom msg.sender the tokens that are to be bridged to address(this). + function sendERC20( + address localToken, + address /* remoteToken */, + address /* remoteReceiver */, + uint256 amount, + bytes calldata /* bridgeSpecificPayload */ + ) external payable override returns (bytes memory) { + IERC20(localToken).transferFrom(msg.sender, address(this), amount); + + // If the flag to hold native is set we assume that i_token points to a WETH contract + // and withdraw native. + // This way we can transfer the raw native back to the sender upon finalization. + if (i_holdNative) { + IWrappedNative(address(i_token)).withdraw(amount); + } + + bytes memory encodedNonce = abi.encode(s_nonce++); + return encodedNonce; + } + + function getBridgeFeeInNative() external pure returns (uint256) { + return 0; + } + + function provideLiquidity(uint256 amount) external { + i_token.safeTransferFrom(msg.sender, address(this), amount); + emit LiquidityAdded(msg.sender, amount); + } + + function withdrawLiquidity(uint256 amount) external { + if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); + i_token.safeTransfer(msg.sender, amount); + emit LiquidityRemoved(msg.sender, amount); + } + + /// @dev for easy encoding offchain + function encodeProvePayload(ProvePayload memory payload) external pure {} + + function encodeFinalizePayload(FinalizePayload memory payload) external pure {} + + function encodePayload(Payload memory payload) external pure {} + + /// @dev Test setup is trusted, so just transfer the tokens to the localReceiver, + /// which should be the local rebalancer. Infer the amount from the bridgeSpecificPayload. + /// Note that this means that this bridge adapter will need to have some tokens, + /// however this is ok in a test environment since we will have infinite tokens. + /// @param localReceiver the address to transfer the tokens to. + /// @param bridgeSpecificPayload the payload to use for the finalization or proving. + /// @return true if the transfer was successful, revert otherwise. + function finalizeWithdrawERC20( + address /* remoteSender */, + address localReceiver, + bytes calldata bridgeSpecificPayload + ) external override returns (bool) { + Payload memory payload = abi.decode(bridgeSpecificPayload, (Payload)); + if (payload.action == FinalizationAction.ProveWithdrawal) { + return _proveWithdrawal(payload); + } else if (payload.action == FinalizationAction.FinalizeWithdrawal) { + return _finalizeWithdrawal(payload, localReceiver); + } + revert InvalidFinalizationAction(); + } + + function _proveWithdrawal(Payload memory payload) internal returns (bool) { + ProvePayload memory provePayload = abi.decode(payload.data, (ProvePayload)); + if (s_nonceProven[provePayload.nonce]) revert NonceAlreadyUsed(provePayload.nonce); + s_nonceProven[provePayload.nonce] = true; + return false; + } + + function _finalizeWithdrawal(Payload memory payload, address localReceiver) internal returns (bool) { + FinalizePayload memory finalizePayload = abi.decode(payload.data, (FinalizePayload)); + if (!s_nonceProven[finalizePayload.nonce]) revert NonceNotProven(finalizePayload.nonce); + if (s_nonceFinalized[finalizePayload.nonce]) revert NonceAlreadyUsed(finalizePayload.nonce); + s_nonceFinalized[finalizePayload.nonce] = true; + // re-entrancy prevented by nonce checks above. + _transferTokens(finalizePayload.amount, localReceiver); + return true; + } + + function _transferTokens(uint256 amount, address localReceiver) internal { + if (i_holdNative) { + (bool success, ) = payable(localReceiver).call{value: amount}(""); + if (!success) { + revert NativeSendFailed(); + } + } else { + i_token.safeTransfer(localReceiver, amount); + } + } +} + +/// @notice Mock L2 Bridge adapter +/// @dev Sends the L2 tokens from the msg sender to address(this) +contract MockL2BridgeAdapter is IBridgeAdapter { + /// @notice Simply transferFrom msg.sender the tokens that are to be bridged. + function sendERC20( + address localToken, + address /* remoteToken */, + address /* recipient */, + uint256 amount, + bytes calldata /* bridgeSpecificPayload */ + ) external payable override returns (bytes memory) { + IERC20(localToken).transferFrom(msg.sender, address(this), amount); + return ""; + } + + function getBridgeFeeInNative() external pure returns (uint256) { + return 0; + } + + // No-op + function finalizeWithdrawERC20( + address /* remoteSender */, + address /* localReceiver */, + bytes calldata /* bridgeSpecificData */ + ) external pure override returns (bool) { + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol new file mode 100644 index 0000000..5e771f0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {OCR3Base} from "../../ocr/OCR3Base.sol"; + +// NoOpOCR3 is a mock implementation of the OCR3Base contract that does nothing +// This is so that we can generate gethwrappers for the contract and use the OCR3 ABI in +// Go code. +contract NoOpOCR3 is OCR3Base { + // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables + string public constant override typeAndVersion = "NoOpOCR3 1.0.0"; + + constructor() OCR3Base() {} + + function _report(bytes calldata, uint64) internal override { + // do nothing + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol new file mode 100644 index 0000000..840e90f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {OCR3Setup} from "./OCR3Setup.t.sol"; +import {OCR3Base} from "../../ocr/OCR3Base.sol"; +import {OCR3Helper} from "../helpers/OCR3Helper.sol"; + +contract OCR3BaseSetup is OCR3Setup { + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + OCR3Helper internal s_OCR3Base; + + bytes32[] internal s_rs; + bytes32[] internal s_ss; + bytes32 internal s_rawVs; + + uint40 internal s_latestEpochAndRound; + + function setUp() public virtual override { + OCR3Setup.setUp(); + s_OCR3Base = new OCR3Helper(); + + bytes32 testReportDigest = getTestReportDigest(); + + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](2); + uint8[] memory vs = new uint8[](2); + + // Calculate signatures + (vs[0], rs[0], ss[0]) = vm.sign(PRIVATE0, testReportDigest); + (vs[1], rs[1], ss[1]) = vm.sign(PRIVATE1, testReportDigest); + + s_rs = rs; + s_ss = ss; + s_rawVs = bytes32(bytes1(vs[0] - 27)) | (bytes32(bytes1(vs[1] - 27)) >> 8); + } + + function getBasicConfigDigest(uint8 f, uint64 currentConfigCount) internal view returns (bytes32) { + bytes memory configBytes = abi.encode(""); + return + s_OCR3Base.configDigestFromConfigData( + block.chainid, + address(s_OCR3Base), + currentConfigCount + 1, + s_valid_signers, + s_valid_transmitters, + f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + } + + function getTestReportDigest() internal view returns (bytes32) { + bytes32 configDigest = getBasicConfigDigest(s_f, 0); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + return keccak256(abi.encodePacked(keccak256(REPORT), reportContext)); + } + + function getBasicConfigDigest( + address contractAddress, + uint8 f, + uint64 currentConfigCount, + bytes memory onchainConfig + ) internal view returns (bytes32) { + return + s_OCR3Base.configDigestFromConfigData( + block.chainid, + contractAddress, + currentConfigCount + 1, + s_valid_signers, + s_valid_transmitters, + f, + onchainConfig, + s_offchainConfigVersion, + abi.encode("") + ); + } +} + +contract OCR3Base_transmit is OCR3BaseSetup { + bytes32 internal s_configDigest; + + function setUp() public virtual override { + OCR3BaseSetup.setUp(); + bytes memory configBytes = abi.encode(""); + + s_configDigest = getBasicConfigDigest(s_f, 0); + s_OCR3Base.setOCR3Config( + s_valid_signers, + s_valid_transmitters, + s_f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + } + + function testTransmit2SignersSuccess_gas() public { + vm.pauseGasMetering(); + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + + vm.startPrank(s_valid_transmitters[0]); + vm.resumeGasMetering(); + s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); + } + + // Reverts + + function testNonIncreasingSequenceNumberReverts() public { + bytes32[3] memory reportContext = [s_configDigest, bytes32(uint256(0)) /* sequence number */, s_configDigest]; + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.NonIncreasingSequenceNumber.selector, 0, 0)); + s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); + } + + function testForkedChainReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + + uint256 chain1 = block.chainid; + uint256 chain2 = chain1 + 1; + vm.chainId(chain2); + vm.expectRevert(abi.encodeWithSelector(OCR3Base.ForkedChain.selector, chain1, chain2)); + vm.startPrank(s_valid_transmitters[0]); + s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); + } + + function testWrongNumberOfSignaturesReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + + vm.expectRevert(OCR3Base.WrongNumberOfSignatures.selector); + s_OCR3Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); + } + + function testConfigDigestMismatchReverts() public { + bytes32 configDigest; + bytes32[3] memory reportContext = [configDigest, bytes32(uint256(1)) /* sequence number */, configDigest]; + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.ConfigDigestMismatch.selector, s_configDigest, configDigest)); + s_OCR3Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); + } + + function testSignatureOutOfRegistrationReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](1); + + vm.expectRevert(OCR3Base.SignaturesOutOfRegistration.selector); + s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); + } + + function testUnAuthorizedTransmitterReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + bytes32[] memory rs = new bytes32[](2); + bytes32[] memory ss = new bytes32[](2); + + vm.expectRevert(OCR3Base.UnauthorizedTransmitter.selector); + s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); + } + + function testNonUniqueSignatureReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + bytes32[] memory rs = s_rs; + bytes32[] memory ss = s_ss; + + rs[1] = rs[0]; + ss[1] = ss[0]; + // Need to reset the rawVs to be valid + bytes32 rawVs = bytes32(bytes1(uint8(28) - 27)) | (bytes32(bytes1(uint8(28) - 27)) >> 8); + + vm.startPrank(s_valid_transmitters[0]); + vm.expectRevert(OCR3Base.NonUniqueSignatures.selector); + s_OCR3Base.transmit(reportContext, REPORT, rs, ss, rawVs); + } + + function testUnauthorizedSignerReverts() public { + bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; + bytes32[] memory rs = new bytes32[](2); + rs[0] = s_configDigest; + bytes32[] memory ss = rs; + + vm.startPrank(s_valid_transmitters[0]); + vm.expectRevert(OCR3Base.UnauthorizedSigner.selector); + s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); + } +} + +contract OCR3Base_setOCR3Config is OCR3BaseSetup { + function testSetConfigSuccess() public { + vm.pauseGasMetering(); + bytes memory configBytes = abi.encode(""); + uint32 configCount = 0; + + bytes32 configDigest = getBasicConfigDigest(s_f, configCount++); + + address[] memory transmitters = s_OCR3Base.getTransmitters(); + assertEq(0, transmitters.length); + + s_OCR3Base.setLatestSeqNum(3); + uint64 seqNum = s_OCR3Base.latestSequenceNumber(); + assertEq(seqNum, 3); + + vm.expectEmit(); + emit ConfigSet( + 0, + configDigest, + configCount, + s_valid_signers, + s_valid_transmitters, + s_f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + + s_OCR3Base.setOCR3Config( + s_valid_signers, + s_valid_transmitters, + s_f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + + transmitters = s_OCR3Base.getTransmitters(); + assertEq(s_valid_transmitters, transmitters); + + configDigest = getBasicConfigDigest(s_f, configCount++); + + seqNum = s_OCR3Base.latestSequenceNumber(); + assertEq(seqNum, 0); + + vm.expectEmit(); + emit ConfigSet( + uint32(block.number), + configDigest, + configCount, + s_valid_signers, + s_valid_transmitters, + s_f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + vm.resumeGasMetering(); + s_OCR3Base.setOCR3Config( + s_valid_signers, + s_valid_transmitters, + s_f, + configBytes, + s_offchainConfigVersion, + configBytes + ); + } + + // Reverts + function testRepeatAddressReverts() public { + address[] memory signers = new address[](10); + signers[0] = address(1245678); + address[] memory transmitters = new address[](10); + transmitters[0] = signers[0]; + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "repeated transmitter address")); + s_OCR3Base.setOCR3Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); + } + + function testSignerCannotBeZeroAddressReverts() public { + uint256 f = 1; + address[] memory signers = new address[](3 * f + 1); + address[] memory transmitters = new address[](3 * f + 1); + for (uint160 i = 0; i < 3 * f + 1; ++i) { + signers[i] = address(i + 1); + transmitters[i] = address(i + 1000); + } + + signers[0] = address(0); + + vm.expectRevert(OCR3Base.OracleCannotBeZeroAddress.selector); + s_OCR3Base.setOCR3Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); + } + + function testTransmitterCannotBeZeroAddressReverts() public { + uint256 f = 1; + address[] memory signers = new address[](3 * f + 1); + address[] memory transmitters = new address[](3 * f + 1); + for (uint160 i = 0; i < 3 * f + 1; ++i) { + signers[i] = address(i + 1); + transmitters[i] = address(i + 1000); + } + + transmitters[0] = address(0); + + vm.expectRevert(OCR3Base.OracleCannotBeZeroAddress.selector); + s_OCR3Base.setOCR3Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); + } + + function testOracleOutOfRegisterReverts() public { + address[] memory signers = new address[](10); + address[] memory transmitters = new address[](0); + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "oracle addresses out of registration")); + s_OCR3Base.setOCR3Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); + } + + function testFTooHighReverts() public { + address[] memory signers = new address[](0); + uint8 f = 1; + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "faulty-oracle f too high")); + s_OCR3Base.setOCR3Config(signers, new address[](0), f, abi.encode(""), 100, abi.encode("")); + } + + function testFMustBePositiveReverts() public { + uint8 f = 0; + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "f must be positive")); + s_OCR3Base.setOCR3Config(new address[](0), new address[](0), f, abi.encode(""), 100, abi.encode("")); + } + + function testTooManySignersReverts() public { + address[] memory signers = new address[](32); + + vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "too many signers")); + s_OCR3Base.setOCR3Config(signers, new address[](0), 0, abi.encode(""), 100, abi.encode("")); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol new file mode 100644 index 0000000..ee60c58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {LiquidityManagerBaseTest} from "../LiquidityManagerBaseTest.t.sol"; + +contract OCR3Setup is LiquidityManagerBaseTest { + // Signer private keys used for these test + uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; + uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; + uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; + uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; + + address[] internal s_valid_signers; + address[] internal s_valid_transmitters; + + uint64 internal constant s_offchainConfigVersion = 3; + uint8 internal constant s_f = 1; + bytes internal constant REPORT = abi.encode("testReport"); + + function setUp() public virtual override { + LiquidityManagerBaseTest.setUp(); + + s_valid_transmitters = new address[](4); + for (uint160 i = 0; i < 4; ++i) { + s_valid_transmitters[i] = address(4 + i); + } + + s_valid_signers = new address[](4); + s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 + s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 + s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b + s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol new file mode 100644 index 0000000..478afa9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +interface IConfigurator { + /// @notice This event is emitted whenever a new configuration is set for a feed. It triggers a new run of the offchain reporting protocol. + event ConfigSet( + bytes32 indexed configId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + function setConfig( + bytes32 configId, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol new file mode 100644 index 0000000..c1b59a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/* + * @title ByteUtil + * @author Michael Fletcher + * @notice Byte utility functions for efficiently parsing and manipulating packed byte data + */ +library ByteUtil { + // Error message when an offset is out of bounds + error MalformedData(); + + /** + * @dev Reads a uint256 from a position within a byte array. + * @param data Byte array to read from. + * @param offset Position to start reading from. + * @return result The uint256 read from the byte array. + */ + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _readUint256(bytes memory data, uint256 offset) internal pure returns (uint256 result) { + //bounds check + if (offset + 32 > data.length) revert MalformedData(); + + assembly { + //load 32 byte word accounting for 32 bit length and offset + result := mload(add(add(data, 32), offset)) + } + } + + /** + * @dev Reads a uint192 from a position within a byte array. + * @param data Byte array to read from. + * @param offset Position to start reading from. + * @return result The uint192 read from the byte array. + */ + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _readUint192(bytes memory data, uint256 offset) internal pure returns (uint256 result) { + //bounds check + if (offset + 24 > data.length) revert MalformedData(); + + assembly { + //load 32 byte word accounting for 32 bit length and offset + result := mload(add(add(data, 32), offset)) + //shift the result right 64 bits + result := shr(64, result) + } + } + + /** + * @dev Reads a uint32 from a position within a byte array. + * @param data Byte array to read from. + * @param offset Position to start reading from. + * @return result The uint32 read from the byte array. + */ + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _readUint32(bytes memory data, uint256 offset) internal pure returns (uint256 result) { + //bounds check + if (offset + 4 > data.length) revert MalformedData(); + + assembly { + //load 32 byte word accounting for 32 bit length and offset + result := mload(add(add(data, 32), offset)) + //shift the result right 224 bits + result := shr(224, result) + } + } + + /** + * @dev Reads an address from a position within a byte array. + * @param data Byte array to read from. + * @param offset Position to start reading from. + * @return result The uint32 read from the byte array. + */ + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _readAddress(bytes memory data, uint256 offset) internal pure returns (address result) { + //bounds check + if (offset + 20 > data.length) revert MalformedData(); + + assembly { + //load 32 byte word accounting for 32 bit length and offset + let word := mload(add(add(data, 32), offset)) + //address is the last 20 bytes of the word, so shift right + result := shr(96, word) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol new file mode 100644 index 0000000..23418bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +/* + * @title Common + * @author Michael Fletcher + * @notice Common functions and structs + */ +library Common { + // @notice The asset struct to hold the address of an asset and amount + struct Asset { + address assetAddress; + uint256 amount; + } + + // @notice Struct to hold the address and its associated weight + struct AddressAndWeight { + address addr; + uint64 weight; + } + + /** + * @notice Checks if an array of AddressAndWeight has duplicate addresses + * @param recipients The array of AddressAndWeight to check + * @return bool True if there are duplicates, false otherwise + */ + function _hasDuplicateAddresses(address[] memory recipients) internal pure returns (bool) { + for (uint256 i = 0; i < recipients.length; ) { + for (uint256 j = i + 1; j < recipients.length; ) { + if (recipients[i] == recipients[j]) { + return true; + } + unchecked { + ++j; + } + } + unchecked { + ++i; + } + } + return false; + } + + /** + * @notice Checks if an array of AddressAndWeight has duplicate addresses + * @param recipients The array of AddressAndWeight to check + * @return bool True if there are duplicates, false otherwise + */ + function _hasDuplicateAddresses(Common.AddressAndWeight[] memory recipients) internal pure returns (bool) { + for (uint256 i = 0; i < recipients.length; ) { + for (uint256 j = i + 1; j < recipients.length; ) { + if (recipients[i].addr == recipients[j].addr) { + return true; + } + unchecked { + ++j; + } + } + unchecked { + ++i; + } + } + return false; + } + + /** + * @notice sorts a list of addresses numerically + * @param arr The array of addresses to sort + * @param left the start index + * @param right the end index + */ + function _quickSort(address[] memory arr, int256 left, int256 right) internal pure { + int256 i = left; + int256 j = right; + if (i == j) return; + address pivot = arr[uint256(left + (right - left) / 2)]; + while (i <= j) { + while (uint160(arr[uint256(i)]) < uint160(pivot)) i++; + while (uint160(pivot) < uint160(arr[uint256(j)])) j--; + if (i <= j) { + (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); + i++; + j--; + } + } + if (left < j) _quickSort(arr, left, j); + if (i < right) _quickSort(arr, i, right); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol new file mode 100644 index 0000000..8f11dab --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {ByteUtil} from "../ByteUtil.sol"; + +contract ByteUtilTest is Test { + using ByteUtil for bytes; + + bytes internal constant B_512 = + hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"; + bytes internal constant B_128 = hex"ffffffffffffffffffffffffffffffff"; + bytes internal constant B_16 = hex"ffff"; + bytes internal constant B_EMPTY = new bytes(0); + + bytes4 internal constant MALFORMED_ERROR_SELECTOR = bytes4(keccak256("MalformedData()")); + + function test_readUint256Max() public pure { + //read the first 32 bytes + uint256 result = B_512._readUint256(0); + + //the result should be the max value of a uint256 + assertEq(result, type(uint256).max); + } + + function test_readUint192Max() public pure { + //read the first 24 bytes + uint256 result = B_512._readUint192(0); + + //the result should be the max value of a uint192 + assertEq(result, type(uint192).max); + } + + function test_readUint32Max() public pure { + //read the first 4 bytes + uint256 result = B_512._readUint32(0); + + //the result should be the max value of a uint32 + assertEq(result, type(uint32).max); + } + + function test_readUint256Min() public pure { + //read the second 32 bytes + uint256 result = B_512._readUint256(32); + + //the result should be the min value of a uint256 + assertEq(result, type(uint256).min); + } + + function test_readUint192Min() public pure { + //read the second 24 bytes + uint256 result = B_512._readUint192(32); + + //the result should be the min value of a uint192 + assertEq(result, type(uint192).min); + } + + function test_readUint32Min() public pure { + //read the second 4 bytes + uint256 result = B_512._readUint32(32); + + //the result should be the min value of a uint32 + assertEq(result, type(uint32).min); + } + + function test_readUint256MultiWord() public pure { + //read the first 32 bytes + uint256 result = B_512._readUint256(31); + + //the result should be the last byte from the first word (ff), and 31 bytes from the second word (0000) (0xFF...0000) + assertEq(result, type(uint256).max << 248); + } + + function test_readUint192MultiWord() public pure { + //read the first 24 bytes + uint256 result = B_512._readUint192(31); + + //the result should be the last byte from the first word (ff), and 23 bytes from the second word (0000) (0xFF...0000) + assertEq(result, type(uint192).max << 184); + } + + function test_readUint32MultiWord() public pure { + //read the first 4 bytes + uint256 result = B_512._readUint32(31); + + //the result should be the last byte from the first word (ff), and 3 bytes from the second word (0000) (0xFF...0000) + assertEq(result, type(uint32).max << 24); + } + + function test_readUint256WithNotEnoughBytes() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //try and read 32 bytes from a 16 byte number + B_128._readUint256(0); + } + + function test_readUint192WithNotEnoughBytes() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //try and read 24 bytes from a 16 byte number + B_128._readUint192(0); + } + + function test_readUint32WithNotEnoughBytes() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //try and read 4 bytes from a 2 byte number + B_16._readUint32(0); + } + + function test_readUint256WithEmptyArray() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //read 20 bytes from an empty array + B_EMPTY._readUint256(0); + } + + function test_readUint192WithEmptyArray() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //read 20 bytes from an empty array + B_EMPTY._readUint192(0); + } + + function test_readUint32WithEmptyArray() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //read 20 bytes from an empty array + B_EMPTY._readUint32(0); + } + + function test_readAddress() public pure { + //read the first 20 bytes + address result = B_512._readAddress(0); + + //the result should be the max value of a uint256 + assertEq(result, address(type(uint160).max)); + } + + function test_readZeroAddress() public pure { + //read the first 32 bytes after the first word + address result = B_512._readAddress(32); + + //the result should be 0x00...0 + assertEq(result, address(type(uint160).min)); + } + + function test_readAddressMultiWord() public pure { + //read the first 20 bytes after byte 13 + address result = B_512._readAddress(13); + + //the result should be the value last 19 bytes of the first word (ffff..) and the first byte of the second word (00) (0xFFFF..00) + assertEq(result, address(type(uint160).max << 8)); + } + + function test_readAddressWithNotEnoughBytes() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //read 20 bytes from a 16 byte array + B_128._readAddress(0); + } + + function test_readAddressWithEmptyArray() public { + //should revert if there's not enough bytes + vm.expectRevert(MALFORMED_ERROR_SELECTOR); + + //read the first 20 bytes of an empty array + B_EMPTY._readAddress(0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol new file mode 100644 index 0000000..44f550e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IFeeManager} from "./interfaces/IFeeManager.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; +import {IRewardManager} from "./interfaces/IRewardManager.sol"; +import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; + +/** + * @title FeeManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract is used for the handling of fees required for users verifying reports. + */ +contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface { + using SafeERC20 for IERC20; + + /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] + mapping(address => mapping(bytes32 => mapping(address => uint256))) public s_subscriberDiscounts; + + /// @notice keep track of any subsidised link that is owed to the reward manager. + mapping(bytes32 => uint256) public s_linkDeficit; + + /// @notice the total discount that can be applied to a fee, 1e18 = 100% discount + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + /// @notice the LINK token address + address public immutable i_linkAddress; + + /// @notice the native token address + address public immutable i_nativeAddress; + + /// @notice the proxy address + address public immutable i_proxyAddress; + + /// @notice the reward manager address + IRewardManager public immutable i_rewardManager; + + // @notice the mask to apply to get the report version + bytes32 private constant REPORT_VERSION_MASK = 0xffff000000000000000000000000000000000000000000000000000000000000; + + // @notice the different report versions + bytes32 private constant REPORT_V1 = 0x0001000000000000000000000000000000000000000000000000000000000000; + + /// @notice the surcharge fee to be paid if paying in native + uint256 public s_nativeSurcharge; + + /// @notice the error thrown if the discount or surcharge is invalid + error InvalidSurcharge(); + + /// @notice the error thrown if the discount is invalid + error InvalidDiscount(); + + /// @notice the error thrown if the address is invalid + error InvalidAddress(); + + /// @notice thrown if msg.value is supplied with a bad quote + error InvalidDeposit(); + + /// @notice thrown if a report has expired + error ExpiredReport(); + + /// @notice thrown if a report has no quote + error InvalidQuote(); + + // @notice thrown when the caller is not authorized + error Unauthorized(); + + // @notice thrown when trying to clear a zero deficit + error ZeroDeficit(); + + /// @notice thrown when trying to pay an address that cannot except funds + error InvalidReceivingAddress(); + + /// @notice Emitted whenever a subscriber's discount is updated + /// @param subscriber address of the subscriber to update discounts for + /// @param feedId Feed ID for the discount + /// @param token Token address for the discount + /// @param discount Discount to apply, in relation to the PERCENTAGE_SCALAR + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + + /// @notice Emitted when updating the native surcharge + /// @param newSurcharge Surcharge amount to apply relative to PERCENTAGE_SCALAR + event NativeSurchargeUpdated(uint64 newSurcharge); + + /// @notice Emits when this contract does not have enough LINK to send to the reward manager when paying in native + /// @param rewards Config digest and link fees which could not be subsidised + event InsufficientLink(IRewardManager.FeePayment[] rewards); + + /// @notice Emitted when funds are withdrawn + /// @param adminAddress Address of the admin + /// @param recipient Address of the recipient + /// @param assetAddress Address of the asset withdrawn + /// @param quantity Amount of the asset withdrawn + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + + /// @notice Emits when a deficit has been cleared for a particular config digest + /// @param configDigest Config digest of the deficit cleared + /// @param linkQuantity Amount of LINK required to pay the deficit + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + + /// @notice Emits when a fee has been processed + /// @param configDigest Config digest of the fee processed + /// @param subscriber Address of the subscriber who paid the fee + /// @param fee Fee paid + /// @param reward Reward paid + /// @param appliedDiscount Discount applied to the fee + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscount + ); + + /** + * @notice Construct the FeeManager contract + * @param _linkAddress The address of the LINK token + * @param _nativeAddress The address of the wrapped ERC-20 version of the native token (represents fee in native or wrapped) + * @param _proxyAddress The address of the proxy contract + * @param _rewardManagerAddress The address of the reward manager contract + */ + constructor( + address _linkAddress, + address _nativeAddress, + address _proxyAddress, + address _rewardManagerAddress + ) ConfirmedOwner(msg.sender) { + if ( + _linkAddress == address(0) || + _nativeAddress == address(0) || + _proxyAddress == address(0) || + _rewardManagerAddress == address(0) + ) revert InvalidAddress(); + + i_linkAddress = _linkAddress; + i_nativeAddress = _nativeAddress; + i_proxyAddress = _proxyAddress; + i_rewardManager = IRewardManager(_rewardManagerAddress); + + IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); + } + + modifier onlyOwnerOrProxy() { + if (msg.sender != i_proxyAddress && msg.sender != owner()) revert Unauthorized(); + _; + } + + modifier onlyProxy() { + if (msg.sender != i_proxyAddress) revert Unauthorized(); + _; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "FeeManager 2.0.0"; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == this.processFee.selector || interfaceId == this.processFeeBulk.selector; + } + + /// @inheritdoc IVerifierFeeManager + function processFee( + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyProxy { + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( + payload, + parameterPayload, + subscriber + ); + + if (fee.amount == 0) { + _tryReturnChange(subscriber, msg.value); + return; + } + + IFeeManager.FeeAndReward[] memory feeAndReward = new IFeeManager.FeeAndReward[](1); + feeAndReward[0] = IFeeManager.FeeAndReward(bytes32(payload), fee, reward, appliedDiscount); + + if (fee.assetAddress == i_linkAddress) { + _handleFeesAndRewards(subscriber, feeAndReward, 1, 0); + } else { + _handleFeesAndRewards(subscriber, feeAndReward, 0, 1); + } + } + + /// @inheritdoc IVerifierFeeManager + function processFeeBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyProxy { + FeeAndReward[] memory feesAndRewards = new IFeeManager.FeeAndReward[](payloads.length); + + //keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees + uint256 numberOfLinkFees; + uint256 numberOfNativeFees; + + uint256 feesAndRewardsIndex; + for (uint256 i; i < payloads.length; ++i) { + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( + payloads[i], + parameterPayload, + subscriber + ); + + if (fee.amount != 0) { + feesAndRewards[feesAndRewardsIndex++] = IFeeManager.FeeAndReward( + bytes32(payloads[i]), + fee, + reward, + appliedDiscount + ); + + unchecked { + //keep track of some tallys to make downstream calculations more efficient + if (fee.assetAddress == i_linkAddress) { + ++numberOfLinkFees; + } else { + ++numberOfNativeFees; + } + } + } + } + + if (numberOfLinkFees != 0 || numberOfNativeFees != 0) { + _handleFeesAndRewards(subscriber, feesAndRewards, numberOfLinkFees, numberOfNativeFees); + } else { + _tryReturnChange(subscriber, msg.value); + } + } + + /// @inheritdoc IFeeManager + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) public view returns (Common.Asset memory, Common.Asset memory, uint256) { + Common.Asset memory fee; + Common.Asset memory reward; + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //the report needs to be a support version + bytes32 reportVersion = _getReportVersion(feedId); + + //version 1 of the reports don't require quotes, so the fee will be 0 + if (reportVersion == REPORT_V1) { + fee.assetAddress = i_nativeAddress; + reward.assetAddress = i_linkAddress; + return (fee, reward, 0); + } + + //verify the quote payload is a supported token + if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) { + revert InvalidQuote(); + } + + //decode the report depending on the version + uint256 linkQuantity; + uint256 nativeQuantity; + uint256 expiresAt; + (, , , nativeQuantity, linkQuantity, expiresAt) = abi.decode( + report, + (bytes32, uint32, uint32, uint192, uint192, uint32) + ); + + //read the timestamp bytes from the report data and verify it has not expired + if (expiresAt < block.timestamp) { + revert ExpiredReport(); + } + + //get the discount being applied + uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress]; + + //the reward is always set in LINK + reward.assetAddress = i_linkAddress; + reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + + //calculate either the LINK fee or native fee if it's within the report + if (quoteAddress == i_linkAddress) { + fee.assetAddress = i_linkAddress; + fee.amount = reward.amount; + } else { + uint256 surchargedFee = Math.ceilDiv(nativeQuantity * (PERCENTAGE_SCALAR + s_nativeSurcharge), PERCENTAGE_SCALAR); + + fee.assetAddress = i_nativeAddress; + fee.amount = Math.ceilDiv(surchargedFee * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + } + + //return the fee + return (fee, reward, discount); + } + + /// @inheritdoc IVerifierFeeManager + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external onlyOwnerOrProxy { + i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); + } + + /// @inheritdoc IFeeManager + function setNativeSurcharge(uint64 surcharge) external onlyOwner { + if (surcharge > PERCENTAGE_SCALAR) revert InvalidSurcharge(); + + s_nativeSurcharge = surcharge; + + emit NativeSurchargeUpdated(surcharge); + } + + /// @inheritdoc IFeeManager + function updateSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint64 discount + ) external onlyOwner { + //make sure the discount is not greater than the total discount that can be applied + if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); + //make sure the token is either LINK or native + if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); + + s_subscriberDiscounts[subscriber][feedId][token] = discount; + + emit SubscriberDiscountUpdated(subscriber, feedId, token, discount); + } + + /// @inheritdoc IFeeManager + function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { + //address 0 is used to withdraw native in the context of withdrawing + if (assetAddress == address(0)) { + (bool success, ) = payable(recipient).call{value: quantity}(""); + + if (!success) revert InvalidReceivingAddress(); + return; + } + + //withdraw the requested asset + IERC20(assetAddress).safeTransfer(recipient, quantity); + + //emit event when funds are withdrawn + emit Withdraw(msg.sender, recipient, assetAddress, uint192(quantity)); + } + + /// @inheritdoc IFeeManager + function linkAvailableForPayment() external view returns (uint256) { + //return the amount of LINK this contact has available to pay rewards + return IERC20(i_linkAddress).balanceOf(address(this)); + } + + /** + * @notice Gets the current version of the report that is encoded as the last two bytes of the feed + * @param feedId feed id to get the report version for + */ + function _getReportVersion(bytes32 feedId) internal pure returns (bytes32) { + return REPORT_VERSION_MASK & feedId; + } + + function _processFee( + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) internal view returns (Common.Asset memory, Common.Asset memory, uint256) { + if (subscriber == address(this)) revert InvalidAddress(); + + //decode the report from the payload + (, bytes memory report) = abi.decode(payload, (bytes32[3], bytes)); + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //v1 doesn't need a quote payload, so skip the decoding + address quote; + if (_getReportVersion(feedId) != REPORT_V1) { + //decode the quote from the bytes + (quote) = abi.decode(parameterPayload, (address)); + } + + //decode the fee, it will always be native or LINK + return getFeeAndReward(subscriber, report, quote); + } + + function _handleFeesAndRewards( + address subscriber, + FeeAndReward[] memory feesAndRewards, + uint256 numberOfLinkFees, + uint256 numberOfNativeFees + ) internal { + IRewardManager.FeePayment[] memory linkRewards = new IRewardManager.FeePayment[](numberOfLinkFees); + IRewardManager.FeePayment[] memory nativeFeeLinkRewards = new IRewardManager.FeePayment[](numberOfNativeFees); + + uint256 totalNativeFee; + uint256 totalNativeFeeLinkValue; + + uint256 linkRewardsIndex; + uint256 nativeFeeLinkRewardsIndex; + + uint256 totalNumberOfFees = numberOfLinkFees + numberOfNativeFees; + for (uint256 i; i < totalNumberOfFees; ++i) { + if (feesAndRewards[i].fee.assetAddress == i_linkAddress) { + linkRewards[linkRewardsIndex++] = IRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + } else { + nativeFeeLinkRewards[nativeFeeLinkRewardsIndex++] = IRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + totalNativeFee += feesAndRewards[i].fee.amount; + totalNativeFeeLinkValue += feesAndRewards[i].reward.amount; + } + + if (feesAndRewards[i].appliedDiscount != 0) { + emit DiscountApplied( + feesAndRewards[i].configDigest, + subscriber, + feesAndRewards[i].fee, + feesAndRewards[i].reward, + feesAndRewards[i].appliedDiscount + ); + } + } + + //keep track of change in case of any over payment + uint256 change; + + if (msg.value != 0) { + //there must be enough to cover the fee + if (totalNativeFee > msg.value) revert InvalidDeposit(); + + //wrap the amount required to pay the fee & approve as the subscriber paid in wrapped native + IWERC20(i_nativeAddress).deposit{value: totalNativeFee}(); + + unchecked { + //msg.value is always >= to fee.amount + change = msg.value - totalNativeFee; + } + } else { + if (totalNativeFee != 0) { + //subscriber has paid in wrapped native, so transfer the native to this contract + IERC20(i_nativeAddress).safeTransferFrom(subscriber, address(this), totalNativeFee); + } + } + + if (linkRewards.length != 0) { + i_rewardManager.onFeePaid(linkRewards, subscriber); + } + + if (nativeFeeLinkRewards.length != 0) { + //distribute subsidised fees paid in Native + if (totalNativeFeeLinkValue > IERC20(i_linkAddress).balanceOf(address(this))) { + // If not enough LINK on this contract to forward for rewards, tally the deficit to be paid by out-of-band LINK + for (uint256 i; i < nativeFeeLinkRewards.length; ++i) { + unchecked { + //we have previously tallied the fees, any overflows would have already reverted + s_linkDeficit[nativeFeeLinkRewards[i].poolId] += nativeFeeLinkRewards[i].amount; + } + } + + emit InsufficientLink(nativeFeeLinkRewards); + } else { + //distribute the fees + i_rewardManager.onFeePaid(nativeFeeLinkRewards, address(this)); + } + } + + // a refund may be needed if the payee has paid in excess of the fee + _tryReturnChange(subscriber, change); + } + + function _tryReturnChange(address subscriber, uint256 quantity) internal { + if (quantity != 0) { + payable(subscriber).transfer(quantity); + } + } + + /// @inheritdoc IFeeManager + function payLinkDeficit(bytes32 configDigest) external onlyOwner { + uint256 deficit = s_linkDeficit[configDigest]; + + if (deficit == 0) revert ZeroDeficit(); + + delete s_linkDeficit[configDigest]; + + IRewardManager.FeePayment[] memory deficitFeePayment = new IRewardManager.FeePayment[](1); + + deficitFeePayment[0] = IRewardManager.FeePayment(configDigest, uint192(deficit)); + + i_rewardManager.onFeePaid(deficitFeePayment, address(this)); + + emit LinkDeficitCleared(configDigest, deficit); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol new file mode 100644 index 0000000..49fef51 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IRewardManager} from "./interfaces/IRewardManager.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {Common} from "../libraries/Common.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title RewardManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. + */ +contract RewardManager is IRewardManager, ConfirmedOwner, TypeAndVersionInterface { + using SafeERC20 for IERC20; + + // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] + mapping(bytes32 => uint256) public s_totalRewardRecipientFees; + + // @dev The mapping of fee balances for each pot last time the recipient claimed: s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] + mapping(bytes32 => mapping(address => uint256)) public s_totalRewardRecipientFeesLastClaimedAmounts; + + // @dev The mapping of RewardRecipient weights for a particular poolId: s_rewardRecipientWeights[poolId][rewardRecipient]. + mapping(bytes32 => mapping(address => uint256)) public s_rewardRecipientWeights; + + // @dev Keep track of the reward recipient weights that have been set to prevent duplicates + mapping(bytes32 => bool) public s_rewardRecipientWeightsSet; + + // @dev Store a list of pool ids that have been registered, to make off chain lookups easier + bytes32[] public s_registeredPoolIds; + + // @dev The address for the LINK contract + address public immutable i_linkAddress; + + // The total weight of all RewardRecipients. 1e18 = 100% of the pool fees + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + // The fee manager address + address public s_feeManagerAddress; + + // @notice Thrown whenever the RewardRecipient weights are invalid + error InvalidWeights(); + + // @notice Thrown when any given address is invalid + error InvalidAddress(); + + // @notice Thrown when the pool id is invalid + error InvalidPoolId(); + + // @notice Thrown when the calling contract is not within the authorized contracts + error Unauthorized(); + + // @notice Thrown when getAvailableRewardPoolIds parameters are incorrectly set + error InvalidPoolLength(); + + // Events emitted upon state change + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newFeeManagerAddress); + event FeePaid(FeePayment[] payments, address payer); + + /** + * @notice Constructor + * @param linkAddress address of the wrapped LINK token + */ + constructor(address linkAddress) ConfirmedOwner(msg.sender) { + //ensure that the address ia not zero + if (linkAddress == address(0)) revert InvalidAddress(); + + i_linkAddress = linkAddress; + } + + // @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "RewardManager 1.1.0"; + } + + // @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == this.onFeePaid.selector; + } + + modifier onlyOwnerOrFeeManager() { + if (msg.sender != owner() && msg.sender != s_feeManagerAddress) revert Unauthorized(); + _; + } + + modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { + if (msg.sender != owner() && s_rewardRecipientWeights[poolId][msg.sender] == 0) revert Unauthorized(); + _; + } + + modifier onlyFeeManager() { + if (msg.sender != s_feeManagerAddress) revert Unauthorized(); + _; + } + + /// @inheritdoc IRewardManager + function onFeePaid(FeePayment[] calldata payments, address payer) external override onlyFeeManager { + uint256 totalFeeAmount; + for (uint256 i; i < payments.length; ++i) { + unchecked { + //the total amount for any ERC-20 asset cannot exceed 2^256 - 1 + //see https://github.com/OpenZeppelin/openzeppelin-contracts/blob/36bf1e46fa811f0f07d38eb9cfbc69a955f300ce/contracts/token/ERC20/ERC20.sol#L266 + //for example implementation. + s_totalRewardRecipientFees[payments[i].poolId] += payments[i].amount; + + //tally the total payable fees + totalFeeAmount += payments[i].amount; + } + } + + //transfer the fees to this contract + IERC20(i_linkAddress).safeTransferFrom(payer, address(this), totalFeeAmount); + + emit FeePaid(payments, payer); + } + + /// @inheritdoc IRewardManager + function claimRewards(bytes32[] memory poolIds) external override { + _claimRewards(msg.sender, poolIds); + } + + // wrapper impl for claimRewards + function _claimRewards(address recipient, bytes32[] memory poolIds) internal returns (uint256) { + //get the total amount claimable for this recipient + uint256 claimAmount; + + //loop and claim all the rewards in the poolId pot + for (uint256 i; i < poolIds.length; ++i) { + //get the poolId to be claimed + bytes32 poolId = poolIds[i]; + + //get the total fees for the pot + uint256 totalFeesInPot = s_totalRewardRecipientFees[poolId]; + + unchecked { + //avoid unnecessary storage reads if there's no fees in the pot + if (totalFeesInPot == 0) continue; + + //get the claimable amount for this recipient, this calculation will never exceed the amount in the pot + uint256 claimableAmount = totalFeesInPot - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient]; + + //calculate the recipients share of the fees, which is their weighted share of the difference between the last amount they claimed and the current amount in the pot. This can never be more than the total amount in existence + uint256 recipientShare = (claimableAmount * s_rewardRecipientWeights[poolId][recipient]) / PERCENTAGE_SCALAR; + + //if there's no fees to claim, continue as there's nothing to update + if (recipientShare == 0) continue; + + //keep track of the total amount claimable, this can never be more than the total amount in existence + claimAmount += recipientShare; + + //set the current total amount of fees in the pot as it's used to calculate future claims + s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] = totalFeesInPot; + + //emit event if the recipient has rewards to claim + emit RewardsClaimed(poolIds[i], recipient, uint192(recipientShare)); + } + } + + //check if there's any rewards to claim in the given poolId + if (claimAmount != 0) { + //transfer the reward to the recipient + IERC20(i_linkAddress).safeTransfer(recipient, claimAmount); + } + + return claimAmount; + } + + /// @inheritdoc IRewardManager + function setRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external override onlyOwnerOrFeeManager { + //revert if there are no recipients to set + if (rewardRecipientAndWeights.length == 0) revert InvalidAddress(); + + //check that the weights have not been previously set + if (s_rewardRecipientWeightsSet[poolId]) revert InvalidPoolId(); + + //keep track of the registered poolIds to make off chain lookups easier + s_registeredPoolIds.push(poolId); + + //keep track of which pools have had their reward recipients set + s_rewardRecipientWeightsSet[poolId] = true; + + //set the reward recipients, this will only be called once and contain the full set of RewardRecipients with a total weight of 100% + _setRewardRecipientWeights(poolId, rewardRecipientAndWeights, PERCENTAGE_SCALAR); + + emit RewardRecipientsUpdated(poolId, rewardRecipientAndWeights); + } + + function _setRewardRecipientWeights( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights, + uint256 expectedWeight + ) internal { + //we can't update the weights if it contains duplicates + if (Common._hasDuplicateAddresses(rewardRecipientAndWeights)) revert InvalidAddress(); + + //loop all the reward recipients and validate the weight and address + uint256 totalWeight; + for (uint256 i; i < rewardRecipientAndWeights.length; ++i) { + //get the weight + uint256 recipientWeight = rewardRecipientAndWeights[i].weight; + //get the address + address recipientAddress = rewardRecipientAndWeights[i].addr; + + //ensure the reward recipient address is not zero + if (recipientAddress == address(0)) revert InvalidAddress(); + + //save/overwrite the weight for the reward recipient + s_rewardRecipientWeights[poolId][recipientAddress] = recipientWeight; + + unchecked { + //keep track of the cumulative weight, this cannot overflow as the total weight is restricted at 1e18 + totalWeight += recipientWeight; + } + } + + //if total weight is not met, the fees will either be under or over distributed + if (totalWeight != expectedWeight) revert InvalidWeights(); + } + + /// @inheritdoc IRewardManager + function updateRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata newRewardRecipients + ) external override onlyOwner { + //create an array of poolIds to pass to _claimRewards if required + bytes32[] memory poolIds = new bytes32[](1); + poolIds[0] = poolId; + + //loop all the reward recipients and claim their rewards before updating their weights + uint256 existingTotalWeight; + for (uint256 i; i < newRewardRecipients.length; ++i) { + //get the address + address recipientAddress = newRewardRecipients[i].addr; + //get the existing weight + uint256 existingWeight = s_rewardRecipientWeights[poolId][recipientAddress]; + + //if a recipient is updated, the rewards must be claimed first as they can't claim previous fees at the new weight + _claimRewards(newRewardRecipients[i].addr, poolIds); + + unchecked { + //keep tally of the weights so that the expected collective weight is known + existingTotalWeight += existingWeight; + } + } + + //update the reward recipients, if the new collective weight isn't equal to the previous collective weight, the fees will either be under or over distributed + _setRewardRecipientWeights(poolId, newRewardRecipients, existingTotalWeight); + + //emit event + emit RewardRecipientsUpdated(poolId, newRewardRecipients); + } + + /// @inheritdoc IRewardManager + function payRecipients(bytes32 poolId, address[] calldata recipients) external onlyOwnerOrRecipientInPool(poolId) { + //convert poolIds to an array to match the interface of _claimRewards + bytes32[] memory poolIdsArray = new bytes32[](1); + poolIdsArray[0] = poolId; + + //loop each recipient and claim the rewards for each of the pools and assets + for (uint256 i; i < recipients.length; ++i) { + _claimRewards(recipients[i], poolIdsArray); + } + } + + /// @inheritdoc IRewardManager + function setFeeManager(address newFeeManagerAddress) external onlyOwner { + if (newFeeManagerAddress == address(0)) revert InvalidAddress(); + + s_feeManagerAddress = newFeeManagerAddress; + + emit FeeManagerUpdated(newFeeManagerAddress); + } + + /// @inheritdoc IRewardManager + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory) { + //get the length of the pool ids which we will loop through and potentially return + uint256 registeredPoolIdsLength = s_registeredPoolIds.length; + + uint256 lastIndex = endIndex > registeredPoolIdsLength ? registeredPoolIdsLength : endIndex; + + if (startIndex > lastIndex) revert InvalidPoolLength(); + + //create a new array with the maximum amount of potential pool ids + bytes32[] memory claimablePoolIds = new bytes32[](lastIndex - startIndex); + //we want the pools which a recipient has funds for to be sequential, so we need to keep track of the index + uint256 poolIdArrayIndex; + + //loop all the pool ids, and check if the recipient has a registered weight and a claimable amount + for (uint256 i = startIndex; i < lastIndex; ++i) { + //get the poolId + bytes32 poolId = s_registeredPoolIds[i]; + + //if the recipient has a weight, they are a recipient of this poolId + if (s_rewardRecipientWeights[poolId][recipient] != 0) { + //get the total in this pool + uint256 totalPoolAmount = s_totalRewardRecipientFees[poolId]; + //if the recipient has any LINK, then add the poolId to the array + unchecked { + //s_totalRewardRecipientFeesLastClaimedAmounts can never exceed total pool amount, and the number of pools can't exceed the max array length + if (totalPoolAmount - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] != 0) { + claimablePoolIds[poolIdArrayIndex++] = poolId; + } + } + } + } + + return claimablePoolIds; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol new file mode 100644 index 0000000..fe57421 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol @@ -0,0 +1,559 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IVerifier} from "./interfaces/IVerifier.sol"; +import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; + +// OCR2 standard +uint256 constant MAX_NUM_ORACLES = 31; + +/* + * The verifier contract is used to verify offchain reports signed + * by DONs. A report consists of a price, block number and feed Id. It + * represents the observed price of an asset at a specified block number for + * a feed. The verifier contract is used to verify that such reports have + * been signed by the correct signers. + **/ +contract Verifier is IVerifier, ConfirmedOwner, TypeAndVersionInterface { + // The first byte of the mask can be 0, because we only ever have 31 oracles + uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; + + enum Role { + // Default role for an oracle address. This means that the oracle address + // is not a signer + Unset, + // Role given to an oracle address that is allowed to sign feed data + Signer + } + + struct Signer { + // Index of oracle in a configuration + uint8 index; + // The oracle's role + Role role; + } + + struct Config { + // Fault tolerance + uint8 f; + // Marks whether or not a configuration is active + bool isActive; + // Map of signer addresses to oracles + mapping(address => Signer) oracles; + } + + struct VerifierState { + // The number of times a new configuration + /// has been set + uint32 configCount; + // The block number of the block the last time + /// the configuration was updated. + uint32 latestConfigBlockNumber; + // The latest epoch a report was verified for + uint32 latestEpoch; + // Whether or not the verifier for this feed has been deactivated + bool isDeactivated; + /// The latest config digest set + bytes32 latestConfigDigest; + /// The historical record of all previously set configs by feedId + mapping(bytes32 => Config) s_verificationDataConfigs; + } + + /// @notice This event is emitted when a new report is verified. + /// It is used to keep a historical record of verified reports. + event ReportVerified(bytes32 indexed feedId, address requester); + + /// @notice This event is emitted whenever a new configuration is set for a feed. It triggers a new run of the offchain reporting protocol. + event ConfigSet( + bytes32 indexed feedId, + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + bytes32[] offchainTransmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /// @notice This event is emitted whenever a configuration is deactivated + event ConfigDeactivated(bytes32 indexed feedId, bytes32 configDigest); + + /// @notice This event is emitted whenever a configuration is activated + event ConfigActivated(bytes32 indexed feedId, bytes32 configDigest); + + /// @notice This event is emitted whenever a feed is activated + event FeedActivated(bytes32 indexed feedId); + + /// @notice This event is emitted whenever a feed is deactivated + event FeedDeactivated(bytes32 indexed feedId); + + /// @notice This error is thrown whenever an address tries + /// to exeecute a transaction that it is not authorized to do so + error AccessForbidden(); + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown whenever the feed ID passed in + /// a signed report is empty + error FeedIdEmpty(); + + /// @notice This error is thrown whenever the config digest + /// is empty + error DigestEmpty(); + + /// @notice This error is thrown whenever the config digest + /// passed in has not been set in this verifier + /// @param feedId The feed ID in the signed report + /// @param configDigest The config digest that has not been set + error DigestNotSet(bytes32 feedId, bytes32 configDigest); + + /// @notice This error is thrown whenever the config digest + /// has been deactivated + /// @param feedId The feed ID in the signed report + /// @param configDigest The config digest that is inactive + error DigestInactive(bytes32 feedId, bytes32 configDigest); + + /// @notice This error is thrown whenever trying to set a config + /// with a fault tolerance of 0 + error FaultToleranceMustBePositive(); + + /// @notice This error is thrown whenever a report is signed + /// with more than the max number of signers + /// @param numSigners The number of signers who have signed the report + /// @param maxSigners The maximum number of signers that can sign a report + error ExcessSigners(uint256 numSigners, uint256 maxSigners); + + /// @notice This error is thrown whenever a report is signed + /// with less than the minimum number of signers + /// @param numSigners The number of signers who have signed the report + /// @param minSigners The minimum number of signers that need to sign a report + error InsufficientSigners(uint256 numSigners, uint256 minSigners); + + /// @notice This error is thrown whenever a report is signed + /// with an incorrect number of signers + /// @param numSigners The number of signers who have signed the report + /// @param expectedNumSigners The expected number of signers that need to sign + /// a report + error IncorrectSignatureCount(uint256 numSigners, uint256 expectedNumSigners); + + /// @notice This error is thrown whenever the R and S signer components + /// have different lengths + /// @param rsLength The number of r signature components + /// @param ssLength The number of s signature components + error MismatchedSignatures(uint256 rsLength, uint256 ssLength); + + /// @notice This error is thrown whenever setting a config with duplicate signatures + error NonUniqueSignatures(); + + /// @notice This error is thrown whenever a report fails to verify due to bad or duplicate signatures + error BadVerification(); + + /// @notice This error is thrown whenever the admin tries to deactivate + /// the latest config digest + /// @param feedId The feed ID in the signed report + /// @param configDigest The latest config digest + error CannotDeactivateLatestConfig(bytes32 feedId, bytes32 configDigest); + + /// @notice This error is thrown whenever the feed ID passed in is deactivated + /// @param feedId The feed ID + error InactiveFeed(bytes32 feedId); + + /// @notice This error is thrown whenever the feed ID passed in is not found + /// @param feedId The feed ID + error InvalidFeed(bytes32 feedId); + + /// @notice The address of the verifier proxy + address private immutable i_verifierProxyAddr; + + /// @notice Verifier states keyed on Feed ID + mapping(bytes32 => VerifierState) internal s_feedVerifierStates; + + /// @param verifierProxyAddr The address of the VerifierProxy contract + constructor(address verifierProxyAddr) ConfirmedOwner(msg.sender) { + if (verifierProxyAddr == address(0)) revert ZeroAddress(); + i_verifierProxyAddr = verifierProxyAddr; + } + + modifier checkConfigValid(uint256 numSigners, uint256 f) { + if (f == 0) revert FaultToleranceMustBePositive(); + if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); + if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); + _; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { + return interfaceId == this.verify.selector; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "Verifier 1.2.0"; + } + + /// @inheritdoc IVerifier + function verify( + bytes calldata signedReport, + address sender + ) external override returns (bytes memory verifierResponse) { + if (msg.sender != i_verifierProxyAddr) revert AccessForbidden(); + ( + bytes32[3] memory reportContext, + bytes memory reportData, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); + + // The feed ID is the first 32 bytes of the report data. + bytes32 feedId = bytes32(reportData); + + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + // If the feed has been deactivated, do not verify the report + if (feedVerifierState.isDeactivated) { + revert InactiveFeed(feedId); + } + + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + Config storage s_config = feedVerifierState.s_verificationDataConfigs[configDigest]; + + _validateReport(feedId, configDigest, rs, ss, s_config); + _updateEpoch(reportContext, feedVerifierState); + + bytes32 hashedReport = keccak256(reportData); + + _verifySignatures(hashedReport, reportContext, rs, ss, rawVs, s_config); + emit ReportVerified(feedId, sender); + + return reportData; + } + + /// @notice Validates parameters of the report + /// @param feedId Feed ID from the report + /// @param configDigest Config digest from the report + /// @param rs R components from the report + /// @param ss S components from the report + /// @param config Config for the given feed ID keyed on the config digest + function _validateReport( + bytes32 feedId, + bytes32 configDigest, + bytes32[] memory rs, + bytes32[] memory ss, + Config storage config + ) private view { + uint8 expectedNumSignatures = config.f + 1; + + if (!config.isActive) revert DigestInactive(feedId, configDigest); + if (rs.length != expectedNumSignatures) revert IncorrectSignatureCount(rs.length, expectedNumSignatures); + if (rs.length != ss.length) revert MismatchedSignatures(rs.length, ss.length); + } + + /** + * @notice Conditionally update the epoch for a feed + * @param reportContext Report context containing the epoch and round + * @param feedVerifierState Feed verifier state to conditionally update + */ + function _updateEpoch(bytes32[3] memory reportContext, VerifierState storage feedVerifierState) private { + uint40 epochAndRound = uint40(uint256(reportContext[1])); + uint32 epoch = uint32(epochAndRound >> 8); + if (epoch > feedVerifierState.latestEpoch) { + feedVerifierState.latestEpoch = epoch; + } + } + + /// @notice Verifies that a report has been signed by the correct + /// signers and that enough signers have signed the reports. + /// @param hashedReport The keccak256 hash of the raw report's bytes + /// @param reportContext The context the report was signed in + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param rawVs ith element is the the V component of the ith signature + /// @param s_config The config digest the report was signed for + function _verifySignatures( + bytes32 hashedReport, + bytes32[3] memory reportContext, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs, + Config storage s_config + ) private view { + bytes32 h = keccak256(abi.encodePacked(hashedReport, reportContext)); + // i-th byte counts number of sigs made by i-th signer + uint256 signedCount; + + Signer memory o; + address signerAddress; + uint256 numSigners = rs.length; + for (uint256 i; i < numSigners; ++i) { + signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_config.oracles[signerAddress]; + if (o.role != Role.Signer) revert BadVerification(); + unchecked { + signedCount += 1 << (8 * o.index); + } + } + + if (signedCount & ORACLE_MASK != signedCount) revert BadVerification(); + } + + /// @inheritdoc IVerifier + function setConfig( + bytes32 feedId, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig( + feedId, + block.chainid, + address(this), + 0, // 0 defaults to feedConfig.configCount + 1 + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + recipientAddressesAndWeights + ); + } + + /// @inheritdoc IVerifier + function setConfigFromSource( + bytes32 feedId, + uint256 sourceChainId, + address sourceAddress, + uint32 newConfigCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig( + feedId, + sourceChainId, + sourceAddress, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig, + recipientAddressesAndWeights + ); + } + + /// @notice Sets config based on the given arguments + /// @param feedId Feed ID to set config for + /// @param sourceChainId Chain ID of source config + /// @param sourceAddress Address of source config Verifier + /// @param newConfigCount Optional param to force the new config count + /// @param signers addresses with which oracles sign the reports + /// @param offchainTransmitters CSA key for the ith Oracle + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + /// @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + function _setConfig( + bytes32 feedId, + uint256 sourceChainId, + address sourceAddress, + uint32 newConfigCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) internal { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + // Increment the number of times a config has been set first + if (newConfigCount > 0) feedVerifierState.configCount = newConfigCount; + else feedVerifierState.configCount++; + + bytes32 configDigest = _configDigestFromConfigData( + feedId, + sourceChainId, + sourceAddress, + feedVerifierState.configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + feedVerifierState.s_verificationDataConfigs[configDigest].f = f; + feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; + for (uint8 i; i < signers.length; ++i) { + address signerAddr = signers[i]; + if (signerAddr == address(0)) revert ZeroAddress(); + + // All signer roles are unset by default for a new config digest. + // Here the contract checks to see if a signer's address has already + // been set to ensure that the group of signer addresses that will + // sign reports with the config digest are unique. + bool isSignerAlreadySet = feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr].role != + Role.Unset; + if (isSignerAlreadySet) revert NonUniqueSignatures(); + feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr] = Signer({ + role: Role.Signer, + index: i + }); + } + + IVerifierProxy(i_verifierProxyAddr).setVerifier( + feedVerifierState.latestConfigDigest, + configDigest, + recipientAddressesAndWeights + ); + + emit ConfigSet( + feedId, + feedVerifierState.latestConfigBlockNumber, + configDigest, + feedVerifierState.configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + feedVerifierState.latestEpoch = 0; + feedVerifierState.latestConfigBlockNumber = uint32(block.number); + feedVerifierState.latestConfigDigest = configDigest; + } + + /// @notice Generates the config digest from config data + /// @param feedId Feed ID to set config for + /// @param sourceChainId Chain ID of source config + /// @param sourceAddress Address of source config Verifier + /// @param configCount ordinal number of this config setting among all config settings over the life of this contract + /// @param signers ith element is address ith oracle uses to sign a report + /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) + /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + /// @dev This function is a modified version of the method from OCR2Abstract + function _configDigestFromConfigData( + bytes32 feedId, + uint256 sourceChainId, + address sourceAddress, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + feedId, + sourceChainId, + sourceAddress, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + // 0x0006 corresponds to ConfigDigestPrefixMercuryV02 in libocr + uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /// @inheritdoc IVerifier + function activateConfig(bytes32 feedId, bytes32 configDigest) external onlyOwner { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + if (configDigest == bytes32("")) revert DigestEmpty(); + if (feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(feedId, configDigest); + feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; + emit ConfigActivated(feedId, configDigest); + } + + /// @inheritdoc IVerifier + function deactivateConfig(bytes32 feedId, bytes32 configDigest) external onlyOwner { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + if (configDigest == bytes32("")) revert DigestEmpty(); + if (feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(feedId, configDigest); + if (configDigest == feedVerifierState.latestConfigDigest) { + revert CannotDeactivateLatestConfig(feedId, configDigest); + } + feedVerifierState.s_verificationDataConfigs[configDigest].isActive = false; + emit ConfigDeactivated(feedId, configDigest); + } + + /// @inheritdoc IVerifier + function activateFeed(bytes32 feedId) external onlyOwner { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + if (feedVerifierState.configCount == 0) revert InvalidFeed(feedId); + feedVerifierState.isDeactivated = false; + emit FeedActivated(feedId); + } + + /// @inheritdoc IVerifier + function deactivateFeed(bytes32 feedId) external onlyOwner { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + + if (feedVerifierState.configCount == 0) revert InvalidFeed(feedId); + feedVerifierState.isDeactivated = true; + emit FeedDeactivated(feedId); + } + + /// @inheritdoc IVerifier + function latestConfigDigestAndEpoch( + bytes32 feedId + ) external view override returns (bool scanLogs, bytes32 configDigest, uint32 epoch) { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + return (false, feedVerifierState.latestConfigDigest, feedVerifierState.latestEpoch); + } + + /// @inheritdoc IVerifier + function latestConfigDetails( + bytes32 feedId + ) external view override returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) { + VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; + return ( + feedVerifierState.configCount, + feedVerifierState.latestConfigBlockNumber, + feedVerifierState.latestConfigDigest + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol new file mode 100644 index 0000000..c06312d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; +import {IVerifier} from "./interfaces/IVerifier.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; +import {Common} from "../libraries/Common.sol"; + +/** + * The verifier proxy contract is the gateway for all report verification requests + * on a chain. It is responsible for taking in a verification request and routing + * it to the correct verifier contract. + */ +contract VerifierProxy is IVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { + /// @notice This event is emitted whenever a new verifier contract is set + /// @param oldConfigDigest The config digest that was previously the latest config + /// digest of the verifier contract at the verifier address. + /// @param oldConfigDigest The latest config digest of the verifier contract + /// at the verifier address. + /// @param verifierAddress The address of the verifier contract that verifies reports for + /// a given digest + event VerifierSet(bytes32 oldConfigDigest, bytes32 newConfigDigest, address verifierAddress); + + /// @notice This event is emitted whenever a new verifier contract is initialized + /// @param verifierAddress The address of the verifier contract that verifies reports + event VerifierInitialized(address verifierAddress); + + /// @notice This event is emitted whenever a verifier is unset + /// @param configDigest The config digest that was unset + /// @param verifierAddress The Verifier contract address unset + event VerifierUnset(bytes32 configDigest, address verifierAddress); + + /// @notice This event is emitted when a new access controller is set + /// @param oldAccessController The old access controller address + /// @param newAccessController The new access controller address + event AccessControllerSet(address oldAccessController, address newAccessController); + + /// @notice This event is emitted when a new fee manager is set + /// @param oldFeeManager The old fee manager address + /// @param newFeeManager The new fee manager address + event FeeManagerSet(address oldFeeManager, address newFeeManager); + + /// @notice This error is thrown whenever an address tries + /// to exeecute a transaction that it is not authorized to do so + error AccessForbidden(); + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown when trying to set a verifier address + /// for a digest that has already been initialized + /// @param configDigest The digest for the verifier that has + /// already been set + /// @param verifier The address of the verifier the digest was set for + error ConfigDigestAlreadySet(bytes32 configDigest, address verifier); + + /// @notice This error is thrown when trying to set a verifier address that has already been initialized + error VerifierAlreadyInitialized(address verifier); + + /// @notice This error is thrown when the verifier at an address does + /// not conform to the verifier interface + error VerifierInvalid(); + + /// @notice This error is thrown when the fee manager at an address does + /// not conform to the fee manager interface + error FeeManagerInvalid(); + + /// @notice This error is thrown whenever a verifier is not found + /// @param configDigest The digest for which a verifier is not found + error VerifierNotFound(bytes32 configDigest); + + /// @notice This error is thrown whenever billing fails. + error BadVerification(); + + /// @notice Mapping of authorized verifiers + mapping(address => bool) private s_initializedVerifiers; + + /// @notice Mapping between config digests and verifiers + mapping(bytes32 => address) private s_verifiersByConfig; + + /// @notice The contract to control addresses that are allowed to verify reports + AccessControllerInterface public s_accessController; + + /// @notice The contract to control fees for report verification + IVerifierFeeManager public s_feeManager; + + constructor(AccessControllerInterface accessController) ConfirmedOwner(msg.sender) { + s_accessController = accessController; + } + + modifier checkAccess() { + AccessControllerInterface ac = s_accessController; + if (address(ac) != address(0) && !ac.hasAccess(msg.sender, msg.data)) revert AccessForbidden(); + _; + } + + modifier onlyInitializedVerifier() { + if (!s_initializedVerifiers[msg.sender]) revert AccessForbidden(); + _; + } + + modifier onlyValidVerifier(address verifierAddress) { + if (verifierAddress == address(0)) revert ZeroAddress(); + if (!IERC165(verifierAddress).supportsInterface(IVerifier.verify.selector)) revert VerifierInvalid(); + _; + } + + modifier onlyUnsetConfigDigest(bytes32 configDigest) { + address configDigestVerifier = s_verifiersByConfig[configDigest]; + if (configDigestVerifier != address(0)) revert ConfigDigestAlreadySet(configDigest, configDigestVerifier); + _; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "VerifierProxy 2.0.0"; + } + + /// @inheritdoc IVerifierProxy + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable checkAccess returns (bytes memory) { + IVerifierFeeManager feeManager = s_feeManager; + + // Bill the verifier + if (address(feeManager) != address(0)) { + feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); + } + + return _verify(payload); + } + + /// @inheritdoc IVerifierProxy + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable checkAccess returns (bytes[] memory verifiedReports) { + IVerifierFeeManager feeManager = s_feeManager; + + // Bill the verifier + if (address(feeManager) != address(0)) { + feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); + } + + //verify the reports + verifiedReports = new bytes[](payloads.length); + for (uint256 i; i < payloads.length; ++i) { + verifiedReports[i] = _verify(payloads[i]); + } + + return verifiedReports; + } + + function _verify(bytes calldata payload) internal returns (bytes memory verifiedReport) { + // First 32 bytes of the signed report is the config digest + bytes32 configDigest = bytes32(payload); + address verifierAddress = s_verifiersByConfig[configDigest]; + if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); + + return IVerifier(verifierAddress).verify(payload, msg.sender); + } + + /// @inheritdoc IVerifierProxy + function initializeVerifier(address verifierAddress) external override onlyOwner onlyValidVerifier(verifierAddress) { + if (s_initializedVerifiers[verifierAddress]) revert VerifierAlreadyInitialized(verifierAddress); + + s_initializedVerifiers[verifierAddress] = true; + emit VerifierInitialized(verifierAddress); + } + + /// @inheritdoc IVerifierProxy + function setVerifier( + bytes32 currentConfigDigest, + bytes32 newConfigDigest, + Common.AddressAndWeight[] calldata addressesAndWeights + ) external override onlyUnsetConfigDigest(newConfigDigest) onlyInitializedVerifier { + s_verifiersByConfig[newConfigDigest] = msg.sender; + + // Empty recipients array will be ignored and must be set off chain + if (addressesAndWeights.length > 0) { + if (address(s_feeManager) == address(0)) { + revert ZeroAddress(); + } + + s_feeManager.setFeeRecipients(newConfigDigest, addressesAndWeights); + } + + emit VerifierSet(currentConfigDigest, newConfigDigest, msg.sender); + } + + /// @inheritdoc IVerifierProxy + function unsetVerifier(bytes32 configDigest) external override onlyOwner { + address verifierAddress = s_verifiersByConfig[configDigest]; + if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); + delete s_verifiersByConfig[configDigest]; + emit VerifierUnset(configDigest, verifierAddress); + } + + /// @inheritdoc IVerifierProxy + function getVerifier(bytes32 configDigest) external view override returns (address) { + return s_verifiersByConfig[configDigest]; + } + + /// @inheritdoc IVerifierProxy + function setAccessController(AccessControllerInterface accessController) external onlyOwner { + address oldAccessController = address(s_accessController); + s_accessController = accessController; + emit AccessControllerSet(oldAccessController, address(accessController)); + } + + /// @inheritdoc IVerifierProxy + function setFeeManager(IVerifierFeeManager feeManager) external onlyOwner { + if (address(feeManager) == address(0)) revert ZeroAddress(); + + if ( + !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFee.selector) || + !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFeeBulk.selector) + ) revert FeeManagerInvalid(); + + address oldFeeManager = address(s_feeManager); + s_feeManager = IVerifierFeeManager(feeManager); + emit FeeManagerSet(oldFeeManager, address(feeManager)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol new file mode 100644 index 0000000..818a3a0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; +import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; + +interface IFeeManager is IERC165, IVerifierFeeManager { + /** + * @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount. + * @param subscriber address trying to verify + * @param report report to calculate the fee for + * @param quoteAddress address of the quote payment token + * @return (fee, reward, totalDiscount) fee and the reward data with the discount applied + */ + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) external returns (Common.Asset memory, Common.Asset memory, uint256); + + /** + * @notice Sets the native surcharge + * @param surcharge surcharge to be paid if paying in native + */ + function setNativeSurcharge(uint64 surcharge) external; + + /** + * @notice Adds a subscriber to the fee manager + * @param subscriber address of the subscriber + * @param feedId feed id to apply the discount to + * @param token token to apply the discount to + * @param discount discount to be applied to the fee + */ + function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) external; + + /** + * @notice Withdraws any native or LINK rewards to the owner address + * @param assetAddress address of the asset to withdraw + * @param recipientAddress address to withdraw to + * @param quantity quantity to withdraw + */ + function withdraw(address assetAddress, address recipientAddress, uint192 quantity) external; + + /** + * @notice Returns the link balance of the fee manager + * @return link balance of the fee manager + */ + function linkAvailableForPayment() external returns (uint256); + + /** + * @notice Admin function to pay the LINK deficit for a given config digest + * @param configDigest the config digest to pay the deficit for + */ + function payLinkDeficit(bytes32 configDigest) external; + + /** + * @notice The structure to hold a fee and reward to verify a report + * @param digest the digest linked to the fee and reward + * @param fee the fee paid to verify the report + * @param reward the reward paid upon verification + & @param appliedDiscount the discount applied to the reward + */ + struct FeeAndReward { + bytes32 configDigest; + Common.Asset fee; + Common.Asset reward; + uint256 appliedDiscount; + } + + /** + * @notice The structure to hold quote metadata + * @param quoteAddress the address of the quote + */ + struct Quote { + address quoteAddress; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol new file mode 100644 index 0000000..f08ce34 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IRewardManager is IERC165 { + /** + * @notice Record the fee received for a particular pool + * @param payments array of structs containing pool id and amount + * @param payee the user the funds should be retrieved from + */ + function onFeePaid(FeePayment[] calldata payments, address payee) external; + + /** + * @notice Claims the rewards in a specific pool + * @param poolIds array of poolIds to claim rewards for + */ + function claimRewards(bytes32[] calldata poolIds) external; + + /** + * @notice Set the RewardRecipients and weights for a specific pool. This should only be called once per pool Id. Else updateRewardRecipients should be used. + * @param poolId poolId to set RewardRecipients and weights for + * @param rewardRecipientAndWeights array of each RewardRecipient and associated weight + */ + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata rewardRecipientAndWeights) external; + + /** + * @notice Updates a subset the reward recipients for a specific poolId. The collective weight of the recipients should add up to the recipients existing weights. Any recipients with a weight of 0 will be removed. + * @param poolId the poolId to update + * @param newRewardRecipients array of new reward recipients + */ + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata newRewardRecipients) external; + + /** + * @notice Pays all the recipients for each of the pool ids + * @param poolId the pool id to pay recipients for + * @param recipients array of recipients to pay within the pool + */ + function payRecipients(bytes32 poolId, address[] calldata recipients) external; + + /** + * @notice Sets the fee manager. This needs to be done post construction to prevent a circular dependency. + * @param newFeeManager address of the new verifier proxy + */ + function setFeeManager(address newFeeManager) external; + + /** + * @notice Gets a list of pool ids which have reward for a specific recipient. + * @param recipient address of the recipient to get pool ids for + * @param startIndex the index to start from + * @param endIndex the index to stop at + */ + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory); + + /** + * @notice The structure to hold a fee payment notice + * @param poolId the poolId receiving the payment + * @param amount the amount being paid + */ + struct FeePayment { + bytes32 poolId; + uint192 amount; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol new file mode 100644 index 0000000..94b2603 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IVerifier is IERC165 { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier. + * @param signedReport The encoded data to be verified. + * @param sender The address that requested to verify the contract. + * This is only used for logging purposes. + * @dev Verification is typically only done through the proxy contract so + * we can't just use msg.sender to log the requester as the msg.sender + * contract will always be the proxy. + * @return verifierResponse The encoded verified response. + */ + function verify(bytes calldata signedReport, address sender) external returns (bytes memory verifierResponse); + + /** + * @notice sets offchain reporting protocol configuration incl. participating oracles + * @param feedId Feed ID to set config for + * @param signers addresses with which oracles sign the reports + * @param offchainTransmitters CSA key for the ith Oracle + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + */ + function setConfig( + bytes32 feedId, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external; + + /** + * @notice identical to `setConfig` except with args for sourceChainId and sourceAddress + * @param feedId Feed ID to set config for + * @param sourceChainId Chain ID of source config + * @param sourceAddress Address of source config Verifier + * @param newConfigCount Param to force the new config count + * @param signers addresses with which oracles sign the reports + * @param offchainTransmitters CSA key for the ith Oracle + * @param f number of faulty oracles the system can tolerate + * @param onchainConfig serialized configuration used by the contract (and possibly oracles) + * @param offchainConfigVersion version number for offchainEncoding schema + * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + */ + function setConfigFromSource( + bytes32 feedId, + uint256 sourceChainId, + address sourceAddress, + uint32 newConfigCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external; + + /** + * @notice Activates the configuration for a config digest + * @param feedId Feed ID to activate config for + * @param configDigest The config digest to activate + * @dev This function can be called by the contract admin to activate a configuration. + */ + function activateConfig(bytes32 feedId, bytes32 configDigest) external; + + /** + * @notice Deactivates the configuration for a config digest + * @param feedId Feed ID to deactivate config for + * @param configDigest The config digest to deactivate + * @dev This function can be called by the contract admin to deactivate an incorrect configuration. + */ + function deactivateConfig(bytes32 feedId, bytes32 configDigest) external; + + /** + * @notice Activates the given feed + * @param feedId Feed ID to activated + * @dev This function can be called by the contract admin to activate a feed + */ + function activateFeed(bytes32 feedId) external; + + /** + * @notice Deactivates the given feed + * @param feedId Feed ID to deactivated + * @dev This function can be called by the contract admin to deactivate a feed + */ + function deactivateFeed(bytes32 feedId) external; + + /** + * @notice returns the latest config digest and epoch for a feed + * @param feedId Feed ID to fetch data for + * @return scanLogs indicates whether to rely on the configDigest and epoch + * returned or whether to scan logs for the Transmitted event instead. + * @return configDigest + * @return epoch + */ + function latestConfigDigestAndEpoch( + bytes32 feedId + ) external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /** + * @notice information about current offchain reporting protocol configuration + * @param feedId Feed ID to fetch data for + * @return configCount ordinal number of current config, out of all configs applied to this contract so far + * @return blockNumber block at which this config was set + * @return configDigest domain-separation tag for current config + */ + function latestConfigDetails( + bytes32 feedId + ) external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol new file mode 100644 index 0000000..da3fdfa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IVerifierFeeManager is IERC165 { + /** + * @notice Handles fees for a report from the subscriber and manages rewards + * @param payload report to process the fee for + * @param parameterPayload fee payload + * @param subscriber address of the fee will be applied + */ + function processFee(bytes calldata payload, bytes calldata parameterPayload, address subscriber) external payable; + + /** + * @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager + * @param payloads reports to process + * @param parameterPayload fee payload + * @param subscriber address of the user to process fee for + */ + function processFeeBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable; + + /** + * @notice Sets the fee recipients according to the fee manager + * @param configDigest digest of the configuration + * @param rewardRecipientAndWeights the address and weights of all the recipients to receive rewards + */ + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol new file mode 100644 index 0000000..6609e48 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Common} from "../../libraries/Common.sol"; +import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; +import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; + +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payload The encoded data to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifierResponse The encoded report from the verifier. + */ + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable returns (bytes memory verifierResponse); + + /** + * @notice Bulk verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payloads The encoded payloads to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifiedReports The encoded reports from the verifier. + */ + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable returns (bytes[] memory verifiedReports); + + /** + * @notice Sets the verifier address initially, allowing `setVerifier` to be set by this Verifier in the future + * @param verifierAddress The address of the verifier contract to initialize + */ + function initializeVerifier(address verifierAddress) external; + + /** + * @notice Sets a new verifier for a config digest + * @param currentConfigDigest The current config digest + * @param newConfigDigest The config digest to set + * @param addressesAndWeights The addresses and weights of reward recipients + * reports for a given config digest. + */ + function setVerifier( + bytes32 currentConfigDigest, + bytes32 newConfigDigest, + Common.AddressAndWeight[] memory addressesAndWeights + ) external; + + /** + * @notice Removes a verifier for a given config digest + * @param configDigest The config digest of the verifier to remove + */ + function unsetVerifier(bytes32 configDigest) external; + + /** + * @notice Retrieves the verifier address that verifies reports + * for a config digest. + * @param configDigest The config digest to query for + * @return verifierAddress The address of the verifier contract that verifies + * reports for a given config digest. + */ + function getVerifier(bytes32 configDigest) external view returns (address verifierAddress); + + /** + * @notice Called by the admin to set an access controller contract + * @param accessController The new access controller to set + */ + function setAccessController(AccessControllerInterface accessController) external; + + /** + * @notice Updates the fee manager + * @param feeManager The new fee manager + */ + function setFeeManager(IVerifierFeeManager feeManager) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol new file mode 100644 index 0000000..0d598cd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol @@ -0,0 +1,379 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {FeeManager} from "../../FeeManager.sol"; +import {RewardManager} from "../../RewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; +import {FeeManagerProxy} from "../mocks/FeeManagerProxy.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice Base class for all feeManager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup the feeManager + */ +contract BaseFeeManagerTest is Test { + //contracts + FeeManager internal feeManager; + RewardManager internal rewardManager; + FeeManagerProxy internal feeManagerProxy; + + ERC20Mock internal link; + WERC20Mock internal native; + + //erc20 config + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + //contract owner + address internal constant INVALID_ADDRESS = address(0); + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + address internal constant PROXY = address(uint160(uint256(keccak256("PROXY")))); + + //version masks + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + //feed ids & config digests + bytes32 internal constant DEFAULT_FEED_1_V1 = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V2 = (keccak256("ETH-USD") & V_MASK) | V2_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + bytes32 internal constant DEFAULT_FEED_2_V3 = (keccak256("LINK-USD") & V_MASK) | V3_BITMASK; + bytes32 internal constant DEFAULT_CONFIG_DIGEST = keccak256("DEFAULT_CONFIG_DIGEST"); + + //report + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + //rewards + uint64 internal constant FEE_SCALAR = 1e18; + + address internal constant NATIVE_WITHDRAW_ADDRESS = address(0); + + //the selector for each error + bytes4 internal immutable INVALID_DISCOUNT_ERROR = FeeManager.InvalidDiscount.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR = FeeManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_SURCHARGE_ERROR = FeeManager.InvalidSurcharge.selector; + bytes4 internal immutable EXPIRED_REPORT_ERROR = FeeManager.ExpiredReport.selector; + bytes4 internal immutable INVALID_DEPOSIT_ERROR = FeeManager.InvalidDeposit.selector; + bytes4 internal immutable INVALID_QUOTE_ERROR = FeeManager.InvalidQuote.selector; + bytes4 internal immutable UNAUTHORIZED_ERROR = FeeManager.Unauthorized.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes internal constant INSUFFICIENT_ALLOWANCE_ERROR = "ERC20: insufficient allowance"; + bytes4 internal immutable ZERO_DEFICIT = FeeManager.ZeroDeficit.selector; + + //events emitted + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + event NativeSurchargeUpdated(uint64 newSurcharge); + event InsufficientLink(IRewardManager.FeePayment[] feesAndRewards); + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscountQuantity + ); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeContracts(); + } + + function _initializeContracts() internal { + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + native = new WERC20Mock(); + + feeManagerProxy = new FeeManagerProxy(); + rewardManager = new RewardManager(address(link)); + feeManager = new FeeManager(address(link), address(native), address(feeManagerProxy), address(rewardManager)); + + //link the feeManager to the proxy + feeManagerProxy.setFeeManager(feeManager); + + //link the feeManager to the reward manager + rewardManager.setFeeManager(address(feeManager)); + + //mint some tokens to the admin + link.mint(ADMIN, DEFAULT_LINK_MINT_QUANTITY); + native.mint(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the proxy + link.mint(PROXY, DEFAULT_LINK_MINT_QUANTITY); + native.mint(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function setSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint256 discount, + address sender + ) internal { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the discount + feeManager.updateSubscriberDiscount(subscriber, feedId, token, uint64(discount)); + + //change back to the original address + changePrank(originalAddr); + } + + function setNativeSurcharge(uint256 surcharge, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.setNativeSurcharge(uint64(surcharge)); + + //change back to the original address + changePrank(originalAddr); + } + + // solium-disable-next-line no-unused-vars + function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the fee + (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return fee; + } + + function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the reward + (, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return reward; + } + + function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) { + //get the reward + (, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote); + + return appliedDiscount; + } + + function getV1Report(bytes32 feedId) public pure returns (bytes memory) { + return abi.encode(feedId, uint32(0), int192(0), int192(0), int192(0), uint64(0), bytes32(0), uint64(0), uint64(0)); + } + + function getV2Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0) + ); + } + + function getV3Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0), + int192(0), + int192(0) + ); + } + + function getV3ReportWithCustomExpiryAndFee( + bytes32 feedId, + uint256 expiry, + uint256 linkFee, + uint256 nativeFee + ) public pure returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(nativeFee), + uint192(linkFee), + uint32(expiry), + int192(0), + int192(0), + int192(0) + ); + } + + function getLinkQuote() public view returns (address) { + return address(link); + } + + function getNativeQuote() public view returns (address) { + return address(native); + } + + function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.withdraw(assetAddress, recipient, uint192(amount)); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkBalance(address balanceAddress) public view returns (uint256) { + return link.balanceOf(balanceAddress); + } + + function getNativeBalance(address balanceAddress) public view returns (uint256) { + return native.balanceOf(balanceAddress); + } + + function getNativeUnwrappedBalance(address balanceAddress) public view returns (uint256) { + return balanceAddress.balance; + } + + function mintLink(address recipient, uint256 amount) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(ADMIN); + + //mint the link to the recipient + link.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function mintNative(address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //mint the native to the recipient + native.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function issueUnwrappedNative(address recipient, uint256 quantity) public { + vm.deal(recipient, quantity); + } + + function ProcessFeeAsUser( + bytes memory payload, + address subscriber, + address tokenAddress, + uint256 wrappedNativeValue, + address sender + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //process the fee + feeManager.processFee{value: wrappedNativeValue}(payload, abi.encode(tokenAddress), subscriber); + + //change ProcessFeeAsUserback to the original address + changePrank(originalAddr); + } + + function processFee(bytes memory payload, address subscriber, address feeAddress, uint256 wrappedNativeValue) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFee{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function processFee( + bytes[] memory payloads, + address subscriber, + address feeAddress, + uint256 wrappedNativeValue + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(payloads, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function getPayload(bytes memory reportPayload) public pure returns (bytes memory) { + return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32("")); + } + + function approveLink(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + link.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function approveNative(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + native.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function payLinkDeficit(bytes32 configDigest, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + feeManager.payLinkDeficit(configDigest); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkDeficit(bytes32 configDigest) public view returns (uint256) { + return feeManager.s_linkDeficit(configDigest); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol new file mode 100644 index 0000000..571d348 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseFeeManager.t.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the setup functionality of the feemanager + */ +contract FeeManagerProcessFeeTest is BaseFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_WithdrawERC20() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //get the balances to ne used for comparison + uint256 contractBalance = getLinkBalance(address(feeManager)); + uint256 adminBalance = getLinkBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getLinkBalance(address(feeManager)); + uint256 newAdminBalance = getLinkBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawUnwrappedNative() public { + //issue funds straight to the contract to bypass the lack of fallback function + issueUnwrappedNative(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //get the balances to be used for comparison + uint256 contractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 adminBalance = getNativeUnwrappedBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(NATIVE_WITHDRAW_ADDRESS, ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 newAdminBalance = getNativeUnwrappedBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawNonAdminAddr() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //should revert if not admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //withdraw some balance + withdraw(address(link), ADMIN, DEFAULT_LINK_MINT_QUANTITY, USER); + } + + function test_eventIsEmittedAfterSurchargeIsSet() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 5; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_subscriberDiscountEventIsEmittedOnUpdate() public { + //native surcharge + uint64 discount = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit SubscriberDiscountUpdated(USER, DEFAULT_FEED_1_V3, address(native), discount); + + //set the surcharge + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + } + + function test_eventIsEmittedUponWithdraw() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //the amount to withdraw + uint192 withdrawAmount = 1; + + //expect an emit + vm.expectEmit(); + + //the event to be emitted + emit Withdraw(ADMIN, ADMIN, address(link), withdrawAmount); + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + } + + function test_linkAvailableForPaymentReturnsLinkBalance() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //check there's a balance + assertGt(getLinkBalance(address(feeManager)), 0); + + //check the link available for payment is the link balance + assertEq(feeManager.linkAvailableForPayment(), getLinkBalance(address(feeManager))); + } + + function test_payLinkDeficit() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + emit InsufficientLink(contractFees); + + //process the fee + processFee(payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_payLinkDeficitTwice() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //process the fee + processFee(payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //paying again should revert with 0 + vm.expectRevert(ZERO_DEFICIT); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + } + + function test_payLinkDeficitPaysAllFeesProcessed() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + processFee(payload, USER, address(native), 0); + + //check the deficit has been increased twice + assertEq(getLinkDeficit(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE * 2); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 2); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE * 2); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); + } + + function test_payLinkDeficitOnlyCallableByAdmin() public { + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, USER); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol new file mode 100644 index 0000000..1b0f95d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol @@ -0,0 +1,606 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseFeeManager.t.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager's getFeeAndReward + */ +contract FeeManagerProcessFeeTest is BaseFeeManagerTest { + function test_baseFeeIsAppliedForNative() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_baseFeeIsAppliedForLink() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_discountAIsNotAppliedWhenSetForOtherUsers() public { + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), INVALID_ADDRESS); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_discountIsNotAppliedForInvalidTokenAddress() public { + //should revert with invalid address as it's not a configured token + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, INVALID_ADDRESS, FEE_SCALAR / 2, ADMIN); + } + + function test_discountIsAppliedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_DiscountIsAppliedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE / 2); + } + + function test_discountIsNoLongerAppliedAfterRemoving() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsNotAppliedForLinkFee() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsNoLongerAppliedAfterRemoving() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should be the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //remove the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewSurchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //change the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsAppliedForNativeFeeWithDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //calculate the expected discount quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge) / 2); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge - expectedDiscount); + } + + function test_emptyQuoteRevertsWithError() public { + //expect a revert + vm.expectRevert(INVALID_QUOTE_ERROR); + + //get the fee required by the feeManager + getFee(getV3Report(DEFAULT_FEED_1_V3), address(0), USER); + } + + function test_nativeSurcharge100Percent() public { + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be twice the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2); + } + + function test_nativeSurcharge0Percent() public { + //set the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_nativeSurchargeCannotExceed100Percent() public { + //should revert if surcharge is greater than 100% + vm.expectRevert(INVALID_SURCHARGE_ERROR); + + //set the surcharge above the max + setNativeSurcharge(FEE_SCALAR + 1, ADMIN); + } + + function test_discountIsAppliedWith100PercentSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE; + + //fee should be twice the surcharge minus the discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2 - expectedDiscount); + } + + function test_feeIsZeroWith100PercentDiscount() public { + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_feeIsUpdatedAfterDiscountIsRemoved() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewDiscountIsApplied() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //change the discount to 25% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //expected discount is now 25% + expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 4; + + //fee should be the base fee minus the expected discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_setDiscountOver100Percent() public { + //should revert with invalid discount + vm.expectRevert(INVALID_DISCOUNT_ERROR); + + //set the subscriber discount to over 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR + 1, ADMIN); + } + + function test_surchargeIsNotAppliedWith100PercentDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nonAdminUserCanNotSetDiscount() public { + //should revert with unauthorized + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, USER); + } + + function test_surchargeFeeRoundsUpWhenUneven() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 3; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = (DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR; + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge + 1); + } + + function test_discountFeeRoundsDownWhenUneven() public { + //native surcharge + uint256 discount = FEE_SCALAR / 3; + + //set the subscriber discount to 33.333% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE * discount) / FEE_SCALAR); + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_reportWithNoExpiryOrFeeReturnsZero() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV1Report(DEFAULT_FEED_1_V1), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() public { + //set the subscriber and native discounts + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager for both tokens + Common.Asset memory linkFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory nativeFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity for each token + uint256 expectedDiscountLink = (DEFAULT_REPORT_LINK_FEE * FEE_SCALAR) / 4 / FEE_SCALAR; + uint256 expectedDiscountNative = (DEFAULT_REPORT_NATIVE_FEE * FEE_SCALAR) / 2 / FEE_SCALAR; + + //check the fee calculation for each token + assertEq(linkFee.amount, DEFAULT_REPORT_LINK_FEE - expectedDiscountLink); + assertEq(nativeFee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscountNative); + } + + function test_discountIsNotAppliedToOtherFeeds() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_2_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_noFeeIsAppliedWhenReportHasZeroFee() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nativeSurchargeEventIsEmittedOnUpdate() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_getBaseRewardWithLinkQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkQuoteAndLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getRewardWithNativeQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithNativeQuoteAndSurcharge() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getLinkFeeIsRoundedUp() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal .66% + 1 of the base fee due to a 33% discount rounded up + assertEq(fee.amount, (DEFAULT_REPORT_LINK_FEE * 2) / 3 + 1); + } + + function test_getLinkRewardIsSameAsFee() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //check the reward is in link + assertEq(fee.assetAddress, address(link)); + + //the reward should equal .66% of the base fee due to a 33% discount rounded down + assertEq(reward.amount, fee.amount); + } + + function test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_testRevertIfReportHasExpired() public { + //expect a revert + vm.expectRevert(EXPIRED_REPORT_ERROR); + + //get the fee required by the feeManager + getFee( + getV3ReportWithCustomExpiryAndFee( + DEFAULT_FEED_1_V3, + block.timestamp - 1, + DEFAULT_REPORT_LINK_FEE, + DEFAULT_REPORT_NATIVE_FEE + ), + getNativeQuote(), + USER + ); + } + + function test_discountIsReturnedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNativeWithSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 5, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol new file mode 100644 index 0000000..0e0ed89 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseFeeManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract FeeManagerProcessFeeTest is BaseFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_nonAdminProxyUserCannotProcessFee() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //should revert as the user is not the owner + vm.expectRevert(UNAUTHORIZED_ERROR); + + //process the fee + ProcessFeeAsUser(payload, USER, address(link), 0, USER); + } + + function test_processFeeAsProxy() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeIfSubscriberIsSelf() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert due to the feeManager being the subscriber + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //process the fee will fail due to assertion + processFee(payload, address(feeManager), address(native), 0); + } + + function test_processFeeWithWithEmptyQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link by default + processFee(payload, USER, address(0), 0); + } + + function test_processFeeWithWithZeroQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(INVALID_QUOTE_ERROR); + + //processing the fee will transfer the link by default + processFee(payload, USER, INVALID_ADDRESS, 0); + } + + function test_processFeeWithWithCorruptQuotePayload() public { + //get the default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV3Report(DEFAULT_FEED_1_V3), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //expect an evm revert as the quote is corrupt + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeEmitsEventIfNotEnoughLink() public { + //simulate a deposit of half the link required for the fee + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE / 2); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //expect an emit as there's not enough link + vm.expectEmit(); + + IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); + contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE / 2); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNativeShortFunds() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INVALID_DEPOSIT_ERROR); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddress() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INSUFFICIENT_ALLOWANCE_ERROR); + + //the change will be returned and the user will attempted to be billed in LINK + processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() public { + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, PROXY); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(payload, PROXY, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the native unwrapped is no longer in the account + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //native should not be deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithUnwrappedNativeWithExcessiveFee() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(payload, PROXY, address(native), DEFAULT_REPORT_NATIVE_FEE * 2); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeUsesCorrectDigest() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + //check funds have been paid to the reward manager + assertEq(rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE); + } + + function test_V1PayloadVerifies() public { + //replicate a default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV2Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_V2PayloadVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_V2PayloadWithoutQuoteFails() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(0), 0); + } + + function test_V2PayloadWithoutZeroFee() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithInvalidReportVersionFailsToDecode() public { + bytes memory data = abi.encode(0x0000100000000000000000000000000000000000000000000000000000000000); + + //get the default payload + bytes memory payload = getPayload(data); + + //serialization will fail as there is no report to decode + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, PROXY, address(native), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link to the rewardManager from the user + processFee(payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + + //check the feeManager has had no link deducted + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkReturnsChange() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the change has been returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_V1PayloadVerifiesAndReturnsChange() public { + //emulate a V1 payload with no quote + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + processFee(payload, USER, address(0), DEFAULT_REPORT_NATIVE_FEE); + + //Fee manager should not contain any native + assertEq(address(feeManager).balance, 0); + assertEq(getNativeBalance(address(feeManager)), 0); + + //check the unused native passed in is returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithDiscountEmitsEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE / 2, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + uint256 appliedDiscount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + vm.expectEmit(); + + emit DiscountApplied(DEFAULT_CONFIG_DIGEST, USER, fee, reward, appliedDiscount); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(native), 0); + } + + function test_processFeeWithNoDiscountDoesNotEmitEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee should not revert as the fee is 0 + processFee(payload, USER, address(native), 0); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol new file mode 100644 index 0000000..fa77b98 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseFeeManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract FeeManagerProcessFeeTest is BaseFeeManagerTest { + uint256 internal constant NUMBER_OF_REPORTS = 5; + + function setUp() public override { + super.setUp(); + } + + function test_processMultipleLinkReports() public { + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); + + processFee(payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); + + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 0); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + + //the subscriber (user) should receive funds back and not the proxy, although when live the proxy will forward the funds sent and not cover it seen here + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleWrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS, USER); + + processFee(payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processMultipleUnwrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processV1V2V3Reports() public { + mintLink(address(feeManager), 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory linkPayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory linkPayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = linkPayloadV2; + payloads[2] = linkPayloadV2; + payloads[3] = linkPayloadV3; + payloads[4] = linkPayloadV3; + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * 4, USER); + + processFee(payloads, USER, address(link), 0); + + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - 0); + } + + function test_processV1V2V3ReportsWithUnwrapped() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 4 + 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory nativePayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory nativePayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = nativePayloadV2; + payloads[2] = nativePayloadV2; + payloads[3] = nativePayloadV3; + payloads[4] = nativePayloadV3; + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 4); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleV1Reports() public { + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 5); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_eventIsEmittedIfNotEnoughLink() public { + bytes memory nativePayload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = nativePayload; + payloads[1] = nativePayload; + payloads[2] = nativePayload; + payloads[3] = nativePayload; + payloads[4] = nativePayload; + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 5, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](5); + payments[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[1] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[2] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[3] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[4] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + vm.expectEmit(); + + emit InsufficientLink(payments); + + processFee(payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol new file mode 100644 index 0000000..ee8ba4c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "../verifier/BaseVerifierTest.t.sol"; +import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +contract Verifier_setConfig is BaseTest { + address[] internal s_signerAddrs; + + function setUp() public override { + BaseTest.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + s_signerAddrs = _getSignerAddresses(signers); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } + + function testSetConfigSuccess_gas() public { + s_verifier.setConfig( + FEED_ID, + s_signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } +} + +contract Verifier_verifyWithFee is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + function setUp() public virtual override { + super.setUp(); + + //mint some link and eth to warm the storage + link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); + native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //warm the rewardManager + link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); + (, , bytes32 latestConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //approve funds prior to test + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); + + changePrank(address(feeManager)); + rewardManager.onFeePaid(payments, address(this)); + + changePrank(USER); + } + + function testVerifyProxyWithLinkFeeSuccess_gas() public { + bytes memory signedLinkPayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + s_verifierProxy.verify(signedLinkPayload, abi.encode(link)); + } + + function testVerifyProxyWithNativeFeeSuccess_gas() public { + bytes memory signedNativePayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + s_verifierProxy.verify(signedNativePayload, abi.encode(native)); + } +} + +contract Verifier_bulkVerifyWithFee is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + uint256 internal constant NUMBER_OF_REPORTS_TO_VERIFY = 5; + + function setUp() public virtual override { + super.setUp(); + + //mint some link and eth to warm the storage + link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); + native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //warm the rewardManager + link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); + (, , bytes32 latestConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY); + + //approve funds prior to test + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); + + changePrank(address(feeManager)); + rewardManager.onFeePaid(payments, address(this)); + + changePrank(USER); + } + + function testBulkVerifyProxyWithLinkFeeSuccess_gas() public { + bytes memory signedLinkPayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedLinkPayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); + for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { + signedLinkPayloads[i] = signedLinkPayload; + } + + s_verifierProxy.verifyBulk(signedLinkPayloads, abi.encode(link)); + } + + function testBulkVerifyProxyWithNativeFeeSuccess_gas() public { + bytes memory signedNativePayload = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedNativePayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); + for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { + signedNativePayloads[i] = signedNativePayload; + } + + s_verifierProxy.verifyBulk(signedNativePayloads, abi.encode(native)); + } +} + +contract Verifier_verify is BaseTestWithConfiguredVerifierAndFeeManager { + bytes internal s_signedReport; + bytes32 internal s_configDigest; + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + BaseTest.V1Report memory s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); + bytes32[3] memory reportContext; + reportContext[0] = s_configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); + } + + function testVerifySuccess_gas() public { + changePrank(address(s_verifierProxy)); + + s_verifier.verify(s_signedReport, msg.sender); + } + + function testVerifyProxySuccess_gas() public { + s_verifierProxy.verify(s_signedReport, abi.encode(native)); + } +} + +contract Verifier_accessControlledVerify is BaseTestWithConfiguredVerifierAndFeeManager { + bytes internal s_signedReport; + bytes32 internal s_configDigest; + SimpleWriteAccessController s_accessController; + + address internal constant CLIENT = address(9000); + address internal constant ACCESS_CONTROLLER_ADDR = address(10000); + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + BaseTest.V1Report memory s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); + bytes32[3] memory reportContext; + reportContext[0] = s_configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); + s_accessController = new SimpleWriteAccessController(); + s_verifierProxy.setAccessController(s_accessController); + s_accessController.addAccess(CLIENT); + } + + function testVerifyWithAccessControl_gas() public { + changePrank(CLIENT); + s_verifierProxy.verify(s_signedReport, abi.encode(native)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol new file mode 100644 index 0000000..e9dcd58 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract ErroredVerifier is IVerifier { + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == this.verify.selector; + } + + //define each of the errors thrown in the revert below + + error FailedToVerify(); + error FailedToSetConfig(); + error FailedToActivateConfig(); + error FailedToDeactivateConfig(); + error FailedToActivateFeed(); + error FailedToDeactivateFeed(); + error FailedToGetLatestConfigDigestAndEpoch(); + error FailedToGetLatestConfigDetails(); + + function verify( + bytes memory, + /** + * signedReport* + */ + address + ) + external + pure + override + returns ( + /** + * sender* + */ + bytes memory + ) + { + revert FailedToVerify(); + } + + function setConfig( + bytes32, + address[] memory, + bytes32[] memory, + uint8, + bytes memory, + uint64, + bytes memory, + Common.AddressAndWeight[] memory + ) external pure override { + revert FailedToSetConfig(); + } + + function setConfigFromSource( + bytes32, + uint256, + address, + uint32, + address[] memory, + bytes32[] memory, + uint8, + bytes memory, + uint64, + bytes memory, + Common.AddressAndWeight[] memory + ) external pure override { + revert FailedToSetConfig(); + } + + function activateConfig(bytes32, bytes32) external pure { + revert FailedToActivateConfig(); + } + + function deactivateConfig(bytes32, bytes32) external pure { + revert FailedToDeactivateConfig(); + } + + function activateFeed(bytes32) external pure { + revert FailedToActivateFeed(); + } + + function deactivateFeed(bytes32) external pure { + revert FailedToDeactivateFeed(); + } + + function latestConfigDigestAndEpoch(bytes32) external pure override returns (bool, bytes32, uint32) { + revert FailedToGetLatestConfigDigestAndEpoch(); + } + + function latestConfigDetails(bytes32) external pure override returns (uint32, uint32, bytes32) { + revert FailedToGetLatestConfigDetails(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol new file mode 100644 index 0000000..1c004bf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +// ExposedVerifier exposes certain internal Verifier +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedVerifier { + constructor() {} + + function _configDigestFromConfigData( + bytes32 feedId, + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + feedId, + chainId, + contractAddress, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + function exposedConfigDigestFromConfigData( + bytes32 _feedId, + uint256 _chainId, + address _contractAddress, + uint64 _configCount, + address[] memory _signers, + bytes32[] memory _offchainTransmitters, + uint8 _f, + bytes calldata _onchainConfig, + uint64 _encodedConfigVersion, + bytes memory _encodedConfig + ) public pure returns (bytes32) { + return + _configDigestFromConfigData( + _feedId, + _chainId, + _contractAddress, + _configCount, + _signers, + _offchainTransmitters, + _f, + _onchainConfig, + _encodedConfigVersion, + _encodedConfig + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol new file mode 100644 index 0000000..9abb4c5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IFeeManager} from "../../interfaces/IFeeManager.sol"; + +contract FeeManagerProxy { + IFeeManager internal s_feeManager; + + function processFee(bytes calldata payload, bytes calldata parameterPayload) public payable { + s_feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); + } + + function processFeeBulk(bytes[] calldata payloads, bytes calldata parameterPayload) public payable { + s_feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); + } + + function setFeeManager(IFeeManager feeManager) public { + s_feeManager = feeManager; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol new file mode 100644 index 0000000..c7bd752 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {RewardManager} from "../../../v0.3.0/RewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice Base class for all reward manager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup a primary and secondary pool + */ +contract BaseRewardManagerTest is Test { + //contracts + ERC20Mock internal asset; + ERC20Mock internal unsupported; + RewardManager internal rewardManager; + + //default address for unregistered recipient + address internal constant INVALID_ADDRESS = address(0); + //contract owner + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + //address to represent verifier contract + address internal constant FEE_MANAGER = address(uint160(uint256(keccak256("FEE_MANAGER")))); + //a general user + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + + //default recipients configured in reward manager + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); + address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); + address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); + address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); + address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); + address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); + + //additional recipients not in the reward manager + address internal constant DEFAULT_RECIPIENT_8 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_8")))); + address internal constant DEFAULT_RECIPIENT_9 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_9")))); + + //two pools should be enough to test all edge cases + bytes32 internal constant PRIMARY_POOL_ID = keccak256("primary_pool"); + bytes32 internal constant SECONDARY_POOL_ID = keccak256("secondary_pool"); + bytes32 internal constant INVALID_POOL_ID = keccak256("invalid_pool"); + bytes32 internal constant ZERO_POOL_ID = bytes32(0); + + //convenience arrays of all pool combinations used for testing + bytes32[] internal PRIMARY_POOL_ARRAY = [PRIMARY_POOL_ID]; + bytes32[] internal SECONDARY_POOL_ARRAY = [SECONDARY_POOL_ID]; + bytes32[] internal ALL_POOLS = [PRIMARY_POOL_ID, SECONDARY_POOL_ID]; + + //erc20 config + uint256 internal constant DEFAULT_MINT_QUANTITY = 100 ether; + + //reward scalar (this should match the const in the contract) + uint64 internal constant POOL_SCALAR = 1e18; + uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; + uint64 internal constant FIFTY_PERCENT = POOL_SCALAR / 2; + uint64 internal constant TEN_PERCENT = POOL_SCALAR / 10; + + //the selector for each error + bytes4 internal immutable UNAUTHORIZED_ERROR_SELECTOR = RewardManager.Unauthorized.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR_SELECTOR = RewardManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_WEIGHT_ERROR_SELECTOR = RewardManager.InvalidWeights.selector; + bytes4 internal immutable INVALID_POOL_ID_ERROR_SELECTOR = RewardManager.InvalidPoolId.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes4 internal immutable INVALID_POOL_LENGTH_SELECTOR = RewardManager.InvalidPoolLength.selector; + + // Events emitted within the reward manager + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newProxyAddress); + event FeePaid(IRewardManager.FeePayment[] payments, address payee); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeERC20Contracts(); + _initializeRewardManager(); + } + + function _initializeERC20Contracts() internal { + //create the contracts + asset = new ERC20Mock("ASSET", "AST", ADMIN, 0); + unsupported = new ERC20Mock("UNSUPPORTED", "UNS", ADMIN, 0); + + //mint some tokens to the admin + asset.mint(ADMIN, DEFAULT_MINT_QUANTITY); + unsupported.mint(ADMIN, DEFAULT_MINT_QUANTITY); + + //mint some tokens to the user + asset.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + unsupported.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + } + + function _initializeRewardManager() internal { + //create the contract + rewardManager = new RewardManager(address(asset)); + + rewardManager.setFeeManager(FEE_MANAGER); + } + + function createPrimaryPool() public { + rewardManager.setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients()); + } + + function createSecondaryPool() public { + rewardManager.setRewardRecipients(SECONDARY_POOL_ID, getSecondaryRecipients()); + } + + //override this to test variations of different recipients. changing this function will require existing tests to be updated as constants are hardcoded to be explicit + function getPrimaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); + + return recipients; + } + + function getPrimaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_2; + recipients[2] = DEFAULT_RECIPIENT_3; + recipients[3] = DEFAULT_RECIPIENT_4; + + return recipients; + } + + //override this to test variations of different recipients. + function getSecondaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); + + return recipients; + } + + function getSecondaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_5; + recipients[2] = DEFAULT_RECIPIENT_6; + recipients[3] = DEFAULT_RECIPIENT_7; + + return recipients; + } + + function addFundsToPool(bytes32 poolId, Common.Asset memory amount, address sender) public { + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(poolId, uint192(amount.amount)); + + addFundsToPool(payments, sender); + } + + function addFundsToPool(IRewardManager.FeePayment[] memory payments, address sender) public { + //record the current address and switch to the sender + address originalAddr = msg.sender; + changePrank(sender); + + uint256 totalPayment; + for (uint256 i; i < payments.length; ++i) { + totalPayment += payments[i].amount; + } + + //approve the amount being paid into the pool + ERC20Mock(address(asset)).approve(address(rewardManager), totalPayment); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, sender); + + //change back to the original address + changePrank(originalAddr); + } + + function getAsset(uint256 quantity) public view returns (Common.Asset memory) { + return Common.Asset(address(asset), quantity); + } + + function getAssetBalance(address addr) public view returns (uint256) { + return asset.balanceOf(addr); + } + + function claimRewards(bytes32[] memory poolIds, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //claim the rewards + rewardManager.claimRewards(poolIds); + + //change back to the original address + changePrank(originalAddr); + } + + function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.payRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.setRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setFeeManager(address feeManager, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //update the proxy + rewardManager.setFeeManager(feeManager); + + //change back to the original address + changePrank(originalAddr); + } + + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.updateRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol new file mode 100644 index 0000000..efbe9fd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the claim functionality of the RewardManager contract. + */ +contract RewardManagerClaimTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipients() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } + + function test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() public { + //add funds to a different pool to ensure they're not claimed + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create an array containing duplicate poolIds + bytes32[] memory poolIds = new bytes32[](2); + poolIds[0] = PRIMARY_POOL_ID; + poolIds[1] = PRIMARY_POOL_ID; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(poolIds, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the pool should still have the remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimSingleRecipient() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + } + + function test_claimMultipleRecipients() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - (expectedRecipientAmount * 2)); + } + + function test_claimUnregisteredRecipient() public { + //claim the rewards for a recipient who isn't in this pool + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding 1 to the pool should leave 1 wei worth of dust, which the contract doesn't handle due to it being economically infeasible + addFundsToPool(PRIMARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the rewardManager has the remaining quantity equals 1 wei + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_claimUnregisteredPoolId() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance is still 0 as there's no pool to receive fees from + assertEq(getAssetBalance(recipient.addr), 0); + + //check the rewardManager has the full amount + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_recipientsClaimMultipleDeposits() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should again be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + } + + function test_eventIsEmittedUponClaim() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardsClaimed(PRIMARY_POOL_ID, recipient.addr, uint192(POOL_DEPOSIT_AMOUNT / 4)); + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + } + + function test_eventIsNotEmittedUponUnsuccessfulClaim() public { + //record logs to check no events were emitted + vm.recordLogs(); + + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} + +contract RewardManagerRecipientClaimMultiplePoolsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a two pools + createPrimaryPool(); + createSecondaryPool(); + + //add funds to each of the pools to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsSinglePool() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the pool balance is still equal to DEPOSIT_AMOUNT as the test only claims for one of the pools + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimMultipleRecipientsSinglePool() public { + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_claimMultipleRecipientsMultiplePools() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received. The first recipient is shared across both pools so should receive 1/4 of each pool + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount * 2); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimAllRecipientsMultiplePools() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory secondaryRecipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, secondaryRecipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(secondaryRecipient.addr), expectedRecipientAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + Common.AddressAndWeight memory commonRecipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, commonRecipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, commonRecipient.addr); + + //check the balance matches the ratio the recipient should have received, which is 1/4 of each deposit for each pool + assertEq(getAssetBalance(commonRecipient.addr), expectedRecipientAmount * 2); + } + + function test_claimSingleUniqueRecipient() public { + //the first recipient of the secondary pool is in both pools, so take the second recipient which is unique + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[1]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //the recipient should have received 1/4 of the deposit amount + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimSingleRecipientMultiplePools() public { + //the first recipient of the secondary pool is in both pools + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //this recipient belongs in both pools so should have received 1/4 of each + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimUnregisteredRecipient() public { + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding an uneven amount of dust to each pool, this should round down to the nearest whole number with 4 remaining in the contract + addFundsToPool(PRIMARY_POOL_ID, getAsset(3), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), recipientExpectedAmount * 2); + + //claim funds for each recipient of the secondary pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //contract should have 4 remaining + assertEq(getAssetBalance(address(rewardManager)), 4); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit plus the deposit from the second pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the next deposit amount + expectedRecipientAmount += POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 3 - expectedRecipientAmount); + } + + function test_recipientsClaimMultipleDeposits() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should contain only the funds of the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount * 2); + + //claim funds for each recipient within the pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + } + + //the reward manager balance should again be the balance of the secondary pool as the primary pool has been emptied twice + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimEmptyPoolWhenSecondPoolContainsFunds() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim all rewards for each recipient in the primary pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim all the rewards again for the first recipient as that address is a member of both pools + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + } + + function test_getRewardsAvailableToRecipientInBothPools() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInSinglePool() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[1].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInNoPools() public view { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, 0, type(uint256).max); + + //check the recipient is in neither pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + + //claim the rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //get the available pools again + poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, type(uint256).max); + + //user should not be in any pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() public { + vm.expectRevert(INVALID_POOL_LENGTH_SELECTOR); + + rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, type(uint256).max, 0); + } + + function test_getAvailableRewardsCursorAndTotalPoolsEqual() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 2, 2); + + assertEq(poolIds.length, 0); + } + + function test_getAvailableRewardsCursorSingleResult() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, 1); + + assertEq(poolIds[0], PRIMARY_POOL_ID); + } +} + +contract RewardManagerRecipientClaimDifferentWeightsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with uneven weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 8); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 6); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 4); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} + +contract RewardManagerRecipientClaimUnevenWeightTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + + uint64 oneThird = POOL_SCALAR / 3; + + //init each recipient with even weights. + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, oneThird); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 2 * oneThird + 1); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() public { + //add a smaller amount of funds to the pool + uint256 smallDeposit = 1e8; + + //add a smaller amount of funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(smallDeposit), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (smallDeposit * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //smaller deposits will consequently have less precision and will not be able to be split as evenly, the remaining 1 will be lost due to 333...|... being paid out instead of 333...4| + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //their should be 0 wei left over indicating a successful split + assertEq(getAssetBalance(address(rewardManager)), 0); + } +} + +contract RewardManagerNoRecipientSet is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //add funds to the pool to be split among the recipients once registered + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsAfterRecipientsSet() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //try and claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is not registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipient received nothing + assertEq(getAssetBalance(recipient.addr), 0); + } + + //Set the recipients after the rewards have been paid into the pool + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol new file mode 100644 index 0000000..baff388 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {RewardManager} from "../../../v0.3.0/RewardManager.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the core functionality of the RewardManager contract + */ +contract RewardManagerSetupTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_rejectsZeroLinkAddressOnConstruction() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //create a rewardManager with a zero link address + new RewardManager(address(0)); + } + + function test_eventEmittedUponFeeManagerUpdate() public { + //expect the event to be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit FeeManagerUpdated(FEE_MANAGER); + + //set the verifier proxy + setFeeManager(FEE_MANAGER, ADMIN); + } + + function test_eventEmittedUponFeePaid() public { + //create pool and add funds + createPrimaryPool(); + + //change to the feeManager who is the one who will be paying the fees + changePrank(FEE_MANAGER); + + //approve the amount being paid into the pool + ERC20Mock(getAsset(POOL_DEPOSIT_AMOUNT).assetAddress).approve(address(rewardManager), POOL_DEPOSIT_AMOUNT); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //event is emitted when funds are added + vm.expectEmit(); + emit FeePaid(payments, FEE_MANAGER); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, FEE_MANAGER); + } + + function test_setFeeManagerZeroAddress() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the verifier proxy + setFeeManager(address(0), ADMIN); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol new file mode 100644 index 0000000..89fac66 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {IRewardManager} from "../../interfaces/IRewardManager.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the payRecipients functionality of the RewardManager contract + */ +contract RewardManagerPayRecipientsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_payAllRecipients() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySingleRecipient() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + assertEq(getAssetBalance(recipient), expectedRecipientAmount); + } + + function test_payRecipientWithInvalidPool() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(SECONDARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received nothing + assertEq(getAssetBalance(recipient), 0); + } + + function test_payRecipientsEmptyRecipientList() public { + //get a single recipient + address[] memory recipients = new address[](0); + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //rewardManager should have the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_payAllRecipientsWithAdditionalUnregisteredRecipient() public { + //load all the recipients and add an additional one who is not in the pool + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = DEFAULT_RECIPIENT_5; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + + //the unregistered recipient should receive nothing + assertEq(getAssetBalance(DEFAULT_RECIPIENT_5), 0); + } + + function test_payAllRecipientsWithAdditionalInvalidRecipient() public { + //load all the recipients and add an additional one which is invalid, that should receive nothing + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = INVALID_ADDRESS; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySubsetOfRecipientsInPool() public { + //load a subset of the recipients into an array + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length - 1); + for (uint256 i = 0; i < recipients.length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + + //pay the subset of recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each subset of recipients received the correct amount + for (uint256 i = 0; i < recipients.length - 1; i++) { + assertEq(getAssetBalance(recipients[i]), expectedRecipientAmount); + } + + //check the pool has the remaining balance + assertEq( + getAssetBalance(address(rewardManager)), + POOL_DEPOSIT_AMOUNT - expectedRecipientAmount * recipients.length + ); + } + + function test_payAllRecipientsFromNonAdminUser() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), FEE_MANAGER); + } + + function test_payAllRecipientsFromRecipientInPool() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), DEFAULT_RECIPIENT_1); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_payRecipientsWithInvalidPoolId() public { + //pay all the recipients in the pool + payRecipients(INVALID_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //pool should still contain the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_addFundsToPoolAsOwner() public { + //add funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_addFundsToPoolAsNonOwnerOrFeeManager() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); + payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //add funds to the pool + rewardManager.onFeePaid(payments, USER); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol new file mode 100644 index 0000000..d3e6990 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the setRecipient functionality of the RewardManager contract + */ +contract RewardManagerSetRecipientsTest is BaseRewardManagerTest { + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_setRewardRecipients() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientsIsEmpty() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroWeight() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 25); + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, 0); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroAddress() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = getPrimaryRecipients(); + + //override the first recipient with a zero address + recipients[0].addr = address(0); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWeights() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, 25); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setSingleRewardRecipient() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientTwice() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //should revert if recipients for this pool have already been set + vm.expectRevert(INVALID_POOL_ID_ERROR_SELECTOR); + + //set the recipients again + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() public { + //should revert if the sender is not the owner or proxy + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), USER); + } + + function test_setRewardRecipientFromManagerAddress() public { + //update the proxy address + setFeeManager(FEE_MANAGER, ADMIN); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); + } + + function test_eventIsEmittedUponSetRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRecipientContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol new file mode 100644 index 0000000..0d3a2b6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title BaseRewardManagerTest + * @author Michael Fletcher + * @notice This contract will test the updateRecipient functionality of the RewardManager contract + */ +contract RewardManagerUpdateRewardRecipientsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_onlyAdminCanUpdateRecipients() public { + //should revert if the caller is not the admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); + } + + function test_updateAllRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } + + function test_updatePartialRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //get a subset of the recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have half remaining funds + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + } + + function test_updateRecipientWithNewZeroAddress() public { + //create a new array to hold the existing recipients plus a new zero address + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 1); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add a new address to the primary recipients + recipients[recipients.length - 1] = Common.AddressAndWeight(address(0), 0); + + //should revert if the recipient is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with invalid address + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with the duplicate addresses + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 4); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, ONE_PERCENT * 25); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, ONE_PERCENT * 25); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, ONE_PERCENT * 25); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentPartialSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, FIFTY_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, FIFTY_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 5); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 2); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT * 2); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT * 2); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT * 2); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT * 2); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](9); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 3); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT); + + //should revert as the weight does not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 2); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSetWithInvalidWeights() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + + //should revert as the weight will not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsToSubset() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 0); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 0); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 5); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithUnderWeightSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithExcessiveWeight() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have no funds remaining + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_3), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 3) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_4), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 5) / POOL_SCALAR + expectedRecipientAmount + ); + } + + function test_partialUpdateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_eventIsEmittedUponUpdateRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } +} + +contract RewardManagerUpdateRewardRecipientsMultiplePoolsTest is BaseRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + createSecondaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getSecondaryRecipients() public override returns (Common.AddressAndWeight[] memory) { + //for testing purposes, the primary and secondary pool to contain the same recipients + return getPrimaryRecipients(); + } + + function test_updatePrimaryRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT * 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have the funds for the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the rewards for the updated recipients manually + claimRewards(PRIMARY_POOL_ARRAY, recipients[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[1].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[2].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[3].addr); + + //check the balance matches the ratio the recipient who were updated should have received + assertEq( + getAssetBalance(recipients[0].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[1].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[2].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[3].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol new file mode 100644 index 0000000..4d65414 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {VerifierProxy} from "../../VerifierProxy.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {ErroredVerifier} from "../mocks/ErroredVerifier.sol"; +import {Verifier} from "../../Verifier.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {FeeManager} from "../../FeeManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {RewardManager} from "../../RewardManager.sol"; + +contract BaseTest is Test { + uint256 internal constant MAX_ORACLES = 31; + address internal constant ADMIN = address(1); + address internal constant USER = address(2); + address internal constant MOCK_VERIFIER_ADDRESS = address(100); + address internal constant MOCK_VERIFIER_ADDRESS_TWO = address(200); + address internal constant ACCESS_CONTROLLER_ADDRESS = address(300); + + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + //version 0 feeds + bytes32 internal constant FEED_ID = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_2 = (keccak256("LINK-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_3 = (keccak256("BTC-USD") & V_MASK) | V1_BITMASK; + + //version 3 feeds + bytes32 internal constant FEED_ID_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + bytes32 internal constant INVALID_FEED = keccak256("INVALID"); + uint32 internal constant OBSERVATIONS_TIMESTAMP = 1000; + uint64 internal constant BLOCKNUMBER_LOWER_BOUND = 1000; + uint64 internal constant BLOCKNUMBER_UPPER_BOUND = BLOCKNUMBER_LOWER_BOUND + 5; + int192 internal constant MEDIAN = 1 ether; + int192 internal constant BID = 500000000 gwei; + int192 internal constant ASK = 2 ether; + + bytes32 internal constant EMPTY_BYTES = bytes32(""); + + uint8 internal constant FAULT_TOLERANCE = 10; + uint64 internal constant VERIFIER_VERSION = 1; + + string internal constant SERVER_URL = "https://mercury.server/client/"; + uint8 internal constant MAX_COMMITMENT_DELAY = 5; + + VerifierProxy internal s_verifierProxy; + Verifier internal s_verifier; + Verifier internal s_verifier_2; + ErroredVerifier internal s_erroredVerifier; + + struct Signer { + uint256 mockPrivateKey; + address signerAddress; + } + + struct V1Report { + // The feed ID the report has data for + bytes32 feedId; + // The time the median value was observed on + uint32 observationsTimestamp; + // The median value agreed in an OCR round + int192 median; + // The best bid value agreed in an OCR round + int192 bid; + // The best ask value agreed in an OCR round + int192 ask; + // The upper bound of the block range the median value was observed within + uint64 blocknumberUpperBound; + // The blockhash for the upper bound of block range (ensures correct blockchain) + bytes32 upperBlockhash; + // The lower bound of the block range the median value was observed within + uint64 blocknumberLowerBound; + // The current block timestamp + uint64 currentBlockTimestamp; + } + + Signer[MAX_ORACLES] internal s_signers; + bytes32[] internal s_offchaintransmitters; + bool private s_baseTestInitialized; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + vm.startPrank(ADMIN); + vm.mockCall( + MOCK_VERIFIER_ADDRESS, + abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), + abi.encode(true) + ); + s_verifierProxy = new VerifierProxy(AccessControllerInterface(address(0))); + + s_verifier = new Verifier(address(s_verifierProxy)); + s_verifier_2 = new Verifier(address(s_verifierProxy)); + s_erroredVerifier = new ErroredVerifier(); + + for (uint256 i; i < MAX_ORACLES; i++) { + uint256 mockPK = i + 1; + s_signers[i].mockPrivateKey = mockPK; + s_signers[i].signerAddress = vm.addr(mockPK); + } + } + + function _getSigners(uint256 numSigners) internal view returns (Signer[] memory) { + Signer[] memory signers = new Signer[](numSigners); + for (uint256 i; i < numSigners; i++) { + signers[i] = s_signers[i]; + } + return signers; + } + + function _getSignerAddresses(Signer[] memory signers) internal view returns (address[] memory) { + address[] memory signerAddrs = new address[](signers.length); + for (uint256 i = 0; i < signerAddrs.length; i++) { + signerAddrs[i] = s_signers[i].signerAddress; + } + return signerAddrs; + } + + function _generateSignerSignatures( + bytes memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) { + bytes32[] memory rs = new bytes32[](signers.length); + bytes32[] memory ss = new bytes32[](signers.length); + bytes memory vs = new bytes(signers.length); + + bytes32 hash = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signers.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].mockPrivateKey, hash); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + return (rs, ss, bytes32(vs)); + } + + function _encodeReport(V1Report memory report) internal pure returns (bytes memory) { + return + abi.encode( + report.feedId, + report.observationsTimestamp, + report.median, + report.bid, + report.ask, + report.blocknumberUpperBound, + report.upperBlockhash, + report.blocknumberLowerBound, + report.currentBlockTimestamp + ); + } + + function _generateV1EncodedBlob( + V1Report memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes memory) { + bytes memory reportBytes = _encodeReport(report); + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( + reportBytes, + reportContext, + signers + ); + return abi.encode(reportContext, reportBytes, rs, ss, rawVs); + } + + function _configDigestFromConfigData( + bytes32 feedId, + uint256 chainId, + address verifierAddr, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + feedId, + chainId, + verifierAddr, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + function _createV1Report( + bytes32 feedId, + uint32 observationsTimestamp, + int192 median, + int192 bid, + int192 ask, + uint64 blocknumberUpperBound, + bytes32 upperBlockhash, + uint64 blocknumberLowerBound, + uint32 currentBlockTimestamp + ) internal pure returns (V1Report memory) { + return + V1Report({ + feedId: feedId, + observationsTimestamp: observationsTimestamp, + median: median, + bid: bid, + ask: ask, + blocknumberUpperBound: blocknumberUpperBound, + upperBlockhash: upperBlockhash, + blocknumberLowerBound: blocknumberLowerBound, + currentBlockTimestamp: currentBlockTimestamp + }); + } + + function _ccipReadURL(bytes32 feedId, uint256 commitmentBlock) internal pure returns (string memory url) { + return + string( + abi.encodePacked( + SERVER_URL, + "?feedIDHex=", + Strings.toHexString(uint256(feedId)), + "&L2Blocknumber=", + Strings.toString(commitmentBlock) + ) + ); + } +} + +contract BaseTestWithConfiguredVerifierAndFeeManager is BaseTest { + FeeManager internal feeManager; + RewardManager internal rewardManager; + ERC20Mock internal link; + WERC20Mock internal native; + + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + bytes32 internal v1ConfigDigest; + bytes32 internal v3ConfigDigest; + + struct V3Report { + // The feed ID the report has data for + bytes32 feedId; + // The time the median value was observed on + uint32 observationsTimestamp; + // The timestamp the report is valid from + uint32 validFromTimestamp; + // The link fee + uint192 linkFee; + // The native fee + uint192 nativeFee; + // The expiry of the report + uint32 expiresAt; + // The median value agreed in an OCR round + int192 benchmarkPrice; + // The best bid value agreed in an OCR round + int192 bid; + // The best ask value agreed in an OCR round + int192 ask; + } + + function setUp() public virtual override { + BaseTest.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_verifierProxy.initializeVerifier(address(s_verifier)); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , v1ConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + + s_verifier.setConfig( + FEED_ID_V3, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , v3ConfigDigest) = s_verifier.latestConfigDetails(FEED_ID_V3); + + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + native = new WERC20Mock(); + + rewardManager = new RewardManager(address(link)); + feeManager = new FeeManager(address(link), address(native), address(s_verifierProxy), address(rewardManager)); + + s_verifierProxy.setFeeManager(feeManager); + rewardManager.setFeeManager(address(feeManager)); + } + + function _encodeReport(V3Report memory report) internal pure returns (bytes memory) { + return + abi.encode( + report.feedId, + report.observationsTimestamp, + report.validFromTimestamp, + report.nativeFee, + report.linkFee, + report.expiresAt, + report.benchmarkPrice, + report.bid, + report.ask + ); + } + + function _generateV3EncodedBlob( + V3Report memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes memory) { + bytes memory reportBytes = _encodeReport(report); + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( + reportBytes, + reportContext, + signers + ); + return abi.encode(reportContext, reportBytes, rs, ss, rawVs); + } + + function _generateV1Report() internal view returns (V1Report memory) { + return + _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + bytes32(blockhash(BLOCKNUMBER_UPPER_BOUND)), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + } + + function _generateV3Report() internal view returns (V3Report memory) { + return + V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function _generateReportContext(bytes32 configDigest) internal pure returns (bytes32[3] memory) { + bytes32[3] memory reportContext; + reportContext[0] = configDigest; + reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + return reportContext; + } + + function _approveLink(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + link.approve(spender, quantity); + changePrank(originalAddr); + } + + function _approveNative(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + native.approve(spender, quantity); + changePrank(originalAddr); + } + + function _verify(bytes memory payload, address feeAddress, uint256 wrappedNativeValue, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } + + function _verifyBulk( + bytes[] memory payload, + address feeAddress, + uint256 wrappedNativeValue, + address sender + ) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verifyBulk{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } +} + +contract BaseTestWithMultipleConfiguredDigests is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32 internal s_configDigestOne; + bytes32 internal s_configDigestTwo; + bytes32 internal s_configDigestThree; + bytes32 internal s_configDigestFour; + bytes32 internal s_configDigestFive; + + uint32 internal s_numConfigsSet; + + uint8 internal constant FAULT_TOLERANCE_TWO = 2; + uint8 internal constant FAULT_TOLERANCE_THREE = 1; + + function setUp() public virtual override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + (, , s_configDigestOne) = s_verifier.latestConfigDetails(FEED_ID); + + // Verifier 1, Feed 1, Config 2 + Signer[] memory secondSetOfSigners = _getSigners(8); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(secondSetOfSigners), + s_offchaintransmitters, + FAULT_TOLERANCE_TWO, + bytes(""), + 2, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , s_configDigestTwo) = s_verifier.latestConfigDetails(FEED_ID); + + // Verifier 1, Feed 1, Config 3 + Signer[] memory thirdSetOfSigners = _getSigners(5); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(thirdSetOfSigners), + s_offchaintransmitters, + FAULT_TOLERANCE_THREE, + bytes(""), + 3, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (s_numConfigsSet, , s_configDigestThree) = s_verifier.latestConfigDetails(FEED_ID); + + // Verifier 1, Feed 2, Config 1 + s_verifier.setConfig( + FEED_ID_2, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + 4, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , s_configDigestFour) = s_verifier.latestConfigDetails(FEED_ID_2); + + // Verifier 2, Feed 3, Config 1 + s_verifierProxy.initializeVerifier(address(s_verifier_2)); + s_verifier_2.setConfig( + FEED_ID_3, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , s_configDigestFive) = s_verifier_2.latestConfigDetails(FEED_ID_3); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol new file mode 100644 index 0000000..99daabe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; + +contract VerifierActivateConfigTest is BaseTestWithConfiguredVerifierAndFeeManager { + function test_revertsIfNotOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(address(s_verifierProxy)); + s_verifier.activateConfig(FEED_ID, bytes32("mock")); + } + + function test_revertsIfDigestIsEmpty() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); + s_verifier.activateConfig(FEED_ID, bytes32("")); + } + + function test_revertsIfDigestNotSet() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, FEED_ID, bytes32("non-existent-digest"))); + s_verifier.activateConfig(FEED_ID, bytes32("non-existent-digest")); + } +} + +contract VerifierActivateConfigWithDeactivatedConfigTest is BaseTestWithMultipleConfiguredDigests { + bytes32[3] internal s_reportContext; + + event ConfigActivated(bytes32 configDigest); + + V1Report internal s_testReportOne; + + function setUp() public override { + BaseTestWithMultipleConfiguredDigests.setUp(); + s_reportContext[0] = s_configDigestTwo; + s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportOne = _createV1Report( + FEED_ID, + uint32(block.timestamp), + MEDIAN, + BID, + ASK, + uint64(block.number), + blockhash(block.number + 3), + uint64(block.number + 3), + uint32(block.timestamp) + ); + + s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); + } + + function test_allowsVerification() public { + s_verifier.activateConfig(FEED_ID, s_configDigestTwo); + changePrank(address(s_verifierProxy)); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + s_verifier.verify(signedReport, msg.sender); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol new file mode 100644 index 0000000..fb52c1c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; + +contract VerifierActivateFeedTest is BaseTestWithConfiguredVerifierAndFeeManager { + function test_revertsIfNotOwnerActivateFeed() public { + changePrank(address(s_verifierProxy)); + vm.expectRevert("Only callable by owner"); + s_verifier.activateFeed(FEED_ID); + } + + function test_revertsIfNotOwnerDeactivateFeed() public { + changePrank(address(s_verifierProxy)); + vm.expectRevert("Only callable by owner"); + s_verifier.deactivateFeed(FEED_ID); + } + + function test_revertsIfNoFeedExistsActivate() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.InvalidFeed.selector, INVALID_FEED)); + s_verifier.activateFeed(INVALID_FEED); + } + + function test_revertsIfNoFeedExistsDeactivate() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.InvalidFeed.selector, INVALID_FEED)); + s_verifier.deactivateFeed(INVALID_FEED); + } +} + +contract VerifierDeactivateFeedWithVerifyTest is BaseTestWithMultipleConfiguredDigests { + bytes32[3] internal s_reportContext; + + event ConfigActivated(bytes32 configDigest); + + V1Report internal s_testReportOne; + + function setUp() public override { + BaseTestWithMultipleConfiguredDigests.setUp(); + s_reportContext[0] = s_configDigestOne; + s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportOne = _createV1Report( + FEED_ID, + uint32(block.timestamp), + MEDIAN, + BID, + ASK, + uint64(block.number), + blockhash(block.number + 3), + uint64(block.number + 3), + uint32(block.timestamp) + ); + + s_verifier.deactivateFeed(FEED_ID); + } + + function test_currentReportAllowsVerification() public { + s_verifier.activateFeed(FEED_ID); + changePrank(address(s_verifierProxy)); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + s_verifier.verify(signedReport, msg.sender); + } + + function test_previousReportAllowsVerification() public { + s_verifier.activateFeed(FEED_ID); + changePrank(address(s_verifierProxy)); + + s_reportContext[0] = s_configDigestTwo; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + s_verifier.verify(signedReport, msg.sender); + } + + function test_currentReportFailsVerification() public { + changePrank(address(s_verifierProxy)); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.InactiveFeed.selector, FEED_ID)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_previousReportFailsVerification() public { + changePrank(address(s_verifierProxy)); + + s_reportContext[0] = s_configDigestTwo; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + + vm.expectRevert(abi.encodeWithSelector(Verifier.InactiveFeed.selector, FEED_ID)); + s_verifier.verify(signedReport, msg.sender); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol new file mode 100644 index 0000000..82efd89 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; + +contract VerifierProxyConstructorTest is BaseTest { + function test_correctlySetsTheOwner() public { + VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(address(0))); + assertEq(proxy.owner(), ADMIN); + } + + function test_correctlySetsTheCorrectAccessControllerInterface() public { + address accessControllerAddr = address(1234); + VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(accessControllerAddr)); + assertEq(address(proxy.s_accessController()), accessControllerAddr); + } + + function test_correctlySetsVersion() public view { + string memory version = s_verifierProxy.typeAndVersion(); + assertEq(version, "VerifierProxy 2.0.0"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol new file mode 100644 index 0000000..5537d27 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; + +contract VerifierProxyInitializeVerifierTest is BaseTest { + bytes32 latestDigest; + + function setUp() public override { + BaseTest.setUp(); + } + + function test_revertsIfNotOwner() public { + changePrank(USER); + vm.expectRevert("Only callable by owner"); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } + + function test_revertsIfZeroAddress() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); + s_verifierProxy.initializeVerifier(address(0)); + } + + function test_revertsIfVerifierAlreadyInitialized() public { + s_verifierProxy.initializeVerifier(address(s_verifier)); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierAlreadyInitialized.selector, address(s_verifier))); + s_verifierProxy.initializeVerifier(address(s_verifier)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol new file mode 100644 index 0000000..03bd6d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; + +contract VerifierProxySetAccessControllerTest is BaseTest { + event AccessControllerSet(address oldAccessController, address newAccessController); + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + } + + function test_successfullySetsNewAccessController() public { + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + AccessControllerInterface ac = s_verifierProxy.s_accessController(); + assertEq(address(ac), ACCESS_CONTROLLER_ADDRESS); + } + + function test_successfullySetsNewAccessControllerIsEmpty() public { + s_verifierProxy.setAccessController(AccessControllerInterface(address(0))); + AccessControllerInterface ac = s_verifierProxy.s_accessController(); + assertEq(address(ac), address(0)); + } + + function test_emitsTheCorrectEvent() public { + vm.expectEmit(true, false, false, false); + emit AccessControllerSet(address(0), ACCESS_CONTROLLER_ADDRESS); + s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol new file mode 100644 index 0000000..78e5ff0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {IVerifier} from "../../interfaces/IVerifier.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { + function test_revertsIfNotCorrectVerifier() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); + s_verifierProxy.setVerifier(bytes32("prev-config"), bytes32("new-config"), new Common.AddressAndWeight[](0)); + } + + function test_revertsIfDigestAlreadySet() public { + (, , bytes32 takenDigest) = s_verifier.latestConfigDetails(FEED_ID); + + address maliciousVerifier = address(666); + bytes32 maliciousDigest = bytes32("malicious-digest"); + vm.mockCall( + maliciousVerifier, + abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), + abi.encode(true) + ); + s_verifierProxy.initializeVerifier(maliciousVerifier); + vm.expectRevert( + abi.encodeWithSelector(VerifierProxy.ConfigDigestAlreadySet.selector, takenDigest, address(s_verifier)) + ); + changePrank(address(maliciousVerifier)); + s_verifierProxy.setVerifier(maliciousDigest, takenDigest, new Common.AddressAndWeight[](0)); + } + + function test_updatesVerifierIfVerifier() public { + (, , bytes32 prevDigest) = s_verifier.latestConfigDetails(FEED_ID); + changePrank(address(s_verifier)); + s_verifierProxy.setVerifier(prevDigest, bytes32("new-config"), new Common.AddressAndWeight[](0)); + assertEq(s_verifierProxy.getVerifier(bytes32("new-config")), address(s_verifier)); + assertEq(s_verifierProxy.getVerifier(prevDigest), address(s_verifier)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol new file mode 100644 index 0000000..441626e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; +import {FeeManager} from "../../../v0.3.0/FeeManager.sol"; + +contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { + function test_setFeeManagerZeroAddress() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); + s_verifierProxy.setFeeManager(FeeManager(address(0))); + } + + function test_setFeeManagerWhichDoesntHonourInterface() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.FeeManagerInvalid.selector)); + s_verifierProxy.setFeeManager(FeeManager(address(s_verifier))); + } + + function test_setFeeManagerWhichDoesntHonourIERC165Interface() public { + vm.expectRevert(); + s_verifierProxy.setFeeManager(FeeManager(address(1))); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol new file mode 100644 index 0000000..a51c67e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; + +contract VerifierProxyUnsetVerifierTest is BaseTest { + function test_revertsIfNotAdmin() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifierProxy.unsetVerifier(bytes32("")); + } + + function test_revertsIfDigestDoesNotExist() public { + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32(""))); + s_verifierProxy.unsetVerifier(bytes32("")); + } +} + +contract VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32 internal s_configDigest; + + event VerifierUnset(bytes32 configDigest, address verifierAddr); + + function setUp() public override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); + } + + function test_correctlyUnsetsVerifier() public { + s_verifierProxy.unsetVerifier(s_configDigest); + address verifierAddr = s_verifierProxy.getVerifier(s_configDigest); + assertEq(verifierAddr, address(0)); + } + + function test_emitsAnEventAfterUnsettingVerifier() public { + vm.expectEmit(true, false, false, false); + emit VerifierUnset(s_configDigest, address(s_verifier)); + s_verifierProxy.unsetVerifier(s_configDigest); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol new file mode 100644 index 0000000..9ee9b52 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierSetConfigFromSourceTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + changePrank(USER); + s_verifier.setConfigFromSource( + FEED_ID, + 12345, + address(12345), + 0, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } +} + +contract VerifierSetConfigFromSourceMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { + function test_correctlyUpdatesTheDigestInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfigFromSource( + FEED_ID, + 12345, + address(12345), + 0, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + } + + function test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfigFromSource( + FEED_ID_2, + 12345, + address(12345), + 0, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID_2); + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + + s_verifier_2.setConfigFromSource( + FEED_ID_3, + 12345, + address(12345), + 0, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest2) = s_verifier_2.latestConfigDetails(FEED_ID_3); + address verifierAddr2 = s_verifierProxy.getVerifier(configDigest2); + assertEq(verifierAddr2, address(s_verifier_2)); + } + + function test_correctlySetsConfigWhenDigestsAreRemoved() public { + s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); + + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfigFromSource( + FEED_ID, + 12345, + address(s_verifier), + 0, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + bytes32 expectedConfigDigest = _configDigestFromConfigData( + FEED_ID, + 12345, + address(s_verifier), + s_numConfigsSet + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + + assertEq(configCount, s_numConfigsSet + 1); + assertEq(blockNumber, block.number); + assertEq(configDigest, expectedConfigDigest); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol new file mode 100644 index 0000000..972ead8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierSetConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + changePrank(USER); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfSetWithTooManySigners() public { + address[] memory signers = new address[](MAX_ORACLES + 1); + vm.expectRevert(abi.encodeWithSelector(Verifier.ExcessSigners.selector, signers.length, MAX_ORACLES)); + s_verifier.setConfig( + FEED_ID, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfFaultToleranceIsZero() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.FaultToleranceMustBePositive.selector)); + Signer[] memory signers = _getSigners(MAX_ORACLES); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(signers), + s_offchaintransmitters, + 0, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfNotEnoughSigners() public { + address[] memory signers = new address[](2); + signers[0] = address(1000); + signers[1] = address(1001); + + vm.expectRevert( + abi.encodeWithSelector(Verifier.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) + ); + s_verifier.setConfig( + FEED_ID, + signers, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfDuplicateSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = signerAddrs[1]; + vm.expectRevert(abi.encodeWithSelector(Verifier.NonUniqueSignatures.selector)); + s_verifier.setConfig( + FEED_ID, + signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_revertsIfSignerContainsZeroAddress() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = address(0); + vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); + s_verifier.setConfig( + FEED_ID, + signerAddrs, + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + } + + function test_correctlyUpdatesTheConfig() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_verifierProxy.initializeVerifier(address(s_verifier)); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + bytes32 expectedConfigDigest = _configDigestFromConfigData( + FEED_ID, + block.chainid, + address(s_verifier), + 1, + _getSignerAddresses(signers), + s_offchaintransmitters, + FAULT_TOLERANCE, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(configCount, 1); + assertEq(blockNumber, block.number); + assertEq(configDigest, expectedConfigDigest); + + (bool scanLogs, bytes32 configDigestTwo, uint32 epoch) = s_verifier.latestConfigDigestAndEpoch(FEED_ID); + assertEq(scanLogs, false); + assertEq(configDigestTwo, expectedConfigDigest); + assertEq(epoch, 0); + } +} + +contract VerifierSetConfigWhenThereAreMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { + function test_correctlyUpdatesTheDigestInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + } + + function test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() public { + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfig( + FEED_ID_2, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID_2); + address verifierAddr = s_verifierProxy.getVerifier(configDigest); + assertEq(verifierAddr, address(s_verifier)); + + s_verifier_2.setConfig( + FEED_ID_3, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + (, , bytes32 configDigest2) = s_verifier_2.latestConfigDetails(FEED_ID_3); + address verifierAddr2 = s_verifierProxy.getVerifier(configDigest2); + assertEq(verifierAddr2, address(s_verifier_2)); + } + + function test_correctlySetsConfigWhenDigestsAreRemoved() public { + s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); + + Signer[] memory newSigners = _getSigners(15); + + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + + bytes32 expectedConfigDigest = _configDigestFromConfigData( + FEED_ID, + block.chainid, + address(s_verifier), + s_numConfigsSet + 1, + _getSignerAddresses(newSigners), + s_offchaintransmitters, + 4, + bytes(""), + VERIFIER_VERSION, + bytes("") + ); + + (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + + assertEq(configCount, s_numConfigsSet + 1); + assertEq(blockNumber, block.number); + assertEq(configDigest, expectedConfigDigest); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol new file mode 100644 index 0000000..81f65f0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; + +contract VerifierConstructorTest is BaseTest { + function test_revertsIfInitializedWithEmptyVerifierProxy() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); + new Verifier(address(0)); + } + + function test_setsTheCorrectProperties() public { + Verifier v = new Verifier(address(s_verifierProxy)); + assertEq(v.owner(), ADMIN); + + (bool scanLogs, bytes32 configDigest, uint32 epoch) = v.latestConfigDigestAndEpoch(FEED_ID); + assertEq(scanLogs, false); + assertEq(configDigest, EMPTY_BYTES); + assertEq(epoch, 0); + + (uint32 configCount, uint32 blockNumber, bytes32 configDigestTwo) = v.latestConfigDetails(FEED_ID); + assertEq(configCount, 0); + assertEq(blockNumber, 0); + assertEq(configDigestTwo, EMPTY_BYTES); + + string memory typeAndVersion = s_verifier.typeAndVersion(); + assertEq(typeAndVersion, "Verifier 1.2.0"); + } +} + +contract VerifierSupportsInterfaceTest is BaseTest { + function test_falseIfIsNotCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(bytes4("abcd")); + assertEq(isInterface, false); + } + + function test_trueIfIsCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(Verifier.verify.selector); + assertEq(isInterface, true); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol new file mode 100644 index 0000000..ad67a23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; + +contract VerifierTestWithConfiguredVerifierAndFeeManager is BaseTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + function setUp() public virtual override { + super.setUp(); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + } +} + +contract VerifierTestBillingReport is VerifierTestWithConfiguredVerifierAndFeeManager { + function test_verifyWithLink() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + _verify(signedReport, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNative() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + _verify(signedReport, address(native), 0, USER); + + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNativeUnwrapped() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithNativeUnwrappedReturnsChange() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } +} + +contract VerifierBulkVerifyBillingReport is VerifierTestWithConfiguredVerifierAndFeeManager { + uint256 internal constant NUMBERS_OF_REPORTS = 5; + + function test_verifyWithBulkLink() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS, USER); + + _verifyBulk(signedReports, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNative() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + + _verifyBulk(signedReports, address(native), 0, USER); + + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNativeUnwrapped() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithBulkNativeUnwrappedReturnsChange() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * (NUMBERS_OF_REPORTS * 2), USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyMultiVersions() public { + bytes memory signedReportV1 = _generateV1EncodedBlob( + _generateV1Report(), + _generateReportContext(v1ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory signedReportV3 = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](3); + + signedReports[0] = signedReportV1; + signedReports[1] = signedReportV3; + signedReports[2] = signedReportV3; + + _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); + + _verifyBulk(signedReports, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - 2 * DEFAULT_REPORT_LINK_FEE); + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); + } + + function test_verifyMultiVersionsReturnsVerifiedReports() public { + bytes memory signedReportV1 = _generateV1EncodedBlob( + _generateV1Report(), + _generateReportContext(v1ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory signedReportV3 = _generateV3EncodedBlob( + _generateV3Report(), + _generateReportContext(v3ConfigDigest), + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](3); + + signedReports[0] = signedReportV1; + signedReports[1] = signedReportV3; + signedReports[2] = signedReportV3; + + _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); + + address originalAddr = msg.sender; + changePrank(USER); + + bytes[] memory verifierReports = s_verifierProxy.verifyBulk{value: 0}(signedReports, abi.encode(link)); + + changePrank(originalAddr); + + assertEq(verifierReports[0], _encodeReport(_generateV1Report())); + assertEq(verifierReports[1], _encodeReport(_generateV3Report())); + assertEq(verifierReports[2], _encodeReport(_generateV3Report())); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol new file mode 100644 index 0000000..e192a2e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; + +contract VerificationdeactivateConfigWhenThereAreMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifier.deactivateConfig(FEED_ID, bytes32("")); + } + + function test_revertsIfRemovingAnEmptyDigest() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); + s_verifier.deactivateConfig(FEED_ID, bytes32("")); + } + + function test_revertsIfRemovingAnNonExistentDigest() public { + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, FEED_ID, bytes32("mock-digest"))); + s_verifier.deactivateConfig(FEED_ID, bytes32("mock-digest")); + } + + function test_correctlyRemovesAMiddleDigest() public { + s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); + (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(lastConfigDigest, s_configDigestThree); + } + + function test_correctlyRemovesTheFirstDigest() public { + s_verifier.deactivateConfig(FEED_ID, s_configDigestOne); + (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(lastConfigDigest, s_configDigestThree); + } + + function test_correctlyUnsetsDigestsInSequence() public { + // Delete config digest 2 + s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); + (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(lastConfigDigest, s_configDigestThree); + + // Delete config digest 1 + s_verifier.deactivateConfig(FEED_ID, s_configDigestOne); + (, , lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(lastConfigDigest, s_configDigestThree); + + // Delete config digest 3 + vm.expectRevert( + abi.encodeWithSelector(Verifier.CannotDeactivateLatestConfig.selector, FEED_ID, s_configDigestThree) + ); + s_verifier.deactivateConfig(FEED_ID, s_configDigestThree); + (, , lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + assertEq(lastConfigDigest, s_configDigestThree); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol new file mode 100644 index 0000000..1c14ba9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; +import {Verifier} from "../../../v0.3.0/Verifier.sol"; +import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierVerifyTest is BaseTestWithConfiguredVerifierAndFeeManager { + bytes32[3] internal s_reportContext; + + event ReportVerified(bytes32 indexed feedId, address requester); + + V1Report internal s_testReportOne; + + function setUp() public virtual override { + BaseTestWithConfiguredVerifierAndFeeManager.setUp(); + (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); + s_reportContext[0] = configDigest; + s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportOne = _createV1Report( + FEED_ID, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + } + + function assertReportsEqual(bytes memory response, V1Report memory testReport) public pure { + ( + bytes32 feedId, + uint32 timestamp, + int192 median, + int192 bid, + int192 ask, + uint64 blockNumUB, + bytes32 upperBlockhash, + uint64 blockNumLB + ) = abi.decode(response, (bytes32, uint32, int192, int192, int192, uint64, bytes32, uint64)); + assertEq(feedId, testReport.feedId); + assertEq(timestamp, testReport.observationsTimestamp); + assertEq(median, testReport.median); + assertEq(bid, testReport.bid); + assertEq(ask, testReport.ask); + assertEq(blockNumLB, testReport.blocknumberLowerBound); + assertEq(blockNumUB, testReport.blocknumberUpperBound); + assertEq(upperBlockhash, testReport.upperBlockhash); + } +} + +contract VerifierProxyVerifyTest is VerifierVerifyTest { + function test_revertsIfNoVerifierConfigured() public { + s_reportContext[0] = bytes32("corrupt-digest"); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32("corrupt-digest"))); + s_verifierProxy.verify(signedReport, bytes("")); + } + + function test_proxiesToTheCorrectVerifier() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes memory response = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(response, s_testReportOne); + } +} + +contract VerifierProxyAccessControlledVerificationTest is VerifierVerifyTest { + function setUp() public override { + VerifierVerifyTest.setUp(); + AccessControllerInterface accessController = AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS); + + s_verifierProxy.setAccessController(accessController); + } + + function test_revertsIfNoAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(false) + ); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); + + changePrank(USER); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_proxiesToTheVerifierIfHasAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(true) + ); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + changePrank(USER); + bytes memory response = s_verifierProxy.verify(signedReport, bytes("")); + assertReportsEqual(response, s_testReportOne); + } +} + +contract VerifierVerifySingleConfigDigestTest is VerifierVerifyTest { + function test_revertsIfVerifiedByNonProxy() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(Verifier.AccessForbidden.selector)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfVerifiedWithIncorrectAddresses() public { + Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); + signers[10].mockPrivateKey = 1234; + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfMismatchedSignatureLength() public { + bytes32[] memory rs = new bytes32[](FAULT_TOLERANCE + 1); + bytes32[] memory ss = new bytes32[](FAULT_TOLERANCE + 3); + bytes32 rawVs = bytes32(""); + bytes memory signedReport = abi.encode(s_reportContext, abi.encode(s_testReportOne), rs, ss, rawVs); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.MismatchedSignatures.selector, rs.length, ss.length)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfConfigDigestNotSet() public { + bytes32[3] memory reportContext = s_reportContext; + reportContext[0] = bytes32("wrong-context-digest"); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID, reportContext[0])); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfReportHasUnconfiguredFeedID() public { + V1Report memory report = _createV1Report( + FEED_ID_2, + OBSERVATIONS_TIMESTAMP, + MEDIAN, + BID, + ASK, + BLOCKNUMBER_UPPER_BOUND, + blockhash(BLOCKNUMBER_UPPER_BOUND), + BLOCKNUMBER_LOWER_BOUND, + uint32(block.timestamp) + ); + bytes memory signedReport = _generateV1EncodedBlob(report, s_reportContext, _getSigners(FAULT_TOLERANCE + 1)); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID_2, s_reportContext[0])); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfWrongNumberOfSigners() public { + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, _getSigners(10)); + vm.expectRevert(abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, 10, FAULT_TOLERANCE + 1)); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_revertsIfDuplicateSignersHaveSigned() public { + Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); + // Duplicate signer at index 1 + signers[0] = signers[1]; + bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); + vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } + + function test_returnsThePriceAndBlockNumIfReportVerified() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + + assertReportsEqual(response, s_testReportOne); + } + + function test_setsTheCorrectEpoch() public { + s_reportContext[1] = bytes32(uint256(5 << 8)); + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + + (, , uint32 latestEpoch) = s_verifier.latestConfigDigestAndEpoch(FEED_ID); + assertEq(latestEpoch, 5); + } + + function test_emitsAnEventIfReportVerified() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + vm.expectEmit(true, true, true, true, address(s_verifier)); + emit ReportVerified(s_testReportOne.feedId, msg.sender); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } +} + +contract VerifierVerifyMultipleConfigDigestTest is VerifierVerifyTest { + bytes32 internal s_oldConfigDigest; + bytes32 internal s_newConfigDigest; + + uint8 internal constant FAULT_TOLERANCE_TWO = 5; + + function setUp() public override { + VerifierVerifyTest.setUp(); + (, , s_oldConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + s_verifier.setConfig( + FEED_ID, + _getSignerAddresses(_getSigners(20)), + s_offchaintransmitters, + FAULT_TOLERANCE_TWO, + bytes(""), + VERIFIER_VERSION, + bytes(""), + new Common.AddressAndWeight[](0) + ); + (, , s_newConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); + } + + function test_revertsIfVerifyingWithAnUnsetDigest() public { + s_verifier.deactivateConfig(FEED_ID, (s_oldConfigDigest)); + + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID, s_reportContext[0])); + s_verifier.verify(signedReport, msg.sender); + } + + function test_canVerifyOlderReportsWithOlderConfigs() public { + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + assertReportsEqual(response, s_testReportOne); + } + + function test_canVerifyNewerReportsWithNewerConfigs() public { + s_reportContext[0] = s_newConfigDigest; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + changePrank(address(s_verifierProxy)); + bytes memory response = s_verifier.verify(signedReport, msg.sender); + assertReportsEqual(response, s_testReportOne); + } + + function test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() public { + // Try sending the older digest signed with the new set of signers + s_reportContext[0] = s_oldConfigDigest; + bytes memory signedReport = _generateV1EncodedBlob( + s_testReportOne, + s_reportContext, + _getSigners(FAULT_TOLERANCE_TWO + 1) + ); + vm.expectRevert( + abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, FAULT_TOLERANCE_TWO + 1, FAULT_TOLERANCE + 1) + ); + changePrank(address(s_verifierProxy)); + s_verifier.verify(signedReport, msg.sender); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol new file mode 100644 index 0000000..08ac1d4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; +import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; +import {IDestinationFeeManager} from "./interfaces/IDestinationFeeManager.sol"; +import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; + +/** + * @title FeeManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract is used for the handling of fees required for users verifying reports. + */ +contract DestinationFeeManager is + IDestinationFeeManager, + IDestinationVerifierFeeManager, + ConfirmedOwner, + TypeAndVersionInterface +{ + using SafeERC20 for IERC20; + + /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] + mapping(address => mapping(bytes32 => mapping(address => uint256))) public s_subscriberDiscounts; + + /// @notice map of global discounts + mapping(address => mapping(address => uint256)) public s_globalDiscounts; + + /// @notice keep track of any subsidised link that is owed to the reward manager. + mapping(bytes32 => uint256) public s_linkDeficit; + + /// @notice the total discount that can be applied to a fee, 1e18 = 100% discount + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + /// @notice the LINK token address + address public immutable i_linkAddress; + + /// @notice the native token address + address public immutable i_nativeAddress; + + /// @notice the verifier address + mapping(address => address) public s_verifierAddressList; + + /// @notice the reward manager address + IDestinationRewardManager public i_rewardManager; + + // @notice the mask to apply to get the report version + bytes32 private constant REPORT_VERSION_MASK = 0xffff000000000000000000000000000000000000000000000000000000000000; + + // @notice the different report versions + bytes32 private constant REPORT_V1 = 0x0001000000000000000000000000000000000000000000000000000000000000; + + /// @notice the surcharge fee to be paid if paying in native + uint256 public s_nativeSurcharge; + + /// @notice the error thrown if the discount or surcharge is invalid + error InvalidSurcharge(); + + /// @notice the error thrown if the discount is invalid + error InvalidDiscount(); + + /// @notice the error thrown if the address is invalid + error InvalidAddress(); + + /// @notice thrown if msg.value is supplied with a bad quote + error InvalidDeposit(); + + /// @notice thrown if a report has expired + error ExpiredReport(); + + /// @notice thrown if a report has no quote + error InvalidQuote(); + + // @notice thrown when the caller is not authorized + error Unauthorized(); + + // @notice thrown when trying to clear a zero deficit + error ZeroDeficit(); + + /// @notice thrown when trying to pay an address that cannot except funds + error InvalidReceivingAddress(); + + /// @notice thrown when trying to bulk verify reports where theres not a matching number of poolIds + error PoolIdMismatch(); + + /// @notice Emitted whenever a subscriber's discount is updated + /// @param subscriber address of the subscriber to update discounts for + /// @param feedId Feed ID for the discount + /// @param token Token address for the discount + /// @param discount Discount to apply, in relation to the PERCENTAGE_SCALAR + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + + /// @notice Emitted when updating the native surcharge + /// @param newSurcharge Surcharge amount to apply relative to PERCENTAGE_SCALAR + event NativeSurchargeUpdated(uint64 newSurcharge); + + /// @notice Emits when this contract does not have enough LINK to send to the reward manager when paying in native + /// @param rewards Config digest and link fees which could not be subsidised + event InsufficientLink(IDestinationRewardManager.FeePayment[] rewards); + + /// @notice Emitted when funds are withdrawn + /// @param adminAddress Address of the admin + /// @param recipient Address of the recipient + /// @param assetAddress Address of the asset withdrawn + /// @param quantity Amount of the asset withdrawn + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + + /// @notice Emits when a deficit has been cleared for a particular config digest + /// @param configDigest Config digest of the deficit cleared + /// @param linkQuantity Amount of LINK required to pay the deficit + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + + /// @notice Emits when a fee has been processed + /// @param configDigest Config digest of the fee processed + /// @param subscriber Address of the subscriber who paid the fee + /// @param fee Fee paid + /// @param reward Reward paid + /// @param appliedDiscount Discount applied to the fee + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscount + ); + + /** + * @notice Construct the FeeManager contract + * @param _linkAddress The address of the LINK token + * @param _nativeAddress The address of the wrapped ERC-20 version of the native token (represents fee in native or wrapped) + * @param _verifierAddress The address of the verifier contract + * @param _rewardManagerAddress The address of the reward manager contract + */ + constructor( + address _linkAddress, + address _nativeAddress, + address _verifierAddress, + address _rewardManagerAddress + ) ConfirmedOwner(msg.sender) { + if ( + _linkAddress == address(0) || + _nativeAddress == address(0) || + _verifierAddress == address(0) || + _rewardManagerAddress == address(0) + ) revert InvalidAddress(); + + i_linkAddress = _linkAddress; + i_nativeAddress = _nativeAddress; + s_verifierAddressList[_verifierAddress] = _verifierAddress; + i_rewardManager = IDestinationRewardManager(_rewardManagerAddress); + + IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); + } + + modifier onlyVerifier() { + if (msg.sender != s_verifierAddressList[msg.sender]) revert Unauthorized(); + _; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "DestinationFeeManager 0.4.0"; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return + interfaceId == type(IDestinationFeeManager).interfaceId || + interfaceId == type(IDestinationVerifierFeeManager).interfaceId; + } + + /// @inheritdoc IDestinationVerifierFeeManager + function processFee( + bytes32 recipient, + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyVerifier { + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _calculateFee( + payload, + parameterPayload, + subscriber + ); + + if (fee.amount == 0) { + _tryReturnChange(subscriber, msg.value); + return; + } + + IDestinationFeeManager.FeeAndReward[] memory feeAndReward = new IDestinationFeeManager.FeeAndReward[](1); + feeAndReward[0] = IDestinationFeeManager.FeeAndReward(recipient, fee, reward, appliedDiscount); + + if (fee.assetAddress == i_linkAddress) { + _handleFeesAndRewards(subscriber, feeAndReward, 1, 0); + } else { + _handleFeesAndRewards(subscriber, feeAndReward, 0, 1); + } + } + + /// @inheritdoc IDestinationVerifierFeeManager + function processFeeBulk( + bytes32[] memory poolIds, + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable override onlyVerifier { + //poolIDs are mapped to payloads, so they should be the same length + if (poolIds.length != payloads.length) revert PoolIdMismatch(); + + IDestinationFeeManager.FeeAndReward[] memory feesAndRewards = new IDestinationFeeManager.FeeAndReward[]( + payloads.length + ); + + //keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees + uint256 numberOfLinkFees; + uint256 numberOfNativeFees; + + uint256 feesAndRewardsIndex; + for (uint256 i; i < payloads.length; ++i) { + if (poolIds[i] == bytes32(0)) revert InvalidAddress(); + + (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _calculateFee( + payloads[i], + parameterPayload, + subscriber + ); + + if (fee.amount != 0) { + feesAndRewards[feesAndRewardsIndex++] = IDestinationFeeManager.FeeAndReward( + poolIds[i], + fee, + reward, + appliedDiscount + ); + + unchecked { + //keep track of some tallys to make downstream calculations more efficient + if (fee.assetAddress == i_linkAddress) { + ++numberOfLinkFees; + } else { + ++numberOfNativeFees; + } + } + } + } + + if (numberOfLinkFees != 0 || numberOfNativeFees != 0) { + _handleFeesAndRewards(subscriber, feesAndRewards, numberOfLinkFees, numberOfNativeFees); + } else { + _tryReturnChange(subscriber, msg.value); + } + } + + /// @inheritdoc IDestinationFeeManager + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) public view returns (Common.Asset memory, Common.Asset memory, uint256) { + Common.Asset memory fee; + Common.Asset memory reward; + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //the report needs to be a support version + bytes32 reportVersion = _getReportVersion(feedId); + + //version 1 of the reports don't require quotes, so the fee will be 0 + if (reportVersion == REPORT_V1) { + fee.assetAddress = i_nativeAddress; + reward.assetAddress = i_linkAddress; + return (fee, reward, 0); + } + + //verify the quote payload is a supported token + if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) { + revert InvalidQuote(); + } + + //decode the report depending on the version + uint256 linkQuantity; + uint256 nativeQuantity; + uint256 expiresAt; + (, , , nativeQuantity, linkQuantity, expiresAt) = abi.decode( + report, + (bytes32, uint32, uint32, uint192, uint192, uint32) + ); + + //read the timestamp bytes from the report data and verify it has not expired + if (expiresAt < block.timestamp) { + revert ExpiredReport(); + } + + //check if feed discount has been applied + uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress]; + + if (discount == 0) { + //check if a global discount has been applied + discount = s_globalDiscounts[subscriber][quoteAddress]; + } + + //the reward is always set in LINK + reward.assetAddress = i_linkAddress; + reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + + //calculate either the LINK fee or native fee if it's within the report + if (quoteAddress == i_linkAddress) { + fee.assetAddress = i_linkAddress; + fee.amount = reward.amount; + } else { + uint256 surchargedFee = Math.ceilDiv(nativeQuantity * (PERCENTAGE_SCALAR + s_nativeSurcharge), PERCENTAGE_SCALAR); + + fee.assetAddress = i_nativeAddress; + fee.amount = Math.ceilDiv(surchargedFee * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); + } + + //return the fee + return (fee, reward, discount); + } + + /// @inheritdoc IDestinationVerifierFeeManager + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external onlyVerifier { + i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); + } + + /// @inheritdoc IDestinationFeeManager + function setNativeSurcharge(uint64 surcharge) external onlyOwner { + if (surcharge > PERCENTAGE_SCALAR) revert InvalidSurcharge(); + + s_nativeSurcharge = surcharge; + + emit NativeSurchargeUpdated(surcharge); + } + + /// @inheritdoc IDestinationFeeManager + function updateSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint64 discount + ) external onlyOwner { + //make sure the discount is not greater than the total discount that can be applied + if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); + //make sure the token is either LINK or native + if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); + + s_subscriberDiscounts[subscriber][feedId][token] = discount; + + emit SubscriberDiscountUpdated(subscriber, feedId, token, discount); + } + + function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external onlyOwner { + //make sure the discount is not greater than the total discount that can be applied + if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); + //make sure the token is either LINK or native + if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); + + s_globalDiscounts[subscriber][token] = discount; + + emit SubscriberDiscountUpdated(subscriber, bytes32(0), token, discount); + } + + /// @inheritdoc IDestinationFeeManager + function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { + //address 0 is used to withdraw native in the context of withdrawing + if (assetAddress == address(0)) { + (bool success, ) = payable(recipient).call{value: quantity}(""); + + if (!success) revert InvalidReceivingAddress(); + return; + } + + //withdraw the requested asset + IERC20(assetAddress).safeTransfer(recipient, quantity); + + //emit event when funds are withdrawn + emit Withdraw(msg.sender, recipient, assetAddress, uint192(quantity)); + } + + /// @inheritdoc IDestinationFeeManager + function linkAvailableForPayment() external view returns (uint256) { + //return the amount of LINK this contact has available to pay rewards + return IERC20(i_linkAddress).balanceOf(address(this)); + } + + /** + * @notice Gets the current version of the report that is encoded as the last two bytes of the feed + * @param feedId feed id to get the report version for + */ + function _getReportVersion(bytes32 feedId) internal pure returns (bytes32) { + return REPORT_VERSION_MASK & feedId; + } + + function _calculateFee( + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) internal view returns (Common.Asset memory, Common.Asset memory, uint256) { + if (subscriber == address(this)) revert InvalidAddress(); + + //decode the report from the payload + (, bytes memory report) = abi.decode(payload, (bytes32[3], bytes)); + + //get the feedId from the report + bytes32 feedId = bytes32(report); + + //v1 doesn't need a quote payload, so skip the decoding + address quote; + if (_getReportVersion(feedId) != REPORT_V1) { + //decode the quote from the bytes + (quote) = abi.decode(parameterPayload, (address)); + } + + //decode the fee, it will always be native or LINK + return getFeeAndReward(subscriber, report, quote); + } + + function _handleFeesAndRewards( + address subscriber, + IDestinationFeeManager.FeeAndReward[] memory feesAndRewards, + uint256 numberOfLinkFees, + uint256 numberOfNativeFees + ) internal { + IDestinationRewardManager.FeePayment[] memory linkRewards = new IDestinationRewardManager.FeePayment[]( + numberOfLinkFees + ); + IDestinationRewardManager.FeePayment[] memory nativeFeeLinkRewards = new IDestinationRewardManager.FeePayment[]( + numberOfNativeFees + ); + + uint256 totalNativeFee; + uint256 totalNativeFeeLinkValue; + + uint256 linkRewardsIndex; + uint256 nativeFeeLinkRewardsIndex; + + uint256 totalNumberOfFees = numberOfLinkFees + numberOfNativeFees; + for (uint256 i; i < totalNumberOfFees; ++i) { + if (feesAndRewards[i].fee.assetAddress == i_linkAddress) { + linkRewards[linkRewardsIndex++] = IDestinationRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + } else { + nativeFeeLinkRewards[nativeFeeLinkRewardsIndex++] = IDestinationRewardManager.FeePayment( + feesAndRewards[i].configDigest, + uint192(feesAndRewards[i].reward.amount) + ); + totalNativeFee += feesAndRewards[i].fee.amount; + totalNativeFeeLinkValue += feesAndRewards[i].reward.amount; + } + + if (feesAndRewards[i].appliedDiscount != 0) { + emit DiscountApplied( + feesAndRewards[i].configDigest, + subscriber, + feesAndRewards[i].fee, + feesAndRewards[i].reward, + feesAndRewards[i].appliedDiscount + ); + } + } + + //keep track of change in case of any over payment + uint256 change; + + if (msg.value != 0) { + //there must be enough to cover the fee + if (totalNativeFee > msg.value) revert InvalidDeposit(); + + //wrap the amount required to pay the fee & approve as the subscriber paid in wrapped native + IWERC20(i_nativeAddress).deposit{value: totalNativeFee}(); + + unchecked { + //msg.value is always >= to fee.amount + change = msg.value - totalNativeFee; + } + } else { + if (totalNativeFee != 0) { + //subscriber has paid in wrapped native, so transfer the native to this contract + IERC20(i_nativeAddress).safeTransferFrom(subscriber, address(this), totalNativeFee); + } + } + + if (linkRewards.length != 0) { + i_rewardManager.onFeePaid(linkRewards, subscriber); + } + + if (nativeFeeLinkRewards.length != 0) { + //distribute subsidised fees paid in Native + if (totalNativeFeeLinkValue > IERC20(i_linkAddress).balanceOf(address(this))) { + // If not enough LINK on this contract to forward for rewards, tally the deficit to be paid by out-of-band LINK + for (uint256 i; i < nativeFeeLinkRewards.length; ++i) { + unchecked { + //we have previously tallied the fees, any overflows would have already reverted + s_linkDeficit[nativeFeeLinkRewards[i].poolId] += nativeFeeLinkRewards[i].amount; + } + } + + emit InsufficientLink(nativeFeeLinkRewards); + } else { + //distribute the fees + i_rewardManager.onFeePaid(nativeFeeLinkRewards, address(this)); + } + } + + // a refund may be needed if the payee has paid in excess of the fee + _tryReturnChange(subscriber, change); + } + + function _tryReturnChange(address subscriber, uint256 quantity) internal { + if (quantity != 0) { + payable(subscriber).transfer(quantity); + } + } + + /// @inheritdoc IDestinationFeeManager + function payLinkDeficit(bytes32 configDigest) external onlyOwner { + uint256 deficit = s_linkDeficit[configDigest]; + + if (deficit == 0) revert ZeroDeficit(); + + delete s_linkDeficit[configDigest]; + + IDestinationRewardManager.FeePayment[] memory deficitFeePayment = new IDestinationRewardManager.FeePayment[](1); + + deficitFeePayment[0] = IDestinationRewardManager.FeePayment(configDigest, uint192(deficit)); + + i_rewardManager.onFeePaid(deficitFeePayment, address(this)); + + emit LinkDeficitCleared(configDigest, deficit); + } + + /// @inheritdoc IDestinationFeeManager + function addVerifier(address verifierAddress) external onlyOwner { + if (verifierAddress == address(0)) revert InvalidAddress(); + //check doesn't already exist + if (s_verifierAddressList[verifierAddress] != address(0)) revert InvalidAddress(); + s_verifierAddressList[verifierAddress] = verifierAddress; + } + + /// @inheritdoc IDestinationFeeManager + function removeVerifier(address verifierAddress) external onlyOwner { + if (verifierAddress == address(0)) revert InvalidAddress(); + //check doesn't already exist + if (s_verifierAddressList[verifierAddress] == address(0)) revert InvalidAddress(); + delete s_verifierAddressList[verifierAddress]; + } + + /// @inheritdoc IDestinationFeeManager + function setRewardManager(address rewardManagerAddress) external onlyOwner { + if (rewardManagerAddress == address(0)) revert InvalidAddress(); + + if (!IERC165(rewardManagerAddress).supportsInterface(type(IDestinationRewardManager).interfaceId)) { + revert InvalidAddress(); + } + + IERC20(i_linkAddress).approve(address(i_rewardManager), 0); + i_rewardManager = IDestinationRewardManager(rewardManagerAddress); + IERC20(i_linkAddress).approve(address(rewardManagerAddress), type(uint256).max); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol new file mode 100644 index 0000000..4b4c1f5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; +import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {Common} from "../libraries/Common.sol"; +import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; + +/** + * @title DestinationRewardManager + * @author Michael Fletcher + * @author Austin Born + * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. + */ +contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, TypeAndVersionInterface { + using SafeERC20 for IERC20; + + // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] + mapping(bytes32 => uint256) public s_totalRewardRecipientFees; + + // @dev The mapping of fee balances for each pot last time the recipient claimed: s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] + mapping(bytes32 => mapping(address => uint256)) public s_totalRewardRecipientFeesLastClaimedAmounts; + + // @dev The mapping of RewardRecipient weights for a particular poolId: s_rewardRecipientWeights[poolId][rewardRecipient]. + mapping(bytes32 => mapping(address => uint256)) public s_rewardRecipientWeights; + + // @dev Keep track of the reward recipient weights that have been set to prevent duplicates + mapping(bytes32 => bool) public s_rewardRecipientWeightsSet; + + // @dev Store a list of pool ids that have been registered, to make off chain lookups easier + bytes32[] public s_registeredPoolIds; + + // @dev The address for the LINK contract + address public immutable i_linkAddress; + + // The total weight of all RewardRecipients. 1e18 = 100% of the pool fees + uint64 private constant PERCENTAGE_SCALAR = 1e18; + + // The fee manager address + mapping(address => address) public s_feeManagerAddressList; + + // @notice Thrown whenever the RewardRecipient weights are invalid + error InvalidWeights(); + + // @notice Thrown when any given address is invalid + error InvalidAddress(); + + // @notice Thrown when the pool id is invalid + error InvalidPoolId(); + + // @notice Thrown when the calling contract is not within the authorized contracts + error Unauthorized(); + + // @notice Thrown when getAvailableRewardPoolIds parameters are incorrectly set + error InvalidPoolLength(); + + // Events emitted upon state change + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newFeeManagerAddress); + event FeePaid(FeePayment[] payments, address payer); + + /** + * @notice Constructor + * @param linkAddress address of the wrapped LINK token + */ + constructor(address linkAddress) ConfirmedOwner(msg.sender) { + //ensure that the address ia not zero + if (linkAddress == address(0)) revert InvalidAddress(); + + i_linkAddress = linkAddress; + } + + // @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "DestinationRewardManager 0.4.0"; + } + + // @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == type(IDestinationRewardManager).interfaceId; + } + + modifier onlyOwnerOrFeeManager() { + if (msg.sender != s_feeManagerAddressList[msg.sender] && msg.sender != owner()) revert Unauthorized(); + _; + } + + modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { + if (s_rewardRecipientWeights[poolId][msg.sender] == 0 && msg.sender != owner()) revert Unauthorized(); + _; + } + + modifier onlyFeeManager() { + if (msg.sender != s_feeManagerAddressList[msg.sender]) revert Unauthorized(); + _; + } + + /// @inheritdoc IDestinationRewardManager + function onFeePaid(FeePayment[] calldata payments, address payer) external override onlyFeeManager { + uint256 totalFeeAmount; + for (uint256 i; i < payments.length; ++i) { + unchecked { + //the total amount for any ERC-20 asset cannot exceed 2^256 - 1 + //see https://github.com/OpenZeppelin/openzeppelin-contracts/blob/36bf1e46fa811f0f07d38eb9cfbc69a955f300ce/contracts/token/ERC20/ERC20.sol#L266 + //for example implementation. + s_totalRewardRecipientFees[payments[i].poolId] += payments[i].amount; + + //tally the total payable fees + totalFeeAmount += payments[i].amount; + } + } + + //transfer the fees to this contract + IERC20(i_linkAddress).safeTransferFrom(payer, address(this), totalFeeAmount); + + emit FeePaid(payments, payer); + } + + /// @inheritdoc IDestinationRewardManager + function claimRewards(bytes32[] memory poolIds) external override { + _claimRewards(msg.sender, poolIds); + } + + // wrapper impl for claimRewards + function _claimRewards(address recipient, bytes32[] memory poolIds) internal returns (uint256) { + //get the total amount claimable for this recipient + uint256 claimAmount; + + //loop and claim all the rewards in the poolId pot + for (uint256 i; i < poolIds.length; ++i) { + //get the poolId to be claimed + bytes32 poolId = poolIds[i]; + + //get the total fees for the pot + uint256 totalFeesInPot = s_totalRewardRecipientFees[poolId]; + + unchecked { + //avoid unnecessary storage reads if there's no fees in the pot + if (totalFeesInPot == 0) continue; + + //get the claimable amount for this recipient, this calculation will never exceed the amount in the pot + uint256 claimableAmount = totalFeesInPot - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient]; + + //calculate the recipients share of the fees, which is their weighted share of the difference between the last amount they claimed and the current amount in the pot. This can never be more than the total amount in existence + uint256 recipientShare = (claimableAmount * s_rewardRecipientWeights[poolId][recipient]) / PERCENTAGE_SCALAR; + + //if there's no fees to claim, continue as there's nothing to update + if (recipientShare == 0) continue; + + //keep track of the total amount claimable, this can never be more than the total amount in existence + claimAmount += recipientShare; + + //set the current total amount of fees in the pot as it's used to calculate future claims + s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] = totalFeesInPot; + + //emit event if the recipient has rewards to claim + emit RewardsClaimed(poolIds[i], recipient, uint192(recipientShare)); + } + } + + //check if there's any rewards to claim in the given poolId + if (claimAmount != 0) { + //transfer the reward to the recipient + IERC20(i_linkAddress).safeTransfer(recipient, claimAmount); + } + + return claimAmount; + } + + /// @inheritdoc IDestinationRewardManager + function setRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external override onlyOwnerOrFeeManager { + //revert if there are no recipients to set + if (rewardRecipientAndWeights.length == 0) revert InvalidAddress(); + + //check that the weights have not been previously set + if (s_rewardRecipientWeightsSet[poolId]) revert InvalidPoolId(); + + //keep track of the registered poolIds to make off chain lookups easier + s_registeredPoolIds.push(poolId); + + //keep track of which pools have had their reward recipients set + s_rewardRecipientWeightsSet[poolId] = true; + + //set the reward recipients, this will only be called once and contain the full set of RewardRecipients with a total weight of 100% + _setRewardRecipientWeights(poolId, rewardRecipientAndWeights, PERCENTAGE_SCALAR); + + emit RewardRecipientsUpdated(poolId, rewardRecipientAndWeights); + } + + function _setRewardRecipientWeights( + bytes32 poolId, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights, + uint256 expectedWeight + ) internal { + //we can't update the weights if it contains duplicates + if (Common._hasDuplicateAddresses(rewardRecipientAndWeights)) revert InvalidAddress(); + + //loop all the reward recipients and validate the weight and address + uint256 totalWeight; + for (uint256 i; i < rewardRecipientAndWeights.length; ++i) { + //get the weight + uint256 recipientWeight = rewardRecipientAndWeights[i].weight; + //get the address + address recipientAddress = rewardRecipientAndWeights[i].addr; + + //ensure the reward recipient address is not zero + if (recipientAddress == address(0)) revert InvalidAddress(); + + //save/overwrite the weight for the reward recipient + s_rewardRecipientWeights[poolId][recipientAddress] = recipientWeight; + + unchecked { + //keep track of the cumulative weight, this cannot overflow as the total weight is restricted at 1e18 + totalWeight += recipientWeight; + } + } + + //if total weight is not met, the fees will either be under or over distributed + if (totalWeight != expectedWeight) revert InvalidWeights(); + } + + /// @inheritdoc IDestinationRewardManager + function updateRewardRecipients( + bytes32 poolId, + Common.AddressAndWeight[] calldata newRewardRecipients + ) external override onlyOwner { + //create an array of poolIds to pass to _claimRewards if required + bytes32[] memory poolIds = new bytes32[](1); + poolIds[0] = poolId; + + //loop all the reward recipients and claim their rewards before updating their weights + uint256 existingTotalWeight; + for (uint256 i; i < newRewardRecipients.length; ++i) { + //get the address + address recipientAddress = newRewardRecipients[i].addr; + //get the existing weight + uint256 existingWeight = s_rewardRecipientWeights[poolId][recipientAddress]; + + //if a recipient is updated, the rewards must be claimed first as they can't claim previous fees at the new weight + _claimRewards(newRewardRecipients[i].addr, poolIds); + + unchecked { + //keep tally of the weights so that the expected collective weight is known + existingTotalWeight += existingWeight; + } + } + + //update the reward recipients, if the new collective weight isn't equal to the previous collective weight, the fees will either be under or over distributed + _setRewardRecipientWeights(poolId, newRewardRecipients, existingTotalWeight); + + //emit event + emit RewardRecipientsUpdated(poolId, newRewardRecipients); + } + + /// @inheritdoc IDestinationRewardManager + function payRecipients(bytes32 poolId, address[] calldata recipients) external onlyOwnerOrRecipientInPool(poolId) { + //convert poolIds to an array to match the interface of _claimRewards + bytes32[] memory poolIdsArray = new bytes32[](1); + poolIdsArray[0] = poolId; + + //loop each recipient and claim the rewards for each of the pools and assets + for (uint256 i; i < recipients.length; ++i) { + _claimRewards(recipients[i], poolIdsArray); + } + } + + /// @inheritdoc IDestinationRewardManager + function addFeeManager(address newFeeManagerAddress) external onlyOwner { + if (newFeeManagerAddress == address(0)) revert InvalidAddress(); + if (s_feeManagerAddressList[newFeeManagerAddress] != address(0)) revert InvalidAddress(); + + s_feeManagerAddressList[newFeeManagerAddress] = newFeeManagerAddress; + + emit FeeManagerUpdated(newFeeManagerAddress); + } + + /// @inheritdoc IDestinationRewardManager + function removeFeeManager(address feeManagerAddress) external onlyOwner { + if (s_feeManagerAddressList[feeManagerAddress] == address(0)) revert InvalidAddress(); + delete s_feeManagerAddressList[feeManagerAddress]; + } + + /// @inheritdoc IDestinationRewardManager + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory) { + //get the length of the pool ids which we will loop through and potentially return + uint256 registeredPoolIdsLength = s_registeredPoolIds.length; + + uint256 lastIndex = endIndex > registeredPoolIdsLength ? registeredPoolIdsLength : endIndex; + + if (startIndex > lastIndex) revert InvalidPoolLength(); + + //create a new array with the maximum amount of potential pool ids + bytes32[] memory claimablePoolIds = new bytes32[](lastIndex - startIndex); + //we want the pools which a recipient has funds for to be sequential, so we need to keep track of the index + uint256 poolIdArrayIndex; + + //loop all the pool ids, and check if the recipient has a registered weight and a claimable amount + for (uint256 i = startIndex; i < lastIndex; ++i) { + //get the poolId + bytes32 poolId = s_registeredPoolIds[i]; + + //if the recipient has a weight, they are a recipient of this poolId + if (s_rewardRecipientWeights[poolId][recipient] != 0) { + //get the total in this pool + uint256 totalPoolAmount = s_totalRewardRecipientFees[poolId]; + //if the recipient has any LINK, then add the poolId to the array + unchecked { + //s_totalRewardRecipientFeesLastClaimedAmounts can never exceed total pool amount, and the number of pools can't exceed the max array length + if (totalPoolAmount - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] != 0) { + claimablePoolIds[poolIdArrayIndex++] = poolId; + } + } + } + } + + return claimablePoolIds; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol new file mode 100644 index 0000000..8ab0f6a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {IDestinationVerifier} from "./interfaces/IDestinationVerifier.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../libraries/Common.sol"; +import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; +import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; +import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; +import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; + +// OCR2 standard +uint256 constant MAX_NUM_ORACLES = 31; + +/** + * @title DestinationVerifier + * @author Michael Fletcher + * @notice This contract will be used to verify reports based on the oracle signatures. This is not the source verifier which required individual fee configurations, instead, this checks that a report has been signed by one of the configured oracles. + */ +contract DestinationVerifier is + IDestinationVerifier, + IDestinationVerifierProxyVerifier, + ConfirmedOwner, + TypeAndVersionInterface +{ + /// @notice The list of DON configurations by hash(address|donConfigId) - set to true if the signer is part of the config + mapping(bytes32 => bool) private s_signerByAddressAndDonConfigId; + + /// array of DON configs + DonConfig[] private s_donConfigs; + + /// @notice The address of the verifierProxy + address public s_feeManager; + + /// @notice The address of the access controller + address public s_accessController; + + /// @notice The address of the verifierProxy + IDestinationVerifierProxy public immutable i_verifierProxy; + + /// @notice This error is thrown whenever trying to set a config + /// with a fault tolerance of 0 + error FaultToleranceMustBePositive(); + + /// @notice This error is thrown whenever a report is signed + /// with more than the max number of signers + /// @param numSigners The number of signers who have signed the report + /// @param maxSigners The maximum number of signers that can sign a report + error ExcessSigners(uint256 numSigners, uint256 maxSigners); + + /// @notice This error is thrown whenever a report is signed or expected to be signed with less than the minimum number of signers + /// @param numSigners The number of signers who have signed the report + /// @param minSigners The minimum number of signers that need to sign a report + error InsufficientSigners(uint256 numSigners, uint256 minSigners); + + /// @notice This error is thrown whenever a report is submitted with no signatures + error NoSigners(); + + /// @notice This error is thrown whenever a DonConfig already exists + /// @param donConfigId The ID of the DonConfig that already exists + error DonConfigAlreadyExists(bytes24 donConfigId); + + /// @notice This error is thrown whenever the R and S signer components + /// have different lengths + /// @param rsLength The number of r signature components + /// @param ssLength The number of s signature components + error MismatchedSignatures(uint256 rsLength, uint256 ssLength); + + /// @notice This error is thrown whenever setting a config with duplicate signatures + error NonUniqueSignatures(); + + /* @notice This error is thrown whenever a report fails to verify. This error be thrown for multiple reasons and it's purposely like + * this to prevent information being leaked about the verification process which could be used to enable free verifications maliciously + */ + error BadVerification(); + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown when the fee manager at an address does + /// not conform to the fee manager interface + error FeeManagerInvalid(); + + /// @notice This error is thrown whenever an address tries + /// to execute a verification that it is not authorized to do so + error AccessForbidden(); + + /// @notice This error is thrown whenever a config does not exist + error DonConfigDoesNotExist(); + + /// @notice This error is thrown when the activation time is either in the future or less than the current configs + error BadActivationTime(); + + /// @notice This event is emitted when a new report is verified. + /// It is used to keep a historical record of verified reports. + event ReportVerified(bytes32 indexed feedId, address requester); + + /// @notice This event is emitted whenever a configuration is activated or deactivated + event ConfigActivated(bytes24 donConfigId, bool isActive); + + /// @notice This event is emitted whenever a configuration is removed + event ConfigRemoved(bytes24 donConfigId); + + /// @notice event is emitted whenever a new DON Config is set + event ConfigSet( + bytes24 indexed donConfigId, + address[] signers, + uint8 f, + Common.AddressAndWeight[] recipientAddressesAndWeights, + uint16 donConfigIndex + ); + + /// @notice This event is emitted when a new fee manager is set + /// @param oldFeeManager The old fee manager address + /// @param newFeeManager The new fee manager address + event FeeManagerSet(address oldFeeManager, address newFeeManager); + + /// @notice This event is emitted when a new access controller is set + /// @param oldAccessController The old access controller address + /// @param newAccessController The new access controller address + event AccessControllerSet(address oldAccessController, address newAccessController); + + struct DonConfig { + // The ID of the DonConfig + bytes24 donConfigId; + // Fault tolerance of the DON + uint8 f; + // Whether the config is active + bool isActive; + // The time the config was set + uint32 activationTime; + } + + constructor(address verifierProxy) ConfirmedOwner(msg.sender) { + if (verifierProxy == address(0)) { + revert ZeroAddress(); + } + + i_verifierProxy = IDestinationVerifierProxy(verifierProxy); + } + + /// @inheritdoc IDestinationVerifierProxyVerifier + function verify( + bytes calldata signedReport, + bytes calldata parameterPayload, + address sender + ) external payable override onlyProxy checkAccess(sender) returns (bytes memory) { + (bytes memory verifierResponse, bytes32 donConfigId) = _verify(signedReport, sender); + + address fm = s_feeManager; + if (fm != address(0)) { + //process the fee and catch the error + try + IDestinationVerifierFeeManager(fm).processFee{value: msg.value}( + donConfigId, + signedReport, + parameterPayload, + sender + ) + { + //do nothing + } catch { + // we purposefully obfuscate the error here to prevent information leaking leading to free verifications + revert BadVerification(); + } + } + + return verifierResponse; + } + + /// @inheritdoc IDestinationVerifierProxyVerifier + function verifyBulk( + bytes[] calldata signedReports, + bytes calldata parameterPayload, + address sender + ) external payable override onlyProxy checkAccess(sender) returns (bytes[] memory) { + bytes[] memory verifierResponses = new bytes[](signedReports.length); + bytes32[] memory donConfigs = new bytes32[](signedReports.length); + + for (uint256 i; i < signedReports.length; ++i) { + (bytes memory report, bytes32 config) = _verify(signedReports[i], sender); + verifierResponses[i] = report; + donConfigs[i] = config; + } + + address fm = s_feeManager; + if (fm != address(0)) { + //process the fee and catch the error + try + IDestinationVerifierFeeManager(fm).processFeeBulk{value: msg.value}( + donConfigs, + signedReports, + parameterPayload, + sender + ) + { + //do nothing + } catch { + // we purposefully obfuscate the error here to prevent information leaking leading to free verifications + revert BadVerification(); + } + } + + return verifierResponses; + } + + function _verify(bytes calldata signedReport, address sender) internal returns (bytes memory, bytes32) { + ( + bytes32[3] memory reportContext, + bytes memory reportData, + bytes32[] memory rs, + bytes32[] memory ss, + bytes32 rawVs + ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); + + // Signature lengths must match + if (rs.length != ss.length) revert MismatchedSignatures(rs.length, ss.length); + + //Must always be at least 1 signer + if (rs.length == 0) revert NoSigners(); + + // The payload is hashed and signed by the oracles - we need to recover the addresses + bytes32 signedPayload = keccak256(abi.encodePacked(keccak256(reportData), reportContext)); + address[] memory signers = new address[](rs.length); + for (uint256 i; i < rs.length; ++i) { + signers[i] = ecrecover(signedPayload, uint8(rawVs[i]) + 27, rs[i], ss[i]); + } + + // Duplicate signatures are not allowed + if (Common._hasDuplicateAddresses(signers)) { + revert BadVerification(); + } + + //We need to know the timestamp the report was generated to lookup the active activeDonConfig + uint256 reportTimestamp = _decodeReportTimestamp(reportData); + + // Find the latest config for this report + DonConfig memory activeDonConfig = _findActiveConfig(reportTimestamp); + + // Check a config has been set + if (activeDonConfig.donConfigId == bytes24(0)) { + revert BadVerification(); + } + + //check the config is active + if (!activeDonConfig.isActive) { + revert BadVerification(); + } + + //check we have enough signatures + if (signers.length <= activeDonConfig.f) { + revert BadVerification(); + } + + //check each signer is registered against the active DON + bytes32 signerDonConfigKey; + for (uint256 i; i < signers.length; ++i) { + signerDonConfigKey = keccak256(abi.encodePacked(signers[i], activeDonConfig.donConfigId)); + if (!s_signerByAddressAndDonConfigId[signerDonConfigKey]) { + revert BadVerification(); + } + } + + emit ReportVerified(bytes32(reportData), sender); + + return (reportData, activeDonConfig.donConfigId); + } + + /// @inheritdoc IDestinationVerifier + function setConfigWithActivationTime( + address[] memory signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights, + uint32 activationTime + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig(signers, f, recipientAddressesAndWeights, activationTime); + } + + /// @inheritdoc IDestinationVerifier + function setConfig( + address[] memory signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig(signers, f, recipientAddressesAndWeights, uint32(block.timestamp)); + } + + function _setConfig( + address[] memory signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights, + uint32 activationTime + ) internal { + // Duplicate addresses would break protocol rules + if (Common._hasDuplicateAddresses(signers)) { + revert NonUniqueSignatures(); + } + + //activation time cannot be in the future + if (activationTime > block.timestamp) { + revert BadActivationTime(); + } + + // Sort signers to ensure donConfigId is deterministic + Common._quickSort(signers, 0, int256(signers.length - 1)); + + //DonConfig is made up of hash(signers|f) + bytes24 donConfigId = bytes24(keccak256(abi.encodePacked(signers, f))); + + // Register the signers for this DON + for (uint256 i; i < signers.length; ++i) { + if (signers[i] == address(0)) revert ZeroAddress(); + /** This index is registered so we can efficiently lookup whether a NOP is part of a config without having to + loop through the entire config each verification. It's effectively a DonConfig <-> Signer + composite key which keys track of all historic configs for a signer */ + s_signerByAddressAndDonConfigId[keccak256(abi.encodePacked(signers[i], donConfigId))] = true; + } + + // Check the activation time is greater than the latest config + uint256 donConfigLength = s_donConfigs.length; + if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].activationTime >= activationTime) { + revert BadActivationTime(); + } + + // Check the config we're setting isn't already set as the current active config as this will increase search costs unnecessarily when verifying historic reports + if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].donConfigId == donConfigId) { + revert DonConfigAlreadyExists(donConfigId); + } + + // We may want to register these later or skip this step in the unlikely scenario they've previously been registered in the RewardsManager + if (recipientAddressesAndWeights.length != 0) { + if (s_feeManager == address(0)) { + revert FeeManagerInvalid(); + } + IDestinationVerifierFeeManager(s_feeManager).setFeeRecipients(donConfigId, recipientAddressesAndWeights); + } + + // push the DonConfig + s_donConfigs.push(DonConfig(donConfigId, f, true, activationTime)); + + emit ConfigSet(donConfigId, signers, f, recipientAddressesAndWeights, uint16(donConfigLength)); + } + + /// @inheritdoc IDestinationVerifier + function setFeeManager(address feeManager) external override onlyOwner { + if (!IERC165(feeManager).supportsInterface(type(IDestinationVerifierFeeManager).interfaceId)) + revert FeeManagerInvalid(); + + address oldFeeManager = s_feeManager; + s_feeManager = feeManager; + + emit FeeManagerSet(oldFeeManager, feeManager); + } + + /// @inheritdoc IDestinationVerifier + function setAccessController(address accessController) external override onlyOwner { + address oldAccessController = s_accessController; + s_accessController = accessController; + emit AccessControllerSet(oldAccessController, accessController); + } + + /// @inheritdoc IDestinationVerifier + function setConfigActive(uint256 donConfigIndex, bool isActive) external onlyOwner { + // Config must exist + if (donConfigIndex >= s_donConfigs.length) { + revert DonConfigDoesNotExist(); + } + + // Update the config + DonConfig storage config = s_donConfigs[donConfigIndex]; + config.isActive = isActive; + + emit ConfigActivated(config.donConfigId, isActive); + } + + /// @inheritdoc IDestinationVerifier + function removeLatestConfig() external onlyOwner { + if (s_donConfigs.length == 0) { + revert DonConfigDoesNotExist(); + } + + DonConfig memory config = s_donConfigs[s_donConfigs.length - 1]; + + s_donConfigs.pop(); + + emit ConfigRemoved(config.donConfigId); + } + + function _decodeReportTimestamp(bytes memory reportPayload) internal pure returns (uint256) { + (, , uint256 timestamp) = abi.decode(reportPayload, (bytes32, uint32, uint32)); + + return timestamp; + } + + function _findActiveConfig(uint256 timestamp) internal view returns (DonConfig memory) { + DonConfig memory activeDonConfig; + + // 99% of the time the signer config will be the last index, however for historic reports generated by a previous configuration we'll need to cycle back + uint256 i = s_donConfigs.length; + while (i > 0) { + --i; + if (s_donConfigs[i].activationTime <= timestamp) { + activeDonConfig = s_donConfigs[i]; + break; + } + } + return activeDonConfig; + } + + modifier checkConfigValid(uint256 numSigners, uint256 f) { + if (f == 0) revert FaultToleranceMustBePositive(); + if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); + if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); + _; + } + + modifier onlyProxy() { + if (address(i_verifierProxy) != msg.sender) { + revert AccessForbidden(); + } + _; + } + + modifier checkAccess(address sender) { + address ac = s_accessController; + if (address(ac) != address(0) && !IAccessController(ac).hasAccess(sender, msg.data)) revert AccessForbidden(); + _; + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return + interfaceId == type(IDestinationVerifier).interfaceId || + interfaceId == type(IDestinationVerifierProxyVerifier).interfaceId; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "DestinationVerifier 0.4.0"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol new file mode 100644 index 0000000..6790883 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; +import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; + +/** + * @title DestinationVerifierProxy + * @author Michael Fletcher + * @notice This contract will be used to route all requests through to the assigned verifier contract. This contract does not support individual feed configurations and is aimed at being a simple proxy for the verifier contract on any destination chain. + */ +contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { + /// @notice The active verifier for this proxy + IDestinationVerifierProxyVerifier private s_verifier; + + /// @notice This error is thrown whenever a zero address is passed + error ZeroAddress(); + + /// @notice This error is thrown when trying to set a verifier address that does not implement the expected interface + error VerifierInvalid(address verifierAddress); + + constructor() ConfirmedOwner(msg.sender) {} + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "DestinationVerifierProxy 0.4.0"; + } + + /// @inheritdoc IDestinationVerifierProxy + function verify(bytes calldata payload, bytes calldata parameterPayload) external payable returns (bytes memory) { + return s_verifier.verify{value: msg.value}(payload, parameterPayload, msg.sender); + } + + /// @inheritdoc IDestinationVerifierProxy + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable returns (bytes[] memory verifiedReports) { + return s_verifier.verifyBulk{value: msg.value}(payloads, parameterPayload, msg.sender); + } + + /// @inheritdoc IDestinationVerifierProxy + function setVerifier(address verifierAddress) external onlyOwner { + //check it supports the functions we need + if (!IERC165(verifierAddress).supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId)) + revert VerifierInvalid(verifierAddress); + + s_verifier = IDestinationVerifierProxyVerifier(verifierAddress); + } + + /// @inheritdoc IDestinationVerifierProxy + // solhint-disable-next-line func-name-mixedcase + function s_feeManager() external view override returns (address) { + return s_verifier.s_feeManager(); + } + + /// @inheritdoc IDestinationVerifierProxy + // solhint-disable-next-line func-name-mixedcase + function s_accessController() external view override returns (address) { + return s_verifier.s_accessController(); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == type(IDestinationVerifierProxy).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol new file mode 100644 index 0000000..00420a4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IDestinationFeeManager is IERC165 { + /** + * @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount. + * @param subscriber address trying to verify + * @param report report to calculate the fee for + * @param quoteAddress address of the quote payment token + * @return (fee, reward, totalDiscount) fee and the reward data with the discount applied + */ + function getFeeAndReward( + address subscriber, + bytes memory report, + address quoteAddress + ) external returns (Common.Asset memory, Common.Asset memory, uint256); + + /** + * @notice Sets the native surcharge + * @param surcharge surcharge to be paid if paying in native + */ + function setNativeSurcharge(uint64 surcharge) external; + + /** + * @notice Adds a subscriber to the fee manager + * @param subscriber address of the subscriber + * @param feedId feed id to apply the discount to + * @param token token to apply the discount to + * @param discount discount to be applied to the fee + */ + function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) external; + + /** + * @notice Adds a subscriber to the fee manager + * @param subscriber address of the subscriber + * @param token token to apply the discount to + * @param discount discount to be applied to the fee + */ + function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external; + + /** + * @notice Withdraws any native or LINK rewards to the owner address + * @param assetAddress address of the asset to withdraw + * @param recipientAddress address to withdraw to + * @param quantity quantity to withdraw + */ + function withdraw(address assetAddress, address recipientAddress, uint192 quantity) external; + + /** + * @notice Returns the link balance of the fee manager + * @return link balance of the fee manager + */ + function linkAvailableForPayment() external returns (uint256); + + /** + * @notice Admin function to pay the LINK deficit for a given config digest + * @param configDigest the config digest to pay the deficit for + */ + function payLinkDeficit(bytes32 configDigest) external; + + /** + * @notice Adds the verifier to the list of verifiers able to use the feeManager + * @param verifier address of the verifier + */ + function addVerifier(address verifier) external; + + /** + * @notice Removes the verifier from the list of verifiers able to use the feeManager + * @param verifier address of the verifier + */ + function removeVerifier(address verifier) external; + + /** + * @notice Sets the reward manager to the address + * @param rewardManager address of the reward manager + */ + function setRewardManager(address rewardManager) external; + + /** + * @notice The structure to hold a fee and reward to verify a report + * @param digest the digest linked to the fee and reward + * @param fee the fee paid to verify the report + * @param reward the reward paid upon verification + & @param appliedDiscount the discount applied to the reward + */ + struct FeeAndReward { + bytes32 configDigest; + Common.Asset fee; + Common.Asset reward; + uint256 appliedDiscount; + } + + /** + * @notice The structure to hold quote metadata + * @param quoteAddress the address of the quote + */ + struct Quote { + address quoteAddress; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol new file mode 100644 index 0000000..95f0793 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IDestinationRewardManager is IERC165 { + /** + * @notice Record the fee received for a particular pool + * @param payments array of structs containing pool id and amount + * @param payee the user the funds should be retrieved from + */ + function onFeePaid(FeePayment[] calldata payments, address payee) external; + + /** + * @notice Claims the rewards in a specific pool + * @param poolIds array of poolIds to claim rewards for + */ + function claimRewards(bytes32[] calldata poolIds) external; + + /** + * @notice Set the RewardRecipients and weights for a specific pool. This should only be called once per pool Id. Else updateRewardRecipients should be used. + * @param poolId poolId to set RewardRecipients and weights for + * @param rewardRecipientAndWeights array of each RewardRecipient and associated weight + */ + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata rewardRecipientAndWeights) external; + + /** + * @notice Updates a subset the reward recipients for a specific poolId. The collective weight of the recipients should add up to the recipients existing weights. Any recipients with a weight of 0 will be removed. + * @param poolId the poolId to update + * @param newRewardRecipients array of new reward recipients + */ + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata newRewardRecipients) external; + + /** + * @notice Pays all the recipients for each of the pool ids + * @param poolId the pool id to pay recipients for + * @param recipients array of recipients to pay within the pool + */ + function payRecipients(bytes32 poolId, address[] calldata recipients) external; + + /** + * @notice Add the fee manager to the list of feeManagers able to call the reward manager + * @param newFeeManager address of the new verifier proxy + */ + function addFeeManager(address newFeeManager) external; + + /** + * @notice Removes the fee manager. This needs to be done post construction to prevent a circular dependency. + * @param feeManager address of the verifier proxy to remove + */ + function removeFeeManager(address feeManager) external; + + /** + * @notice Gets a list of pool ids which have reward for a specific recipient. + * @param recipient address of the recipient to get pool ids for + * @param startIndex the index to start from + * @param endIndex the index to stop at + */ + function getAvailableRewardPoolIds( + address recipient, + uint256 startIndex, + uint256 endIndex + ) external view returns (bytes32[] memory); + + /** + * @notice The structure to hold a fee payment notice + * @param poolId the poolId receiving the payment + * @param amount the amount being paid + */ + struct FeePayment { + bytes32 poolId; + uint192 amount; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol new file mode 100644 index 0000000..041a8c8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Common} from "../../libraries/Common.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IDestinationVerifier is IERC165 { + /** + * @notice sets off-chain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param f number of faulty oracles the system can tolerate + * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + */ + function setConfig( + address[] memory signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights + ) external; + + /** + * @notice sets off-chain reporting protocol configuration incl. participating oracles + * @param signers addresses with which oracles sign the reports + * @param f number of faulty oracles the system can tolerate + * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards + * @param activationTime the time at which the config was activated + */ + function setConfigWithActivationTime( + address[] memory signers, + uint8 f, + Common.AddressAndWeight[] memory recipientAddressesAndWeights, + uint32 activationTime + ) external; + + /** + * @notice Sets the fee manager address + * @param feeManager The address of the fee manager + */ + function setFeeManager(address feeManager) external; + + /** + * @notice Sets the access controller address + * @param accessController The address of the access controller + */ + function setAccessController(address accessController) external; + + /** + * @notice Updates the config active status + * @param donConfigId The ID of the config to update + * @param isActive The new config active status + */ + function setConfigActive(uint256 donConfigId, bool isActive) external; + + /** + * @notice Removes the latest config + */ + function removeLatestConfig() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol new file mode 100644 index 0000000..291f370 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {Common} from "../../libraries/Common.sol"; + +interface IDestinationVerifierFeeManager is IERC165 { + /** + * @notice Handles fees for a report from the subscriber and manages rewards + * @param poolId pool id of the pool to pay into + * @param payload report to process the fee for + * @param parameterPayload fee payload + * @param subscriber address of the fee will be applied + */ + function processFee( + bytes32 poolId, + bytes calldata payload, + bytes calldata parameterPayload, + address subscriber + ) external payable; + + /** + * @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager + * @param poolIds pool ids of the pool to pay into + * @param payloads reports to process + * @param parameterPayload fee payload + * @param subscriber address of the user to process fee for + */ + function processFeeBulk( + bytes32[] memory poolIds, + bytes[] calldata payloads, + bytes calldata parameterPayload, + address subscriber + ) external payable; + + /** + * @notice Sets the fee recipients according to the fee manager + * @param configDigest digest of the configuration + * @param rewardRecipientAndWeights the address and weights of all the recipients to receive rewards + */ + function setFeeRecipients( + bytes32 configDigest, + Common.AddressAndWeight[] calldata rewardRecipientAndWeights + ) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol new file mode 100644 index 0000000..e0dcb30 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IDestinationVerifierProxy is IERC165 { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the verifier, and bills the user if applicable. + * @param payload The encoded data to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifierResponse The encoded report from the verifier. + */ + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable returns (bytes memory verifierResponse); + + /** + * @notice Bulk verifies that the data encoded has been signed + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payloads The encoded payloads to be verified, including the signed + * report. + * @param parameterPayload fee metadata for billing + * @return verifiedReports The encoded reports from the verifier. + */ + function verifyBulk( + bytes[] calldata payloads, + bytes calldata parameterPayload + ) external payable returns (bytes[] memory verifiedReports); + + /** + * @notice Sets the active verifier for this proxy + * @param verifierAddress The address of the verifier contract + */ + function setVerifier(address verifierAddress) external; + + /** + * @notice Used to honor the source verifierProxy feeManager interface + * @return IVerifierFeeManager + */ + // solhint-disable-next-line func-name-mixedcase + function s_feeManager() external view returns (address); + + /** + * @notice Used to honor the source verifierProxy feeManager interface + * @return AccessControllerInterface + */ + // solhint-disable-next-line func-name-mixedcase + function s_accessController() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol new file mode 100644 index 0000000..a957f8f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IDestinationVerifierProxyVerifier is IERC165 { + /** + * @notice Verifies that the data encoded has been signed correctly using the signatures included within the payload. + * @param signedReport The encoded data to be verified. + * @param parameterPayload The encoded parameters to be used in the verification and billing process. + * @param sender The address that requested to verify the contract.Used for logging and applying the fee. + * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. + * @return verifierResponse The encoded verified response. + */ + function verify( + bytes calldata signedReport, + bytes calldata parameterPayload, + address sender + ) external payable returns (bytes memory verifierResponse); + + /** + * @notice Bulk verifies that the data encoded has been signed correctly using the signatures included within the payload. + * @param signedReports The encoded data to be verified. + * @param parameterPayload The encoded parameters to be used in the verification and billing process. + * @param sender The address that requested to verify the contract. Used for logging and applying the fee. + * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. + * @return verifiedReports The encoded verified responses. + */ + function verifyBulk( + bytes[] calldata signedReports, + bytes calldata parameterPayload, + address sender + ) external payable returns (bytes[] memory verifiedReports); + + /* + * @notice Returns the reward manager + * @return IDestinationRewardManager + */ + // solhint-disable-next-line func-name-mixedcase + function s_feeManager() external view returns (address); + + /** + * @notice Returns the access controller + * @return IDestinationFeeManager + */ + // solhint-disable-next-line func-name-mixedcase + function s_accessController() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol new file mode 100644 index 0000000..38b1bad --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {DestinationFeeManager} from "../../DestinationFeeManager.sol"; +import {DestinationRewardManager} from "../../DestinationRewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; +import {DestinationFeeManagerProxy} from "../mocks/DestinationFeeManagerProxy.sol"; + +/** + * @title BaseDestinationFeeManagerTest + * @author Michael Fletcher + * @notice Base class for all feeManager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup the feeManager + */ +contract BaseDestinationFeeManagerTest is Test { + //contracts + DestinationFeeManager internal feeManager; + DestinationRewardManager internal rewardManager; + DestinationFeeManagerProxy internal feeManagerProxy; + + ERC20Mock internal link; + WERC20Mock internal native; + + //erc20 config + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + //contract owner + address internal constant INVALID_ADDRESS = address(0); + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + address internal constant PROXY = address(uint160(uint256(keccak256("PROXY")))); + + //version masks + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + //feed ids & config digests + bytes32 internal constant DEFAULT_FEED_1_V1 = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V2 = (keccak256("ETH-USD") & V_MASK) | V2_BITMASK; + bytes32 internal constant DEFAULT_FEED_1_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + bytes32 internal constant DEFAULT_FEED_2_V3 = (keccak256("LINK-USD") & V_MASK) | V3_BITMASK; + bytes32 internal constant DEFAULT_CONFIG_DIGEST = keccak256("DEFAULT_CONFIG_DIGEST"); + bytes32 internal constant DEFAULT_CONFIG_DIGEST2 = keccak256("DEFAULT_CONFIG_DIGEST2"); + + //report + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + //rewards + uint64 internal constant FEE_SCALAR = 1e18; + + address internal constant NATIVE_WITHDRAW_ADDRESS = address(0); + + //the selector for each error + bytes4 internal immutable INVALID_DISCOUNT_ERROR = DestinationFeeManager.InvalidDiscount.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR = DestinationFeeManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_SURCHARGE_ERROR = DestinationFeeManager.InvalidSurcharge.selector; + bytes4 internal immutable EXPIRED_REPORT_ERROR = DestinationFeeManager.ExpiredReport.selector; + bytes4 internal immutable INVALID_DEPOSIT_ERROR = DestinationFeeManager.InvalidDeposit.selector; + bytes4 internal immutable INVALID_QUOTE_ERROR = DestinationFeeManager.InvalidQuote.selector; + bytes4 internal immutable UNAUTHORIZED_ERROR = DestinationFeeManager.Unauthorized.selector; + bytes4 internal immutable POOLID_MISMATCH_ERROR = DestinationFeeManager.PoolIdMismatch.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes internal constant INSUFFICIENT_ALLOWANCE_ERROR = "ERC20: insufficient allowance"; + bytes4 internal immutable ZERO_DEFICIT = DestinationFeeManager.ZeroDeficit.selector; + + //events emitted + event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); + event NativeSurchargeUpdated(uint64 newSurcharge); + event InsufficientLink(IDestinationRewardManager.FeePayment[] feesAndRewards); + event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); + event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); + event DiscountApplied( + bytes32 indexed configDigest, + address indexed subscriber, + Common.Asset fee, + Common.Asset reward, + uint256 appliedDiscountQuantity + ); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeContracts(); + } + + function _initializeContracts() internal { + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + native = new WERC20Mock(); + + feeManagerProxy = new DestinationFeeManagerProxy(); + rewardManager = new DestinationRewardManager(address(link)); + feeManager = new DestinationFeeManager( + address(link), + address(native), + address(feeManagerProxy), + address(rewardManager) + ); + + //link the feeManager to the proxy + feeManagerProxy.setDestinationFeeManager(address(feeManager)); + + //link the feeManager to the reward manager + rewardManager.addFeeManager(address(feeManager)); + + //mint some tokens to the admin + link.mint(ADMIN, DEFAULT_LINK_MINT_QUANTITY); + native.mint(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some tokens to the proxy + link.mint(PROXY, DEFAULT_LINK_MINT_QUANTITY); + native.mint(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function setSubscriberDiscount( + address subscriber, + bytes32 feedId, + address token, + uint256 discount, + address sender + ) internal { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the discount + feeManager.updateSubscriberDiscount(subscriber, feedId, token, uint64(discount)); + + //change back to the original address + changePrank(originalAddr); + } + + function setSubscriberGlobalDiscount(address subscriber, address token, uint256 discount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the discount + feeManager.updateSubscriberGlobalDiscount(subscriber, token, uint64(discount)); + + //change back to the original address + changePrank(originalAddr); + } + + function setNativeSurcharge(uint256 surcharge, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.setNativeSurcharge(uint64(surcharge)); + + //change back to the original address + changePrank(originalAddr); + } + + // solium-disable-next-line no-unused-vars + function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the fee + (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return fee; + } + + function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { + //get the reward + (, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote); + + return reward; + } + + function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) { + //get the reward + (, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote); + + return appliedDiscount; + } + + function getV1Report(bytes32 feedId) public pure returns (bytes memory) { + return abi.encode(feedId, uint32(0), int192(0), int192(0), int192(0), uint64(0), bytes32(0), uint64(0), uint64(0)); + } + + function getV2Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0) + ); + } + + function getV3Report(bytes32 feedId) public view returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(DEFAULT_REPORT_NATIVE_FEE), + uint192(DEFAULT_REPORT_LINK_FEE), + uint32(block.timestamp), + int192(0), + int192(0), + int192(0) + ); + } + + function getV3ReportWithCustomExpiryAndFee( + bytes32 feedId, + uint256 expiry, + uint256 linkFee, + uint256 nativeFee + ) public pure returns (bytes memory) { + return + abi.encode( + feedId, + uint32(0), + uint32(0), + uint192(nativeFee), + uint192(linkFee), + uint32(expiry), + int192(0), + int192(0), + int192(0) + ); + } + + function getLinkQuote() public view returns (address) { + return address(link); + } + + function getNativeQuote() public view returns (address) { + return address(native); + } + + function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //set the surcharge + feeManager.withdraw(assetAddress, recipient, uint192(amount)); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkBalance(address balanceAddress) public view returns (uint256) { + return link.balanceOf(balanceAddress); + } + + function getNativeBalance(address balanceAddress) public view returns (uint256) { + return native.balanceOf(balanceAddress); + } + + function getNativeUnwrappedBalance(address balanceAddress) public view returns (uint256) { + return balanceAddress.balance; + } + + function mintLink(address recipient, uint256 amount) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(ADMIN); + + //mint the link to the recipient + link.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function mintNative(address recipient, uint256 amount, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //mint the native to the recipient + native.mint(recipient, amount); + + //change back to the original address + changePrank(originalAddr); + } + + function issueUnwrappedNative(address recipient, uint256 quantity) public { + vm.deal(recipient, quantity); + } + + function ProcessFeeAsUser( + bytes32 poolId, + bytes memory payload, + address subscriber, + address tokenAddress, + uint256 wrappedNativeValue, + address sender + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //process the fee + feeManager.processFee{value: wrappedNativeValue}(poolId, payload, abi.encode(tokenAddress), subscriber); + + //change ProcessFeeAsUserback to the original address + changePrank(originalAddr); + } + + function processFee( + bytes32 poolId, + bytes memory payload, + address subscriber, + address feeAddress, + uint256 wrappedNativeValue + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFee{value: wrappedNativeValue}(poolId, payload, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function processFee( + bytes32[] memory poolIds, + bytes[] memory payloads, + address subscriber, + address feeAddress, + uint256 wrappedNativeValue + ) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(subscriber); + + //process the fee + feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(poolIds, payloads, abi.encode(feeAddress)); + + //change back to the original address + changePrank(originalAddr); + } + + function getPayload(bytes memory reportPayload) public pure returns (bytes memory) { + return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32("")); + } + + function approveLink(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + link.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function approveNative(address spender, uint256 quantity, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + native.approve(spender, quantity); + + //change back to the original address + changePrank(originalAddr); + } + + function payLinkDeficit(bytes32 configDigest, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //approve the link to be transferred + feeManager.payLinkDeficit(configDigest); + + //change back to the original address + changePrank(originalAddr); + } + + function getLinkDeficit(bytes32 configDigest) public view returns (uint256) { + return feeManager.s_linkDeficit(configDigest); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol new file mode 100644 index 0000000..305125c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseDestinationFeeManager.t.sol"; + +/** + * @title BaseDestinationFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the setup functionality of the feemanager + */ +contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_WithdrawERC20() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //get the balances to ne used for comparison + uint256 contractBalance = getLinkBalance(address(feeManager)); + uint256 adminBalance = getLinkBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getLinkBalance(address(feeManager)); + uint256 newAdminBalance = getLinkBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawUnwrappedNative() public { + //issue funds straight to the contract to bypass the lack of fallback function + issueUnwrappedNative(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); + + //get the balances to be used for comparison + uint256 contractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 adminBalance = getNativeUnwrappedBalance(ADMIN); + + //the amount to withdraw + uint256 withdrawAmount = contractBalance / 2; + + //withdraw some balance + withdraw(NATIVE_WITHDRAW_ADDRESS, ADMIN, withdrawAmount, ADMIN); + + //check the balance has been reduced + uint256 newContractBalance = getNativeUnwrappedBalance(address(feeManager)); + uint256 newAdminBalance = getNativeUnwrappedBalance(ADMIN); + + //check the balance is greater than zero + assertGt(newContractBalance, 0); + //check the balance has been reduced by the correct amount + assertEq(newContractBalance, contractBalance - withdrawAmount); + //check the admin balance has increased by the correct amount + assertEq(newAdminBalance, adminBalance + withdrawAmount); + } + + function test_WithdrawNonAdminAddr() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //should revert if not admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //withdraw some balance + withdraw(address(link), ADMIN, DEFAULT_LINK_MINT_QUANTITY, USER); + } + + function test_eventIsEmittedAfterSurchargeIsSet() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 5; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_subscriberDiscountEventIsEmittedOnUpdate() public { + //native surcharge + uint64 discount = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit SubscriberDiscountUpdated(USER, DEFAULT_FEED_1_V3, address(native), discount); + + //set the surcharge + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + } + + function test_eventIsEmittedUponWithdraw() public { + //simulate a fee + mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); + + //the amount to withdraw + uint192 withdrawAmount = 1; + + //expect an emit + vm.expectEmit(); + + //the event to be emitted + emit Withdraw(ADMIN, ADMIN, address(link), withdrawAmount); + + //withdraw some balance + withdraw(address(link), ADMIN, withdrawAmount, ADMIN); + } + + function test_linkAvailableForPaymentReturnsLinkBalance() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //check there's a balance + assertGt(getLinkBalance(address(feeManager)), 0); + + //check the link available for payment is the link balance + assertEq(feeManager.linkAvailableForPayment(), getLinkBalance(address(feeManager))); + } + + function test_payLinkDeficit() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); + contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + emit InsufficientLink(contractFees); + + //process the fee + processFee(contractFees[0].poolId, payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_payLinkDeficitTwice() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //not enough funds in the reward pool should trigger an insufficient link event + vm.expectEmit(); + + IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); + contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //process the fee + processFee(contractFees[0].poolId, payload, USER, address(native), 0); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //paying again should revert with 0 + vm.expectRevert(ZERO_DEFICIT); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + } + + function test_payLinkDeficitPaysAllFeesProcessed() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + + //check the deficit has been increased twice + assertEq(getLinkDeficit(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE * 2); + + //double check the rewardManager balance is 0 + assertEq(getLinkBalance(address(rewardManager)), 0); + + //simulate a deposit of link to cover the deficit + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 2); + + vm.expectEmit(); + emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE * 2); + + //pay the deficit which will transfer link from the rewardManager to the rewardManager + payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); + + //check the rewardManager received the link + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); + } + + function test_payLinkDeficitOnlyCallableByAdmin() public { + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + payLinkDeficit(DEFAULT_CONFIG_DIGEST, USER); + } + + function test_revertOnSettingAnAddressZeroVerifier() public { + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.addVerifier(address(0)); + } + + function test_onlyCallableByOwnerReverts() public { + address STRANGER = address(999); + changePrank(STRANGER); + vm.expectRevert(bytes("Only callable by owner")); + feeManager.addVerifier(address(0)); + } + + function test_addVerifierExistingAddress() public { + address dummyAddress = address(998); + feeManager.addVerifier(dummyAddress); + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.addVerifier(dummyAddress); + } + + function test_addVerifier() public { + address dummyAddress = address(998); + feeManager.addVerifier(dummyAddress); + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.addVerifier(dummyAddress); + + // check calls to setFeeRecipients it should not error unauthorized + changePrank(dummyAddress); + bytes32 dummyConfigDigest = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); + recipients[0] = Common.AddressAndWeight(address(991), 1e18); + feeManager.setFeeRecipients(dummyConfigDigest, recipients); + + // removing this verifier should result in unauthorized when calling setFeeRecipients + changePrank(ADMIN); + feeManager.removeVerifier(dummyAddress); + changePrank(dummyAddress); + vm.expectRevert(UNAUTHORIZED_ERROR); + feeManager.setFeeRecipients(dummyConfigDigest, recipients); + } + + function test_removeVerifierZeroAaddress() public { + address dummyAddress = address(0); + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.removeVerifier(dummyAddress); + } + + function test_removeVerifierNonExistentAddress() public { + address dummyAddress = address(991); + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.removeVerifier(dummyAddress); + } + + function test_setRewardManagerZeroAddress() public { + vm.expectRevert(INVALID_ADDRESS_ERROR); + feeManager.setRewardManager(address(0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol new file mode 100644 index 0000000..ddd3ac5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol @@ -0,0 +1,720 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseDestinationFeeManager.t.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager's getFeeAndReward + */ +contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { + function test_baseFeeIsAppliedForNative() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_baseFeeIsAppliedForLink() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_discountAIsNotAppliedWhenSetForOtherUsers() public { + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), INVALID_ADDRESS); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_discountIsNotAppliedForInvalidTokenAddress() public { + //should revert with invalid address as it's not a configured token + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //set the subscriber discount for another user + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, INVALID_ADDRESS, FEE_SCALAR / 2, ADMIN); + } + + function test_discountIsAppliedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_DiscountIsAppliedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE / 2); + } + + function test_discountIsNoLongerAppliedAfterRemoving() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsNotAppliedForLinkFee() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_surchargeIsNoLongerAppliedAfterRemoving() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should be the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //remove the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the default + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewSurchargeIsApplied() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + + //change the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge + expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); + } + + function test_surchargeIsAppliedForNativeFeeWithDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); + + //calculate the expected discount quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge) / 2); + + //expected fee should the base fee offset by the surcharge and discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge - expectedDiscount); + } + + function test_emptyQuoteRevertsWithError() public { + //expect a revert + vm.expectRevert(INVALID_QUOTE_ERROR); + + //get the fee required by the feeManager + getFee(getV3Report(DEFAULT_FEED_1_V3), address(0), USER); + } + + function test_nativeSurcharge100Percent() public { + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be twice the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2); + } + + function test_nativeSurcharge0Percent() public { + //set the surcharge + setNativeSurcharge(0, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_nativeSurchargeCannotExceed100Percent() public { + //should revert if surcharge is greater than 100% + vm.expectRevert(INVALID_SURCHARGE_ERROR); + + //set the surcharge above the max + setNativeSurcharge(FEE_SCALAR + 1, ADMIN); + } + + function test_discountIsAppliedWith100PercentSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE; + + //fee should be twice the surcharge minus the discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2 - expectedDiscount); + } + + function test_feeIsZeroWith100PercentDiscount() public { + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_feeIsUpdatedAfterDiscountIsRemoved() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //remove the discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), 0, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_feeIsUpdatedAfterNewDiscountIsApplied() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity + uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; + + //fee should be 50% of the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + + //change the discount to 25% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); + + //get the fee required by the feeManager + fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //expected discount is now 25% + expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 4; + + //fee should be the base fee minus the expected discount + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_setDiscountOver100Percent() public { + //should revert with invalid discount + vm.expectRevert(INVALID_DISCOUNT_ERROR); + + //set the subscriber discount to over 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR + 1, ADMIN); + } + + function test_surchargeIsNotAppliedWith100PercentDiscount() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 5; + + //set the subscriber discount to 100% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nonAdminUserCanNotSetDiscount() public { + //should revert with unauthorized + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, USER); + } + + function test_surchargeFeeRoundsUpWhenUneven() public { + //native surcharge + uint256 nativeSurcharge = FEE_SCALAR / 3; + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected surcharge quantity + uint256 expectedSurcharge = (DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR; + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge + 1); + } + + function test_discountFeeRoundsDownWhenUneven() public { + //native surcharge + uint256 discount = FEE_SCALAR / 3; + + //set the subscriber discount to 33.333% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected quantity + uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE * discount) / FEE_SCALAR); + + //expected fee should the base fee offset by the expected surcharge + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); + } + + function test_reportWithNoExpiryOrFeeReturnsZero() public view { + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV1Report(DEFAULT_FEED_1_V1), getNativeQuote(), USER); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() public { + //set the subscriber and native discounts + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager for both tokens + Common.Asset memory linkFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory nativeFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //calculate the expected discount quantity for each token + uint256 expectedDiscountLink = (DEFAULT_REPORT_LINK_FEE * FEE_SCALAR) / 4 / FEE_SCALAR; + uint256 expectedDiscountNative = (DEFAULT_REPORT_NATIVE_FEE * FEE_SCALAR) / 2 / FEE_SCALAR; + + //check the fee calculation for each token + assertEq(linkFee.amount, DEFAULT_REPORT_LINK_FEE - expectedDiscountLink); + assertEq(nativeFee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscountNative); + } + + function test_discountIsNotAppliedToOtherFeeds() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_2_V3), getNativeQuote(), USER); + + //fee should be the base fee + assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); + } + + function test_noFeeIsAppliedWhenReportHasZeroFee() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), + getNativeQuote(), + USER + ); + + //fee should be zero + assertEq(fee.amount, 0); + } + + function test_nativeSurchargeEventIsEmittedOnUpdate() public { + //native surcharge + uint64 nativeSurcharge = FEE_SCALAR / 3; + + //an event should be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit NativeSurchargeUpdated(nativeSurcharge); + + //set the surcharge + setNativeSurcharge(nativeSurcharge, ADMIN); + } + + function test_getBaseRewardWithLinkQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkQuoteAndLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getRewardWithNativeQuote() public view { + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithNativeQuoteAndSurcharge() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_getRewardWithLinkDiscount() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal the discounted base fee + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); + } + + function test_getLinkFeeIsRoundedUp() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //the reward should equal .66% + 1 of the base fee due to a 33% discount rounded up + assertEq(fee.amount, (DEFAULT_REPORT_LINK_FEE * 2) / 3 + 1); + } + + function test_getLinkRewardIsSameAsFee() public { + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //check the reward is in link + assertEq(fee.assetAddress, address(link)); + + //the reward should equal .66% of the base fee due to a 33% discount rounded down + assertEq(reward.amount, fee.amount); + } + + function test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() public { + //set the native surcharge + setNativeSurcharge(FEE_SCALAR / 2, ADMIN); + + //set the link discount + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); + + //get the fee required by the feeManager + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //the reward should equal the base fee in link regardless of the surcharge + assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); + } + + function test_testRevertIfReportHasExpired() public { + //expect a revert + vm.expectRevert(EXPIRED_REPORT_ERROR); + + //get the fee required by the feeManager + getFee( + getV3ReportWithCustomExpiryAndFee( + DEFAULT_FEED_1_V3, + block.timestamp - 1, + DEFAULT_REPORT_LINK_FEE, + DEFAULT_REPORT_NATIVE_FEE + ), + getNativeQuote(), + USER + ); + } + + function test_discountIsReturnedForLink() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); + + //get the fee applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNative() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_DiscountIsReturnedForNativeWithSurcharge() public { + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //set the surcharge + setNativeSurcharge(FEE_SCALAR / 5, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountWithNativeAndLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + } + + function test_GlobalDiscountIsOverridenByIndividualDiscountNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 4); + } + + function test_GlobalDiscountIsOverridenByIndividualDiscountLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 4); + } + + function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroLink() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + + //set the global discount to zero + setSubscriberGlobalDiscount(USER, address(link), 0, ADMIN); + + //get the discount applied + discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); + + //fee should be zero + assertEq(discount, 0); + } + + function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroNative() public { + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); + + //get the discount applied + uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be half the default + assertEq(discount, FEE_SCALAR / 2); + + //set the global discount to zero + setSubscriberGlobalDiscount(USER, address(native), 0, ADMIN); + + //get the discount applied + discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + //fee should be zero + assertEq(discount, 0); + } + + function test_GlobalDiscountCantBeSetToMoreThanMaximum() public { + //should revert with invalid discount + vm.expectRevert(INVALID_DISCOUNT_ERROR); + + //set the global discount to 101% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR + 1, ADMIN); + } + + function test_onlyOwnerCanSetGlobalDiscount() public { + //should revert with unauthorized + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //set the global discount to 50% + setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, USER); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol new file mode 100644 index 0000000..0880352 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Common} from "../../../libraries/Common.sol"; +import "./BaseDestinationFeeManager.t.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { + function setUp() public override { + super.setUp(); + } + + function test_nonAdminProxyUserCannotProcessFee() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //should revert as the user is not the owner + vm.expectRevert(UNAUTHORIZED_ERROR); + + //process the fee + ProcessFeeAsUser(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0, USER); + } + + function test_processFeeAsProxy() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeIfSubscriberIsSelf() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert due to the feeManager being the subscriber + vm.expectRevert(INVALID_ADDRESS_ERROR); + + //process the fee will fail due to assertion + processFee(DEFAULT_CONFIG_DIGEST, payload, address(feeManager), address(native), 0); + } + + function test_processFeeWithWithEmptyQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link by default + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); + } + + function test_processFeeWithWithZeroQuotePayload() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as the quote is invalid + vm.expectRevert(INVALID_QUOTE_ERROR); + + //processing the fee will transfer the link by default + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, INVALID_ADDRESS, 0); + } + + function test_processFeeWithWithCorruptQuotePayload() public { + //get the default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV3Report(DEFAULT_FEED_1_V3), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //expect an evm revert as the quote is corrupt + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + } + + function test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); + } + + function test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + } + + function test_processFeeNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeEmitsEventIfNotEnoughLink() public { + //simulate a deposit of half the link required for the fee + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE / 2); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //expect an emit as there's not enough link + vm.expectEmit(); + + IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); + contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + //emit the event that is expected to be emitted + emit InsufficientLink(contractFees); + + //processing the fee will transfer the native from the user to the feeManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE / 2); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNative() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithUnwrappedNativeShortFunds() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INVALID_DEPOSIT_ERROR); + + //only the proxy or admin can call processFee, they will pass in the native value on the users behalf + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddress() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //expect a revert as not enough funds + vm.expectRevert(INSUFFICIENT_ALLOWANCE_ERROR); + + //the change will be returned and the user will attempted to be billed in LINK + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE - 1); + } + + function test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() public { + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, PROXY); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the native unwrapped is no longer in the account + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //native should not be deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithUnwrappedNativeWithExcessiveFee() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. + processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(native), DEFAULT_REPORT_NATIVE_FEE * 2); + + //check the native has been transferred and converted to wrapped native + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); + + //check the link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the feeManager has had the link deducted, the remaining balance should be 0 + assertEq(getLinkBalance(address(feeManager)), 0); + + //check the subscriber has had the native deducted + assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeUsesCorrectDigest() public { + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + //check funds have been paid to the reward manager + assertEq(rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE); + } + + function test_V1PayloadVerifies() public { + //replicate a default payload + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV2Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); + } + + function test_V2PayloadVerifies() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_V2PayloadWithoutQuoteFails() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); + } + + function test_V2PayloadWithoutZeroFee() public { + //get the default payload + bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + + //expect a revert as the quote is invalid + vm.expectRevert(); + + //processing the fee will transfer the link from the user to the rewardManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + } + + function test_processFeeWithInvalidReportVersionFailsToDecode() public { + bytes memory data = abi.encode(0x0000100000000000000000000000000000000000000000000000000000000000); + + //get the default payload + bytes memory payload = getPayload(data); + + //serialization will fail as there is no report to decode + vm.expectRevert(); + + //processing the fee will not withdraw anything as there is no fee to collect + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //call processFee should not revert as the fee is 0 + processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(native), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) + ); + + //approve the link to be transferred from the from the subscriber to the rewardManager + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + + //processing the fee will transfer the link to the rewardManager from the user + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + + //check the link has been transferred + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + //check the user has had the link fee deducted + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //processing the fee will transfer the native from the user to the feeManager + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + + //check the native has been transferred + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); + + //check no link has been transferred to the rewardManager + assertEq(getLinkBalance(address(rewardManager)), 0); + + //check the feeManager has had no link deducted + assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE); + + //check the subscriber has had the native deducted + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + } + + function test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); + } + + function test_processFeeWithZeroNativeNonZeroLinkReturnsChange() public { + //get the default payload + bytes memory payload = getPayload( + getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) + ); + + //call processFee should not revert as the fee is 0 + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE); + + //check the change has been returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_V1PayloadVerifiesAndReturnsChange() public { + //emulate a V1 payload with no quote + bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); + + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), DEFAULT_REPORT_NATIVE_FEE); + + //Fee manager should not contain any native + assertEq(address(feeManager).balance, 0); + assertEq(getNativeBalance(address(feeManager)), 0); + + //check the unused native passed in is returned + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processFeeWithDiscountEmitsEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //set the subscriber discount to 50% + setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE / 2, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + uint256 appliedDiscount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); + + vm.expectEmit(); + + emit DiscountApplied(DEFAULT_CONFIG_DIGEST, USER, fee, reward, appliedDiscount); + + //call processFee should not revert as the fee is 0 + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + } + + function test_processFeeWithNoDiscountDoesNotEmitEvent() public { + //simulate a deposit of link for the conversion pool + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); + + //approve the native to be transferred from the user + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + + //get the default payload + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + //call processFee should not revert as the fee is 0 + processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol new file mode 100644 index 0000000..a50441b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import "./BaseDestinationFeeManager.t.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +/** + * @title BaseFeeManagerTest + * @author Michael Fletcher + * @notice This contract will test the functionality of the feeManager processFee + */ +contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { + uint256 internal constant NUMBER_OF_REPORTS = 5; + + function setUp() public override { + super.setUp(); + } + + function test_processMultipleLinkReports() public { + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); + + processFee(poolIds, payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); + + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 0); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + + //the subscriber (user) should receive funds back and not the proxy, although when live the proxy will forward the funds sent and not cover it seen here + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleWrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS, USER); + + processFee(poolIds, payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processMultipleUnwrappedNativeReports() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); + } + + function test_processV1V2V3Reports() public { + mintLink(address(feeManager), 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory linkPayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory linkPayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = linkPayloadV2; + payloads[2] = linkPayloadV2; + payloads[3] = linkPayloadV3; + payloads[4] = linkPayloadV3; + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * 4, USER); + + bytes32[] memory poolIds = new bytes32[](5); + for (uint256 i = 0; i < 5; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + processFee(poolIds, payloads, USER, address(link), 0); + + assertEq(getNativeBalance(address(feeManager)), 0); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - 0); + } + + function test_processV1V2V3ReportsWithUnwrapped() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 4 + 1); + + bytes memory payloadV1 = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes memory nativePayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); + bytes memory nativePayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = payloadV1; + payloads[1] = nativePayloadV2; + payloads[2] = nativePayloadV2; + payloads[3] = nativePayloadV3; + payloads[4] = nativePayloadV3; + + bytes32[] memory poolIds = new bytes32[](5); + for (uint256 i = 0; i < 5; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 4); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); + assertEq(getLinkBalance(address(feeManager)), 1); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 4); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_processMultipleV1Reports() public { + bytes memory payload = abi.encode( + [DEFAULT_CONFIG_DIGEST, 0, 0], + getV1Report(DEFAULT_FEED_1_V1), + new bytes32[](1), + new bytes32[](1), + bytes32("") + ); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 5); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + } + + function test_eventIsEmittedIfNotEnoughLink() public { + bytes memory nativePayload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](5); + payloads[0] = nativePayload; + payloads[1] = nativePayload; + payloads[2] = nativePayload; + payloads[3] = nativePayload; + payloads[4] = nativePayload; + + approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 5, USER); + + IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](5); + payments[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[1] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[2] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[3] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + payments[4] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); + + vm.expectEmit(); + + bytes32[] memory poolIds = new bytes32[](5); + for (uint256 i = 0; i < 5; ++i) { + poolIds[i] = payments[i].poolId; + } + + emit InsufficientLink(payments); + + processFee(poolIds, payloads, USER, address(native), 0); + + assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY); + } + + function test_processPoolIdsPassedMismatched() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + // poolIds passed are different that number of reports in payload + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS - 1); + for (uint256 i = 0; i < NUMBER_OF_REPORTS - 1; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + vm.expectRevert(POOLID_MISMATCH_ERROR); + processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); + } + + function test_poolIdsCannotBeZeroAddress() public { + mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); + + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + + poolIds[2] = 0x000; + vm.expectRevert(INVALID_ADDRESS_ERROR); + processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); + } + + function test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() public { + bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); + + bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + payloads[i] = payload; + } + + bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); + for (uint256 i = 0; i < NUMBER_OF_REPORTS - 1; ++i) { + poolIds[i] = DEFAULT_CONFIG_DIGEST; + } + poolIds[NUMBER_OF_REPORTS - 1] = DEFAULT_CONFIG_DIGEST2; + + approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); + + // Checking no rewards yet for each pool + for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { + bytes32 p_id = poolIds[i]; + uint256 poolDeficit = rewardManager.s_totalRewardRecipientFees(p_id); + assertEq(poolDeficit, 0); + } + + processFee(poolIds, payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); + + assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + assertEq(getLinkBalance(address(feeManager)), 0); + assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); + assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); + + // Checking each pool got the correct rewards + uint256 expectedRewards = DEFAULT_REPORT_LINK_FEE * (NUMBER_OF_REPORTS - 1); + uint256 poolRewards = rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST); + assertEq(poolRewards, expectedRewards); + + expectedRewards = DEFAULT_REPORT_LINK_FEE; + poolRewards = rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST2); + assertEq(poolRewards, expectedRewards); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol new file mode 100644 index 0000000..7dde878 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IDestinationVerifierFeeManager} from "../../interfaces/IDestinationVerifierFeeManager.sol"; + +contract DestinationFeeManagerProxy { + IDestinationVerifierFeeManager internal s_feeManager; + + function processFee(bytes32 poolId, bytes calldata payload, bytes calldata parameterPayload) public payable { + s_feeManager.processFee{value: msg.value}(poolId, payload, parameterPayload, msg.sender); + } + + function processFeeBulk( + bytes32[] memory poolIds, + bytes[] calldata payloads, + bytes calldata parameterPayload + ) public payable { + s_feeManager.processFeeBulk{value: msg.value}(poolIds, payloads, parameterPayload, msg.sender); + } + + function setDestinationFeeManager(address feeManager) public { + s_feeManager = IDestinationVerifierFeeManager(feeManager); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol new file mode 100644 index 0000000..7cafb16 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +/** + * @title DestinationRewardManagerTest + * @author Michael Fletcher + * @notice Base class for all reward manager tests + * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup a primary and secondary pool + */ +contract BaseDestinationRewardManagerTest is Test { + //contracts + ERC20Mock internal asset; + ERC20Mock internal unsupported; + DestinationRewardManager internal rewardManager; + + //default address for unregistered recipient + address internal constant INVALID_ADDRESS = address(0); + //contract owner + address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); + //address to represent feeManager contract + address internal constant FEE_MANAGER = address(uint160(uint256(keccak256("FEE_MANAGER")))); + //address to represent another feeManager + address internal constant FEE_MANAGER_2 = address(uint160(uint256(keccak256("FEE_MANAGER_2")))); + //a general user + address internal constant USER = address(uint160(uint256(keccak256("USER")))); + + //default recipients configured in reward manager + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); + address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); + address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); + address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); + address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); + address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); + + //additional recipients not in the reward manager + address internal constant DEFAULT_RECIPIENT_8 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_8")))); + address internal constant DEFAULT_RECIPIENT_9 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_9")))); + + //two pools should be enough to test all edge cases + bytes32 internal constant PRIMARY_POOL_ID = keccak256("primary_pool"); + bytes32 internal constant SECONDARY_POOL_ID = keccak256("secondary_pool"); + bytes32 internal constant INVALID_POOL_ID = keccak256("invalid_pool"); + bytes32 internal constant ZERO_POOL_ID = bytes32(0); + + //convenience arrays of all pool combinations used for testing + bytes32[] internal PRIMARY_POOL_ARRAY = [PRIMARY_POOL_ID]; + bytes32[] internal SECONDARY_POOL_ARRAY = [SECONDARY_POOL_ID]; + bytes32[] internal ALL_POOLS = [PRIMARY_POOL_ID, SECONDARY_POOL_ID]; + + //erc20 config + uint256 internal constant DEFAULT_MINT_QUANTITY = 100 ether; + + //reward scalar (this should match the const in the contract) + uint64 internal constant POOL_SCALAR = 1e18; + uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; + uint64 internal constant FIFTY_PERCENT = POOL_SCALAR / 2; + uint64 internal constant TEN_PERCENT = POOL_SCALAR / 10; + + //the selector for each error + bytes4 internal immutable UNAUTHORIZED_ERROR_SELECTOR = DestinationRewardManager.Unauthorized.selector; + bytes4 internal immutable INVALID_ADDRESS_ERROR_SELECTOR = DestinationRewardManager.InvalidAddress.selector; + bytes4 internal immutable INVALID_WEIGHT_ERROR_SELECTOR = DestinationRewardManager.InvalidWeights.selector; + bytes4 internal immutable INVALID_POOL_ID_ERROR_SELECTOR = DestinationRewardManager.InvalidPoolId.selector; + bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; + bytes4 internal immutable INVALID_POOL_LENGTH_SELECTOR = DestinationRewardManager.InvalidPoolLength.selector; + + // Events emitted within the reward manager + event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); + event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); + event FeeManagerUpdated(address newProxyAddress); + event FeePaid(IDestinationRewardManager.FeePayment[] payments, address payee); + + function setUp() public virtual { + //change to admin user + vm.startPrank(ADMIN); + + //init required contracts + _initializeERC20Contracts(); + _initializeRewardManager(); + } + + function _initializeERC20Contracts() internal { + //create the contracts + asset = new ERC20Mock("ASSET", "AST", ADMIN, 0); + unsupported = new ERC20Mock("UNSUPPORTED", "UNS", ADMIN, 0); + + //mint some tokens to the admin + asset.mint(ADMIN, DEFAULT_MINT_QUANTITY); + unsupported.mint(ADMIN, DEFAULT_MINT_QUANTITY); + + //mint some tokens to the user + asset.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + unsupported.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); + } + + function _initializeRewardManager() internal { + //create the contract + rewardManager = new DestinationRewardManager(address(asset)); + + rewardManager.addFeeManager(FEE_MANAGER); + } + + function createPrimaryPool() public { + rewardManager.setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients()); + } + + function createSecondaryPool() public { + rewardManager.setRewardRecipients(SECONDARY_POOL_ID, getSecondaryRecipients()); + } + + //override this to test variations of different recipients. changing this function will require existing tests to be updated as constants are hardcoded to be explicit + function getPrimaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); + + return recipients; + } + + function getPrimaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_2; + recipients[2] = DEFAULT_RECIPIENT_3; + recipients[3] = DEFAULT_RECIPIENT_4; + + return recipients; + } + + //override this to test variations of different recipients. + function getSecondaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights. 2500 = 25% of pool + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); + + return recipients; + } + + function getSecondaryRecipientAddresses() public pure returns (address[] memory) { + //array of recipients + address[] memory recipients = new address[](4); + + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_5; + recipients[2] = DEFAULT_RECIPIENT_6; + recipients[3] = DEFAULT_RECIPIENT_7; + + return recipients; + } + + function addFundsToPool(bytes32 poolId, Common.Asset memory amount, address sender) public { + IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); + payments[0] = IDestinationRewardManager.FeePayment(poolId, uint192(amount.amount)); + + addFundsToPool(payments, sender); + } + + function addFundsToPool(IDestinationRewardManager.FeePayment[] memory payments, address sender) public { + //record the current address and switch to the sender + address originalAddr = msg.sender; + changePrank(sender); + + uint256 totalPayment; + for (uint256 i; i < payments.length; ++i) { + totalPayment += payments[i].amount; + } + + //approve the amount being paid into the pool + ERC20Mock(address(asset)).approve(address(rewardManager), totalPayment); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, sender); + + //change back to the original address + changePrank(originalAddr); + } + + function getAsset(uint256 quantity) public view returns (Common.Asset memory) { + return Common.Asset(address(asset), quantity); + } + + function getAssetBalance(address addr) public view returns (uint256) { + return asset.balanceOf(addr); + } + + function claimRewards(bytes32[] memory poolIds, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //claim the rewards + rewardManager.claimRewards(poolIds); + + //change back to the original address + changePrank(originalAddr); + } + + function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.payRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.setRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function setFeeManager(address feeManager, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //update the proxy + rewardManager.addFeeManager(feeManager); + + //change back to the original address + changePrank(originalAddr); + } + + function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.updateRewardRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol new file mode 100644 index 0000000..c0a67d0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol @@ -0,0 +1,790 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title DestinationRewardManagerClaimTest + * @author Michael Fletcher + * @notice This contract will test the claim functionality of the RewardManager contract. + */ +contract DestinationRewardManagerClaimTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipients() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } + + function test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() public { + //add funds to a different pool to ensure they're not claimed + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create an array containing duplicate poolIds + bytes32[] memory poolIds = new bytes32[](2); + poolIds[0] = PRIMARY_POOL_ID; + poolIds[1] = PRIMARY_POOL_ID; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(poolIds, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the pool should still have the remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimSingleRecipient() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + } + + function test_claimMultipleRecipients() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - (expectedRecipientAmount * 2)); + } + + function test_claimUnregisteredRecipient() public { + //claim the rewards for a recipient who isn't in this pool + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding 1 to the pool should leave 1 wei worth of dust, which the contract doesn't handle due to it being economically infeasible + addFundsToPool(PRIMARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the rewardManager has the remaining quantity equals 1 wei + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_claimUnregisteredPoolId() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance is still 0 as there's no pool to receive fees from + assertEq(getAssetBalance(recipient.addr), 0); + + //check the rewardManager has the full amount + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_recipientsClaimMultipleDeposits() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //expected recipient amount is 1/4 of the pool deposit + expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should again be 0 as all of the funds have been claimed + assertEq(getAssetBalance(address(rewardManager)), 0); + } + + function test_eventIsEmittedUponClaim() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardsClaimed(PRIMARY_POOL_ID, recipient.addr, uint192(POOL_DEPOSIT_AMOUNT / 4)); + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + } + + function test_eventIsNotEmittedUponUnsuccessfulClaim() public { + //record logs to check no events were emitted + vm.recordLogs(); + + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //no logs should have been emitted + assertEq(vm.getRecordedLogs().length, 0); + } +} + +contract DestinationRewardManagerRecipientClaimMultiplePoolsTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a two pools + createPrimaryPool(); + createSecondaryPool(); + + //add funds to each of the pools to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsSinglePool() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //check the pool balance is still equal to DEPOSIT_AMOUNT as the test only claims for one of the pools + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimMultipleRecipientsSinglePool() public { + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); + } + + function test_claimMultipleRecipientsMultiplePools() public { + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received. The first recipient is shared across both pools so should receive 1/4 of each pool + assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount * 2); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimAllRecipientsMultiplePools() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim funds for each recipient within the pool + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory secondaryRecipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, secondaryRecipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(secondaryRecipient.addr), expectedRecipientAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + Common.AddressAndWeight memory commonRecipient = getPrimaryRecipients()[0]; + + //claim the individual rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, commonRecipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, commonRecipient.addr); + + //check the balance matches the ratio the recipient should have received, which is 1/4 of each deposit for each pool + assertEq(getAssetBalance(commonRecipient.addr), expectedRecipientAmount * 2); + } + + function test_claimSingleUniqueRecipient() public { + //the first recipient of the secondary pool is in both pools, so take the second recipient which is unique + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[1]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //the recipient should have received 1/4 of the deposit amount + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimSingleRecipientMultiplePools() public { + //the first recipient of the secondary pool is in both pools + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; + + //this recipient belongs in both pools so should have received 1/4 of each + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); + } + + function test_claimUnregisteredRecipient() public { + //claim the individual rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); + claimRewards(SECONDARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); + + //check the recipients didn't receive any fees from this pool + assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); + assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), 0); + + //check the rewardManager has the remaining quantity + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2); + } + + function test_claimUnevenAmountRoundsDown() public { + //adding an uneven amount of dust to each pool, this should round down to the nearest whole number with 4 remaining in the contract + addFundsToPool(PRIMARY_POOL_ID, getAsset(3), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(1), FEE_MANAGER); + + //the recipient should have received 1/4 of the deposit amount for each pool + uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), recipientExpectedAmount * 2); + + //claim funds for each recipient of the secondary pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); + } + + //contract should have 4 remaining + assertEq(getAssetBalance(address(rewardManager)), 4); + } + + function test_singleRecipientClaimMultipleDeposits() public { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit plus the deposit from the second pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - expectedRecipientAmount); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the individual rewards for this recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received 1/4 of the next deposit amount + expectedRecipientAmount += POOL_DEPOSIT_AMOUNT / 4; + + //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + + //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 3 - expectedRecipientAmount); + } + + function test_recipientsClaimMultipleDeposits() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim funds for each recipient within the pool + for (uint256 i; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //the reward manager balance should contain only the funds of the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add funds to the pool to be split among the recipients + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //special case to handle the first recipient of each pool as they're the same address + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount * 2); + + //claim funds for each recipient within the pool except the first + for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); + } + + //the reward manager balance should again be the balance of the secondary pool as the primary pool has been emptied twice + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_claimEmptyPoolWhenSecondPoolContainsFunds() public { + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //claim all rewards for each recipient in the primary pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //claim all the rewards again for the first recipient as that address is a member of both pools + claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //check the balance + assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); + } + + function test_getRewardsAvailableToRecipientInBothPools() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInSinglePool() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[1].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInNoPools() public view { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, 0, type(uint256).max); + + //check the recipient is in neither pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() public { + //get index 0 as this recipient is in both default pools + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( + getPrimaryRecipients()[0].addr, + 0, + type(uint256).max + ); + + //check the recipient is in both pools + assertEq(poolIds[0], PRIMARY_POOL_ID); + assertEq(poolIds[1], SECONDARY_POOL_ID); + + //claim the rewards for each pool + claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); + claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); + + //get the available pools again + poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, type(uint256).max); + + //user should not be in any pool + assertEq(poolIds[0], ZERO_POOL_ID); + assertEq(poolIds[1], ZERO_POOL_ID); + } + + function test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() public { + vm.expectRevert(INVALID_POOL_LENGTH_SELECTOR); + + rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, type(uint256).max, 0); + } + + function test_getAvailableRewardsCursorAndTotalPoolsEqual() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 2, 2); + + assertEq(poolIds.length, 0); + } + + function test_getAvailableRewardsCursorSingleResult() public { + bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, 1); + + assertEq(poolIds[0], PRIMARY_POOL_ID); + } +} + +contract DestinationRewardManagerRecipientClaimDifferentWeightsTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with uneven weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 8); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 6); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 4); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} + +contract DestinationRewardManagerRecipientClaimUnevenWeightTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + } + + function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + + uint64 oneThird = POOL_SCALAR / 3; + + //init each recipient with even weights. + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, oneThird); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 2 * oneThird + 1); + + return recipients; + } + + function test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() public { + //add a smaller amount of funds to the pool + uint256 smallDeposit = 1e8; + + //add a smaller amount of funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(smallDeposit), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (smallDeposit * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //smaller deposits will consequently have less precision and will not be able to be split as evenly, the remaining 1 will be lost due to 333...|... being paid out instead of 333...4| + assertEq(getAssetBalance(address(rewardManager)), 1); + } + + function test_allRecipientsClaimingReceiveExpectedAmount() public { + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop all the recipients and claim their expected amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //claim the individual rewards for each recipient + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //the recipient should have received a share proportional to their weight + uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + + //their should be 0 wei left over indicating a successful split + assertEq(getAssetBalance(address(rewardManager)), 0); + } +} + +contract DestinationRewardManagerNoRecipientSet is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //add funds to the pool to be split among the recipients once registered + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_claimAllRecipientsAfterRecipientsSet() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //try and claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is not registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the recipient received nothing + assertEq(getAssetBalance(recipient.addr), 0); + } + + //Set the recipients after the rewards have been paid into the pool + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //claim funds for each recipient within the pool + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //get the recipient that is claiming + Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; + + //there should be no rewards claimed as the recipient is registered + claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); + + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol new file mode 100644 index 0000000..4c79d2c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; +import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +/** + * @title DestinationRewardManagerSetupTest + * @author Michael Fletcher + * @notice This contract will test the core functionality of the DestinationRewardManager contract + */ +contract DestinationRewardManagerSetupTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_rejectsZeroLinkAddressOnConstruction() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //create a rewardManager with a zero link address + new DestinationRewardManager(address(0)); + } + + function test_eventEmittedUponFeeManagerUpdate() public { + //expect the event to be emitted + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit FeeManagerUpdated(FEE_MANAGER_2); + + //set the verifier proxy + setFeeManager(FEE_MANAGER_2, ADMIN); + } + + function test_eventEmittedUponFeePaid() public { + //create pool and add funds + createPrimaryPool(); + + //change to the feeManager who is the one who will be paying the fees + changePrank(FEE_MANAGER); + + //approve the amount being paid into the pool + ERC20Mock(getAsset(POOL_DEPOSIT_AMOUNT).assetAddress).approve(address(rewardManager), POOL_DEPOSIT_AMOUNT); + + IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); + payments[0] = IDestinationRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //event is emitted when funds are added + vm.expectEmit(); + emit FeePaid(payments, FEE_MANAGER); + + //this represents the verifier adding some funds to the pool + rewardManager.onFeePaid(payments, FEE_MANAGER); + } + + function test_setFeeManagerZeroAddress() public { + //should revert if the contract is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the verifier proxy + setFeeManager(address(0), ADMIN); + } + + function test_addFeeManagerZeroAddress() public { + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + rewardManager.addFeeManager(address(0)); + } + + function test_addFeeManagerExistingAddress() public { + address dummyAddress = address(998); + rewardManager.addFeeManager(dummyAddress); + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + rewardManager.addFeeManager(dummyAddress); + } + + function test_removeFeeManagerNonExistentAddress() public { + address dummyAddress = address(991); + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + rewardManager.removeFeeManager(dummyAddress); + } + + function test_addRemoveFeeManager() public { + address dummyAddress1 = address(1); + address dummyAddress2 = address(2); + rewardManager.addFeeManager(dummyAddress1); + rewardManager.addFeeManager(dummyAddress2); + assertEq(rewardManager.s_feeManagerAddressList(dummyAddress1), dummyAddress1); + assertEq(rewardManager.s_feeManagerAddressList(dummyAddress2), dummyAddress2); + rewardManager.removeFeeManager(dummyAddress1); + assertEq(rewardManager.s_feeManagerAddressList(dummyAddress1), address(0)); + assertEq(rewardManager.s_feeManagerAddressList(dummyAddress2), dummyAddress2); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol new file mode 100644 index 0000000..4aa3c86 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +/** + * @title DestinationRewardManagerPayRecipientsTest + * @author Michael Fletcher + * @notice This contract will test the payRecipients functionality of the RewardManager contract + */ +contract DestinationRewardManagerPayRecipientsTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_payAllRecipients() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySingleRecipient() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received 1/4 of the deposit amount + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + assertEq(getAssetBalance(recipient), expectedRecipientAmount); + } + + function test_payRecipientWithInvalidPool() public { + //get the first individual recipient + address recipient = getPrimaryRecipientAddresses()[0]; + + //get a single recipient as an array + address[] memory recipients = new address[](1); + recipients[0] = recipient; + + //pay a single recipient + payRecipients(SECONDARY_POOL_ID, recipients, ADMIN); + + //the recipient should have received nothing + assertEq(getAssetBalance(recipient), 0); + } + + function test_payRecipientsEmptyRecipientList() public { + //get a single recipient + address[] memory recipients = new address[](0); + + //pay a single recipient + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //rewardManager should have the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_payAllRecipientsWithAdditionalUnregisteredRecipient() public { + //load all the recipients and add an additional one who is not in the pool + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = DEFAULT_RECIPIENT_5; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + + //the unregistered recipient should receive nothing + assertEq(getAssetBalance(DEFAULT_RECIPIENT_5), 0); + } + + function test_payAllRecipientsWithAdditionalInvalidRecipient() public { + //load all the recipients and add an additional one which is invalid, that should receive nothing + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + recipients[recipients.length - 1] = INVALID_ADDRESS; + + //pay the recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_paySubsetOfRecipientsInPool() public { + //load a subset of the recipients into an array + address[] memory recipients = new address[](getPrimaryRecipientAddresses().length - 1); + for (uint256 i = 0; i < recipients.length; i++) { + recipients[i] = getPrimaryRecipientAddresses()[i]; + } + + //pay the subset of recipients + payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //each recipient should receive 1/4 of the pool except the last + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each subset of recipients received the correct amount + for (uint256 i = 0; i < recipients.length - 1; i++) { + assertEq(getAssetBalance(recipients[i]), expectedRecipientAmount); + } + + //check the pool has the remaining balance + assertEq( + getAssetBalance(address(rewardManager)), + POOL_DEPOSIT_AMOUNT - expectedRecipientAmount * recipients.length + ); + } + + function test_payAllRecipientsFromNonAdminUser() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), FEE_MANAGER); + } + + function test_payAllRecipientsFromRecipientInPool() public { + //pay all the recipients in the pool + payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), DEFAULT_RECIPIENT_1); + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //check each recipient received the correct amount + for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { + assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); + } + } + + function test_payRecipientsWithInvalidPoolId() public { + //pay all the recipients in the pool + payRecipients(INVALID_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); + + //pool should still contain the full balance + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_addFundsToPoolAsOwner() public { + //add funds to the pool + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_addFundsToPoolAsNonOwnerOrFeeManager() public { + //should revert if the caller isn't an admin or recipient within the pool + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); + payments[0] = IDestinationRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); + + //add funds to the pool + rewardManager.onFeePaid(payments, USER); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol new file mode 100644 index 0000000..facbaa1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title DestinationRewardManagerSetRecipientsTest + * @author Michael Fletcher + * @notice This contract will test the setRecipient functionality of the RewardManager contract + */ +contract DestinationRewardManagerSetRecipientsTest is BaseDestinationRewardManagerTest { + function setUp() public override { + //setup contracts + super.setUp(); + } + + function test_setRewardRecipients() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientsIsEmpty() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroWeight() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 25); + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, 0); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWithZeroAddress() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = getPrimaryRecipients(); + + //override the first recipient with a zero address + recipients[0].addr = address(0); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientWeights() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 25); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, 25); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, 25); + + //should revert if the recipients array is empty + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setSingleRewardRecipient() public { + //array of recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); + + //init each recipient with even weights + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR); + + //set the recipients with a recipient with a weight of 100% + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_setRewardRecipientTwice() public { + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //should revert if recipients for this pool have already been set + vm.expectRevert(INVALID_POOL_ID_ERROR_SELECTOR); + + //set the recipients again + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() public { + //should revert if the sender is not the owner or proxy + vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), USER); + } + + function test_setRewardRecipientFromManagerAddress() public { + //update the proxy address + setFeeManager(FEE_MANAGER_2, ADMIN); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER_2); + } + + function test_eventIsEmittedUponSetRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + } + + function test_setRecipientContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //set the recipients + setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol new file mode 100644 index 0000000..226be8e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; +import {Common} from "../../../libraries/Common.sol"; + +/** + * @title DestinationRewardManagerUpdateRewardRecipientsTest + * @author Michael Fletcher + * @notice This contract will test the updateRecipient functionality of the RewardManager contract + */ +contract DestinationRewardManagerUpdateRewardRecipientsTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function test_onlyAdminCanUpdateRecipients() public { + //should revert if the caller is not the admin + vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); + } + + function test_updateAllRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } + + function test_updatePartialRecipientsWithSameAddressAndWeight() public { + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //get a subset of the recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have half remaining funds + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + } + + function test_updateRecipientWithNewZeroAddress() public { + //create a new array to hold the existing recipients plus a new zero address + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 1); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add a new address to the primary recipients + recipients[recipients.length - 1] = Common.AddressAndWeight(address(0), 0); + + //should revert if the recipient is a zero address + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with invalid address + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsContainsDuplicateRecipients() public { + //create a new array to hold the existing recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); + + //add all the existing recipients + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i] = getPrimaryRecipients()[i]; + } + //add all the existing recipients again + for (uint256 i; i < getPrimaryRecipients().length; i++) { + recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; + } + + //should revert as the list contains a duplicate + vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); + + //update the recipients with the duplicate addresses + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 4); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, ONE_PERCENT * 25); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, ONE_PERCENT * 25); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, ONE_PERCENT * 25); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, ONE_PERCENT * 25); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentPartialSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, FIFTY_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, FIFTY_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 5); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 2); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT * 2); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT * 2); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT * 2); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT * 2); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForLargerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](9); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 3); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT); + recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT); + recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT); + + //should revert as the weight does not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); + + //update the existing recipients + recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); + recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); + recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 2); + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientsToDifferentSetWithInvalidWeights() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //copy the recipient and set the weight to 0 which implies the recipient is being replaced + recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); + } + + //add the new recipients individually + recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); + recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); + + //should revert as the weight will not equal 100% + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsToSubset() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 0); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 0); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 5); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithUnderWeightSet() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updatePartialRecipientsWithExcessiveWeight() public { + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR); + + //should revert as the new weights exceed the previous weights being replaced + vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + } + + function test_updateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 3); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have no funds remaining + assertEq(getAssetBalance(address(rewardManager)), 0); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_3), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 3) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_4), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 5) / POOL_SCALAR + expectedRecipientAmount + ); + } + + function test_partialUpdateRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set with their new weights + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //loop each user and claim the rewards + for (uint256 i; i < recipients.length; i++) { + //claim the rewards for this recipient + claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); + } + + //manually check the balance of each recipient + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_1), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(DEFAULT_RECIPIENT_2), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + + //the reward manager should have half the funds remaining + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + } + + function test_eventIsEmittedUponUpdateRecipients() public { + //expect an emit + vm.expectEmit(); + + //emit the event that is expected to be emitted + emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); + + //expected recipient amount is 1/4 of the pool deposit + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //updating a recipient should force the funds to be paid out + updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < getPrimaryRecipients().length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); + } + } +} + +contract DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest is BaseDestinationRewardManagerTest { + uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; + + function setUp() public override { + //setup contracts + super.setUp(); + + //create a single pool for these tests + createPrimaryPool(); + createSecondaryPool(); + + //add funds to the pool to be split among the recipients + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + } + + function getSecondaryRecipients() public override returns (Common.AddressAndWeight[] memory) { + //for testing purposes, the primary and secondary pool to contain the same recipients + return getPrimaryRecipients(); + } + + function test_updatePrimaryRecipientWeights() public { + //expected recipient amount is 1/4 of the pool deposit for original recipients + uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; + + //create a list of containing recipients from the primary configured set, and new recipients + Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); + recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT * 4); + recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); + recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); + recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); + + //updating a recipient should force the funds to be paid out for the primary recipients + updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); + + //check each recipient received the correct amount + for (uint256 i; i < recipients.length; i++) { + //check the balance matches the ratio the recipient should have received + assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); + } + + //the reward manager should still have the funds for the secondary pool + assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); + + //add more funds to the pool to check new distribution + addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); + + //claim the rewards for the updated recipients manually + claimRewards(PRIMARY_POOL_ARRAY, recipients[0].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[1].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[2].addr); + claimRewards(PRIMARY_POOL_ARRAY, recipients[3].addr); + + //check the balance matches the ratio the recipient who were updated should have received + assertEq( + getAssetBalance(recipients[0].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[1].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[2].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + assertEq( + getAssetBalance(recipients[3].addr), + (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol new file mode 100644 index 0000000..ec3b3a0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {DestinationVerifierProxy} from "../../DestinationVerifierProxy.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IDestinationVerifier} from "../../interfaces/IDestinationVerifier.sol"; +import {IDestinationVerifierProxy} from "../../interfaces/IDestinationVerifierProxy.sol"; +import {DestinationVerifier} from "../../DestinationVerifier.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {DestinationFeeManager} from "../../DestinationFeeManager.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; +import {DestinationRewardManager} from "../../DestinationRewardManager.sol"; +import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; + +contract BaseTest is Test { + uint64 internal constant POOL_SCALAR = 1e18; + uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; + uint256 internal constant MAX_ORACLES = 31; + address internal constant ADMIN = address(1); + address internal constant USER = address(2); + + address internal constant MOCK_VERIFIER_ADDRESS = address(100); + address internal constant ACCESS_CONTROLLER_ADDRESS = address(300); + + uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; + uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; + + uint64 internal constant VERIFIER_VERSION = 1; + + uint8 internal constant FAULT_TOLERANCE = 10; + + DestinationVerifierProxy internal s_verifierProxy; + DestinationVerifier internal s_verifier; + DestinationFeeManager internal feeManager; + DestinationRewardManager internal rewardManager; + ERC20Mock internal link; + WERC20Mock internal native; + + struct Signer { + uint256 mockPrivateKey; + address signerAddress; + } + + Signer[MAX_ORACLES] internal s_signers; + bytes32[] internal s_offchaintransmitters; + bool private s_baseTestInitialized; + + struct V3Report { + // The feed ID the report has data for + bytes32 feedId; + // The time the median value was observed on + uint32 observationsTimestamp; + // The timestamp the report is valid from + uint32 validFromTimestamp; + // The link fee + uint192 linkFee; + // The native fee + uint192 nativeFee; + // The expiry of the report + uint32 expiresAt; + // The median value agreed in an OCR round + int192 benchmarkPrice; + // The best bid value agreed in an OCR round + int192 bid; + // The best ask value agreed in an OCR round + int192 ask; + } + + bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; + bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; + + bytes32 internal constant INVALID_FEED = keccak256("INVALID"); + uint32 internal constant OBSERVATIONS_TIMESTAMP = 1000; + uint64 internal constant BLOCKNUMBER_LOWER_BOUND = 1000; + uint64 internal constant BLOCKNUMBER_UPPER_BOUND = BLOCKNUMBER_LOWER_BOUND + 5; + int192 internal constant MEDIAN = 1 ether; + int192 internal constant BID = 500000000 gwei; + int192 internal constant ASK = 2 ether; + + //version 0 feeds + bytes32 internal constant FEED_ID = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_2 = (keccak256("LINK-USD") & V_MASK) | V1_BITMASK; + bytes32 internal constant FEED_ID_3 = (keccak256("BTC-USD") & V_MASK) | V1_BITMASK; + + //version 3 feeds + bytes32 internal constant FEED_ID_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; + + function _encodeReport(V3Report memory report) internal pure returns (bytes memory) { + return + abi.encode( + report.feedId, + report.observationsTimestamp, + report.validFromTimestamp, + report.nativeFee, + report.linkFee, + report.expiresAt, + report.benchmarkPrice, + report.bid, + report.ask + ); + } + + function _generateSignerSignatures( + bytes memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) { + bytes32[] memory rs = new bytes32[](signers.length); + bytes32[] memory ss = new bytes32[](signers.length); + bytes memory vs = new bytes(signers.length); + + bytes32 hash = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + for (uint256 i = 0; i < signers.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].mockPrivateKey, hash); + rs[i] = r; + ss[i] = s; + vs[i] = bytes1(v - 27); + } + return (rs, ss, bytes32(vs)); + } + + function _generateV3EncodedBlob( + V3Report memory report, + bytes32[3] memory reportContext, + Signer[] memory signers + ) internal pure returns (bytes memory) { + bytes memory reportBytes = _encodeReport(report); + (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( + reportBytes, + reportContext, + signers + ); + return abi.encode(reportContext, reportBytes, rs, ss, rawVs); + } + + function _verify(bytes memory payload, address feeAddress, uint256 wrappedNativeValue, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } + + function _generateV3Report() internal view returns (V3Report memory) { + return + V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function _verifyBulk( + bytes[] memory payload, + address feeAddress, + uint256 wrappedNativeValue, + address sender + ) internal { + address originalAddr = msg.sender; + changePrank(sender); + + s_verifierProxy.verifyBulk{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } + + function _approveLink(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + link.approve(spender, quantity); + changePrank(originalAddr); + } + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + vm.startPrank(ADMIN); + + s_verifierProxy = new DestinationVerifierProxy(); + s_verifier = new DestinationVerifier(address(s_verifierProxy)); + s_verifierProxy.setVerifier(address(s_verifier)); + + // setting up FeeManager and RewardManager + native = new WERC20Mock(); + link = new ERC20Mock("LINK", "LINK", ADMIN, 0); + rewardManager = new DestinationRewardManager(address(link)); + feeManager = new DestinationFeeManager(address(link), address(native), address(s_verifier), address(rewardManager)); + + for (uint256 i; i < MAX_ORACLES; i++) { + uint256 mockPK = i + 1; + s_signers[i].mockPrivateKey = mockPK; + s_signers[i].signerAddress = vm.addr(mockPK); + } + } + + function _getSigners(uint256 numSigners) internal view returns (Signer[] memory) { + Signer[] memory signers = new Signer[](numSigners); + for (uint256 i; i < numSigners; i++) { + signers[i] = s_signers[i]; + } + return signers; + } + + function _getSignerAddresses(Signer[] memory signers) internal pure returns (address[] memory) { + address[] memory signerAddrs = new address[](signers.length); + for (uint256 i = 0; i < signerAddrs.length; i++) { + signerAddrs[i] = signers[i].signerAddress; + } + return signerAddrs; + } + + function _signerAddressAndDonConfigKey(address signer, bytes24 donConfigId) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(signer, donConfigId)); + } + + function _donConfigIdFromConfigData(address[] memory signers, uint8 f) internal pure returns (bytes24) { + Common._quickSort(signers, 0, int256(signers.length - 1)); + bytes24 donConfigId = bytes24(keccak256(abi.encodePacked(signers, f))); + return donConfigId; + } + + function assertReportsEqual(bytes memory response, V3Report memory testReport) public pure { + ( + bytes32 feedId, + uint32 observationsTimestamp, + uint32 validFromTimestamp, + uint192 nativeFee, + uint192 linkFee, + uint32 expiresAt, + int192 benchmarkPrice, + int192 bid, + int192 ask + ) = abi.decode(response, (bytes32, uint32, uint32, uint192, uint192, uint32, int192, int192, int192)); + assertEq(feedId, testReport.feedId); + assertEq(observationsTimestamp, testReport.observationsTimestamp); + assertEq(validFromTimestamp, testReport.validFromTimestamp); + assertEq(expiresAt, testReport.expiresAt); + assertEq(benchmarkPrice, testReport.benchmarkPrice); + assertEq(bid, testReport.bid); + assertEq(ask, testReport.ask); + assertEq(linkFee, testReport.linkFee); + assertEq(nativeFee, testReport.nativeFee); + } + + function _approveNative(address spender, uint256 quantity, address sender) internal { + address originalAddr = msg.sender; + changePrank(sender); + + native.approve(spender, quantity); + changePrank(originalAddr); + } +} + +contract VerifierWithFeeManager is BaseTest { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_verifierProxy.setVerifier(address(s_verifier)); + s_verifier.setFeeManager(address(feeManager)); + rewardManager.addFeeManager(address(feeManager)); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + } +} + +contract MultipleVerifierWithMultipleFeeManagers is BaseTest { + uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; + uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; + + DestinationVerifier internal s_verifier2; + DestinationVerifier internal s_verifier3; + + DestinationVerifierProxy internal s_verifierProxy2; + DestinationVerifierProxy internal s_verifierProxy3; + + DestinationFeeManager internal feeManager2; + + function setUp() public virtual override { + /* + - Sets up 3 verifiers + - Sets up 2 Fee managers, wire the fee managers and verifiers + - Sets up a Reward Manager which can be used by both fee managers + */ + BaseTest.setUp(); + + s_verifierProxy2 = new DestinationVerifierProxy(); + s_verifierProxy3 = new DestinationVerifierProxy(); + + s_verifier2 = new DestinationVerifier(address(s_verifierProxy2)); + s_verifier3 = new DestinationVerifier(address(s_verifierProxy3)); + + s_verifierProxy2.setVerifier(address(s_verifier2)); + s_verifierProxy3.setVerifier(address(s_verifier3)); + + feeManager2 = new DestinationFeeManager( + address(link), + address(native), + address(s_verifier), + address(rewardManager) + ); + + s_verifier.setFeeManager(address(feeManager)); + s_verifier2.setFeeManager(address(feeManager)); + s_verifier3.setFeeManager(address(feeManager2)); + + // this is already set in the base contract + // feeManager.addVerifier(address(s_verifier)); + feeManager.addVerifier(address(s_verifier2)); + feeManager2.addVerifier(address(s_verifier3)); + + rewardManager.addFeeManager(address(feeManager)); + rewardManager.addFeeManager(address(feeManager2)); + + //mint some tokens to the user + link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); + native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); + vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); + + //mint some link tokens to the feeManager pool + link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol new file mode 100644 index 0000000..d4772ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {IDestinationFeeManager} from "../../../v0.4.0/interfaces/IDestinationFeeManager.sol"; +import {IDestinationRewardManager} from "../../../v0.4.0/interfaces/IDestinationRewardManager.sol"; +import {IDestinationVerifierProxy} from "../../../v0.4.0/interfaces/IDestinationVerifierProxy.sol"; +import {Common} from "../../../libraries/Common.sol"; +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; + +/* +This test checks the interfaces of destination verifier matches the expectations. +The code here comes from this example: + +https://docs.chain.link/chainlink-automation/guides/streams-lookup + +*/ + +// Custom interfaces for IVerifierProxy and IFeeManager +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed. + * correctly by routing to the correct verifier, and bills the user if applicable. + * @param payload The encoded data to be verified, including the signed + * report. + * @param parameterPayload Fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address. + * @return verifierResponse The encoded report from the verifier. + */ + function verify( + bytes calldata payload, + bytes calldata parameterPayload + ) external payable returns (bytes memory verifierResponse); + + function s_feeManager() external view returns (IDestinationFeeManager); +} + +interface IFeeManager { + /** + * @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers. + * This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses. + * @param subscriber The address attempting to verify the report. A discount is applied if this address + * is recognized as a subscriber. + * @param unverifiedReport The report data awaiting verification. The content of this report is used to + * determine the base fee and reward, before considering subscriber discounts. + * @param quoteAddress The payment token address used for quoting fees and rewards. + * @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable. + * @return reward The reward allocated to the caller for successfully verifying the report. + * @return totalDiscount The total discount amount deducted from the fee for subscribers. + */ + function getFeeAndReward( + address subscriber, + bytes memory unverifiedReport, + address quoteAddress + ) external returns (Common.Asset memory, Common.Asset memory, uint256); + + function i_linkAddress() external view returns (address); + + function i_nativeAddress() external view returns (address); + + function i_rewardManager() external view returns (address); +} + +//Tests +// https://docs.chain.link/chainlink-automation/guides/streams-lookup +contract VerifierInterfacesTest is VerifierWithFeeManager { + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + + IVerifierProxy public verifier; + V3Report internal s_testReport; + + address public FEE_ADDRESS; + string public constant DATASTREAMS_FEEDLABEL = "feedIDs"; + string public constant DATASTREAMS_QUERYLABEL = "timestamp"; + int192 public last_retrieved_price; + bytes internal signedReport; + bytes32[3] internal s_reportContext; + uint8 MINIMAL_FAULT_TOLERANCE = 2; + + function setUp() public virtual override { + VerifierWithFeeManager.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + Signer[] memory signers = _getSigners(MAX_ORACLES); + + s_testReport = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); + weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); + s_verifier.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights); + signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); + + verifier = IVerifierProxy(address(s_verifierProxy)); + } + + function test_DestinationContractInterfaces() public { + bytes memory unverifiedReport = signedReport; + + (, bytes memory reportData) = abi.decode(unverifiedReport, (bytes32[3], bytes)); + + // Report verification fees + IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager())); + IDestinationRewardManager rewardManager = IDestinationRewardManager(address(feeManager.i_rewardManager())); + + address feeTokenAddress = feeManager.i_linkAddress(); + (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(address(this), reportData, feeTokenAddress); + + // Approve rewardManager to spend this contract's balance in fees + _approveLink(address(rewardManager), fee.amount, USER); + _verify(unverifiedReport, address(feeTokenAddress), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - fee.amount); + assertEq(link.balanceOf(address(rewardManager)), fee.amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol new file mode 100644 index 0000000..2851057 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationFeeManager} from "../../../v0.4.0/DestinationFeeManager.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +contract DestinationVerifierProxyInitializeVerifierTest is BaseTest { + function test_setVerifierCalledByNoOwner() public { + address STRANGER = address(999); + changePrank(STRANGER); + vm.expectRevert(bytes("Only callable by owner")); + s_verifierProxy.setVerifier(address(s_verifier)); + } + + function test_setVerifierWhichDoesntHonourInterface() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifierProxy.VerifierInvalid.selector, address(rewardManager))); + s_verifierProxy.setVerifier(address(rewardManager)); + } + + function test_setVerifierOk() public { + s_verifierProxy.setVerifier(address(s_verifier)); + assertEq(s_verifierProxy.s_feeManager(), s_verifier.s_feeManager()); + assertEq(s_verifierProxy.s_accessController(), s_verifier.s_accessController()); + } + + function test_correctlySetsTheOwner() public { + DestinationVerifierProxy proxy = new DestinationVerifierProxy(); + assertEq(proxy.owner(), ADMIN); + } + + function test_correctlySetsVersion() public view { + string memory version = s_verifierProxy.typeAndVersion(); + assertEq(version, "DestinationVerifierProxy 0.4.0"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol new file mode 100644 index 0000000..6309efc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract DestinationVerifierSetConfigTest is BaseTest { + bytes32[3] internal s_reportContext; + V3Report internal s_testReport; + + function setUp() public virtual override { + BaseTest.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + } + + function test_removeLatestConfigWhenNoConfigShouldFail() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); + s_verifier.removeLatestConfig(); + } + + function test_removeLatestConfig() public { + /* + This test sets two Configs: Config A and Config B. + - it removes and readds config B multiple times while trying Config A verifications + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); + signersA[0] = signers[0]; + signersA[1] = signers[1]; + signersA[2] = signers[2]; + signersA[3] = signers[3]; + signersA[4] = signers[4]; + signersA[5] = signers[5]; + signersA[6] = signers[6]; + + // ConfigA + address[] memory signersAddrA = _getSignerAddresses(signersA); + s_verifier.setConfig(signersAddrA, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 10); + V3Report memory s_testReportA = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + vm.warp(block.timestamp + 100); + // Config B + BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[0] = signers[8]; + signersB[1] = signers[9]; + signersB[2] = signers[10]; + signersB[3] = signers[11]; + signersB[4] = signers[12]; + signersB[5] = signers[13]; + signersB[6] = signers[14]; + address[] memory signersAddrsB = _getSignerAddresses(signersB); + s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory s_testReportB = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); + reportSignersA[0] = signers[0]; + reportSignersA[1] = signers[1]; + reportSignersA[2] = signers[2]; + + BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); + reportSignersB[0] = signers[8]; + reportSignersB[1] = signers[9]; + reportSignersB[2] = signers[10]; + + bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); + bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); + + // verifying should work + s_verifierProxy.verify(signedReportA, abi.encode(native)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + s_verifier.removeLatestConfig(); + + // this should remove the latest config, so ConfigA should be able to verify reports still + s_verifierProxy.verify(signedReportA, abi.encode(native)); + // this report cannot be verified any longer because ConfigB is not there + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + // since ConfigB is removed we should be able to set it again with no errors + s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + // we should be able to remove ConfigB + s_verifier.removeLatestConfig(); + // removing configA + s_verifier.removeLatestConfig(); + + // verifigny should fail + // verifying should work + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportA, abi.encode(native)); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + + // removing again should fail. no other configs exist + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); + s_verifier.removeLatestConfig(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol new file mode 100644 index 0000000..d40b674 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; + +contract DestinationVerifierSetAccessControllerTest is BaseTest { + event AccessControllerSet(address oldAccessController, address newAccessController); + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + + changePrank(USER); + s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); + } + + function test_successfullySetsNewAccessController() public { + s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); + address ac = s_verifier.s_accessController(); + assertEq(ac, ACCESS_CONTROLLER_ADDRESS); + } + + function test_successfullySetsNewAccessControllerIsEmpty() public { + s_verifier.setAccessController(address(0)); + address ac = s_verifier.s_accessController(); + assertEq(ac, address(0)); + } + + function test_emitsTheCorrectEvent() public { + vm.expectEmit(true, false, false, false); + emit AccessControllerSet(address(0), ACCESS_CONTROLLER_ADDRESS); + s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol new file mode 100644 index 0000000..4f96e49 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract DestinationVerifierSetConfigTest is BaseTest { + function setUp() public virtual override { + BaseTest.setUp(); + } + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + Signer[] memory signers = _getSigners(MAX_ORACLES); + changePrank(USER); + s_verifier.setConfig(_getSignerAddresses(signers), FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfSetWithTooManySigners() public { + address[] memory signers = new address[](MAX_ORACLES + 1); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ExcessSigners.selector, signers.length, MAX_ORACLES)); + s_verifier.setConfig(signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfFaultToleranceIsZero() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.FaultToleranceMustBePositive.selector)); + Signer[] memory signers = _getSigners(MAX_ORACLES); + s_verifier.setConfig(_getSignerAddresses(signers), 0, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfNotEnoughSigners() public { + address[] memory signers = new address[](2); + signers[0] = address(1000); + signers[1] = address(1001); + + vm.expectRevert( + abi.encodeWithSelector(DestinationVerifier.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) + ); + s_verifier.setConfig(signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfDuplicateSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = signerAddrs[1]; + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.NonUniqueSignatures.selector)); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_revertsIfSignerContainsZeroAddress() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + signerAddrs[0] = address(0); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ZeroAddress.selector)); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_donConfigIdIsSameForSignersInDifferentOrder() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + + bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + + address temp = signerAddrs[0]; + signerAddrs[0] = signerAddrs[1]; + signerAddrs[1] = temp; + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigAlreadyExists.selector, expectedDonConfigId)); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } + + function test_NoDonConfigAlreadyExists() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + vm.warp(block.timestamp + 1); + + // testing adding same set of Signers but different FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); + + vm.warp(block.timestamp + 1); + + // testing adding a different set of Signers with same FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert + address[] memory signerAddrsMinusOne = new address[](signerAddrs.length - 1); + for (uint256 i = 0; i < signerAddrs.length - 1; i++) { + signerAddrsMinusOne[i] = signerAddrs[i]; + } + s_verifier.setConfig(signerAddrsMinusOne, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); + } + + function test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + + bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigAlreadyExists.selector, expectedDonConfigId)); + + // Same call to setConfig with different addressAndWeights do not entail a new DonConfigID + // Resulting in a DonConfigAlreadyExists error + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); + weights[0] = Common.AddressAndWeight(signers[0].signerAddress, 1); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + } + + function test_setConfigActiveUnknownDonConfigId() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); + s_verifier.setConfigActive(3, true); + } + + function test_setConfigWithActivationTime() public { + // simple case setting a config with specific activation time + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 activationTime = 10; + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + activationTime + ); + } + + function test_setConfigWithActivationTimeNoFutureTimeShouldFail() public { + // calling setConfigWithActivationTime with a future timestamp should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 activationTime = uint32(block.timestamp) + 100; + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + activationTime + ); + } + + function test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() public { + // setting a config older than the latest current config should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + uint32 oldActivationTime = uint32(block.timestamp) - 1; + // sets a config with timestamp = block.timestamp + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // setting a config with ealier timestamp retuls in failure + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfigWithActivationTime( + signerAddrs, + FAULT_TOLERANCE - 1, + new Common.AddressAndWeight[](0), + oldActivationTime + ); + } + + function test_setConfigWithActivationTimeTheSameAsLatestConfigShouldFail() public { + // setting a config older than the latest current config should fail + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + // sets a config with timestamp = block.timestamp + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // setting a config with ealier timestamp retuls in failure + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol new file mode 100644 index 0000000..fdf75d6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; + +contract VerifierSetAccessControllerTest is BaseTest { + event FeeManagerSet(address oldFeeManager, address newFeeManager); + + function test_revertsIfCalledByNonOwner() public { + vm.expectRevert("Only callable by owner"); + changePrank(USER); + s_verifier.setFeeManager(address(feeManager)); + } + + function test_successfullySetsNewFeeManager() public { + vm.expectEmit(true, false, false, false); + emit FeeManagerSet(address(0), ACCESS_CONTROLLER_ADDRESS); + s_verifier.setFeeManager(address(feeManager)); + address ac = s_verifier.s_feeManager(); + assertEq(ac, address(feeManager)); + } + + function test_setFeeManagerWhichDoesntHonourInterface() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.FeeManagerInvalid.selector)); + s_verifier.setFeeManager(address(rewardManager)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol new file mode 100644 index 0000000..476acbf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {IDestinationVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifier.sol"; +import {IDestinationVerifierProxyVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol"; + +contract DestinationVerifierConstructorTest is BaseTest { + bytes32[3] internal s_reportContext; + + function test_revertsIfInitializedWithEmptyVerifierProxy() public { + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ZeroAddress.selector)); + new DestinationVerifier(address(0)); + } + + function test_typeAndVersion() public { + DestinationVerifier v = new DestinationVerifier(address(s_verifierProxy)); + assertEq(v.owner(), ADMIN); + string memory typeAndVersion = s_verifier.typeAndVersion(); + assertEq(typeAndVersion, "DestinationVerifier 0.4.0"); + } + + function test_falseIfIsNotCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(bytes4("abcd")); + assertEq(isInterface, false); + } + + function test_trueIfIsCorrectInterface() public view { + bool isInterface = s_verifier.supportsInterface(type(IDestinationVerifier).interfaceId) && + s_verifier.supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId); + assertEq(isInterface, true); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol new file mode 100644 index 0000000..574e169 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierBillingTests is VerifierWithFeeManager { + bytes32[3] internal s_reportContext; + V3Report internal s_testReportThree; + + function setUp() public virtual override { + VerifierWithFeeManager.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReportThree = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function test_verifyWithLinkV3Report() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); + bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(signedReport, address(link), 0, USER); + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + // internal state checks + assertEq(feeManager.s_linkDeficit(expectedDonConfigId), 0); + assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigId), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNativeERC20() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); + weights[0] = Common.AddressAndWeight(signerAddrs[0], ONE_PERCENT * 100); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + bytes memory signedReport = _generateV3EncodedBlob( + s_testReportThree, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); + _verify(signedReport, address(native), 0, USER); + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + } + + function test_verifyWithNativeUnwrapped() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + bytes memory signedReport = _generateV3EncodedBlob( + s_testReportThree, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithNativeUnwrappedReturnsChange() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + bytes memory signedReport = _generateV3EncodedBlob( + s_testReportThree, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE * 2, USER); + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); + assertEq(address(feeManager).balance, 0); + } +} + +contract DestinationVerifierBulkVerifyBillingReport is VerifierWithFeeManager { + uint256 internal constant NUMBERS_OF_REPORTS = 5; + + bytes32[3] internal s_reportContext; + + function setUp() public virtual override { + VerifierWithFeeManager.setUp(); + // setting a DonConfig we can reuse in the rest of tests + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + } + + function test_verifyWithBulkLink() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS, USER); + + _verifyBulk(signedReports, address(link), 0, USER); + + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNative() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + _verifyBulk(signedReports, address(native), 0, USER); + assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + } + + function test_verifyWithBulkNativeUnwrapped() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), 200 * DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); + assertEq(address(feeManager).balance, 0); + } + + function test_verifyWithBulkNativeUnwrappedReturnsChange() public { + bytes memory signedReport = _generateV3EncodedBlob( + _generateV3Report(), + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); + for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { + signedReports[i] = signedReport; + } + + _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * (NUMBERS_OF_REPORTS * 2), USER); + + assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); + assertEq(address(feeManager).balance, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol new file mode 100644 index 0000000..8ca954b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierBillingTests is VerifierWithFeeManager { + uint8 MINIMAL_FAULT_TOLERANCE = 2; + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); + address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); + address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); + address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); + address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); + address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); + + function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.payRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + bytes32[3] internal s_reportContext; + V3Report internal s_testReport; + + function setUp() public virtual override { + VerifierWithFeeManager.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReport = generateReportAtTimestamp(block.timestamp); + } + + function generateReportAtTimestamp(uint256 timestamp) public pure returns (V3Report memory) { + return + V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + // ask michael about this expires at, is it usually set at what blocks + expiresAt: uint32(timestamp) + 500, + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function getRecipientAndWeightsGroup2() public pure returns (Common.AddressAndWeight[] memory, address[] memory) { + address[] memory recipients = new address[](4); + recipients[0] = DEFAULT_RECIPIENT_4; + recipients[1] = DEFAULT_RECIPIENT_5; + recipients[2] = DEFAULT_RECIPIENT_6; + recipients[3] = DEFAULT_RECIPIENT_7; + + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](4); + //init each recipient with even weights. 2500 = 25% of pool + weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); + weights[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); + weights[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); + weights[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); + return (weights, recipients); + } + + function getRecipientAndWeightsGroup1() public pure returns (Common.AddressAndWeight[] memory, address[] memory) { + address[] memory recipients = new address[](4); + recipients[0] = DEFAULT_RECIPIENT_1; + recipients[1] = DEFAULT_RECIPIENT_2; + recipients[2] = DEFAULT_RECIPIENT_3; + recipients[3] = DEFAULT_RECIPIENT_4; + + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](4); + //init each recipient with even weights. 2500 = 25% of pool + weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); + weights[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); + weights[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); + weights[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); + return (weights, recipients); + } + + function test_rewardsAreDistributedAccordingToWeights() public { + /* + Simple test verifying that rewards are distributed according to address and weights + associated to the DonConfig used to verify the report + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); + weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); + bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(signedReport, address(link), 0, USER); + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + // internal state checks + assertEq(feeManager.s_linkDeficit(expectedDonConfigId), 0); + assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigId), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + // check the recipients are paid according to weights + address[] memory recipients = new address[](1); + recipients[0] = DEFAULT_RECIPIENT_1; + payRecipients(expectedDonConfigId, recipients, ADMIN); + assertEq(link.balanceOf(recipients[0]), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), 0); + } + + function test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() public { + /* + Rewards are distributed according to AddressAndWeight's + associated to the DonConfig used to verify the report: + - multiple recipients + - multiple verifications + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + (Common.AddressAndWeight[] memory weights, address[] memory recipients) = getRecipientAndWeightsGroup1(); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + + bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); + bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + + uint256 number_of_reports_verified = 10; + + for (uint256 i = 0; i < number_of_reports_verified; i++) { + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(signedReport, address(link), 0, USER); + } + + uint256 expected_pool_amount = DEFAULT_REPORT_LINK_FEE * number_of_reports_verified; + + //each recipient should receive 1/4 of the pool + uint256 expectedRecipientAmount = expected_pool_amount / 4; + + payRecipients(expectedDonConfigId, recipients, ADMIN); + for (uint256 i = 0; i < recipients.length; i++) { + // checking each recipient got rewards as set by the weights + assertEq(link.balanceOf(recipients[i]), expectedRecipientAmount); + } + // checking nothing left in reward manager + assertEq(link.balanceOf(address(rewardManager)), 0); + } + + function test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() public { + /* + Verifies that reports verified with historical give rewards according to the verifying config AddressAndWeight. + - Sets two Configs: ConfigA and ConfigB, These two Configs have different Recipient and Weights + - Verifies a couple reports with each config + - Pays recipients + - Asserts expected rewards for each recipient + */ + + Signer[] memory signers = _getSigners(10); + address[] memory signerAddrs = _getSignerAddresses(signers); + + (Common.AddressAndWeight[] memory weights, address[] memory recipients) = getRecipientAndWeightsGroup1(); + + // Create ConfigA + s_verifier.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights); + vm.warp(block.timestamp + 100); + + V3Report memory testReportAtT1 = generateReportAtTimestamp(block.timestamp); + bytes memory signedReportT1 = _generateV3EncodedBlob(testReportAtT1, s_reportContext, signers); + bytes32 expectedDonConfigIdA = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE); + + uint256 number_of_reports_verified = 2; + + // advancing the blocktimestamp so we can test verifying with configs + vm.warp(block.timestamp + 100); + + Signer[] memory signers2 = _getSigners(12); + address[] memory signerAddrs2 = _getSignerAddresses(signers2); + (Common.AddressAndWeight[] memory weights2, address[] memory recipients2) = getRecipientAndWeightsGroup2(); + + // Create ConfigB + s_verifier.setConfig(signerAddrs2, MINIMAL_FAULT_TOLERANCE, weights2); + bytes32 expectedDonConfigIdB = _donConfigIdFromConfigData(signerAddrs2, MINIMAL_FAULT_TOLERANCE); + + V3Report memory testReportAtT2 = generateReportAtTimestamp(block.timestamp); + + // verifiying using ConfigA (report with Old timestamp) + for (uint256 i = 0; i < number_of_reports_verified; i++) { + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(signedReportT1, address(link), 0, USER); + } + + // verifying using ConfigB (report with new timestamp) + for (uint256 i = 0; i < number_of_reports_verified; i++) { + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(_generateV3EncodedBlob(testReportAtT2, s_reportContext, signers2), address(link), 0, USER); + } + + uint256 expected_pool_amount = DEFAULT_REPORT_LINK_FEE * number_of_reports_verified; + assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigIdA), expected_pool_amount); + assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigIdB), expected_pool_amount); + + // check the recipients are paid according to weights + payRecipients(expectedDonConfigIdA, recipients, ADMIN); + + for (uint256 i = 0; i < recipients.length; i++) { + // //each recipient should receive 1/4 of the pool + assertEq(link.balanceOf(recipients[i]), expected_pool_amount / 4); + } + + payRecipients(expectedDonConfigIdB, recipients2, ADMIN); + + for (uint256 i = 1; i < recipients2.length; i++) { + // //each recipient should receive 1/4 of the pool + assertEq(link.balanceOf(recipients2[i]), expected_pool_amount / 4); + } + + // this recipient was part of the two config weights + assertEq(link.balanceOf(recipients2[0]), (expected_pool_amount / 4) * 2); + assertEq(link.balanceOf(address(rewardManager)), 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol new file mode 100644 index 0000000..6a90cbf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {MultipleVerifierWithMultipleFeeManagers} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract MultiVerifierBillingTests is MultipleVerifierWithMultipleFeeManagers { + uint8 MINIMAL_FAULT_TOLERANCE = 2; + address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); + address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); + address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); + address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); + address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); + address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); + address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); + + bytes32[3] internal s_reportContext; + V3Report internal s_testReport; + + function setUp() public virtual override { + MultipleVerifierWithMultipleFeeManagers.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + s_testReport = generateReportAtTimestamp(block.timestamp); + } + + function _verify( + DestinationVerifierProxy proxy, + bytes memory payload, + address feeAddress, + uint256 wrappedNativeValue, + address sender + ) internal { + address originalAddr = msg.sender; + changePrank(sender); + + proxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); + + changePrank(originalAddr); + } + + function generateReportAtTimestamp(uint256 timestamp) public pure returns (V3Report memory) { + return + V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + // ask michael about this expires at, is it usually set at what blocks + expiresAt: uint32(timestamp) + 500, + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { + //record the current address and switch to the recipient + address originalAddr = msg.sender; + changePrank(sender); + + //pay the recipients + rewardManager.payRecipients(poolId, recipients); + + //change back to the original address + changePrank(originalAddr); + } + + function test_multipleFeeManagersAndVerifiers() public { + /* + In this test we got: + - three verifiers (verifier, verifier2, verifier3). + - two fee managers (feeManager, feeManager2) + - one reward manager + + we glue: + - feeManager is used by verifier1 and verifier2 + - feeManager is used by verifier3 + - Rewardmanager is used by feeManager and feeManager2 + + In this test we do verificatons via verifier1, verifier2 and verifier3 and check that rewards are set accordingly + + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); + weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); + + Common.AddressAndWeight[] memory weights2 = new Common.AddressAndWeight[](1); + weights2[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 100); + + Common.AddressAndWeight[] memory weights3 = new Common.AddressAndWeight[](1); + weights3[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 100); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); + s_verifier2.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights2); + s_verifier3.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE + 1, weights3); + bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); + bytes32 expectedDonConfigID = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); + bytes32 expectedDonConfigID2 = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE); + bytes32 expectedDonConfigID3 = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE + 1); + + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(s_verifierProxy, signedReport, address(link), 0, USER); + assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); + + // internal state checks + assertEq(feeManager.s_linkDeficit(expectedDonConfigID), 0); + assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigID), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); + + // check the recipients are paid according to weights + // These rewards happened through verifier1 and feeManager1 + address[] memory recipients = new address[](1); + recipients[0] = DEFAULT_RECIPIENT_1; + payRecipients(expectedDonConfigID, recipients, ADMIN); + assertEq(link.balanceOf(recipients[0]), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), 0); + + // these rewards happaned through verifier2 and feeManager1 + address[] memory recipients2 = new address[](1); + recipients2[0] = DEFAULT_RECIPIENT_2; + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(s_verifierProxy2, signedReport, address(link), 0, USER); + payRecipients(expectedDonConfigID2, recipients2, ADMIN); + assertEq(link.balanceOf(recipients2[0]), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), 0); + + // these rewards happened through verifier3 and feeManager2 + address[] memory recipients3 = new address[](1); + recipients3[0] = DEFAULT_RECIPIENT_3; + _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); + _verify(s_verifierProxy3, signedReport, address(link), 0, USER); + payRecipients(expectedDonConfigID3, recipients3, ADMIN); + assertEq(link.balanceOf(recipients3[0]), DEFAULT_REPORT_LINK_FEE); + assertEq(link.balanceOf(address(rewardManager)), 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol new file mode 100644 index 0000000..1c57295 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierVerifyBulkTest is BaseTest { + bytes32[3] internal s_reportContext; + V3Report internal s_testReportThree; + + function setUp() public virtual override { + BaseTest.setUp(); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + + s_testReportThree = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function test_revertsVerifyBulkIfNoAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(false) + ); + bytes memory signedReport = _generateV3EncodedBlob( + s_testReportThree, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + bytes[] memory signedReports = new bytes[](2); + signedReports[0] = signedReport; + signedReports[1] = signedReport; + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.AccessForbidden.selector)); + changePrank(USER); + s_verifier.verifyBulk(signedReports, abi.encode(native), msg.sender); + } + + function test_verifyBulkSingleCaseWithSingleConfig() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + // Config1 + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory report = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); + reportSigners[0] = signers[0]; + reportSigners[1] = signers[1]; + reportSigners[2] = signers[2]; + + bytes[] memory signedReports = new bytes[](10); + + bytes memory signedReport = _generateV3EncodedBlob(report, s_reportContext, reportSigners); + + for (uint256 i = 0; i < signedReports.length; i++) { + signedReports[i] = signedReport; + } + + bytes[] memory verifierResponses = s_verifierProxy.verifyBulk(signedReports, abi.encode(native)); + + for (uint256 i = 0; i < verifierResponses.length; i++) { + bytes memory verifierResponse = verifierResponses[i]; + assertReportsEqual(verifierResponse, report); + } + } + + function test_verifyBulkWithSingleConfigOneVerifyFails() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + // Config1 + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); + reportSigners[0] = signers[0]; + reportSigners[1] = signers[1]; + reportSigners[2] = signers[2]; + + bytes[] memory signedReports = new bytes[](11); + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners); + + for (uint256 i = 0; i < 10; i++) { + signedReports[i] = signedReport; + } + + // Making the last report in this batch not verifiable + BaseTest.Signer[] memory reportSigners2 = new BaseTest.Signer[](3); + reportSigners2[0] = signers[30]; + reportSigners2[1] = signers[29]; + reportSigners2[2] = signers[28]; + signedReports[10] = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners2); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verifyBulk(signedReports, abi.encode(native)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol new file mode 100644 index 0000000..e72cfd0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; +import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; +import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; +import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; +import {Common} from "../../../libraries/Common.sol"; + +contract VerifierVerifyTest is BaseTest { + bytes32[3] internal s_reportContext; + V3Report internal s_testReportThree; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_testReportThree = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + } + + function test_verifyReport() public { + // Simple use case just setting a config and verifying a report + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); + + bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(verifierResponse, s_testReportThree); + } + + function test_verifyTooglingActiveFlagsDonConfigs() public { + // sets config + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // verifies report + bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(verifierResponse, s_testReportThree); + + // test verifying via a config that is deactivated + s_verifier.setConfigActive(0, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); + + // test verifying via a reactivated config + s_verifier.setConfigActive(0, true); + verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(verifierResponse, s_testReportThree); + } + + function test_failToVerifyReportIfNotEnoughSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + // only one signer, signers < MINIMAL_FAULT_TOLERANCE + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](1); + signersSubset2[0] = signers[4]; + + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_failToVerifyReportIfNoSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + // No signers for this report + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](0); + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.NoSigners.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_failToVerifyReportIfDupSigners() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + // One signer is repeated + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](4); + signersSubset2[0] = signers[0]; + signersSubset2[1] = signers[1]; + // repeated signers + signersSubset2[2] = signers[2]; + signersSubset2[3] = signers[2]; + + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_failToVerifyReportIfSignerNotInConfig() public { + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + // one report whose signer is not in the config + BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](4); + // these signers are part ofm the config + reportSigners[0] = signers[4]; + reportSigners[1] = signers[5]; + reportSigners[2] = signers[6]; + // this single signer is not in the config + reportSigners[3] = signers[7]; + + bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_canVerifyOlderV3ReportsWithOlderConfigs() public { + /* + This test is checking we can use historical Configs to verify reports: + - DonConfigA has signers {A, B, C, E} is set at time T1 + - DonConfigB has signers {A, B, C, D} is set at time T2 + - checks we can verify a report with {B, C, D} signers (via DonConfigB) + - checks we can verify a report with {B, C, E} signers and timestamp below T2 (via DonConfigA historical config) + - checks we can't verify a report with {B, C, E} signers and timestamp above T2 (it gets verivied via DonConfigB) + - sets DonConfigA as deactivated + - checks we can't verify a report with {B, C, E} signers and timestamp below T2 (via DonConfigA) + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + // Config1 + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); + signersSubset2[0] = signers[0]; + signersSubset2[1] = signers[1]; + signersSubset2[2] = signers[2]; + signersSubset2[3] = signers[3]; + signersSubset2[4] = signers[4]; + signersSubset2[5] = signers[5]; + signersSubset2[6] = signers[29]; + address[] memory signersAddrSubset2 = _getSignerAddresses(signersSubset2); + + V3Report memory reportAtSetConfig1Timestmap = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + vm.warp(block.timestamp + 100); + + // Config2 + s_verifier.setConfig(signersAddrSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory reportAtSetConfig2Timestmap = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](5); + reportSigners[0] = signers[0]; + reportSigners[1] = signers[1]; + reportSigners[2] = signers[2]; + reportSigners[3] = signers[3]; + reportSigners[4] = signers[29]; + + bytes memory signedReport = _generateV3EncodedBlob(reportAtSetConfig2Timestmap, s_reportContext, reportSigners); + + // this report is verified via Config2 + bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); + assertReportsEqual(verifierResponse, reportAtSetConfig2Timestmap); + + BaseTest.Signer[] memory reportSigners2 = new BaseTest.Signer[](5); + reportSigners2[0] = signers[0]; + reportSigners2[1] = signers[1]; + reportSigners2[2] = signers[2]; + reportSigners2[3] = signers[3]; + reportSigners2[4] = signers[6]; + + bytes memory signedReport2 = _generateV3EncodedBlob(reportAtSetConfig1Timestmap, s_reportContext, reportSigners2); + + // this report is verified via Config1 (using a historical config) + bytes memory verifierResponse2 = s_verifierProxy.verify(signedReport2, abi.encode(native)); + assertReportsEqual(verifierResponse2, reportAtSetConfig1Timestmap); + + // same report with same signers but with a higher timestamp gets verified via Config2 + // which means verification fails + bytes memory signedReport3 = _generateV3EncodedBlob(reportAtSetConfig2Timestmap, s_reportContext, reportSigners2); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport3, abi.encode(native)); + + // deactivating Config1 and trying a reverifications ends in failure + s_verifier.setConfigActive(0, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport2, abi.encode(native)); + } + + function test_revertsVerifyIfNoAccess() public { + vm.mockCall( + ACCESS_CONTROLLER_ADDRESS, + abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), + abi.encode(false) + ); + bytes memory signedReport = _generateV3EncodedBlob( + s_testReportThree, + s_reportContext, + _getSigners(FAULT_TOLERANCE + 1) + ); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.AccessForbidden.selector)); + + changePrank(USER); + s_verifier.verify(signedReport, abi.encode(native), msg.sender); + } + + function test_canVerifyNewerReportsWithNewerConfigs() public { + /* + This test is checking that we use prefer verifiying via newer configs instead of old ones. + - DonConfigA has signers {A, B, C, E} is set at time T1 + - DonConfigB has signers {F, G, H, I} is set at time T2 + - DonConfigC has signers {J, K, L, M } is set at time T3 + - checks we can verify a report with {K, L, M} signers (via DonConfigC) + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + // Config1 + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); + signersSubset2[0] = signers[7]; + signersSubset2[1] = signers[8]; + signersSubset2[2] = signers[9]; + signersSubset2[3] = signers[10]; + signersSubset2[4] = signers[11]; + signersSubset2[5] = signers[12]; + signersSubset2[6] = signers[13]; + + address[] memory signersAddrSubset2 = _getSignerAddresses(signersSubset2); + // Config2 + s_verifier.setConfig(signersAddrSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + + BaseTest.Signer[] memory signersSubset3 = new BaseTest.Signer[](7); + signersSubset3[0] = signers[30]; + signersSubset3[1] = signers[29]; + signersSubset3[2] = signers[28]; + signersSubset3[3] = signers[27]; + signersSubset3[4] = signers[26]; + signersSubset3[5] = signers[25]; + signersSubset3[6] = signers[24]; + + address[] memory signersAddrSubset3 = _getSignerAddresses(signersSubset3); + // Config3 + s_verifier.setConfig(signersAddrSubset3, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 1); + + V3Report memory report = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); + reportSigners[0] = signers[30]; + reportSigners[1] = signers[29]; + reportSigners[2] = signers[28]; + + bytes memory signedReport = _generateV3EncodedBlob(report, s_reportContext, reportSigners); + + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_rollingOutConfiguration() public { + /* + This test is checking that we can roll out to a new DON without downtime using a transition configuration + - DonConfigA has signers {A, B, C} is set at time T1 + - DonConfigB (transition config) has signers {A, B, C, D, E, F} is set at time T2 + - DonConfigC has signers {D, E, F} is set at time T3 + + - checks we can verify a report with {A, B, C} signers (via DonConfigA) at time between T1 and T2 + - checks we can verify a report with {A, B, C} signers (via DonConfigB) at time between T2 and T3 + - checks we can verify a report with {D, E, F} signers (via DonConfigB) at time between T2 and T3 + - checks we can verify a report with {D, E, F} signers (via DonConfigC) at time > T3 + - checks we can't verify a report with {A, B, C} signers (via DonConfigC) and timestamp >T3 at time > T3 + - checks we can verify a report with {A, B, C} signers (via DonConfigC) and timestamp between T2 and T3 at time > T3 (historical check) + + */ + + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); + signersSubset1[0] = signers[0]; + signersSubset1[1] = signers[1]; + signersSubset1[2] = signers[2]; + signersSubset1[3] = signers[3]; + signersSubset1[4] = signers[4]; + signersSubset1[5] = signers[5]; + signersSubset1[6] = signers[6]; + + // ConfigA + address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); + s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory reportT1 = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSignersConfigA = new BaseTest.Signer[](3); + reportSignersConfigA[0] = signers[0]; + reportSignersConfigA[1] = signers[1]; + reportSignersConfigA[2] = signers[2]; + + // just testing ConfigA + bytes memory signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); + s_verifierProxy.verify(signedReport, abi.encode(native)); + + vm.warp(block.timestamp + 100); + + BaseTest.Signer[] memory signersSuperset = new BaseTest.Signer[](14); + // signers in ConfigA + signersSuperset[0] = signers[0]; + signersSuperset[1] = signers[1]; + signersSuperset[2] = signers[2]; + signersSuperset[3] = signers[3]; + signersSuperset[4] = signers[4]; + signersSuperset[5] = signers[5]; + signersSuperset[6] = signers[6]; + // new signers + signersSuperset[7] = signers[7]; + signersSuperset[8] = signers[8]; + signersSuperset[9] = signers[9]; + signersSuperset[10] = signers[10]; + signersSuperset[11] = signers[11]; + signersSuperset[12] = signers[12]; + signersSuperset[13] = signers[13]; + + BaseTest.Signer[] memory reportSignersConfigC = new BaseTest.Signer[](3); + reportSignersConfigC[0] = signers[7]; + reportSignersConfigC[1] = signers[8]; + reportSignersConfigC[2] = signers[9]; + + // ConfigB (transition Config) + address[] memory signersAddrsSuperset = _getSignerAddresses(signersSuperset); + s_verifier.setConfig(signersAddrsSuperset, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory reportT2 = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // testing we can verify a fresh (block timestamp) report with ConfigA signers. This should use ConfigB + signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigA); + s_verifierProxy.verify(signedReport, abi.encode(native)); + + // testing we can verify an old ( non fresh block timestamp) report with ConfigA signers. This should use ConfigA + signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); + s_verifierProxy.verify(signedReport, abi.encode(native)); + // deactivating to make sure we are really verifiying via ConfigA + s_verifier.setConfigActive(0, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + s_verifier.setConfigActive(0, true); + + // testing we can verify a fresh (block timestamp) report with the new signers. This should use ConfigB + signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigC); + s_verifierProxy.verify(signedReport, abi.encode(native)); + + vm.warp(block.timestamp + 100); + + // Adding ConfigC + BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); + signersSubset2[0] = signers[7]; + signersSubset2[1] = signers[8]; + signersSubset2[2] = signers[9]; + signersSubset2[3] = signers[10]; + signersSubset2[4] = signers[11]; + signersSubset2[5] = signers[12]; + signersSubset2[6] = signers[13]; + address[] memory signersAddrsSubset2 = _getSignerAddresses(signersSubset2); + s_verifier.setConfig(signersAddrsSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + V3Report memory reportT3 = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // testing we can verify reports with ConfigC signers + signedReport = _generateV3EncodedBlob(reportT3, s_reportContext, reportSignersConfigC); + s_verifierProxy.verify(signedReport, abi.encode(native)); + + // testing an old report (block timestamp) with ConfigC signers should verify via ConfigB + signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigC); + s_verifierProxy.verify(signedReport, abi.encode(native)); + // deactivating to make sure we are really verifiying via ConfigB + s_verifier.setConfigActive(1, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + s_verifier.setConfigActive(1, true); + + // testing a recent report with ConfigA signers should not verify + signedReport = _generateV3EncodedBlob(reportT3, s_reportContext, reportSignersConfigA); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + + // testing an old report (block timestamp) with ConfigA signers should verify via ConfigB + signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigA); + s_verifierProxy.verify(signedReport, abi.encode(native)); + // deactivating to make sure we are really verifiying via ConfigB + s_verifier.setConfigActive(1, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + s_verifier.setConfigActive(1, true); + + // testing an old report (block timestamp) with ConfigA signers should verify via ConfigA + signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); + s_verifierProxy.verify(signedReport, abi.encode(native)); + // deactivating to make sure we are really verifiying via ConfigB + s_verifier.setConfigActive(0, false); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + s_verifier.setConfigActive(0, true); + } + + function test_verifyFailsWhenReportIsOlderThanConfig() public { + /* + - SetConfig A at time T0 + - SetConfig B at time T1 + - tries verifing report issued at blocktimestmap < T0 + + this test is failing: ToDo Ask Michael + */ + Signer[] memory signers = _getSigners(MAX_ORACLES); + address[] memory signerAddrs = _getSignerAddresses(signers); + s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); + + vm.warp(block.timestamp + 100); + + V3Report memory reportAtTMinus100 = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp - 100), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + vm.warp(block.timestamp + 100); + s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); + + bytes memory signedReport = _generateV3EncodedBlob(reportAtTMinus100, s_reportContext, signers); + + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedReport, abi.encode(native)); + } + + function test_scenarioRollingNewChainWithHistoricConfigs() public { + /* + This test is checking that we can roll out in a new network and set historic configurations : + - Stars with a chain at blocktimestamp 1000 + - SetConfigA with teimstamp 100 + - SetConfigB with timesmtap 200 + - SetConfigC with timestamp current + - tries verifying reports for all the configs + */ + + vm.warp(block.timestamp + 1000); + + Signer[] memory signers = _getSigners(MAX_ORACLES); + + uint8 MINIMAL_FAULT_TOLERANCE = 2; + BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); + signersA[0] = signers[0]; + signersA[1] = signers[1]; + signersA[2] = signers[2]; + signersA[3] = signers[3]; + signersA[4] = signers[4]; + signersA[5] = signers[5]; + signersA[6] = signers[6]; + + // ConfigA (historical config) + uint32 configATimestmap = 100; + address[] memory signersAddrA = _getSignerAddresses(signersA); + s_verifier.setConfigWithActivationTime( + signersAddrA, + MINIMAL_FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + configATimestmap + ); + + // ConfigB (historical config) + uint32 configBTimestmap = 200; + // Config B + BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[0] = signers[8]; + signersB[1] = signers[9]; + signersB[2] = signers[10]; + signersB[3] = signers[11]; + signersB[4] = signers[12]; + signersB[5] = signers[13]; + signersB[6] = signers[14]; + address[] memory signersAddrsB = _getSignerAddresses(signersB); + s_verifier.setConfigWithActivationTime( + signersAddrsB, + MINIMAL_FAULT_TOLERANCE, + new Common.AddressAndWeight[](0), + configBTimestmap + ); + + // ConfigC (config at current timestamp) + // BaseTest.Signer[] memory signersC = new BaseTest.Signer[](7); + // signers in ConfigA + signersB[6] = signers[15]; + address[] memory signersAddrsC = _getSignerAddresses(signersB); + s_verifier.setConfig(signersAddrsC, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); + + vm.warp(block.timestamp + 10); + + // historical report + V3Report memory s_testReportA = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(101), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // historical report + V3Report memory s_testReportB = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(201), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + // report at recent timestamp + V3Report memory s_testReportC = V3Report({ + feedId: FEED_ID_V3, + observationsTimestamp: OBSERVATIONS_TIMESTAMP, + validFromTimestamp: uint32(block.timestamp), + nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), + linkFee: uint192(DEFAULT_REPORT_LINK_FEE), + expiresAt: uint32(block.timestamp + 1000), + benchmarkPrice: MEDIAN, + bid: BID, + ask: ASK + }); + + BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); + reportSignersA[0] = signers[0]; + reportSignersA[1] = signers[1]; + reportSignersA[2] = signers[2]; + + BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); + reportSignersB[0] = signers[8]; + reportSignersB[1] = signers[9]; + reportSignersB[2] = signers[14]; + + BaseTest.Signer[] memory reportSignersC = new BaseTest.Signer[](3); + reportSignersC[0] = signers[15]; + reportSignersC[1] = signers[13]; + reportSignersC[2] = signers[12]; + + bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); + bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); + bytes memory signedReportC = _generateV3EncodedBlob(s_testReportC, s_reportContext, reportSignersC); + + // verifying historical reports + s_verifierProxy.verify(signedReportA, abi.encode(native)); + s_verifierProxy.verify(signedReportB, abi.encode(native)); + // verifiying a current report + s_verifierProxy.verify(signedReportC, abi.encode(native)); + + // current report verified by historical report fails + bytes memory signedNewReportWithOldSignatures = _generateV3EncodedBlob( + s_testReportC, + s_reportContext, + reportSignersA + ); + vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); + s_verifierProxy.verify(signedNewReportWithOldSignatures, abi.encode(native)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol new file mode 100644 index 0000000..f5e5040 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {IChannelConfigStore} from "./interfaces/IChannelConfigStore.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; + +contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, TypeAndVersionInterface { + event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); + + constructor() ConfirmedOwner(msg.sender) {} + + /// @notice The version of a channel definition keyed by DON ID + // Increments by 1 on every update + mapping(uint256 => uint256) internal s_channelDefinitionVersions; + + function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external onlyOwner { + uint32 newVersion = uint32(++s_channelDefinitionVersions[uint256(donId)]); + emit NewChannelDefinition(donId, newVersion, url, sha); + } + + function typeAndVersion() external pure override returns (string memory) { + return "ChannelConfigStore 0.0.1"; + } + + function supportsInterface(bytes4 interfaceId) external pure returns (bool) { + return interfaceId == type(IChannelConfigStore).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol new file mode 100644 index 0000000..5945f7a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {IConfigurator} from "../../interfaces/IConfigurator.sol"; + +// OCR2 standard +uint256 constant MAX_NUM_ORACLES = 31; + +/** + * @title Configurator + * @author samsondav + * @notice This contract is intended to be deployed on the source chain and acts as a OCR3 configurator for LLO/Mercury + **/ + +contract Configurator is IConfigurator, ConfirmedOwner, TypeAndVersionInterface, IERC165 { + /// @notice This error is thrown whenever trying to set a config + /// with a fault tolerance of 0 + error FaultToleranceMustBePositive(); + + /// @notice This error is thrown whenever a report is signed + /// with more than the max number of signers + /// @param numSigners The number of signers who have signed the report + /// @param maxSigners The maximum number of signers that can sign a report + error ExcessSigners(uint256 numSigners, uint256 maxSigners); + + /// @notice This error is thrown whenever a report is signed + /// with less than the minimum number of signers + /// @param numSigners The number of signers who have signed the report + /// @param minSigners The minimum number of signers that need to sign a report + error InsufficientSigners(uint256 numSigners, uint256 minSigners); + + struct ConfigurationState { + // The number of times a new configuration + // has been set + uint64 configCount; + // The block number of the block the last time + /// the configuration was updated. + uint32 latestConfigBlockNumber; + } + + constructor() ConfirmedOwner(msg.sender) {} + + /// @notice Configuration states keyed on DON ID + mapping(bytes32 => ConfigurationState) internal s_configurationStates; + + /// @inheritdoc IConfigurator + function setConfig( + bytes32 donId, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external override checkConfigValid(signers.length, f) onlyOwner { + _setConfig( + donId, + block.chainid, + address(this), + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + } + + /// @notice Sets config based on the given arguments + /// @param donId DON ID to set config for + /// @param sourceChainId Chain ID of source config + /// @param sourceAddress Address of source config Verifier + /// @param signers addresses with which oracles sign the reports + /// @param offchainTransmitters CSA key for the ith Oracle + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + function _setConfig( + bytes32 donId, + uint256 sourceChainId, + address sourceAddress, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal { + ConfigurationState storage configurationState = s_configurationStates[donId]; + + uint64 newConfigCount = ++configurationState.configCount; + + bytes32 configDigest = _configDigestFromConfigData( + donId, + sourceChainId, + sourceAddress, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + emit ConfigSet( + donId, + configurationState.latestConfigBlockNumber, + configDigest, + newConfigCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ); + + configurationState.latestConfigBlockNumber = uint32(block.number); + } + + /// @notice Generates the config digest from config data + /// @param donId DON ID to set config for + /// @param sourceChainId Chain ID of configurator contract + /// @param sourceAddress Address of configurator contract + /// @param configCount ordinal number of this config setting among all config settings over the life of this contract + /// @param signers ith element is address ith oracle uses to sign a report + /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) + /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + /// @dev This function is a modified version of the method from OCR2Abstract + function _configDigestFromConfigData( + bytes32 donId, + uint256 sourceChainId, + address sourceAddress, + uint64 configCount, + address[] memory signers, + bytes32[] memory offchainTransmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + donId, + sourceChainId, + sourceAddress, + configCount, + signers, + offchainTransmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 + // 0x0006 corresponds to ConfigDigestPrefixLLO in libocr + uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 + return bytes32((prefix & prefixMask) | (h & ~prefixMask)); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { + return interfaceId == type(IConfigurator).interfaceId; + } + + /// @inheritdoc TypeAndVersionInterface + function typeAndVersion() external pure override returns (string memory) { + return "Configurator 0.4.0"; + } + + modifier checkConfigValid(uint256 numSigners, uint256 f) { + if (f == 0) revert FaultToleranceMustBePositive(); + if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); + if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol new file mode 100644 index 0000000..8628e3c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; + +interface IChannelConfigStore is IERC165 { + function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol new file mode 100644 index 0000000..70b033e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.19; + +import {IChannelConfigStore} from "../interfaces/IChannelConfigStore.sol"; +import {Test} from "forge-std/Test.sol"; +import {ChannelConfigStore} from "../ChannelConfigStore.sol"; +import {ExposedChannelConfigStore} from "./mocks/ExposedChannelConfigStore.sol"; + +/** + * @title ChannelConfigStoreTest + * @author samsondav + * @notice Base class for ChannelConfigStore tests + */ +contract ChannelConfigStoreTest is Test { + ExposedChannelConfigStore public channelConfigStore; + event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); + + function setUp() public virtual { + channelConfigStore = new ExposedChannelConfigStore(); + } + + function testTypeAndVersion() public view { + assertEq(channelConfigStore.typeAndVersion(), "ChannelConfigStore 0.0.1"); + } + + function testSupportsInterface() public view { + assertTrue(channelConfigStore.supportsInterface(type(IChannelConfigStore).interfaceId)); + } + + function testSetChannelDefinitions() public { + vm.expectEmit(); + emit NewChannelDefinition(42, 1, "url", keccak256("sha")); + channelConfigStore.setChannelDefinitions(42, "url", keccak256("sha")); + + vm.expectEmit(); + emit NewChannelDefinition(42, 2, "url2", keccak256("sha2")); + channelConfigStore.setChannelDefinitions(42, "url2", keccak256("sha2")); + + assertEq(channelConfigStore.exposedReadChannelDefinitionStates(42), uint32(2)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol new file mode 100644 index 0000000..1ffd512 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ChannelConfigStore} from "../../ChannelConfigStore.sol"; + +// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedChannelConfigStore is ChannelConfigStore { + constructor() {} + + function exposedReadChannelDefinitionStates(uint256 donId) public view returns (uint256) { + return s_channelDefinitionVersions[donId]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol new file mode 100644 index 0000000..7b1370a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Configurator} from "../../Configurator.sol"; + +// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore +// methods/structures so that golang code can access them, and we get +// reliable type checking on their usage +contract ExposedConfigurator is Configurator { + constructor() {} + + function exposedReadConfigurationStates(bytes32 donId) public view returns (ConfigurationState memory) { + return s_configurationStates[donId]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol new file mode 100644 index 0000000..753ba91 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: MIT +// Warning: this is an autogenerated file! DO NOT EDIT. + +pragma solidity ^0.8.6; + +contract FunctionsBillingRegistryEventsMock { + struct Commitment {uint64 subscriptionId;address client;uint32 gasLimit;uint256 gasPrice;address don;uint96 donFee;uint96 registryFee;uint96 estimatedCost;uint256 timestamp; } + event AuthorizedSendersChanged(address[] senders,address changedBy); + event BillingEnd(bytes32 indexed requestId,uint64 subscriptionId,uint96 signerPayment,uint96 transmitterPayment,uint96 totalCost,bool success); + event BillingStart(bytes32 indexed requestId,Commitment commitment); + event ConfigSet(uint32 maxGasLimit,uint32 stalenessSeconds,uint256 gasAfterPaymentCalculation,int256 fallbackWeiPerUnitLink,uint32 gasOverhead); + event FundsRecovered(address to,uint256 amount); + event Initialized(uint8 version); + event OwnershipTransferRequested(address indexed from,address indexed to); + event OwnershipTransferred(address indexed from,address indexed to); + event Paused(address account); + event RequestTimedOut(bytes32 indexed requestId); + event SubscriptionCanceled(uint64 indexed subscriptionId,address to,uint256 amount); + event SubscriptionConsumerAdded(uint64 indexed subscriptionId,address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subscriptionId,address consumer); + event SubscriptionCreated(uint64 indexed subscriptionId,address owner); + event SubscriptionFunded(uint64 indexed subscriptionId,uint256 oldBalance,uint256 newBalance); + event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId,address from,address to); + event SubscriptionOwnerTransferred(uint64 indexed subscriptionId,address from,address to); + event Unpaused(address account); + function emitAuthorizedSendersChanged(address[] memory senders,address changedBy) public { + emit AuthorizedSendersChanged(senders,changedBy); + } + function emitBillingEnd(bytes32 requestId,uint64 subscriptionId,uint96 signerPayment,uint96 transmitterPayment,uint96 totalCost,bool success) public { + emit BillingEnd(requestId,subscriptionId,signerPayment,transmitterPayment,totalCost,success); + } + function emitBillingStart(bytes32 requestId,Commitment memory commitment) public { + emit BillingStart(requestId,commitment); + } + function emitConfigSet(uint32 maxGasLimit,uint32 stalenessSeconds,uint256 gasAfterPaymentCalculation,int256 fallbackWeiPerUnitLink,uint32 gasOverhead) public { + emit ConfigSet(maxGasLimit,stalenessSeconds,gasAfterPaymentCalculation,fallbackWeiPerUnitLink,gasOverhead); + } + function emitFundsRecovered(address to,uint256 amount) public { + emit FundsRecovered(to,amount); + } + function emitInitialized(uint8 version) public { + emit Initialized(version); + } + function emitOwnershipTransferRequested(address from,address to) public { + emit OwnershipTransferRequested(from,to); + } + function emitOwnershipTransferred(address from,address to) public { + emit OwnershipTransferred(from,to); + } + function emitPaused(address account) public { + emit Paused(account); + } + function emitRequestTimedOut(bytes32 requestId) public { + emit RequestTimedOut(requestId); + } + function emitSubscriptionCanceled(uint64 subscriptionId,address to,uint256 amount) public { + emit SubscriptionCanceled(subscriptionId,to,amount); + } + function emitSubscriptionConsumerAdded(uint64 subscriptionId,address consumer) public { + emit SubscriptionConsumerAdded(subscriptionId,consumer); + } + function emitSubscriptionConsumerRemoved(uint64 subscriptionId,address consumer) public { + emit SubscriptionConsumerRemoved(subscriptionId,consumer); + } + function emitSubscriptionCreated(uint64 subscriptionId,address owner) public { + emit SubscriptionCreated(subscriptionId,owner); + } + function emitSubscriptionFunded(uint64 subscriptionId,uint256 oldBalance,uint256 newBalance) public { + emit SubscriptionFunded(subscriptionId,oldBalance,newBalance); + } + function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId,address from,address to) public { + emit SubscriptionOwnerTransferRequested(subscriptionId,from,to); + } + function emitSubscriptionOwnerTransferred(uint64 subscriptionId,address from,address to) public { + emit SubscriptionOwnerTransferred(subscriptionId,from,to); + } + function emitUnpaused(address account) public { + emit Unpaused(account); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol new file mode 100644 index 0000000..c68de7f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +// Warning: this is an autogenerated file! DO NOT EDIT. + +pragma solidity ^0.8.6; + +contract FunctionsOracleEventsMock { + event AuthorizedSendersActive(address account); + event AuthorizedSendersChanged(address[] senders,address changedBy); + event AuthorizedSendersDeactive(address account); + event ConfigSet(uint32 previousConfigBlockNumber,bytes32 configDigest,uint64 configCount,address[] signers,address[] transmitters,uint8 f,bytes onchainConfig,uint64 offchainConfigVersion,bytes offchainConfig); + event Initialized(uint8 version); + event InvalidRequestID(bytes32 indexed requestId); + event OracleRequest(bytes32 indexed requestId,address requestingContract,address requestInitiator,uint64 subscriptionId,address subscriptionOwner,bytes data); + event OracleResponse(bytes32 indexed requestId); + event OwnershipTransferRequested(address indexed from,address indexed to); + event OwnershipTransferred(address indexed from,address indexed to); + event ResponseTransmitted(bytes32 indexed requestId,address transmitter); + event Transmitted(bytes32 configDigest,uint32 epoch); + event UserCallbackError(bytes32 indexed requestId,string reason); + event UserCallbackRawError(bytes32 indexed requestId,bytes lowLevelData); + function emitAuthorizedSendersActive(address account) public { + emit AuthorizedSendersActive(account); + } + function emitAuthorizedSendersChanged(address[] memory senders,address changedBy) public { + emit AuthorizedSendersChanged(senders,changedBy); + } + function emitAuthorizedSendersDeactive(address account) public { + emit AuthorizedSendersDeactive(account); + } + function emitConfigSet(uint32 previousConfigBlockNumber,bytes32 configDigest,uint64 configCount,address[] memory signers,address[] memory transmitters,uint8 f,bytes memory onchainConfig,uint64 offchainConfigVersion,bytes memory offchainConfig) public { + emit ConfigSet(previousConfigBlockNumber,configDigest,configCount,signers,transmitters,f,onchainConfig,offchainConfigVersion,offchainConfig); + } + function emitInitialized(uint8 version) public { + emit Initialized(version); + } + function emitInvalidRequestID(bytes32 requestId) public { + emit InvalidRequestID(requestId); + } + function emitOracleRequest(bytes32 requestId,address requestingContract,address requestInitiator,uint64 subscriptionId,address subscriptionOwner,bytes memory data) public { + emit OracleRequest(requestId,requestingContract,requestInitiator,subscriptionId,subscriptionOwner,data); + } + function emitOracleResponse(bytes32 requestId) public { + emit OracleResponse(requestId); + } + function emitOwnershipTransferRequested(address from,address to) public { + emit OwnershipTransferRequested(from,to); + } + function emitOwnershipTransferred(address from,address to) public { + emit OwnershipTransferred(from,to); + } + function emitResponseTransmitted(bytes32 requestId,address transmitter) public { + emit ResponseTransmitted(requestId,transmitter); + } + function emitTransmitted(bytes32 configDigest,uint32 epoch) public { + emit Transmitted(configDigest,epoch); + } + function emitUserCallbackError(bytes32 requestId,string memory reason) public { + emit UserCallbackError(requestId,reason); + } + function emitUserCallbackRawError(bytes32 requestId,bytes memory lowLevelData) public { + emit UserCallbackRawError(requestId,lowLevelData); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol new file mode 100644 index 0000000..bdc935c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../shared/interfaces/AggregatorValidatorInterface.sol"; + +contract MockAggregatorValidator is AggregatorValidatorInterface { + uint8 immutable id; + + constructor(uint8 id_) { + id = id_; + } + + event ValidateCalled( + uint8 id, + uint256 previousRoundId, + int256 previousAnswer, + uint256 currentRoundId, + int256 currentAnswer + ); + + function validate( + uint256 previousRoundId, + int256 previousAnswer, + uint256 currentRoundId, + int256 currentAnswer + ) external override returns (bool) { + emit ValidateCalled(id, previousRoundId, previousAnswer, currentRoundId, currentAnswer); + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol new file mode 100644 index 0000000..fbfdf0f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +/** + * @dev this contract mocks the arbitrum precompiled ArbSys contract + * https://developer.arbitrum.io/arbos/precompiles#ArbSys + */ +contract MockArbSys { + function arbBlockNumber() public view returns (uint256) { + return block.number; + } + + function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32) { + return blockhash(arbBlockNum); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol new file mode 100644 index 0000000..a68f1b1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; + +contract MockLinkToken { + uint256 private constant TOTAL_SUPPLY = 1_000_000_000 * 1e18; + + constructor() { + balances[msg.sender] = TOTAL_SUPPLY; + } + + mapping(address => uint256) public balances; + + function totalSupply() external pure returns (uint256 totalTokensIssued) { + return TOTAL_SUPPLY; // 1 billion LINK -> 1e27 Juels + } + + function transfer(address _to, uint256 _value) public returns (bool) { + balances[msg.sender] = balances[msg.sender] - _value; + balances[_to] = balances[_to] + _value; + return true; + } + + function setBalance(address _address, uint256 _value) external returns (bool) { + balances[_address] = _value; + return true; + } + + function balanceOf(address _address) external view returns (uint256) { + return balances[_address]; + } + + function transferAndCall(address _to, uint256 _value, bytes calldata _data) public returns (bool success) { + transfer(_to, _value); + if (isContract(_to)) { + contractFallback(_to, _value, _data); + } + return true; + } + + function isContract(address _addr) private view returns (bool hasCode) { + uint256 length; + assembly { + length := extcodesize(_addr) + } + return length > 0; + } + + function contractFallback(address _to, uint256 _value, bytes calldata _data) private { + IERC677Receiver receiver = IERC677Receiver(_to); + receiver.onTokenTransfer(msg.sender, _value, _data); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol new file mode 100644 index 0000000..5366bbe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +contract MockOffchainAggregator { + event RoundIdUpdated(uint80 roundId); + + uint80 public roundId; + + function requestNewRound() external returns (uint80) { + roundId++; + emit RoundIdUpdated(roundId); + return roundId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol new file mode 100644 index 0000000..ffb0924 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwnerWithProposal} from "../shared/access/ConfirmedOwnerWithProposal.sol"; +import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + +// solhint-disable gas-custom-errors +contract AuthorizedForwarder is ConfirmedOwnerWithProposal, AuthorizedReceiver { + using Address for address; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable linkToken; + + event OwnershipTransferRequestedWithMessage(address indexed from, address indexed to, bytes message); + + constructor( + address link, + address owner, + address recipient, + bytes memory message + ) ConfirmedOwnerWithProposal(owner, recipient) { + require(link != address(0), "Link token cannot be a zero address"); + linkToken = link; + if (recipient != address(0)) { + emit OwnershipTransferRequestedWithMessage(owner, recipient, message); + } + } + + string public constant typeAndVersion = "AuthorizedForwarder 1.1.0"; + + // @notice Forward a call to another contract + // @dev Only callable by an authorized sender + // @param to address + // @param data to forward + function forward(address to, bytes calldata data) external validateAuthorizedSender { + require(to != linkToken, "Cannot forward to Link token"); + _forward(to, data); + } + + // @notice Forward multiple calls to other contracts in a multicall style + // @dev Only callable by an authorized sender + // @param tos An array of addresses to forward the calls to + // @param datas An array of data to forward to each corresponding address + function multiForward(address[] calldata tos, bytes[] calldata datas) external validateAuthorizedSender { + require(tos.length == datas.length, "Arrays must have the same length"); + + for (uint256 i = 0; i < tos.length; ++i) { + address to = tos[i]; + require(to != linkToken, "Cannot forward to Link token"); + + // Perform the forward operation + _forward(to, datas[i]); + } + } + + // @notice Forward a call to another contract + // @dev Only callable by the owner + // @param to address + // @param data to forward + function ownerForward(address to, bytes calldata data) external onlyOwner { + _forward(to, data); + } + + // @notice Transfer ownership with instructions for recipient + // @param to address proposed recipient of ownership + // @param message instructions for recipient upon accepting ownership + function transferOwnershipWithMessage(address to, bytes calldata message) external { + transferOwnership(to); + emit OwnershipTransferRequestedWithMessage(msg.sender, to, message); + } + + // @notice concrete implementation of AuthorizedReceiver + // @return bool of whether sender is authorized + function _canSetAuthorizedSenders() internal view override returns (bool) { + return owner() == msg.sender; + } + + // @notice common forwarding functionality and validation + function _forward(address to, bytes calldata data) private { + require(to.isContract(), "Must forward to a contract"); + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory result) = to.call(data); + if (!success) { + if (result.length == 0) revert("Forwarded call reverted without reason"); + assembly { + revert(add(32, result), mload(result)) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol new file mode 100644 index 0000000..919602b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; + +// solhint-disable gas-custom-errors +abstract contract AuthorizedReceiver is IAuthorizedReceiver { + mapping(address sender => bool authorized) private s_authorizedSenders; + address[] private s_authorizedSenderList; + + event AuthorizedSendersChanged(address[] senders, address changedBy); + + // @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. + // @param senders The addresses of the authorized Chainlink node + function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter { + require(senders.length > 0, "Must have at least 1 sender"); + // Set previous authorized senders to false + uint256 authorizedSendersLength = s_authorizedSenderList.length; + for (uint256 i = 0; i < authorizedSendersLength; ++i) { + s_authorizedSenders[s_authorizedSenderList[i]] = false; + } + // Set new to true + for (uint256 i = 0; i < senders.length; ++i) { + require(s_authorizedSenders[senders[i]] == false, "Must not have duplicate senders"); + s_authorizedSenders[senders[i]] = true; + } + // Replace list + s_authorizedSenderList = senders; + emit AuthorizedSendersChanged(senders, msg.sender); + } + + // @notice Retrieve a list of authorized senders + // @return array of addresses + function getAuthorizedSenders() external view override returns (address[] memory) { + return s_authorizedSenderList; + } + + // @notice Use this to check if a node is authorized for fulfilling requests + // @param sender The address of the Chainlink node + // @return The authorization status of the node + function isAuthorizedSender(address sender) public view override returns (bool) { + return s_authorizedSenders[sender]; + } + + // @notice customizable guard of who can update the authorized sender list + // @return bool whether sender can update authorized sender list + function _canSetAuthorizedSenders() internal virtual returns (bool); + + // @notice validates the sender is an authorized sender + function _validateIsAuthorizedSender() internal view { + require(isAuthorizedSender(msg.sender), "Not authorized sender"); + } + + // @notice prevents non-authorized addresses from calling this method + modifier validateAuthorizedSender() { + _validateIsAuthorizedSender(); + _; + } + + // @notice prevents non-authorized addresses from calling this method + modifier validateAuthorizedSenderSetter() { + require(_canSetAuthorizedSenders(), "Cannot set authorized senders"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol new file mode 100644 index 0000000..dab259c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +// solhint-disable gas-custom-errors +abstract contract LinkTokenReceiver { + // @notice Called when LINK is sent to the contract via `transferAndCall` + // @dev The data payload's first 2 words will be overwritten by the `sender` and `amount` + // values to ensure correctness. Calls oracleRequest. + // @param sender Address of the sender + // @param amount Amount of LINK sent (specified in wei) + // @param data Payload of the transaction + function onTokenTransfer( + address sender, + uint256 amount, + bytes memory data + ) public validateFromLINK permittedFunctionsForLINK(data) { + assembly { + // solhint-disable-next-line avoid-low-level-calls + mstore(add(data, 36), sender) // ensure correct sender is passed + // solhint-disable-next-line avoid-low-level-calls + mstore(add(data, 68), amount) // ensure correct amount is passed0.8.19 + } + // solhint-disable-next-line avoid-low-level-calls + (bool success, ) = address(this).delegatecall(data); // calls oracleRequest + require(success, "Unable to create request"); + } + + function getChainlinkToken() public view virtual returns (address); + + // @notice Validate the function called on token transfer + function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal virtual; + + // @dev Reverts if not sent from the LINK token + modifier validateFromLINK() { + require(msg.sender == getChainlinkToken(), "Must use LINK token"); + _; + } + + // @dev Reverts if the given data does not begin with the `oracleRequest` function selector + // @param data The data payload of the request + modifier permittedFunctionsForLINK(bytes memory data) { + bytes4 funcSelector; + assembly { + // solhint-disable-next-line avoid-low-level-calls + funcSelector := mload(add(data, 32)) + } + _validateTokenTransferAction(funcSelector, data); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol new file mode 100644 index 0000000..64882e4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; +import {LinkTokenReceiver} from "./LinkTokenReceiver.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; +import {OperatorInterface} from "../interfaces/OperatorInterface.sol"; +import {IOwnable} from "../shared/interfaces/IOwnable.sol"; +import {IWithdrawal} from "./interfaces/IWithdrawal.sol"; +import {OracleInterface} from "../interfaces/OracleInterface.sol"; +import {SafeCast} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; + +// @title The Chainlink Operator contract +// @notice Node operators can deploy this contract to fulfill requests sent to them +// solhint-disable gas-custom-errors +contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, IWithdrawal { + struct Commitment { + bytes31 paramsHash; + uint8 dataVersion; + } + + uint256 public constant EXPIRYTIME = 5 minutes; + uint256 private constant MAXIMUM_DATA_VERSION = 256; + uint256 private constant MINIMUM_CONSUMER_GAS_LIMIT = 400000; + uint256 private constant SELECTOR_LENGTH = 4; + uint256 private constant EXPECTED_REQUEST_WORDS = 2; + uint256 private constant MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS); + // We initialize fields to 1 instead of 0 so that the first invocation + // does not cost more gas. + uint256 private constant ONE_FOR_CONSISTENT_GAS_COST = 1; + // oracleRequest is intended for version 1, enabling single word responses + bytes4 private constant ORACLE_REQUEST_SELECTOR = this.oracleRequest.selector; + // operatorRequest is intended for version 2, enabling multi-word responses + bytes4 private constant OPERATOR_REQUEST_SELECTOR = this.operatorRequest.selector; + + LinkTokenInterface internal immutable i_linkToken; + mapping(bytes32 => Commitment) private s_commitments; + mapping(address => bool) private s_owned; + // Tokens sent for requests that have not been fulfilled yet + uint256 private s_tokensInEscrow = ONE_FOR_CONSISTENT_GAS_COST; + + event OracleRequest( + bytes32 indexed specId, + address requester, + bytes32 requestId, + uint256 payment, + address callbackAddr, + bytes4 callbackFunctionId, + uint256 cancelExpiration, + uint256 dataVersion, + bytes data + ); + + event CancelOracleRequest(bytes32 indexed requestId); + + event OracleResponse(bytes32 indexed requestId); + + event OwnableContractAccepted(address indexed acceptedContract); + + event TargetsUpdatedAuthorizedSenders(address[] targets, address[] senders, address changedBy); + + // @notice Deploy with the address of the LINK token + // @dev Sets the LinkToken address for the imported LinkTokenInterface + // @param link The address of the LINK token + // @param owner The address of the owner + constructor(address link, address owner) ConfirmedOwner(owner) { + i_linkToken = LinkTokenInterface(link); // external but already deployed and unalterable + } + + string public constant typeAndVersion = "Operator 1.0.0"; + + // @notice Creates the Chainlink request. This is a backwards compatible API + // with the Oracle.sol contract, but the behavior changes because + // callbackAddress is assumed to be the same as the request sender. + // @param callbackAddress The consumer of the request + // @param payment The amount of payment given (specified in wei) + // @param specId The Job Specification ID + // @param callbackAddress The address the oracle data will be sent to + // @param callbackFunctionId The callback function ID for the response + // @param nonce The nonce sent by the requester + // @param dataVersion The specified data version + // @param data The extra request parameters + function oracleRequest( + address sender, + uint256 payment, + bytes32 specId, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 nonce, + uint256 dataVersion, + bytes calldata data + ) external override validateFromLINK { + (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( + sender, + payment, + callbackAddress, + callbackFunctionId, + nonce, + dataVersion + ); + emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); + } + + // @notice Creates the Chainlink request + // @dev Stores the hash of the params as the on-chain commitment for the request. + // Emits OracleRequest event for the Chainlink node to detect. + // @param sender The sender of the request + // @param payment The amount of payment given (specified in wei) + // @param specId The Job Specification ID + // @param callbackFunctionId The callback function ID for the response + // @param nonce The nonce sent by the requester + // @param dataVersion The specified data version + // @param data The extra request parameters + function operatorRequest( + address sender, + uint256 payment, + bytes32 specId, + bytes4 callbackFunctionId, + uint256 nonce, + uint256 dataVersion, + bytes calldata data + ) external override validateFromLINK { + (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( + sender, + payment, + sender, + callbackFunctionId, + nonce, + dataVersion + ); + emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); + } + + // @notice Called by the Chainlink node to fulfill requests + // @dev Given params must hash back to the commitment stored from `oracleRequest`. + // Will call the callback address' callback function without bubbling up error + // checking in a `require` so that the node can get paid. + // @param requestId The fulfillment request ID that must match the requester's + // @param payment The payment amount that will be released for the oracle (specified in wei) + // @param callbackAddress The callback address to call for fulfillment + // @param callbackFunctionId The callback function ID to use for fulfillment + // @param expiration The expiration that the node should respond by before the requester can cancel + // @param data The data to return to the consuming contract + // @return Status if the external call was successful + function fulfillOracleRequest( + bytes32 requestId, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration, + bytes32 data + ) + external + override + validateAuthorizedSender + validateRequestId(requestId) + validateCallbackAddress(callbackAddress) + returns (bool) + { + _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 1); + emit OracleResponse(requestId); + require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); + // All updates to the oracle's fulfillment should come before calling the + // callback(addr+functionId) as it is untrusted. + // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern + (bool success, ) = callbackAddress.call(abi.encodeWithSelector(callbackFunctionId, requestId, data)); // solhint-disable-line avoid-low-level-calls + return success; + } + + // @notice Called by the Chainlink node to fulfill requests with multi-word support + // @dev Given params must hash back to the commitment stored from `oracleRequest`. + // Will call the callback address' callback function without bubbling up error + // checking in a `require` so that the node can get paid. + // @param requestId The fulfillment request ID that must match the requester's + // @param payment The payment amount that will be released for the oracle (specified in wei) + // @param callbackAddress The callback address to call for fulfillment + // @param callbackFunctionId The callback function ID to use for fulfillment + // @param expiration The expiration that the node should respond by before the requester can cancel + // @param data The data to return to the consuming contract + // @return Status if the external call was successful + function fulfillOracleRequest2( + bytes32 requestId, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration, + bytes calldata data + ) + external + override + validateAuthorizedSender + validateRequestId(requestId) + validateCallbackAddress(callbackAddress) + validateMultiWordResponseId(requestId, data) + returns (bool) + { + _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 2); + emit OracleResponse(requestId); + require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); + // All updates to the oracle's fulfillment should come before calling the + // callback(addr+functionId) as it is untrusted. + // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern + (bool success, ) = callbackAddress.call(abi.encodePacked(callbackFunctionId, data)); // solhint-disable-line avoid-low-level-calls + return success; + } + + // @notice Transfer the ownership of ownable contracts. This is primarily + // intended for Authorized Forwarders but could possibly be extended to work + // with future contracts.OracleInterface + // @param ownable list of addresses to transfer + // @param newOwner address to transfer ownership to + function transferOwnableContracts(address[] calldata ownable, address newOwner) external onlyOwner { + for (uint256 i = 0; i < ownable.length; ++i) { + s_owned[ownable[i]] = false; + IOwnable(ownable[i]).transferOwnership(newOwner); + } + } + + // @notice Accept the ownership of an ownable contract. This is primarily + // intended for Authorized Forwarders but could possibly be extended to work + // with future contracts. + // @dev Must be the pending owner on the contract + // @param ownable list of addresses of Ownable contracts to accept + function acceptOwnableContracts(address[] calldata ownable) public validateAuthorizedSenderSetter { + for (uint256 i = 0; i < ownable.length; ++i) { + s_owned[ownable[i]] = true; + emit OwnableContractAccepted(ownable[i]); + IOwnable(ownable[i]).acceptOwnership(); + } + } + + // @notice Sets the fulfillment permission for + // @param targets The addresses to set permissions on + // @param senders The addresses that are allowed to send updates + function setAuthorizedSendersOn( + address[] calldata targets, + address[] calldata senders + ) public validateAuthorizedSenderSetter { + emit TargetsUpdatedAuthorizedSenders(targets, senders, msg.sender); + + for (uint256 i = 0; i < targets.length; ++i) { + IAuthorizedReceiver(targets[i]).setAuthorizedSenders(senders); + } + } + + // @notice Accepts ownership of ownable contracts and then immediately sets + // the authorized sender list on each of the newly owned contracts. This is + // primarily intended for Authorized Forwarders but could possibly be + // extended to work with future contracts. + // @param targets The addresses to set permissions on + // @param senders The addresses that are allowed to send updates + function acceptAuthorizedReceivers( + address[] calldata targets, + address[] calldata senders + ) external validateAuthorizedSenderSetter { + acceptOwnableContracts(targets); + setAuthorizedSendersOn(targets, senders); + } + + // @notice Allows the node operator to withdraw earned LINK to a given address + // @dev The owner of the contract can be another wallet and does not have to be a Chainlink node + // @param recipient The address to send the LINK token to + // @param amount The amount to send (specified in wei) + function withdraw( + address recipient, + uint256 amount + ) external override(OracleInterface, IWithdrawal) onlyOwner validateAvailableFunds(amount) { + assert(i_linkToken.transfer(recipient, amount)); + } + + // @notice Displays the amount of LINK that is available for the node operator to withdraw + // @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage + // @return The amount of withdrawable LINK on the contract + function withdrawable() external view override(OracleInterface, IWithdrawal) returns (uint256) { + return _fundsAvailable(); + } + + // @notice Forward a call to another contract + // @dev Only callable by the owner + // @param to address + // @param data to forward + function ownerForward(address to, bytes calldata data) external onlyOwner validateNotToLINK(to) { + require(to.code.length != 0, "Must forward to a contract"); + // solhint-disable-next-line avoid-low-level-calls + (bool status, ) = to.call(data); + require(status, "Forwarded call failed"); + } + + // @notice Interact with other LinkTokenReceiver contracts by calling transferAndCall + // @param to The address to transfer to. + // @param value The amount to be transferred. + // @param data The extra data to be passed to the receiving contract. + // @return success bool + function ownerTransferAndCall( + address to, + uint256 value, + bytes calldata data + ) external override onlyOwner validateAvailableFunds(value) returns (bool success) { + return i_linkToken.transferAndCall(to, value, data); + } + + // @notice Distribute funds to multiple addresses using ETH send + // to this payable function. + // @dev Array length must be equal, ETH sent must equal the sum of amounts. + // A malicious receiver could cause the distribution to revert, in which case + // it is expected that the address is removed from the list. + // @param receivers list of addresses + // @param amounts list of amounts + function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable { + require(receivers.length > 0 && receivers.length == amounts.length, "Invalid array length(s)"); + uint256 valueRemaining = msg.value; + for (uint256 i = 0; i < receivers.length; ++i) { + uint256 sendAmount = amounts[i]; + valueRemaining = valueRemaining - sendAmount; + (bool success, ) = receivers[i].call{value: sendAmount}(""); + require(success, "Address: unable to send value, recipient may have reverted"); + } + require(valueRemaining == 0, "Too much ETH sent"); + } + + // @notice Allows recipient to cancel requests sent to this oracle contract. + // Will transfer the LINK sent for the request back to the recipient address. + // @dev Given params must hash to a commitment stored on the contract in order + // for the request to be valid. Emits CancelOracleRequest event. + // @param requestId The request ID + // @param payment The amount of payment given (specified in wei) + // @param callbackFunc The requester's specified callback function selector + // @param expiration The time of the expiration for the request + function cancelOracleRequest( + bytes32 requestId, + uint256 payment, + bytes4 callbackFunc, + uint256 expiration + ) public override { + bytes31 paramsHash = _buildParamsHash(payment, msg.sender, callbackFunc, expiration); + require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); + // solhint-disable-next-line not-rely-on-time + require(expiration <= block.timestamp, "Request is not expired"); + + delete s_commitments[requestId]; + emit CancelOracleRequest(requestId); + + // Free up the escrowed funds, as we're sending them back to the requester + s_tokensInEscrow -= payment; + i_linkToken.transfer(msg.sender, payment); + } + + // @notice Allows requester to cancel requests sent to this oracle contract. + // Will transfer the LINK sent for the request back to the recipient address. + // @dev Given params must hash to a commitment stored on the contract in order + // for the request to be valid. Emits CancelOracleRequest event. + // @param nonce The nonce used to generate the request ID + // @param payment The amount of payment given (specified in wei) + // @param callbackFunc The requester's specified callback function selector + // @param expiration The time of the expiration for the request + function cancelOracleRequestByRequester( + uint256 nonce, + uint256 payment, + bytes4 callbackFunc, + uint256 expiration + ) external { + cancelOracleRequest(keccak256(abi.encodePacked(msg.sender, nonce)), payment, callbackFunc, expiration); + } + + // @notice Returns the address of the LINK token + // @dev This is the public implementation for chainlinkTokenAddress, which is + // an internal method of the ChainlinkClient contract + function getChainlinkToken() public view override returns (address) { + return address(i_linkToken); + } + + // @notice Require that the token transfer action is valid + // @dev OPERATOR_REQUEST_SELECTOR = multiword, ORACLE_REQUEST_SELECTOR = singleword + function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal pure override { + require(data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length"); + require( + funcSelector == OPERATOR_REQUEST_SELECTOR || funcSelector == ORACLE_REQUEST_SELECTOR, + "Must use whitelisted functions" + ); + } + + // @notice Verify the Oracle Request and record necessary information + // @param sender The sender of the request + // @param payment The amount of payment given (specified in wei) + // @param callbackAddress The callback address for the response + // @param callbackFunctionId The callback function ID for the response + // @param nonce The nonce sent by the requester + function _verifyAndProcessOracleRequest( + address sender, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 nonce, + uint256 dataVersion + ) private validateNotToLINK(callbackAddress) returns (bytes32 requestId, uint256 expiration) { + requestId = keccak256(abi.encodePacked(sender, nonce)); + require(s_commitments[requestId].paramsHash == 0, "Must use a unique ID"); + // solhint-disable-next-line not-rely-on-time + expiration = block.timestamp + EXPIRYTIME; + bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); + s_commitments[requestId] = Commitment(paramsHash, SafeCast.toUint8(dataVersion)); + s_tokensInEscrow = s_tokensInEscrow + payment; + return (requestId, expiration); + } + + // @notice Verify the Oracle request and unlock escrowed payment + // @param requestId The fulfillment request ID that must match the requester's + // @param payment The payment amount that will be released for the oracle (specified in wei) + // @param callbackAddress The callback address to call for fulfillment + // @param callbackFunctionId The callback function ID to use for fulfillment + // @param expiration The expiration that the node should respond by before the requester can cancel + function _verifyOracleRequestAndProcessPayment( + bytes32 requestId, + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration, + uint256 dataVersion + ) internal { + bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); + require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); + require(s_commitments[requestId].dataVersion <= SafeCast.toUint8(dataVersion), "Data versions must match"); + s_tokensInEscrow = s_tokensInEscrow - payment; + delete s_commitments[requestId]; + } + + // @notice Build the bytes31 hash from the payment, callback and expiration. + // @param payment The payment amount that will be released for the oracle (specified in wei) + // @param callbackAddress The callback address to call for fulfillment + // @param callbackFunctionId The callback function ID to use for fulfillment + // @param expiration The expiration that the node should respond by before the requester can cancel + // @return hash bytes31 + function _buildParamsHash( + uint256 payment, + address callbackAddress, + bytes4 callbackFunctionId, + uint256 expiration + ) internal pure returns (bytes31) { + return bytes31(keccak256(abi.encodePacked(payment, callbackAddress, callbackFunctionId, expiration))); + } + + // @notice Returns the LINK available in this contract, not locked in escrow + // @return uint256 LINK tokens available + function _fundsAvailable() private view returns (uint256) { + return i_linkToken.balanceOf(address(this)) - (s_tokensInEscrow - ONE_FOR_CONSISTENT_GAS_COST); + } + + // @notice concrete implementation of AuthorizedReceiver + // @return bool of whether sender is authorized + function _canSetAuthorizedSenders() internal view override returns (bool) { + return isAuthorizedSender(msg.sender) || owner() == msg.sender; + } + + // MODIFIERS + + // @dev Reverts if the first 32 bytes of the bytes array is not equal to requestId + // @param requestId bytes32 + // @param data bytes + modifier validateMultiWordResponseId(bytes32 requestId, bytes calldata data) { + require(data.length >= 32, "Response must be > 32 bytes"); + bytes32 firstDataWord; + assembly { + firstDataWord := calldataload(data.offset) + } + require(requestId == firstDataWord, "First word must be requestId"); + _; + } + + // @dev Reverts if amount requested is greater than withdrawable balance + // @param amount The given amount to compare to `s_withdrawableTokens` + modifier validateAvailableFunds(uint256 amount) { + require(_fundsAvailable() >= amount, "Amount requested is greater than withdrawable balance"); + _; + } + + // @dev Reverts if request ID does not exist + // @param requestId The given request ID to check in stored `commitments` + modifier validateRequestId(bytes32 requestId) { + require(s_commitments[requestId].paramsHash != 0, "Must have a valid requestId"); + _; + } + + // @dev Reverts if the callback address is the LINK token + // @param to The callback address + modifier validateNotToLINK(address to) { + require(to != address(i_linkToken), "Cannot call to LINK"); + _; + } + + // @dev Reverts if the target address is owned by the operator + modifier validateCallbackAddress(address callbackAddress) { + require(!s_owned[callbackAddress], "Cannot call owned contract"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol new file mode 100644 index 0000000..1503535 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Operator} from "./Operator.sol"; +import {AuthorizedForwarder} from "./AuthorizedForwarder.sol"; + +// @title Operator Factory +// @notice Creates Operator contracts for node operators +// solhint-disable gas-custom-errors +contract OperatorFactory { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address public immutable linkToken; + mapping(address => bool) private s_created; + + event OperatorCreated(address indexed operator, address indexed owner, address indexed sender); + event AuthorizedForwarderCreated(address indexed forwarder, address indexed owner, address indexed sender); + + // @param linkAddress address + constructor(address linkAddress) { + linkToken = linkAddress; + } + + string public constant typeAndVersion = "OperatorFactory 1.0.0"; + + // @notice creates a new Operator contract with the msg.sender as owner + function deployNewOperator() external returns (address) { + Operator operator = new Operator(linkToken, msg.sender); + + s_created[address(operator)] = true; + emit OperatorCreated(address(operator), msg.sender, msg.sender); + + return address(operator); + } + + // @notice creates a new Operator contract with the msg.sender as owner and a + // new Operator Forwarder with the OperatorFactory as the owner + function deployNewOperatorAndForwarder() external returns (address, address) { + Operator operator = new Operator(linkToken, msg.sender); + s_created[address(operator)] = true; + emit OperatorCreated(address(operator), msg.sender, msg.sender); + + AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, address(this), address(operator), new bytes(0)); + s_created[address(forwarder)] = true; + emit AuthorizedForwarderCreated(address(forwarder), address(this), msg.sender); + + return (address(operator), address(forwarder)); + } + + // @notice creates a new Forwarder contract with the msg.sender as owner + function deployNewForwarder() external returns (address) { + AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, msg.sender, address(0), new bytes(0)); + + s_created[address(forwarder)] = true; + emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); + + return address(forwarder); + } + + // @notice creates a new Forwarder contract with the msg.sender as owner + function deployNewForwarderAndTransferOwnership(address to, bytes calldata message) external returns (address) { + AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, msg.sender, to, message); + + s_created[address(forwarder)] = true; + emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); + + return address(forwarder); + } + + // @notice indicates whether this factory deployed an address + function created(address query) external view returns (bool) { + return s_created[query]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol new file mode 100644 index 0000000..78140d5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IAuthorizedReceiver { + function isAuthorizedSender(address sender) external view returns (bool); + + function getAuthorizedSenders() external returns (address[] memory); + + function setAuthorizedSenders(address[] calldata senders) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol new file mode 100644 index 0000000..433738d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IWithdrawal { + // @notice transfer LINK held by the contract belonging to msg.sender to + // another address + // @param recipient is the address to send the LINK to + // @param amount is the amount of LINK to send + function withdraw(address recipient, uint256 amount) external; + + // @notice query the available amount of LINK to withdraw by msg.sender + function withdrawable() external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol new file mode 100644 index 0000000..d54dc62 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; +import {Operator} from "../Operator.sol"; + +contract FactoryTest is Deployer { + function setUp() public { + _setUp(); + + vm.startPrank(ALICE); + } + + function test_DeployNewOperator_Success() public { + // Deploy a new operator using the factory. + address newOperator = s_factory.deployNewOperator(); + // Assert that the new operator was indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + } + + function test_DeployNewOperatorAndForwarder_Success() public { + // Deploy both a new operator and a new forwarder using the factory. + (address newOperator, address newForwarder) = s_factory.deployNewOperatorAndForwarder(); + + // Assert that the new operator and the new forwarder were indeed created by the factory. + assertTrue(s_factory.created(newOperator)); + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed operator. + require(Operator(newOperator).owner() == ALICE); + + //Operator to accept ownership + vm.startPrank(newOperator); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + // Ensure that the newly deployed operator is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == newOperator, "operator is not the owner"); + } + + function test_DeployNewForwarder_Success() public { + // Deploy a new forwarder using the factory. + address newForwarder = s_factory.deployNewForwarder(); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is the owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + } + + function test_DeployNewForwarderAndTransferOwnership_Success() public { + // Deploy a new forwarder with a proposal to transfer its ownership to Bob. + address newForwarder = s_factory.deployNewForwarderAndTransferOwnership(BOB, new bytes(0)); + // Assert that the new forwarder was indeed created by the factory. + assertTrue(s_factory.created(newForwarder)); + // Ensure that Alice is still the current owner of the newly deployed forwarder. + require(AuthorizedForwarder(newForwarder).owner() == ALICE); + + // Only proposed owner can call acceptOwnership() + vm.expectRevert("Must be proposed owner"); + AuthorizedForwarder(newForwarder).acceptOwnership(); + + vm.startPrank(BOB); + // Let Bob accept the ownership. + AuthorizedForwarder(newForwarder).acceptOwnership(); + // Ensure that Bob is now the owner of the forwarder after the transfer. + require(AuthorizedForwarder(newForwarder).owner() == BOB); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol new file mode 100644 index 0000000..ba6ce1c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Deployer} from "./testhelpers/Deployer.t.sol"; +import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; + +contract ForwarderTest is Deployer { + AuthorizedForwarder internal s_forwarder; + + function setUp() public { + _setUp(); + + vm.prank(ALICE); + s_forwarder = AuthorizedForwarder(s_factory.deployNewForwarder()); + } + + function test_SetAuthorizedSenders_Success() public { + address[] memory senders; + + // Expect a revert when trying to set an empty list of authorized senders + vm.expectRevert("Cannot set authorized senders"); + s_forwarder.setAuthorizedSenders(senders); + + vm.prank(ALICE); + // Expect a revert because the sender list is empty + vm.expectRevert("Must have at least 1 sender"); + s_forwarder.setAuthorizedSenders(senders); + + // Create a list with two identical sender addresses + senders = new address[](2); + senders[0] = SENDER_1; + senders[1] = SENDER_1; + + vm.prank(ALICE); + // Expect a revert because the sender list has duplicates + vm.expectRevert("Must not have duplicate senders"); + s_forwarder.setAuthorizedSenders(senders); + + // Set the second sender to a different address + senders[1] = SENDER_2; + + vm.prank(ALICE); + // Update the authorized senders list + s_forwarder.setAuthorizedSenders(senders); + + // Check if both SENDER_1 and SENDER_2 are now authorized + assertTrue(s_forwarder.isAuthorizedSender(SENDER_1)); + assertTrue(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Fetch the authorized senders and verify they match the set addresses + address[] memory returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + require(returnedSenders[1] == senders[1]); + + // Create a new list with only SENDER_3 + senders = new address[](1); + senders[0] = SENDER_3; + + // Prank 'alice' and update the authorized senders to just SENDER_3 + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + + // Ensure SENDER_1 and SENDER_2 are no longer authorized + assertFalse(s_forwarder.isAuthorizedSender(SENDER_1)); + assertFalse(s_forwarder.isAuthorizedSender(SENDER_2)); + + // Check that SENDER_3 is now the only authorized sender + assertTrue(s_forwarder.isAuthorizedSender(SENDER_3)); + returnedSenders = s_forwarder.getAuthorizedSenders(); + require(returnedSenders[0] == senders[0]); + } + + function test_Forward_Success(uint256 _value) public { + _addSenders(); + + vm.expectRevert("Not authorized sender"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.forward(address(s_link), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.forward(address(0), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.forward(address(s_mockReceiver), new bytes(0)); + + vm.prank(SENDER_1); + vm.expectRevert("test revert message"); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("revertMessage()")); + + vm.prank(SENDER_1); + s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("receiveData(uint256)", _value)); + + require(s_mockReceiver.getValue() == _value); + } + + function test_MultiForward_Success(uint256 _value1, uint256 _value2) public { + _addSenders(); + + address[] memory tos; + bytes[] memory datas; + + vm.expectRevert("Not authorized sender"); + s_forwarder.multiForward(tos, datas); + + tos = new address[](2); + datas = new bytes[](1); + + vm.prank(SENDER_1); + vm.expectRevert("Arrays must have the same length"); + s_forwarder.multiForward(tos, datas); + + datas = new bytes[](2); + + vm.prank(SENDER_1); + vm.expectRevert("Must forward to a contract"); + s_forwarder.multiForward(tos, datas); + + tos[0] = address(s_mockReceiver); + tos[1] = address(s_link); + + vm.prank(SENDER_1); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.multiForward(tos, datas); + + datas[0] = abi.encodeWithSignature("receiveData(uint256)", _value1); + datas[1] = abi.encodeWithSignature("receiveData(uint256)", _value2); + + vm.prank(SENDER_1); + vm.expectRevert("Cannot forward to Link token"); + s_forwarder.multiForward(tos, datas); + + tos[1] = address(s_mockReceiver); + + vm.prank(SENDER_1); + s_forwarder.multiForward(tos, datas); + + require(s_mockReceiver.getValue() == _value2); + } + + function test_OwnerForward_Success() public { + vm.expectRevert("Only callable by owner"); + s_forwarder.ownerForward(address(0), new bytes(0)); + + vm.prank(ALICE); + vm.expectRevert("Forwarded call reverted without reason"); + s_forwarder.ownerForward(address(s_link), new bytes(0)); + + vm.prank(ALICE); + s_forwarder.ownerForward(address(s_link), abi.encodeWithSignature("balanceOf(address)", address(0))); + } + + function test_TransferOwnershipWithMessage_Success() public { + vm.prank(BOB); + vm.expectRevert("Only callable by owner"); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.prank(ALICE); + s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); + + vm.expectRevert("Must be proposed owner"); + s_forwarder.acceptOwnership(); + + vm.prank(BOB); + s_forwarder.acceptOwnership(); + + require(s_forwarder.owner() == BOB); + } + + function _addSenders() internal { + address[] memory senders = new address[](3); + senders[0] = SENDER_1; + senders[1] = SENDER_2; + senders[2] = SENDER_3; + + vm.prank(ALICE); + s_forwarder.setAuthorizedSenders(senders); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol new file mode 100644 index 0000000..6c4a7c2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Operator} from "../Operator.sol"; +import {Callback} from "./testhelpers/Callback.sol"; +import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; +import {Deployer} from "./testhelpers/Deployer.t.sol"; + +contract OperatorTest is Deployer { + ChainlinkClientHelper private s_client; + Callback private s_callback; + Operator private s_operator; + + function setUp() public { + _setUp(); + s_client = new ChainlinkClientHelper(address(s_link)); + + address[] memory auth = new address[](1); + auth[0] = address(this); + s_operator = new Operator(address(s_link), address(this)); + s_operator.setAuthorizedSenders(auth); + + s_callback = new Callback(address(s_operator)); + } + + function test_SendRequest_Success(uint96 payment) public { + vm.assume(payment > 0); + deal(address(s_link), address(s_client), payment); + // We're going to cancel one request and fulfill the other + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // 1 payment in escrow + // Client has zero link + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), payment); + } + + function test_SendRequestAndCancelRequest_Success(uint96 payment) public { + vm.assume(payment > 1); + payment /= payment; + + deal(address(s_link), address(s_client), 2 * payment); + + // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + + // We're going to cancel one request and fulfill the other + bytes32 requestId = s_client.sendRequest(address(s_operator), payment); + bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); + + // Nothing withdrawable + // Operator now has the 2 payments in escrow + // Client has zero payments + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Fulfill one request + uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_client), + s_client.FULFILL_SELECTOR(), + expiration, + bytes32(hex"01") + ); + // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); + assertEq(s_link.balanceOf(address(s_client)), 0); + + // Advance time so we can cancel + vm.warp(expiration + 1); + s_client.cancelRequest(requestIdToCancel, payment, expiration); + + // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable + assertEq(s_operator.withdrawable(), payment); + assertEq(s_link.balanceOf(address(s_operator)), payment); + assertEq(s_link.balanceOf(address(s_client)), payment); + + // Withdraw the remaining payment + s_operator.withdraw(address(s_client), payment); + + // End state is exactly the same as the initial state. + assertEq(s_operator.withdrawable(), 0); + assertEq(s_link.balanceOf(address(s_operator)), 0); + assertEq(s_link.balanceOf(address(s_client)), 2 * payment); + } + + function test_OracleRequest_Success() public { + // Define some mock values + bytes32 specId = keccak256("testSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 0; + uint256 dataVersion = 1; + bytes memory data = ""; + + uint256 initialLinkBalance = s_link.balanceOf(address(s_operator)); + uint256 payment = 1 ether; // Mock payment value + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), ALICE, payment); + assertEq(s_link.balanceOf(ALICE), 1 ether, "balance update failed"); + + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + data + ) + ); + + // Check that the LINK tokens were transferred to the Operator contract + assertEq(s_link.balanceOf(address(s_operator)), initialLinkBalance + payment); + // No withdrawable LINK as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore); + } + + function test_FulfillOracleRequest_Success() public { + // This test file is the callback target and actual sender contract + // so we should enable it to set Authorised senders to itself + address[] memory senders = new address[](2); + senders[0] = address(this); + senders[0] = BOB; + + s_operator.setAuthorizedSenders(senders); + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForFulfill"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 1; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + // Convert bytes to bytes32 + bytes32 data = bytes32(keccak256(dataBytes)); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + address(this), + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // Fulfill the request using the operator + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + vm.prank(BOB); + s_operator.fulfillOracleRequest(requestId, payment, address(s_callback), callbackFunctionId, expiration, data); + + assertEq(s_callback.getCallbacksReceived(), 1, "Oracle request was not fulfilled"); + + // Withdrawable balance + assertEq(s_operator.withdrawable(), withdrawableBefore + payment, "Internal accounting not updated correctly"); + } + + function test_CancelOracleRequest_Success() public { + // Define mock values for creating a new oracle request + bytes32 specId = keccak256("testSpecForCancel"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 2; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + uint256 withdrawableBefore = s_operator.withdrawable(); + + // Send LINK tokens to the Operator contract using `transferAndCall` + deal(address(s_link), BOB, payment); + vm.prank(BOB); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + BOB, + payment, + specId, + BOB, + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + // No withdrawable balance as it's all locked + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + + bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); + + vm.startPrank(ALICE); + vm.expectRevert(bytes("Params do not match request ID")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.startPrank(BOB); + vm.expectRevert(bytes("Request is not expired")); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + vm.warp(expiration); + s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); + + // Check if the LINK tokens were refunded to the sender (bob in this case) + assertEq(s_link.balanceOf(BOB), 1 ether, "Oracle request was not canceled properly"); + + assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); + } + + function test_NotAuthorizedSender_Revert() public { + bytes32 specId = keccak256("unauthorizedFulfillSpec"); + bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); + uint256 nonce = 5; + uint256 dataVersion = 1; + bytes memory dataBytes = ""; + uint256 payment = 1 ether; + uint256 expiration = block.timestamp + 5 minutes; + + deal(address(s_link), ALICE, payment); + vm.prank(ALICE); + s_link.transferAndCall( + address(s_operator), + payment, + abi.encodeWithSignature( + "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", + ALICE, + payment, + specId, + address(s_callback), + callbackFunctionId, + nonce, + dataVersion, + dataBytes + ) + ); + + bytes32 requestId = keccak256(abi.encodePacked(ALICE, nonce)); + + vm.prank(BOB); + vm.expectRevert(bytes("Not authorized sender")); + s_operator.fulfillOracleRequest( + requestId, + payment, + address(s_callback), + callbackFunctionId, + expiration, + bytes32(keccak256(dataBytes)) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol new file mode 100644 index 0000000..7004b53 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Consumer} from "./Consumer.sol"; + +contract BasicConsumer is Consumer { + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol new file mode 100644 index 0000000..3d72571 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract Callback { + address private s_operator; + uint256 private s_callbacksReceived = 0; + + constructor(address _operator) { + s_operator = _operator; + } + + // Callback function for oracle request fulfillment + function callback(bytes32) public { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == s_operator, "Only Operator can call this function"); + s_callbacksReceived += 1; + } + + function getCallbacksReceived() public view returns (uint256) { + return s_callbacksReceived; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol new file mode 100644 index 0000000..9b6ba6b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; + +contract ChainlinkClientHelper is ChainlinkClient { + bytes4 public constant FULFILL_SELECTOR = this.fulfill.selector; + + constructor(address link) { + _setChainlinkToken(link); + } + + function sendRequest(address op, uint256 payment) external returns (bytes32) { + return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILL_SELECTOR), payment); + } + + function cancelRequest(bytes32 requestId, uint256 payment, uint256 expiration) external { + _cancelChainlinkRequest(requestId, payment, this.fulfill.selector, expiration); + } + + function fulfill(bytes32) external {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol new file mode 100644 index 0000000..dba5d40 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol @@ -0,0 +1,127 @@ +pragma solidity ^0.8.0; + +import {ChainlinkClient, Chainlink} from "../../../ChainlinkClient.sol"; + +/** + * @title The Chainlinked contract + * @notice Contract writers can inherit this contract in order to create requests for the + * Chainlink network. ChainlinkClient is an alias of the Chainlinked contract. + */ +// solhint-disable +contract Chainlinked is ChainlinkClient { + /** + * @notice Creates a request that can hold additional parameters + * @param _specId The Job Specification ID that the request will be created for + * @param _callbackAddress The callback address that the response will be sent to + * @param _callbackFunctionSignature The callback function signature to use for the callback address + * @return A Chainlink Request struct in memory + */ + function newRequest( + bytes32 _specId, + address _callbackAddress, + bytes4 _callbackFunctionSignature + ) internal pure returns (Chainlink.Request memory) { + return _buildChainlinkRequest(_specId, _callbackAddress, _callbackFunctionSignature); + } + + /** + * @notice Creates a Chainlink request to the stored oracle address + * @dev Calls `sendChainlinkRequestTo` with the stored oracle address + * @param _req The initialized Chainlink Request + * @param _payment The amount of LINK to send for the request + * @return The request ID + */ + function chainlinkRequest(Chainlink.Request memory _req, uint256 _payment) internal returns (bytes32) { + return _sendChainlinkRequest(_req, _payment); + } + + /** + * @notice Creates a Chainlink request to the specified oracle address + * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to + * send LINK which creates a request on the target oracle contract. + * Emits ChainlinkRequested event. + * @param _oracle The address of the oracle for the request + * @param _req The initialized Chainlink Request + * @param _payment The amount of LINK to send for the request + * @return requestId The request ID + */ + function chainlinkRequestTo( + address _oracle, + Chainlink.Request memory _req, + uint256 _payment + ) internal returns (bytes32 requestId) { + return _sendChainlinkRequestTo(_oracle, _req, _payment); + } + + /** + * @notice Sets the stored oracle address + * @param _oracle The address of the oracle contract + */ + function setOracle(address _oracle) internal { + _setChainlinkOracle(_oracle); + } + + /** + * @notice Sets the LINK token address + * @param _link The address of the LINK token contract + */ + function setLinkToken(address _link) internal { + _setChainlinkToken(_link); + } + + /** + * @notice Retrieves the stored address of the LINK token + * @return The address of the LINK token + */ + function chainlinkToken() internal view returns (address) { + return _chainlinkTokenAddress(); + } + + /** + * @notice Retrieves the stored address of the oracle contract + * @return The address of the oracle contract + */ + function oracleAddress() internal view returns (address) { + return _chainlinkOracleAddress(); + } + + /** + * @notice Ensures that the fulfillment is valid for this contract + * @dev Use if the contract developer prefers methods instead of modifiers for validation + * @param _requestId The request ID for fulfillment + */ + function fulfillChainlinkRequest( + bytes32 _requestId + ) + internal + recordChainlinkFulfillment(_requestId) // solhint-disable-next-line no-empty-blocks + {} + + /** + * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS + * @dev Accounts for subnodes having different resolvers + * @param _ens The address of the ENS contract + * @param _node The ENS node hash + */ + function setChainlinkWithENS(address _ens, bytes32 _node) internal { + _useChainlinkWithENS(_ens, _node); + } + + /** + * @notice Sets the stored oracle contract with the address resolved by ENS + * @dev This may be called on its own as long as `setChainlinkWithENS` has been called previously + */ + function setOracleWithENS() internal { + _updateChainlinkOracleWithENS(); + } + + /** + * @notice Allows for a request which was created on another contract to be fulfilled + * on this contract + * @param _oracle The address of the oracle contract that will fulfill the request + * @param _requestId The request ID used for the response + */ + function addExternalRequest(address _oracle, bytes32 _requestId) internal { + _addChainlinkExternalRequest(_oracle, _requestId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol new file mode 100644 index 0000000..3ec32dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; + +contract Consumer is ChainlinkClient { + using Chainlink for Chainlink.Request; + + bytes32 internal s_specId; + bytes32 internal s_currentPrice; + + event RequestFulfilled( + bytes32 indexed requestId, // User-defined ID + bytes32 indexed price + ); + + function requestEthereumPrice(string memory _currency, uint256 _payment) public { + requestEthereumPriceByCallback(_currency, _payment, address(this)); + } + + function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public { + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, _callback, this.fulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + string[] memory path = new string[](1); + path[0] = _currency; + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); + } + + function cancelRequest( + address _oracle, + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public { + ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); + requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); + } + + function withdrawLink() public { + LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); + // solhint-disable-next-line gas-custom-errors + require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); + } + + function addExternalRequest(address _oracle, bytes32 _requestId) external { + _addChainlinkExternalRequest(_oracle, _requestId); + } + + function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { + emit RequestFulfilled(_requestId, _price); + s_currentPrice = _price; + } + + function getCurrentPrice() public view returns (bytes32) { + return s_currentPrice; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol new file mode 100644 index 0000000..da746c7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +import {MockReceiver} from "./MockReceiver.sol"; +import {AuthorizedForwarder} from "../../AuthorizedForwarder.sol"; +import {Operator} from "../../Operator.sol"; +import {OperatorFactory} from "../../OperatorFactory.sol"; +import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; + +abstract contract Deployer is Test { + OperatorFactory internal s_factory; + LinkToken internal s_link; + MockReceiver internal s_mockReceiver; + + address internal constant ALICE = address(0x101); + address internal constant BOB = address(0x102); + address internal constant SENDER_1 = address(0x103); + address internal constant SENDER_2 = address(0x104); + address internal constant SENDER_3 = address(0x105); + + function _setUp() internal { + _deploy(); + } + + function _deploy() internal { + s_link = new LinkToken(); + s_factory = new OperatorFactory(address(s_link)); + + s_mockReceiver = new MockReceiver(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol new file mode 100644 index 0000000..f278791 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; +import {OracleInterface} from "../../../interfaces/OracleInterface.sol"; + +/* solhint-disable no-empty-blocks */ +contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { + function cancelOracleRequest(bytes32, uint256, bytes4, uint256) external override {} + function fulfillOracleRequest(bytes32, uint256, address, bytes4, uint256, bytes32) external override returns (bool) {} + function getAuthorizationStatus(address) external pure returns (bool) { + return false; + } + function onTokenTransfer(address, uint256, bytes calldata) external pure {} + function oracleRequest( + address, + uint256, + bytes32, + address, + bytes4, + uint256, + uint256, + bytes calldata + ) external override {} + function setFulfillmentPermission(address, bool) external {} + function withdraw(address, uint256) external override {} + function withdrawable() external view override returns (uint256) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol new file mode 100644 index 0000000..0291020 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Consumer} from "./Consumer.sol"; +import {Chainlink} from "../../../Chainlink.sol"; + +contract GasGuzzlingConsumer is Consumer { + using Chainlink for Chainlink.Request; + + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; + } + + function gassyRequestEthereumPrice(uint256 _payment) public { + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyFulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + string[] memory path = new string[](1); + path[0] = "USD"; + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); + } + + function gassyFulfill(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { + while (true) {} + } + + function gassyMultiWordRequest(uint256 _payment) public { + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyMultiWordFulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + string[] memory path = new string[](1); + path[0] = "USD"; + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); + } + + function gassyMultiWordFulfill(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { + while (true) {} + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol new file mode 100644 index 0000000..722362b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.8.0; + +// GetterSetter is a contract to aid debugging and testing during development. +// solhint-disable +contract GetterSetter { + bytes32 private s_getBytes32; + uint256 private s_getUint256; + bytes32 private s_requestId; + bytes private s_getBytes; + + event SetBytes32(address indexed from, bytes32 indexed value); + event SetUint256(address indexed from, uint256 indexed value); + event SetBytes(address indexed from, bytes value); + + event Output(bytes32 b32, uint256 u256, bytes32 b322); + + function setBytes32(bytes32 _value) public { + s_getBytes32 = _value; + emit SetBytes32(msg.sender, _value); + } + + function requestedBytes32(bytes32 _requestId, bytes32 _value) public { + s_requestId = _requestId; + setBytes32(_value); + } + + function setBytes(bytes memory _value) public { + s_getBytes = _value; + emit SetBytes(msg.sender, _value); + } + + function getBytes() public view returns (bytes memory _value) { + return s_getBytes; + } + + function requestedBytes(bytes32 _requestId, bytes memory _value) public { + s_requestId = _requestId; + setBytes(_value); + } + + function setUint256(uint256 _value) public { + s_getUint256 = _value; + emit SetUint256(msg.sender, _value); + } + + function requestedUint256(bytes32 _requestId, uint256 _value) public { + s_requestId = _requestId; + setUint256(_value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol new file mode 100644 index 0000000..11c863f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol @@ -0,0 +1,67 @@ +pragma solidity ^0.8.0; + +import {CBORChainlink as CBOR_Chainlink} from "../../../vendor/CBORChainlink.sol"; +import {BufferChainlink as Buffer_Chainlink} from "../../../vendor/BufferChainlink.sol"; + +// solhint-disable +library MaliciousChainlink { + using CBOR_Chainlink for Buffer_Chainlink.buffer; + + struct Request { + bytes32 specId; + address callbackAddress; + bytes4 callbackFunctionId; + uint256 nonce; + Buffer_Chainlink.buffer buf; + } + + struct WithdrawRequest { + bytes32 specId; + address callbackAddress; + bytes4 callbackFunctionId; + uint256 nonce; + Buffer_Chainlink.buffer buf; + } + + function initializeWithdraw( + WithdrawRequest memory self, + bytes32 _specId, + address _callbackAddress, + bytes4 _callbackFunction + ) internal pure returns (MaliciousChainlink.WithdrawRequest memory) { + Buffer_Chainlink.init(self.buf, 128); + self.specId = _specId; + self.callbackAddress = _callbackAddress; + self.callbackFunctionId = _callbackFunction; + return self; + } + + function add(Request memory self, string memory _key, string memory _value) internal pure { + self.buf.encodeString(_key); + self.buf.encodeString(_value); + } + + function addBytes(Request memory self, string memory _key, bytes memory _value) internal pure { + self.buf.encodeString(_key); + self.buf.encodeBytes(_value); + } + + function addInt(Request memory self, string memory _key, int256 _value) internal pure { + self.buf.encodeString(_key); + self.buf.encodeInt(_value); + } + + function addUint(Request memory self, string memory _key, uint256 _value) internal pure { + self.buf.encodeString(_key); + self.buf.encodeUInt(_value); + } + + function addStringArray(Request memory self, string memory _key, string[] memory _values) internal pure { + self.buf.encodeString(_key); + self.buf.startArray(); + for (uint256 i = 0; i < _values.length; i++) { + self.buf.encodeString(_values[i]); + } + self.buf.endSequence(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol new file mode 100644 index 0000000..989c39c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol @@ -0,0 +1,116 @@ +pragma solidity ^0.8.0; + +import {MaliciousChainlink} from "./MaliciousChainlink.sol"; +import {Chainlinked, Chainlink} from "./Chainlinked.sol"; +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; + +// solhint-disable +contract MaliciousChainlinked is Chainlinked { + using MaliciousChainlink for MaliciousChainlink.Request; + using MaliciousChainlink for MaliciousChainlink.WithdrawRequest; + using Chainlink for Chainlink.Request; + + uint256 private s_maliciousRequests = 1; + mapping(bytes32 => address) private s_maliciousPendingRequests; + + function newWithdrawRequest( + bytes32 _specId, + address _callbackAddress, + bytes4 _callbackFunction + ) internal pure returns (MaliciousChainlink.WithdrawRequest memory) { + MaliciousChainlink.WithdrawRequest memory req; + return req.initializeWithdraw(_specId, _callbackAddress, _callbackFunction); + } + + function chainlinkTargetRequest( + address _target, + Chainlink.Request memory _req, + uint256 _amount + ) internal returns (bytes32 requestId) { + requestId = keccak256(abi.encodePacked(_target, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); + emit ChainlinkRequested(requestId); + LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); + require( + link.transferAndCall(oracleAddress(), _amount, encodeTargetRequest(_req)), + "Unable to transferAndCall to oracle" + ); + s_maliciousRequests += 1; + + return requestId; + } + + function chainlinkPriceRequest(Chainlink.Request memory _req, uint256 _amount) internal returns (bytes32 requestId) { + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); + emit ChainlinkRequested(requestId); + LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); + require( + link.transferAndCall(oracleAddress(), _amount, encodePriceRequest(_req)), + "Unable to transferAndCall to oracle" + ); + s_maliciousRequests += 1; + + return requestId; + } + + function chainlinkWithdrawRequest( + MaliciousChainlink.WithdrawRequest memory _req, + uint256 _wei + ) internal returns (bytes32 requestId) { + requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); + _req.nonce = s_maliciousRequests; + s_maliciousPendingRequests[requestId] = oracleAddress(); + emit ChainlinkRequested(requestId); + LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); + require( + link.transferAndCall(oracleAddress(), _wei, encodeWithdrawRequest(_req)), + "Unable to transferAndCall to oracle" + ); + s_maliciousRequests += 1; + return requestId; + } + + function encodeWithdrawRequest(MaliciousChainlink.WithdrawRequest memory _req) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + bytes4(keccak256("withdraw(address,uint256)")), + _req.callbackAddress, + _req.callbackFunctionId, + _req.nonce, + _req.buf.buf + ); + } + + function encodeTargetRequest(Chainlink.Request memory _req) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + bytes4(keccak256("oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)")), + 0, // overridden by onTokenTransfer + 0, // overridden by onTokenTransfer + _req.id, + _req.callbackAddress, + _req.callbackFunctionId, + _req.nonce, + 1, + _req.buf.buf + ); + } + + function encodePriceRequest(Chainlink.Request memory _req) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + bytes4(keccak256("oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)")), + 0, // overridden by onTokenTransfer + 2000000000000000000, // overridden by onTokenTransfer + _req.id, + _req.callbackAddress, + _req.callbackFunctionId, + _req.nonce, + 1, + _req.buf.buf + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol new file mode 100644 index 0000000..bd731c7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol @@ -0,0 +1,49 @@ +pragma solidity ^0.8.0; + +import {Chainlinked, Chainlink} from "./Chainlinked.sol"; + +// solhint-disable +contract MaliciousConsumer is Chainlinked { + uint256 private constant ORACLE_PAYMENT = 1 ether; + uint256 private s_expiration; + + constructor(address _link, address _oracle) payable { + setLinkToken(_link); + setOracle(_oracle); + } + + fallback() external payable {} // solhint-disable-line no-empty-blocks + + function requestData(bytes32 _id, bytes memory _callbackFunc) public { + Chainlink.Request memory req = newRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); + s_expiration = block.timestamp + 5 minutes; + chainlinkRequest(req, ORACLE_PAYMENT); + } + + function assertFail(bytes32, bytes32) public pure { + assert(1 == 2); + } + + function cancelRequestOnFulfill(bytes32 _requestId, bytes32) public { + _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); + } + + function remove() public { + selfdestruct(payable(address(0))); + } + + function stealEthCall(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { + (bool success, ) = address(this).call{value: 100}(""); + require(success, "Call failed"); + } + + function stealEthSend(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { + require(payable(address(this)).send(100), "Send failed"); + } + + function stealEthTransfer(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { + payable(address(this)).transfer(100); + } + + function doesNothing(bytes32, bytes32) public pure {} // solhint-disable-line no-empty-blocks +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol new file mode 100644 index 0000000..93af16f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainlinkClient} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; + +contract MaliciousMultiWordConsumer is ChainlinkClient { + uint256 private constant ORACLE_PAYMENT = 1 ether; + uint256 private s_expiration; + + constructor(address _link, address _oracle) payable { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + } + + receive() external payable {} // solhint-disable-line no-empty-blocks + + function requestData(bytes32 _id, bytes memory _callbackFunc) public { + Chainlink.Request memory req = _buildChainlinkRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); + s_expiration = block.timestamp + 5 minutes; // solhint-disable-line not-rely-on-time + _sendChainlinkRequest(req, ORACLE_PAYMENT); + } + + function assertFail(bytes32, bytes memory) public pure { + assert(1 == 2); + } + + function cancelRequestOnFulfill(bytes32 _requestId, bytes memory) public { + _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); + } + + function remove() public { + selfdestruct(payable(address(0))); + } + + function stealEthCall(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { + (bool success, ) = address(this).call{value: 100}(""); // solhint-disable-line avoid-call-value + // solhint-disable-next-line gas-custom-errors + require(success, "Call failed"); + } + + function stealEthSend(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { + // solhint-disable-next-line check-send-result + bool success = payable(address(this)).send(100); // solhint-disable-line multiple-sends + // solhint-disable-next-line gas-custom-errors + require(success, "Send failed"); + } + + function stealEthTransfer(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { + payable(address(this)).transfer(100); + } + + function doesNothing(bytes32, bytes memory) public pure {} // solhint-disable-line no-empty-blocks +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol new file mode 100644 index 0000000..c01c8a6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol @@ -0,0 +1,52 @@ +pragma solidity ^0.8.0; + +import {MaliciousChainlink} from "./MaliciousChainlink.sol"; +import {MaliciousChainlinked, Chainlink} from "./MaliciousChainlinked.sol"; +import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; + +contract MaliciousRequester is MaliciousChainlinked { + uint256 private constant ORACLE_PAYMENT = 1 ether; + uint256 private s_expiration; + + constructor(address _link, address _oracle) { + setLinkToken(_link); + setOracle(_oracle); + } + + function maliciousWithdraw() public { + MaliciousChainlink.WithdrawRequest memory req = newWithdrawRequest( + "specId", + address(this), + this.doesNothing.selector + ); + chainlinkWithdrawRequest(req, ORACLE_PAYMENT); + } + + function request(bytes32 _id, address _target, bytes memory _callbackFunc) public returns (bytes32 requestId) { + Chainlink.Request memory req = newRequest(_id, _target, bytes4(keccak256(_callbackFunc))); + s_expiration = block.timestamp + 5 minutes; // solhint-disable-line not-rely-on-time + return chainlinkRequest(req, ORACLE_PAYMENT); + } + + function maliciousPrice(bytes32 _id) public returns (bytes32 requestId) { + Chainlink.Request memory req = newRequest(_id, address(this), this.doesNothing.selector); + return chainlinkPriceRequest(req, ORACLE_PAYMENT); + } + + function maliciousTargetConsumer(address _target) public returns (bytes32 requestId) { + Chainlink.Request memory req = newRequest("specId", _target, bytes4(keccak256("fulfill(bytes32,bytes32)"))); + return chainlinkTargetRequest(_target, req, ORACLE_PAYMENT); + } + + function maliciousRequestCancel(bytes32 _id, bytes memory _callbackFunc) public { + ChainlinkRequestInterface oracle = ChainlinkRequestInterface(oracleAddress()); + oracle.cancelOracleRequest( + request(_id, address(this), _callbackFunc), + ORACLE_PAYMENT, + this.maliciousRequestCancel.selector, + s_expiration + ); + } + + function doesNothing(bytes32, bytes32) public pure {} // solhint-disable-line no-empty-blocks +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol new file mode 100644 index 0000000..38a0c3d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract MockReceiver { + uint256 private s_value; + + function receiveData(uint256 _value) public { + s_value = _value; + } + + function revertMessage() public pure { + // solhint-disable-next-line gas-custom-errors + revert("test revert message"); + } + + function getValue() external view returns (uint256) { + return s_value; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol new file mode 100644 index 0000000..b3fdfcb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol @@ -0,0 +1,145 @@ +pragma solidity ^0.8.0; + +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../Chainlink.sol"; + +contract MultiWordConsumer is ChainlinkClient { + using Chainlink for Chainlink.Request; + + bytes32 internal s_specId; + bytes internal s_currentPrice; + + bytes32 private s_usd; + bytes32 private s_eur; + bytes32 private s_jpy; + + uint256 private s_usdInt; + uint256 private s_eurInt; + uint256 private s_jpyInt; + + event RequestFulfilled( + bytes32 indexed requestId, // User-defined ID + bytes indexed price + ); + + event RequestMultipleFulfilled(bytes32 indexed requestId, bytes32 indexed usd, bytes32 indexed eur, bytes32 jpy); + + event RequestMultipleFulfilledWithCustomURLs( + bytes32 indexed requestId, + uint256 indexed usd, + uint256 indexed eur, + uint256 jpy + ); + + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; + } + + function setSpecID(bytes32 _specId) public { + s_specId = _specId; + } + + function requestEthereumPrice(string memory, uint256 _payment) public { + Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillBytes.selector); + _sendOperatorRequest(req, _payment); + } + + function requestMultipleParameters(string memory, uint256 _payment) public { + Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillMultipleParameters.selector); + _sendOperatorRequest(req, _payment); + } + + function requestMultipleParametersWithCustomURLs( + string memory _urlUSD, + string memory _pathUSD, + string memory _urlEUR, + string memory _pathEUR, + string memory _urlJPY, + string memory _pathJPY, + uint256 _payment + ) public { + Chainlink.Request memory req = _buildOperatorRequest( + s_specId, + this.fulfillMultipleParametersWithCustomURLs.selector + ); + req._add("urlUSD", _urlUSD); + req._add("pathUSD", _pathUSD); + req._add("urlEUR", _urlEUR); + req._add("pathEUR", _pathEUR); + req._add("urlJPY", _urlJPY); + req._add("pathJPY", _pathJPY); + _sendOperatorRequest(req, _payment); + } + + function cancelRequest( + address _oracle, + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public { + ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); + requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); + } + + function withdrawLink() public { + LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); + // solhint-disable-next-line gas-custom-errors + require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); + } + + function addExternalRequest(address _oracle, bytes32 _requestId) external { + _addChainlinkExternalRequest(_oracle, _requestId); + } + + function fulfillMultipleParameters( + bytes32 _requestId, + bytes32 _usd, + bytes32 _eur, + bytes32 _jpy + ) public recordChainlinkFulfillment(_requestId) { + emit RequestMultipleFulfilled(_requestId, _usd, _eur, _jpy); + s_usd = _usd; + s_eur = _eur; + s_jpy = _jpy; + } + + function fulfillMultipleParametersWithCustomURLs( + bytes32 _requestId, + uint256 _usd, + uint256 _eur, + uint256 _jpy + ) public recordChainlinkFulfillment(_requestId) { + emit RequestMultipleFulfilledWithCustomURLs(_requestId, _usd, _eur, _jpy); + s_usdInt = _usd; + s_eurInt = _eur; + s_jpyInt = _jpy; + } + + function fulfillBytes(bytes32 _requestId, bytes memory _price) public recordChainlinkFulfillment(_requestId) { + emit RequestFulfilled(_requestId, _price); + s_currentPrice = _price; + } + + function publicGetNextRequestCount() external view returns (uint256) { + return _getNextRequestCount(); + } + + function getCurrentPrice() public view returns (bytes memory _value) { + return s_currentPrice; + } + + function usd() public view returns (bytes32 _value) { + return s_usd; + } + + function eur() public view returns (bytes32 _value) { + return s_eur; + } + + function jpy() public view returns (bytes32 _value) { + return s_jpy; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol new file mode 100644 index 0000000..93102d1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {OwnerIsCreator} from "./OwnerIsCreator.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @title The AuthorizedCallers contract +/// @notice A contract that manages multiple authorized callers. Enables restricting access to certain functions to a set of addresses. +contract AuthorizedCallers is OwnerIsCreator { + using EnumerableSet for EnumerableSet.AddressSet; + + event AuthorizedCallerAdded(address caller); + event AuthorizedCallerRemoved(address caller); + + error UnauthorizedCaller(address caller); + error ZeroAddressNotAllowed(); + + /// @notice Update args for changing the authorized callers + struct AuthorizedCallerArgs { + address[] addedCallers; + address[] removedCallers; + } + + /// @dev Set of authorized callers + EnumerableSet.AddressSet internal s_authorizedCallers; + + /// @param authorizedCallers the authorized callers to set + constructor(address[] memory authorizedCallers) { + _applyAuthorizedCallerUpdates( + AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + } + + /// @return authorizedCallers Returns all authorized callers + function getAllAuthorizedCallers() external view returns (address[] memory) { + return s_authorizedCallers.values(); + } + + /// @notice Updates the list of authorized callers + /// @param authorizedCallerArgs Callers to add and remove. Removals are performed first. + function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyOwner { + _applyAuthorizedCallerUpdates(authorizedCallerArgs); + } + + /// @notice Updates the list of authorized callers + /// @param authorizedCallerArgs Callers to add and remove. Removals are performed first. + function _applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) internal { + address[] memory removedCallers = authorizedCallerArgs.removedCallers; + for (uint256 i = 0; i < removedCallers.length; ++i) { + address caller = removedCallers[i]; + + if (s_authorizedCallers.remove(caller)) { + emit AuthorizedCallerRemoved(caller); + } + } + + address[] memory addedCallers = authorizedCallerArgs.addedCallers; + for (uint256 i = 0; i < addedCallers.length; ++i) { + address caller = addedCallers[i]; + + if (caller == address(0)) { + revert ZeroAddressNotAllowed(); + } + + s_authorizedCallers.add(caller); + emit AuthorizedCallerAdded(caller); + } + } + + /// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller. + function _validateCaller() internal view { + if (!s_authorizedCallers.contains(msg.sender)) { + revert UnauthorizedCaller(msg.sender); + } + } + + /// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller. + modifier onlyAuthorizedCallers() { + _validateCaller(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol new file mode 100644 index 0000000..5b0c159 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol"; + +/// @title The ConfirmedOwner contract +/// @notice A contract with helpers for basic contract ownership. +contract ConfirmedOwner is ConfirmedOwnerWithProposal { + constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol new file mode 100644 index 0000000..2a6dd94 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IOwnable} from "../interfaces/IOwnable.sol"; + +/// @title The ConfirmedOwner contract +/// @notice A contract with helpers for basic contract ownership. +contract ConfirmedOwnerWithProposal is IOwnable { + address private s_owner; + address private s_pendingOwner; + + event OwnershipTransferRequested(address indexed from, address indexed to); + event OwnershipTransferred(address indexed from, address indexed to); + + constructor(address newOwner, address pendingOwner) { + // solhint-disable-next-line gas-custom-errors + require(newOwner != address(0), "Cannot set owner to zero"); + + s_owner = newOwner; + if (pendingOwner != address(0)) { + _transferOwnership(pendingOwner); + } + } + + /// @notice Allows an owner to begin transferring ownership to a new address. + function transferOwnership(address to) public override onlyOwner { + _transferOwnership(to); + } + + /// @notice Allows an ownership transfer to be completed by the recipient. + function acceptOwnership() external override { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == s_pendingOwner, "Must be proposed owner"); + + address oldOwner = s_owner; + s_owner = msg.sender; + s_pendingOwner = address(0); + + emit OwnershipTransferred(oldOwner, msg.sender); + } + + /// @notice Get the current owner + function owner() public view override returns (address) { + return s_owner; + } + + /// @notice validate, transfer ownership, and emit relevant events + function _transferOwnership(address to) private { + // solhint-disable-next-line gas-custom-errors + require(to != msg.sender, "Cannot transfer to self"); + + s_pendingOwner = to; + + emit OwnershipTransferRequested(s_owner, to); + } + + /// @notice validate access + function _validateOwnership() internal view { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == s_owner, "Only callable by owner"); + } + + /// @notice Reverts if called by anyone other than the contract owner. + modifier onlyOwner() { + _validateOwnership(); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol new file mode 100644 index 0000000..829c687 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "./ConfirmedOwner.sol"; + +/// @title The OwnerIsCreator contract +/// @notice A contract with helpers for basic contract ownership. +contract OwnerIsCreator is ConfirmedOwner { + constructor() ConfirmedOwner(msg.sender) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol new file mode 100644 index 0000000..f4ea905 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {SimpleWriteAccessController} from "./SimpleWriteAccessController.sol"; + +/// @title SimpleReadAccessController +/// @notice Gives access to: +/// - any externally owned account (note that off-chain actors can always read +/// any contract storage regardless of on-chain access control measures, so this +/// does not weaken the access control while improving usability) +/// - accounts explicitly added to an access list +/// @dev SimpleReadAccessController is not suitable for access controlling writes +/// since it grants any externally owned account access! See +/// SimpleWriteAccessController for that. +contract SimpleReadAccessController is SimpleWriteAccessController { + /// @notice Returns the access of an address + /// @param _user The address to query + function hasAccess(address _user, bytes memory _calldata) public view virtual override returns (bool) { + // solhint-disable-next-line avoid-tx-origin + return super.hasAccess(_user, _calldata) || _user == tx.origin; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol new file mode 100644 index 0000000..5a53bdf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "./ConfirmedOwner.sol"; +import {AccessControllerInterface} from "../interfaces/AccessControllerInterface.sol"; + +/// @title SimpleWriteAccessController +/// @notice Gives access to accounts explicitly added to an access list by the controller's owner. +/// @dev does not make any special permissions for externally, see SimpleReadAccessController for that. +contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwner { + bool public checkEnabled; + mapping(address => bool) internal s_accessList; + + event AddedAccess(address user); + event RemovedAccess(address user); + event CheckAccessEnabled(); + event CheckAccessDisabled(); + + constructor() ConfirmedOwner(msg.sender) { + checkEnabled = true; + } + + /// @notice Returns the access of an address + /// @param _user The address to query + function hasAccess(address _user, bytes memory) public view virtual override returns (bool) { + return s_accessList[_user] || !checkEnabled; + } + + /// @notice Adds an address to the access list + /// @param _user The address to add + function addAccess(address _user) external onlyOwner { + if (!s_accessList[_user]) { + s_accessList[_user] = true; + + emit AddedAccess(_user); + } + } + + /// @notice Removes an address from the access list + /// @param _user The address to remove + function removeAccess(address _user) external onlyOwner { + if (s_accessList[_user]) { + s_accessList[_user] = false; + + emit RemovedAccess(_user); + } + } + + /// @notice makes the access check enforced + function enableAccessCheck() external onlyOwner { + if (!checkEnabled) { + checkEnabled = true; + + emit CheckAccessEnabled(); + } + } + + /// @notice makes the access check unenforced + function disableAccessCheck() external onlyOwner { + if (checkEnabled) { + checkEnabled = false; + + emit CheckAccessDisabled(); + } + } + + /// @dev reverts if the caller does not have access + modifier checkAccess() { + // solhint-disable-next-line gas-custom-errors + require(hasAccess(msg.sender, msg.data), "No access"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol new file mode 100644 index 0000000..6716dc1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice This library contains various callWithExactGas functions. All of them are +/// safe from gas bomb attacks. +/// @dev There is code duplication in this library. This is done to not leave the assembly +/// the blocks. +library CallWithExactGas { + error NoContract(); + error NoGasForCallExactCheck(); + error NotEnoughGasForCall(); + + bytes4 internal constant NO_CONTRACT_SIG = 0x0c3b563c; + bytes4 internal constant NO_GAS_FOR_CALL_EXACT_CHECK_SIG = 0xafa32a2c; + bytes4 internal constant NOT_ENOUGH_GAS_FOR_CALL_SIG = 0x37c3be29; + + /// @notice calls target address with exactly gasAmount gas and payload as calldata. + /// Accounts for gasForCallExactCheck gas that will be used by this function. Will revert + /// if the target is not a contact. Will revert when there is not enough gas to call the + /// target with gasAmount gas. + /// @dev Ignores the return data, which makes it immune to gas bomb attacks. + /// @return success whether the call succeeded + function _callWithExactGas( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck + ) internal returns (bool success) { + assembly { + // solidity calls check that a contract actually exists at the destination, so we do the same + // Note we do this check prior to measuring gas so gasForCallExactCheck (our "cushion") + // doesn't need to account for it. + if iszero(extcodesize(target)) { + mstore(0x0, NO_CONTRACT_SIG) + revert(0x0, 0x4) + } + + let g := gas() + // Compute g -= gasForCallExactCheck and check for underflow + // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. gasForCallExactCheck ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, gasForCallExactCheck) { + mstore(0x0, NO_GAS_FOR_CALL_EXACT_CHECK_SIG) + revert(0x0, 0x4) + } + g := sub(g, gasForCallExactCheck) + // if g - g//64 <= gasAmount, revert. We subtract g//64 because of EIP-150 + if iszero(gt(sub(g, div(g, 64)), gasLimit)) { + mstore(0x0, NOT_ENOUGH_GAS_FOR_CALL_SIG) + revert(0x0, 0x4) + } + + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) + } + return success; + } + + /// @notice calls target address with exactly gasAmount gas and payload as calldata. + /// Account for gasForCallExactCheck gas that will be used by this function. Will revert + /// if the target is not a contact. Will revert when there is not enough gas to call the + /// target with gasAmount gas. + /// @dev Caps the return data length, which makes it immune to gas bomb attacks. + /// @dev Return data cap logic borrowed from + /// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol. + /// @return success whether the call succeeded + /// @return retData the return data from the call, capped at maxReturnBytes bytes + /// @return gasUsed the gas used by the external call. Does not include the overhead of this function. + function _callWithExactGasSafeReturnData( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck, + uint16 maxReturnBytes + ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { + // allocate retData memory ahead of time + retData = new bytes(maxReturnBytes); + + assembly { + // solidity calls check that a contract actually exists at the destination, so we do the same + // Note we do this check prior to measuring gas so gasForCallExactCheck (our "cushion") + // doesn't need to account for it. + if iszero(extcodesize(target)) { + mstore(0x0, NO_CONTRACT_SIG) + revert(0x0, 0x4) + } + + let g := gas() + // Compute g -= gasForCallExactCheck and check for underflow + // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. gasForCallExactCheck ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, gasForCallExactCheck) { + mstore(0x0, NO_GAS_FOR_CALL_EXACT_CHECK_SIG) + revert(0x0, 0x4) + } + g := sub(g, gasForCallExactCheck) + // if g - g//64 <= gasAmount, revert. We subtract g//64 because of EIP-150 + if iszero(gt(sub(g, div(g, 64)), gasLimit)) { + mstore(0x0, NOT_ENOUGH_GAS_FOR_CALL_SIG) + revert(0x0, 0x4) + } + + // We save the gas before the call so we can calculate how much gas the call used + let gasBeforeCall := gas() + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) + gasUsed := sub(gasBeforeCall, gas()) + + // limit our copy to maxReturnBytes bytes + let toCopy := returndatasize() + if gt(toCopy, maxReturnBytes) { + toCopy := maxReturnBytes + } + // Store the length of the copied bytes + mstore(retData, toCopy) + // copy the bytes from retData[0:_toCopy] + returndatacopy(add(retData, 0x20), 0x0, toCopy) + } + return (success, retData, gasUsed); + } + + /// @notice Calls target address with exactly gasAmount gas and payload as calldata + /// or reverts if at least gasLimit gas is not available. + /// @dev Does not check if target is a contract. If it is not a contract, the low-level + /// call will still be made and it will succeed. + /// @dev Ignores the return data, which makes it immune to gas bomb attacks. + /// @return success whether the call succeeded + /// @return sufficientGas Whether there was enough gas to make the call + function _callWithExactGasEvenIfTargetIsNoContract( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck + ) internal returns (bool success, bool sufficientGas) { + assembly { + let g := gas() + // Compute g -= CALL_WITH_EXACT_GAS_CUSHION and check for underflow. We + // need the cushion since the logic following the above call to gas also + // costs gas which we cannot account for exactly. So cushion is a + // conservative upper bound for the cost of this logic. + if iszero(lt(g, gasForCallExactCheck)) { + g := sub(g, gasForCallExactCheck) + // If g - g//64 <= gasAmount, we don't have enough gas. We subtract g//64 because of EIP-150. + if gt(sub(g, div(g, 64)), gasLimit) { + // Call and ignore success/return data. Note that we did not check + // whether a contract actually exists at the target address. + success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) + sufficientGas := true + } + } + } + return (success, sufficientGas); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol new file mode 100644 index 0000000..c14a03b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: MIT +/* solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore */ +pragma solidity ^0.8.0; + +import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; +import {EnumerableMapBytes32} from "./EnumerableMapBytes32.sol"; + +// TODO: the lib can be replaced with OZ v5.1 post-upgrade, which has AddressToAddressMap and AddressToBytes32Map +library EnumerableMapAddresses { + using EnumerableMap for EnumerableMap.UintToAddressMap; + using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map; + using EnumerableMapBytes32 for EnumerableMapBytes32.Bytes32ToBytesMap; + + struct AddressToAddressMap { + EnumerableMap.UintToAddressMap _inner; + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) { + return map._inner.set(uint256(uint160(key)), value); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function remove(AddressToAddressMap storage map, address key) internal returns (bool) { + return map._inner.remove(uint256(uint160(key))); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { + return map._inner.contains(uint256(uint160(key))); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function length(AddressToAddressMap storage map) internal view returns (uint256) { + return map._inner.length(); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) { + (uint256 key, address value) = map._inner.at(index); + return (address(uint160(key)), value); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) { + return map._inner.tryGet(uint256(uint160(key))); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function get(AddressToAddressMap storage map, address key) internal view returns (address) { + return map._inner.get(uint256(uint160(key))); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function get( + AddressToAddressMap storage map, + address key, + string memory errorMessage + ) internal view returns (address) { + return map._inner.get(uint256(uint160(key)), errorMessage); + } + + struct AddressToBytes32Map { + EnumerableMap.Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) { + return map._inner.set(bytes32(uint256(uint160(key))), value); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function remove(AddressToBytes32Map storage map, address key) internal returns (bool) { + return map._inner.remove(bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) { + return map._inner.contains(bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function length(AddressToBytes32Map storage map) internal view returns (uint256) { + return map._inner.length(); + } + + /** + * @dev Returns the element stored at position `index` in the map. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address, bytes32) { + (bytes32 key, bytes32 value) = map._inner.at(index); + return (address(uint160(uint256(key))), value); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool, bytes32) { + (bool success, bytes32 value) = map._inner.tryGet(bytes32(uint256(uint160(key)))); + return (success, value); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) { + return map._inner.get(bytes32(uint256(uint160(key)))); + } + + struct AddressToBytesMap { + EnumerableMapBytes32.Bytes32ToBytesMap _inner; + } + + /** + * @dev Sets the value for `key` in the map. Returns true if the key was added to the map, that is if it was not already present. + * @param map The map where the value will be set + * @param key The key to set the value for + * @param value The value to set for the key + * @return bool indicating whether the key was added to the map + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function set(AddressToBytesMap storage map, address key, bytes memory value) internal returns (bool) { + return map._inner.set(bytes32(uint256(uint160(key))), value); + } + + /** + * @dev Removes the value for `key` in the map. Returns true if the key was removed from the map, that is if it was present. + * @param map The map where the value will be removed + * @param key The key to remove the value for + * @return bool indicating whether the key was removed from the map + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function remove(AddressToBytesMap storage map, address key) internal returns (bool) { + return map._inner.remove(bytes32(uint256(uint160(key)))); + } + + /** + * @dev Checks if the map contains the `key`. Returns true if the key is in the map. + * @param map The map to check for the presence of the key + * @param key The key to check for presence in the map + * @return bool indicating whether the key is in the map + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function contains(AddressToBytesMap storage map, address key) internal view returns (bool) { + return map._inner.contains(bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. + * @param map The map to check the length of + * @return uint256 indicating the number of elements in the map + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function length(AddressToBytesMap storage map) internal view returns (uint256) { + return map._inner.length(); + } + + /** + * @dev Returns the element stored at position `index` in the map. Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed. + * @param map The map to retrieve the element from + * @param index The index to retrieve the element at + * @return address The key of the element at the specified index + * @return bytes The value of the element at the specified index + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function at(AddressToBytesMap storage map, uint256 index) internal view returns (address, bytes memory) { + (bytes32 key, bytes memory value) = map._inner.at(index); + return (address(uint160(uint256(key))), value); + } + + /** + * @dev Tries to return the value associated with `key`. Does not revert if `key` is not in the map. + * @param map The map to retrieve the value from + * @param key The key to retrieve the value for + * @return bool indicating whether the key was in the map + * @return bytes The value associated with the key + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function tryGet(AddressToBytesMap storage map, address key) internal view returns (bool, bytes memory) { + return map._inner.tryGet(bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the value associated with `key`. + * @param map The map to retrieve the value from + * @param key The key to retrieve the value for + * @return bytes The value associated with the key + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function get(AddressToBytesMap storage map, address key) internal view returns (bytes memory) { + return map._inner.get(bytes32(uint256(uint160(key)))); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol new file mode 100644 index 0000000..2ec9098 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +/* solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore */ +pragma solidity ^0.8.0; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - Entries are added, removed, and checked for existence in constant time + * (O(1)). + * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableMapBytes32 for EnumerableMapBytes32.Bytes32ToBytesMap; + * + * // Declare a set state variable + * EnumerableMapBytes32.Bytes32ToBytesMap private myMap; + * } + * ``` + * + * The following map types are supported: + * + * - `bytes32 -> bytes` (`Bytes32ToBytes`) + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean up an EnumerableMapBytes32, you should remove all elements one by one. + * ==== + */ +library EnumerableMapBytes32 { + using EnumerableSet for EnumerableSet.Bytes32Set; + + error NonexistentKeyError(); + + struct Bytes32ToBytesMap { + EnumerableSet.Bytes32Set _keys; + mapping(bytes32 => bytes) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function set(Bytes32ToBytesMap storage map, bytes32 key, bytes memory value) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function remove(Bytes32ToBytesMap storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + return map._keys.remove(key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function contains(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function length(Bytes32ToBytesMap storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function at(Bytes32ToBytesMap storage map, uint256 index) internal view returns (bytes32, bytes memory) { + bytes32 key = map._keys.at(index); + return (key, map._values[key]); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function tryGet(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool, bytes memory) { + bytes memory value = map._values[key]; + if (value.length == 0) { + return (contains(map, key), bytes("")); + } else { + return (true, value); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function get(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bytes memory) { + bytes memory value = map._values[key]; + if (value.length == 0 && !contains(map, key)) { + revert NonexistentKeyError(); + } + return value; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol new file mode 100644 index 0000000..b780967 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +/// @dev this is a fully copy of OZ's EnumerableSet library with the addition of a Bytes16Set + +pragma solidity ^0.8.0; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // Bytes16Set + + struct Bytes16Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes16Set storage set, bytes16 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes16Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes16Set storage set, uint256 index) internal view returns (bytes16) { + return bytes16(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes16Set storage set) internal view returns (bytes16[] memory) { + bytes32[] memory store = _values(set._inner); + bytes16[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol new file mode 100644 index 0000000..cc51e85 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface AccessControllerInterface { + function hasAccess(address user, bytes calldata data) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol new file mode 100644 index 0000000..0ee4aa5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface AggregatorInterface { + function latestAnswer() external view returns (int256); + + function latestTimestamp() external view returns (uint256); + + function latestRound() external view returns (uint256); + + function getAnswer(uint256 roundId) external view returns (int256); + + function getTimestamp(uint256 roundId) external view returns (uint256); + + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + + event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol new file mode 100644 index 0000000..7e27915 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AggregatorInterface} from "./AggregatorInterface.sol"; +import {AggregatorV3Interface} from "./AggregatorV3Interface.sol"; + +// solhint-disable-next-line interface-starts-with-i +interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol new file mode 100644 index 0000000..2ba1925 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface AggregatorV3Interface { + function decimals() external view returns (uint8); + + function description() external view returns (string memory); + + function version() external view returns (uint256); + + function getRoundData( + uint80 _roundId + ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol new file mode 100644 index 0000000..f654cda --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface AggregatorValidatorInterface { + function validate( + uint256 previousRoundId, + int256 previousAnswer, + uint256 currentRoundId, + int256 currentAnswer + ) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol new file mode 100644 index 0000000..07cb7a1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IAccessController { + function hasAccess(address user, bytes calldata data) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol new file mode 100644 index 0000000..5cb8cfc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +interface IERC677Receiver { + function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol new file mode 100644 index 0000000..3141fe9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOwnable { + function owner() external returns (address); + + function transferOwnership(address recipient) external; + + function acceptOwnership() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol new file mode 100644 index 0000000..135f6d0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ITypeAndVersion { + function typeAndVersion() external pure returns (string memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol new file mode 100644 index 0000000..9607353 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IWERC20 { + function deposit() external payable; + + function withdraw(uint256) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol new file mode 100644 index 0000000..b23736b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface LinkTokenInterface { + function allowance(address owner, address spender) external view returns (uint256 remaining); + + function approve(address spender, uint256 value) external returns (bool success); + + function balanceOf(address owner) external view returns (uint256 balance); + + function decimals() external view returns (uint8 decimalPlaces); + + function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); + + function increaseApproval(address spender, uint256 subtractedValue) external; + + function name() external view returns (string memory tokenName); + + function symbol() external view returns (string memory tokenSymbol); + + function totalSupply() external view returns (uint256 totalTokensIssued); + + function transfer(address to, uint256 value) external returns (bool success); + + function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); + + function transferFrom(address from, address to, uint256 value) external returns (bool success); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol new file mode 100644 index 0000000..6155b38 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; + +contract WERC20Mock is ERC20 { + constructor() ERC20("WERC20Mock", "WERC") {} + + event Deposit(address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + + receive() external payable { + deposit(); + } + + function deposit() public payable { + _mint(msg.sender, msg.value); + emit Deposit(msg.sender, msg.value); + } + + function withdraw(uint256 wad) public { + // solhint-disable-next-line gas-custom-errors, reason-string + require(balanceOf(msg.sender) >= wad); + _burn(msg.sender, wad); + payable(msg.sender).transfer(wad); + emit Withdrawal(msg.sender, wad); + } + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol new file mode 100644 index 0000000..cd3f197 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ITypeAndVersion} from "../interfaces/ITypeAndVersion.sol"; + +abstract contract OCR2Abstract is ITypeAndVersion { + uint256 internal constant MAX_NUM_ORACLES = 31; + uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 + uint256 private constant PREFIX = 0x0001 << (256 - 16); // 0x000100..00 + + /// @notice triggers a new run of the offchain reporting protocol + /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis + /// @param configDigest configDigest of this configuration + /// @param configCount ordinal number of this config setting among all config settings over the life of this contract + /// @param signers ith element is address ith oracle uses to sign a report + /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method + /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + event ConfigSet( + uint32 previousConfigBlockNumber, + bytes32 configDigest, + uint64 configCount, + address[] signers, + address[] transmitters, + uint8 f, + bytes onchainConfig, + uint64 offchainConfigVersion, + bytes offchainConfig + ); + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param signers addresses with which oracles sign the reports + /// @param transmitters addresses oracles use to transmit the reports + /// @param f number of faulty oracles the system can tolerate + /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) + /// @param offchainConfigVersion version number for offchainEncoding schema + /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract + function setConfig( + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) external virtual; + + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) + function latestConfigDetails() + external + view + virtual + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); + + function _configDigestFromConfigData( + uint256 chainId, + address contractAddress, + uint64 configCount, + address[] memory signers, + address[] memory transmitters, + uint8 f, + bytes memory onchainConfig, + uint64 offchainConfigVersion, + bytes memory offchainConfig + ) internal pure returns (bytes32) { + uint256 h = uint256( + keccak256( + abi.encode( + chainId, + contractAddress, + configCount, + signers, + transmitters, + f, + onchainConfig, + offchainConfigVersion, + offchainConfig + ) + ) + ); + return bytes32((PREFIX & PREFIX_MASK) | (h & ~PREFIX_MASK)); + } + + /// @notice optionally emitted to indicate the latest configDigest and epoch for + /// which a report was successfully transmitted. Alternatively, the contract may + /// use latestConfigDigestAndEpoch with scanLogs set to false. + event Transmitted(bytes32 configDigest, uint32 epoch); + + /// @notice optionally returns the latest configDigest and epoch for which a + /// report was successfully transmitted. Alternatively, the contract may return + /// scanLogs set to true and use Transmitted events to provide this information + /// to offchain watchers. + /// @return scanLogs indicates whether to rely on the configDigest and epoch + /// returned or whether to scan logs for the Transmitted event instead. + /// @return configDigest + /// @return epoch + function latestConfigDigestAndEpoch() + external + view + virtual + returns (bool scanLogs, bytes32 configDigest, uint32 epoch); + + /// @notice transmit is called to post a new report to the contract + /// @param reportContext [0]: ConfigDigest, [1]: 27 byte padding, 4-byte epoch and 1-byte round, [2]: ExtraHash + /// @param report serialized report, which the signatures are signing. + /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries + /// @param rawVs ith element is the the V component of the ith signature + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external virtual; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol new file mode 100644 index 0000000..1dfc21f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol @@ -0,0 +1,330 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {OwnerIsCreator} from "../access/OwnerIsCreator.sol"; +import {OCR2Abstract} from "./OCR2Abstract.sol"; + +/// @notice Onchain verification of reports from the offchain reporting protocol +/// @dev THIS CONTRACT HAS NOT GONE THROUGH ANY SECURITY REVIEW. DO NOT USE IN PROD. +/// @dev For details on its operation, see the offchain reporting protocol design +/// doc, which refers to this contract as simply the "contract". +/// @dev This contract is meant to aid rapid development of new applications based on OCR2. +/// However, for actual production contracts, it is expected that most of the logic of this contract +/// will be folded directly into the application contract. Inheritance prevents us from doing lots +/// of juicy storage layout optimizations, leading to a substantial increase in gas cost. +// solhint-disable gas-custom-errors +abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract { + error ReportInvalid(); + + bool internal immutable i_uniqueReports; + + constructor(bool uniqueReports) OwnerIsCreator() { + i_uniqueReports = uniqueReports; + } + + /// @dev Storing these fields used on the hot path in a ConfigInfo variable reduces + /// the retrieval of all of them to a single SLOAD. If any further fields are + /// added, make sure that storage of the struct still takes at most 32 bytes. + struct ConfigInfo { + bytes32 latestConfigDigest; + uint8 f; // ───╮ + uint8 n; // ───╯ + } + ConfigInfo internal s_configInfo; + + /// @dev Incremented each time a new config is posted. This count is incorporated + /// into the config digest, to prevent replay attacks. + uint32 internal s_configCount; + /// @dev Makes it easier for offchain systems to extract config from logs. + uint32 internal s_latestConfigBlockNumber; + + /// @dev Used for s_oracles[a].role, where a is an address, to track the purpose + /// of the address, or to indicate that the address is unset. + enum Role { + // No oracle role has been set for address a + Unset, + // Signing address for the s_oracles[a].index'th oracle. I.e., report + // signatures from this oracle should ecrecover back to address a. + Signer, + // Transmission address for the s_oracles[a].index'th oracle. I.e., if a + // report is received by OCR2Aggregator.transmit in which msg.sender is + // a, it is attributed to the s_oracles[a].index'th oracle. + Transmitter + } + + struct Oracle { + uint8 index; // ───╮ Index of oracle in s_signers/s_transmitters + Role role; // ─────╯ Role of the address which mapped to this struct + } + + mapping(address => Oracle) /* signer OR transmitter address */ internal s_oracles; + + /// @notice Contains the signing address of each oracle + address[] internal s_signers; + + /// @notice Contains the transmission address of each oracle, + /// i.e. the address the oracle actually sends transactions to the contract from + address[] internal s_transmitters; + + /// @dev Reverts transaction if config args are invalid + modifier checkConfigValid(uint256 _numSigners, uint256 _numTransmitters, uint256 _f) { + require(_numSigners <= MAX_NUM_ORACLES, "too many signers"); + require(_f > 0, "f must be positive"); + require(_numSigners == _numTransmitters, "oracle addresses out of registration"); + require(_numSigners > 3 * _f, "faulty-oracle f too high"); + _; + } + + // solhint-disable-next-line gas-struct-packing + struct SetConfigArgs { + address[] signers; + address[] transmitters; + uint8 f; + bytes onchainConfig; + uint64 offchainConfigVersion; + bytes offchainConfig; + } + + /// @inheritdoc OCR2Abstract + function latestConfigDigestAndEpoch() + external + view + virtual + override + returns (bool scanLogs, bytes32 configDigest, uint32 epoch) + { + return (true, bytes32(0), uint32(0)); + } + + /// @notice sets offchain reporting protocol configuration incl. participating oracles + /// @param _signers addresses with which oracles sign the reports + /// @param _transmitters addresses oracles use to transmit the reports + /// @param _f number of faulty oracles the system can tolerate + /// @param _onchainConfig encoded on-chain contract configuration + /// @param _offchainConfigVersion version number for offchainEncoding schema + /// @param _offchainConfig encoded off-chain oracle configuration + function setConfig( + address[] memory _signers, + address[] memory _transmitters, + uint8 _f, + bytes memory _onchainConfig, + uint64 _offchainConfigVersion, + bytes memory _offchainConfig + ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { + SetConfigArgs memory args = SetConfigArgs({ + signers: _signers, + transmitters: _transmitters, + f: _f, + onchainConfig: _onchainConfig, + offchainConfigVersion: _offchainConfigVersion, + offchainConfig: _offchainConfig + }); + + _beforeSetConfig(args.f, args.onchainConfig); + + while (s_signers.length != 0) { + // remove any old signer/transmitter addresses + uint256 lastIdx = s_signers.length - 1; + address signer = s_signers[lastIdx]; + address transmitter = s_transmitters[lastIdx]; + delete s_oracles[signer]; + delete s_oracles[transmitter]; + s_signers.pop(); + s_transmitters.pop(); + } + + for (uint256 i = 0; i < args.signers.length; ++i) { + // add new signer/transmitter addresses + require(s_oracles[args.signers[i]].role == Role.Unset, "repeated signer address"); + s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); + require(s_oracles[args.transmitters[i]].role == Role.Unset, "repeated transmitter address"); + s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); + s_signers.push(args.signers[i]); + s_transmitters.push(args.transmitters[i]); + } + s_configInfo.f = args.f; + uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; + s_latestConfigBlockNumber = uint32(block.number); + s_configCount += 1; + { + s_configInfo.latestConfigDigest = _configDigestFromConfigData( + block.chainid, + address(this), + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + } + s_configInfo.n = uint8(args.signers.length); + + emit ConfigSet( + previousConfigBlockNumber, + s_configInfo.latestConfigDigest, + s_configCount, + args.signers, + args.transmitters, + args.f, + args.onchainConfig, + args.offchainConfigVersion, + args.offchainConfig + ); + + _afterSetConfig(args.f, args.onchainConfig); + } + + /// @notice information about current offchain reporting protocol configuration + /// @return configCount ordinal number of current config, out of all configs applied to this contract so far + /// @return blockNumber block at which this config was set + /// @return configDigest domain-separation tag for current config (see configDigestFromConfigData) + function latestConfigDetails() + external + view + override + returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) + { + return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); + } + + /// @return list of addresses permitted to transmit reports to this contract + /// @dev The list will match the order used to specify the transmitter during setConfig + function transmitters() external view returns (address[] memory) { + return s_transmitters; + } + + function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + function _afterSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; + + /// @dev hook to allow additional validation of the report by the extending contract + /// @param configDigest separation tag for current config (see configDigestFromConfigData) + /// @param epochAndRound 27 byte padding, 4-byte epoch and 1-byte round + /// @param report serialized report + function _validateReport( + bytes32 configDigest, + uint40 epochAndRound, + bytes memory report + ) internal virtual returns (bool); + + /// @dev hook called after the report has been fully validated + /// for the extending contract to handle additional logic, such as oracle payment + /// @param initialGas the amount of gas before validation + /// @param transmitter the address of the account that submitted the report + /// @param signers the addresses of all signing accounts + /// @param report serialized report + function _report( + uint256 initialGas, + address transmitter, + uint8 signerCount, + address[MAX_NUM_ORACLES] memory signers, + bytes calldata report + ) internal virtual; + + // The constant-length components of the msg.data sent to transmit. + // See the "If we wanted to call sam" example on for example reasoning + // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html + uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = + 4 + // function selector + 32 * + 3 + // 3 words containing reportContext + 32 + // word containing start location of abiencoded report value + 32 + // word containing location start of abiencoded rs value + 32 + // word containing start location of abiencoded ss value + 32 + // rawVs value + 32 + // word containing length of report + 32 + // word containing length rs + 32 + // word containing length of ss + 0; // placeholder + + function _requireExpectedMsgDataLength( + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss + ) private pure { + // calldata will never be big enough to make this overflow + uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + + report.length + // one byte pure entry in _report + rs.length * + 32 + // 32 bytes per entry in _rs + ss.length * + 32 + // 32 bytes per entry in _ss + 0; // placeholder + require(msg.data.length == expected, "calldata length mismatch"); + } + + /// @notice transmit is called to post a new report to the contract + /// @param report serialized report, which the signatures are signing. + /// @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries + /// @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries + /// @param rawVs ith element is the the V component of the ith signature + function transmit( + // NOTE: If these parameters are changed, expectedMsgDataLength and/or + // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly + bytes32[3] calldata reportContext, + bytes calldata report, + bytes32[] calldata rs, + bytes32[] calldata ss, + bytes32 rawVs // signatures + ) external override { + uint256 initialGas = gasleft(); // This line must come first + + { + // reportContext consists of: + // reportContext[0]: ConfigDigest + // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round + // reportContext[2]: ExtraHash + bytes32 configDigest = reportContext[0]; + uint32 epochAndRound = uint32(uint256(reportContext[1])); + + if (!_validateReport(configDigest, epochAndRound, report)) { + revert ReportInvalid(); + } + + emit Transmitted(configDigest, uint32(epochAndRound >> 8)); + + ConfigInfo memory configInfo = s_configInfo; + require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); + + _requireExpectedMsgDataLength(report, rs, ss); + + uint256 expectedNumSignatures; + if (i_uniqueReports) { + expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1; + } else { + expectedNumSignatures = configInfo.f + 1; + } + + require(rs.length == expectedNumSignatures, "wrong number of signatures"); + require(rs.length == ss.length, "signatures out of registration"); + + Oracle memory transmitter = s_oracles[msg.sender]; + require( // Check that sender is authorized to report + transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index], + "unauthorized transmitter" + ); + } + + address[MAX_NUM_ORACLES] memory signed; + uint8 signerCount = 0; + + { + // Verify signatures attached to report + bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); + + Oracle memory o; + for (uint256 i = 0; i < rs.length; ++i) { + address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); + o = s_oracles[signer]; + require(o.role == Role.Signer, "address not authorized to sign"); + require(signed[o.index] == address(0), "non-unique signature"); + signed[o.index] = signer; + signerCount += 1; + } + } + + _report(initialGas, msg.sender, signerCount, signed, report); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md new file mode 100644 index 0000000..e7ccc51 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md @@ -0,0 +1,5 @@ +# OCR2 Rapid Prototype Contracts + +The contracts in this directory are to aid rapid prototyping of OCR2 based products. They abstract OCR2 config and boilerplate code so that specific logic can be implemented and tested quickly. They are not optimized or audited. + +Do not use these contracts in production. For actual production contracts, it is expected that most of the logic of these contracts will be folded directly into the application contract. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol new file mode 100644 index 0000000..4d8ef60 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + address internal constant OWNER = 0x72da681452Ab957d1020c25fFaCA47B43980b7C3; + address internal constant STRANGER = 0x02e7d5DD1F4dDbC9f512FfA01d30aa190Ae3edBb; + + // Fri May 26 2023 13:49:53 GMT+0000 + uint256 internal constant BLOCK_TIME = 1685108993; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + vm.label(OWNER, "Owner"); + vm.label(STRANGER, "Stranger"); + + // Set the sender to OWNER permanently + vm.startPrank(OWNER); + deal(OWNER, 1e20); + + // Set the block time to a constant known value + vm.warp(BLOCK_TIME); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol new file mode 100644 index 0000000..34ae684 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {AuthorizedCallers} from "../../access/AuthorizedCallers.sol"; +import {BaseTest} from "../BaseTest.t.sol"; + +contract AuthorizedCallers_setup is BaseTest { + address[] s_callers; + + AuthorizedCallers s_authorizedCallers; + + function setUp() public override { + super.setUp(); + s_callers.push(makeAddr("caller1")); + s_callers.push(makeAddr("caller2")); + + s_authorizedCallers = new AuthorizedCallers(s_callers); + } +} + +contract AuthorizedCallers_constructor is AuthorizedCallers_setup { + event AuthorizedCallerAdded(address caller); + + function test_constructor_Success() public { + for (uint256 i = 0; i < s_callers.length; ++i) { + vm.expectEmit(); + emit AuthorizedCallerAdded(s_callers[i]); + } + + s_authorizedCallers = new AuthorizedCallers(s_callers); + + assertEq(s_callers, s_authorizedCallers.getAllAuthorizedCallers()); + } + + function test_ZeroAddressNotAllowed_Revert() public { + s_callers[0] = address(0); + + vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); + + new AuthorizedCallers(s_callers); + } +} + +contract AuthorizedCallers_applyAuthorizedCallerUpdates is AuthorizedCallers_setup { + event AuthorizedCallerAdded(address caller); + event AuthorizedCallerRemoved(address caller); + + function test_OnlyAdd_Success() public { + address[] memory addedCallers = new address[](2); + addedCallers[0] = vm.addr(3); + addedCallers[1] = vm.addr(4); + + address[] memory removedCallers = new address[](0); + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); + + vm.expectEmit(); + emit AuthorizedCallerAdded(addedCallers[0]); + vm.expectEmit(); + emit AuthorizedCallerAdded(addedCallers[1]); + + s_authorizedCallers.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + address[] memory expectedCallers = new address[](4); + expectedCallers[0] = s_callers[0]; + expectedCallers[1] = s_callers[1]; + expectedCallers[2] = addedCallers[0]; + expectedCallers[3] = addedCallers[1]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); + } + + function test_OnlyRemove_Success() public { + address[] memory addedCallers = new address[](0); + address[] memory removedCallers = new address[](1); + removedCallers[0] = s_callers[0]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); + + vm.expectEmit(); + emit AuthorizedCallerRemoved(removedCallers[0]); + + s_authorizedCallers.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + address[] memory expectedCallers = new address[](1); + expectedCallers[0] = s_callers[1]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); + } + + function test_AddAndRemove_Success() public { + address[] memory addedCallers = new address[](2); + addedCallers[0] = address(42); + addedCallers[1] = address(43); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = s_callers[0]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); + + vm.expectEmit(); + emit AuthorizedCallerRemoved(removedCallers[0]); + vm.expectEmit(); + emit AuthorizedCallerAdded(addedCallers[0]); + vm.expectEmit(); + emit AuthorizedCallerAdded(addedCallers[1]); + + s_authorizedCallers.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + // Order of the set changes on removal + address[] memory expectedCallers = new address[](3); + expectedCallers[0] = s_callers[1]; + expectedCallers[1] = addedCallers[0]; + expectedCallers[2] = addedCallers[1]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); + } + + function test_RemoveThenAdd_Success() public { + address[] memory addedCallers = new address[](1); + addedCallers[0] = s_callers[0]; + + address[] memory removedCallers = new address[](1); + removedCallers[0] = s_callers[0]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); + + vm.expectEmit(); + emit AuthorizedCallerRemoved(removedCallers[0]); + + vm.expectEmit(); + emit AuthorizedCallerAdded(addedCallers[0]); + + s_authorizedCallers.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + address[] memory expectedCallers = new address[](2); + expectedCallers[0] = s_callers[1]; + expectedCallers[1] = s_callers[0]; + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); + } + + function test_SkipRemove_Success() public { + address[] memory addedCallers = new address[](0); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = address(42); + + vm.recordLogs(); + s_authorizedCallers.applyAuthorizedCallerUpdates( + AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); + assertEq(vm.getRecordedLogs().length, 0); + } + + function test_OnlyCallableByOwner_Revert() public { + vm.stopPrank(); + + AuthorizedCallers.AuthorizedCallerArgs memory authorizedCallerArgs = AuthorizedCallers.AuthorizedCallerArgs({ + addedCallers: new address[](0), + removedCallers: new address[](0) + }); + + vm.expectRevert("Only callable by owner"); + + s_authorizedCallers.applyAuthorizedCallerUpdates(authorizedCallerArgs); + } + + function test_ZeroAddressNotAllowed_Revert() public { + s_callers[0] = address(0); + + vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); + + new AuthorizedCallers(s_callers); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol new file mode 100644 index 0000000..3623cb8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {CallWithExactGas} from "../../call/CallWithExactGas.sol"; +import {CallWithExactGasHelper} from "./CallWithExactGasHelper.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {GenericReceiver} from "../testhelpers/GenericReceiver.sol"; +import {GasConsumer} from "../testhelpers/GasConsumer.sol"; + +contract CallWithExactGasSetup is BaseTest { + GenericReceiver internal s_receiver; + CallWithExactGasHelper internal s_caller; + GasConsumer internal s_gasConsumer; + + uint256 internal constant DEFAULT_GAS_LIMIT = 20_000; + uint16 internal constant DEFAULT_GAS_FOR_CALL_EXACT_CHECK = 5000; + uint256 internal constant EXTCODESIZE_GAS_COST = 2600; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_receiver = new GenericReceiver(false); + s_caller = new CallWithExactGasHelper(); + s_gasConsumer = new GasConsumer(); + } +} + +contract CallWithExactGas__callWithExactGas is CallWithExactGasSetup { + function test_callWithExactGasSuccess(bytes memory payload, bytes4 funcSelector) public { + vm.pauseGasMetering(); + + bytes memory data = abi.encodeWithSelector(funcSelector, payload); + vm.assume( + funcSelector != GenericReceiver.setRevert.selector && + funcSelector != GenericReceiver.setErr.selector && + funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector + ); + + vm.expectCall(address(s_receiver), data); + vm.resumeGasMetering(); + + bool success = s_caller.callWithExactGas( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + assertTrue(success); + } + + function test_CallWithExactGasSafeReturnDataExactGas() public { + // The calculated overhead for otherwise unaccounted for gas usage + uint256 overheadForCallWithExactGas = 364; + + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGas.selector, + "", + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + // Since only 63/64th of the gas gets passed, we compensate + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); + + allowedGas += EXTCODESIZE_GAS_COST + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + overheadForCallWithExactGas; + + // Due to EIP-150 we expect to lose 1/64, so we compensate for this + allowedGas = (allowedGas * 64) / 63; + + (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); + + assertTrue(success); + assertEq(abi.encode(true), retData); + } + + function test_CallWithExactGasReceiverErrorSuccess() public { + bytes memory data = abi.encode("0x52656E73"); + + bytes memory errorData = new bytes(20); + for (uint256 i = 0; i < errorData.length; ++i) { + errorData[i] = 0x01; + } + s_receiver.setErr(errorData); + s_receiver.setRevert(true); + + vm.expectCall(address(s_receiver), data); + + bool success = s_caller.callWithExactGas( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT * 10, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + assertFalse(success); + } + + function test_NoContractReverts() public { + address addressWithoutContract = address(1337); + + vm.expectRevert(CallWithExactGas.NoContract.selector); + + s_caller.callWithExactGas( + "", // empty payload as it will revert well before needing it + addressWithoutContract, + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + } + + function test_NoGasForCallExactCheckReverts() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGas.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + (bool success, bytes memory retData) = address(s_caller).call{gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1}(payload); + assertFalse(success); + assertEq(retData.length, CallWithExactGas.NoGasForCallExactCheck.selector.length); + assertEq(abi.encodeWithSelector(CallWithExactGas.NoGasForCallExactCheck.selector), retData); + } + + function test_NotEnoughGasForCallReverts() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGas.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + // the extcodesize and account for EIP-150. This doesn't account for any other gas + // usage, and will therefore fail because the checks and memory stored/loads + // also cost gas. + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; + // extcodesize gas cost + allowedGas += EXTCODESIZE_GAS_COST; + // EIP-150 + allowedGas = (allowedGas * 64) / 63; + + // Expect this call to fail due to not having enough gas for the final call + (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); + + assertFalse(success); + assertEq(retData.length, CallWithExactGas.NotEnoughGasForCall.selector.length); + assertEq(abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector), retData); + } +} + +contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSetup { + function testFuzz_CallWithExactGasSafeReturnDataSuccess(bytes memory payload, bytes4 funcSelector) public { + vm.pauseGasMetering(); + bytes memory data = abi.encodeWithSelector(funcSelector, payload); + vm.assume( + funcSelector != GenericReceiver.setRevert.selector && + funcSelector != GenericReceiver.setErr.selector && + funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector + ); + uint16 maxRetBytes = 0; + + vm.expectCall(address(s_receiver), data); + vm.resumeGasMetering(); + + (bool success, bytes memory retData, uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + maxRetBytes + ); + + assertTrue(success); + assertEq(retData.length, 0); + assertGt(gasUsed, 500); + } + + function test_CallWithExactGasSafeReturnDataExactGas() public { + // The gas cost for `extcodesize` + uint256 extcodesizeGas = EXTCODESIZE_GAS_COST; + // The calculated overhead for retData initialization + uint256 overheadForRetDataInit = 114; + // The calculated overhead for otherwise unaccounted for gas usage + uint256 overheadForCallWithExactGas = 486; + + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasSafeReturnData.selector, + "", + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + 0 + ); + + // Since only 63/64th of the gas gets passed, we compensate + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); + + allowedGas += + extcodesizeGas + + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + + overheadForRetDataInit + + overheadForCallWithExactGas; + + // Due to EIP-150 we expect to lose 1/64, so we compensate for this + allowedGas = (allowedGas * 64) / 63; + + vm.expectCall(address(s_receiver), ""); + (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); + + assertTrue(success); + (bool innerSuccess, bytes memory innerRetData, uint256 gasUsed) = abi.decode(retData, (bool, bytes, uint256)); + + assertTrue(innerSuccess); + assertEq(innerRetData.length, 0); + assertGt(gasUsed, 500); + } + + function test_Fuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { + vm.assume(gasLimitMultiplier > 0); // Assume not zero to avoid zero gas being passed to s_gasConsumer + uint16 maxRetBytes = 0; + + vm.expectCall(address(s_gasConsumer), abi.encodeWithSelector(s_gasConsumer.consumeAllGas.selector)); + + // Default gas limit of 20k times the amount generated by the fuzzer + uint256 gasLimit = DEFAULT_GAS_LIMIT * gasLimitMultiplier; + + (bool success, , uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( + abi.encodePacked(s_gasConsumer.consumeAllGas.selector), + address(s_gasConsumer), + gasLimit, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + maxRetBytes + ); + + // Was determined as the least amount of gas needed for pre-call stack management. + // when an OOG error is thrown, used gas returned by the library is 122 <= x <= 137 based on the + // gas limit passed in. This was determined through trial and error and fuzzing. + uint256 CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD = 122; + + assertTrue(success, "Error: External Call Failed"); + + // Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library + assertApproxEqAbs( + gasUsed - CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD, + gasLimit, + gasLimit / 64, + "Error: All gas not consumed by receiver" + ); + } + + function test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() external { + uint16 maxRetBytes = 0; + + vm.expectCall(address(s_gasConsumer), abi.encodeWithSelector(s_gasConsumer.throwOutOfGasError.selector)); + + (bool success, , ) = s_caller.callWithExactGasSafeReturnData( + abi.encodePacked(s_gasConsumer.throwOutOfGasError.selector), + address(s_gasConsumer), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + maxRetBytes + ); + + assertFalse(success, "Error: External Call Succeeded where it should not"); + } + + function testFuzz_CallWithExactGasReceiverErrorSuccess(uint16 testRetBytes) public { + uint16 maxReturnBytes = 500; + // Bound with upper limit, otherwise the test runs out of gas. + testRetBytes = uint16(bound(testRetBytes, 0, maxReturnBytes * 10)); + + bytes memory data = abi.encode("0x52656E73"); + + bytes memory errorData = new bytes(testRetBytes); + for (uint256 i = 0; i < errorData.length; ++i) { + errorData[i] = 0x01; + } + s_receiver.setErr(errorData); + s_receiver.setRevert(true); + + vm.expectCall(address(s_receiver), data); + + (bool success, bytes memory retData, uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT * 10, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + maxReturnBytes + ); + + assertFalse(success); + + bytes memory expectedReturnData = errorData; + + // If expected return data is longer than MAX_RET_BYTES, truncate it to MAX_RET_BYTES + if (expectedReturnData.length > maxReturnBytes) { + expectedReturnData = new bytes(maxReturnBytes); + for (uint256 i = 0; i < maxReturnBytes; ++i) { + expectedReturnData[i] = errorData[i]; + } + } + assertEq(expectedReturnData, retData); + assertGt(gasUsed, 500); + } + + function test_NoContractReverts() public { + address addressWithoutContract = address(1337); + + vm.expectRevert(CallWithExactGas.NoContract.selector); + + s_caller.callWithExactGasSafeReturnData( + "", // empty payload as it will revert well before needing it + addressWithoutContract, + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + 0 + ); + } + + function test_NoGasForCallExactCheckReverts() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasSafeReturnData.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + 0 + ); + + (bool success, bytes memory retData) = address(s_caller).call{gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1}(payload); + assertFalse(success); + assertEq(retData.length, CallWithExactGas.NoGasForCallExactCheck.selector.length); + assertEq(abi.encodeWithSelector(CallWithExactGas.NoGasForCallExactCheck.selector), retData); + } + + function test_NotEnoughGasForCallReverts() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasSafeReturnData.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + 0 + ); + + // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + // the extcodesize and account for EIP-150. This doesn't account for any other gas + // usage, and will therefore fail because the checks and memory stored/loads + // also cost gas. + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; + // extcodesize gas cost + allowedGas += EXTCODESIZE_GAS_COST; + // EIP-150 + allowedGas = (allowedGas * 64) / 63; + + // Expect this call to fail due to not having enough gas for the final call + (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); + + assertFalse(success); + assertEq(retData.length, CallWithExactGas.NotEnoughGasForCall.selector.length); + assertEq(abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector), retData); + } +} + +contract CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract is CallWithExactGasSetup { + function test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes memory payload, bytes4 funcSelector) public { + vm.pauseGasMetering(); + bytes memory data = abi.encodeWithSelector(funcSelector, payload); + vm.assume( + funcSelector != GenericReceiver.setRevert.selector && + funcSelector != GenericReceiver.setErr.selector && + funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector + ); + vm.expectCall(address(s_receiver), data); + vm.resumeGasMetering(); + + (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + assertTrue(success); + assertTrue(sufficientGas); + } + + function test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() public { + // The calculated overhead for otherwise unaccounted for gas usage + uint256 overheadForCallWithExactGas = 446; + + bytes memory data = abi.encode("0x52656E73"); + + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, + data, + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + // Since only 63/64th of the gas gets passed, we compensate + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); + + allowedGas += DEFAULT_GAS_FOR_CALL_EXACT_CHECK + overheadForCallWithExactGas; + + // Due to EIP-150 we expect to lose 1/64, so we compensate for this + allowedGas = (allowedGas * 64) / 63; + + vm.expectCall(address(s_receiver), data); + (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{gas: allowedGas}(payload); + + // The call succeeds + assertTrue(outerCallSuccess); + + (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); + assertTrue(success); + assertTrue(sufficientGas); + } + + function test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() public { + bytes memory data = abi.encode("0x52656E73"); + + bytes memory errorData = new bytes(20); + for (uint256 i = 0; i < errorData.length; ++i) { + errorData[i] = 0x01; + } + s_receiver.setErr(errorData); + s_receiver.setRevert(true); + + vm.expectCall(address(s_receiver), data); + + (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( + data, + address(s_receiver), + DEFAULT_GAS_LIMIT * 10, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + // We don't care if it reverts, we only care if we have enough gas + assertFalse(success); + assertTrue(sufficientGas); + } + + function test_NoContractSuccess() public { + bytes memory data = abi.encode("0x52656E73"); + address addressWithoutContract = address(1337); + + (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( + data, + addressWithoutContract, + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + assertTrue(success); + assertTrue(sufficientGas); + } + + function test_NoGasForCallExactCheckReturnFalseSuccess() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{ + gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1 + }(payload); + + // The call succeeds + assertTrue(outerCallSuccess); + + (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); + assertFalse(success); + assertFalse(sufficientGas); + } + + function test_NotEnoughGasForCallReturnsFalseSuccess() public { + bytes memory payload = abi.encodeWithSelector( + s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, + "", // empty payload as it will revert well before needing it + address(s_receiver), + DEFAULT_GAS_LIMIT, + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + ); + + // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, + // and account for EIP-150. This doesn't account for any other gas usage, and + // will therefore fail because the checks and memory stored/loads also cost gas. + uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; + // EIP-150 + allowedGas = (allowedGas * 64) / 63; + + // Expect this call to fail due to not having enough gas for the final call + (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{gas: allowedGas}(payload); + + // The call succeeds + assertTrue(outerCallSuccess); + + (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); + assertFalse(success); + assertFalse(sufficientGas); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol new file mode 100644 index 0000000..9323156 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {CallWithExactGas} from "../../call/CallWithExactGas.sol"; + +contract CallWithExactGasHelper { + function callWithExactGas( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck + ) public returns (bool success) { + return CallWithExactGas._callWithExactGas(payload, target, gasLimit, gasForCallExactCheck); + } + + function callWithExactGasSafeReturnData( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck, + uint16 maxReturnBytes + ) public returns (bool success, bytes memory retData, uint256 gasUsed) { + return + CallWithExactGas._callWithExactGasSafeReturnData(payload, target, gasLimit, gasForCallExactCheck, maxReturnBytes); + } + + function callWithExactGasEvenIfTargetIsNoContract( + bytes memory payload, + address target, + uint256 gasLimit, + uint16 gasForCallExactCheck + ) public returns (bool success, bool sufficientGas) { + return CallWithExactGas._callWithExactGasEvenIfTargetIsNoContract(payload, target, gasLimit, gasForCallExactCheck); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol new file mode 100644 index 0000000..097e79e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BaseTest} from "../BaseTest.t.sol"; +import {EnumerableMapAddresses} from "../../enumerable/EnumerableMapAddresses.sol"; + +contract EnumerableMapAddressesTest is BaseTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + EnumerableMapAddresses.AddressToAddressMap internal s_addressToAddressMap; + EnumerableMapAddresses.AddressToBytes32Map internal s_addressToBytes32Map; + EnumerableMapAddresses.AddressToBytesMap internal s_addressToBytesMap; + + bytes32 internal constant MOCK_BYTES32_VALUE = bytes32(uint256(42)); + bytes internal constant MOCK_BYTES_VALUE = "0x123456789abcdef"; + + function setUp() public virtual override { + BaseTest.setUp(); + } +} + +contract EnumerableMapAddresses_set is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testSetSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + assertTrue(!s_addressToAddressMap.set(address(this), address(this))); + } + + function testBytes32SetSuccess() public { + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertTrue(s_addressToBytes32Map.contains(address(this))); + assertTrue(!s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + } + + function testBytesSetSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + assertTrue(!s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + } +} + +contract EnumerableMapAddresses_remove is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testRemoveSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.remove(address(this))); + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(!s_addressToAddressMap.remove(address(this))); + } + + function testBytes32RemoveSuccess() public { + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertTrue(s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.remove(address(this))); + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(!s_addressToBytes32Map.remove(address(this))); + } + + function testBytesRemoveSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.remove(address(this))); + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(!s_addressToBytesMap.remove(address(this))); + } +} + +contract EnumerableMapAddresses_contains is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testContainsSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + } + + function testBytes32ContainsSuccess() public { + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertTrue(s_addressToBytes32Map.contains(address(this))); + } + + function testBytesContainsSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + } +} + +contract EnumerableMapAddresses_length is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testLengthSuccess() public { + assertEq(s_addressToAddressMap.length(), 0); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertEq(s_addressToAddressMap.length(), 1); + assertTrue(s_addressToAddressMap.remove(address(this))); + assertEq(s_addressToAddressMap.length(), 0); + } + + function testBytes32LengthSuccess() public { + assertEq(s_addressToBytes32Map.length(), 0); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertEq(s_addressToBytes32Map.length(), 1); + assertTrue(s_addressToBytes32Map.remove(address(this))); + assertEq(s_addressToBytes32Map.length(), 0); + } + + function testBytesLengthSuccess() public { + assertEq(s_addressToBytesMap.length(), 0); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertEq(s_addressToBytesMap.length(), 1); + assertTrue(s_addressToBytesMap.remove(address(this))); + assertEq(s_addressToBytesMap.length(), 0); + } +} + +contract EnumerableMapAddresses_at is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testAtSuccess() public { + assertEq(s_addressToAddressMap.length(), 0); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertEq(s_addressToAddressMap.length(), 1); + (address key, address value) = s_addressToAddressMap.at(0); + assertEq(key, address(this)); + assertEq(value, address(this)); + } + + function testBytes32AtSuccess() public { + assertEq(s_addressToBytes32Map.length(), 0); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertEq(s_addressToBytes32Map.length(), 1); + (address key, bytes32 value) = s_addressToBytes32Map.at(0); + assertEq(key, address(this)); + assertEq(value, MOCK_BYTES32_VALUE); + } + + function testBytesAtSuccess() public { + assertEq(s_addressToBytesMap.length(), 0); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertEq(s_addressToBytesMap.length(), 1); + (address key, bytes memory value) = s_addressToBytesMap.at(0); + assertEq(key, address(this)); + assertEq(value, MOCK_BYTES_VALUE); + } +} + +contract EnumerableMapAddresses_tryGet is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testTryGetSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + (bool success, address value) = s_addressToAddressMap.tryGet(address(this)); + assertTrue(success); + assertEq(value, address(this)); + } + + function testBytes32TryGetSuccess() public { + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertTrue(s_addressToBytes32Map.contains(address(this))); + (bool success, bytes32 value) = s_addressToBytes32Map.tryGet(address(this)); + assertTrue(success); + assertEq(value, MOCK_BYTES32_VALUE); + } + + function testBytesTryGetSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + (bool success, bytes memory value) = s_addressToBytesMap.tryGet(address(this)); + assertTrue(success); + assertEq(value, MOCK_BYTES_VALUE); + } +} + +contract EnumerableMapAddresses_get is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testGetSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + assertEq(s_addressToAddressMap.get(address(this)), address(this)); + } + + function testBytes32GetSuccess() public { + assertTrue(!s_addressToBytes32Map.contains(address(this))); + assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); + assertTrue(s_addressToBytes32Map.contains(address(this))); + assertEq(s_addressToBytes32Map.get(address(this)), MOCK_BYTES32_VALUE); + } + + function testBytesGetSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + assertEq(s_addressToBytesMap.get(address(this)), MOCK_BYTES_VALUE); + } +} + +contract EnumerableMapAddresses_get_errorMessage is EnumerableMapAddressesTest { + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; + + function testGetErrorMessageSuccess() public { + assertTrue(!s_addressToAddressMap.contains(address(this))); + assertTrue(s_addressToAddressMap.set(address(this), address(this))); + assertTrue(s_addressToAddressMap.contains(address(this))); + assertEq(s_addressToAddressMap.get(address(this), "EnumerableMapAddresses: nonexistent key"), address(this)); + } + + function testBytesGetErrorMessageSuccess() public { + assertTrue(!s_addressToBytesMap.contains(address(this))); + assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); + assertTrue(s_addressToBytesMap.contains(address(this))); + assertEq(s_addressToBytesMap.get(address(this)), MOCK_BYTES_VALUE); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol new file mode 100644 index 0000000..4dd9fe9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line gas-struct-packing +struct TestStruct { + int32 Field; + string DifferentField; + uint8 OracleId; + uint8[32] OracleIds; + address Account; + address[] Accounts; + int192 BigField; + MidLevelDynamicTestStruct NestedDynamicStruct; + MidLevelStaticTestStruct NestedStaticStruct; +} + +struct MidLevelDynamicTestStruct { + bytes2 FixedBytes; + InnerDynamicTestStruct Inner; +} + +struct InnerDynamicTestStruct { + int64 IntVal; + string S; +} + +struct MidLevelStaticTestStruct { + bytes2 FixedBytes; + InnerStaticTestStruct Inner; +} + +struct InnerStaticTestStruct { + int64 IntVal; + address A; +} + +contract ChainReaderTester { + event Triggered( + int32 indexed field, + uint8 oracleId, + MidLevelDynamicTestStruct nestedDynamicStruct, + MidLevelStaticTestStruct nestedStaticStruct, + uint8[32] oracleIds, + address Account, + address[] Accounts, + string differentField, + int192 bigField + ); + + event TriggeredEventWithDynamicTopic(string indexed fieldHash, string field); + + // First topic is event hash + event TriggeredWithFourTopics(int32 indexed field1, int32 indexed field2, int32 indexed field3); + + // first topic is event hash, second and third topics get hashed before getting stored + event TriggeredWithFourTopicsWithHashed(string indexed field1, uint8[32] indexed field2, bytes32 indexed field3); + + // emits dynamic bytes which encode data in the same way every time. + event StaticBytes(bytes message); + + TestStruct[] private s_seen; + uint64[] private s_arr; + uint64 private s_value; + + constructor() { + // See chain_reader_interface_tests.go in chainlink-relay + s_arr.push(3); + s_arr.push(4); + } + + function addTestStruct( + int32 field, + string calldata differentField, + uint8 oracleId, + uint8[32] calldata oracleIds, + address account, + address[] calldata accounts, + int192 bigField, + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct + ) public { + s_seen.push( + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ) + ); + } + + function setAlterablePrimitiveValue(uint64 value) public { + s_value = value; + } + + function returnSeen( + int32 field, + string calldata differentField, + uint8 oracleId, + uint8[32] calldata oracleIds, + address account, + address[] calldata accounts, + int192 bigField, + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct + ) public pure returns (TestStruct memory) { + return + TestStruct( + field, + differentField, + oracleId, + oracleIds, + account, + accounts, + bigField, + nestedDynamicStruct, + nestedStaticStruct + ); + } + + function getElementAtIndex(uint256 i) public view returns (TestStruct memory) { + // See chain_reader_interface_tests.go in chainlink-relay + return s_seen[i - 1]; + } + + function getPrimitiveValue() public pure returns (uint64) { + // See chain_reader_interface_tests.go in chainlink-relay + return 3; + } + + function getAlterablePrimitiveValue() public view returns (uint64) { + // See chain_reader_interface_tests.go in chainlink-relay + return s_value; + } + + function getDifferentPrimitiveValue() public pure returns (uint64) { + // See chain_reader_interface_tests.go in chainlink-relay + return 1990; + } + + function getSliceValue() public view returns (uint64[] memory) { + return s_arr; + } + + function triggerEvent( + int32 field, + uint8 oracleId, + MidLevelDynamicTestStruct calldata nestedDynamicStruct, + MidLevelStaticTestStruct calldata nestedStaticStruct, + uint8[32] calldata oracleIds, + address account, + address[] calldata accounts, + string calldata differentField, + int192 bigField + ) public { + emit Triggered( + field, + oracleId, + nestedDynamicStruct, + nestedStaticStruct, + oracleIds, + account, + accounts, + differentField, + bigField + ); + } + + function triggerEventWithDynamicTopic(string calldata field) public { + emit TriggeredEventWithDynamicTopic(field, field); + } + + // first topic is the event signature + function triggerWithFourTopics(int32 field1, int32 field2, int32 field3) public { + emit TriggeredWithFourTopics(field1, field2, field3); + } + + // first topic is event hash, second and third topics get hashed before getting stored + function triggerWithFourTopicsWithHashed(string memory field1, uint8[32] memory field2, bytes32 field3) public { + emit TriggeredWithFourTopicsWithHashed(field1, field2, field3); + } + + // emulate CCTP message event. + function triggerStaticBytes( + uint32 val1, + uint32 val2, + uint32 val3, + uint64 val4, + bytes32 val5, + bytes32 val6, + bytes32 val7, + bytes memory raw + ) public { + bytes memory _message = abi.encodePacked(val1, val2, val3, val4, val5, val6, val7, raw); + emit StaticBytes(_message); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol new file mode 100644 index 0000000..f2b2f19 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkToken} from "../../token/ERC677/LinkToken.sol"; + +// This contract exists to mirror the functionality of the old token, which +// always deployed with 1b tokens sent to the deployer. +contract LinkTokenTestHelper is LinkToken { + constructor() { + _mint(msg.sender, 1e27); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol new file mode 100644 index 0000000..47ecbb0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../access/ConfirmedOwner.sol"; + +contract ConfirmedOwnerTestHelper is ConfirmedOwner { + event Here(); + + constructor() ConfirmedOwner(msg.sender) {} + + function modifierOnlyOwner() public onlyOwner { + emit Here(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol new file mode 100644 index 0000000..daf8479 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +contract GasConsumer { + function consumeAllGas() external view { + assembly { + // While loop that operates indefinitely, written in yul to ensure better granularity over exactly how much gas is spent + for { + // Loop will run forever since 0 < 1 + } lt(0, 1) {} { + // If 100 gas is remaining, then exit the loop by returning. 100 was determined by manual binary search to be + // the minimal amount of gas needed but less than the cost of another loop + if lt(gas(), 100) { + return(0x0, 0x0) // Return with no return data + } + } + } + } + + function throwOutOfGasError() external pure { + while (true) { + // Intentionally consume all gas to throw an OOG error. + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol new file mode 100644 index 0000000..2c05801 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract GenericReceiver { + bool public s_toRevert; + bytes private s_err; + + constructor(bool toRevert) { + s_toRevert = toRevert; + } + + function setRevert(bool toRevert) external { + s_toRevert = toRevert; + } + + function setErr(bytes memory err) external { + s_err = err; + } + + // solhint-disable-next-line payable-fallback + fallback() external { + if (s_toRevert) { + bytes memory reason = s_err; + assembly { + revert(add(32, reason), mload(reason)) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol new file mode 100644 index 0000000..2815f99 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol @@ -0,0 +1,347 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IBurnMintERC20} from "../../../token/ERC20/IBurnMintERC20.sol"; +import {IERC677} from "../../../token/ERC677/IERC677.sol"; + +import {BaseTest} from "../../BaseTest.t.sol"; +import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract BurnMintERC677Setup is BaseTest { + event Transfer(address indexed from, address indexed to, uint256 value); + event MintAccessGranted(address indexed minter); + event BurnAccessGranted(address indexed burner); + event MintAccessRevoked(address indexed minter); + event BurnAccessRevoked(address indexed burner); + + BurnMintERC677 internal s_burnMintERC677; + + address internal s_mockPool = address(6243783892); + uint256 internal s_amount = 1e18; + + function setUp() public virtual override { + BaseTest.setUp(); + s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 1e27); + + // Set s_mockPool to be a burner and minter + s_burnMintERC677.grantMintAndBurnRoles(s_mockPool); + deal(address(s_burnMintERC677), OWNER, s_amount); + } +} + +contract BurnMintERC677_constructor is BurnMintERC677Setup { + function testConstructorSuccess() public { + string memory name = "Chainlink token v2"; + string memory symbol = "LINK2"; + uint8 decimals = 19; + uint256 maxSupply = 1e33; + s_burnMintERC677 = new BurnMintERC677(name, symbol, decimals, maxSupply); + + assertEq(name, s_burnMintERC677.name()); + assertEq(symbol, s_burnMintERC677.symbol()); + assertEq(decimals, s_burnMintERC677.decimals()); + assertEq(maxSupply, s_burnMintERC677.maxSupply()); + } +} + +contract BurnMintERC677_approve is BurnMintERC677Setup { + function testApproveSuccess() public { + uint256 balancePre = s_burnMintERC677.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC677.approve(STRANGER, sendingAmount); + + changePrank(STRANGER); + + s_burnMintERC677.transferFrom(OWNER, STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC677.balanceOf(STRANGER)); + } + + // Reverts + + function testInvalidAddressReverts() public { + vm.expectRevert(); + + s_burnMintERC677.approve(address(s_burnMintERC677), s_amount); + } +} + +contract BurnMintERC677_transfer is BurnMintERC677Setup { + function testTransferSuccess() public { + uint256 balancePre = s_burnMintERC677.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC677.transfer(STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC677.balanceOf(STRANGER)); + } + + // Reverts + + function testInvalidAddressReverts() public { + vm.expectRevert(); + + s_burnMintERC677.transfer(address(s_burnMintERC677), s_amount); + } +} + +contract BurnMintERC677_mint is BurnMintERC677Setup { + function testBasicMintSuccess() public { + uint256 balancePre = s_burnMintERC677.balanceOf(OWNER); + + s_burnMintERC677.grantMintAndBurnRoles(OWNER); + + vm.expectEmit(); + emit Transfer(address(0), OWNER, s_amount); + + s_burnMintERC677.mint(OWNER, s_amount); + + assertEq(balancePre + s_amount, s_burnMintERC677.balanceOf(OWNER)); + } + + // Revert + + function testSenderNotMinterReverts() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, OWNER)); + s_burnMintERC677.mint(STRANGER, 1e18); + } + + function testMaxSupplyExceededReverts() public { + changePrank(s_mockPool); + + // Mint max supply + s_burnMintERC677.mint(OWNER, s_burnMintERC677.maxSupply()); + + vm.expectRevert( + abi.encodeWithSelector(BurnMintERC677.MaxSupplyExceeded.selector, s_burnMintERC677.maxSupply() + 1) + ); + + // Attempt to mint 1 more than max supply + s_burnMintERC677.mint(OWNER, 1); + } +} + +contract BurnMintERC677_burn is BurnMintERC677Setup { + function testBasicBurnSuccess() public { + s_burnMintERC677.grantBurnRole(OWNER); + deal(address(s_burnMintERC677), OWNER, s_amount); + + vm.expectEmit(); + emit Transfer(OWNER, address(0), s_amount); + + s_burnMintERC677.burn(s_amount); + + assertEq(0, s_burnMintERC677.balanceOf(OWNER)); + } + + // Revert + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); + + s_burnMintERC677.burnFrom(STRANGER, s_amount); + } + + function testExceedsBalanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC677.burn(s_amount * 2); + } + + function testBurnFromZeroAddressReverts() public { + s_burnMintERC677.grantBurnRole(address(0)); + changePrank(address(0)); + + vm.expectRevert("ERC20: burn from the zero address"); + + s_burnMintERC677.burn(0); + } +} + +contract BurnMintERC677_burnFromAlias is BurnMintERC677Setup { + function setUp() public virtual override { + BurnMintERC677Setup.setUp(); + } + + function testBurnFromSuccess() public { + s_burnMintERC677.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC677.burn(OWNER, s_amount); + + assertEq(0, s_burnMintERC677.balanceOf(OWNER)); + } + + // Reverts + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); + + s_burnMintERC677.burn(OWNER, s_amount); + } + + function testInsufficientAllowanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC677.burn(OWNER, s_amount); + } + + function testExceedsBalanceReverts() public { + s_burnMintERC677.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC677.burn(OWNER, s_amount * 2); + } +} + +contract BurnMintERC677_burnFrom is BurnMintERC677Setup { + function setUp() public virtual override { + BurnMintERC677Setup.setUp(); + } + + function testBurnFromSuccess() public { + s_burnMintERC677.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC677.burnFrom(OWNER, s_amount); + + assertEq(0, s_burnMintERC677.balanceOf(OWNER)); + } + + // Reverts + + function testSenderNotBurnerReverts() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); + + s_burnMintERC677.burnFrom(OWNER, s_amount); + } + + function testInsufficientAllowanceReverts() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC677.burnFrom(OWNER, s_amount); + } + + function testExceedsBalanceReverts() public { + s_burnMintERC677.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC677.burnFrom(OWNER, s_amount * 2); + } +} + +contract BurnMintERC677_grantRole is BurnMintERC677Setup { + function testGrantMintAccessSuccess() public { + assertFalse(s_burnMintERC677.isMinter(STRANGER)); + + vm.expectEmit(); + emit MintAccessGranted(STRANGER); + + s_burnMintERC677.grantMintAndBurnRoles(STRANGER); + + assertTrue(s_burnMintERC677.isMinter(STRANGER)); + + vm.expectEmit(); + emit MintAccessRevoked(STRANGER); + + s_burnMintERC677.revokeMintRole(STRANGER); + + assertFalse(s_burnMintERC677.isMinter(STRANGER)); + } + + function testGrantBurnAccessSuccess() public { + assertFalse(s_burnMintERC677.isBurner(STRANGER)); + + vm.expectEmit(); + emit BurnAccessGranted(STRANGER); + + s_burnMintERC677.grantBurnRole(STRANGER); + + assertTrue(s_burnMintERC677.isBurner(STRANGER)); + + vm.expectEmit(); + emit BurnAccessRevoked(STRANGER); + + s_burnMintERC677.revokeBurnRole(STRANGER); + + assertFalse(s_burnMintERC677.isBurner(STRANGER)); + } + + function testGrantManySuccess() public { + uint256 numberOfPools = 10; + address[] memory permissionedAddresses = new address[](numberOfPools + 1); + permissionedAddresses[0] = s_mockPool; + + for (uint160 i = 0; i < numberOfPools; ++i) { + permissionedAddresses[i + 1] = address(i); + s_burnMintERC677.grantMintAndBurnRoles(address(i)); + } + + assertEq(permissionedAddresses, s_burnMintERC677.getBurners()); + assertEq(permissionedAddresses, s_burnMintERC677.getMinters()); + } +} + +contract BurnMintERC677_grantMintAndBurnRoles is BurnMintERC677Setup { + function testGrantMintAndBurnRolesSuccess() public { + assertFalse(s_burnMintERC677.isMinter(STRANGER)); + assertFalse(s_burnMintERC677.isBurner(STRANGER)); + + vm.expectEmit(); + emit MintAccessGranted(STRANGER); + vm.expectEmit(); + emit BurnAccessGranted(STRANGER); + + s_burnMintERC677.grantMintAndBurnRoles(STRANGER); + + assertTrue(s_burnMintERC677.isMinter(STRANGER)); + assertTrue(s_burnMintERC677.isBurner(STRANGER)); + } +} + +contract BurnMintERC677_decreaseApproval is BurnMintERC677Setup { + function testDecreaseApprovalSuccess() public { + s_burnMintERC677.approve(s_mockPool, s_amount); + uint256 allowance = s_burnMintERC677.allowance(OWNER, s_mockPool); + assertEq(allowance, s_amount); + s_burnMintERC677.decreaseApproval(s_mockPool, s_amount); + assertEq(s_burnMintERC677.allowance(OWNER, s_mockPool), allowance - s_amount); + } +} + +contract BurnMintERC677_increaseApproval is BurnMintERC677Setup { + function testIncreaseApprovalSuccess() public { + s_burnMintERC677.approve(s_mockPool, s_amount); + uint256 allowance = s_burnMintERC677.allowance(OWNER, s_mockPool); + assertEq(allowance, s_amount); + s_burnMintERC677.increaseApproval(s_mockPool, s_amount); + assertEq(s_burnMintERC677.allowance(OWNER, s_mockPool), allowance + s_amount); + } +} + +contract BurnMintERC677_supportsInterface is BurnMintERC677Setup { + function testConstructorSuccess() public view { + assertTrue(s_burnMintERC677.supportsInterface(type(IERC20).interfaceId)); + assertTrue(s_burnMintERC677.supportsInterface(type(IERC677).interfaceId)); + assertTrue(s_burnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); + assertTrue(s_burnMintERC677.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol new file mode 100644 index 0000000..614b3be --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBurnMintERC20} from "../../../token/ERC20/IBurnMintERC20.sol"; +import {IOptimismMintableERC20Minimal, IOptimismMintableERC20} from "../../../token/ERC20/IOptimismMintableERC20.sol"; +import {IERC677} from "../../../token/ERC677/IERC677.sol"; + +import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; +import {OpStackBurnMintERC677} from "../../../token/ERC677/OpStackBurnMintERC677.sol"; + +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract OpStackBurnMintERC677Setup is BaseTest { + address internal s_l1Token = address(897352983527); + address internal s_l2Bridge = address(1928235235); + + OpStackBurnMintERC677 internal s_opStackBurnMintERC677; + + function setUp() public virtual override { + BaseTest.setUp(); + s_opStackBurnMintERC677 = new OpStackBurnMintERC677("Chainlink Token", "LINK", 18, 1e27, s_l1Token, s_l2Bridge); + } +} + +contract OpStackBurnMintERC677_constructor is OpStackBurnMintERC677Setup { + function testConstructorSuccess() public { + string memory name = "Chainlink token l2"; + string memory symbol = "LINK L2"; + uint8 decimals = 18; + uint256 maxSupply = 1e33; + s_opStackBurnMintERC677 = new OpStackBurnMintERC677(name, symbol, decimals, maxSupply, s_l1Token, s_l2Bridge); + + assertEq(name, s_opStackBurnMintERC677.name()); + assertEq(symbol, s_opStackBurnMintERC677.symbol()); + assertEq(decimals, s_opStackBurnMintERC677.decimals()); + assertEq(maxSupply, s_opStackBurnMintERC677.maxSupply()); + assertEq(s_l1Token, s_opStackBurnMintERC677.remoteToken()); + assertEq(s_l2Bridge, s_opStackBurnMintERC677.bridge()); + } +} + +contract OpStackBurnMintERC677_supportsInterface is OpStackBurnMintERC677Setup { + function testConstructorSuccess() public view { + assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IOptimismMintableERC20Minimal).interfaceId)); + assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC677).interfaceId)); + assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); + assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC165).interfaceId)); + } +} + +contract OpStackBurnMintERC677_interfaceCompatibility is OpStackBurnMintERC677Setup { + event Transfer(address indexed from, address indexed to, uint256 value); + + IOptimismMintableERC20 internal s_opStackToken; + + function setUp() public virtual override { + OpStackBurnMintERC677Setup.setUp(); + s_opStackToken = IOptimismMintableERC20(address(s_opStackBurnMintERC677)); + } + + function testStaticFunctionsCompatibility() public { + assertEq(s_l1Token, s_opStackToken.remoteToken()); + assertEq(s_l2Bridge, s_opStackToken.bridge()); + } + + function testMintCompatibility() public { + // Ensure roles work + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, OWNER)); + s_opStackToken.mint(OWNER, 1); + + // Use the actual contract to grant mint + s_opStackBurnMintERC677.grantMintRole(OWNER); + + // Ensure zero address check works + vm.expectRevert("ERC20: mint to the zero address"); + s_opStackToken.mint(address(0x0), 0); + + address mintToAddress = address(0x1); + uint256 mintAmount = 1; + + vm.expectEmit(); + emit Transfer(address(0), mintToAddress, mintAmount); + + s_opStackToken.mint(mintToAddress, mintAmount); + } + + function testBurnCompatibility() public { + // Ensure roles work + vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); + s_opStackToken.burn(address(0x0), 1); + + // Use the actual contract to grant burn + s_opStackBurnMintERC677.grantBurnRole(OWNER); + + // Ensure zero address check works + vm.expectRevert("ERC20: approve from the zero address"); + s_opStackToken.burn(address(0x0), 0); + + address burnFromAddress = address(0x1); + uint256 burnAmount = 1; + + // Ensure `burn(address, amount)` works like burnFrom and requires allowance + vm.expectRevert("ERC20: insufficient allowance"); + s_opStackToken.burn(burnFromAddress, burnAmount); + + changePrank(burnFromAddress); + deal(address(s_opStackToken), burnFromAddress, burnAmount); + s_opStackBurnMintERC677.approve(OWNER, burnAmount); + changePrank(OWNER); + + vm.expectEmit(); + emit Transfer(burnFromAddress, address(0x0), burnAmount); + + s_opStackToken.burn(burnFromAddress, burnAmount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol new file mode 100644 index 0000000..bf88df6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {BaseTest} from "../BaseTest.t.sol"; +import {SortedSetValidationUtil} from "../../../shared/util/SortedSetValidationUtil.sol"; + +contract SortedSetValidationUtilBaseTest is BaseTest { + uint256 constant OFFSET = 5; + + modifier _ensureSetLength(uint256 subsetLength, uint256 supersetLength) { + vm.assume(subsetLength > 0 && supersetLength > 0 && subsetLength <= supersetLength); + _; + } + + function _createSets( + uint256 subsetLength, + uint256 supersetLength + ) internal pure returns (bytes32[] memory subset, bytes32[] memory superset) { + subset = new bytes32[](subsetLength); + superset = new bytes32[](supersetLength); + } + + function _convertArrayToSortedSet(bytes32[] memory arr, uint256 offSet) internal pure { + for (uint256 i = 1; i < arr.length; ++i) { + arr[i] = bytes32(uint256(arr[i - 1]) + offSet); + } + } + + function _convertToUnsortedSet(bytes32[] memory arr, uint256 ptr1, uint256 ptr2) internal pure { + // Swap two elements to make it unsorted + (arr[ptr1], arr[ptr2]) = (arr[ptr2], arr[ptr1]); + } + + function _convertArrayToSubset(bytes32[] memory subset, bytes32[] memory superset) internal pure { + for (uint256 i; i < subset.length; ++i) { + subset[i] = superset[i]; + } + } + + function _makeInvalidSubset(bytes32[] memory subset, bytes32[] memory superset, uint256 ptr) internal pure { + _convertArrayToSubset(subset, superset); + subset[ptr] = bytes32(uint256(subset[ptr]) + 1); + } + + function _convertArrayToHaveDuplicates(bytes32[] memory arr, uint256 ptr1, uint256 ptr2) internal pure { + arr[ptr2] = arr[ptr1]; + } +} + +contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValidationUtilBaseTest { + // Successes. + + function test__checkIsValidUniqueSubset_ValidSubset_Success() public pure { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertArrayToSubset(subset, superset); + + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + // Reverts. + + function test__checkIsValidUniqueSubset_EmptySubset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(0, 5); + _convertArrayToSortedSet(superset, OFFSET); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.EmptySet.selector)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_EmptySuperset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 0); + _convertArrayToSortedSet(subset, OFFSET); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.EmptySet.selector)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_NotASubset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _makeInvalidSubset(subset, superset, 1); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertToUnsortedSet(subset, 1, 2); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, subset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertArrayToSubset(subset, superset); + _convertToUnsortedSet(superset, 1, 2); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, superset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_HasDuplicates_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertArrayToSubset(subset, superset); + _convertArrayToHaveDuplicates(subset, 1, 2); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, subset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(6, 5); + _convertArrayToSortedSet(subset, OFFSET); + _convertArrayToSortedSet(superset, OFFSET); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public pure { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(5, 5); + _convertArrayToSortedSet(subset, OFFSET); + _convertArrayToSortedSet(superset, OFFSET); + + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SingleElementSubset() public pure { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertArrayToSubset(subset, superset); + + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public pure { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); + _convertArrayToSortedSet(subset, OFFSET); + _convertArrayToSortedSet(superset, OFFSET); + + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); + _convertArrayToSortedSet(subset, OFFSET); + superset[0] = bytes32(uint256(subset[0]) + 10); // Different value + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } + + function test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() public { + (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); + _convertArrayToSortedSet(superset, OFFSET); + _convertArrayToSubset(subset, superset); + _convertArrayToHaveDuplicates(superset, 1, 2); + + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, superset)); + SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol new file mode 100644 index 0000000..b9b3b54 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +interface IBurnMintERC20 is IERC20 { + /// @notice Mints new tokens for a given address. + /// @param account The address to mint the new tokens to. + /// @param amount The number of tokens to be minted. + /// @dev this function increases the total supply. + function mint(address account, uint256 amount) external; + + /// @notice Burns tokens from the sender. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burn(uint256 amount) external; + + /// @notice Burns tokens from a given address.. + /// @param account The address to burn tokens from. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burn(address account, uint256 amount) external; + + /// @notice Burns tokens from a given address.. + /// @param account The address to burn tokens from. + /// @param amount The number of tokens to be burned. + /// @dev this function decreases the total supply. + function burnFrom(address account, uint256 amount) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol new file mode 100644 index 0000000..4e9d3a2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// solhint-disable one-contract-per-file +pragma solidity ^0.8.0; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +/// @title IOptimismMintableERC20Minimal +/// @dev This interface is a subset of the Optimism ERC20 interface that is defined +/// below. This is done to now have to overwrite the burn and mint functions again in +/// the implementation, as that leads to more complicated, error prone code. +interface IOptimismMintableERC20Minimal is IERC165 { + /// @notice Returns the address of the token on L1. + function remoteToken() external view returns (address); + + /// @notice Returns the address of the bridge on L2. + function bridge() external returns (address); +} + +/// @title IOptimismMintableERC20 +/// @notice This is the complete interface for the Optimism mintable ERC20 token as defined in +/// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/universal/IOptimismMintableERC20.sol +interface IOptimismMintableERC20 is IERC165, IOptimismMintableERC20Minimal { + function mint(address _to, uint256 _amount) external; + + function burn(address _from, uint256 _amount) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol new file mode 100644 index 0000000..24573f3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IBurnMintERC20} from "../ERC20/IBurnMintERC20.sol"; +import {IERC677} from "./IERC677.sol"; + +import {ERC677} from "./ERC677.sol"; +import {OwnerIsCreator} from "../../access/OwnerIsCreator.sol"; + +import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +/// @notice A basic ERC677 compatible token contract with burn and minting roles. +/// @dev The total supply can be limited during deployment. +contract BurnMintERC677 is IBurnMintERC20, ERC677, IERC165, ERC20Burnable, OwnerIsCreator { + using EnumerableSet for EnumerableSet.AddressSet; + + error SenderNotMinter(address sender); + error SenderNotBurner(address sender); + error MaxSupplyExceeded(uint256 supplyAfterMint); + + event MintAccessGranted(address indexed minter); + event BurnAccessGranted(address indexed burner); + event MintAccessRevoked(address indexed minter); + event BurnAccessRevoked(address indexed burner); + + // @dev the allowed minter addresses + EnumerableSet.AddressSet internal s_minters; + // @dev the allowed burner addresses + EnumerableSet.AddressSet internal s_burners; + + /// @dev The number of decimals for the token + uint8 internal immutable i_decimals; + + /// @dev The maximum supply of the token, 0 if unlimited + uint256 internal immutable i_maxSupply; + + constructor(string memory name, string memory symbol, uint8 decimals_, uint256 maxSupply_) ERC677(name, symbol) { + i_decimals = decimals_; + i_maxSupply = maxSupply_; + } + + function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { + return + interfaceId == type(IERC20).interfaceId || + interfaceId == type(IERC677).interfaceId || + interfaceId == type(IBurnMintERC20).interfaceId || + interfaceId == type(IERC165).interfaceId; + } + + // ================================================================ + // | ERC20 | + // ================================================================ + + /// @dev Returns the number of decimals used in its user representation. + function decimals() public view virtual override returns (uint8) { + return i_decimals; + } + + /// @dev Returns the max supply of the token, 0 if unlimited. + function maxSupply() public view virtual returns (uint256) { + return i_maxSupply; + } + + /// @dev Uses OZ ERC20 _transfer to disallow sending to address(0). + /// @dev Disallows sending to address(this) + function _transfer(address from, address to, uint256 amount) internal virtual override validAddress(to) { + super._transfer(from, to, amount); + } + + /// @dev Uses OZ ERC20 _approve to disallow approving for address(0). + /// @dev Disallows approving for address(this) + function _approve(address owner, address spender, uint256 amount) internal virtual override validAddress(spender) { + super._approve(owner, spender, amount); + } + + /// @dev Exists to be backwards compatible with the older naming convention. + function decreaseApproval(address spender, uint256 subtractedValue) external returns (bool success) { + return decreaseAllowance(spender, subtractedValue); + } + + /// @dev Exists to be backwards compatible with the older naming convention. + function increaseApproval(address spender, uint256 addedValue) external { + increaseAllowance(spender, addedValue); + } + + /// @notice Check if recipient is valid (not this contract address). + /// @param recipient the account we transfer/approve to. + /// @dev Reverts with an empty revert to be compatible with the existing link token when + /// the recipient is this contract address. + modifier validAddress(address recipient) virtual { + // solhint-disable-next-line reason-string, gas-custom-errors + if (recipient == address(this)) revert(); + _; + } + + // ================================================================ + // | Burning & minting | + // ================================================================ + + /// @inheritdoc ERC20Burnable + /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). + /// @dev Decreases the total supply. + function burn(uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyBurner { + super.burn(amount); + } + + /// @inheritdoc IBurnMintERC20 + /// @dev Alias for BurnFrom for compatibility with the older naming convention. + /// @dev Uses burnFrom for all validation & logic. + function burn(address account, uint256 amount) public virtual override { + burnFrom(account, amount); + } + + /// @inheritdoc ERC20Burnable + /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). + /// @dev Decreases the total supply. + function burnFrom(address account, uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyBurner { + super.burnFrom(account, amount); + } + + /// @inheritdoc IBurnMintERC20 + /// @dev Uses OZ ERC20 _mint to disallow minting to address(0). + /// @dev Disallows minting to address(this) + /// @dev Increases the total supply. + function mint(address account, uint256 amount) external override onlyMinter validAddress(account) { + if (i_maxSupply != 0 && totalSupply() + amount > i_maxSupply) revert MaxSupplyExceeded(totalSupply() + amount); + + _mint(account, amount); + } + + // ================================================================ + // | Roles | + // ================================================================ + + /// @notice grants both mint and burn roles to `burnAndMinter`. + /// @dev calls public functions so this function does not require + /// access controls. This is handled in the inner functions. + function grantMintAndBurnRoles(address burnAndMinter) external { + grantMintRole(burnAndMinter); + grantBurnRole(burnAndMinter); + } + + /// @notice Grants mint role to the given address. + /// @dev only the owner can call this function. + function grantMintRole(address minter) public onlyOwner { + if (s_minters.add(minter)) { + emit MintAccessGranted(minter); + } + } + + /// @notice Grants burn role to the given address. + /// @dev only the owner can call this function. + function grantBurnRole(address burner) public onlyOwner { + if (s_burners.add(burner)) { + emit BurnAccessGranted(burner); + } + } + + /// @notice Revokes mint role for the given address. + /// @dev only the owner can call this function. + function revokeMintRole(address minter) public onlyOwner { + if (s_minters.remove(minter)) { + emit MintAccessRevoked(minter); + } + } + + /// @notice Revokes burn role from the given address. + /// @dev only the owner can call this function + function revokeBurnRole(address burner) public onlyOwner { + if (s_burners.remove(burner)) { + emit BurnAccessRevoked(burner); + } + } + + /// @notice Returns all permissioned minters + function getMinters() public view returns (address[] memory) { + return s_minters.values(); + } + + /// @notice Returns all permissioned burners + function getBurners() public view returns (address[] memory) { + return s_burners.values(); + } + + // ================================================================ + // | Access | + // ================================================================ + + /// @notice Checks whether a given address is a minter for this token. + /// @return true if the address is allowed to mint. + function isMinter(address minter) public view returns (bool) { + return s_minters.contains(minter); + } + + /// @notice Checks whether a given address is a burner for this token. + /// @return true if the address is allowed to burn. + function isBurner(address burner) public view returns (bool) { + return s_burners.contains(burner); + } + + /// @notice Checks whether the msg.sender is a permissioned minter for this token + /// @dev Reverts with a SenderNotMinter if the check fails + modifier onlyMinter() { + if (!isMinter(msg.sender)) revert SenderNotMinter(msg.sender); + _; + } + + /// @notice Checks whether the msg.sender is a permissioned burner for this token + /// @dev Reverts with a SenderNotBurner if the check fails + modifier onlyBurner() { + if (!isBurner(msg.sender)) revert SenderNotBurner(msg.sender); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol new file mode 100644 index 0000000..5876ddf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {IERC677} from "./IERC677.sol"; +import {IERC677Receiver} from "../../interfaces/IERC677Receiver.sol"; + +import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; + +contract ERC677 is IERC677, ERC20 { + constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + + /// @inheritdoc IERC677 + function transferAndCall(address to, uint256 amount, bytes memory data) public returns (bool success) { + super.transfer(to, amount); + emit Transfer(msg.sender, to, amount, data); + if (to.code.length > 0) { + IERC677Receiver(to).onTokenTransfer(msg.sender, amount, data); + } + return true; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol new file mode 100644 index 0000000..7e303a4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IERC677 { + event Transfer(address indexed from, address indexed to, uint256 value, bytes data); + + /// @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver + /// @param to The address which you want to transfer to + /// @param amount The amount of tokens to be transferred + /// @param data bytes Additional data with no specified format, sent in call to `to` + /// @return true unless throwing + function transferAndCall(address to, uint256 amount, bytes memory data) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol new file mode 100644 index 0000000..b4640a8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {BurnMintERC677} from "./BurnMintERC677.sol"; + +contract LinkToken is BurnMintERC677 { + constructor() BurnMintERC677("ChainLink Token", "LINK", 18, 1e27) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol new file mode 100644 index 0000000..95c64c9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IOptimismMintableERC20Minimal, IOptimismMintableERC20} from "../ERC20/IOptimismMintableERC20.sol"; + +import {BurnMintERC677} from "./BurnMintERC677.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +/// @notice A basic ERC677 compatible token contract with burn and minting roles that supports +/// the native L2 bridging requirements of the Optimism Stack. +/// @dev Note: the L2 bridge contract needs to be given burn and mint privileges manually, +/// since this contract does not automatically grant them. This allows the owner to revoke +/// the bridge's privileges if necessary. +contract OpStackBurnMintERC677 is BurnMintERC677, IOptimismMintableERC20Minimal { + /// @dev The address of the L1 token. + address internal immutable i_l1Token; + /// @dev The address of the L2 bridge. + address internal immutable i_l2Bridge; + + constructor( + string memory name, + string memory symbol, + uint8 decimals_, + uint256 maxSupply_, + address l1Token, + address l2Bridge + ) BurnMintERC677(name, symbol, decimals_, maxSupply_) { + i_l1Token = l1Token; + i_l2Bridge = l2Bridge; + } + + function supportsInterface(bytes4 interfaceId) public pure virtual override(IERC165, BurnMintERC677) returns (bool) { + return + interfaceId == type(IOptimismMintableERC20).interfaceId || + interfaceId == type(IOptimismMintableERC20Minimal).interfaceId || + super.supportsInterface(interfaceId); + } + + /// @notice Returns the address of the L1 token. + function remoteToken() public view override returns (address) { + return i_l1Token; + } + + /// @notice Returns the address of the L2 bridge. + function bridge() public view override returns (address) { + return i_l2Bridge; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol new file mode 100644 index 0000000..fec11e4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/// @title Sorted Set Validation Utility +/// @notice Provides utility functions for validating sorted sets and their subset relationships. +/// @dev This library is used to ensure that arrays of bytes32 are sorted sets and to check subset relations. +library SortedSetValidationUtil { + /// @dev Error to be thrown when an operation is attempted on an empty set. + error EmptySet(); + /// @dev Error to be thrown when the set is not in ascending unique order. + error NotASortedSet(bytes32[] set); + /// @dev Error to be thrown when the first array is not a subset of the second array. + error NotASubset(bytes32[] subset, bytes32[] superset); + + /// @notice Checks if `subset` is a valid and unique subset of `superset`. + /// NOTE: Empty set is not considered a valid subset of superset for our use case. + /// @dev Both arrays must be valid sets (unique, sorted in ascending order) and `subset` must be entirely contained within `superset`. + /// @param subset The array of bytes32 to validate as a subset. + /// @param superset The array of bytes32 in which subset is checked against. + /// @custom:revert EmptySet If either `subset` or `superset` is empty. + /// @custom:revert NotASubset If `subset` is not a subset of `superset`. + function _checkIsValidUniqueSubset(bytes32[] memory subset, bytes32[] memory superset) internal pure { + if (subset.length == 0 || superset.length == 0) { + revert EmptySet(); + } + + _checkIsValidSet(subset); + _checkIsValidSet(superset); + + uint256 i = 0; // Pointer for 'subset' + uint256 j = 0; // Pointer for 'superset' + + while (i < subset.length && j < superset.length) { + if (subset[i] > superset[j]) { + ++j; // Move the pointer in 'superset' to find a match + } else if (subset[i] == superset[j]) { + ++i; // Found a match, move the pointer in 'subset' + ++j; // Also move in 'superset' to continue checking + } else { + revert NotASubset(subset, superset); + } + } + + if (i < subset.length) { + revert NotASubset(subset, superset); + } + } + + /// @notice Validates that a given set is sorted and has unique elements. + /// @dev Iterates through the array to check that each element is greater than the previous. + /// @param set The array of bytes32 to validate. + /// @custom:revert NotASortedSet If any element is not greater than its predecessor or if any two consecutive elements are equal. + function _checkIsValidSet(bytes32[] memory set) private pure { + for (uint256 i = 1; i < set.length; ++i) { + if (set[i] <= set[i - 1]) { + revert NotASortedSet(set); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol new file mode 100644 index 0000000..e85521a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol @@ -0,0 +1,82 @@ +pragma solidity 0.8.16; + +contract AutomationConsumerBenchmark { + event PerformingUpkeep(uint256 id, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); + + mapping(uint256 => uint256) public initialCall; + mapping(uint256 => uint256) public nextEligible; + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup + mapping(uint256 => uint256) public count; + uint256 deployedAt; + + constructor() { + deployedAt = block.number; + } + + function checkUpkeep(bytes calldata checkData) external view returns (bool, bytes memory) { + ( + uint256 id, + uint256 interval, + uint256 range, + uint256 checkBurnAmount, + uint256 performBurnAmount, + uint256 firstEligibleBuffer + ) = abi.decode(checkData, (uint256, uint256, uint256, uint256, uint256, uint256)); + uint256 startGas = gasleft(); + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + // burn gas + if (checkBurnAmount > 0 && eligible(id, range, firstEligibleBuffer)) { + while (startGas - gasleft() < checkBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + return (eligible(id, range, firstEligibleBuffer), checkData); + } + + function performUpkeep(bytes calldata performData) external { + ( + uint256 id, + uint256 interval, + uint256 range, + uint256 checkBurnAmount, + uint256 performBurnAmount, + uint256 firstEligibleBuffer + ) = abi.decode(performData, (uint256, uint256, uint256, uint256, uint256, uint256)); + require(eligible(id, range, firstEligibleBuffer)); + uint256 startGas = gasleft(); + if (initialCall[id] == 0) { + initialCall[id] = block.number; + } + nextEligible[id] = block.number + interval; + count[id]++; + emit PerformingUpkeep(id, tx.origin, initialCall[id], nextEligible[id], block.number); + // burn gas + bytes32 dummyIndex = blockhash(block.number - 1); + bool dummy; + while (startGas - gasleft() < performBurnAmount) { + dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads + dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); + } + } + + function getCountPerforms(uint256 id) public view returns (uint256) { + return count[id]; + } + + function eligible(uint256 id, uint256 range, uint256 firstEligibleBuffer) internal view returns (bool) { + return + initialCall[id] == 0 + ? block.number >= firstEligibleBuffer + deployedAt + : (block.number - initialCall[id] < range && block.number > nextEligible[id]); + } + + function checkEligible(uint256 id, uint256 range, uint256 firstEligibleBuffer) public view returns (bool) { + return eligible(id, range, firstEligibleBuffer); + } + + function reset() external { + deployedAt = block.number; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol new file mode 100644 index 0000000..21fa9b0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.8.0; + +// Broken is a contract to aid debugging and testing reverting calls during development. +contract Broken { + error Unauthorized(string reason, int256 reason2); + + function revertWithCustomError() public pure { + revert Unauthorized("param", 121); + } + + function revertWithMessage(string memory message) public pure { + require(false, message); + } + + function revertSilently() public pure { + require(false); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol new file mode 100644 index 0000000..a344138 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../ChainlinkClient.sol"; + +contract ChainlinkClientTestHelper is ChainlinkClient { + constructor(address _link, address _oracle) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + } + + event Request(bytes32 id, address callbackAddress, bytes4 callbackfunctionSelector, bytes data); + event LinkAmount(uint256 amount); + + function publicNewRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature) public { + Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); + emit Request(req.id, req.callbackAddress, req.callbackFunctionId, req.buf.buf); + } + + function publicRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature, uint256 _wei) public { + Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); + _sendChainlinkRequest(req, _wei); + } + + function publicRequestRunTo( + address _oracle, + bytes32 _id, + address _address, + bytes memory _fulfillmentSignature, + uint256 _wei + ) public { + Chainlink.Request memory run = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); + _sendChainlinkRequestTo(_oracle, run, _wei); + } + + function publicRequestOracleData(bytes32 _id, bytes memory _fulfillmentSignature, uint256 _wei) public { + Chainlink.Request memory req = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); + _sendOperatorRequest(req, _wei); + } + + function publicRequestOracleDataFrom( + address _oracle, + bytes32 _id, + bytes memory _fulfillmentSignature, + uint256 _wei + ) public { + Chainlink.Request memory run = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); + _sendOperatorRequestTo(_oracle, run, _wei); + } + + function publicCancelRequest( + bytes32 _requestId, + uint256 _payment, + bytes4 _callbackFunctionId, + uint256 _expiration + ) public { + _cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); + } + + function publicChainlinkToken() public view returns (address) { + return _chainlinkTokenAddress(); + } + + function publicFulfillChainlinkRequest(bytes32 _requestId, bytes32) public { + fulfillRequest(_requestId, bytes32(0)); + } + + function fulfillRequest(bytes32 _requestId, bytes32) public { + _validateChainlinkCallback(_requestId); + } + + function publicLINK(uint256 _amount) public { + emit LinkAmount(LINK_DIVISIBILITY * _amount); + } + + function publicOracleAddress() public view returns (address) { + return _chainlinkOracleAddress(); + } + + function publicAddExternalRequest(address _oracle, bytes32 _requestId) public { + _addChainlinkExternalRequest(_oracle, _requestId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol new file mode 100644 index 0000000..d42f30c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../Chainlink.sol"; +import "../vendor/CBORChainlink.sol"; +import "../vendor/BufferChainlink.sol"; + +contract ChainlinkTestHelper { + using Chainlink for Chainlink.Request; + using CBORChainlink for BufferChainlink.buffer; + + Chainlink.Request private req; + + event RequestData(bytes payload); + + function closeEvent() public { + emit RequestData(req.buf.buf); + } + + function setBuffer(bytes memory data) public { + Chainlink.Request memory r2 = req; + r2._setBuffer(data); + req = r2; + } + + function add(string memory _key, string memory _value) public { + Chainlink.Request memory r2 = req; + r2._add(_key, _value); + req = r2; + } + + function addBytes(string memory _key, bytes memory _value) public { + Chainlink.Request memory r2 = req; + r2._addBytes(_key, _value); + req = r2; + } + + function addInt(string memory _key, int256 _value) public { + Chainlink.Request memory r2 = req; + r2._addInt(_key, _value); + req = r2; + } + + function addUint(string memory _key, uint256 _value) public { + Chainlink.Request memory r2 = req; + r2._addUint(_key, _value); + req = r2; + } + + // Temporarily have method receive bytes32[] memory until experimental + // string[] memory can be invoked from truffle tests. + function addStringArray(string memory _key, string[] memory _values) public { + Chainlink.Request memory r2 = req; + r2._addStringArray(_key, _values); + req = r2; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol new file mode 100644 index 0000000..1ceb789 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +contract Counter { + error AlwaysRevert(); + + uint256 public count = 0; + + function increment() public returns (uint256) { + count += 1; + return count; + } + + function reset() public { + count = 0; + } + + function alwaysRevert() public pure { + revert AlwaysRevert(); + } + + function alwaysRevertWithString() public pure { + revert("always revert"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol new file mode 100644 index 0000000..cee50c1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +contract CronReceiver { + event Received1(); + event Received2(); + + function handler1() external { + emit Received1(); + } + + function handler2() external { + emit Received2(); + } + + function revertHandler() external { + revert("revert!"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol new file mode 100644 index 0000000..a29ba36 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import "../automation/upkeeps/ERC20BalanceMonitor.sol"; + +contract ERC20BalanceMonitorExposed is ERC20BalanceMonitor { + constructor( + address erc20TokenAddress, + address keeperRegistryAddress, + uint256 minWaitPeriod + ) ERC20BalanceMonitor(erc20TokenAddress, keeperRegistryAddress, minWaitPeriod) {} + + function setLastTopUpXXXTestOnly(address target, uint56 lastTopUpTimestamp) external { + s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol new file mode 100644 index 0000000..74cc682 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import "../automation/upkeeps/EthBalanceMonitor.sol"; + +contract EthBalanceMonitorExposed is EthBalanceMonitor { + constructor( + address keeperRegistryAddress, + uint256 minWaitPeriod + ) EthBalanceMonitor(keeperRegistryAddress, minWaitPeriod) {} + + function setLastTopUpXXXTestOnly(address target, uint56 lastTopUpTimestamp) external { + s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol new file mode 100644 index 0000000..c9fc623 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; + +contract FeedConsumer { + AggregatorV2V3Interface public immutable AGGREGATOR; + + constructor(address feedAddress) { + AGGREGATOR = AggregatorV2V3Interface(feedAddress); + } + + function latestAnswer() external view returns (int256 answer) { + return AGGREGATOR.latestAnswer(); + } + + function latestTimestamp() external view returns (uint256) { + return AGGREGATOR.latestTimestamp(); + } + + function latestRound() external view returns (uint256) { + return AGGREGATOR.latestRound(); + } + + function getAnswer(uint256 roundId) external view returns (int256) { + return AGGREGATOR.getAnswer(roundId); + } + + function getTimestamp(uint256 roundId) external view returns (uint256) { + return AGGREGATOR.getTimestamp(roundId); + } + + function decimals() external view returns (uint8) { + return AGGREGATOR.decimals(); + } + + function description() external view returns (string memory) { + return AGGREGATOR.description(); + } + + function version() external view returns (uint256) { + return AGGREGATOR.version(); + } + + function getRoundData( + uint80 _roundId + ) + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return AGGREGATOR.getRoundData(_roundId); + } + + function latestRoundData() + external + view + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return AGGREGATOR.latestRoundData(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol new file mode 100644 index 0000000..3e35cae --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../Flags.sol"; + +contract FlagsTestHelper { + Flags public flags; + + constructor(address flagsContract) { + flags = Flags(flagsContract); + } + + function getFlag(address subject) external view returns (bool) { + return flags.getFlag(subject); + } + + function getFlags(address[] calldata subjects) external view returns (bool[] memory) { + return flags.getFlags(subjects); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol new file mode 100644 index 0000000..88ccca5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol @@ -0,0 +1,18 @@ +pragma solidity ^0.8.0; + +import "../shared/access/ConfirmedOwner.sol"; + +contract Greeter is ConfirmedOwner { + string public greeting; + + constructor(address owner) ConfirmedOwner(owner) {} + + function setGreeting(string calldata _greeting) external onlyOwner { + require(bytes(_greeting).length > 0, "Invalid greeting length"); + greeting = _greeting; + } + + function triggerRevert() external pure { + require(false, "Greeter: revert triggered"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol new file mode 100644 index 0000000..2e931c4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../automation/KeeperCompatible.sol"; + +contract KeeperCompatibleTestHelper is KeeperCompatible { + function checkUpkeep(bytes calldata) external override returns (bool, bytes memory) {} + + function performUpkeep(bytes calldata) external override {} + + function verifyCannotExecute() public view cannotExecute {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol new file mode 100644 index 0000000..37306cc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract LogEmitter { + event Log1(uint256); + event Log2(uint256 indexed); + event Log3(string); + event Log4(uint256 indexed, uint256 indexed); + + function EmitLog1(uint256[] memory v) public { + for (uint256 i = 0; i < v.length; i++) { + emit Log1(v[i]); + } + } + + function EmitLog2(uint256[] memory v) public { + for (uint256 i = 0; i < v.length; i++) { + emit Log2(v[i]); + } + } + + function EmitLog3(string[] memory v) public { + for (uint256 i = 0; i < v.length; i++) { + emit Log3(v[i]); + } + } + + function EmitLog4(uint256 v, uint256 w, uint256 c) public { + for (uint256 i = 0; i < c; i++) { + emit Log4(v, w); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol new file mode 100644 index 0000000..f85e028 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol @@ -0,0 +1,11 @@ +pragma solidity 0.8.6; + +contract MockArbGasInfo { + function getCurrentTxL1GasFees() external view returns (uint256) { + return 1000000; + } + + function getPricesInWei() external view returns (uint256, uint256, uint256, uint256, uint256, uint256) { + return (0, 1000, 0, 0, 0, 0); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol new file mode 100644 index 0000000..445a361 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import {IInbox} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; +import {IBridge} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol"; + +contract MockArbitrumInbox is IInbox { + event RetryableTicketNoRefundAliasRewriteCreated( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes data + ); + + function sendL2Message(bytes calldata /* messageData */) external pure override returns (uint256) { + return 0; + } + + function sendUnsignedTransaction( + uint256 /* maxGas */, + uint256 /* gasPriceBid */, + uint256 /* nonce */, + address /* destAddr */, + uint256 /* amount */, + bytes calldata /* data */ + ) external pure override returns (uint256) { + return 0; + } + + function sendContractTransaction( + uint256 /* maxGas */, + uint256 /* gasPriceBid */, + address /* destAddr */, + uint256 /* amount */, + bytes calldata /* data */ + ) external pure override returns (uint256) { + return 0; + } + + function sendL1FundedUnsignedTransaction( + uint256 /* maxGas */, + uint256 /* gasPriceBid */, + uint256 /* nonce */, + address /* destAddr */, + bytes calldata /* data */ + ) external payable override returns (uint256) { + return 0; + } + + function sendL1FundedContractTransaction( + uint256 /* maxGas */, + uint256 /* gasPriceBid */, + address /* destAddr */, + bytes calldata /* data */ + ) external payable override returns (uint256) { + return 0; + } + + function createRetryableTicketNoRefundAliasRewrite( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable override returns (uint256) { + emit RetryableTicketNoRefundAliasRewriteCreated( + destAddr, + arbTxCallValue, + maxSubmissionCost, + submissionRefundAddress, + valueRefundAddress, + maxGas, + gasPriceBid, + data + ); + return 42; + } + + function createRetryableTicket( + address /* destAddr */, + uint256 /* arbTxCallValue */, + uint256 /* maxSubmissionCost */, + address /* submissionRefundAddress */, + address /* valueRefundAddress */, + uint256 /* maxGas */, + uint256 /* gasPriceBid */, + bytes calldata /* data */ + ) external payable override returns (uint256) { + return 0; + } + + function depositEth(address /* destAddr */) external payable override returns (uint256) { + return 0; + } + + function depositEthRetryable( + address /* destAddr */, + uint256 /* maxSubmissionCost */, + uint256 /* maxGas */, + uint256 /* maxGasPrice */ + ) external payable override returns (uint256) { + return 0; + } + + function bridge() external pure override returns (IBridge) { + return IBridge(address(0)); + } + + /// @notice This mock function simply replicates the formula used by Arbitrum's + /// DelayedInbox in the Nitro upgrade. The function has been copied here from the Arbitrum + /// team's repository. + /// @param dataLength The length of the calldata that will be executed in L2 + /// @param baseFee The base fee to pay for the transaction. + /// @dev The calculation will use the L1 base fee if it is passed 0. + function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) public view returns (uint256) { + return (1400 + 6 * dataLength) * (baseFee == 0 ? block.basefee : baseFee); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol new file mode 100644 index 0000000..d685aac --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../shared/interfaces/AggregatorV3Interface.sol"; + +contract MockETHLINKAggregator is AggregatorV3Interface { + int256 public answer; + + constructor(int256 _answer) public { + answer = _answer; + } + + function decimals() external view override returns (uint8) { + return 18; + } + + function description() external view override returns (string memory) { + return "MockETHLINKAggregator"; + } + + function version() external view override returns (uint256) { + return 1; + } + + function getRoundData( + uint80 _roundId + ) + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, block.timestamp, block.timestamp, 1); + } + + function latestRoundData() + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, block.timestamp, block.timestamp, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol new file mode 100644 index 0000000..3184f9d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +contract MockGasBoundCaller { + error TransactionFailed(address target); + + function gasBoundCall(address target, uint256 gasAmount, bytes memory data) external payable { + bool success; + assembly { + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + + // gas bound caller will propagate the revert + if (!success) { + revert TransactionFailed(target); + } + + uint256 pubdataGas = 500000; + bytes memory returnData = abi.encode(address(0), pubdataGas); + + uint256 paddedReturndataLen = returnData.length + 96; + if (paddedReturndataLen % 32 != 0) { + paddedReturndataLen += 32 - (paddedReturndataLen % 32); + } + + assembly { + mstore(sub(returnData, 0x40), 0x40) + mstore(sub(returnData, 0x20), pubdataGas) + return(sub(returnData, 0x40), paddedReturndataLen) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol new file mode 100644 index 0000000..6bb0dae --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +contract MockOVMGasPriceOracle { + function getL1Fee(bytes memory) public pure returns (uint256) { + return 2000000; + } + + function getL1FeeUpperBound(uint256) public pure returns (uint256) { + return 2000000; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol new file mode 100644 index 0000000..a92ff8f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Interface Imports */ +import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; + +contract MockOptimismL1CrossDomainMessenger is IL1CrossDomainMessenger { + uint256 private s_nonce; + + // slither-disable-next-line external-function + function xDomainMessageSender() public pure returns (address) { + return address(0); + } + + function sendMessage(address _target, bytes memory _message, uint32 _gasLimit) public { + emit SentMessage(_target, msg.sender, _message, s_nonce, _gasLimit); + s_nonce++; + } + + /** + * Relays a cross domain message to a contract. + * @inheritdoc IL1CrossDomainMessenger + */ + // slither-disable-next-line external-function + function relayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _messageNonce, + L2MessageInclusionProof memory _proof + ) public {} + + function replayMessage( + address _target, + address _sender, + bytes memory _message, + uint256 _queueIndex, + uint32 _oldGasLimit, + uint32 _newGasLimit + ) public {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol new file mode 100644 index 0000000..38ec337 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* Interface Imports */ +import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; + +contract MockOptimismL2CrossDomainMessenger is IL2CrossDomainMessenger { + uint256 private s_nonce; + address private s_sender; + + // slither-disable-next-line external-function + function xDomainMessageSender() public view returns (address) { + return s_sender; + } + + function setSender(address newSender) external { + s_sender = newSender; + } + + function sendMessage(address _target, bytes memory _message, uint32 _gasLimit) public { + emit SentMessage(_target, msg.sender, _message, s_nonce, _gasLimit); + s_nonce++; + } + + function relayMessage(address _target, address _sender, bytes memory _message, uint256 _messageNonce) external {} + + receive() external payable {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol new file mode 100644 index 0000000..9822d23 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../shared/interfaces/AggregatorV2V3Interface.sol"; + +/** + * @title MockV3Aggregator + * @notice Based on the FluxAggregator contract + * @notice Use this contract when you need to test + * other contract's ability to read data from an + * aggregator contract, but how the aggregator got + * its answer is unimportant + */ +contract MockV3Aggregator is AggregatorV2V3Interface { + uint256 public constant override version = 0; + + uint8 public override decimals; + int256 public override latestAnswer; + uint256 public override latestTimestamp; + uint256 public override latestRound; + + mapping(uint256 => int256) public override getAnswer; + mapping(uint256 => uint256) public override getTimestamp; + mapping(uint256 => uint256) private getStartedAt; + + constructor(uint8 _decimals, int256 _initialAnswer) { + decimals = _decimals; + updateAnswer(_initialAnswer); + } + + function updateAnswer(int256 _answer) public { + latestAnswer = _answer; + latestTimestamp = block.timestamp; + latestRound++; + getAnswer[latestRound] = _answer; + getTimestamp[latestRound] = block.timestamp; + getStartedAt[latestRound] = block.timestamp; + } + + function updateRoundData(uint80 _roundId, int256 _answer, uint256 _timestamp, uint256 _startedAt) public { + latestRound = _roundId; + latestAnswer = _answer; + latestTimestamp = _timestamp; + getAnswer[latestRound] = _answer; + getTimestamp[latestRound] = _timestamp; + getStartedAt[latestRound] = _startedAt; + } + + function getRoundData( + uint80 _roundId + ) + external + view + override + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId); + } + + function latestRoundData() + external + view + override + returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return ( + uint80(latestRound), + getAnswer[latestRound], + getStartedAt[latestRound], + getTimestamp[latestRound], + uint80(latestRound) + ); + } + + function description() external pure override returns (string memory) { + return "v0.8/tests/MockV3Aggregator.sol"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol new file mode 100644 index 0000000..265d4b6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.19; + +contract MockZKSyncSystemContext { + function gasPrice() external pure returns (uint256) { + return 250000000; // 0.25 gwei + } + + function gasPerPubdataByte() external pure returns (uint256) { + return 500; + } + + function getCurrentPubdataSpent() external pure returns (uint256 currentPubdataSpent) { + return 1000; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol new file mode 100644 index 0000000..641bf75 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +contract ReceiveEmitter { + event FundsReceived(uint256 amount, uint256 newBalance); + + receive() external payable { + emit FundsReceived(msg.value, address(this).balance); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol new file mode 100644 index 0000000..618787e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +contract ReceiveFallbackEmitter { + event FundsReceived(uint256 amount, uint256 newBalance); + + fallback() external payable { + emit FundsReceived(msg.value, address(this).balance); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol new file mode 100644 index 0000000..d9a2bdc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +contract ReceiveReverter { + receive() external payable { + revert("Can't send funds"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol new file mode 100644 index 0000000..dec93d5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol @@ -0,0 +1,159 @@ +pragma solidity 0.8.16; + +import "../automation/interfaces/AutomationCompatibleInterface.sol"; +import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; +import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; + +interface IVerifierProxy { + /** + * @notice Verifies that the data encoded has been signed + * correctly by routing to the correct verifier. + * @param signedReport The encoded data to be verified. + * @return verifierResponse The encoded response from the verifier. + */ + function verify(bytes memory signedReport) external returns (bytes memory verifierResponse); +} + +contract StreamsLookupUpkeep is AutomationCompatibleInterface, StreamsLookupCompatibleInterface { + event MercuryPerformEvent(address indexed sender, uint256 indexed blockNumber, bytes v0, bytes verifiedV0, bytes ed); + + ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); + // keep these in sync with verifier proxy in RDD + IVerifierProxy internal constant PRODUCTION_TESTNET_VERIFIER_PROXY = + IVerifierProxy(0x09DFf56A4fF44e0f4436260A04F5CFa65636A481); + IVerifierProxy internal constant STAGING_TESTNET_VERIFIER_PROXY = + IVerifierProxy(0x60448B880c9f3B501af3f343DA9284148BD7D77C); + + uint256 public testRange; + uint256 public interval; + uint256 public previousPerformBlock; + uint256 public initialBlock; + uint256 public counter; + string[] public feeds; + string public feedParamKey; + string public timeParamKey; + bool public immutable useArbBlock; + bool public staging; + bool public verify; + bool public shouldRevertCallback; + bool public callbackReturnBool; + + constructor(uint256 _testRange, uint256 _interval, bool _useArbBlock, bool _staging, bool _verify) { + testRange = _testRange; + interval = _interval; + previousPerformBlock = 0; + initialBlock = 0; + counter = 0; + useArbBlock = _useArbBlock; + feedParamKey = "feedIDs"; // feedIDs for v0.3 + timeParamKey = "timestamp"; // timestamp + // search feeds in notion: "Schema and Feed ID Registry" + feeds = [ + //"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", // ETH / USD in production testnet v0.2 + //"0x4254432d5553442d415242495452554d2d544553544e45540000000000000000" // BTC / USD in production testnet v0.2 + "0x00028c915d6af0fd66bba2d0fc9405226bca8d6806333121a7d9832103d1563c" // ETH / USD in staging testnet v0.3 + ]; + staging = _staging; + verify = _verify; + callbackReturnBool = true; + } + + function setParamKeys(string memory _feedParamKey, string memory _timeParamKey) external { + feedParamKey = _feedParamKey; + timeParamKey = _timeParamKey; + } + + function setFeeds(string[] memory _feeds) external { + feeds = _feeds; + } + + function setShouldRevertCallback(bool value) public { + shouldRevertCallback = value; + } + + function setCallbackReturnBool(bool value) public { + callbackReturnBool = value; + } + + function reset() public { + previousPerformBlock = 0; + initialBlock = 0; + counter = 0; + } + + function checkCallback(bytes[] memory values, bytes memory extraData) external view returns (bool, bytes memory) { + require(!shouldRevertCallback, "shouldRevertCallback is true"); + // do sth about the chainlinkBlob data in values and extraData + bytes memory performData = abi.encode(values, extraData); + return (callbackReturnBool, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (false, new bytes(0)); + } + + function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { + if (!eligible()) { + return (false, data); + } + uint256 timeParam; + if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { + if (useArbBlock) { + timeParam = ARB_SYS.arbBlockNumber(); + } else { + timeParam = block.number; + } + } else { + // assume this will be feedIDs for v0.3 + timeParam = block.timestamp; + } + + // encode ARB_SYS as extraData to verify that it is provided to checkCallback correctly. + // in reality, this can be any data or empty + revert StreamsLookup(feedParamKey, feeds, timeParamKey, timeParam, abi.encodePacked(address(ARB_SYS))); + } + + function performUpkeep(bytes calldata performData) external { + uint256 blockNumber; + if (useArbBlock) { + blockNumber = ARB_SYS.arbBlockNumber(); + } else { + blockNumber = block.number; + } + if (initialBlock == 0) { + initialBlock = blockNumber; + } + (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + previousPerformBlock = blockNumber; + counter = counter + 1; + + bytes memory v0 = ""; + bytes memory v1 = ""; + if (verify) { + if (staging) { + v0 = STAGING_TESTNET_VERIFIER_PROXY.verify(values[0]); + } else { + v0 = PRODUCTION_TESTNET_VERIFIER_PROXY.verify(values[0]); + } + } + emit MercuryPerformEvent(msg.sender, blockNumber, values[0], v0, extraData); + } + + function eligible() public view returns (bool) { + if (initialBlock == 0) { + return true; + } + + uint256 blockNumber; + if (useArbBlock) { + blockNumber = ARB_SYS.arbBlockNumber(); + } else { + blockNumber = block.number; + } + return (blockNumber - initialBlock) < testRange && (blockNumber - previousPerformBlock) >= interval; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol new file mode 100644 index 0000000..18b9960 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract VRFLogEmitter { + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint64 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); + + function emitRandomWordsRequested( + bytes32 keyHash, + uint256 requestId, + uint256 preSeed, + uint64 subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address sender + ) public { + emit RandomWordsRequested( + keyHash, + requestId, + preSeed, + subId, + minimumRequestConfirmations, + callbackGasLimit, + numWords, + sender + ); + } + + function emitRandomWordsFulfilled(uint256 requestId, uint256 outputSeed, uint96 payment, bool success) public { + emit RandomWordsFulfilled(requestId, outputSeed, payment, success); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol new file mode 100644 index 0000000..86ebf8b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol @@ -0,0 +1,572 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {IKeeperRegistryMaster, IAutomationV21PlusCommon} from "../automation/interfaces/v2_1/IKeeperRegistryMaster.sol"; +import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import "../automation/v2_1/AutomationRegistrar2_1.sol"; +import {LogTriggerConfig} from "../automation/v2_1/AutomationUtils2_1.sol"; + +abstract contract VerifiableLoadBase is ConfirmedOwner { + error IndexOutOfRange(); + event LogEmitted(uint256 indexed upkeepId, uint256 indexed blockNum, address indexed addr); + event LogEmittedAgain(uint256 indexed upkeepId, uint256 indexed blockNum, address indexed addr); + event UpkeepTopUp(uint256 upkeepId, uint96 amount, uint256 blockNum); + + using EnumerableSet for EnumerableSet.UintSet; + ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); + //bytes32 public constant emittedSig = 0x97009585a4d2440f981ab6f6eec514343e1e6b2aa9b991a26998e6806f41bf08; //keccak256(LogEmitted(uint256,uint256,address)) + bytes32 public immutable emittedSig = LogEmitted.selector; + // bytes32 public constant emittedAgainSig = 0xc76416badc8398ce17c93eab7b4f60f263241694cf503e4df24f233a8cc1c50d; //keccak256(LogEmittedAgain(uint256,uint256,address)) + bytes32 public immutable emittedAgainSig = LogEmittedAgain.selector; + + mapping(uint256 => uint256) public lastTopUpBlocks; + mapping(uint256 => uint256) public intervals; + mapping(uint256 => uint256) public previousPerformBlocks; + mapping(uint256 => uint256) public firstPerformBlocks; + mapping(uint256 => uint256) public counters; + mapping(uint256 => uint256) public performGasToBurns; + mapping(uint256 => uint256) public checkGasToBurns; + mapping(uint256 => uint256) public performDataSizes; + mapping(uint256 => uint256) public gasLimits; + mapping(bytes32 => bool) public dummyMap; // used to force storage lookup + mapping(uint256 => uint256[]) public delays; // how to query for delays for a certain past period: calendar day and/or past 24 hours + + mapping(uint256 => mapping(uint16 => uint256[])) public bucketedDelays; + mapping(uint256 => uint16) public buckets; + EnumerableSet.UintSet internal s_upkeepIDs; + AutomationRegistrar2_1 public registrar; + LinkTokenInterface public linkToken; + IKeeperRegistryMaster public registry; + // check if an upkeep is eligible for adding funds at this interval + uint256 public upkeepTopUpCheckInterval = 5; + // an upkeep will get this amount of LINK for every top up + uint96 public addLinkAmount = 200000000000000000; // 0.2 LINK + // if an upkeep's balance is less than this threshold * min balance, this upkeep is eligible for adding funds + uint8 public minBalanceThresholdMultiplier = 20; + // if this contract is using arbitrum block number + bool public immutable useArbitrumBlockNum; + + // the following fields are immutable bc if they are adjusted, the existing upkeeps' delays will be stored in + // different sizes of buckets. it's better to redeploy this contract with new values. + uint16 public immutable BUCKET_SIZE = 100; + + // search feeds in notion: "Schema and Feed ID Registry" + string[] public feedsHex = [ + "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", + "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000" + ]; + string public feedParamKey = "feedIdHex"; // feedIDs for v0.3 + string public timeParamKey = "blockNumber"; // timestamp for v0.3 + + /** + * @param _registrar a automation registrar 2.1 address + * @param _useArb if this contract will use arbitrum block number + */ + constructor(AutomationRegistrar2_1 _registrar, bool _useArb) ConfirmedOwner(msg.sender) { + registrar = _registrar; + (address registryAddress, ) = registrar.getConfig(); + registry = IKeeperRegistryMaster(payable(address(registryAddress))); + linkToken = registrar.LINK(); + useArbitrumBlockNum = _useArb; + } + + receive() external payable {} + + function setParamKeys(string memory _feedParamKey, string memory _timeParamKey) external { + feedParamKey = _feedParamKey; + timeParamKey = _timeParamKey; + } + + function setFeeds(string[] memory _feeds) external { + feedsHex = _feeds; + } + + /** + * @notice withdraws LINKs from this contract to msg sender when testing is finished. + */ + function withdrawLinks() external onlyOwner { + uint256 balance = linkToken.balanceOf(address(this)); + linkToken.transfer(msg.sender, balance); + } + + function getBlockNumber() internal view returns (uint256) { + if (useArbitrumBlockNum) { + return ARB_SYS.arbBlockNumber(); + } else { + return block.number; + } + } + + /** + * @notice sets registrar, registry, and link token address. + * @param newRegistrar the new registrar address + */ + function setConfig(AutomationRegistrar2_1 newRegistrar) external { + registrar = newRegistrar; + (address registryAddress, ) = registrar.getConfig(); + registry = IKeeperRegistryMaster(payable(address(registryAddress))); + linkToken = registrar.LINK(); + } + + /** + * @notice gets an array of active upkeep IDs. + * @param startIndex the start index of upkeep IDs + * @param maxCount the max number of upkeep IDs requested + * @return an array of active upkeep IDs + */ + function getActiveUpkeepIDsDeployedByThisContract( + uint256 startIndex, + uint256 maxCount + ) external view returns (uint256[] memory) { + uint256 maxIdx = s_upkeepIDs.length(); + if (startIndex >= maxIdx) revert IndexOutOfRange(); + if (maxCount == 0) { + maxCount = maxIdx - startIndex; + } + uint256[] memory ids = new uint256[](maxCount); + for (uint256 idx = 0; idx < maxCount; idx++) { + ids[idx] = s_upkeepIDs.at(startIndex + idx); + } + return ids; + } + + /** + * @notice gets an array of active upkeep IDs. + * @param startIndex the start index of upkeep IDs + * @param maxCount the max number of upkeep IDs requested + * @return an array of active upkeep IDs + */ + function getAllActiveUpkeepIDsOnRegistry( + uint256 startIndex, + uint256 maxCount + ) external view returns (uint256[] memory) { + return registry.getActiveUpkeepIDs(startIndex, maxCount); + } + + /** + * @notice register an upkeep via the registrar. + * @param params a registration params struct + * @return an upkeep ID + */ + function _registerUpkeep(AutomationRegistrar2_1.RegistrationParams memory params) private returns (uint256) { + uint256 upkeepId = registrar.registerUpkeep(params); + s_upkeepIDs.add(upkeepId); + gasLimits[upkeepId] = params.gasLimit; + return upkeepId; + } + + /** + * @notice returns a log trigger config + */ + function getLogTriggerConfig( + address addr, + uint8 selector, + bytes32 topic0, + bytes32 topic1, + bytes32 topic2, + bytes32 topic3 + ) external view returns (bytes memory logTrigger) { + LogTriggerConfig memory cfg = LogTriggerConfig({ + contractAddress: addr, + filterSelector: selector, + topic0: topic0, + topic1: topic1, + topic2: topic2, + topic3: topic3 + }); + return abi.encode(cfg); + } + + // this function sets pipeline data and trigger config for log trigger upkeeps + function batchPreparingUpkeeps( + uint256[] calldata upkeepIds, + uint8 selector, + bytes32 topic0, + bytes32 topic1, + bytes32 topic2, + bytes32 topic3 + ) external { + uint256 len = upkeepIds.length; + for (uint256 i = 0; i < len; i++) { + uint256 upkeepId = upkeepIds[i]; + + this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); + + uint8 triggerType = registry.getTriggerType(upkeepId); + if (triggerType == 1) { + // currently no using a filter selector + bytes memory triggerCfg = this.getLogTriggerConfig(address(this), selector, topic0, topic2, topic2, topic3); + registry.setUpkeepTriggerConfig(upkeepId, triggerCfg); + } + } + } + + // this function sets pipeline data and trigger config for log trigger upkeeps + function batchPreparingUpkeepsSimple(uint256[] calldata upkeepIds, uint8 log, uint8 selector) external { + uint256 len = upkeepIds.length; + for (uint256 i = 0; i < len; i++) { + uint256 upkeepId = upkeepIds[i]; + + this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); + + uint8 triggerType = registry.getTriggerType(upkeepId); + if (triggerType == 1) { + // currently no using a filter selector + bytes32 sig = emittedSig; + if (log != 0) { + sig = emittedAgainSig; + } + bytes memory triggerCfg = this.getLogTriggerConfig( + address(this), + selector, + sig, + bytes32(abi.encode(upkeepId)), + bytes32(0), + bytes32(0) + ); + registry.setUpkeepTriggerConfig(upkeepId, triggerCfg); + } + } + } + + function updateLogTriggerConfig1( + uint256 upkeepId, + address addr, + uint8 selector, + bytes32 topic0, + bytes32 topic1, + bytes32 topic2, + bytes32 topic3 + ) external { + registry.setUpkeepTriggerConfig(upkeepId, this.getLogTriggerConfig(addr, selector, topic0, topic1, topic2, topic3)); + } + + function updateLogTriggerConfig2(uint256 upkeepId, bytes calldata cfg) external { + registry.setUpkeepTriggerConfig(upkeepId, cfg); + } + + /** + * @notice batch registering upkeeps. + * @param number the number of upkeeps to be registered + * @param gasLimit the gas limit of each upkeep + * @param triggerType the trigger type of this upkeep, 0 for conditional, 1 for log trigger + * @param triggerConfig the trigger config of this upkeep + * @param amount the amount of LINK to fund each upkeep + * @param checkGasToBurn the amount of check gas to burn + * @param performGasToBurn the amount of perform gas to burn + */ + function batchRegisterUpkeeps( + uint8 number, + uint32 gasLimit, + uint8 triggerType, + bytes memory triggerConfig, + uint96 amount, + uint256 checkGasToBurn, + uint256 performGasToBurn + ) external { + AutomationRegistrar2_1.RegistrationParams memory params = AutomationRegistrar2_1.RegistrationParams({ + name: "test", + encryptedEmail: bytes(""), + upkeepContract: address(this), + gasLimit: gasLimit, + adminAddress: address(this), // use address of this contract as the admin + triggerType: triggerType, + checkData: bytes(""), // update pipeline data later bc upkeep id is not available now + triggerConfig: triggerConfig, + offchainConfig: bytes(""), + amount: amount + }); + + linkToken.approve(address(registrar), amount * number); + + uint256[] memory upkeepIds = new uint256[](number); + for (uint8 i = 0; i < number; i++) { + uint256 upkeepId = _registerUpkeep(params); + upkeepIds[i] = upkeepId; + checkGasToBurns[upkeepId] = checkGasToBurn; + performGasToBurns[upkeepId] = performGasToBurn; + } + } + + function topUpFund(uint256 upkeepId, uint256 blockNum) public { + if (blockNum - lastTopUpBlocks[upkeepId] > upkeepTopUpCheckInterval) { + IAutomationV21PlusCommon.UpkeepInfoLegacy memory info = registry.getUpkeep(upkeepId); + uint96 minBalance = registry.getMinBalanceForUpkeep(upkeepId); + if (info.balance < minBalanceThresholdMultiplier * minBalance) { + addFunds(upkeepId, addLinkAmount); + lastTopUpBlocks[upkeepId] = blockNum; + emit UpkeepTopUp(upkeepId, addLinkAmount, blockNum); + } + } + } + + function getMinBalanceForUpkeep(uint256 upkeepId) external view returns (uint96) { + return registry.getMinBalanceForUpkeep(upkeepId); + } + + function getForwarder(uint256 upkeepID) external view returns (address) { + return registry.getForwarder(upkeepID); + } + + function getBalance(uint256 id) external view returns (uint96 balance) { + return registry.getBalance(id); + } + + function getTriggerType(uint256 upkeepId) external view returns (uint8) { + return registry.getTriggerType(upkeepId); + } + + function burnPerformGas(uint256 upkeepId, uint256 startGas, uint256 blockNum) public { + uint256 performGasToBurn = performGasToBurns[upkeepId]; + while (startGas - gasleft() + 10000 < performGasToBurn) { + dummyMap[blockhash(blockNum)] = false; + } + } + + /** + * @notice adds fund for an upkeep. + * @param upkeepId the upkeep ID + * @param amount the amount of LINK to be funded for the upkeep + */ + function addFunds(uint256 upkeepId, uint96 amount) public { + linkToken.approve(address(registry), amount); + registry.addFunds(upkeepId, amount); + } + + /** + * @notice updates pipeline data for an upkeep. In order for the upkeep to be performed, the pipeline data must be the abi encoded upkeep ID. + * @param upkeepId the upkeep ID + * @param pipelineData the new pipeline data for the upkeep + */ + function updateUpkeepPipelineData(uint256 upkeepId, bytes calldata pipelineData) external { + registry.setUpkeepCheckData(upkeepId, pipelineData); + } + + function withdrawLinks(uint256 upkeepId) external { + registry.withdrawFunds(upkeepId, address(this)); + } + + function batchWithdrawLinks(uint256[] calldata upkeepIds) external { + uint256 len = upkeepIds.length; + for (uint32 i = 0; i < len; i++) { + this.withdrawLinks(upkeepIds[i]); + } + } + + /** + * @notice batch canceling upkeeps. + * @param upkeepIds an array of upkeep IDs + */ + function batchCancelUpkeeps(uint256[] calldata upkeepIds) external { + uint256 len = upkeepIds.length; + for (uint8 i = 0; i < len; i++) { + registry.cancelUpkeep(upkeepIds[i]); + s_upkeepIDs.remove(upkeepIds[i]); + } + } + + function eligible(uint256 upkeepId) public view returns (bool) { + if (firstPerformBlocks[upkeepId] == 0) { + return true; + } + return (getBlockNumber() - previousPerformBlocks[upkeepId]) >= intervals[upkeepId]; + } + + // /** + // * @notice set a new add LINK amount. + // * @param amount the new value + // */ + // function setAddLinkAmount(uint96 amount) external { + // addLinkAmount = amount; + // } + // + // function setUpkeepTopUpCheckInterval(uint256 newInterval) external { + // upkeepTopUpCheckInterval = newInterval; + // } + // + // function setMinBalanceThresholdMultiplier(uint8 newMinBalanceThresholdMultiplier) external { + // minBalanceThresholdMultiplier = newMinBalanceThresholdMultiplier; + // } + + // function setPerformGasToBurn(uint256 upkeepId, uint256 value) public { + // performGasToBurns[upkeepId] = value; + // } + // + // function setCheckGasToBurn(uint256 upkeepId, uint256 value) public { + // checkGasToBurns[upkeepId] = value; + // } + + function setPerformDataSize(uint256 upkeepId, uint256 value) public { + performDataSizes[upkeepId] = value; + } + + function setUpkeepGasLimit(uint256 upkeepId, uint32 gasLimit) public { + registry.setUpkeepGasLimit(upkeepId, gasLimit); + gasLimits[upkeepId] = gasLimit; + } + + function setInterval(uint256 upkeepId, uint256 _interval) external { + intervals[upkeepId] = _interval; + firstPerformBlocks[upkeepId] = 0; + counters[upkeepId] = 0; + + delete delays[upkeepId]; + uint16 currentBucket = buckets[upkeepId]; + for (uint16 i = 0; i <= currentBucket; i++) { + delete bucketedDelays[upkeepId][i]; + } + delete buckets[upkeepId]; + } + + /** + * @notice batch setting intervals for an array of upkeeps. + * @param upkeepIds an array of upkeep IDs + * @param interval a new interval + */ + function batchSetIntervals(uint256[] calldata upkeepIds, uint32 interval) external { + uint256 len = upkeepIds.length; + for (uint256 i = 0; i < len; i++) { + this.setInterval(upkeepIds[i], interval); + } + } + + /** + * @notice batch updating pipeline data for all upkeeps. + * @param upkeepIds an array of upkeep IDs + */ + function batchUpdatePipelineData(uint256[] calldata upkeepIds) external { + uint256 len = upkeepIds.length; + for (uint256 i = 0; i < len; i++) { + uint256 upkeepId = upkeepIds[i]; + this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); + } + } + + /** + * @notice finds all log trigger upkeeps and emits logs to serve as the initial trigger for upkeeps + */ + function batchSendLogs(uint8 log) external { + uint256[] memory upkeepIds = this.getActiveUpkeepIDsDeployedByThisContract(0, 0); + uint256 len = upkeepIds.length; + uint256 blockNum = getBlockNumber(); + for (uint256 i = 0; i < len; i++) { + uint256 upkeepId = upkeepIds[i]; + uint8 triggerType = registry.getTriggerType(upkeepId); + if (triggerType == 1) { + if (log == 0) { + emit LogEmitted(upkeepId, blockNum, address(this)); + } else { + emit LogEmittedAgain(upkeepId, blockNum, address(this)); + } + } + } + } + + function getUpkeepInfo(uint256 upkeepId) public view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory) { + return registry.getUpkeep(upkeepId); + } + + function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { + return registry.getUpkeepTriggerConfig(upkeepId); + } + + function getUpkeepPrivilegeConfig(uint256 upkeepId) public view returns (bytes memory) { + return registry.getUpkeepPrivilegeConfig(upkeepId); + } + + function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory cfg) external { + registry.setUpkeepPrivilegeConfig(upkeepId, cfg); + } + + function sendLog(uint256 upkeepId, uint8 log) external { + uint256 blockNum = getBlockNumber(); + if (log == 0) { + emit LogEmitted(upkeepId, blockNum, address(this)); + } else { + emit LogEmittedAgain(upkeepId, blockNum, address(this)); + } + } + + function getDelaysLength(uint256 upkeepId) public view returns (uint256) { + return delays[upkeepId].length; + } + + function getBucketedDelaysLength(uint256 upkeepId) public view returns (uint256) { + uint16 currentBucket = buckets[upkeepId]; + uint256 len = 0; + for (uint16 i = 0; i <= currentBucket; i++) { + len += bucketedDelays[upkeepId][i].length; + } + return len; + } + + function getDelays(uint256 upkeepId) public view returns (uint256[] memory) { + return delays[upkeepId]; + } + + function getBucketedDelays(uint256 upkeepId, uint16 bucket) public view returns (uint256[] memory) { + return bucketedDelays[upkeepId][bucket]; + } + + function getSumDelayLastNPerforms(uint256 upkeepId, uint256 n) public view returns (uint256, uint256) { + uint256[] memory delays = delays[upkeepId]; + return getSumDelayLastNPerforms(delays, n); + } + + function getSumDelayInBucket(uint256 upkeepId, uint16 bucket) public view returns (uint256, uint256) { + uint256[] memory delays = bucketedDelays[upkeepId][bucket]; + return getSumDelayLastNPerforms(delays, delays.length); + } + + function getSumDelayLastNPerforms(uint256[] memory delays, uint256 n) internal view returns (uint256, uint256) { + uint256 i; + uint256 len = delays.length; + if (n == 0 || n >= len) { + n = len; + } + uint256 sum = 0; + + for (i = 0; i < n; i++) sum = sum + delays[len - i - 1]; + return (sum, n); + } + + function getPxDelayLastNPerforms(uint256 upkeepId, uint256 p, uint256 n) public view returns (uint256) { + return getPxDelayLastNPerforms(delays[upkeepId], p, n); + } + + function getPxDelayLastNPerforms(uint256[] memory delays, uint256 p, uint256 n) internal view returns (uint256) { + uint256 i; + uint256 len = delays.length; + if (n == 0 || n >= len) { + n = len; + } + uint256[] memory subArr = new uint256[](n); + + for (i = 0; i < n; i++) subArr[i] = (delays[len - i - 1]); + quickSort(subArr, int256(0), int256(subArr.length - 1)); + + if (p == 100) { + return subArr[subArr.length - 1]; + } + return subArr[(p * subArr.length) / 100]; + } + + function quickSort(uint256[] memory arr, int256 left, int256 right) private pure { + int256 i = left; + int256 j = right; + if (i == j) return; + uint256 pivot = arr[uint256(left + (right - left) / 2)]; + while (i <= j) { + while (arr[uint256(i)] < pivot) i++; + while (pivot < arr[uint256(j)]) j--; + if (i <= j) { + (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); + i++; + j--; + } + } + if (left < j) quickSort(arr, left, j); + if (i < right) quickSort(arr, i, right); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol new file mode 100644 index 0000000..39b95bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import "./VerifiableLoadBase.sol"; +import "../automation/interfaces/ILogAutomation.sol"; +import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; + +contract VerifiableLoadLogTriggerUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface, ILogAutomation { + bool public useMercury; + uint8 public logNum; + + /** + * @param _registrar a automation registrar 2.1 address + * @param _useArb if this contract will use arbitrum block number + * @param _useMercury if the log trigger upkeeps will use mercury lookup + */ + constructor( + AutomationRegistrar2_1 _registrar, + bool _useArb, + bool _useMercury + ) VerifiableLoadBase(_registrar, _useArb) { + useMercury = _useMercury; + logNum = 0; + } + + function setLog(uint8 _log) external { + logNum = _log; + } + + function checkLog(Log calldata log, bytes memory checkData) external returns (bool, bytes memory) { + uint256 startGas = gasleft(); + uint256 blockNum = getBlockNumber(); + uint256 uid = abi.decode(checkData, (uint256)); + + bytes32 sig = emittedSig; + if (logNum != 0) { + sig = emittedAgainSig; + } + // filter by event signature + if (log.topics[0] == sig) { + bytes memory t1 = abi.encodePacked(log.topics[1]); // bytes32 to bytes + uint256 upkeepId = abi.decode(t1, (uint256)); + if (upkeepId != uid) { + revert("upkeep ids don't match"); + } + bytes memory t2 = abi.encodePacked(log.topics[2]); + uint256 blockNum = abi.decode(t2, (uint256)); + + bytes memory t3 = abi.encodePacked(log.topics[3]); + address addr = abi.decode(t3, (address)); + + uint256 checkGasToBurn = checkGasToBurns[upkeepId]; + while (startGas - gasleft() + 15000 < checkGasToBurn) { + dummyMap[blockhash(blockNum)] = false; + } + + uint256 timeParam; + if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { + timeParam = blockNum; + } else { + // assume this will be feedIDs for v0.3 + timeParam = block.timestamp; + } + + if (useMercury) { + revert StreamsLookup(feedParamKey, feedsHex, timeParamKey, timeParam, abi.encode(upkeepId, blockNum, addr)); + } + + // if we don't use mercury, create a perform data which resembles the output of checkCallback + bytes[] memory values = new bytes[](feedsHex.length); + bytes memory extraData = abi.encode(upkeepId, blockNum, addr); + return (true, abi.encode(values, extraData)); + } + revert("unexpected event sig"); + } + + function performUpkeep(bytes calldata performData) external { + uint256 startGas = gasleft(); + (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + (uint256 upkeepId, uint256 logBlockNumber, address addr) = abi.decode(extraData, (uint256, uint256, address)); + + uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; + uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; + uint256 currentBlockNum = getBlockNumber(); + + if (firstPerformBlock == 0) { + firstPerformBlocks[upkeepId] = currentBlockNum; + } else { + uint256 delay = currentBlockNum - logBlockNumber; + uint16 bucket = buckets[upkeepId]; + uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; + if (bucketDelays.length == BUCKET_SIZE) { + bucket++; + buckets[upkeepId] = bucket; + } + bucketedDelays[upkeepId][bucket].push(delay); + delays[upkeepId].push(delay); + } + + uint256 counter = counters[upkeepId] + 1; + counters[upkeepId] = counter; + previousPerformBlocks[upkeepId] = currentBlockNum; + + // for every upkeepTopUpCheckInterval (5), check if the upkeep balance is at least + // minBalanceThresholdMultiplier (20) * min balance. If not, add addLinkAmount (0.2) to the upkeep + // upkeepTopUpCheckInterval, minBalanceThresholdMultiplier, and addLinkAmount are configurable + topUpFund(upkeepId, currentBlockNum); + emit LogEmitted(upkeepId, currentBlockNum, address(this)); + burnPerformGas(upkeepId, startGas, currentBlockNum); + } + + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external pure override returns (bool, bytes memory) { + bytes memory performData = abi.encode(values, extraData); + return (true, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (false, new bytes(0)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol new file mode 100644 index 0000000..c74aec1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import "./VerifiableLoadBase.sol"; +import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; + +contract VerifiableLoadStreamsLookupUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface { + constructor(AutomationRegistrar2_1 _registrar, bool _useArb) VerifiableLoadBase(_registrar, _useArb) {} + + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external pure override returns (bool, bytes memory) { + // do sth about the chainlinkBlob data in values and extraData + bytes memory performData = abi.encode(values, extraData); + return (true, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + // dummy function with default values + return (false, new bytes(0)); + } + + function checkUpkeep(bytes calldata checkData) external returns (bool, bytes memory) { + uint256 startGas = gasleft(); + uint256 upkeepId = abi.decode(checkData, (uint256)); + + uint256 performDataSize = performDataSizes[upkeepId]; + uint256 checkGasToBurn = checkGasToBurns[upkeepId]; + bytes memory pData = abi.encode(upkeepId, new bytes(performDataSize)); + uint256 blockNum = getBlockNumber(); + bool needed = eligible(upkeepId); + while (startGas - gasleft() + 10000 < checkGasToBurn) { + // 10K margin over gas to burn + // Hard coded check gas to burn + dummyMap[blockhash(blockNum)] = false; // arbitrary storage writes + } + if (!needed) { + return (false, pData); + } + + uint256 timeParam; + if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { + timeParam = blockNum; + } else { + // assume this will be feedIDs for v0.3 + timeParam = block.timestamp; + } + + revert StreamsLookup(feedParamKey, feedsHex, timeParamKey, timeParam, abi.encode(upkeepId)); + } + + function performUpkeep(bytes calldata performData) external { + uint256 startGas = gasleft(); + (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + uint256 upkeepId = abi.decode(extraData, (uint256)); + uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; + uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; + uint256 blockNum = getBlockNumber(); + + if (firstPerformBlock == 0) { + firstPerformBlocks[upkeepId] = blockNum; + } else { + uint256 delay = blockNum - previousPerformBlock - intervals[upkeepId]; + uint16 bucket = buckets[upkeepId]; + uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; + if (bucketDelays.length == BUCKET_SIZE) { + bucket++; + buckets[upkeepId] = bucket; + } + bucketedDelays[upkeepId][bucket].push(delay); + delays[upkeepId].push(delay); + } + + uint256 counter = counters[upkeepId] + 1; + counters[upkeepId] = counter; + previousPerformBlocks[upkeepId] = blockNum; + + topUpFund(upkeepId, blockNum); + burnPerformGas(upkeepId, startGas, blockNum); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol new file mode 100644 index 0000000..bab75e9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.16; + +import "./VerifiableLoadBase.sol"; + +contract VerifiableLoadUpkeep is VerifiableLoadBase { + constructor(AutomationRegistrar2_1 _registrar, bool _useArb) VerifiableLoadBase(_registrar, _useArb) {} + + function checkUpkeep(bytes calldata checkData) external returns (bool, bytes memory) { + uint256 startGas = gasleft(); + uint256 upkeepId = abi.decode(checkData, (uint256)); + + uint256 performDataSize = performDataSizes[upkeepId]; + uint256 checkGasToBurn = checkGasToBurns[upkeepId]; + bytes memory pData = abi.encode(upkeepId, new bytes(performDataSize)); + uint256 blockNum = getBlockNumber(); + bool needed = eligible(upkeepId); + while (startGas - gasleft() + 10000 < checkGasToBurn) { + dummyMap[blockhash(blockNum)] = false; + blockNum--; + } + return (needed, pData); + } + + function performUpkeep(bytes calldata performData) external { + uint256 startGas = gasleft(); + (uint256 upkeepId, ) = abi.decode(performData, (uint256, bytes)); + uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; + uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; + uint256 blockNum = getBlockNumber(); + if (firstPerformBlock == 0) { + firstPerformBlocks[upkeepId] = blockNum; + } else { + uint256 delay = blockNum - previousPerformBlock - intervals[upkeepId]; + uint16 bucket = buckets[upkeepId]; + uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; + if (bucketDelays.length == BUCKET_SIZE) { + bucket++; + buckets[upkeepId] = bucket; + } + bucketedDelays[upkeepId][bucket].push(delay); + delays[upkeepId].push(delay); + } + + uint256 counter = counters[upkeepId] + 1; + counters[upkeepId] = counter; + previousPerformBlocks[upkeepId] = blockNum; + + topUpFund(upkeepId, blockNum); + burnPerformGas(upkeepId, startGas, blockNum); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol new file mode 100644 index 0000000..932d350 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol"; +import {SCALibrary} from "./SCALibrary.sol"; +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; +import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; + +/// @dev LINK token paymaster implementation. +/// TODO: more documentation. +contract Paymaster is IPaymaster, ConfirmedOwner { + error OnlyCallableFromLink(); + error InvalidCalldata(); + error Unauthorized(address sender, address validator); + error UserOperationAlreadyTried(bytes32 userOpHash); + error InsufficientFunds(uint256 juelsNeeded, uint256 subscriptionBalance); + + LinkTokenInterface public immutable i_linkToken; + AggregatorV3Interface public immutable i_linkEthFeed; + address public immutable i_entryPoint; + + struct Config { + uint32 stalenessSeconds; + int256 fallbackWeiPerUnitLink; + } + Config public s_config; + + mapping(bytes32 => bool) internal s_userOpHashMapping; + mapping(address => uint256) internal s_subscriptions; + + constructor( + LinkTokenInterface linkToken, + AggregatorV3Interface linkEthFeed, + address entryPoint + ) ConfirmedOwner(msg.sender) { + i_linkToken = linkToken; + i_linkEthFeed = linkEthFeed; + i_entryPoint = entryPoint; + } + + function setConfig(uint32 stalenessSeconds, int256 fallbackWeiPerUnitLink) external onlyOwner { + s_config = Config({stalenessSeconds: stalenessSeconds, fallbackWeiPerUnitLink: fallbackWeiPerUnitLink}); + } + + function onTokenTransfer(address /* _sender */, uint256 _amount, bytes calldata _data) external { + if (msg.sender != address(i_linkToken)) { + revert OnlyCallableFromLink(); + } + if (_data.length != 32) { + revert InvalidCalldata(); + } + + address subscription = abi.decode(_data, (address)); + s_subscriptions[subscription] += _amount; + } + + function validatePaymasterUserOp( + UserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) external returns (bytes memory context, uint256 validationData) { + if (msg.sender != i_entryPoint) { + revert Unauthorized(msg.sender, i_entryPoint); + } + if (s_userOpHashMapping[userOpHash]) { + revert UserOperationAlreadyTried(userOpHash); + } + + uint256 extraCostJuels = _handleExtraCostJuels(userOp); + uint256 costJuels = _getCostJuels(maxCost) + extraCostJuels; + if (s_subscriptions[userOp.sender] < costJuels) { + revert InsufficientFunds(costJuels, s_subscriptions[userOp.sender]); + } + + s_userOpHashMapping[userOpHash] = true; + return (abi.encode(userOp.sender, extraCostJuels), _packValidationData(false, 0, 0)); // success + } + + /// @dev Calculates any extra LINK cost for the user operation, based on the funding type passed to the + /// @dev paymaster. Handles funding the LINK token funding described in the user operation. + /// TODO: add logic for subscription top-up. + function _handleExtraCostJuels(UserOperation calldata userOp) internal returns (uint256 extraCost) { + if (userOp.paymasterAndData.length == 20) { + return 0; // no extra data, stop here + } + + uint8 paymentType = uint8(userOp.paymasterAndData[20]); + + // For direct funding, use top-up logic. + if (paymentType == uint8(SCALibrary.LinkPaymentType.DIRECT_FUNDING)) { + SCALibrary.DirectFundingData memory directFundingData = abi.decode( + userOp.paymasterAndData[21:], + (SCALibrary.DirectFundingData) + ); + if ( + directFundingData.topupThreshold != 0 && + i_linkToken.balanceOf(directFundingData.recipient) < directFundingData.topupThreshold + ) { + i_linkToken.transfer(directFundingData.recipient, directFundingData.topupAmount); + extraCost = directFundingData.topupAmount; + } + } + return extraCost; + } + + /// @dev Deducts user subscription balance after execution. + function postOp(PostOpMode /* mode */, bytes calldata context, uint256 actualGasCost) external { + if (msg.sender != i_entryPoint) { + revert Unauthorized(msg.sender, i_entryPoint); + } + (address sender, uint256 extraCostJuels) = abi.decode(context, (address, uint256)); + s_subscriptions[sender] -= (_getCostJuels(actualGasCost) + extraCostJuels); + } + + function _getCostJuels(uint256 costWei) internal view returns (uint256 costJuels) { + costJuels = (1e18 * costWei) / uint256(_getFeedData()); + return costJuels; + } + + function _getFeedData() internal view returns (int256) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = i_linkEthFeed.latestRoundData(); + if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_config.fallbackWeiPerUnitLink; + } + return weiPerUnitLink; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol new file mode 100644 index 0000000..589c55f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IAccount} from "../../../vendor/entrypoint/interfaces/IAccount.sol"; +import {SCALibrary} from "./SCALibrary.sol"; +import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; +import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; + +/// @dev Smart Contract Account, a contract deployed for a single user and that allows +/// @dev them to invoke meta-transactions. +/// TODO: Consider making the Smart Contract Account upgradeable. +contract SCA is IAccount { + uint256 public s_nonce; + address public immutable i_owner; + address public immutable i_entryPoint; + + error IncorrectNonce(uint256 currentNonce, uint256 nonceGiven); + error NotAuthorized(address sender); + error BadFormatOrOOG(); + error TransactionExpired(uint256 deadline, uint256 currentTimestamp); + error InvalidSignature(bytes32 operationHash, address owner); + + // Assign the owner of this contract upon deployment. + constructor(address owner, address entryPoint) { + i_owner = owner; + i_entryPoint = entryPoint; + } + + /// @dev Validates the user operation via a signature check. + /// TODO: Utilize a "validAfter" for a tx to be only valid _after_ a certain time. + function validateUserOp( + UserOperation calldata userOp, + bytes32 userOpHash, + uint256 /* missingAccountFunds - unused in favor of paymaster */ + ) external returns (uint256 validationData) { + if (userOp.nonce != s_nonce) { + // Revert for non-signature errors. + revert IncorrectNonce(s_nonce, userOp.nonce); + } + + // Verify signature on hash. + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, address(this)); + bytes memory signature = userOp.signature; + if (SCALibrary._recoverSignature(signature, fullHash) != i_owner) { + return _packValidationData(true, 0, 0); // signature error + } + s_nonce++; + + // Unpack deadline, return successful signature. + (, , uint48 deadline, ) = abi.decode(userOp.callData[4:], (address, uint256, uint48, bytes)); + return _packValidationData(false, deadline, 0); + } + + /// @dev Execute a transaction on behalf of the owner. This function can only + /// @dev be called by the EntryPoint contract, and assumes that `validateUserOp` has succeeded. + function executeTransactionFromEntryPoint(address to, uint256 value, uint48 deadline, bytes calldata data) external { + if (msg.sender != i_entryPoint) { + revert NotAuthorized(msg.sender); + } + if (deadline != 0 && block.timestamp > deadline) { + revert TransactionExpired(deadline, block.timestamp); + } + + // Execute transaction. Bubble up an error if found. + (bool success, bytes memory returnData) = to.call{value: value}(data); + if (!success) { + if (returnData.length == 0) revert BadFormatOrOOG(); + assembly { + revert(add(32, returnData), mload(returnData)) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol new file mode 100644 index 0000000..095a342 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +library SCALibrary { + // keccak256("EIP712Domain(uint256 chainId, address verifyingContract)"); + bytes32 internal constant DOMAIN_SEPARATOR = hex"1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea61"; + + // keccak256("executeTransactionFromEntryPoint(address to, uint256 value, bytes calldata data)"); + bytes32 internal constant TYPEHASH = hex"4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0"; + + enum LinkPaymentType { + DIRECT_FUNDING, + SUBSCRIPTION // TODO: implement + } + + struct DirectFundingData { + address recipient; // recipient of the top-up + uint256 topupThreshold; // set to zero to disable auto-topup + uint256 topupAmount; + } + + function _getUserOpFullHash(bytes32 userOpHash, address scaAddress) internal view returns (bytes32 fullHash) { + bytes32 hashOfEncoding = keccak256(abi.encode(SCALibrary.TYPEHASH, userOpHash)); + fullHash = keccak256( + abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + SCALibrary.DOMAIN_SEPARATOR, + block.chainid, + scaAddress, + hashOfEncoding + ) + ); + return fullHash; + } + + function _recoverSignature(bytes memory signature, bytes32 fullHash) internal pure returns (address) { + bytes32 r; + bytes32 s; + assembly { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + } + uint8 v = uint8(signature[64]); + + return ecrecover(fullHash, v + 27, r, s); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol new file mode 100644 index 0000000..f27c8e1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +contract SmartContractAccountFactory { + event ContractCreated(address scaAddress); + + error DeploymentFailed(); + + /// @dev Use create2 to deploy a new Smart Contract Account. + /// @dev See EIP-1014 for more on CREATE2. + /// TODO: Return the address of the Smart Contract Account even if it is already + /// deployed. + function deploySmartContractAccount( + bytes32 abiEncodedOwnerAddress, + bytes memory initCode + ) external payable returns (address scaAddress) { + assembly { + scaAddress := create2( + 0, // value - left at zero here + add(0x20, initCode), // initialization bytecode + mload(initCode), // length of initialization bytecode + abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses + ) + } + if (scaAddress == address(0)) { + revert DeploymentFailed(); + } + + emit ContractCreated(scaAddress); + + return scaAddress; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol new file mode 100644 index 0000000..5851c86 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @dev Ownerless greeter contract. +contract Greeter { + string private s_greeting; + + function setGreeting(string memory greeting) external { + s_greeting = greeting; + } + + function getGreeting() external view returns (string memory) { + return s_greeting; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol new file mode 100644 index 0000000..b080484 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {SCA} from "../ERC-4337/SCA.sol"; +import {SmartContractAccountFactory} from "../ERC-4337/SmartContractAccountFactory.sol"; +import {SCALibrary} from "../ERC-4337/SCALibrary.sol"; + +library SmartContractAccountHelper { + bytes internal constant INITIALIZE_CODE = type(SCA).creationCode; + + function getFullEndTxEncoding( + address endContract, + uint256 value, + uint256 deadline, + bytes memory data + ) public view returns (bytes memory encoding) { + encoding = bytes.concat( + SCA.executeTransactionFromEntryPoint.selector, + abi.encode(endContract, value, block.timestamp + deadline, data) + ); + return encoding; + } + + function getFullHashForSigning(bytes32 userOpHash, address scaAddress) public view returns (bytes32) { + return SCALibrary._getUserOpFullHash(userOpHash, scaAddress); + } + + function getSCAInitCodeWithConstructor( + address owner, + address entryPoint + ) public pure returns (bytes memory initCode) { + initCode = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + return initCode; + } + + function getInitCode( + address factory, + address owner, + address entryPoint + ) external pure returns (bytes memory initCode) { + bytes32 salt = bytes32(uint256(uint160(owner)) << 96); + bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + initCode = bytes.concat( + bytes20(address(factory)), + abi.encodeWithSelector( + SmartContractAccountFactory.deploySmartContractAccount.selector, + salt, + initializeCodeWithConstructor + ) + ); + return initCode; + } + + /// @dev Computes the smart contract address that results from a CREATE2 operation, per EIP-1014. + function calculateSmartContractAccountAddress( + address owner, + address entryPoint, + address factory + ) external pure returns (address) { + bytes32 salt = bytes32(uint256(uint160(owner)) << 96); + bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + bytes32 initializeCodeHash = keccak256(initializeCodeWithConstructor); + return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(factory), salt, initializeCodeHash))))); + } + + function getAbiEncodedDirectRequestData( + address recipient, + uint256 topupThreshold, + uint256 topupAmount + ) external pure returns (bytes memory) { + SCALibrary.DirectFundingData memory data = SCALibrary.DirectFundingData({ + recipient: recipient, + topupThreshold: topupThreshold, + topupAmount: topupAmount + }); + return abi.encode(data); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol new file mode 100644 index 0000000..4da698d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + // Set msg.sender to OWNER until changePrank or stopPrank is called + vm.startPrank(OWNER); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol new file mode 100644 index 0000000..fdfe190 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol @@ -0,0 +1,365 @@ +pragma solidity 0.8.19; + +import "../../shared/interfaces/LinkTokenInterface.sol"; + +import "./BaseTest.t.sol"; +import "../dev/ERC-4337/SmartContractAccountFactory.sol"; +import "../dev/testhelpers/SmartContractAccountHelper.sol"; +import "../dev/ERC-4337/SCA.sol"; +import "../dev/testhelpers/Greeter.sol"; +import "../dev/ERC-4337/Paymaster.sol"; +import "../../transmission/dev/ERC-4337/SCALibrary.sol"; +import "../../mocks/MockLinkToken.sol"; +import "../../tests/MockV3Aggregator.sol"; +import "../../vrf/mocks/VRFCoordinatorMock.sol"; +import "../../vrf/testhelpers/VRFConsumer.sol"; + +import "../../vendor/entrypoint/interfaces/UserOperation.sol"; +import "../../vendor/entrypoint/core/EntryPoint.sol"; +import "../../vendor/entrypoint/interfaces/IEntryPoint.sol"; + +/*--------------------------------------------------------------------------------------------------------------------+ +| EIP 712 + 1014 + 4337 | +| ________________ | +| This implementation allows for meta-transactions to be signed by end-users and posted on-chain by executors. It | +| utilizes the following components: | +| - EIP-712: The method by which meta-transactions are authorized. | +| - EIP-1014: The method by which the Smart Contract Account is generated. | +| - EIP-4337: The method by which meta-transactions are executed. | +| | +| The below tests illustrate end-user flows for interacting with this meta-transaction system. For users with | +| existing Smart Contract Accounts (SCAs), they simply sign off on the operation, after which the executor | +| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then execute the transaction | +| as the SCA. For users without existing SCAs, EIP-1014 ensures that the address of an SCA can be known in advance, | +| so users can sign-off on transactions that will be executed by a not-yet-deployed SCA. The EntryPoint contract | +| takes advantage of this functionality and allows for the SCA to be created in the same user operation that invokes | +| it, and the end-user signs off on this creation-and-execution flow. After the initial creation-and-execution, the | +| SCA is reused for future transactions. | +| | +| End-Dapps/protocols do not need to be EIP-2771-compliant or accommodate any other kind of transaction standard. | +| They can be interacted with out-of-the-box through the SCA, which acts in place of the user's EOA as their | +| immutable identity. | +| | +-+---------------------------------------------------------------------------------------------------------------------*/ + +contract EIP_712_1014_4337 is BaseTest { + event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); + + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + address internal ENTRY_POINT; + + Greeter greeter; + EntryPoint entryPoint; + MockV3Aggregator linkEthFeed; + + // Randomly generated private/public key pair. + uint256 END_USER_PKEY = uint256(bytes32(hex"99d518dbfea4b4ec301390f7e26d53d711fa1ca0c1a6e4cbed89617d4c578a8e")); + address END_USER = 0xB6708257D4E1bf0b8C144793fc2Ff3193C737ed1; + + function setUp() public override { + BaseTest.setUp(); + // Fund user accounts; + vm.deal(END_USER, 10_000 ether); + vm.deal(LINK_WHALE, 10_000 ether); + + // Impersonate a LINK whale. + changePrank(LINK_WHALE); + + // Create simple greeter contract. + greeter = new Greeter(); + assertEq("", greeter.getGreeting()); + + // Create entry point contract. + entryPoint = new EntryPoint(); + ENTRY_POINT = address(entryPoint); + + // Deploy link/eth feed. + linkEthFeed = new MockV3Aggregator(18, 5000000000000000); // .005 ETH + } + + /// @dev Test case for user that already has a Smart Contract Account. + /// @dev EntryPoint.sol should use the existing SCA to execute the meta transaction. + function testEIP712EIP4337WithExistingSmartContractAccount() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Deploy the end-contract. + bytes32 salt = bytes32(uint256(uint160(END_USER)) << 96); + bytes memory fullInitializeCode = SmartContractAccountHelper.getSCAInitCodeWithConstructor(END_USER, ENTRY_POINT); + factory.deploySmartContractAccount(salt, fullInitializeCode); + changePrank(END_USER); + + // Ensure a correct deployment and a functioning end-contract. + uint256 contractCodeSize; + assembly { + contractCodeSize := extcodesize(toDeployAddress) + } + assertTrue(contractCodeSize > 0); + assertEq(END_USER, SCA(toDeployAddress).i_owner()); + + // Create the calldata for a setGreeting call. + string memory greeting = "hi"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); // abi.encodeWithSelector equivalent + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: "", + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: "", + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(toDeployAddress); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("hi", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + /// @dev Test case for fresh user, EntryPoint.sol should generate a + /// @dev Smart Contract Account for them and execute the meta transaction. + function testEIP712EIP4337AndCreateSmartContractAccount() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a setGreeting call. + string memory greeting = "bye"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: "", + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(toDeployAddress); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("bye", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + assertEq(SCA(toDeployAddress).i_owner(), END_USER); + } + + /// @dev Test case for a user executing a setGreeting with a LINK token paymaster. + function testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a setGreeting call. + string memory greeting = "good day"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Create Link token, and deposit into paymaster. + MockLinkToken linkToken = new MockLinkToken(); + Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); + linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); + + // Construct the user opeartion. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_500_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: abi.encodePacked(address(paymaster)), + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(address(paymaster)); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("good day", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + /// @dev Test case for a VRF Request via LINK token paymaster and an SCA. + function testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a VRF request. + bytes32 keyhash = bytes32(uint256(123)); + uint256 fee = 1 ether; + bytes memory encodedVRFRequestCallData = bytes.concat( + VRFConsumer.doRequestRandomness.selector, + abi.encode(keyhash, fee) + ); + + // Create the VRF Contracts + MockLinkToken linkToken = new MockLinkToken(); + VRFCoordinatorMock vrfCoordinator = new VRFCoordinatorMock(address(linkToken)); + VRFConsumer vrfConsumer = new VRFConsumer(address(vrfCoordinator), address(linkToken)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(vrfConsumer), // end-contract + uint256(0), // value + 0, // timeout (seconds) + encodedVRFRequestCallData + ); + + // Create Link token, and deposit into paymaster. + Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); + linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); + + // Construct direct funding data. + SCALibrary.DirectFundingData memory directFundingData = SCALibrary.DirectFundingData({ + recipient: address(vrfConsumer), + topupThreshold: 1, + topupAmount: 10 ether + }); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 200_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 10, + maxPriorityFeePerGas: 10, + paymasterAndData: abi.encodePacked(address(paymaster), uint8(0), abi.encode(directFundingData)), + signature: "" + }); + + // Sign user operation. + bytes32 fullHash = SCALibrary._getUserOpFullHash(entryPoint.getUserOpHash(op), toDeployAddress); + op.signature = getSignature(fullHash); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(address(paymaster)); + + // Assert correct log is emitted for the end-contract vrf request. + vm.expectEmit(true, true, true, true); + emit RandomnessRequest( + address(vrfConsumer), + keyhash, + 0, // seed - we use a zero seed + fee + ); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + + // Execute user operation and ensure correct outcome. + entryPoint.handleOps(operations, payable(END_USER)); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + function getSignature(bytes32 h) internal view returns (bytes memory) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, h); + return abi.encodePacked(r, s, v - 27); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol new file mode 100644 index 0000000..0517df2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol @@ -0,0 +1,152 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity >=0.4.21 <0.9.0; + +/// @title Provides insight into the cost of using the chain. +/// @notice These methods have been adjusted to account for Nitro's heavy use of calldata compression. +/// Of note to end-users, we no longer make a distinction between non-zero and zero-valued calldata bytes. +/// Precompiled contract that exists in every Arbitrum chain at 0x000000000000000000000000000000000000006c. +interface ArbGasInfo { + /// @notice Get gas prices for a provided aggregator + /// @return return gas prices in wei + /// ( + /// per L2 tx, + /// per L1 calldata byte + /// per storage allocation, + /// per ArbGas base, + /// per ArbGas congestion, + /// per ArbGas total + /// ) + function getPricesInWeiWithAggregator(address aggregator) + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + uint256, + uint256 + ); + + /// @notice Get gas prices. Uses the caller's preferred aggregator, or the default if the caller doesn't have a preferred one. + /// @return return gas prices in wei + /// ( + /// per L2 tx, + /// per L1 calldata byte + /// per storage allocation, + /// per ArbGas base, + /// per ArbGas congestion, + /// per ArbGas total + /// ) + function getPricesInWei() + external + view + returns ( + uint256, + uint256, + uint256, + uint256, + uint256, + uint256 + ); + + /// @notice Get prices in ArbGas for the supplied aggregator + /// @return (per L2 tx, per L1 calldata byte, per storage allocation) + function getPricesInArbGasWithAggregator(address aggregator) + external + view + returns ( + uint256, + uint256, + uint256 + ); + + /// @notice Get prices in ArbGas. Assumes the callers preferred validator, or the default if caller doesn't have a preferred one. + /// @return (per L2 tx, per L1 calldata byte, per storage allocation) + function getPricesInArbGas() + external + view + returns ( + uint256, + uint256, + uint256 + ); + + /// @notice Get the gas accounting parameters. `gasPoolMax` is always zero, as the exponential pricing model has no such notion. + /// @return (speedLimitPerSecond, gasPoolMax, maxTxGasLimit) + function getGasAccountingParams() + external + view + returns ( + uint256, + uint256, + uint256 + ); + + /// @notice Get the minimum gas price needed for a tx to succeed + function getMinimumGasPrice() external view returns (uint256); + + /// @notice Get ArbOS's estimate of the L1 basefee in wei + function getL1BaseFeeEstimate() external view returns (uint256); + + /// @notice Get how slowly ArbOS updates its estimate of the L1 basefee + function getL1BaseFeeEstimateInertia() external view returns (uint64); + + /// @notice Get the L1 pricer reward rate, in wei per unit + /// Available in ArbOS version 11 + function getL1RewardRate() external view returns (uint64); + + /// @notice Get the L1 pricer reward recipient + /// Available in ArbOS version 11 + function getL1RewardRecipient() external view returns (address); + + /// @notice Deprecated -- Same as getL1BaseFeeEstimate() + function getL1GasPriceEstimate() external view returns (uint256); + + /// @notice Get L1 gas fees paid by the current transaction + function getCurrentTxL1GasFees() external view returns (uint256); + + /// @notice Get the backlogged amount of gas burnt in excess of the speed limit + function getGasBacklog() external view returns (uint64); + + /// @notice Get how slowly ArbOS updates the L2 basefee in response to backlogged gas + function getPricingInertia() external view returns (uint64); + + /// @notice Get the forgivable amount of backlogged gas ArbOS will ignore when raising the basefee + function getGasBacklogTolerance() external view returns (uint64); + + /// @notice Returns the surplus of funds for L1 batch posting payments (may be negative). + function getL1PricingSurplus() external view returns (int256); + + /// @notice Returns the base charge (in L1 gas) attributed to each data batch in the calldata pricer + function getPerBatchGasCharge() external view returns (int64); + + /// @notice Returns the cost amortization cap in basis points + function getAmortizedCostCapBips() external view returns (uint64); + + /// @notice Returns the available funds from L1 fees + function getL1FeesAvailable() external view returns (uint256); + + /// @notice Returns the equilibration units parameter for L1 price adjustment algorithm + /// Available in ArbOS version 20 + function getL1PricingEquilibrationUnits() external view returns (uint256); + + /// @notice Returns the last time the L1 calldata pricer was updated. + /// Available in ArbOS version 20 + function getLastL1PricingUpdateTime() external view returns (uint64); + + /// @notice Returns the amount of L1 calldata payments due for rewards (per the L1 reward rate) + /// Available in ArbOS version 20 + function getL1PricingFundsDueForRewards() external view returns (uint256); + + /// @notice Returns the amount of L1 calldata posted since the last update. + /// Available in ArbOS version 20 + function getL1PricingUnitsSinceUpdate() external view returns (uint64); + + /// @notice Returns the L1 pricing surplus as of the last update (may be negative). + /// Available in ArbOS version 20 + function getLastL1PricingSurplus() external view returns (int256); +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol new file mode 100644 index 0000000..fb48f36 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol @@ -0,0 +1,153 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +pragma solidity >=0.4.21 <0.9.0; + +/** + * @title System level functionality + * @notice For use by contracts to interact with core L2-specific functionality. + * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. + */ +interface ArbSys { + /** + * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) + * @return block number as int + */ + function arbBlockNumber() external view returns (uint256); + + /** + * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum) + * @return block hash + */ + function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32); + + /** + * @notice Gets the rollup's unique chain identifier + * @return Chain identifier as int + */ + function arbChainID() external view returns (uint256); + + /** + * @notice Get internal version number identifying an ArbOS build + * @return version number as int + */ + function arbOSVersion() external view returns (uint256); + + /** + * @notice Returns 0 since Nitro has no concept of storage gas + * @return uint 0 + */ + function getStorageGasAvailable() external view returns (uint256); + + /** + * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract) + * @dev this call has been deprecated and may be removed in a future release + * @return true if current execution frame is not a call by another L2 contract + */ + function isTopLevelCall() external view returns (bool); + + /** + * @notice map L1 sender contract address to its L2 alias + * @param sender sender address + * @param unused argument no longer used + * @return aliased sender address + */ + function mapL1SenderContractAddressToL2Alias(address sender, address unused) + external + pure + returns (address); + + /** + * @notice check if the caller (of this caller of this) is an aliased L1 contract address + * @return true iff the caller's address is an alias for an L1 contract address + */ + function wasMyCallersAddressAliased() external view returns (bool); + + /** + * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing + * @return address of the caller's caller, without applying L1 contract address aliasing + */ + function myCallersAddressWithoutAliasing() external view returns (address); + + /** + * @notice Send given amount of Eth to dest from sender. + * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data. + * @param destination recipient address on L1 + * @return unique identifier for this L2-to-L1 transaction. + */ + function withdrawEth(address destination) + external + payable + returns (uint256); + + /** + * @notice Send a transaction to L1 + * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data + * to a contract address without any code (as enforced by the Bridge contract). + * @param destination recipient address on L1 + * @param data (optional) calldata for L1 contract call + * @return a unique identifier for this L2-to-L1 transaction. + */ + function sendTxToL1(address destination, bytes calldata data) + external + payable + returns (uint256); + + /** + * @notice Get send Merkle tree state + * @return size number of sends in the history + * @return root root hash of the send history + * @return partials hashes of partial subtrees in the send history tree + */ + function sendMerkleTreeState() + external + view + returns ( + uint256 size, + bytes32 root, + bytes32[] memory partials + ); + + /** + * @notice creates a send txn from L2 to L1 + * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf + */ + event L2ToL1Tx( + address caller, + address indexed destination, + uint256 indexed hash, + uint256 indexed position, + uint256 arbBlockNum, + uint256 ethBlockNum, + uint256 timestamp, + uint256 callvalue, + bytes data + ); + + /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade + event L2ToL1Transaction( + address caller, + address indexed destination, + uint256 indexed uniqueId, + uint256 indexed batchNumber, + uint256 indexInBatch, + uint256 arbBlockNum, + uint256 ethBlockNum, + uint256 timestamp, + uint256 callvalue, + bytes data + ); + + /** + * @notice logs a merkle branch for proof synthesis + * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event + * @param hash the merkle hash + * @param position = (level << 192) + leaf + */ + event SendMerkleUpdate( + uint256 indexed reserved, + bytes32 indexed hash, + uint256 indexed position + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol new file mode 100644 index 0000000..a57b4dd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: BSD-2-Clause +pragma solidity ^0.8.4; + +/** +* @dev A library for working with mutable byte buffers in Solidity. +* +* Byte buffers are mutable and expandable, and provide a variety of primitives +* for appending to them. At any time you can fetch a bytes object containing the +* current contents of the buffer. The bytes object should not be stored between +* operations, as it may change due to resizing of the buffer. +*/ +library Buffer { + /** + * @dev Represents a mutable buffer. Buffers have a current value (buf) and + * a capacity. The capacity may be longer than the current value, in + * which case it can be extended without the need to allocate more memory. + */ + struct buffer { + bytes buf; + uint capacity; + } + + /** + * @dev Initializes a buffer with an initial capacity. + * @param buf The buffer to initialize. + * @param capacity The number of bytes of space to allocate the buffer. + * @return The buffer, for chaining. + */ + function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { + if (capacity % 32 != 0) { + capacity += 32 - (capacity % 32); + } + // Allocate space for the buffer data + buf.capacity = capacity; + assembly { + let ptr := mload(0x40) + mstore(buf, ptr) + mstore(ptr, 0) + let fpm := add(32, add(ptr, capacity)) + if lt(fpm, ptr) { + revert(0, 0) + } + mstore(0x40, fpm) + } + return buf; + } + + /** + * @dev Initializes a new buffer from an existing bytes object. + * Changes to the buffer may mutate the original value. + * @param b The bytes object to initialize the buffer with. + * @return A new buffer. + */ + function fromBytes(bytes memory b) internal pure returns(buffer memory) { + buffer memory buf; + buf.buf = b; + buf.capacity = b.length; + return buf; + } + + function resize(buffer memory buf, uint capacity) private pure { + bytes memory oldbuf = buf.buf; + init(buf, capacity); + append(buf, oldbuf); + } + + /** + * @dev Sets buffer length to 0. + * @param buf The buffer to truncate. + * @return The original buffer, for chaining.. + */ + function truncate(buffer memory buf) internal pure returns (buffer memory) { + assembly { + let bufptr := mload(buf) + mstore(bufptr, 0) + } + return buf; + } + + /** + * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @param len The number of bytes to copy. + * @return The original buffer, for chaining. + */ + function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) { + require(len <= data.length); + + uint off = buf.buf.length; + uint newCapacity = off + len; + if (newCapacity > buf.capacity) { + resize(buf, newCapacity * 2); + } + + uint dest; + uint src; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Start address = buffer address + offset + sizeof(buffer length) + dest := add(add(bufptr, 32), off) + // Update buffer length if we're extending it + if gt(newCapacity, buflen) { + mstore(bufptr, newCapacity) + } + src := add(data, 32) + } + + // Copy word-length chunks while possible + for (; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + unchecked { + uint mask = (256 ** (32 - len)) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + return buf; + } + + /** + * @dev Appends a byte string to a buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { + return append(buf, data, data.length); + } + + /** + * @dev Appends a byte to the buffer. Resizes if doing so would exceed the + * capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { + uint off = buf.buf.length; + uint offPlusOne = off + 1; + if (off >= buf.capacity) { + resize(buf, offPlusOne * 2); + } + + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Address = buffer address + sizeof(buffer length) + off + let dest := add(add(bufptr, off), 32) + mstore8(dest, data) + // Update buffer length if we extended it + if gt(offPlusOne, mload(bufptr)) { + mstore(bufptr, offPlusOne) + } + } + + return buf; + } + + /** + * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @param len The number of bytes to write (left-aligned). + * @return The original buffer, for chaining. + */ + function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) { + uint off = buf.buf.length; + uint newCapacity = len + off; + if (newCapacity > buf.capacity) { + resize(buf, newCapacity * 2); + } + + unchecked { + uint mask = (256 ** len) - 1; + // Right-align data + data = data >> (8 * (32 - len)); + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Address = buffer address + sizeof(buffer length) + newCapacity + let dest := add(bufptr, newCapacity) + mstore(dest, or(and(mload(dest), not(mask)), data)) + // Update buffer length if we extended it + if gt(newCapacity, mload(bufptr)) { + mstore(bufptr, newCapacity) + } + } + } + return buf; + } + + /** + * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chhaining. + */ + function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { + return append(buf, bytes32(data), 20); + } + + /** + * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { + return append(buf, data, 32); + } + + /** + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @param len The number of bytes to write (right-aligned). + * @return The original buffer. + */ + function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { + uint off = buf.buf.length; + uint newCapacity = len + off; + if (newCapacity > buf.capacity) { + resize(buf, newCapacity * 2); + } + + uint mask = (256 ** len) - 1; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Address = buffer address + sizeof(buffer length) + newCapacity + let dest := add(bufptr, newCapacity) + mstore(dest, or(and(mload(dest), not(mask)), data)) + // Update buffer length if we extended it + if gt(newCapacity, mload(bufptr)) { + mstore(bufptr, newCapacity) + } + } + return buf; + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol new file mode 100644 index 0000000..aebc1f7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { ISemver } from "../universal/ISemver.sol"; +import { Predeploys } from "../libraries/Predeploys.sol"; +import { L1Block } from "./L1Block.sol"; + +/// @custom:proxied +/// @custom:predeploy 0x420000000000000000000000000000000000000F +/// @title GasPriceOracle +/// @notice This contract maintains the variables responsible for computing the L1 portion of the +/// total fee charged on L2. Before Bedrock, this contract held variables in state that were +/// read during the state transition function to compute the L1 portion of the transaction +/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has +/// the values used to compute the L1 portion of the fee in its state. +/// +/// The contract exposes an API that is useful for knowing how large the L1 portion of the +/// transaction fee will be. The following events were deprecated with Bedrock: +/// - event OverheadUpdated(uint256 overhead); +/// - event ScalarUpdated(uint256 scalar); +/// - event DecimalsUpdated(uint256 decimals); +contract GasPriceOracle is ISemver { + /// @notice Number of decimals used in the scalar. + uint256 public constant DECIMALS = 6; + + /// @notice Semantic version. + /// @custom:semver 1.1.0 + string public constant version = "1.1.0"; + + /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input + /// transaction, the current L1 base fee, and the various dynamic parameters. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function getL1Fee(bytes memory _data) external view returns (uint256) { + uint256 l1GasUsed = getL1GasUsed(_data); + uint256 l1Fee = l1GasUsed * l1BaseFee(); + uint256 divisor = 10 ** DECIMALS; + uint256 unscaled = l1Fee * scalar(); + uint256 scaled = unscaled / divisor; + return scaled; + } + + /// @notice Retrieves the current gas price (base fee). + /// @return Current L2 gas price (base fee). + function gasPrice() public view returns (uint256) { + return block.basefee; + } + + /// @notice Retrieves the current base fee. + /// @return Current L2 base fee. + function baseFee() public view returns (uint256) { + return block.basefee; + } + + /// @notice Retrieves the current fee overhead. + /// @return Current fee overhead. + function overhead() public view returns (uint256) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); + } + + /// @notice Retrieves the current fee scalar. + /// @return Current fee scalar. + function scalar() public view returns (uint256) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); + } + + /// @notice Retrieves the latest known L1 base fee. + /// @return Latest known L1 base fee. + function l1BaseFee() public view returns (uint256) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); + } + + /// @custom:legacy + /// @notice Retrieves the number of decimals used in the scalar. + /// @return Number of decimals used in the scalar. + function decimals() public pure returns (uint256) { + return DECIMALS; + } + + /// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which + /// represents the per-transaction gas overhead of posting the transaction and state + /// roots to L1. Adds 68 bytes of padding to account for the fact that the input does + /// not have a signature. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. + /// @return Amount of L1 gas used to publish the transaction. + function getL1GasUsed(bytes memory _data) public view returns (uint256) { + uint256 total = 0; + uint256 length = _data.length; + for (uint256 i = 0; i < length; i++) { + if (_data[i] == 0) { + total += 4; + } else { + total += 16; + } + } + uint256 unsigned = total + overhead(); + return unsigned + (68 * 16); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol new file mode 100644 index 0000000..7722b53 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import { ISemver } from "../universal/ISemver.sol"; + +/// @custom:proxied +/// @custom:predeploy 0x4200000000000000000000000000000000000015 +/// @title L1Block +/// @notice The L1Block predeploy gives users access to information about the last known L1 block. +/// Values within this contract are updated once per epoch (every L1 block) and can only be +/// set by the "depositor" account, a special system address. Depositor account transactions +/// are created by the protocol whenever we move to a new epoch. +contract L1Block is ISemver { + /// @notice Address of the special depositor account. + address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; + + /// @notice The latest L1 block number known by the L2 system. + uint64 public number; + + /// @notice The latest L1 timestamp known by the L2 system. + uint64 public timestamp; + + /// @notice The latest L1 basefee. + uint256 public basefee; + + /// @notice The latest L1 blockhash. + bytes32 public hash; + + /// @notice The number of L2 blocks in the same epoch. + uint64 public sequenceNumber; + + /// @notice The versioned hash to authenticate the batcher by. + bytes32 public batcherHash; + + /// @notice The overhead value applied to the L1 portion of the transaction fee. + uint256 public l1FeeOverhead; + + /// @notice The scalar value applied to the L1 portion of the transaction fee. + uint256 public l1FeeScalar; + + /// @custom:semver 1.1.0 + string public constant version = "1.1.0"; + + /// @notice Updates the L1 block values. + /// @param _number L1 blocknumber. + /// @param _timestamp L1 timestamp. + /// @param _basefee L1 basefee. + /// @param _hash L1 blockhash. + /// @param _sequenceNumber Number of L2 blocks since epoch start. + /// @param _batcherHash Versioned hash to authenticate batcher by. + /// @param _l1FeeOverhead L1 fee overhead. + /// @param _l1FeeScalar L1 fee scalar. + function setL1BlockValues( + uint64 _number, + uint64 _timestamp, + uint256 _basefee, + bytes32 _hash, + uint64 _sequenceNumber, + bytes32 _batcherHash, + uint256 _l1FeeOverhead, + uint256 _l1FeeScalar + ) + external + { + require(msg.sender == DEPOSITOR_ACCOUNT, "L1Block: only the depositor account can set L1 block values"); + + number = _number; + timestamp = _timestamp; + basefee = _basefee; + hash = _hash; + sequenceNumber = _sequenceNumber; + batcherHash = _batcherHash; + l1FeeOverhead = _l1FeeOverhead; + l1FeeScalar = _l1FeeScalar; + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol new file mode 100644 index 0000000..4a0d399 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title Predeploys +/// @notice Contains constant addresses for contracts that are pre-deployed to the L2 system. +library Predeploys { + /// @notice Address of the L2ToL1MessagePasser predeploy. + address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016; + + /// @notice Address of the L2CrossDomainMessenger predeploy. + address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; + + /// @notice Address of the L2StandardBridge predeploy. + address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; + + /// @notice Address of the L2ERC721Bridge predeploy. + address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014; + + //// @notice Address of the SequencerFeeWallet predeploy. + address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; + + /// @notice Address of the OptimismMintableERC20Factory predeploy. + address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012; + + /// @notice Address of the OptimismMintableERC721Factory predeploy. + address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017; + + /// @notice Address of the L1Block predeploy. + address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; + + /// @notice Address of the GasPriceOracle predeploy. Includes fee information + /// and helpers for computing the L1 portion of the transaction fee. + address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F; + + /// @custom:legacy + /// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger + /// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead. + address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; + + /// @custom:legacy + /// @notice Address of the DeployerWhitelist predeploy. No longer active. + address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; + + /// @custom:legacy + /// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the + /// state trie as of the Bedrock upgrade. Contract has been locked and write functions + /// can no longer be accessed. + address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; + + /// @custom:legacy + /// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy + /// instead, which exposes more information about the L1 state. + address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013; + + /// @custom:legacy + /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated + /// L2ToL1MessagePasser contract instead. + address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; + + /// @notice Address of the ProxyAdmin predeploy. + address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; + + /// @notice Address of the BaseFeeVault predeploy. + address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; + + /// @notice Address of the L1FeeVault predeploy. + address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; + + /// @notice Address of the GovernanceToken predeploy. + address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; + + /// @notice Address of the SchemaRegistry predeploy. + address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020; + + /// @notice Address of the EAS predeploy. + address internal constant EAS = 0x4200000000000000000000000000000000000021; +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol new file mode 100644 index 0000000..ae9569a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title ISemver +/// @notice ISemver is a simple contract for ensuring that contracts are +/// versioned using semantic versioning. +interface ISemver { + /// @notice Getter for the semantic version of the contract. This is not + /// meant to be used onchain but instead meant to be used by offchain + /// tooling. + /// @return Semver contract version as a string. + function version() external view returns (string memory); +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol new file mode 100644 index 0000000..01e07a7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +import {ISemver} from "../universal/ISemver.sol"; +import {Predeploys} from "../libraries/Predeploys.sol"; +import {L1Block} from "../L2/L1Block.sol"; +import {Constants} from "../libraries/Constants.sol"; +import {LibZip} from "../deps/LibZip.sol"; + +/// @custom:proxied +/// @custom:predeploy 0x420000000000000000000000000000000000000F +/// @title GasPriceOracle +/// @notice This contract maintains the variables responsible for computing the L1 portion of the +/// total fee charged on L2. Before Bedrock, this contract held variables in state that were +/// read during the state transition function to compute the L1 portion of the transaction +/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has +/// the values used to compute the L1 portion of the fee in its state. +/// +/// The contract exposes an API that is useful for knowing how large the L1 portion of the +/// transaction fee will be. The following events were deprecated with Bedrock: +/// - event OverheadUpdated(uint256 overhead); +/// - event ScalarUpdated(uint256 scalar); +/// - event DecimalsUpdated(uint256 decimals); +contract GasPriceOracle is ISemver { + /// @notice Number of decimals used in the scalar. + uint256 public constant DECIMALS = 6; + + /// @notice Semantic version. + /// @custom:semver 1.3.0 + string public constant version = "1.3.0"; + + /// @notice This is the intercept value for the linear regression used to estimate the final size of the + /// compressed transaction. + int32 private constant COST_INTERCEPT = -42_585_600; + + /// @notice This is the coefficient value for the linear regression used to estimate the final size of the + /// compressed transaction. + uint32 private constant COST_FASTLZ_COEF = 836_500; + + /// @notice This is the minimum bound for the fastlz to brotli size estimation. Any estimations below this + /// are set to this value. + uint256 private constant MIN_TRANSACTION_SIZE = 100; + + /// @notice Indicates whether the network has gone through the Ecotone upgrade. + bool public isEcotone; + + /// @notice Indicates whether the network has gone through the Fjord upgrade. + bool public isFjord; + + /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input + /// transaction, the current L1 base fee, and the various dynamic parameters. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function getL1Fee(bytes memory _data) external view returns (uint256) { + if (isFjord) { + return _getL1FeeFjord(_data); + } else if (isEcotone) { + return _getL1FeeEcotone(_data); + } + return _getL1FeeBedrock(_data); + } + + /// @notice returns an upper bound for the L1 fee for a given transaction size. + /// It is provided for callers who wish to estimate L1 transaction costs in the + /// write path, and is much more gas efficient than `getL1Fee`. + /// It assumes the worst case of fastlz upper-bound which covers %99.99 txs. + /// @param _unsignedTxSize Unsigned fully RLP-encoded transaction size to get the L1 fee for. + /// @return L1 estimated upper-bound fee that should be paid for the tx + function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256) { + require(isFjord, "GasPriceOracle: getL1FeeUpperBound only supports Fjord"); + + // Add 68 to the size to account for unsigned tx: + uint256 txSize = _unsignedTxSize + 68; + // txSize / 255 + 16 is the pratical fastlz upper-bound covers %99.99 txs. + uint256 flzUpperBound = txSize + txSize / 255 + 16; + + return _fjordL1Cost(flzUpperBound); + } + + /// @notice Set chain to be Ecotone chain (callable by depositor account) + function setEcotone() external { + require( + msg.sender == Constants.DEPOSITOR_ACCOUNT, + "GasPriceOracle: only the depositor account can set isEcotone flag" + ); + require(isEcotone == false, "GasPriceOracle: Ecotone already active"); + isEcotone = true; + } + + /// @notice Set chain to be Fjord chain (callable by depositor account) + function setFjord() external { + require( + msg.sender == Constants.DEPOSITOR_ACCOUNT, + "GasPriceOracle: only the depositor account can set isFjord flag" + ); + require(isEcotone, "GasPriceOracle: Fjord can only be activated after Ecotone"); + require(isFjord == false, "GasPriceOracle: Fjord already active"); + isFjord = true; + } + + /// @notice Retrieves the current gas price (base fee). + /// @return Current L2 gas price (base fee). + function gasPrice() public view returns (uint256) { + return block.basefee; + } + + /// @notice Retrieves the current base fee. + /// @return Current L2 base fee. + function baseFee() public view returns (uint256) { + return block.basefee; + } + + /// @custom:legacy + /// @notice Retrieves the current fee overhead. + /// @return Current fee overhead. + function overhead() public view returns (uint256) { + require(!isEcotone, "GasPriceOracle: overhead() is deprecated"); + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); + } + + /// @custom:legacy + /// @notice Retrieves the current fee scalar. + /// @return Current fee scalar. + function scalar() public view returns (uint256) { + require(!isEcotone, "GasPriceOracle: scalar() is deprecated"); + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); + } + + /// @notice Retrieves the latest known L1 base fee. + /// @return Latest known L1 base fee. + function l1BaseFee() public view returns (uint256) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); + } + + /// @notice Retrieves the current blob base fee. + /// @return Current blob base fee. + function blobBaseFee() public view returns (uint256) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee(); + } + + /// @notice Retrieves the current base fee scalar. + /// @return Current base fee scalar. + function baseFeeScalar() public view returns (uint32) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar(); + } + + /// @notice Retrieves the current blob base fee scalar. + /// @return Current blob base fee scalar. + function blobBaseFeeScalar() public view returns (uint32) { + return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar(); + } + + /// @custom:legacy + /// @notice Retrieves the number of decimals used in the scalar. + /// @return Number of decimals used in the scalar. + function decimals() public pure returns (uint256) { + return DECIMALS; + } + + /// @notice Computes the amount of L1 gas used for a transaction. Adds 68 bytes + /// of padding to account for the fact that the input does not have a signature. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. + /// @return Amount of L1 gas used to publish the transaction. + /// @custom:deprecated This method does not accurately estimate the gas used for a transaction. + /// If you are calculating fees use getL1Fee or getL1FeeUpperBound. + function getL1GasUsed(bytes memory _data) public view returns (uint256) { + if (isFjord) { + // Add 68 to the size to account for unsigned tx + // Assume the compressed data is mostly non-zero, and would pay 16 gas per calldata byte + // Divide by 1e6 due to the scaling factor of the linear regression + return (_fjordLinearRegression(LibZip.flzCompress(_data).length + 68) * 16) / 1e6; + } + uint256 l1GasUsed = _getCalldataGas(_data); + if (isEcotone) { + return l1GasUsed; + } + return l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); + } + + /// @notice Computation of the L1 portion of the fee for Bedrock. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function _getL1FeeBedrock(bytes memory _data) internal view returns (uint256) { + uint256 l1GasUsed = _getCalldataGas(_data); + uint256 fee = (l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * + l1BaseFee() * + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); + return fee / (10 ** DECIMALS); + } + + /// @notice L1 portion of the fee after Ecotone. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function _getL1FeeEcotone(bytes memory _data) internal view returns (uint256) { + uint256 l1GasUsed = _getCalldataGas(_data); + uint256 scaledBaseFee = baseFeeScalar() * 16 * l1BaseFee(); + uint256 scaledBlobBaseFee = blobBaseFeeScalar() * blobBaseFee(); + uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee); + return fee / (16 * 10 ** DECIMALS); + } + + /// @notice L1 portion of the fee after Fjord. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function _getL1FeeFjord(bytes memory _data) internal view returns (uint256) { + return _fjordL1Cost(LibZip.flzCompress(_data).length + 68); + } + + /// @notice L1 gas estimation calculation. + /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. + /// @return Amount of L1 gas used to publish the transaction. + function _getCalldataGas(bytes memory _data) internal pure returns (uint256) { + uint256 total = 0; + uint256 length = _data.length; + for (uint256 i = 0; i < length; i++) { + if (_data[i] == 0) { + total += 4; + } else { + total += 16; + } + } + return total + (68 * 16); + } + + /// @notice Fjord L1 cost based on the compressed and original tx size. + /// @param _fastLzSize estimated compressed tx size. + /// @return Fjord L1 fee that should be paid for the tx + function _fjordL1Cost(uint256 _fastLzSize) internal view returns (uint256) { + // Apply the linear regression to estimate the Brotli 10 size + uint256 estimatedSize = _fjordLinearRegression(_fastLzSize); + uint256 feeScaled = baseFeeScalar() * 16 * l1BaseFee() + blobBaseFeeScalar() * blobBaseFee(); + return (estimatedSize * feeScaled) / (10 ** (DECIMALS * 2)); + } + + /// @notice Takes the fastLz size compression and returns the estimated Brotli + /// @param _fastLzSize fastlz compressed tx size. + /// @return Number of bytes in the compressed transaction + function _fjordLinearRegression(uint256 _fastLzSize) internal pure returns (uint256) { + int256 estimatedSize = COST_INTERCEPT + int256(COST_FASTLZ_COEF * _fastLzSize); + if (estimatedSize < int256(MIN_TRANSACTION_SIZE) * 1e6) { + estimatedSize = int256(MIN_TRANSACTION_SIZE) * 1e6; + } + return uint256(estimatedSize); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol new file mode 100644 index 0000000..a58c85b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/L1Block.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +import {ISemver} from "../universal/ISemver.sol"; +import {Constants} from "../libraries/Constants.sol"; +import {GasPayingToken, IGasToken} from "../libraries/GasPayingToken.sol"; +import "../libraries/L1BlockErrors.sol"; + +/// @custom:proxied +/// @custom:predeploy 0x4200000000000000000000000000000000000015 +/// @title L1Block +/// @notice The L1Block predeploy gives users access to information about the last known L1 block. +/// Values within this contract are updated once per epoch (every L1 block) and can only be +/// set by the "depositor" account, a special system address. Depositor account transactions +/// are created by the protocol whenever we move to a new epoch. +contract L1Block is ISemver, IGasToken { + /// @notice Event emitted when the gas paying token is set. + event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); + + /// @notice Address of the special depositor account. + function DEPOSITOR_ACCOUNT() public pure returns (address addr_) { + addr_ = Constants.DEPOSITOR_ACCOUNT; + } + + /// @notice The latest L1 block number known by the L2 system. + uint64 public number; + + /// @notice The latest L1 timestamp known by the L2 system. + uint64 public timestamp; + + /// @notice The latest L1 base fee. + uint256 public basefee; + + /// @notice The latest L1 blockhash. + bytes32 public hash; + + /// @notice The number of L2 blocks in the same epoch. + uint64 public sequenceNumber; + + /// @notice The scalar value applied to the L1 blob base fee portion of the blob-capable L1 cost func. + uint32 public blobBaseFeeScalar; + + /// @notice The scalar value applied to the L1 base fee portion of the blob-capable L1 cost func. + uint32 public baseFeeScalar; + + /// @notice The versioned hash to authenticate the batcher by. + bytes32 public batcherHash; + + /// @notice The overhead value applied to the L1 portion of the transaction fee. + /// @custom:legacy + uint256 public l1FeeOverhead; + + /// @notice The scalar value applied to the L1 portion of the transaction fee. + /// @custom:legacy + uint256 public l1FeeScalar; + + /// @notice The latest L1 blob base fee. + uint256 public blobBaseFee; + + /// @custom:semver 1.4.1-beta.1 + function version() public pure virtual returns (string memory) { + return "1.4.1-beta.1"; + } + + /// @notice Returns the gas paying token, its decimals, name and symbol. + /// If nothing is set in state, then it means ether is used. + function gasPayingToken() public view returns (address addr_, uint8 decimals_) { + (addr_, decimals_) = GasPayingToken.getToken(); + } + + /// @notice Returns the gas paying token name. + /// If nothing is set in state, then it means ether is used. + function gasPayingTokenName() public view returns (string memory name_) { + name_ = GasPayingToken.getName(); + } + + /// @notice Returns the gas paying token symbol. + /// If nothing is set in state, then it means ether is used. + function gasPayingTokenSymbol() public view returns (string memory symbol_) { + symbol_ = GasPayingToken.getSymbol(); + } + + /// @notice Getter for custom gas token paying networks. Returns true if the + /// network uses a custom gas token. + function isCustomGasToken() public view returns (bool) { + (address token, ) = gasPayingToken(); + return token != Constants.ETHER; + } + + /// @custom:legacy + /// @notice Updates the L1 block values. + /// @param _number L1 blocknumber. + /// @param _timestamp L1 timestamp. + /// @param _basefee L1 basefee. + /// @param _hash L1 blockhash. + /// @param _sequenceNumber Number of L2 blocks since epoch start. + /// @param _batcherHash Versioned hash to authenticate batcher by. + /// @param _l1FeeOverhead L1 fee overhead. + /// @param _l1FeeScalar L1 fee scalar. + function setL1BlockValues( + uint64 _number, + uint64 _timestamp, + uint256 _basefee, + bytes32 _hash, + uint64 _sequenceNumber, + bytes32 _batcherHash, + uint256 _l1FeeOverhead, + uint256 _l1FeeScalar + ) external { + require(msg.sender == DEPOSITOR_ACCOUNT(), "L1Block: only the depositor account can set L1 block values"); + + number = _number; + timestamp = _timestamp; + basefee = _basefee; + hash = _hash; + sequenceNumber = _sequenceNumber; + batcherHash = _batcherHash; + l1FeeOverhead = _l1FeeOverhead; + l1FeeScalar = _l1FeeScalar; + } + + /// @notice Updates the L1 block values for an Ecotone upgraded chain. + /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. + /// Params are expected to be in the following order: + /// 1. _baseFeeScalar L1 base fee scalar + /// 2. _blobBaseFeeScalar L1 blob base fee scalar + /// 3. _sequenceNumber Number of L2 blocks since epoch start. + /// 4. _timestamp L1 timestamp. + /// 5. _number L1 blocknumber. + /// 6. _basefee L1 base fee. + /// 7. _blobBaseFee L1 blob base fee. + /// 8. _hash L1 blockhash. + /// 9. _batcherHash Versioned hash to authenticate batcher by. + function setL1BlockValuesEcotone() external { + address depositor = DEPOSITOR_ACCOUNT(); + assembly { + // Revert if the caller is not the depositor account. + if xor(caller(), depositor) { + mstore(0x00, 0x3cc50b45) // 0x3cc50b45 is the 4-byte selector of "NotDepositor()" + revert(0x1C, 0x04) // returns the stored 4-byte selector from above + } + // sequencenum (uint64), blobBaseFeeScalar (uint32), baseFeeScalar (uint32) + sstore(sequenceNumber.slot, shr(128, calldataload(4))) + // number (uint64) and timestamp (uint64) + sstore(number.slot, shr(128, calldataload(20))) + sstore(basefee.slot, calldataload(36)) // uint256 + sstore(blobBaseFee.slot, calldataload(68)) // uint256 + sstore(hash.slot, calldataload(100)) // bytes32 + sstore(batcherHash.slot, calldataload(132)) // bytes32 + } + } + + /// @notice Sets the gas paying token for the L2 system. Can only be called by the special + /// depositor account. This function is not called on every L2 block but instead + /// only called by specially crafted L1 deposit transactions. + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external { + if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor(); + + GasPayingToken.set({_token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol}); + + emit GasPayingTokenSet({token: _token, decimals: _decimals, name: _name, symbol: _symbol}); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol new file mode 100644 index 0000000..bf6d8c2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/transmissions11/solmate/blob/97bdb2003b70382996a79a406813f76417b1cf90/src/utils/LibString.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @notice Library for converting numbers into strings and other string operations. +/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) +/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) +/// +/// Note: +/// For performance and bytecode compactness, most of the string operations are restricted to +/// byte strings (7-bit ASCII), except where otherwise specified. +/// Usage of byte string operations on charsets with runes spanning two or more bytes +/// can lead to undefined behavior. +library LibString { + /// @dev Returns a string from a small bytes32 string. + /// `s` must be null-terminated, or behavior will be undefined. + function fromSmallString(bytes32 s) internal pure returns (string memory result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(0x40) + let n := 0 + for { + + } byte(n, s) { + n := add(n, 1) + } { + + } // Scan for '\0'. + mstore(result, n) + let o := add(result, 0x20) + mstore(o, s) + mstore(add(o, n), 0) + mstore(0x40, add(result, 0x40)) + } + } + + /// @dev Returns the string as a normalized null-terminated small string. + function toSmallString(string memory s) internal pure returns (bytes32 result) { + /// @solidity memory-safe-assembly + assembly { + result := mload(s) + if iszero(lt(result, 33)) { + mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. + revert(0x1c, 0x04) + } + result := shl(shl(3, sub(32, result)), mload(add(s, result))) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol new file mode 100644 index 0000000..5adc429 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/Vectorized/solady/blob/3e8031b16417154dc2beae71b7b45f415d29566b/src/utils/LibZip.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @notice Library for compressing and decompressing bytes. +/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol) +/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor) +/// @author FastLZ by ariya (https://github.com/ariya/FastLZ) +/// +/// @dev Note: +/// The accompanying solady.js library includes implementations of +/// FastLZ and calldata operations for convenience. +library LibZip { + /// @dev Returns the compressed `data`. + function flzCompress(bytes memory data) internal pure returns (bytes memory result) { + /// @solidity memory-safe-assembly + assembly { + function ms8(d_, v_) -> _d { + mstore8(d_, v_) + _d := add(d_, 1) + } + function u24(p_) -> _u { + let w := mload(p_) + _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w))) + } + function cmp(p_, q_, e_) -> _l { + for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } { + e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_) + } + } + function literals(runs_, src_, dest_) -> _o { + for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } { + mstore(ms8(_o, 31), mload(src_)) + _o := add(_o, 0x21) + src_ := add(src_, 0x20) + } + if iszero(runs_) { leave } + mstore(ms8(_o, sub(runs_, 1)), mload(src_)) + _o := add(1, add(_o, runs_)) + } + function match(l_, d_, o_) -> _o { + for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } { + o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_)) + } + if iszero(lt(l_, 7)) { + _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_)) + leave + } + _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_)) + } + function setHash(i_, v_) { + let p := add(mload(0x40), shl(2, i_)) + mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_)))) + } + function getHash(i_) -> _h { + _h := shr(224, mload(add(mload(0x40), shl(2, i_)))) + } + function hash(v_) -> _r { + _r := and(shr(19, mul(2654435769, v_)), 0x1fff) + } + function setNextHash(ip_, ipStart_) -> _ip { + setHash(hash(u24(ip_)), sub(ip_, ipStart_)) + _ip := add(ip_, 1) + } + codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap. + let op := add(mload(0x40), 0x8000) + let a := add(data, 0x20) + let ipStart := a + let ipLimit := sub(add(ipStart, mload(data)), 13) + for { let ip := add(2, a) } lt(ip, ipLimit) {} { + let r := 0 + let d := 0 + for {} 1 {} { + let s := u24(ip) + let h := hash(s) + r := add(ipStart, getHash(h)) + setHash(h, sub(ip, ipStart)) + d := sub(ip, r) + if iszero(lt(ip, ipLimit)) { break } + ip := add(ip, 1) + if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } } + } + if iszero(lt(ip, ipLimit)) { break } + ip := sub(ip, 1) + if gt(ip, a) { op := literals(sub(ip, a), a, op) } + let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9)) + op := match(l, d, op) + ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart) + a := ip + } + op := literals(sub(add(ipStart, mload(data)), a), a, op) + result := mload(0x40) + let t := add(result, 0x8000) + let n := sub(op, t) + mstore(result, n) // Store the length. + // Copy the result to compact the memory, overwriting the hashmap. + let o := add(result, 0x20) + for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) } + mstore(add(o, n), 0) // Zeroize the slot after the string. + mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory. + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol new file mode 100644 index 0000000..79981ec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Constants.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @title Constants +/// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just +/// the stuff used in multiple contracts. Constants that only apply to a single contract +/// should be defined in that contract instead. +library Constants { + /// @notice Special address to be used as the tx origin for gas estimation calls in the + /// OptimismPortal and CrossDomainMessenger calls. You only need to use this address if + /// the minimum gas limit specified by the user is not actually enough to execute the + /// given message and you're attempting to estimate the actual necessary gas limit. We + /// use address(1) because it's the ecrecover precompile and therefore guaranteed to + /// never have any code on any EVM chain. + address internal constant ESTIMATION_ADDRESS = address(1); + + /// @notice Value used for the L2 sender storage slot in both the OptimismPortal and the + /// CrossDomainMessenger contracts before an actual sender is set. This value is + /// non-zero to reduce the gas cost of message passing transactions. + address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; + + /// @notice The storage slot that holds the address of a proxy implementation. + /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` + bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /// @notice The storage slot that holds the address of the owner. + /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` + bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + + /// @notice The address that represents ether when dealing with ERC20 token addresses. + address internal constant ETHER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + + /// @notice The address that represents the system caller responsible for L1 attributes + /// transactions. + address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol new file mode 100644 index 0000000..7754f50 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/GasPayingToken.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +import {Storage} from "./Storage.sol"; +import {Constants} from "./Constants.sol"; +import {LibString} from "../deps/LibString.sol"; + +/// @title IGasToken +/// @notice Implemented by contracts that are aware of the custom gas token used +/// by the L2 network. +interface IGasToken { + /// @notice Getter for the ERC20 token address that is used to pay for gas and its decimals. + function gasPayingToken() external view returns (address, uint8); + /// @notice Returns the gas token name. + function gasPayingTokenName() external view returns (string memory); + /// @notice Returns the gas token symbol. + function gasPayingTokenSymbol() external view returns (string memory); + /// @notice Returns true if the network uses a custom gas token. + function isCustomGasToken() external view returns (bool); +} + +/// @title GasPayingToken +/// @notice Handles reading and writing the custom gas token to storage. +/// To be used in any place where gas token information is read or +/// written to state. If multiple contracts use this library, the +/// values in storage should be kept in sync between them. +library GasPayingToken { + /// @notice The storage slot that contains the address and decimals of the gas paying token + bytes32 internal constant GAS_PAYING_TOKEN_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtoken")) - 1); + + /// @notice The storage slot that contains the ERC20 `name()` of the gas paying token + bytes32 internal constant GAS_PAYING_TOKEN_NAME_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokenname")) - 1); + + /// @notice the storage slot that contains the ERC20 `symbol()` of the gas paying token + bytes32 internal constant GAS_PAYING_TOKEN_SYMBOL_SLOT = + bytes32(uint256(keccak256("opstack.gaspayingtokensymbol")) - 1); + + /// @notice Reads the gas paying token and its decimals from the magic + /// storage slot. If nothing is set in storage, then the ether + /// address is returned instead. + function getToken() internal view returns (address addr_, uint8 decimals_) { + bytes32 slot = Storage.getBytes32(GAS_PAYING_TOKEN_SLOT); + addr_ = address(uint160(uint256(slot) & uint256(type(uint160).max))); + if (addr_ == address(0)) { + addr_ = Constants.ETHER; + decimals_ = 18; + } else { + decimals_ = uint8(uint256(slot) >> 160); + } + } + + /// @notice Reads the gas paying token's name from the magic storage slot. + /// If nothing is set in storage, then the ether name, 'Ether', is returned instead. + function getName() internal view returns (string memory name_) { + (address addr, ) = getToken(); + if (addr == Constants.ETHER) { + name_ = "Ether"; + } else { + name_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_NAME_SLOT)); + } + } + + /// @notice Reads the gas paying token's symbol from the magic storage slot. + /// If nothing is set in storage, then the ether symbol, 'ETH', is returned instead. + function getSymbol() internal view returns (string memory symbol_) { + (address addr, ) = getToken(); + if (addr == Constants.ETHER) { + symbol_ = "ETH"; + } else { + symbol_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT)); + } + } + + /// @notice Writes the gas paying token, its decimals, name and symbol to the magic storage slot. + function set(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) internal { + Storage.setBytes32(GAS_PAYING_TOKEN_SLOT, bytes32((uint256(_decimals) << 160) | uint256(uint160(_token)))); + Storage.setBytes32(GAS_PAYING_TOKEN_NAME_SLOT, _name); + Storage.setBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT, _symbol); + } + + /// @notice Maps a string to a normalized null-terminated small string. + function sanitize(string memory _str) internal pure returns (bytes32) { + require(bytes(_str).length <= 32, "GasPayingToken: string cannot be greater than 32 bytes"); + + return LibString.toSmallString(_str); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol new file mode 100644 index 0000000..e6a180a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @notice Error returns when a non-depositor account tries to set L1 block values. +error NotDepositor(); + +/// @notice Error when a chain ID is not in the interop dependency set. +error NotDependency(); + +/// @notice Error when the interop dependency set size is too large. +error DependencySetSizeTooLarge(); + +/// @notice Error when a chain ID already in the interop dependency set is attempted to be added. +error AlreadyDependency(); + +/// @notice Error when the chain's chain ID is attempted to be removed from the interop dependency set. +error CantRemovedDependency(); diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol new file mode 100644 index 0000000..5b42d2e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Predeploys.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @title Predeploys +/// @notice Contains constant addresses for protocol contracts that are pre-deployed to the L2 system. +// This excludes the preinstalls (non-protocol contracts). +library Predeploys { + /// @notice Number of predeploy-namespace addresses reserved for protocol usage. + uint256 internal constant PREDEPLOY_COUNT = 2048; + + /// @custom:legacy + /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated + /// L2ToL1MessagePasser contract instead. + address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; + + /// @custom:legacy + /// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger + /// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead. + /// Not embedded into new OP-Stack chains. + address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; + + /// @custom:legacy + /// @notice Address of the DeployerWhitelist predeploy. No longer active. + address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; + + /// @notice Address of the canonical WETH contract. + address internal constant WETH = 0x4200000000000000000000000000000000000006; + + /// @notice Address of the L2CrossDomainMessenger predeploy. + address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; + + /// @notice Address of the GasPriceOracle predeploy. Includes fee information + /// and helpers for computing the L1 portion of the transaction fee. + address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F; + + /// @notice Address of the L2StandardBridge predeploy. + address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; + + //// @notice Address of the SequencerFeeWallet predeploy. + address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; + + /// @notice Address of the OptimismMintableERC20Factory predeploy. + address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012; + + /// @custom:legacy + /// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy + /// instead, which exposes more information about the L1 state. + address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013; + + /// @notice Address of the L2ERC721Bridge predeploy. + address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014; + + /// @notice Address of the L1Block predeploy. + address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; + + /// @notice Address of the L2ToL1MessagePasser predeploy. + address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016; + + /// @notice Address of the OptimismMintableERC721Factory predeploy. + address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017; + + /// @notice Address of the ProxyAdmin predeploy. + address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; + + /// @notice Address of the BaseFeeVault predeploy. + address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; + + /// @notice Address of the L1FeeVault predeploy. + address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; + + /// @notice Address of the SchemaRegistry predeploy. + address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020; + + /// @notice Address of the EAS predeploy. + address internal constant EAS = 0x4200000000000000000000000000000000000021; + + /// @notice Address of the GovernanceToken predeploy. + address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; + + /// @custom:legacy + /// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the + /// state trie as of the Bedrock upgrade. Contract has been locked and write functions + /// can no longer be accessed. + address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; + + /// @notice Address of the CrossL2Inbox predeploy. + address internal constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; + + /// @notice Address of the L2ToL2CrossDomainMessenger predeploy. + address internal constant L2_TO_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000023; + + /// @notice Returns the name of the predeploy at the given address. + function getName(address _addr) internal pure returns (string memory out_) { + require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); + if (_addr == LEGACY_MESSAGE_PASSER) return "LegacyMessagePasser"; + if (_addr == L1_MESSAGE_SENDER) return "L1MessageSender"; + if (_addr == DEPLOYER_WHITELIST) return "DeployerWhitelist"; + if (_addr == WETH) return "WETH"; + if (_addr == L2_CROSS_DOMAIN_MESSENGER) return "L2CrossDomainMessenger"; + if (_addr == GAS_PRICE_ORACLE) return "GasPriceOracle"; + if (_addr == L2_STANDARD_BRIDGE) return "L2StandardBridge"; + if (_addr == SEQUENCER_FEE_WALLET) return "SequencerFeeVault"; + if (_addr == OPTIMISM_MINTABLE_ERC20_FACTORY) return "OptimismMintableERC20Factory"; + if (_addr == L1_BLOCK_NUMBER) return "L1BlockNumber"; + if (_addr == L2_ERC721_BRIDGE) return "L2ERC721Bridge"; + if (_addr == L1_BLOCK_ATTRIBUTES) return "L1Block"; + if (_addr == L2_TO_L1_MESSAGE_PASSER) return "L2ToL1MessagePasser"; + if (_addr == OPTIMISM_MINTABLE_ERC721_FACTORY) return "OptimismMintableERC721Factory"; + if (_addr == PROXY_ADMIN) return "ProxyAdmin"; + if (_addr == BASE_FEE_VAULT) return "BaseFeeVault"; + if (_addr == L1_FEE_VAULT) return "L1FeeVault"; + if (_addr == SCHEMA_REGISTRY) return "SchemaRegistry"; + if (_addr == EAS) return "EAS"; + if (_addr == GOVERNANCE_TOKEN) return "GovernanceToken"; + if (_addr == LEGACY_ERC20_ETH) return "LegacyERC20ETH"; + if (_addr == CROSS_L2_INBOX) return "CrossL2Inbox"; + if (_addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) return "L2ToL2CrossDomainMessenger"; + revert("Predeploys: unnamed predeploy"); + } + + /// @notice Returns true if the predeploy is not proxied. + function notProxied(address _addr) internal pure returns (bool) { + return _addr == GOVERNANCE_TOKEN || _addr == WETH; + } + + /// @notice Returns true if the address is a defined predeploy that is embedded into new OP-Stack chains. + function isSupportedPredeploy(address _addr, bool _useInterop) internal pure returns (bool) { + return + _addr == LEGACY_MESSAGE_PASSER || + _addr == DEPLOYER_WHITELIST || + _addr == WETH || + _addr == L2_CROSS_DOMAIN_MESSENGER || + _addr == GAS_PRICE_ORACLE || + _addr == L2_STANDARD_BRIDGE || + _addr == SEQUENCER_FEE_WALLET || + _addr == OPTIMISM_MINTABLE_ERC20_FACTORY || + _addr == L1_BLOCK_NUMBER || + _addr == L2_ERC721_BRIDGE || + _addr == L1_BLOCK_ATTRIBUTES || + _addr == L2_TO_L1_MESSAGE_PASSER || + _addr == OPTIMISM_MINTABLE_ERC721_FACTORY || + _addr == PROXY_ADMIN || + _addr == BASE_FEE_VAULT || + _addr == L1_FEE_VAULT || + _addr == SCHEMA_REGISTRY || + _addr == EAS || + _addr == GOVERNANCE_TOKEN || + (_useInterop && _addr == CROSS_L2_INBOX) || + (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER); + } + + function isPredeployNamespace(address _addr) internal pure returns (bool) { + return uint160(_addr) >> 11 == uint160(0x4200000000000000000000000000000000000000) >> 11; + } + + /// @notice Function to compute the expected address of the predeploy implementation + /// in the genesis state. + function predeployToCodeNamespace(address _addr) internal pure returns (address) { + require(isPredeployNamespace(_addr), "Predeploys: can only derive code-namespace address for predeploy addresses"); + return + address( + uint160((uint256(uint160(_addr)) & 0xffff) | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000))) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol new file mode 100644 index 0000000..3da986b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Storage.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @title Storage +/// @notice Storage handles reading and writing to arbitary storage locations +library Storage { + /// @notice Returns an address stored in an arbitrary storage slot. + /// These storage slots decouple the storage layout from + /// solc's automation. + /// @param _slot The storage slot to retrieve the address from. + function getAddress(bytes32 _slot) internal view returns (address addr_) { + assembly { + addr_ := sload(_slot) + } + } + + /// @notice Stores an address in an arbitrary storage slot, `_slot`. + /// @param _slot The storage slot to store the address in. + /// @param _address The protocol version to store + /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses + /// in arbitrary storage slots. + function setAddress(bytes32 _slot, address _address) internal { + assembly { + sstore(_slot, _address) + } + } + + /// @notice Returns a uint256 stored in an arbitrary storage slot. + /// These storage slots decouple the storage layout from + /// solc's automation. + /// @param _slot The storage slot to retrieve the address from. + function getUint(bytes32 _slot) internal view returns (uint256 value_) { + assembly { + value_ := sload(_slot) + } + } + + /// @notice Stores a value in an arbitrary storage slot, `_slot`. + /// @param _slot The storage slot to store the address in. + /// @param _value The protocol version to store + /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values + /// in arbitrary storage slots. + function setUint(bytes32 _slot, uint256 _value) internal { + assembly { + sstore(_slot, _value) + } + } + + /// @notice Returns a bytes32 stored in an arbitrary storage slot. + /// These storage slots decouple the storage layout from + /// solc's automation. + /// @param _slot The storage slot to retrieve the address from. + function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) { + assembly { + value_ := sload(_slot) + } + } + + /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`. + /// @param _slot The storage slot to store the address in. + /// @param _value The bytes32 value to store. + /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values + /// in arbitrary storage slots. + function setBytes32(bytes32 _slot, bytes32 _value) internal { + assembly { + sstore(_slot, _value) + } + } + + /// @notice Stores a bool value in an arbitrary storage slot, `_slot`. + /// @param _slot The storage slot to store the bool in. + /// @param _value The bool value to store + /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values + /// in arbitrary storage slots. + function setBool(bytes32 _slot, bool _value) internal { + assembly { + sstore(_slot, _value) + } + } + + /// @notice Returns a bool stored in an arbitrary storage slot. + /// @param _slot The storage slot to retrieve the bool from. + function getBool(bytes32 _slot) internal view returns (bool value_) { + assembly { + value_ := sload(_slot) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol new file mode 100644 index 0000000..d9f3cfd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract +/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/universal/ISemver.sol +/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle +/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist +/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract + +/// @title ISemver +/// @notice ISemver is a simple contract for ensuring that contracts are +/// versioned using semantic versioning. +interface ISemver { + /// @notice Getter for the semantic version of the contract. This is not + /// meant to be used onchain but instead meant to be used by offchain + /// tooling. + /// @return Semver contract version as a string. + function version() external view returns (string memory); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol new file mode 100644 index 0000000..8b5aad8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.7.6 <0.9.0; + +/** + * @title iOVM_CrossDomainMessenger + */ +interface iOVM_CrossDomainMessenger { + /********** + * Events * + **********/ + + event SentMessage(bytes message); + event RelayedMessage(bytes32 msgHash); + event FailedRelayedMessage(bytes32 msgHash); + + /************* + * Variables * + *************/ + + function xDomainMessageSender() external view returns (address); + + /******************** + * Public Functions * + ********************/ + + /** + * Sends a cross domain message to the target messenger. + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _gasLimit Gas limit for the provided message. + */ + function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol new file mode 100644 index 0000000..a3e137a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.6; + +/* External Imports */ +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title OVM_GasPriceOracle + * @dev This contract exposes the current l2 gas price, a measure of how congested the network + * currently is. This measure is used by the Sequencer to determine what fee to charge for + * transactions. When the system is more congested, the l2 gas price will increase and fees + * will also increase as a result. + * + * All public variables are set while generating the initial L2 state. The + * constructor doesn't run in practice as the L2 state generation script uses + * the deployed bytecode instead of running the initcode. + */ +contract OVM_GasPriceOracle is Ownable { + /************* + * Variables * + *************/ + + // Current L2 gas price + uint256 public gasPrice; + // Current L1 base fee + uint256 public l1BaseFee; + // Amortized cost of batch submission per transaction + uint256 public overhead; + // Value to scale the fee up by + uint256 public scalar; + // Number of decimals of the scalar + uint256 public decimals; + + /*************** + * Constructor * + ***************/ + + /** + * @param _owner Address that will initially own this contract. + */ + constructor(address _owner) Ownable() { + transferOwnership(_owner); + } + + /********** + * Events * + **********/ + + event GasPriceUpdated(uint256); + event L1BaseFeeUpdated(uint256); + event OverheadUpdated(uint256); + event ScalarUpdated(uint256); + event DecimalsUpdated(uint256); + + /******************** + * Public Functions * + ********************/ + + /** + * Allows the owner to modify the l2 gas price. + * @param _gasPrice New l2 gas price. + */ + // slither-disable-next-line external-function + function setGasPrice(uint256 _gasPrice) public onlyOwner { + gasPrice = _gasPrice; + emit GasPriceUpdated(_gasPrice); + } + + /** + * Allows the owner to modify the l1 base fee. + * @param _baseFee New l1 base fee + */ + // slither-disable-next-line external-function + function setL1BaseFee(uint256 _baseFee) public onlyOwner { + l1BaseFee = _baseFee; + emit L1BaseFeeUpdated(_baseFee); + } + + /** + * Allows the owner to modify the overhead. + * @param _overhead New overhead + */ + // slither-disable-next-line external-function + function setOverhead(uint256 _overhead) public onlyOwner { + overhead = _overhead; + emit OverheadUpdated(_overhead); + } + + /** + * Allows the owner to modify the scalar. + * @param _scalar New scalar + */ + // slither-disable-next-line external-function + function setScalar(uint256 _scalar) public onlyOwner { + scalar = _scalar; + emit ScalarUpdated(_scalar); + } + + /** + * Allows the owner to modify the decimals. + * @param _decimals New decimals + */ + // slither-disable-next-line external-function + function setDecimals(uint256 _decimals) public onlyOwner { + decimals = _decimals; + emit DecimalsUpdated(_decimals); + } + + /** + * Computes the L1 portion of the fee + * based on the size of the RLP encoded tx + * and the current l1BaseFee + * @param _data Unsigned RLP encoded tx, 6 elements + * @return L1 fee that should be paid for the tx + */ + // slither-disable-next-line external-function + function getL1Fee(bytes memory _data) public view returns (uint256) { + uint256 l1GasUsed = getL1GasUsed(_data); + uint256 l1Fee = l1GasUsed * l1BaseFee; + uint256 divisor = 10**decimals; + uint256 unscaled = l1Fee * scalar; + uint256 scaled = unscaled / divisor; + return scaled; + } + + // solhint-disable max-line-length + /** + * Computes the amount of L1 gas used for a transaction + * The overhead represents the per batch gas overhead of + * posting both transaction and state roots to L1 given larger + * batch sizes. + * 4 gas for 0 byte + * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33 + * 16 gas for non zero byte + * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87 + * This will need to be updated if calldata gas prices change + * Account for the transaction being unsigned + * Padding is added to account for lack of signature on transaction + * 1 byte for RLP V prefix + * 1 byte for V + * 1 byte for RLP R prefix + * 32 bytes for R + * 1 byte for RLP S prefix + * 32 bytes for S + * Total: 68 bytes of padding + * @param _data Unsigned RLP encoded tx, 6 elements + * @return Amount of L1 gas used for a transaction + */ + // solhint-enable max-line-length + function getL1GasUsed(bytes memory _data) public view returns (uint256) { + uint256 total = 0; + for (uint256 i = 0; i < _data.length; i++) { + if (_data[i] == 0) { + total += 4; + } else { + total += 16; + } + } + uint256 unsigned = total + overhead; + return unsigned + (68 * 16); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol new file mode 100644 index 0000000..b2a6c78 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +/* External Imports */ +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title OVM_GasPriceOracle + * @dev This contract exposes the current l2 gas price, a measure of how congested the network + * currently is. This measure is used by the Sequencer to determine what fee to charge for + * transactions. When the system is more congested, the l2 gas price will increase and fees + * will also increase as a result. + * + * All public variables are set while generating the initial L2 state. The + * constructor doesn't run in practice as the L2 state generation script uses + * the deployed bytecode instead of running the initcode. + */ +contract OVM_GasPriceOracle is Ownable { + /************* + * Variables * + *************/ + + // Current L2 gas price + uint256 public gasPrice; + // Current L1 base fee + uint256 public l1BaseFee; + // Amortized cost of batch submission per transaction + uint256 public overhead; + // Value to scale the fee up by + uint256 public scalar; + // Number of decimals of the scalar + uint256 public decimals; + + /*************** + * Constructor * + ***************/ + + /** + * @param _owner Address that will initially own this contract. + */ + constructor(address _owner) Ownable() { + transferOwnership(_owner); + } + + /********** + * Events * + **********/ + + event GasPriceUpdated(uint256); + event L1BaseFeeUpdated(uint256); + event OverheadUpdated(uint256); + event ScalarUpdated(uint256); + event DecimalsUpdated(uint256); + + /******************** + * Public Functions * + ********************/ + + /** + * Allows the owner to modify the l2 gas price. + * @param _gasPrice New l2 gas price. + */ + // slither-disable-next-line external-function + function setGasPrice(uint256 _gasPrice) public onlyOwner { + gasPrice = _gasPrice; + emit GasPriceUpdated(_gasPrice); + } + + /** + * Allows the owner to modify the l1 base fee. + * @param _baseFee New l1 base fee + */ + // slither-disable-next-line external-function + function setL1BaseFee(uint256 _baseFee) public onlyOwner { + l1BaseFee = _baseFee; + emit L1BaseFeeUpdated(_baseFee); + } + + /** + * Allows the owner to modify the overhead. + * @param _overhead New overhead + */ + // slither-disable-next-line external-function + function setOverhead(uint256 _overhead) public onlyOwner { + overhead = _overhead; + emit OverheadUpdated(_overhead); + } + + /** + * Allows the owner to modify the scalar. + * @param _scalar New scalar + */ + // slither-disable-next-line external-function + function setScalar(uint256 _scalar) public onlyOwner { + scalar = _scalar; + emit ScalarUpdated(_scalar); + } + + /** + * Allows the owner to modify the decimals. + * @param _decimals New decimals + */ + // slither-disable-next-line external-function + function setDecimals(uint256 _decimals) public onlyOwner { + decimals = _decimals; + emit DecimalsUpdated(_decimals); + } + + /** + * Computes the L1 portion of the fee + * based on the size of the RLP encoded tx + * and the current l1BaseFee + * @param _data Unsigned RLP encoded tx, 6 elements + * @return L1 fee that should be paid for the tx + */ + // slither-disable-next-line external-function + function getL1Fee(bytes memory _data) public view returns (uint256) { + uint256 l1GasUsed = getL1GasUsed(_data); + uint256 l1Fee = l1GasUsed * l1BaseFee; + uint256 divisor = 10 ** decimals; + uint256 unscaled = l1Fee * scalar; + uint256 scaled = unscaled / divisor; + return scaled; + } + + // solhint-disable max-line-length + /** + * Computes the amount of L1 gas used for a transaction + * The overhead represents the per batch gas overhead of + * posting both transaction and state roots to L1 given larger + * batch sizes. + * 4 gas for 0 byte + * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33 + * 16 gas for non zero byte + * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87 + * This will need to be updated if calldata gas prices change + * Account for the transaction being unsigned + * Padding is added to account for lack of signature on transaction + * 1 byte for RLP V prefix + * 1 byte for V + * 1 byte for RLP R prefix + * 32 bytes for R + * 1 byte for RLP S prefix + * 32 bytes for S + * Total: 68 bytes of padding + * @param _data Unsigned RLP encoded tx, 6 elements + * @return Amount of L1 gas used for a transaction + */ + // solhint-enable max-line-length + function getL1GasUsed(bytes memory _data) public view returns (uint256) { + uint256 total = 0; + for (uint256 i = 0; i < _data.length; i++) { + if (_data[i] == 0) { + total += 4; + } else { + total += 16; + } + } + uint256 unsigned = total + overhead; + return unsigned + (68 * 16); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol new file mode 100644 index 0000000..95b88e9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +interface IScrollL1GasPriceOracle { + /********** + * Events * + **********/ + + /// @notice Emitted when current fee overhead is updated. + /// @param overhead The current fee overhead updated. + event OverheadUpdated(uint256 overhead); + + /// @notice Emitted when current fee scalar is updated. + /// @param scalar The current fee scalar updated. + event ScalarUpdated(uint256 scalar); + + /// @notice Emitted when current l1 base fee is updated. + /// @param l1BaseFee The current l1 base fee updated. + event L1BaseFeeUpdated(uint256 l1BaseFee); + + /************************* + * Public View Functions * + *************************/ + + /// @notice Return the current l1 fee overhead. + function overhead() external view returns (uint256); + + /// @notice Return the current l1 fee scalar. + function scalar() external view returns (uint256); + + /// @notice Return the latest known l1 base fee. + function l1BaseFee() external view returns (uint256); + + /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input + /// transaction, the current L1 base fee, and the various dynamic parameters. + /// @param data Unsigned fully RLP-encoded transaction to get the L1 fee for. + /// @return L1 fee that should be paid for the tx + function getL1Fee(bytes memory data) external view returns (uint256); + + /// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which + /// represents the per-transaction gas overhead of posting the transaction and state + /// roots to L1. Adds 74 bytes of padding to account for the fact that the input does + /// not have a signature. + /// @param data Unsigned fully RLP-encoded transaction to get the L1 gas for. + /// @return Amount of L1 gas used to publish the transaction. + function getL1GasUsed(bytes memory data) external view returns (uint256); + + /***************************** + * Public Mutating Functions * + *****************************/ + + /// @notice Allows whitelisted caller to modify the l1 base fee. + /// @param _l1BaseFee New l1 base fee. + function setL1BaseFee(uint256 _l1BaseFee) external; +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol new file mode 100644 index 0000000..761fac9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @dev A library for working with mutable byte buffers in Solidity. + * + * Byte buffers are mutable and expandable, and provide a variety of primitives + * for writing to them. At any time you can fetch a bytes object containing the + * current contents of the buffer. The bytes object should not be stored between + * operations, as it may change due to resizing of the buffer. + */ +library BufferChainlink { + /** + * @dev Represents a mutable buffer. Buffers have a current value (buf) and + * a capacity. The capacity may be longer than the current value, in + * which case it can be extended without the need to allocate more memory. + */ + struct buffer { + bytes buf; + uint256 capacity; + } + + /** + * @dev Initializes a buffer with an initial capacity. + * @param buf The buffer to initialize. + * @param capacity The number of bytes of space to allocate the buffer. + * @return The buffer, for chaining. + */ + function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) { + if (capacity % 32 != 0) { + capacity += 32 - (capacity % 32); + } + // Allocate space for the buffer data + buf.capacity = capacity; + assembly { + let ptr := mload(0x40) + mstore(buf, ptr) + mstore(ptr, 0) + mstore(0x40, add(32, add(ptr, capacity))) + } + return buf; + } + + /** + * @dev Initializes a new buffer from an existing bytes object. + * Changes to the buffer may mutate the original value. + * @param b The bytes object to initialize the buffer with. + * @return A new buffer. + */ + function fromBytes(bytes memory b) internal pure returns (buffer memory) { + buffer memory buf; + buf.buf = b; + buf.capacity = b.length; + return buf; + } + + function resize(buffer memory buf, uint256 capacity) private pure { + bytes memory oldbuf = buf.buf; + init(buf, capacity); + append(buf, oldbuf); + } + + function max(uint256 a, uint256 b) private pure returns (uint256) { + if (a > b) { + return a; + } + return b; + } + + /** + * @dev Sets buffer length to 0. + * @param buf The buffer to truncate. + * @return The original buffer, for chaining.. + */ + function truncate(buffer memory buf) internal pure returns (buffer memory) { + assembly { + let bufptr := mload(buf) + mstore(bufptr, 0) + } + return buf; + } + + /** + * @dev Writes a byte string to a buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param off The start offset to write to. + * @param data The data to append. + * @param len The number of bytes to copy. + * @return The original buffer, for chaining. + */ + function write( + buffer memory buf, + uint256 off, + bytes memory data, + uint256 len + ) internal pure returns (buffer memory) { + require(len <= data.length); + + if (off + len > buf.capacity) { + resize(buf, max(buf.capacity, len + off) * 2); + } + + uint256 dest; + uint256 src; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Start address = buffer address + offset + sizeof(buffer length) + dest := add(add(bufptr, 32), off) + // Update buffer length if we're extending it + if gt(add(len, off), buflen) { + mstore(bufptr, add(len, off)) + } + src := add(data, 32) + } + + // Copy word-length chunks while possible + for (; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + unchecked { + uint256 mask = (256**(32 - len)) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + return buf; + } + + /** + * @dev Appends a byte string to a buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @param len The number of bytes to copy. + * @return The original buffer, for chaining. + */ + function append( + buffer memory buf, + bytes memory data, + uint256 len + ) internal pure returns (buffer memory) { + return write(buf, buf.buf.length, data, len); + } + + /** + * @dev Appends a byte string to a buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { + return write(buf, buf.buf.length, data, data.length); + } + + /** + * @dev Writes a byte to the buffer. Resizes if doing so would exceed the + * capacity of the buffer. + * @param buf The buffer to append to. + * @param off The offset to write the byte at. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function writeUint8( + buffer memory buf, + uint256 off, + uint8 data + ) internal pure returns (buffer memory) { + if (off >= buf.capacity) { + resize(buf, buf.capacity * 2); + } + + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Length of existing buffer data + let buflen := mload(bufptr) + // Address = buffer address + sizeof(buffer length) + off + let dest := add(add(bufptr, off), 32) + mstore8(dest, data) + // Update buffer length if we extended it + if eq(off, buflen) { + mstore(bufptr, add(buflen, 1)) + } + } + return buf; + } + + /** + * @dev Appends a byte to the buffer. Resizes if doing so would exceed the + * capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) { + return writeUint8(buf, buf.buf.length, data); + } + + /** + * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param off The offset to write at. + * @param data The data to append. + * @param len The number of bytes to write (left-aligned). + * @return The original buffer, for chaining. + */ + function write( + buffer memory buf, + uint256 off, + bytes32 data, + uint256 len + ) private pure returns (buffer memory) { + if (len + off > buf.capacity) { + resize(buf, (len + off) * 2); + } + + unchecked { + uint256 mask = (256**len) - 1; + // Right-align data + data = data >> (8 * (32 - len)); + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Address = buffer address + sizeof(buffer length) + off + len + let dest := add(add(bufptr, off), len) + mstore(dest, or(and(mload(dest), not(mask)), data)) + // Update buffer length if we extended it + if gt(add(off, len), mload(bufptr)) { + mstore(bufptr, add(off, len)) + } + } + } + return buf; + } + + /** + * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the + * capacity of the buffer. + * @param buf The buffer to append to. + * @param off The offset to write at. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function writeBytes20( + buffer memory buf, + uint256 off, + bytes20 data + ) internal pure returns (buffer memory) { + return write(buf, off, bytes32(data), 20); + } + + /** + * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chhaining. + */ + function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { + return write(buf, buf.buf.length, bytes32(data), 20); + } + + /** + * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer, for chaining. + */ + function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { + return write(buf, buf.buf.length, data, 32); + } + + /** + * @dev Writes an integer to the buffer. Resizes if doing so would exceed + * the capacity of the buffer. + * @param buf The buffer to append to. + * @param off The offset to write at. + * @param data The data to append. + * @param len The number of bytes to write (right-aligned). + * @return The original buffer, for chaining. + */ + function writeInt( + buffer memory buf, + uint256 off, + uint256 data, + uint256 len + ) private pure returns (buffer memory) { + if (len + off > buf.capacity) { + resize(buf, (len + off) * 2); + } + + uint256 mask = (256**len) - 1; + assembly { + // Memory address of the buffer data + let bufptr := mload(buf) + // Address = buffer address + off + sizeof(buffer length) + len + let dest := add(add(bufptr, off), len) + mstore(dest, or(and(mload(dest), not(mask)), data)) + // Update buffer length if we extended it + if gt(add(off, len), mload(bufptr)) { + mstore(bufptr, add(off, len)) + } + } + return buf; + } + + /** + * @dev Appends a byte to the end of the buffer. Resizes if doing so would + * exceed the capacity of the buffer. + * @param buf The buffer to append to. + * @param data The data to append. + * @return The original buffer. + */ + function appendInt( + buffer memory buf, + uint256 data, + uint256 len + ) internal pure returns (buffer memory) { + return writeInt(buf, buf.buf.length, data, len); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol new file mode 100644 index 0000000..5ee0cec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.19; + +import {BufferChainlink} from "./BufferChainlink.sol"; + +library CBORChainlink { + using BufferChainlink for BufferChainlink.buffer; + + uint8 private constant MAJOR_TYPE_INT = 0; + uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; + uint8 private constant MAJOR_TYPE_BYTES = 2; + uint8 private constant MAJOR_TYPE_STRING = 3; + uint8 private constant MAJOR_TYPE_ARRAY = 4; + uint8 private constant MAJOR_TYPE_MAP = 5; + uint8 private constant MAJOR_TYPE_TAG = 6; + uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; + + uint8 private constant TAG_TYPE_BIGNUM = 2; + uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; + + function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { + if(value <= 23) { + buf.appendUint8(uint8((major << 5) | value)); + } else if (value <= 0xFF) { + buf.appendUint8(uint8((major << 5) | 24)); + buf.appendInt(value, 1); + } else if (value <= 0xFFFF) { + buf.appendUint8(uint8((major << 5) | 25)); + buf.appendInt(value, 2); + } else if (value <= 0xFFFFFFFF) { + buf.appendUint8(uint8((major << 5) | 26)); + buf.appendInt(value, 4); + } else { + buf.appendUint8(uint8((major << 5) | 27)); + buf.appendInt(value, 8); + } + } + + function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { + buf.appendUint8(uint8((major << 5) | 31)); + } + + function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { + if(value > 0xFFFFFFFFFFFFFFFF) { + encodeBigNum(buf, value); + } else { + encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); + } + } + + function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { + if(value < -0x10000000000000000) { + encodeSignedBigNum(buf, value); + } else if(value > 0xFFFFFFFFFFFFFFFF) { + encodeBigNum(buf, uint(value)); + } else if(value >= 0) { + encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value))); + } else { + encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value))); + } + } + + function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { + encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); + buf.append(value); + } + + function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { + buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); + encodeBytes(buf, abi.encode(value)); + } + + function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { + buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); + encodeBytes(buf, abi.encode(uint256(-1 - input))); + } + + function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { + encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); + buf.append(bytes(value)); + } + + function startArray(BufferChainlink.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); + } + + function startMap(BufferChainlink.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); + } + + function endSequence(BufferChainlink.buffer memory buf) internal pure { + encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol new file mode 100644 index 0000000..d375ca4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT + +// sourced from https://github.com/pipermerriam/ethereum-datetime + +pragma solidity ^0.8.0; + +library DateTime { + /* + * Date and Time utilities for ethereum contracts + * + */ + struct _DateTime { + uint16 year; + uint8 month; + uint8 day; + uint8 hour; + uint8 minute; + uint8 second; + uint8 weekday; + } + + uint256 constant DAY_IN_SECONDS = 86400; + uint256 constant YEAR_IN_SECONDS = 31536000; + uint256 constant LEAP_YEAR_IN_SECONDS = 31622400; + + uint256 constant HOUR_IN_SECONDS = 3600; + uint256 constant MINUTE_IN_SECONDS = 60; + + uint16 constant ORIGIN_YEAR = 1970; + + function isLeapYear(uint16 year) internal pure returns (bool) { + if (year % 4 != 0) { + return false; + } + if (year % 100 != 0) { + return true; + } + if (year % 400 != 0) { + return false; + } + return true; + } + + function leapYearsBefore(uint256 year) internal pure returns (uint256) { + year -= 1; + return year / 4 - year / 100 + year / 400; + } + + function getDaysInMonth(uint8 month, uint16 year) + internal + pure + returns (uint8) + { + if ( + month == 1 || + month == 3 || + month == 5 || + month == 7 || + month == 8 || + month == 10 || + month == 12 + ) { + return 31; + } else if (month == 4 || month == 6 || month == 9 || month == 11) { + return 30; + } else if (isLeapYear(year)) { + return 29; + } else { + return 28; + } + } + + function parseTimestamp(uint256 timestamp) + internal + pure + returns (_DateTime memory dt) + { + uint256 secondsAccountedFor = 0; + uint256 buf; + uint8 i; + + // Year + dt.year = getYear(timestamp); + buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); + + secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; + secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); + + // Month + uint256 secondsInMonth; + for (i = 1; i <= 12; i++) { + secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); + if (secondsInMonth + secondsAccountedFor > timestamp) { + dt.month = i; + break; + } + secondsAccountedFor += secondsInMonth; + } + + // Day + for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { + if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { + dt.day = i; + break; + } + secondsAccountedFor += DAY_IN_SECONDS; + } + + // Hour + dt.hour = getHour(timestamp); + + // Minute + dt.minute = getMinute(timestamp); + + // Second + dt.second = getSecond(timestamp); + + // Day of week. + dt.weekday = getWeekday(timestamp); + } + + function getYear(uint256 timestamp) internal pure returns (uint16) { + uint256 secondsAccountedFor = 0; + uint16 year; + uint256 numLeapYears; + + // Year + year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); + numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); + + secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; + secondsAccountedFor += + YEAR_IN_SECONDS * + (year - ORIGIN_YEAR - numLeapYears); + + while (secondsAccountedFor > timestamp) { + if (isLeapYear(uint16(year - 1))) { + secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; + } else { + secondsAccountedFor -= YEAR_IN_SECONDS; + } + year -= 1; + } + return year; + } + + function getMonth(uint256 timestamp) internal pure returns (uint8) { + return parseTimestamp(timestamp).month; + } + + function getDay(uint256 timestamp) internal pure returns (uint8) { + return parseTimestamp(timestamp).day; + } + + function getHour(uint256 timestamp) internal pure returns (uint8) { + return uint8((timestamp / 60 / 60) % 24); + } + + function getMinute(uint256 timestamp) internal pure returns (uint8) { + return uint8((timestamp / 60) % 60); + } + + function getSecond(uint256 timestamp) internal pure returns (uint8) { + return uint8(timestamp % 60); + } + + function getWeekday(uint256 timestamp) internal pure returns (uint8) { + return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); + } + + function toTimestamp( + uint16 year, + uint8 month, + uint8 day + ) internal pure returns (uint256 timestamp) { + return toTimestamp(year, month, day, 0, 0, 0); + } + + function toTimestamp( + uint16 year, + uint8 month, + uint8 day, + uint8 hour + ) internal pure returns (uint256 timestamp) { + return toTimestamp(year, month, day, hour, 0, 0); + } + + function toTimestamp( + uint16 year, + uint8 month, + uint8 day, + uint8 hour, + uint8 minute + ) internal pure returns (uint256 timestamp) { + return toTimestamp(year, month, day, hour, minute, 0); + } + + function toTimestamp( + uint16 year, + uint8 month, + uint8 day, + uint8 hour, + uint8 minute, + uint8 second + ) internal pure returns (uint256 timestamp) { + uint16 i; + + // Year + for (i = ORIGIN_YEAR; i < year; i++) { + if (isLeapYear(i)) { + timestamp += LEAP_YEAR_IN_SECONDS; + } else { + timestamp += YEAR_IN_SECONDS; + } + } + + // Month + uint8[12] memory monthDayCounts; + monthDayCounts[0] = 31; + if (isLeapYear(year)) { + monthDayCounts[1] = 29; + } else { + monthDayCounts[1] = 28; + } + monthDayCounts[2] = 31; + monthDayCounts[3] = 30; + monthDayCounts[4] = 31; + monthDayCounts[5] = 30; + monthDayCounts[6] = 31; + monthDayCounts[7] = 31; + monthDayCounts[8] = 30; + monthDayCounts[9] = 31; + monthDayCounts[10] = 30; + monthDayCounts[11] = 31; + + for (i = 1; i < month; i++) { + timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1]; + } + + // Day + timestamp += DAY_IN_SECONDS * (day - 1); + + // Hour + timestamp += HOUR_IN_SECONDS * (hour); + + // Minute + timestamp += MINUTE_IN_SECONDS * (minute); + + // Second + timestamp += second; + + return timestamp; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol new file mode 100644 index 0000000..eb92ced --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +abstract contract ENSResolver { + function addr(bytes32 node) public view virtual returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol new file mode 100644 index 0000000..9af4bf8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +interface IERC165 { + /// @notice Query if a contract implements an interface + /// @param interfaceID The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol new file mode 100644 index 0000000..ae8b6af --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.6 <0.9.0; + +import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; + +/** + * @title iOVM_CrossDomainMessenger + */ +interface iOVM_CrossDomainMessenger { + /********** + * Events * + **********/ + + event SentMessage(bytes message); + event RelayedMessage(bytes32 msgHash); + event FailedRelayedMessage(bytes32 msgHash); + + /************* + * Variables * + *************/ + + function xDomainMessageSender() external view returns (address); + + /******************** + * Public Functions * + ********************/ + + /** + * Sends a cross domain message to the target messenger. + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _gasLimit Gas limit for the provided message. + */ + function sendMessage( + address _target, + bytes calldata _message, + uint32 _gasLimit + ) external; +} + +contract MockOVMCrossDomainMessenger is iOVM_CrossDomainMessenger{ + address internal mockMessageSender; + + constructor(address sender) { + mockMessageSender = sender; + } + + function xDomainMessageSender() external view override returns (address) { + return mockMessageSender; + } + + function _setMockMessageSender(address sender) external { + mockMessageSender = sender; + } + + /******************** + * Public Functions * + ********************/ + + /** + * Sends a cross domain message to the target messenger. + * @param _target Target contract address. + * @param _message Message to send to the target. + * @param _gasLimit Gas limit for the provided message. + */ + function sendMessage( + address _target, + bytes calldata _message, + uint32 _gasLimit + ) external override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol new file mode 100644 index 0000000..bb5390b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; + +/// sourced from: https://github.com/scroll-tech/scroll/blob/develop/contracts/src/libraries/IScrollMessenger.sol +interface IScrollMessenger { + /// ********** + /// * Events * + /// ********** + + /// @notice Emitted when a cross domain message is sent. + /// @param sender The address of the sender who initiates the message. + /// @param target The address of target contract to call. + /// @param value The amount of value passed to the target contract. + /// @param messageNonce The nonce of the message. + /// @param gasLimit The optional gas limit passed to L1 or L2. + /// @param message The calldata passed to the target contract. + event SentMessage( + address indexed sender, + address indexed target, + uint256 value, + uint256 messageNonce, + uint256 gasLimit, + bytes message + ); + + /// @notice Emitted when a cross domain message is relayed successfully. + /// @param messageHash The hash of the message. + event RelayedMessage(bytes32 indexed messageHash); + + /// @notice Emitted when a cross domain message is failed to relay. + /// @param messageHash The hash of the message. + event FailedRelayedMessage(bytes32 indexed messageHash); + + /// ************************* + /// * Public View Functions * + /// ************************* + + /// @notice Return the sender of a cross domain message. + function xDomainMessageSender() external view returns (address); + + /// ***************************** + /// * Public Mutating Functions * + /// ***************************** + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param target The address of account who receive the message. + /// @param value The amount of ether passed when call target contract. + /// @param message The content of the message. + /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. + function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit) external payable; + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param target The address of account who receive the message. + /// @param value The amount of ether passed when call target contract. + /// @param message The content of the message. + /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. + /// @param refundAddress The address of account who will receive the refunded fee. + function sendMessage( + address target, + uint256 value, + bytes calldata message, + uint256 gasLimit, + address refundAddress + ) external payable; +} + +contract MockScrollCrossDomainMessenger is IScrollMessenger { + address internal mockMessageSender; + + constructor(address sender) { + mockMessageSender = sender; + } + + function xDomainMessageSender() external view override returns (address) { + return mockMessageSender; + } + + function _setMockMessageSender(address sender) external { + mockMessageSender = sender; + } + + /// ***************************** + /// * Public Mutating Functions * + /// ***************************** + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } + + /// @notice Send cross chain message from L1 to L2 or L2 to L1. + /// @param _target The address of account who receive the message. + /// @param _message The content of the message. + function sendMessage(address _target, uint256, bytes calldata _message, uint256, address) external payable override { + Address.functionCall(_target, _message, "sendMessage reverted"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol new file mode 100644 index 0000000..15a7d2f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.0 <0.9.0; + +/// @title Multi Send - Allows to batch multiple transactions into one. +/// @author Nick Dodson - +/// @author Gonçalo Sá - +/// @author Stefan George - +/// @author Richard Meissner - +contract MultiSend { + address private immutable multisendSingleton; + + constructor() { + multisendSingleton = address(this); + } + + /// @dev Sends multiple transactions and reverts all if one fails. + /// @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of + /// operation as a uint8 with 0 for a call or 1 for a delegatecall (=> 1 byte), + /// to as a address (=> 20 bytes), + /// value as a uint256 (=> 32 bytes), + /// data length as a uint256 (=> 32 bytes), + /// data as bytes. + /// see abi.encodePacked for more information on packed encoding + /// @notice This method is payable as delegatecalls keep the msg.value from the previous call + /// If the calling method (e.g. execTransaction) received ETH this would revert otherwise + function multiSend(bytes memory transactions) public payable { + require(address(this) != multisendSingleton, "MultiSend should only be called via delegatecall"); + // solhint-disable-next-line no-inline-assembly + assembly { + let length := mload(transactions) + let i := 0x20 + for { + // Pre block is not used in "while mode" + } lt(i, length) { + // Post block is not used in "while mode" + } { + // First byte of the data is the operation. + // We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a word). + // This will also zero out unused data. + let operation := shr(0xf8, mload(add(transactions, i))) + // We offset the load address by 1 byte (operation byte) + // We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data. + let to := shr(0x60, mload(add(transactions, add(i, 0x01)))) + // We offset the load address by 21 byte (operation byte + 20 address bytes) + let value := mload(add(transactions, add(i, 0x15))) + // We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes) + let dataLength := mload(add(transactions, add(i, 0x35))) + // We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data length bytes) + let data := add(transactions, add(i, 0x55)) + let success := 0 + switch operation + case 0 { + success := call(gas(), to, value, data, dataLength, 0, 0) + } + case 1 { + success := delegatecall(gas(), to, data, dataLength, 0, 0) + } + if eq(success, 0) { + revert(0, 0) + } + // Next entry starts at 85 byte + data length + i := add(i, add(0x55, dataLength)) + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol new file mode 100644 index 0000000..4a17bd9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol @@ -0,0 +1,842 @@ +// SPDX-License-Identifier: Apache 2.0 + +/* + * @title String & slice utility library for Solidity contracts. + * @author Nick Johnson + * + * @dev Functionality in this library is largely implemented using an + * abstraction called a 'slice'. A slice represents a part of a string - + * anything from the entire string to a single character, or even no + * characters at all (a 0-length slice). Since a slice only has to specify + * an offset and a length, copying and manipulating slices is a lot less + * expensive than copying and manipulating the strings they reference. + * + * To further reduce gas costs, most functions on slice that need to return + * a slice modify the original one instead of allocating a new one; for + * instance, `s.split(".")` will return the text up to the first '.', + * modifying s to only contain the remainder of the string after the '.'. + * In situations where you do not want to modify the original slice, you + * can make a copy first with `.copy()`, for example: + * `s.copy().split(".")`. Try and avoid using this idiom in loops; since + * Solidity has no memory management, it will result in allocating many + * short-lived slices that are later discarded. + * + * Functions that return two slices come in two versions: a non-allocating + * version that takes the second slice as an argument, modifying it in + * place, and an allocating version that allocates and returns the second + * slice; see `nextRune` for example. + * + * Functions that have to copy string data will return strings rather than + * slices; these can be cast back to slices for further processing if + * required. + * + * For convenience, some functions are provided with non-modifying + * variants that create a new slice and return both; for instance, + * `s.splitNew('.')` leaves s unmodified, and returns two values + * corresponding to the left and right parts of the string. + */ + +pragma solidity ^0.8.0; + +library strings { + struct slice { + uint256 _len; + uint256 _ptr; + } + + function memcpy( + uint256 dest, + uint256 src, + uint256 len + ) private pure { + // Copy word-length chunks while possible + for (; len >= 32; len -= 32) { + assembly { + mstore(dest, mload(src)) + } + dest += 32; + src += 32; + } + + // Copy remaining bytes + uint256 mask = type(uint256).max; + if (len > 0) { + mask = 256**(32 - len) - 1; + } + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + /* + * @dev Returns a slice containing the entire string. + * @param self The string to make a slice from. + * @return A newly allocated slice containing the entire string. + */ + function toSlice(string memory self) internal pure returns (slice memory) { + uint256 ptr; + assembly { + ptr := add(self, 0x20) + } + return slice(bytes(self).length, ptr); + } + + /* + * @dev Returns the length of a null-terminated bytes32 string. + * @param self The value to find the length of. + * @return The length of the string, from 0 to 32. + */ + function len(bytes32 self) internal pure returns (uint256) { + uint256 ret; + if (self == 0) return 0; + if (uint256(self) & type(uint128).max == 0) { + ret += 16; + self = bytes32(uint256(self) / 0x100000000000000000000000000000000); + } + if (uint256(self) & type(uint64).max == 0) { + ret += 8; + self = bytes32(uint256(self) / 0x10000000000000000); + } + if (uint256(self) & type(uint32).max == 0) { + ret += 4; + self = bytes32(uint256(self) / 0x100000000); + } + if (uint256(self) & type(uint16).max == 0) { + ret += 2; + self = bytes32(uint256(self) / 0x10000); + } + if (uint256(self) & type(uint8).max == 0) { + ret += 1; + } + return 32 - ret; + } + + /* + * @dev Returns a slice containing the entire bytes32, interpreted as a + * null-terminated utf-8 string. + * @param self The bytes32 value to convert to a slice. + * @return A new slice containing the value of the input argument up to the + * first null. + */ + function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { + // Allocate space for `self` in memory, copy it there, and point ret at it + assembly { + let ptr := mload(0x40) + mstore(0x40, add(ptr, 0x20)) + mstore(ptr, self) + mstore(add(ret, 0x20), ptr) + } + ret._len = len(self); + } + + /* + * @dev Returns a new slice containing the same data as the current slice. + * @param self The slice to copy. + * @return A new slice containing the same data as `self`. + */ + function copy(slice memory self) internal pure returns (slice memory) { + return slice(self._len, self._ptr); + } + + /* + * @dev Copies a slice to a new string. + * @param self The slice to copy. + * @return A newly allocated string containing the slice's text. + */ + function toString(slice memory self) internal pure returns (string memory) { + string memory ret = new string(self._len); + uint256 retptr; + assembly { + retptr := add(ret, 32) + } + + memcpy(retptr, self._ptr, self._len); + return ret; + } + + /* + * @dev Returns the length in runes of the slice. Note that this operation + * takes time proportional to the length of the slice; avoid using it + * in loops, and call `slice.empty()` if you only need to know whether + * the slice is empty or not. + * @param self The slice to operate on. + * @return The length of the slice in runes. + */ + function len(slice memory self) internal pure returns (uint256 l) { + // Starting at ptr-31 means the LSB will be the byte we care about + uint256 ptr = self._ptr - 31; + uint256 end = ptr + self._len; + for (l = 0; ptr < end; l++) { + uint8 b; + assembly { + b := and(mload(ptr), 0xFF) + } + if (b < 0x80) { + ptr += 1; + } else if (b < 0xE0) { + ptr += 2; + } else if (b < 0xF0) { + ptr += 3; + } else if (b < 0xF8) { + ptr += 4; + } else if (b < 0xFC) { + ptr += 5; + } else { + ptr += 6; + } + } + } + + /* + * @dev Returns true if the slice is empty (has a length of 0). + * @param self The slice to operate on. + * @return True if the slice is empty, False otherwise. + */ + function empty(slice memory self) internal pure returns (bool) { + return self._len == 0; + } + + /* + * @dev Returns a positive number if `other` comes lexicographically after + * `self`, a negative number if it comes before, or zero if the + * contents of the two slices are equal. Comparison is done per-rune, + * on unicode codepoints. + * @param self The first slice to compare. + * @param other The second slice to compare. + * @return The result of the comparison. + */ + function compare(slice memory self, slice memory other) + internal + pure + returns (int256) + { + uint256 shortest = self._len; + if (other._len < self._len) shortest = other._len; + + uint256 selfptr = self._ptr; + uint256 otherptr = other._ptr; + for (uint256 idx = 0; idx < shortest; idx += 32) { + uint256 a; + uint256 b; + assembly { + a := mload(selfptr) + b := mload(otherptr) + } + if (a != b) { + // Mask out irrelevant bytes and check again + uint256 mask = type(uint256).max; // 0xffff... + if (shortest < 32) { + mask = ~(2**(8 * (32 - shortest + idx)) - 1); + } + unchecked { + uint256 diff = (a & mask) - (b & mask); + if (diff != 0) return int256(diff); + } + } + selfptr += 32; + otherptr += 32; + } + return int256(self._len) - int256(other._len); + } + + /* + * @dev Returns true if the two slices contain the same text. + * @param self The first slice to compare. + * @param self The second slice to compare. + * @return True if the slices are equal, false otherwise. + */ + function equals(slice memory self, slice memory other) + internal + pure + returns (bool) + { + return compare(self, other) == 0; + } + + /* + * @dev Extracts the first rune in the slice into `rune`, advancing the + * slice to point to the next rune and returning `self`. + * @param self The slice to operate on. + * @param rune The slice that will contain the first rune. + * @return `rune`. + */ + function nextRune(slice memory self, slice memory rune) + internal + pure + returns (slice memory) + { + rune._ptr = self._ptr; + + if (self._len == 0) { + rune._len = 0; + return rune; + } + + uint256 l; + uint256 b; + // Load the first byte of the rune into the LSBs of b + assembly { + b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) + } + if (b < 0x80) { + l = 1; + } else if (b < 0xE0) { + l = 2; + } else if (b < 0xF0) { + l = 3; + } else { + l = 4; + } + + // Check for truncated codepoints + if (l > self._len) { + rune._len = self._len; + self._ptr += self._len; + self._len = 0; + return rune; + } + + self._ptr += l; + self._len -= l; + rune._len = l; + return rune; + } + + /* + * @dev Returns the first rune in the slice, advancing the slice to point + * to the next rune. + * @param self The slice to operate on. + * @return A slice containing only the first rune from `self`. + */ + function nextRune(slice memory self) + internal + pure + returns (slice memory ret) + { + nextRune(self, ret); + } + + /* + * @dev Returns the number of the first codepoint in the slice. + * @param self The slice to operate on. + * @return The number of the first codepoint in the slice. + */ + function ord(slice memory self) internal pure returns (uint256 ret) { + if (self._len == 0) { + return 0; + } + + uint256 word; + uint256 length; + uint256 divisor = 2**248; + + // Load the rune into the MSBs of b + assembly { + word := mload(mload(add(self, 32))) + } + uint256 b = word / divisor; + if (b < 0x80) { + ret = b; + length = 1; + } else if (b < 0xE0) { + ret = b & 0x1F; + length = 2; + } else if (b < 0xF0) { + ret = b & 0x0F; + length = 3; + } else { + ret = b & 0x07; + length = 4; + } + + // Check for truncated codepoints + if (length > self._len) { + return 0; + } + + for (uint256 i = 1; i < length; i++) { + divisor = divisor / 256; + b = (word / divisor) & 0xFF; + if (b & 0xC0 != 0x80) { + // Invalid UTF-8 sequence + return 0; + } + ret = (ret * 64) | (b & 0x3F); + } + + return ret; + } + + /* + * @dev Returns the keccak-256 hash of the slice. + * @param self The slice to hash. + * @return The hash of the slice. + */ + function keccak(slice memory self) internal pure returns (bytes32 ret) { + assembly { + ret := keccak256(mload(add(self, 32)), mload(self)) + } + } + + /* + * @dev Returns true if `self` starts with `needle`. + * @param self The slice to operate on. + * @param needle The slice to search for. + * @return True if the slice starts with the provided text, false otherwise. + */ + function startsWith(slice memory self, slice memory needle) + internal + pure + returns (bool) + { + if (self._len < needle._len) { + return false; + } + + if (self._ptr == needle._ptr) { + return true; + } + + bool equal; + assembly { + let length := mload(needle) + let selfptr := mload(add(self, 0x20)) + let needleptr := mload(add(needle, 0x20)) + equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) + } + return equal; + } + + /* + * @dev If `self` starts with `needle`, `needle` is removed from the + * beginning of `self`. Otherwise, `self` is unmodified. + * @param self The slice to operate on. + * @param needle The slice to search for. + * @return `self` + */ + function beyond(slice memory self, slice memory needle) + internal + pure + returns (slice memory) + { + if (self._len < needle._len) { + return self; + } + + bool equal = true; + if (self._ptr != needle._ptr) { + assembly { + let length := mload(needle) + let selfptr := mload(add(self, 0x20)) + let needleptr := mload(add(needle, 0x20)) + equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) + } + } + + if (equal) { + self._len -= needle._len; + self._ptr += needle._len; + } + + return self; + } + + /* + * @dev Returns true if the slice ends with `needle`. + * @param self The slice to operate on. + * @param needle The slice to search for. + * @return True if the slice starts with the provided text, false otherwise. + */ + function endsWith(slice memory self, slice memory needle) + internal + pure + returns (bool) + { + if (self._len < needle._len) { + return false; + } + + uint256 selfptr = self._ptr + self._len - needle._len; + + if (selfptr == needle._ptr) { + return true; + } + + bool equal; + assembly { + let length := mload(needle) + let needleptr := mload(add(needle, 0x20)) + equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) + } + + return equal; + } + + /* + * @dev If `self` ends with `needle`, `needle` is removed from the + * end of `self`. Otherwise, `self` is unmodified. + * @param self The slice to operate on. + * @param needle The slice to search for. + * @return `self` + */ + function until(slice memory self, slice memory needle) + internal + pure + returns (slice memory) + { + if (self._len < needle._len) { + return self; + } + + uint256 selfptr = self._ptr + self._len - needle._len; + bool equal = true; + if (selfptr != needle._ptr) { + assembly { + let length := mload(needle) + let needleptr := mload(add(needle, 0x20)) + equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) + } + } + + if (equal) { + self._len -= needle._len; + } + + return self; + } + + // Returns the memory address of the first byte of the first occurrence of + // `needle` in `self`, or the first byte after `self` if not found. + function findPtr( + uint256 selflen, + uint256 selfptr, + uint256 needlelen, + uint256 needleptr + ) private pure returns (uint256) { + uint256 ptr = selfptr; + uint256 idx; + + if (needlelen <= selflen) { + if (needlelen <= 32) { + bytes32 mask; + if (needlelen > 0) { + mask = bytes32(~(2**(8 * (32 - needlelen)) - 1)); + } + + bytes32 needledata; + assembly { + needledata := and(mload(needleptr), mask) + } + + uint256 end = selfptr + selflen - needlelen; + bytes32 ptrdata; + assembly { + ptrdata := and(mload(ptr), mask) + } + + while (ptrdata != needledata) { + if (ptr >= end) return selfptr + selflen; + ptr++; + assembly { + ptrdata := and(mload(ptr), mask) + } + } + return ptr; + } else { + // For long needles, use hashing + bytes32 hash; + assembly { + hash := keccak256(needleptr, needlelen) + } + + for (idx = 0; idx <= selflen - needlelen; idx++) { + bytes32 testHash; + assembly { + testHash := keccak256(ptr, needlelen) + } + if (hash == testHash) return ptr; + ptr += 1; + } + } + } + return selfptr + selflen; + } + + // Returns the memory address of the first byte after the last occurrence of + // `needle` in `self`, or the address of `self` if not found. + function rfindPtr( + uint256 selflen, + uint256 selfptr, + uint256 needlelen, + uint256 needleptr + ) private pure returns (uint256) { + uint256 ptr; + + if (needlelen <= selflen) { + if (needlelen <= 32) { + bytes32 mask; + if (needlelen > 0) { + mask = bytes32(~(2**(8 * (32 - needlelen)) - 1)); + } + + bytes32 needledata; + assembly { + needledata := and(mload(needleptr), mask) + } + + ptr = selfptr + selflen - needlelen; + bytes32 ptrdata; + assembly { + ptrdata := and(mload(ptr), mask) + } + + while (ptrdata != needledata) { + if (ptr <= selfptr) return selfptr; + ptr--; + assembly { + ptrdata := and(mload(ptr), mask) + } + } + return ptr + needlelen; + } else { + // For long needles, use hashing + bytes32 hash; + assembly { + hash := keccak256(needleptr, needlelen) + } + ptr = selfptr + (selflen - needlelen); + while (ptr >= selfptr) { + bytes32 testHash; + assembly { + testHash := keccak256(ptr, needlelen) + } + if (hash == testHash) return ptr + needlelen; + ptr -= 1; + } + } + } + return selfptr; + } + + /* + * @dev Modifies `self` to contain everything from the first occurrence of + * `needle` to the end of the slice. `self` is set to the empty slice + * if `needle` is not found. + * @param self The slice to search and modify. + * @param needle The text to search for. + * @return `self`. + */ + function find(slice memory self, slice memory needle) + internal + pure + returns (slice memory) + { + uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); + self._len -= ptr - self._ptr; + self._ptr = ptr; + return self; + } + + /* + * @dev Modifies `self` to contain the part of the string from the start of + * `self` to the end of the first occurrence of `needle`. If `needle` + * is not found, `self` is set to the empty slice. + * @param self The slice to search and modify. + * @param needle The text to search for. + * @return `self`. + */ + function rfind(slice memory self, slice memory needle) + internal + pure + returns (slice memory) + { + uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); + self._len = ptr - self._ptr; + return self; + } + + /* + * @dev Splits the slice, setting `self` to everything after the first + * occurrence of `needle`, and `token` to everything before it. If + * `needle` does not occur in `self`, `self` is set to the empty slice, + * and `token` is set to the entirety of `self`. + * @param self The slice to split. + * @param needle The text to search for in `self`. + * @param token An output parameter to which the first token is written. + * @return `token`. + */ + function split( + slice memory self, + slice memory needle, + slice memory token + ) internal pure returns (slice memory) { + uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); + token._ptr = self._ptr; + token._len = ptr - self._ptr; + if (ptr == self._ptr + self._len) { + // Not found + self._len = 0; + } else { + self._len -= token._len + needle._len; + self._ptr = ptr + needle._len; + } + return token; + } + + /* + * @dev Splits the slice, setting `self` to everything after the first + * occurrence of `needle`, and returning everything before it. If + * `needle` does not occur in `self`, `self` is set to the empty slice, + * and the entirety of `self` is returned. + * @param self The slice to split. + * @param needle The text to search for in `self`. + * @return The part of `self` up to the first occurrence of `delim`. + */ + function split(slice memory self, slice memory needle) + internal + pure + returns (slice memory token) + { + split(self, needle, token); + } + + /* + * @dev Splits the slice, setting `self` to everything before the last + * occurrence of `needle`, and `token` to everything after it. If + * `needle` does not occur in `self`, `self` is set to the empty slice, + * and `token` is set to the entirety of `self`. + * @param self The slice to split. + * @param needle The text to search for in `self`. + * @param token An output parameter to which the first token is written. + * @return `token`. + */ + function rsplit( + slice memory self, + slice memory needle, + slice memory token + ) internal pure returns (slice memory) { + uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); + token._ptr = ptr; + token._len = self._len - (ptr - self._ptr); + if (ptr == self._ptr) { + // Not found + self._len = 0; + } else { + self._len -= token._len + needle._len; + } + return token; + } + + /* + * @dev Splits the slice, setting `self` to everything before the last + * occurrence of `needle`, and returning everything after it. If + * `needle` does not occur in `self`, `self` is set to the empty slice, + * and the entirety of `self` is returned. + * @param self The slice to split. + * @param needle The text to search for in `self`. + * @return The part of `self` after the last occurrence of `delim`. + */ + function rsplit(slice memory self, slice memory needle) + internal + pure + returns (slice memory token) + { + rsplit(self, needle, token); + } + + /* + * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. + * @param self The slice to search. + * @param needle The text to search for in `self`. + * @return The number of occurrences of `needle` found in `self`. + */ + function count(slice memory self, slice memory needle) + internal + pure + returns (uint256 cnt) + { + uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + + needle._len; + while (ptr <= self._ptr + self._len) { + cnt++; + ptr = + findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + + needle._len; + } + } + + /* + * @dev Returns True if `self` contains `needle`. + * @param self The slice to search. + * @param needle The text to search for in `self`. + * @return True if `needle` is found in `self`, false otherwise. + */ + function contains(slice memory self, slice memory needle) + internal + pure + returns (bool) + { + return + rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; + } + + /* + * @dev Returns a newly allocated string containing the concatenation of + * `self` and `other`. + * @param self The first slice to concatenate. + * @param other The second slice to concatenate. + * @return The concatenation of the two strings. + */ + function concat(slice memory self, slice memory other) + internal + pure + returns (string memory) + { + string memory ret = new string(self._len + other._len); + uint256 retptr; + assembly { + retptr := add(ret, 32) + } + memcpy(retptr, self._ptr, self._len); + memcpy(retptr + self._len, other._ptr, other._len); + return ret; + } + + /* + * @dev Joins an array of slices, using `self` as a delimiter, returning a + * newly allocated string. + * @param self The delimiter to use. + * @param parts A list of slices to join. + * @return A newly allocated string containing all the slices in `parts`, + * joined with `self`. + */ + function join(slice memory self, slice[] memory parts) + internal + pure + returns (string memory) + { + if (parts.length == 0) return ""; + + uint256 length = self._len * (parts.length - 1); + for (uint256 i = 0; i < parts.length; i++) length += parts[i]._len; + + string memory ret = new string(length); + uint256 retptr; + assembly { + retptr := add(ret, 32) + } + + for (uint256 i = 0; i < parts.length; i++) { + memcpy(retptr, parts[i]._ptr, parts[i]._len); + retptr += parts[i]._len; + if (i < parts.length - 1) { + memcpy(retptr, self._ptr, self._len); + retptr += self._len; + } + } + + return ret; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol new file mode 100644 index 0000000..3d9e757 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// NOTICE: pragma change from original (^0.6.11) +pragma solidity ^0.8.0; + +interface IBridge { + event MessageDelivered( + uint256 indexed messageIndex, + bytes32 indexed beforeInboxAcc, + address inbox, + uint8 kind, + address sender, + bytes32 messageDataHash + ); + + function deliverMessageToInbox( + uint8 kind, + address sender, + bytes32 messageDataHash + ) external payable returns (uint256); + + function executeCall( + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (bool success, bytes memory returnData); + + // These are only callable by the admin + function setInbox(address inbox, bool enabled) external; + + function setOutbox(address inbox, bool enabled) external; + + // View functions + + function activeOutbox() external view returns (address); + + function allowedInboxes(address inbox) external view returns (bool); + + function allowedOutboxes(address outbox) external view returns (bool); + + function inboxAccs(uint256 index) external view returns (bytes32); + + function messageCount() external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol new file mode 100644 index 0000000..b83fcec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// NOTICE: pragma change from original (^0.6.11) +pragma solidity ^0.8.0; + +import "./IBridge.sol"; +import "./IMessageProvider.sol"; + +interface IInbox is IMessageProvider { + function sendL2Message(bytes calldata messageData) external returns (uint256); + + function sendUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendL1FundedUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function sendL1FundedContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function createRetryableTicketNoRefundAliasRewrite( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable returns (uint256); + + function createRetryableTicket( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable returns (uint256); + + function depositEth(address destAddr) external payable returns (uint256); + + function depositEthRetryable( + address destAddr, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 maxGasPrice + ) external payable returns (uint256); + + function bridge() external view returns (IBridge); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol new file mode 100644 index 0000000..a29dc65 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// NOTICE: pragma change from original (^0.6.11) +pragma solidity ^0.8.0; + +interface IMessageProvider { + event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + + event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol new file mode 100644 index 0000000..dd3d544 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2019-2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// NOTICE: pragma change from original (^0.6.11) +pragma solidity ^0.8.0; + +library AddressAliasHelper { + uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); + + /// @notice Utility function that converts the msg.sender viewed in the L2 to the + /// address in the L1 that submitted a tx to the inbox + /// @param l1Address L2 address as viewed in msg.sender + /// @return l2Address the address in the L1 that triggered the tx to L2 + function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { + unchecked { + l2Address = address(uint160(l1Address) + offset); + } + } + + /// @notice Utility function that converts the msg.sender viewed in the L2 to the + /// address in the L1 that submitted a tx to the inbox + /// @param l2Address L2 address as viewed in msg.sender + /// @return l1Address the address in the L1 that triggered the tx to L2 + function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { + unchecked { + l1Address = address(uint160(l2Address) - offset); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol new file mode 100644 index 0000000..86a34b0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol @@ -0,0 +1,861 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ + +import "../interfaces/IAccount.sol"; +import "../interfaces/IPaymaster.sol"; +import "../interfaces/IEntryPoint.sol"; + +import "../utils/Exec.sol"; +import "./StakeManager.sol"; +import "./SenderCreator.sol"; +import "./Helpers.sol"; + +contract EntryPoint is IEntryPoint, StakeManager { + using UserOperationLib for UserOperation; + + SenderCreator private immutable senderCreator = new SenderCreator(); + + // internal value used during simulation: need to query aggregator. + address private constant SIMULATE_FIND_AGGREGATOR = address(1); + + // marker for inner call revert on out of gas + bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; + + uint256 private constant REVERT_REASON_MAX_LEN = 2048; + + /** + * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value + * in case of signature failure, instead of revert. + */ + uint256 public constant SIG_VALIDATION_FAILED = 1; + + /** + * compensate the caller's beneficiary address with the collected fees of all UserOperations. + * @param beneficiary the address to receive the fees + * @param amount amount to transfer. + */ + function _compensate(address payable beneficiary, uint256 amount) internal { + require(beneficiary != address(0), "AA90 invalid beneficiary"); + (bool success, ) = beneficiary.call{value: amount}(""); + require(success, "AA91 failed send to beneficiary"); + } + + /** + * execute a user op + * @param opIndex index into the opInfo array + * @param userOp the userOp to execute + * @param opInfo the opInfo filled by validatePrepayment for this userOp. + * @return collected the total amount this userOp paid. + */ + function _executeUserOp( + uint256 opIndex, + UserOperation calldata userOp, + UserOpInfo memory opInfo + ) private returns (uint256 collected) { + uint256 preGas = gasleft(); + bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); + + try this.innerHandleOp(userOp.callData, opInfo, context) returns ( + uint256 _actualGasCost + ) { + collected = _actualGasCost; + } catch { + bytes32 innerRevertCode; + assembly { + returndatacopy(0, 0, 32) + innerRevertCode := mload(0) + } + // handleOps was called with gas limit too low. abort entire bundle. + if (innerRevertCode == INNER_OUT_OF_GAS) { + //report paymaster, since if it is not deliberately caused by the bundler, + // it must be a revert caused by paymaster. + revert FailedOp(opIndex, "AA95 out of gas"); + } + + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + collected = _handlePostOp( + opIndex, + IPaymaster.PostOpMode.postOpReverted, + opInfo, + context, + actualGas + ); + } + } + + /** + * Execute a batch of UserOperations. + * no signature aggregator is used. + * if any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops the operations to execute + * @param beneficiary the address to receive the fees + */ + function handleOps( + UserOperation[] calldata ops, + address payable beneficiary + ) public { + uint256 opslen = ops.length; + UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); + + unchecked { + for (uint256 i = 0; i < opslen; i++) { + UserOpInfo memory opInfo = opInfos[i]; + ( + uint256 validationData, + uint256 pmValidationData + ) = _validatePrepayment(i, ops[i], opInfo); + _validateAccountAndPaymasterValidationData( + i, + validationData, + pmValidationData, + address(0) + ); + } + + uint256 collected = 0; + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(i, ops[i], opInfos[i]); + } + + _compensate(beneficiary, collected); + } //unchecked + } + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) + * @param beneficiary the address to receive the fees + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) public { + uint256 opasLen = opsPerAggregator.length; + uint256 totalOps = 0; + for (uint256 i = 0; i < opasLen; i++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[i]; + UserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + //address(1) is special marker of "signature error" + require( + address(aggregator) != address(1), + "AA96 invalid aggregator" + ); + + if (address(aggregator) != address(0)) { + // solhint-disable-next-line no-empty-blocks + try aggregator.validateSignatures(ops, opa.signature) {} catch { + revert SignatureValidationFailed(address(aggregator)); + } + } + + totalOps += ops.length; + } + + UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps); + + uint256 opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + UserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + uint256 opslen = ops.length; + for (uint256 i = 0; i < opslen; i++) { + UserOpInfo memory opInfo = opInfos[opIndex]; + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(opIndex, ops[i], opInfo); + _validateAccountAndPaymasterValidationData( + i, + validationData, + paymasterValidationData, + address(aggregator) + ); + opIndex++; + } + } + + uint256 collected = 0; + opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + emit SignatureAggregatorChanged(address(opa.aggregator)); + UserOperation[] calldata ops = opa.userOps; + uint256 opslen = ops.length; + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); + opIndex++; + } + } + emit SignatureAggregatorChanged(address(0)); + + _compensate(beneficiary, collected); + } + + /// @inheritdoc IEntryPoint + function simulateHandleOp( + UserOperation calldata op, + address target, + bytes calldata targetCallData + ) external override { + UserOpInfo memory opInfo; + _simulationOnlyValidations(op); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, op, opInfo); + ValidationData memory data = _intersectTimeRange( + validationData, + paymasterValidationData + ); + + numberMarker(); + uint256 paid = _executeUserOp(0, op, opInfo); + numberMarker(); + bool targetSuccess; + bytes memory targetResult; + if (target != address(0)) { + (targetSuccess, targetResult) = target.call(targetCallData); + } + revert ExecutionResult( + opInfo.preOpGas, + paid, + data.validAfter, + data.validUntil, + targetSuccess, + targetResult + ); + } + + // A memory copy of UserOp static fields only. + // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. + struct MemoryUserOp { + address sender; + uint256 nonce; + uint256 callGasLimit; + uint256 verificationGasLimit; + uint256 preVerificationGas; + address paymaster; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + } + + struct UserOpInfo { + MemoryUserOp mUserOp; + bytes32 userOpHash; + uint256 prefund; + uint256 contextOffset; + uint256 preOpGas; + } + + /** + * inner function to handle a UserOperation. + * Must be declared "external" to open a call context, but it can only be called by handleOps. + */ + function innerHandleOp( + bytes memory callData, + UserOpInfo memory opInfo, + bytes calldata context + ) external returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + require(msg.sender == address(this), "AA92 internal call only"); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + + uint256 callGasLimit = mUserOp.callGasLimit; + unchecked { + // handleOps was called with gas limit too low. abort entire bundle. + if ( + gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000 + ) { + assembly { + mstore(0, INNER_OUT_OF_GAS) + revert(0, 32) + } + } + } + + IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded; + if (callData.length > 0) { + bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); + if (!success) { + bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); + if (result.length > 0) { + emit UserOperationRevertReason( + opInfo.userOpHash, + mUserOp.sender, + mUserOp.nonce, + result + ); + } + mode = IPaymaster.PostOpMode.opReverted; + } + } + + unchecked { + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp) + return _handlePostOp(0, mode, opInfo, context, actualGas); + } + } + + /** + * generate a request Id - unique identifier for this request. + * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. + */ + function getUserOpHash(UserOperation calldata userOp) + public + view + returns (bytes32) + { + return + keccak256(abi.encode(userOp.hash(), address(this), block.chainid)); + } + + /** + * copy general fields from userOp into the memory opInfo structure. + */ + function _copyUserOpToMemory( + UserOperation calldata userOp, + MemoryUserOp memory mUserOp + ) internal pure { + mUserOp.sender = userOp.sender; + mUserOp.nonce = userOp.nonce; + mUserOp.callGasLimit = userOp.callGasLimit; + mUserOp.verificationGasLimit = userOp.verificationGasLimit; + mUserOp.preVerificationGas = userOp.preVerificationGas; + mUserOp.maxFeePerGas = userOp.maxFeePerGas; + mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; + bytes calldata paymasterAndData = userOp.paymasterAndData; + if (paymasterAndData.length > 0) { + require( + paymasterAndData.length >= 20, + "AA93 invalid paymasterAndData" + ); + mUserOp.paymaster = address(bytes20(paymasterAndData[:20])); + } else { + mUserOp.paymaster = address(0); + } + } + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. + * @param userOp the user operation to validate. + */ + function simulateValidation(UserOperation calldata userOp) external { + UserOpInfo memory outOpInfo; + + _simulationOnlyValidations(userOp); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, userOp, outOpInfo); + StakeInfo memory paymasterInfo = _getStakeInfo( + outOpInfo.mUserOp.paymaster + ); + StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender); + StakeInfo memory factoryInfo; + { + bytes calldata initCode = userOp.initCode; + address factory = initCode.length >= 20 + ? address(bytes20(initCode[0:20])) + : address(0); + factoryInfo = _getStakeInfo(factory); + } + + ValidationData memory data = _intersectTimeRange( + validationData, + paymasterValidationData + ); + address aggregator = data.aggregator; + bool sigFailed = aggregator == address(1); + ReturnInfo memory returnInfo = ReturnInfo( + outOpInfo.preOpGas, + outOpInfo.prefund, + sigFailed, + data.validAfter, + data.validUntil, + getMemoryBytesFromOffset(outOpInfo.contextOffset) + ); + + if (aggregator != address(0) && aggregator != address(1)) { + AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo( + aggregator, + _getStakeInfo(aggregator) + ); + revert ValidationResultWithAggregation( + returnInfo, + senderInfo, + factoryInfo, + paymasterInfo, + aggregatorInfo + ); + } + revert ValidationResult( + returnInfo, + senderInfo, + factoryInfo, + paymasterInfo + ); + } + + function _getRequiredPrefund(MemoryUserOp memory mUserOp) + internal + pure + returns (uint256 requiredPrefund) + { + unchecked { + //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call. + // our security model might call postOp eventually twice + uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1; + uint256 requiredGas = mUserOp.callGasLimit + + mUserOp.verificationGasLimit * + mul + + mUserOp.preVerificationGas; + + requiredPrefund = requiredGas * mUserOp.maxFeePerGas; + } + } + + // create the sender's contract if needed. + function _createSenderIfNeeded( + uint256 opIndex, + UserOpInfo memory opInfo, + bytes calldata initCode + ) internal { + if (initCode.length != 0) { + address sender = opInfo.mUserOp.sender; + if (sender.code.length != 0) + revert FailedOp(opIndex, "AA10 sender already constructed"); + address sender1 = senderCreator.createSender{ + gas: opInfo.mUserOp.verificationGasLimit + }(initCode); + if (sender1 == address(0)) + revert FailedOp(opIndex, "AA13 initCode failed or OOG"); + if (sender1 != sender) + revert FailedOp(opIndex, "AA14 initCode must return sender"); + if (sender1.code.length == 0) + revert FailedOp(opIndex, "AA15 initCode must create sender"); + address factory = address(bytes20(initCode[0:20])); + emit AccountDeployed( + opInfo.userOpHash, + sender, + factory, + opInfo.mUserOp.paymaster + ); + } + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * this method always revert, and returns the address in SenderAddressResult error + * @param initCode the constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes calldata initCode) public { + revert SenderAddressResult(senderCreator.createSender(initCode)); + } + + function _simulationOnlyValidations(UserOperation calldata userOp) + internal + view + { + // solhint-disable-next-line no-empty-blocks + try + this._validateSenderAndPaymaster( + userOp.initCode, + userOp.sender, + userOp.paymasterAndData + ) + {} catch Error(string memory revertReason) { + if (bytes(revertReason).length != 0) { + revert FailedOp(0, revertReason); + } + } + } + + /** + * Called only during simulation. + * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution. + */ + function _validateSenderAndPaymaster( + bytes calldata initCode, + address sender, + bytes calldata paymasterAndData + ) external view { + if (initCode.length == 0 && sender.code.length == 0) { + // it would revert anyway. but give a meaningful message + revert("AA20 account not deployed"); + } + if (paymasterAndData.length >= 20) { + address paymaster = address(bytes20(paymasterAndData[0:20])); + if (paymaster.code.length == 0) { + // it would revert anyway. but give a meaningful message + revert("AA30 paymaster not deployed"); + } + } + // always revert + revert(""); + } + + /** + * call account.validateUserOp. + * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. + * decrement account's deposit if needed + */ + function _validateAccountPrepayment( + uint256 opIndex, + UserOperation calldata op, + UserOpInfo memory opInfo, + uint256 requiredPrefund + ) + internal + returns ( + uint256 gasUsedByValidateAccountPrepayment, + uint256 validationData + ) + { + unchecked { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + address sender = mUserOp.sender; + _createSenderIfNeeded(opIndex, opInfo, op.initCode); + address paymaster = mUserOp.paymaster; + numberMarker(); + uint256 missingAccountFunds = 0; + if (paymaster == address(0)) { + uint256 bal = balanceOf(sender); + missingAccountFunds = bal > requiredPrefund + ? 0 + : requiredPrefund - bal; + } + try + IAccount(sender).validateUserOp{ + gas: mUserOp.verificationGasLimit + }(op, opInfo.userOpHash, missingAccountFunds) + returns (uint256 _validationData) { + validationData = _validationData; + } catch Error(string memory revertReason) { + revert FailedOp( + opIndex, + string.concat("AA23 reverted: ", revertReason) + ); + } catch { + revert FailedOp(opIndex, "AA23 reverted (or OOG)"); + } + if (paymaster == address(0)) { + DepositInfo storage senderInfo = deposits[sender]; + uint256 deposit = senderInfo.deposit; + if (requiredPrefund > deposit) { + revert FailedOp(opIndex, "AA21 didn't pay prefund"); + } + senderInfo.deposit = uint112(deposit - requiredPrefund); + } + gasUsedByValidateAccountPrepayment = preGas - gasleft(); + } + } + + /** + * In case the request has a paymaster: + * Validate paymaster has enough deposit. + * Call paymaster.validatePaymasterUserOp. + * Revert with proper FailedOp in case paymaster reverts. + * Decrement paymaster's deposit + */ + function _validatePaymasterPrepayment( + uint256 opIndex, + UserOperation calldata op, + UserOpInfo memory opInfo, + uint256 requiredPreFund, + uint256 gasUsedByValidateAccountPrepayment + ) internal returns (bytes memory context, uint256 validationData) { + unchecked { + MemoryUserOp memory mUserOp = opInfo.mUserOp; + uint256 verificationGasLimit = mUserOp.verificationGasLimit; + require( + verificationGasLimit > gasUsedByValidateAccountPrepayment, + "AA41 too little verificationGas" + ); + uint256 gas = verificationGasLimit - + gasUsedByValidateAccountPrepayment; + + address paymaster = mUserOp.paymaster; + DepositInfo storage paymasterInfo = deposits[paymaster]; + uint256 deposit = paymasterInfo.deposit; + if (deposit < requiredPreFund) { + revert FailedOp(opIndex, "AA31 paymaster deposit too low"); + } + paymasterInfo.deposit = uint112(deposit - requiredPreFund); + try + IPaymaster(paymaster).validatePaymasterUserOp{gas: gas}( + op, + opInfo.userOpHash, + requiredPreFund + ) + returns (bytes memory _context, uint256 _validationData) { + context = _context; + validationData = _validationData; + } catch Error(string memory revertReason) { + revert FailedOp( + opIndex, + string.concat("AA33 reverted: ", revertReason) + ); + } catch { + revert FailedOp(opIndex, "AA33 reverted (or OOG)"); + } + } + } + + /** + * revert if either account validationData or paymaster validationData is expired + */ + function _validateAccountAndPaymasterValidationData( + uint256 opIndex, + uint256 validationData, + uint256 paymasterValidationData, + address expectedAggregator + ) internal view { + (address aggregator, bool outOfTimeRange) = _getValidationData( + validationData + ); + if (expectedAggregator != aggregator) { + revert FailedOp(opIndex, "AA24 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA22 expired or not due"); + } + //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address. + // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation) + address pmAggregator; + (pmAggregator, outOfTimeRange) = _getValidationData( + paymasterValidationData + ); + if (pmAggregator != address(0)) { + revert FailedOp(opIndex, "AA34 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA32 paymaster expired or not due"); + } + } + + function _getValidationData(uint256 validationData) + internal + view + returns (address aggregator, bool outOfTimeRange) + { + if (validationData == 0) { + return (address(0), false); + } + ValidationData memory data = _parseValidationData(validationData); + // solhint-disable-next-line not-rely-on-time + outOfTimeRange = + block.timestamp > data.validUntil || + block.timestamp < data.validAfter; + aggregator = data.aggregator; + } + + /** + * validate account and paymaster (if defined). + * also make sure total validation doesn't exceed verificationGasLimit + * this method is called off-chain (simulateValidation()) and on-chain (from handleOps) + * @param opIndex the index of this userOp into the "opInfos" array + * @param userOp the userOp to validate + */ + function _validatePrepayment( + uint256 opIndex, + UserOperation calldata userOp, + UserOpInfo memory outOpInfo + ) + private + returns (uint256 validationData, uint256 paymasterValidationData) + { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = outOpInfo.mUserOp; + _copyUserOpToMemory(userOp, mUserOp); + outOpInfo.userOpHash = getUserOpHash(userOp); + + // validate all numeric values in userOp are well below 128 bit, so they can safely be added + // and multiplied without causing overflow + uint256 maxGasValues = mUserOp.preVerificationGas | + mUserOp.verificationGasLimit | + mUserOp.callGasLimit | + userOp.maxFeePerGas | + userOp.maxPriorityFeePerGas; + require(maxGasValues <= type(uint120).max, "AA94 gas values overflow"); + + uint256 gasUsedByValidateAccountPrepayment; + uint256 requiredPreFund = _getRequiredPrefund(mUserOp); + ( + gasUsedByValidateAccountPrepayment, + validationData + ) = _validateAccountPrepayment( + opIndex, + userOp, + outOpInfo, + requiredPreFund + ); + //a "marker" where account opcode validation is done and paymaster opcode validation is about to start + // (used only by off-chain simulateValidation) + numberMarker(); + + bytes memory context; + if (mUserOp.paymaster != address(0)) { + (context, paymasterValidationData) = _validatePaymasterPrepayment( + opIndex, + userOp, + outOpInfo, + requiredPreFund, + gasUsedByValidateAccountPrepayment + ); + } + unchecked { + uint256 gasUsed = preGas - gasleft(); + + if (userOp.verificationGasLimit < gasUsed) { + revert FailedOp(opIndex, "AA40 over verificationGasLimit"); + } + outOpInfo.prefund = requiredPreFund; + outOpInfo.contextOffset = getOffsetOfMemoryBytes(context); + outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas; + } + } + + /** + * process post-operation. + * called just after the callData is executed. + * if a paymaster is defined and its validation returned a non-empty context, its postOp is called. + * the excess amount is refunded to the account (or paymaster - if it was used in the request) + * @param opIndex index in the batch + * @param mode - whether is called from innerHandleOp, or outside (postOpReverted) + * @param opInfo userOp fields and info collected during validation + * @param context the context returned in validatePaymasterUserOp + * @param actualGas the gas used so far by this user operation + */ + function _handlePostOp( + uint256 opIndex, + IPaymaster.PostOpMode mode, + UserOpInfo memory opInfo, + bytes memory context, + uint256 actualGas + ) private returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + unchecked { + address refundAddress; + MemoryUserOp memory mUserOp = opInfo.mUserOp; + uint256 gasPrice = getUserOpGasPrice(mUserOp); + + address paymaster = mUserOp.paymaster; + if (paymaster == address(0)) { + refundAddress = mUserOp.sender; + } else { + refundAddress = paymaster; + if (context.length > 0) { + actualGasCost = actualGas * gasPrice; + if (mode != IPaymaster.PostOpMode.postOpReverted) { + IPaymaster(paymaster).postOp{ + gas: mUserOp.verificationGasLimit + }(mode, context, actualGasCost); + } else { + // solhint-disable-next-line no-empty-blocks + try + IPaymaster(paymaster).postOp{ + gas: mUserOp.verificationGasLimit + }(mode, context, actualGasCost) + {} catch Error(string memory reason) { + revert FailedOp( + opIndex, + string.concat("AA50 postOp reverted: ", reason) + ); + } catch { + revert FailedOp(opIndex, "AA50 postOp revert"); + } + } + } + } + actualGas += preGas - gasleft(); + actualGasCost = actualGas * gasPrice; + if (opInfo.prefund < actualGasCost) { + revert FailedOp(opIndex, "AA51 prefund below actualGasCost"); + } + uint256 refund = opInfo.prefund - actualGasCost; + _incrementDeposit(refundAddress, refund); + bool success = mode == IPaymaster.PostOpMode.opSucceeded; + emit UserOperationEvent( + opInfo.userOpHash, + mUserOp.sender, + mUserOp.paymaster, + mUserOp.nonce, + success, + actualGasCost, + actualGas + ); + } // unchecked + } + + /** + * the gas price this UserOp agrees to pay. + * relayer/block builder might submit the TX with higher priorityFee, but the user should not + */ + function getUserOpGasPrice(MemoryUserOp memory mUserOp) + internal + view + returns (uint256) + { + unchecked { + uint256 maxFeePerGas = mUserOp.maxFeePerGas; + uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; + if (maxFeePerGas == maxPriorityFeePerGas) { + //legacy mode (for networks that don't support basefee opcode) + return maxFeePerGas; + } + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function getOffsetOfMemoryBytes(bytes memory data) + internal + pure + returns (uint256 offset) + { + assembly { + offset := data + } + } + + function getMemoryBytesFromOffset(uint256 offset) + internal + pure + returns (bytes memory data) + { + assembly { + data := offset + } + } + + //place the NUMBER opcode in the code. + // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the + // account and paymaster. + function numberMarker() internal view { + assembly { + mstore(0, number()) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol new file mode 100644 index 0000000..71a6dc3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/** + * returned data from validateUserOp. + * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` + * @param aggregator - address(0) - the account validated the signature by itself. + * address(1) - the account failed to validate the signature. + * otherwise - this is an address of a signature aggregator that must be used to validate the signature. + * @param validAfter - this UserOp is valid only after this timestamp. + * @param validaUntil - this UserOp is valid only up to this timestamp. + */ +struct ValidationData { + address aggregator; + uint48 validAfter; + uint48 validUntil; +} + +//extract sigFailed, validAfter, validUntil. +// also convert zero validUntil to type(uint48).max +function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { + address aggregator = address(uint160(validationData)); + uint48 validUntil = uint48(validationData >> 160); + if (validUntil == 0) { + validUntil = type(uint48).max; + } + uint48 validAfter = uint48(validationData >> (48 + 160)); + return ValidationData(aggregator, validAfter, validUntil); +} + +// intersect account and paymaster ranges. +function _intersectTimeRange( + uint256 validationData, + uint256 paymasterValidationData +) pure returns (ValidationData memory) { + ValidationData memory accountValidationData = _parseValidationData(validationData); + ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); + address aggregator = accountValidationData.aggregator; + if (aggregator == address(0)) { + aggregator = pmValidationData.aggregator; + } + uint48 validAfter = accountValidationData.validAfter; + uint48 validUntil = accountValidationData.validUntil; + uint48 pmValidAfter = pmValidationData.validAfter; + uint48 pmValidUntil = pmValidationData.validUntil; + + if (validAfter < pmValidAfter) validAfter = pmValidAfter; + if (validUntil > pmValidUntil) validUntil = pmValidUntil; + return ValidationData(aggregator, validAfter, validUntil); +} + +/** + * helper to pack the return value for validateUserOp + * @param data - the ValidationData to pack + */ +function _packValidationData(ValidationData memory data) pure returns (uint256) { + return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); +} + +/** + * helper to pack the return value for validateUserOp, when not using an aggregator + * @param sigFailed - true for signature failure, false for success + * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) + * @param validAfter first timestamp this UserOperation is valid + */ +function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { + return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol new file mode 100644 index 0000000..36fad7b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/** + * helper contract for EntryPoint, to call userOp.initCode from a "neutral" address, + * which is explicitly not the entryPoint itself. + */ +contract SenderCreator { + + /** + * call the "initCode" factory to create and return the sender account address + * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata + * @return sender the returned address of the created account, or zero address on failure. + */ + function createSender(bytes calldata initCode) external returns (address sender) { + address factory = address(bytes20(initCode[0 : 20])); + bytes memory initCallData = initCode[20 :]; + bool success; + /* solhint-disable no-inline-assembly */ + assembly { + success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32) + sender := mload(0) + } + if (!success) { + sender = address(0); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol new file mode 100644 index 0000000..e5ca2b9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.12; + +import "../interfaces/IStakeManager.sol"; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable not-rely-on-time */ +/** + * manage deposits and stakes. + * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) + * stake is value locked for at least "unstakeDelay" by a paymaster. + */ +abstract contract StakeManager is IStakeManager { + + /// maps paymaster to their deposits and stakes + mapping(address => DepositInfo) public deposits; + + /// @inheritdoc IStakeManager + function getDepositInfo(address account) public view returns (DepositInfo memory info) { + return deposits[account]; + } + + // internal method to return just the stake info + function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) { + DepositInfo storage depositInfo = deposits[addr]; + info.stake = depositInfo.stake; + info.unstakeDelaySec = depositInfo.unstakeDelaySec; + } + + /// return the deposit (for gas payment) of the account + function balanceOf(address account) public view returns (uint256) { + return deposits[account].deposit; + } + + receive() external payable { + depositTo(msg.sender); + } + + function _incrementDeposit(address account, uint256 amount) internal { + DepositInfo storage info = deposits[account]; + uint256 newAmount = info.deposit + amount; + require(newAmount <= type(uint112).max, "deposit overflow"); + info.deposit = uint112(newAmount); + } + + /** + * add to the deposit of the given account + */ + function depositTo(address account) public payable { + _incrementDeposit(account, msg.value); + DepositInfo storage info = deposits[account]; + emit Deposited(account, info.deposit); + } + + /** + * add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 unstakeDelaySec) public payable { + DepositInfo storage info = deposits[msg.sender]; + require(unstakeDelaySec > 0, "must specify unstake delay"); + require(unstakeDelaySec >= info.unstakeDelaySec, "cannot decrease unstake time"); + uint256 stake = info.stake + msg.value; + require(stake > 0, "no stake specified"); + require(stake <= type(uint112).max, "stake overflow"); + deposits[msg.sender] = DepositInfo( + info.deposit, + true, + uint112(stake), + unstakeDelaySec, + 0 + ); + emit StakeLocked(msg.sender, stake, unstakeDelaySec); + } + + /** + * attempt to unlock the stake. + * the value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external { + DepositInfo storage info = deposits[msg.sender]; + require(info.unstakeDelaySec != 0, "not staked"); + require(info.staked, "already unstaking"); + uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; + info.withdrawTime = withdrawTime; + info.staked = false; + emit StakeUnlocked(msg.sender, withdrawTime); + } + + + /** + * withdraw from the (unlocked) stake. + * must first call unlockStake and wait for the unstakeDelay to pass + * @param withdrawAddress the address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external { + DepositInfo storage info = deposits[msg.sender]; + uint256 stake = info.stake; + require(stake > 0, "No stake to withdraw"); + require(info.withdrawTime > 0, "must call unlockStake() first"); + require(info.withdrawTime <= block.timestamp, "Stake withdrawal is not due"); + info.unstakeDelaySec = 0; + info.withdrawTime = 0; + info.stake = 0; + emit StakeWithdrawn(msg.sender, withdrawAddress, stake); + (bool success,) = withdrawAddress.call{value : stake}(""); + require(success, "failed to withdraw stake"); + } + + /** + * withdraw from the deposit. + * @param withdrawAddress the address to send withdrawn value. + * @param withdrawAmount the amount to withdraw. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external { + DepositInfo storage info = deposits[msg.sender]; + require(withdrawAmount <= info.deposit, "Withdraw amount too large"); + info.deposit = uint112(info.deposit - withdrawAmount); + emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); + (bool success,) = withdrawAddress.call{value : withdrawAmount}(""); + require(success, "failed to withdraw"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol new file mode 100644 index 0000000..1600de3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +interface IAccount { + + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp the operation that is about to be executed. + * @param userOpHash hash of the user's request data. can be used as the basis for signature. + * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. + * The excess is left as a deposit in the entrypoint, for future calls. + * can be withdrawn anytime using "entryPoint.withdrawTo()" + * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. + * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) + external returns (uint256 validationData); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol new file mode 100644 index 0000000..086c6f3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +/** + * Aggregated Signatures validator. + */ +interface IAggregator { + + /** + * validate aggregated signature. + * revert if the aggregated signature does not match the given list of operations. + */ + function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; + + /** + * validate signature of a single userOp + * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation + * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. + * @param userOp the userOperation received from the user. + * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. + * (usually empty, unless account and aggregator support some kind of "multisig" + */ + function validateUserOpSignature(UserOperation calldata userOp) + external view returns (bytes memory sigForUserOp); + + /** + * aggregate multiple signatures into a single value. + * This method is called off-chain to calculate the signature to pass with handleOps() + * bundler MAY use optimized custom code perform this aggregation + * @param userOps array of UserOperations to collect the signatures from. + * @return aggregatedSignature the aggregated signature + */ + function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol new file mode 100644 index 0000000..22bb1b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol @@ -0,0 +1,197 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ +/* solhint-disable reason-string */ + +import "./UserOperation.sol"; +import "./IStakeManager.sol"; +import "./IAggregator.sol"; + +interface IEntryPoint is IStakeManager { + + /*** + * An event emitted after each successful request + * @param userOpHash - unique identifier for the request (hash its entire content, except signature). + * @param sender - the account that generates this request. + * @param paymaster - if non-null, the paymaster that pays for this request. + * @param nonce - the nonce value from the request. + * @param success - true if the sender transaction succeeded, false if reverted. + * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. + * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). + */ + event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); + + /** + * account "sender" was deployed. + * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. + * @param sender the account that is deployed + * @param factory the factory used to deploy this account (in the initCode) + * @param paymaster the paymaster used by this UserOp + */ + event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); + + /** + * An event emitted if the UserOperation "callData" reverted with non-zero length + * @param userOpHash the request unique identifier. + * @param sender the sender of this request + * @param nonce the nonce used in the request + * @param revertReason - the return bytes from the (reverted) call to "callData". + */ + event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); + + /** + * signature aggregator used by the following UserOperationEvents within this bundle. + */ + event SignatureAggregatorChanged(address indexed aggregator); + + /** + * a custom revert error of handleOps, to identify the offending op. + * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. + * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) + * @param reason - revert reason + * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, + * so a failure can be attributed to the correct entity. + * Should be caught in off-chain handleOps simulation and not happen on-chain. + * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * error case when a signature aggregator fails to verify the aggregated signature it had created. + */ + error SignatureValidationFailed(address aggregator); + + /** + * Successful result from simulateValidation. + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + */ + error ValidationResult(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); + + /** + * Successful result from simulateValidation, if the account returns a signature aggregator + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) + * bundler MUST use it to verify the signature, or reject the UserOperation + */ + error ValidationResultWithAggregation(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, + AggregatorStakeInfo aggregatorInfo); + + /** + * return value of getSenderAddress + */ + error SenderAddressResult(address sender); + + /** + * return value of simulateHandleOp + */ + error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); + + //UserOps handled, per aggregator + struct UserOpsPerAggregator { + UserOperation[] userOps; + + // aggregator address + IAggregator aggregator; + // aggregated signature + bytes signature; + } + + /** + * Execute a batch of UserOperation. + * no signature aggregator is used. + * if any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops the operations to execute + * @param beneficiary the address to receive the fees + */ + function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) + * @param beneficiary the address to receive the fees + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; + + /** + * generate a request Id - unique identifier for this request. + * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. + */ + function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32); + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. + * @param userOp the user operation to validate. + */ + function simulateValidation(UserOperation calldata userOp) external; + + /** + * gas and return values during simulation + * @param preOpGas the gas used for validation (including preValidationGas) + * @param prefund the required prefund for this operation + * @param sigFailed validateUserOp's (or paymaster's) signature check failed + * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) + * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) + * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) + */ + struct ReturnInfo { + uint256 preOpGas; + uint256 prefund; + bool sigFailed; + uint48 validAfter; + uint48 validUntil; + bytes paymasterContext; + } + + /** + * returned aggregated signature info. + * the aggregator returned by the account, and its current stake. + */ + struct AggregatorStakeInfo { + address aggregator; + StakeInfo stakeInfo; + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * this method always revert, and returns the address in SenderAddressResult error + * @param initCode the constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes memory initCode) external; + + + /** + * simulate full execution of a UserOperation (including both validation and target execution) + * this method will always revert with "ExecutionResult". + * it performs full validation of the UserOperation, but ignores signature error. + * an optional target address is called after the userop succeeds, and its value is returned + * (before the entire call is reverted) + * Note that in order to collect the the success/failure of the target call, it must be executed + * with trace enabled to track the emitted events. + * @param op the UserOperation to simulate + * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult + * are set to the return from that call. + * @param targetCallData callData to pass to target address + */ + function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol new file mode 100644 index 0000000..af50367 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +/** + * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. + * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. + */ +interface IPaymaster { + + enum PostOpMode { + opSucceeded, // user op succeeded + opReverted, // user op reverted. still has to pay for gas. + postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. + } + + /** + * payment validation: check if paymaster agrees to pay. + * Must verify sender is the entryPoint. + * Revert to reject this request. + * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) + * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. + * @param userOp the user operation + * @param userOpHash hash of the user's request data. + * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) + * @return context value to send to a postOp + * zero length to signify postOp is not required. + * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + external returns (bytes memory context, uint256 validationData); + + /** + * post-operation handler. + * Must verify sender is the entryPoint + * @param mode enum with the following options: + * opSucceeded - user operation succeeded. + * opReverted - user op reverted. still has to pay for gas. + * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. + * Now this is the 2nd call, after user's op was deliberately reverted. + * @param context - the context value returned by validatePaymasterUserOp + * @param actualGasCost - actual gas used so far (without this postOp call). + */ + function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol new file mode 100644 index 0000000..c19c1ba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.12; + +/** + * manage deposits and stakes. + * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) + * stake is value locked for at least "unstakeDelay" by the staked entity. + */ +interface IStakeManager { + + event Deposited( + address indexed account, + uint256 totalDeposit + ); + + event Withdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /// Emitted when stake or unstake delay are modified + event StakeLocked( + address indexed account, + uint256 totalStaked, + uint256 unstakeDelaySec + ); + + /// Emitted once a stake is scheduled for withdrawal + event StakeUnlocked( + address indexed account, + uint256 withdrawTime + ); + + event StakeWithdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /** + * @param deposit the entity's deposit + * @param staked true if this entity is staked. + * @param stake actual amount of ether staked for this entity. + * @param unstakeDelaySec minimum delay to withdraw the stake. + * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked + * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) + * and the rest fit into a 2nd cell. + * 112 bit allows for 10^15 eth + * 48 bit for full timestamp + * 32 bit allows 150 years for unstake delay + */ + struct DepositInfo { + uint112 deposit; + bool staked; + uint112 stake; + uint32 unstakeDelaySec; + uint48 withdrawTime; + } + + //API struct used by getStakeInfo and simulateValidation + struct StakeInfo { + uint256 stake; + uint256 unstakeDelaySec; + } + + /// @return info - full deposit information of given account + function getDepositInfo(address account) external view returns (DepositInfo memory info); + + /// @return the deposit (for gas payment) of the account + function balanceOf(address account) external view returns (uint256); + + /** + * add to the deposit of the given account + */ + function depositTo(address account) external payable; + + /** + * add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 _unstakeDelaySec) external payable; + + /** + * attempt to unlock the stake. + * the value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external; + + /** + * withdraw from the (unlocked) stake. + * must first call unlockStake and wait for the unstakeDelay to pass + * @param withdrawAddress the address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external; + + /** + * withdraw from the deposit. + * @param withdrawAddress the address to send withdrawn value. + * @param withdrawAmount the amount to withdraw. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol new file mode 100644 index 0000000..dfff427 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable no-inline-assembly */ + + /** + * User Operation struct + * @param sender the sender account of this request. + * @param nonce unique value the sender uses to verify it is not a replay. + * @param initCode if set, the account contract will be created by this constructor/ + * @param callData the method call to execute on this account. + * @param callGasLimit the gas limit passed to the callData method call. + * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. + * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. + * @param maxFeePerGas same as EIP-1559 gas parameter. + * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. + * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. + * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. + */ + struct UserOperation { + + address sender; + uint256 nonce; + bytes initCode; + bytes callData; + uint256 callGasLimit; + uint256 verificationGasLimit; + uint256 preVerificationGas; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + bytes paymasterAndData; + bytes signature; + } + +/** + * Utility functions helpful when working with UserOperation structs. + */ +library UserOperationLib { + + function getSender(UserOperation calldata userOp) internal pure returns (address) { + address data; + //read sender from userOp, which is first userOp member (saves 800 gas...) + assembly {data := calldataload(userOp)} + return address(uint160(data)); + } + + //relayer/block builder might submit the TX with higher priorityFee, but the user should not + // pay above what he signed for. + function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { + unchecked { + uint256 maxFeePerGas = userOp.maxFeePerGas; + uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; + if (maxFeePerGas == maxPriorityFeePerGas) { + //legacy mode (for networks that don't support basefee opcode) + return maxFeePerGas; + } + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { + //lighter signature scheme. must match UserOp.ts#packUserOp + bytes calldata sig = userOp.signature; + // copy directly the userOp from calldata up to (but not including) the signature. + // this encoding depends on the ABI encoding of calldata, but is much lighter to copy + // than referencing each field separately. + assembly { + let ofs := userOp + let len := sub(sub(sig.offset, ofs), 32) + ret := mload(0x40) + mstore(0x40, add(ret, add(len, 32))) + mstore(ret, len) + calldatacopy(add(ret, 32), ofs, len) + } + } + + function hash(UserOperation calldata userOp) internal pure returns (bytes32) { + return keccak256(pack(userOp)); + } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol new file mode 100644 index 0000000..69d653d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.5 <0.9.0; + +// solhint-disable no-inline-assembly + +/** + * Utility functions helpful when making different kinds of contract calls in Solidity. + */ +library Exec { + + function call( + address to, + uint256 value, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly { + success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) + } + } + + function staticcall( + address to, + bytes memory data, + uint256 txGas + ) internal view returns (bool success) { + assembly { + success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + function delegateCall( + address to, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly { + success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + // get returned data from last call or calldelegate + function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) { + assembly { + let len := returndatasize() + if gt(len, maxLen) { + len := maxLen + } + let ptr := mload(0x40) + mstore(0x40, add(ptr, add(len, 0x20))) + mstore(ptr, len) + returndatacopy(add(ptr, 0x20), 0, len) + returnData := ptr + } + } + + // revert with explicit byte array (probably reverted info from call) + function revertWithData(bytes memory returnData) internal pure { + assembly { + revert(add(returnData, 32), mload(returnData)) + } + } + + function callAndRevert(address to, bytes memory data, uint256 maxLen) internal { + bool success = call(to,0,data,gasleft()); + if (!success) { + revertWithData(getReturnData(maxLen)); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol new file mode 100644 index 0000000..851ac0c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {StdStorage} from "./StdStorage.sol"; +import {Vm, VmSafe} from "./Vm.sol"; + +abstract contract CommonBase { + // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. + address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + // console.sol and console2.sol work by executing a staticcall to this address. + address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; + // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. + address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. + address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); + // Address of the test contract, deployed by the DEFAULT_SENDER. + address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; + // Deterministic deployment address of the Multicall3 contract. + address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; + // The order of the secp256k1 curve. + uint256 internal constant SECP256K1_ORDER = + 115792089237316195423570985008687907852837564279074904382605163141518161494337; + + uint256 internal constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + Vm internal constant vm = Vm(VM_ADDRESS); + StdStorage internal stdstore; +} + +abstract contract TestBase is CommonBase {} + +abstract contract ScriptBase is CommonBase { + VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol new file mode 100644 index 0000000..94e75f6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +// 💬 ABOUT +// Forge Std's default Script. + +// 🧩 MODULES +import {console} from "./console.sol"; +import {console2} from "./console2.sol"; +import {safeconsole} from "./safeconsole.sol"; +import {StdChains} from "./StdChains.sol"; +import {StdCheatsSafe} from "./StdCheats.sol"; +import {stdJson} from "./StdJson.sol"; +import {stdMath} from "./StdMath.sol"; +import {StdStorage, stdStorageSafe} from "./StdStorage.sol"; +import {StdStyle} from "./StdStyle.sol"; +import {StdUtils} from "./StdUtils.sol"; +import {VmSafe} from "./Vm.sol"; + +// 📦 BOILERPLATE +import {ScriptBase} from "./Base.sol"; + +// ⭐️ SCRIPT +abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils { + // Note: IS_SCRIPT() must return true. + bool public IS_SCRIPT = true; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol new file mode 100644 index 0000000..857ecd5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol @@ -0,0 +1,669 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +import {Vm} from "./Vm.sol"; + +abstract contract StdAssertions { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + event log(string); + event logs(bytes); + + event log_address(address); + event log_bytes32(bytes32); + event log_int(int256); + event log_uint(uint256); + event log_bytes(bytes); + event log_string(string); + + event log_named_address(string key, address val); + event log_named_bytes32(string key, bytes32 val); + event log_named_decimal_int(string key, int256 val, uint256 decimals); + event log_named_decimal_uint(string key, uint256 val, uint256 decimals); + event log_named_int(string key, int256 val); + event log_named_uint(string key, uint256 val); + event log_named_bytes(string key, bytes val); + event log_named_string(string key, string val); + + event log_array(uint256[] val); + event log_array(int256[] val); + event log_array(address[] val); + event log_named_array(string key, uint256[] val); + event log_named_array(string key, int256[] val); + event log_named_array(string key, address[] val); + + bool private _failed; + + function failed() public view returns (bool) { + if (_failed) { + return _failed; + } else { + return vm.load(address(vm), bytes32("failed")) != bytes32(0); + } + } + + function fail() internal virtual { + vm.store(address(vm), bytes32("failed"), bytes32(uint256(1))); + _failed = true; + } + + function assertTrue(bool data) internal pure virtual { + vm.assertTrue(data); + } + + function assertTrue(bool data, string memory err) internal pure virtual { + vm.assertTrue(data, err); + } + + function assertFalse(bool data) internal pure virtual { + vm.assertFalse(data); + } + + function assertFalse(bool data, string memory err) internal pure virtual { + vm.assertFalse(data, err); + } + + function assertEq(bool left, bool right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bool left, bool right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(uint256 left, uint256 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + function assertEq(int256 left, int256 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertEqDecimal(left, right, decimals); + } + + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertEqDecimal(left, right, decimals, err); + } + + function assertEq(address left, address right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(address left, address right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes32 left, bytes32 right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq32(bytes32 left, bytes32 right) internal pure virtual { + assertEq(left, right); + } + + function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + assertEq(left, right, err); + } + + function assertEq(string memory left, string memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertEq(left, right); + } + + function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertEq(left, right, err); + } + + // Legacy helper + function assertEqUint(uint256 left, uint256 right) internal pure virtual { + assertEq(left, right); + } + + function assertNotEq(bool left, bool right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bool left, bool right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(uint256 left, uint256 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + function assertNotEq(int256 left, int256 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals); + } + + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertNotEqDecimal(left, right, decimals, err); + } + + function assertNotEq(address left, address right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(address left, address right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { + assertNotEq(left, right); + } + + function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { + assertNotEq(left, right, err); + } + + function assertNotEq(string memory left, string memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { + vm.assertNotEq(left, right); + } + + function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { + vm.assertNotEq(left, right, err); + } + + function assertLt(uint256 left, uint256 right) internal pure virtual { + vm.assertLt(left, right); + } + + function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertLt(left, right, err); + } + + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + function assertLt(int256 left, int256 right) internal pure virtual { + vm.assertLt(left, right); + } + + function assertLt(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertLt(left, right, err); + } + + function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLtDecimal(left, right, decimals); + } + + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLtDecimal(left, right, decimals, err); + } + + function assertGt(uint256 left, uint256 right) internal pure virtual { + vm.assertGt(left, right); + } + + function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertGt(left, right, err); + } + + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + function assertGt(int256 left, int256 right) internal pure virtual { + vm.assertGt(left, right); + } + + function assertGt(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertGt(left, right, err); + } + + function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGtDecimal(left, right, decimals); + } + + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGtDecimal(left, right, decimals, err); + } + + function assertLe(uint256 left, uint256 right) internal pure virtual { + vm.assertLe(left, right); + } + + function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertLe(left, right, err); + } + + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + function assertLe(int256 left, int256 right) internal pure virtual { + vm.assertLe(left, right); + } + + function assertLe(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertLe(left, right, err); + } + + function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertLeDecimal(left, right, decimals); + } + + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertLeDecimal(left, right, decimals, err); + } + + function assertGe(uint256 left, uint256 right) internal pure virtual { + vm.assertGe(left, right); + } + + function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { + vm.assertGe(left, right, err); + } + + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + function assertGe(int256 left, int256 right) internal pure virtual { + vm.assertGe(left, right); + } + + function assertGe(int256 left, int256 right, string memory err) internal pure virtual { + vm.assertGe(left, right, err); + } + + function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { + vm.assertGeDecimal(left, right, decimals); + } + + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { + vm.assertGeDecimal(left, right, decimals, err); + } + + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) + internal + pure + virtual + { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + function assertApproxEqAbsDecimal( + uint256 left, + uint256 right, + uint256 maxDelta, + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta); + } + + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { + vm.assertApproxEqAbs(left, right, maxDelta, err); + } + + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); + } + + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) + internal + pure + virtual + { + vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); + } + + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + function assertApproxEqRel( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta); + } + + function assertApproxEqRel( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + string memory err + ) internal pure virtual { + vm.assertApproxEqRel(left, right, maxPercentDelta, err); + } + + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); + } + + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% + uint256 decimals, + string memory err + ) internal pure virtual { + vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); + } + + // Inherited from DSTest, not used but kept for backwards-compatibility + function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { + return keccak256(left) == keccak256(right); + } + + function assertEq0(bytes memory left, bytes memory right) internal pure virtual { + assertEq(left, right); + } + + function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertEq(left, right, err); + } + + function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { + assertNotEq(left, right); + } + + function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { + assertNotEq(left, right, err); + } + + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { + assertEqCall(target, callDataA, target, callDataB, true); + } + + function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) + internal + virtual + { + assertEqCall(targetA, callDataA, targetB, callDataB, true); + } + + function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) + internal + virtual + { + assertEqCall(target, callDataA, target, callDataB, strictRevertData); + } + + function assertEqCall( + address targetA, + bytes memory callDataA, + address targetB, + bytes memory callDataB, + bool strictRevertData + ) internal virtual { + (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); + (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); + + if (successA && successB) { + assertEq(returnDataA, returnDataB, "Call return data does not match"); + } + + if (!successA && !successB && strictRevertData) { + assertEq(returnDataA, returnDataB, "Call revert data does not match"); + } + + if (!successA && successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call revert data", returnDataA); + emit log_named_bytes(" Right call return data", returnDataB); + revert("assertion failed"); + } + + if (successA && !successB) { + emit log("Error: Calls were not equal"); + emit log_named_bytes(" Left call return data", returnDataA); + emit log_named_bytes(" Right call revert data", returnDataB); + revert("assertion failed"); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol new file mode 100644 index 0000000..9ca1b82 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {VmSafe} from "./Vm.sol"; + +/** + * StdChains provides information about EVM compatible chains that can be used in scripts/tests. + * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are + * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of + * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the + * alias used in this contract, which can be found as the first argument to the + * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. + * + * There are two main ways to use this contract: + * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or + * `setChain(string memory chainAlias, Chain memory chain)` + * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. + * + * The first time either of those are used, chains are initialized with the default set of RPC URLs. + * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in + * `defaultRpcUrls`. + * + * The `setChain` function is straightforward, and it simply saves off the given chain data. + * + * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say + * we want to retrieve the RPC URL for `mainnet`: + * - If you have specified data with `setChain`, it will return that. + * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it + * is valid (e.g. a URL is specified, or an environment variable is given and exists). + * - If neither of the above conditions is met, the default data is returned. + * + * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. + */ +abstract contract StdChains { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + bool private stdChainsInitialized; + + struct ChainData { + string name; + uint256 chainId; + string rpcUrl; + } + + struct Chain { + // The chain name. + string name; + // The chain's Chain ID. + uint256 chainId; + // The chain's alias. (i.e. what gets specified in `foundry.toml`). + string chainAlias; + // A default RPC endpoint for this chain. + // NOTE: This default RPC URL is included for convenience to facilitate quick tests and + // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy + // usage as you will be throttled and this is a disservice to others who need this endpoint. + string rpcUrl; + } + + // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. + mapping(string => Chain) private chains; + // Maps from the chain's alias to it's default RPC URL. + mapping(string => string) private defaultRpcUrls; + // Maps from a chain ID to it's alias. + mapping(uint256 => string) private idToAlias; + + bool private fallbackToDefaultRpcUrls = true; + + // The RPC URL will be fetched from config or defaultRpcUrls if possible. + function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { + require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); + + initializeStdChains(); + chain = chains[chainAlias]; + require( + chain.chainId != 0, + string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) + ); + + chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + } + + function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { + require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); + initializeStdChains(); + string memory chainAlias = idToAlias[chainId]; + + chain = chains[chainAlias]; + + require( + chain.chainId != 0, + string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) + ); + + chain = getChainWithUpdatedRpcUrl(chainAlias, chain); + } + + // set chain info, with priority to argument's rpcUrl field. + function setChain(string memory chainAlias, ChainData memory chain) internal virtual { + require( + bytes(chainAlias).length != 0, + "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." + ); + + require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); + + initializeStdChains(); + string memory foundAlias = idToAlias[chain.chainId]; + + require( + bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), + string( + abi.encodePacked( + "StdChains setChain(string,ChainData): Chain ID ", + vm.toString(chain.chainId), + " already used by \"", + foundAlias, + "\"." + ) + ) + ); + + uint256 oldChainId = chains[chainAlias].chainId; + delete idToAlias[oldChainId]; + + chains[chainAlias] = + Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); + idToAlias[chain.chainId] = chainAlias; + } + + // set chain info, with priority to argument's rpcUrl field. + function setChain(string memory chainAlias, Chain memory chain) internal virtual { + setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); + } + + function _toUpper(string memory str) private pure returns (string memory) { + bytes memory strb = bytes(str); + bytes memory copy = new bytes(strb.length); + for (uint256 i = 0; i < strb.length; i++) { + bytes1 b = strb[i]; + if (b >= 0x61 && b <= 0x7A) { + copy[i] = bytes1(uint8(b) - 32); + } else { + copy[i] = b; + } + } + return string(copy); + } + + // lookup rpcUrl, in descending order of priority: + // current -> config (foundry.toml) -> environment variable -> default + function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) + private + view + returns (Chain memory) + { + if (bytes(chain.rpcUrl).length == 0) { + try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { + chain.rpcUrl = configRpcUrl; + } catch (bytes memory err) { + string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); + if (fallbackToDefaultRpcUrls) { + chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); + } else { + chain.rpcUrl = vm.envString(envName); + } + // Distinguish 'not found' from 'cannot read' + // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions + bytes memory oldNotFoundError = + abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); + bytes memory newNotFoundError = abi.encodeWithSignature( + "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) + ); + bytes32 errHash = keccak256(err); + if ( + (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) + || bytes(chain.rpcUrl).length == 0 + ) { + /// @solidity memory-safe-assembly + assembly { + revert(add(32, err), mload(err)) + } + } + } + } + return chain; + } + + function setFallbackToDefaultRpcUrls(bool useDefault) internal { + fallbackToDefaultRpcUrls = useDefault; + } + + function initializeStdChains() private { + if (stdChainsInitialized) return; + + stdChainsInitialized = true; + + // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` + setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); + setChainWithDefaultRpcUrl( + "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") + ); + setChainWithDefaultRpcUrl( + "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") + ); + setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); + setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); + setChainWithDefaultRpcUrl( + "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") + ); + setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); + setChainWithDefaultRpcUrl( + "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") + ); + setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); + setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); + setChainWithDefaultRpcUrl( + "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") + ); + setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); + setChainWithDefaultRpcUrl( + "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") + ); + setChainWithDefaultRpcUrl( + "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") + ); + setChainWithDefaultRpcUrl( + "bnb_smart_chain_testnet", + ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") + ); + setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); + setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); + setChainWithDefaultRpcUrl( + "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") + ); + setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); + setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); + setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); + setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); + setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); + setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); + setChainWithDefaultRpcUrl( + "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") + ); + setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); + setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); + setChainWithDefaultRpcUrl( + "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") + ); + setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); + setChainWithDefaultRpcUrl( + "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") + ); + } + + // set chain info, with priority to chainAlias' rpc url in foundry.toml + function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { + string memory rpcUrl = chain.rpcUrl; + defaultRpcUrls[chainAlias] = rpcUrl; + chain.rpcUrl = ""; + setChain(chainAlias, chain); + chain.rpcUrl = rpcUrl; // restore argument + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol new file mode 100644 index 0000000..95850d1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol @@ -0,0 +1,817 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {StdStorage, stdStorage} from "./StdStorage.sol"; +import {console2} from "./console2.sol"; +import {Vm} from "./Vm.sol"; + +abstract contract StdCheatsSafe { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + uint256 private constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + bool private gasMeteringOff; + + // Data structures to parse Transaction objects from the broadcast artifact + // that conform to EIP1559. The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct RawTx1559 { + string[] arguments; + address contractAddress; + string contractName; + // json value name = function + string functionSig; + bytes32 hash; + // json value name = tx + RawTx1559Detail txDetail; + // json value name = type + string opcode; + } + + struct RawTx1559Detail { + AccessList[] accessList; + bytes data; + address from; + bytes gas; + bytes nonce; + address to; + bytes txType; + bytes value; + } + + struct Tx1559 { + string[] arguments; + address contractAddress; + string contractName; + string functionSig; + bytes32 hash; + Tx1559Detail txDetail; + string opcode; + } + + struct Tx1559Detail { + AccessList[] accessList; + bytes data; + address from; + uint256 gas; + uint256 nonce; + address to; + uint256 txType; + uint256 value; + } + + // Data structures to parse Transaction objects from the broadcast artifact + // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct TxLegacy { + string[] arguments; + address contractAddress; + string contractName; + string functionSig; + string hash; + string opcode; + TxDetailLegacy transaction; + } + + struct TxDetailLegacy { + AccessList[] accessList; + uint256 chainId; + bytes data; + address from; + uint256 gas; + uint256 gasPrice; + bytes32 hash; + uint256 nonce; + bytes1 opcode; + bytes32 r; + bytes32 s; + uint256 txType; + address to; + uint8 v; + uint256 value; + } + + struct AccessList { + address accessAddress; + bytes32[] storageKeys; + } + + // Data structures to parse Receipt objects from the broadcast artifact. + // The Raw structs is what is parsed from the JSON + // and then converted to the one that is used by the user for better UX. + + struct RawReceipt { + bytes32 blockHash; + bytes blockNumber; + address contractAddress; + bytes cumulativeGasUsed; + bytes effectiveGasPrice; + address from; + bytes gasUsed; + RawReceiptLog[] logs; + bytes logsBloom; + bytes status; + address to; + bytes32 transactionHash; + bytes transactionIndex; + } + + struct Receipt { + bytes32 blockHash; + uint256 blockNumber; + address contractAddress; + uint256 cumulativeGasUsed; + uint256 effectiveGasPrice; + address from; + uint256 gasUsed; + ReceiptLog[] logs; + bytes logsBloom; + uint256 status; + address to; + bytes32 transactionHash; + uint256 transactionIndex; + } + + // Data structures to parse the entire broadcast artifact, assuming the + // transactions conform to EIP1559. + + struct EIP1559ScriptArtifact { + string[] libraries; + string path; + string[] pending; + Receipt[] receipts; + uint256 timestamp; + Tx1559[] transactions; + TxReturn[] txReturns; + } + + struct RawEIP1559ScriptArtifact { + string[] libraries; + string path; + string[] pending; + RawReceipt[] receipts; + TxReturn[] txReturns; + uint256 timestamp; + RawTx1559[] transactions; + } + + struct RawReceiptLog { + // json value = address + address logAddress; + bytes32 blockHash; + bytes blockNumber; + bytes data; + bytes logIndex; + bool removed; + bytes32[] topics; + bytes32 transactionHash; + bytes transactionIndex; + bytes transactionLogIndex; + } + + struct ReceiptLog { + // json value = address + address logAddress; + bytes32 blockHash; + uint256 blockNumber; + bytes data; + uint256 logIndex; + bytes32[] topics; + uint256 transactionIndex; + uint256 transactionLogIndex; + bool removed; + } + + struct TxReturn { + string internalType; + string value; + } + + struct Account { + address addr; + uint256 key; + } + + enum AddressType { + Payable, + NonPayable, + ZeroAddress, + Precompile, + ForgeAddress + } + + // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + function assumeNotBlacklisted(address token, address addr) internal view virtual { + // Nothing to check if `token` is not a contract. + uint256 tokenCodeSize; + assembly { + tokenCodeSize := extcodesize(token) + } + require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); + + bool success; + bytes memory returnData; + + // 4-byte selector for `isBlacklisted(address)`, used by USDC. + (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); + vm.assume(!success || abi.decode(returnData, (bool)) == false); + + // 4-byte selector for `isBlackListed(address)`, used by USDT. + (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); + vm.assume(!success || abi.decode(returnData, (bool)) == false); + } + + // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for + // backwards compatibility, since this name was used in the original PR which already has + // a release. This function can be removed in a future release once we want a breaking change. + function assumeNoBlacklisted(address token, address addr) internal view virtual { + assumeNotBlacklisted(token, addr); + } + + function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { + if (addressType == AddressType.Payable) { + assumeNotPayable(addr); + } else if (addressType == AddressType.NonPayable) { + assumePayable(addr); + } else if (addressType == AddressType.ZeroAddress) { + assumeNotZeroAddress(addr); + } else if (addressType == AddressType.Precompile) { + assumeNotPrecompile(addr); + } else if (addressType == AddressType.ForgeAddress) { + assumeNotForgeAddress(addr); + } + } + + function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + } + + function assumeAddressIsNot( + address addr, + AddressType addressType1, + AddressType addressType2, + AddressType addressType3 + ) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + assumeAddressIsNot(addr, addressType3); + } + + function assumeAddressIsNot( + address addr, + AddressType addressType1, + AddressType addressType2, + AddressType addressType3, + AddressType addressType4 + ) internal virtual { + assumeAddressIsNot(addr, addressType1); + assumeAddressIsNot(addr, addressType2); + assumeAddressIsNot(addr, addressType3); + assumeAddressIsNot(addr, addressType4); + } + + // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to + // `addr` and checking the `success` return value. + // NOTE: This function may result in state changes depending on the fallback/receive logic + // implemented by `addr`, which should be taken into account when this function is used. + function _isPayable(address addr) private returns (bool) { + require( + addr.balance < UINT256_MAX, + "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" + ); + uint256 origBalanceTest = address(this).balance; + uint256 origBalanceAddr = address(addr).balance; + + vm.deal(address(this), 1); + (bool success,) = payable(addr).call{value: 1}(""); + + // reset balances + vm.deal(address(this), origBalanceTest); + vm.deal(addr, origBalanceAddr); + + return success; + } + + // NOTE: This function may result in state changes depending on the fallback/receive logic + // implemented by `addr`, which should be taken into account when this function is used. See the + // `_isPayable` method for more information. + function assumePayable(address addr) internal virtual { + vm.assume(_isPayable(addr)); + } + + function assumeNotPayable(address addr) internal virtual { + vm.assume(!_isPayable(addr)); + } + + function assumeNotZeroAddress(address addr) internal pure virtual { + vm.assume(addr != address(0)); + } + + function assumeNotPrecompile(address addr) internal pure virtual { + assumeNotPrecompile(addr, _pureChainId()); + } + + function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { + // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific + // address), but the same rationale for excluding them applies so we include those too. + + // These are reserved by Ethereum and may be on all EVM-compatible chains. + vm.assume(addr < address(0x1) || addr > address(0xff)); + + // forgefmt: disable-start + if (chainId == 10 || chainId == 420) { + // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 + vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); + } else if (chainId == 42161 || chainId == 421613) { + // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains + vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); + } else if (chainId == 43114 || chainId == 43113) { + // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 + vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); + vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); + vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); + } + // forgefmt: disable-end + } + + function assumeNotForgeAddress(address addr) internal pure virtual { + // vm, console, and Create2Deployer addresses + vm.assume( + addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 + && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C + ); + } + + function readEIP1559ScriptArtifact(string memory path) + internal + view + virtual + returns (EIP1559ScriptArtifact memory) + { + string memory data = vm.readFile(path); + bytes memory parsedData = vm.parseJson(data); + RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); + EIP1559ScriptArtifact memory artifact; + artifact.libraries = rawArtifact.libraries; + artifact.path = rawArtifact.path; + artifact.timestamp = rawArtifact.timestamp; + artifact.pending = rawArtifact.pending; + artifact.txReturns = rawArtifact.txReturns; + artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); + artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); + return artifact; + } + + function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { + Tx1559[] memory txs = new Tx1559[](rawTxs.length); + for (uint256 i; i < rawTxs.length; i++) { + txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); + } + return txs; + } + + function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { + Tx1559 memory transaction; + transaction.arguments = rawTx.arguments; + transaction.contractName = rawTx.contractName; + transaction.functionSig = rawTx.functionSig; + transaction.hash = rawTx.hash; + transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); + transaction.opcode = rawTx.opcode; + return transaction; + } + + function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) + internal + pure + virtual + returns (Tx1559Detail memory) + { + Tx1559Detail memory txDetail; + txDetail.data = rawDetail.data; + txDetail.from = rawDetail.from; + txDetail.to = rawDetail.to; + txDetail.nonce = _bytesToUint(rawDetail.nonce); + txDetail.txType = _bytesToUint(rawDetail.txType); + txDetail.value = _bytesToUint(rawDetail.value); + txDetail.gas = _bytesToUint(rawDetail.gas); + txDetail.accessList = rawDetail.accessList; + return txDetail; + } + + function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { + string memory deployData = vm.readFile(path); + bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); + RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); + return rawToConvertedEIPTx1559s(rawTxs); + } + + function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { + string memory deployData = vm.readFile(path); + string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); + bytes memory parsedDeployData = vm.parseJson(deployData, key); + RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); + return rawToConvertedEIPTx1559(rawTx); + } + + // Analogous to readTransactions, but for receipts. + function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { + string memory deployData = vm.readFile(path); + bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); + RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); + return rawToConvertedReceipts(rawReceipts); + } + + function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { + string memory deployData = vm.readFile(path); + string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); + bytes memory parsedDeployData = vm.parseJson(deployData, key); + RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); + return rawToConvertedReceipt(rawReceipt); + } + + function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { + Receipt[] memory receipts = new Receipt[](rawReceipts.length); + for (uint256 i; i < rawReceipts.length; i++) { + receipts[i] = rawToConvertedReceipt(rawReceipts[i]); + } + return receipts; + } + + function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { + Receipt memory receipt; + receipt.blockHash = rawReceipt.blockHash; + receipt.to = rawReceipt.to; + receipt.from = rawReceipt.from; + receipt.contractAddress = rawReceipt.contractAddress; + receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); + receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); + receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); + receipt.status = _bytesToUint(rawReceipt.status); + receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); + receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); + receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); + receipt.logsBloom = rawReceipt.logsBloom; + receipt.transactionHash = rawReceipt.transactionHash; + return receipt; + } + + function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) + internal + pure + virtual + returns (ReceiptLog[] memory) + { + ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); + for (uint256 i; i < rawLogs.length; i++) { + logs[i].logAddress = rawLogs[i].logAddress; + logs[i].blockHash = rawLogs[i].blockHash; + logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); + logs[i].data = rawLogs[i].data; + logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); + logs[i].topics = rawLogs[i].topics; + logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); + logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); + logs[i].removed = rawLogs[i].removed; + } + return logs; + } + + // Deploy a contract by fetching the contract bytecode from + // the artifacts directory + // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` + function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { + bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); + /// @solidity memory-safe-assembly + assembly { + addr := create(0, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); + } + + function deployCode(string memory what) internal virtual returns (address addr) { + bytes memory bytecode = vm.getCode(what); + /// @solidity memory-safe-assembly + assembly { + addr := create(0, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); + } + + /// @dev deploy contract with value on construction + function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { + bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); + /// @solidity memory-safe-assembly + assembly { + addr := create(val, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); + } + + function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { + bytes memory bytecode = vm.getCode(what); + /// @solidity memory-safe-assembly + assembly { + addr := create(val, add(bytecode, 0x20), mload(bytecode)) + } + + require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); + } + + // creates a labeled address and the corresponding private key + function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { + privateKey = uint256(keccak256(abi.encodePacked(name))); + addr = vm.addr(privateKey); + vm.label(addr, name); + } + + // creates a labeled address + function makeAddr(string memory name) internal virtual returns (address addr) { + (addr,) = makeAddrAndKey(name); + } + + // Destroys an account immediately, sending the balance to beneficiary. + // Destroying means: balance will be zero, code will be empty, and nonce will be 0 + // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce + // only after tx ends, this will run immediately. + function destroyAccount(address who, address beneficiary) internal virtual { + uint256 currBalance = who.balance; + vm.etch(who, abi.encode()); + vm.deal(who, 0); + vm.resetNonce(who); + + uint256 beneficiaryBalance = beneficiary.balance; + vm.deal(beneficiary, currBalance + beneficiaryBalance); + } + + // creates a struct containing both a labeled address and the corresponding private key + function makeAccount(string memory name) internal virtual returns (Account memory account) { + (account.addr, account.key) = makeAddrAndKey(name); + } + + function deriveRememberKey(string memory mnemonic, uint32 index) + internal + virtual + returns (address who, uint256 privateKey) + { + privateKey = vm.deriveKey(mnemonic, index); + who = vm.rememberKey(privateKey); + } + + function _bytesToUint(bytes memory b) private pure returns (uint256) { + require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); + return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); + } + + function isFork() internal view virtual returns (bool status) { + try vm.activeFork() { + status = true; + } catch (bytes memory) {} + } + + modifier skipWhenForking() { + if (!isFork()) { + _; + } + } + + modifier skipWhenNotForking() { + if (isFork()) { + _; + } + } + + modifier noGasMetering() { + vm.pauseGasMetering(); + // To prevent turning gas monitoring back on with nested functions that use this modifier, + // we check if gasMetering started in the off position. If it did, we don't want to turn + // it back on until we exit the top level function that used the modifier + // + // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. + // funcA will have `gasStartedOff` as false, funcB will have it as true, + // so we only turn metering back on at the end of the funcA + bool gasStartedOff = gasMeteringOff; + gasMeteringOff = true; + + _; + + // if gas metering was on when this modifier was called, turn it back on at the end + if (!gasStartedOff) { + gasMeteringOff = false; + vm.resumeGasMetering(); + } + } + + // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no + // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We + // can't simply access the chain ID in a normal view or pure function because the solc View Pure + // Checker changed `chainid` from pure to view in 0.8.0. + function _viewChainId() private view returns (uint256 chainId) { + // Assembly required since `block.chainid` was introduced in 0.8.0. + assembly { + chainId := chainid() + } + + address(this); // Silence warnings in older Solc versions. + } + + function _pureChainId() private pure returns (uint256 chainId) { + function() internal view returns (uint256) fnIn = _viewChainId; + function() internal pure returns (uint256) pureChainId; + assembly { + pureChainId := fnIn + } + chainId = pureChainId(); + } +} + +// Wrappers around cheatcodes to avoid footguns +abstract contract StdCheats is StdCheatsSafe { + using stdStorage for StdStorage; + + StdStorage private stdstore; + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + + // Skip forward or rewind time by the specified number of seconds + function skip(uint256 time) internal virtual { + vm.warp(block.timestamp + time); + } + + function rewind(uint256 time) internal virtual { + vm.warp(block.timestamp - time); + } + + // Setup a prank from an address that has some ether + function hoax(address msgSender) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.prank(msgSender); + } + + function hoax(address msgSender, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.prank(msgSender); + } + + function hoax(address msgSender, address origin) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.prank(msgSender, origin); + } + + function hoax(address msgSender, address origin, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.prank(msgSender, origin); + } + + // Start perpetual prank from an address that has some ether + function startHoax(address msgSender) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.startPrank(msgSender); + } + + function startHoax(address msgSender, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.startPrank(msgSender); + } + + // Start perpetual prank from an address that has some ether + // tx.origin is set to the origin parameter + function startHoax(address msgSender, address origin) internal virtual { + vm.deal(msgSender, 1 << 128); + vm.startPrank(msgSender, origin); + } + + function startHoax(address msgSender, address origin, uint256 give) internal virtual { + vm.deal(msgSender, give); + vm.startPrank(msgSender, origin); + } + + function changePrank(address msgSender) internal virtual { + console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); + vm.stopPrank(); + vm.startPrank(msgSender); + } + + function changePrank(address msgSender, address txOrigin) internal virtual { + vm.stopPrank(); + vm.startPrank(msgSender, txOrigin); + } + + // The same as Vm's `deal` + // Use the alternative signature for ERC20 tokens + function deal(address to, uint256 give) internal virtual { + vm.deal(to, give); + } + + // Set the balance of an account for any ERC20 token + // Use the alternative signature to update `totalSupply` + function deal(address token, address to, uint256 give) internal virtual { + deal(token, to, give, false); + } + + // Set the balance of an account for any ERC1155 token + // Use the alternative signature to update `totalSupply` + function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { + dealERC1155(token, to, id, give, false); + } + + function deal(address token, address to, uint256 give, bool adjust) internal virtual { + // get current balance + (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); + uint256 prevBal = abi.decode(balData, (uint256)); + + // update balance + stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); + + // update total supply + if (adjust) { + (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); + uint256 totSup = abi.decode(totSupData, (uint256)); + if (give < prevBal) { + totSup -= (prevBal - give); + } else { + totSup += (give - prevBal); + } + stdstore.target(token).sig(0x18160ddd).checked_write(totSup); + } + } + + function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { + // get current balance + (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); + uint256 prevBal = abi.decode(balData, (uint256)); + + // update balance + stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); + + // update total supply + if (adjust) { + (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); + require( + totSupData.length != 0, + "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." + ); + uint256 totSup = abi.decode(totSupData, (uint256)); + if (give < prevBal) { + totSup -= (prevBal - give); + } else { + totSup += (give - prevBal); + } + stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); + } + } + + function dealERC721(address token, address to, uint256 id) internal virtual { + // check if token id is already minted and the actual owner. + (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); + require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); + + // get owner current balance + (, bytes memory fromBalData) = + token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); + uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); + + // get new user current balance + (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); + uint256 toPrevBal = abi.decode(toBalData, (uint256)); + + // update balances + stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); + stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); + + // update owner + stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); + } + + function deployCodeTo(string memory what, address where) internal virtual { + deployCodeTo(what, "", 0, where); + } + + function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { + deployCodeTo(what, args, 0, where); + } + + function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { + bytes memory creationCode = vm.getCode(what); + vm.etch(where, abi.encodePacked(creationCode, args)); + (bool success, bytes memory runtimeBytecode) = where.call{value: value}(""); + require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); + vm.etch(where, runtimeBytecode); + } + + // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. + function console2_log_StdCheats(string memory p0) private view { + (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); + status; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol new file mode 100644 index 0000000..a302191 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test +pragma solidity >=0.6.2 <0.9.0; + +library stdError { + bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); + bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); + bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); + bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); + bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); + bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); + bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); + bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); + bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol new file mode 100644 index 0000000..056db98 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +abstract contract StdInvariant { + struct FuzzSelector { + address addr; + bytes4[] selectors; + } + + struct FuzzArtifactSelector { + string artifact; + bytes4[] selectors; + } + + struct FuzzInterface { + address addr; + string[] artifacts; + } + + address[] private _excludedContracts; + address[] private _excludedSenders; + address[] private _targetedContracts; + address[] private _targetedSenders; + + string[] private _excludedArtifacts; + string[] private _targetedArtifacts; + + FuzzArtifactSelector[] private _targetedArtifactSelectors; + + FuzzSelector[] private _excludedSelectors; + FuzzSelector[] private _targetedSelectors; + + FuzzInterface[] private _targetedInterfaces; + + // Functions for users: + // These are intended to be called in tests. + + function excludeContract(address newExcludedContract_) internal { + _excludedContracts.push(newExcludedContract_); + } + + function excludeSelector(FuzzSelector memory newExcludedSelector_) internal { + _excludedSelectors.push(newExcludedSelector_); + } + + function excludeSender(address newExcludedSender_) internal { + _excludedSenders.push(newExcludedSender_); + } + + function excludeArtifact(string memory newExcludedArtifact_) internal { + _excludedArtifacts.push(newExcludedArtifact_); + } + + function targetArtifact(string memory newTargetedArtifact_) internal { + _targetedArtifacts.push(newTargetedArtifact_); + } + + function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal { + _targetedArtifactSelectors.push(newTargetedArtifactSelector_); + } + + function targetContract(address newTargetedContract_) internal { + _targetedContracts.push(newTargetedContract_); + } + + function targetSelector(FuzzSelector memory newTargetedSelector_) internal { + _targetedSelectors.push(newTargetedSelector_); + } + + function targetSender(address newTargetedSender_) internal { + _targetedSenders.push(newTargetedSender_); + } + + function targetInterface(FuzzInterface memory newTargetedInterface_) internal { + _targetedInterfaces.push(newTargetedInterface_); + } + + // Functions for forge: + // These are called by forge to run invariant tests and don't need to be called in tests. + + function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { + excludedArtifacts_ = _excludedArtifacts; + } + + function excludeContracts() public view returns (address[] memory excludedContracts_) { + excludedContracts_ = _excludedContracts; + } + + function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) { + excludedSelectors_ = _excludedSelectors; + } + + function excludeSenders() public view returns (address[] memory excludedSenders_) { + excludedSenders_ = _excludedSenders; + } + + function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { + targetedArtifacts_ = _targetedArtifacts; + } + + function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) { + targetedArtifactSelectors_ = _targetedArtifactSelectors; + } + + function targetContracts() public view returns (address[] memory targetedContracts_) { + targetedContracts_ = _targetedContracts; + } + + function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { + targetedSelectors_ = _targetedSelectors; + } + + function targetSenders() public view returns (address[] memory targetedSenders_) { + targetedSenders_ = _targetedSenders; + } + + function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { + targetedInterfaces_ = _targetedInterfaces; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol new file mode 100644 index 0000000..2a033c0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {VmSafe} from "./Vm.sol"; + +// Helpers for parsing and writing JSON files +// To parse: +// ``` +// using stdJson for string; +// string memory json = vm.readFile(""); +// json.readUint(""); +// ``` +// To write: +// ``` +// using stdJson for string; +// string memory json = "json"; +// json.serialize("a", uint256(123)); +// string memory semiFinal = json.serialize("b", string("test")); +// string memory finalJson = json.serialize("c", semiFinal); +// finalJson.write(""); +// ``` + +library stdJson { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function keyExists(string memory json, string memory key) internal view returns (bool) { + return vm.keyExistsJson(json, key); + } + + function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { + return vm.parseJson(json, key); + } + + function readUint(string memory json, string memory key) internal pure returns (uint256) { + return vm.parseJsonUint(json, key); + } + + function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { + return vm.parseJsonUintArray(json, key); + } + + function readInt(string memory json, string memory key) internal pure returns (int256) { + return vm.parseJsonInt(json, key); + } + + function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { + return vm.parseJsonIntArray(json, key); + } + + function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { + return vm.parseJsonBytes32(json, key); + } + + function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { + return vm.parseJsonBytes32Array(json, key); + } + + function readString(string memory json, string memory key) internal pure returns (string memory) { + return vm.parseJsonString(json, key); + } + + function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { + return vm.parseJsonStringArray(json, key); + } + + function readAddress(string memory json, string memory key) internal pure returns (address) { + return vm.parseJsonAddress(json, key); + } + + function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { + return vm.parseJsonAddressArray(json, key); + } + + function readBool(string memory json, string memory key) internal pure returns (bool) { + return vm.parseJsonBool(json, key); + } + + function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { + return vm.parseJsonBoolArray(json, key); + } + + function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { + return vm.parseJsonBytes(json, key); + } + + function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { + return vm.parseJsonBytesArray(json, key); + } + + function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { + return keyExists(json, key) ? readUint(json, key) : defaultValue; + } + + function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) + internal + view + returns (uint256[] memory) + { + return keyExists(json, key) ? readUintArray(json, key) : defaultValue; + } + + function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { + return keyExists(json, key) ? readInt(json, key) : defaultValue; + } + + function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) + internal + view + returns (int256[] memory) + { + return keyExists(json, key) ? readIntArray(json, key) : defaultValue; + } + + function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) + internal + view + returns (bytes32) + { + return keyExists(json, key) ? readBytes32(json, key) : defaultValue; + } + + function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) + internal + view + returns (bytes32[] memory) + { + return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; + } + + function readStringOr(string memory json, string memory key, string memory defaultValue) + internal + view + returns (string memory) + { + return keyExists(json, key) ? readString(json, key) : defaultValue; + } + + function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) + internal + view + returns (string[] memory) + { + return keyExists(json, key) ? readStringArray(json, key) : defaultValue; + } + + function readAddressOr(string memory json, string memory key, address defaultValue) + internal + view + returns (address) + { + return keyExists(json, key) ? readAddress(json, key) : defaultValue; + } + + function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) + internal + view + returns (address[] memory) + { + return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; + } + + function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { + return keyExists(json, key) ? readBool(json, key) : defaultValue; + } + + function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) + internal + view + returns (bool[] memory) + { + return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; + } + + function readBytesOr(string memory json, string memory key, bytes memory defaultValue) + internal + view + returns (bytes memory) + { + return keyExists(json, key) ? readBytes(json, key) : defaultValue; + } + + function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) + internal + view + returns (bytes[] memory) + { + return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; + } + + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { + return vm.serializeJson(jsonKey, rootObject); + } + + function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bool[] memory value) + internal + returns (string memory) + { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256[] memory value) + internal + returns (string memory) + { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256[] memory value) + internal + returns (string memory) + { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address[] memory value) + internal + returns (string memory) + { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string[] memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function write(string memory jsonKey, string memory path) internal { + vm.writeJson(jsonKey, path); + } + + function write(string memory jsonKey, string memory path, string memory valueKey) internal { + vm.writeJson(jsonKey, path, valueKey); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol new file mode 100644 index 0000000..459523b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +library stdMath { + int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; + + function abs(int256 a) internal pure returns (uint256) { + // Required or it will fail when `a = type(int256).min` + if (a == INT256_MIN) { + return 57896044618658097711785492504343953926634992332820282019728792003956564819968; + } + + return uint256(a > 0 ? a : -a); + } + + function delta(uint256 a, uint256 b) internal pure returns (uint256) { + return a > b ? a - b : b - a; + } + + function delta(int256 a, int256 b) internal pure returns (uint256) { + // a and b are of the same sign + // this works thanks to two's complement, the left-most bit is the sign bit + if ((a ^ b) > -1) { + return delta(abs(a), abs(b)); + } + + // a and b are of opposite signs + return abs(a) + abs(b); + } + + function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 absDelta = delta(a, b); + + return absDelta * 1e18 / b; + } + + function percentDelta(int256 a, int256 b) internal pure returns (uint256) { + uint256 absDelta = delta(a, b); + uint256 absB = abs(b); + + return absDelta * 1e18 / absB; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol new file mode 100644 index 0000000..bf3223d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol @@ -0,0 +1,473 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {Vm} from "./Vm.sol"; + +struct FindData { + uint256 slot; + uint256 offsetLeft; + uint256 offsetRight; + bool found; +} + +struct StdStorage { + mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; + bytes32[] _keys; + bytes4 _sig; + uint256 _depth; + address _target; + bytes32 _set; + bool _enable_packed_slots; + bytes _calldata; +} + +library stdStorageSafe { + event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); + event WARNING_UninitedSlot(address who, uint256 slot); + + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + function sigs(string memory sigStr) internal pure returns (bytes4) { + return bytes4(keccak256(bytes(sigStr))); + } + + function getCallParams(StdStorage storage self) internal view returns (bytes memory) { + if (self._calldata.length == 0) { + return flatten(self._keys); + } else { + return self._calldata; + } + } + + // Calls target contract with configured parameters + function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { + bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); + (bool success, bytes memory rdat) = self._target.staticcall(cald); + bytes32 result = bytesToBytes32(rdat, 32 * self._depth); + + return (success, result); + } + + // Tries mutating slot value to determine if the targeted value is stored in it. + // If current value is 0, then we are setting slot value to type(uint256).max + // Otherwise, we set it to 0. That way, return value should always be affected. + function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { + bytes32 prevSlotValue = vm.load(self._target, slot); + (bool success, bytes32 prevReturnValue) = callTarget(self); + + bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); + vm.store(self._target, slot, testVal); + + (, bytes32 newReturnValue) = callTarget(self); + + vm.store(self._target, slot, prevSlotValue); + + return (success && (prevReturnValue != newReturnValue)); + } + + // Tries setting one of the bits in slot to 1 until return value changes. + // Index of resulted bit is an offset packed slot has from left/right side + function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { + for (uint256 offset = 0; offset < 256; offset++) { + uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); + vm.store(self._target, slot, bytes32(valueToPut)); + + (bool success, bytes32 data) = callTarget(self); + + if (success && (uint256(data) > 0)) { + return (true, offset); + } + } + return (false, 0); + } + + function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { + bytes32 prevSlotValue = vm.load(self._target, slot); + + (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); + (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); + + // `findOffset` may mutate slot value, so we are setting it to initial value + vm.store(self._target, slot, prevSlotValue); + return (foundLeft && foundRight, offsetLeft, offsetRight); + } + + function find(StdStorage storage self) internal returns (FindData storage) { + return find(self, true); + } + + /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against + // slot complexity: + // if flat, will be bytes32(uint256(uint)); + // if map, will be keccak256(abi.encode(key, uint(slot))); + // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); + // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); + function find(StdStorage storage self, bool _clear) internal returns (FindData storage) { + address who = self._target; + bytes4 fsig = self._sig; + uint256 field_depth = self._depth; + bytes memory params = getCallParams(self); + + // calldata to test against + if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { + if (_clear) { + clear(self); + } + return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + } + vm.record(); + (, bytes32 callResult) = callTarget(self); + (bytes32[] memory reads,) = vm.accesses(address(who)); + + if (reads.length == 0) { + revert("stdStorage find(StdStorage): No storage use detected for target."); + } else { + for (uint256 i = reads.length; --i >= 0;) { + bytes32 prev = vm.load(who, reads[i]); + if (prev == bytes32(0)) { + emit WARNING_UninitedSlot(who, uint256(reads[i])); + } + + if (!checkSlotMutatesCall(self, reads[i])) { + continue; + } + + (uint256 offsetLeft, uint256 offsetRight) = (0, 0); + + if (self._enable_packed_slots) { + bool found; + (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); + if (!found) { + continue; + } + } + + // Check that value between found offsets is equal to the current call result + uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; + + if (uint256(callResult) != curVal) { + continue; + } + + emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); + self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = + FindData(uint256(reads[i]), offsetLeft, offsetRight, true); + break; + } + } + + require( + self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, + "stdStorage find(StdStorage): Slot(s) not found." + ); + + if (_clear) { + clear(self); + } + return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + } + + function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { + self._target = _target; + return self; + } + + function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { + self._sig = _sig; + return self; + } + + function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { + self._sig = sigs(_sig); + return self; + } + + function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { + self._calldata = _calldata; + return self; + } + + function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { + self._keys.push(bytes32(uint256(uint160(who)))); + return self; + } + + function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { + self._keys.push(bytes32(amt)); + return self; + } + + function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { + self._keys.push(key); + return self; + } + + function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { + self._enable_packed_slots = true; + return self; + } + + function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { + self._depth = _depth; + return self; + } + + function read(StdStorage storage self) private returns (bytes memory) { + FindData storage data = find(self, false); + uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); + uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; + clear(self); + return abi.encode(value); + } + + function read_bytes32(StdStorage storage self) internal returns (bytes32) { + return abi.decode(read(self), (bytes32)); + } + + function read_bool(StdStorage storage self) internal returns (bool) { + int256 v = read_int(self); + if (v == 0) return false; + if (v == 1) return true; + revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); + } + + function read_address(StdStorage storage self) internal returns (address) { + return abi.decode(read(self), (address)); + } + + function read_uint(StdStorage storage self) internal returns (uint256) { + return abi.decode(read(self), (uint256)); + } + + function read_int(StdStorage storage self) internal returns (int256) { + return abi.decode(read(self), (int256)); + } + + function parent(StdStorage storage self) internal returns (uint256, bytes32) { + address who = self._target; + uint256 field_depth = self._depth; + vm.startMappingRecording(); + uint256 child = find(self, true).slot - field_depth; + (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); + if (!found) { + revert( + "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + ); + } + return (uint256(parent_slot), key); + } + + function root(StdStorage storage self) internal returns (uint256) { + address who = self._target; + uint256 field_depth = self._depth; + vm.startMappingRecording(); + uint256 child = find(self, true).slot - field_depth; + bool found; + bytes32 root_slot; + bytes32 parent_slot; + (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); + if (!found) { + revert( + "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." + ); + } + while (found) { + root_slot = parent_slot; + (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); + } + return uint256(root_slot); + } + + function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { + bytes32 out; + + uint256 max = b.length > 32 ? 32 : b.length; + for (uint256 i = 0; i < max; i++) { + out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); + } + return out; + } + + function flatten(bytes32[] memory b) private pure returns (bytes memory) { + bytes memory result = new bytes(b.length * 32); + for (uint256 i = 0; i < b.length; i++) { + bytes32 k = b[i]; + /// @solidity memory-safe-assembly + assembly { + mstore(add(result, add(32, mul(32, i))), k) + } + } + + return result; + } + + function clear(StdStorage storage self) internal { + delete self._target; + delete self._sig; + delete self._keys; + delete self._depth; + delete self._enable_packed_slots; + delete self._calldata; + } + + // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` + // (slotValue & mask) >> offsetRight will be the value of the given packed variable + function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { + // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; + // using assembly because (1 << 256) causes overflow + assembly { + mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) + } + } + + // Returns slot value with updated packed variable. + function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) + internal + pure + returns (bytes32 newValue) + { + return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); + } +} + +library stdStorage { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function sigs(string memory sigStr) internal pure returns (bytes4) { + return stdStorageSafe.sigs(sigStr); + } + + function find(StdStorage storage self) internal returns (uint256) { + return find(self, true); + } + + function find(StdStorage storage self, bool _clear) internal returns (uint256) { + return stdStorageSafe.find(self, _clear).slot; + } + + function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { + return stdStorageSafe.target(self, _target); + } + + function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { + return stdStorageSafe.sig(self, _sig); + } + + function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { + return stdStorageSafe.sig(self, _sig); + } + + function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, who); + } + + function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, amt); + } + + function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { + return stdStorageSafe.with_key(self, key); + } + + function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { + return stdStorageSafe.with_calldata(self, _calldata); + } + + function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { + return stdStorageSafe.enable_packed_slots(self); + } + + function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { + return stdStorageSafe.depth(self, _depth); + } + + function clear(StdStorage storage self) internal { + stdStorageSafe.clear(self); + } + + function checked_write(StdStorage storage self, address who) internal { + checked_write(self, bytes32(uint256(uint160(who)))); + } + + function checked_write(StdStorage storage self, uint256 amt) internal { + checked_write(self, bytes32(amt)); + } + + function checked_write_int(StdStorage storage self, int256 val) internal { + checked_write(self, bytes32(uint256(val))); + } + + function checked_write(StdStorage storage self, bool write) internal { + bytes32 t; + /// @solidity memory-safe-assembly + assembly { + t := write + } + checked_write(self, t); + } + + function checked_write(StdStorage storage self, bytes32 set) internal { + address who = self._target; + bytes4 fsig = self._sig; + uint256 field_depth = self._depth; + bytes memory params = stdStorageSafe.getCallParams(self); + + if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { + find(self, false); + } + FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; + if ((data.offsetLeft + data.offsetRight) > 0) { + uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); + require( + uint256(set) < maxVal, + string( + abi.encodePacked( + "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", + vm.toString(maxVal) + ) + ) + ); + } + bytes32 curVal = vm.load(who, bytes32(data.slot)); + bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); + + vm.store(who, bytes32(data.slot), valToSet); + + (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); + + if (!success || callResult != set) { + vm.store(who, bytes32(data.slot), curVal); + revert("stdStorage find(StdStorage): Failed to write value."); + } + clear(self); + } + + function read_bytes32(StdStorage storage self) internal returns (bytes32) { + return stdStorageSafe.read_bytes32(self); + } + + function read_bool(StdStorage storage self) internal returns (bool) { + return stdStorageSafe.read_bool(self); + } + + function read_address(StdStorage storage self) internal returns (address) { + return stdStorageSafe.read_address(self); + } + + function read_uint(StdStorage storage self) internal returns (uint256) { + return stdStorageSafe.read_uint(self); + } + + function read_int(StdStorage storage self) internal returns (int256) { + return stdStorageSafe.read_int(self); + } + + function parent(StdStorage storage self) internal returns (uint256, bytes32) { + return stdStorageSafe.parent(self); + } + + function root(StdStorage storage self) internal returns (uint256) { + return stdStorageSafe.root(self); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol new file mode 100644 index 0000000..d371e0c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +import {VmSafe} from "./Vm.sol"; + +library StdStyle { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + string constant RED = "\u001b[91m"; + string constant GREEN = "\u001b[92m"; + string constant YELLOW = "\u001b[93m"; + string constant BLUE = "\u001b[94m"; + string constant MAGENTA = "\u001b[95m"; + string constant CYAN = "\u001b[96m"; + string constant BOLD = "\u001b[1m"; + string constant DIM = "\u001b[2m"; + string constant ITALIC = "\u001b[3m"; + string constant UNDERLINE = "\u001b[4m"; + string constant INVERSE = "\u001b[7m"; + string constant RESET = "\u001b[0m"; + + function styleConcat(string memory style, string memory self) private pure returns (string memory) { + return string(abi.encodePacked(style, self, RESET)); + } + + function red(string memory self) internal pure returns (string memory) { + return styleConcat(RED, self); + } + + function red(uint256 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(int256 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(address self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function red(bool self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function redBytes(bytes memory self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function redBytes32(bytes32 self) internal pure returns (string memory) { + return red(vm.toString(self)); + } + + function green(string memory self) internal pure returns (string memory) { + return styleConcat(GREEN, self); + } + + function green(uint256 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(int256 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(address self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function green(bool self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function greenBytes(bytes memory self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function greenBytes32(bytes32 self) internal pure returns (string memory) { + return green(vm.toString(self)); + } + + function yellow(string memory self) internal pure returns (string memory) { + return styleConcat(YELLOW, self); + } + + function yellow(uint256 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(int256 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(address self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellow(bool self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellowBytes(bytes memory self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function yellowBytes32(bytes32 self) internal pure returns (string memory) { + return yellow(vm.toString(self)); + } + + function blue(string memory self) internal pure returns (string memory) { + return styleConcat(BLUE, self); + } + + function blue(uint256 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(int256 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(address self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blue(bool self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blueBytes(bytes memory self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function blueBytes32(bytes32 self) internal pure returns (string memory) { + return blue(vm.toString(self)); + } + + function magenta(string memory self) internal pure returns (string memory) { + return styleConcat(MAGENTA, self); + } + + function magenta(uint256 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(int256 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(address self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magenta(bool self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magentaBytes(bytes memory self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function magentaBytes32(bytes32 self) internal pure returns (string memory) { + return magenta(vm.toString(self)); + } + + function cyan(string memory self) internal pure returns (string memory) { + return styleConcat(CYAN, self); + } + + function cyan(uint256 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(int256 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(address self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyan(bool self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyanBytes(bytes memory self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function cyanBytes32(bytes32 self) internal pure returns (string memory) { + return cyan(vm.toString(self)); + } + + function bold(string memory self) internal pure returns (string memory) { + return styleConcat(BOLD, self); + } + + function bold(uint256 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(int256 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(address self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function bold(bool self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function boldBytes(bytes memory self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function boldBytes32(bytes32 self) internal pure returns (string memory) { + return bold(vm.toString(self)); + } + + function dim(string memory self) internal pure returns (string memory) { + return styleConcat(DIM, self); + } + + function dim(uint256 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(int256 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(address self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dim(bool self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dimBytes(bytes memory self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function dimBytes32(bytes32 self) internal pure returns (string memory) { + return dim(vm.toString(self)); + } + + function italic(string memory self) internal pure returns (string memory) { + return styleConcat(ITALIC, self); + } + + function italic(uint256 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(int256 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(address self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italic(bool self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italicBytes(bytes memory self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function italicBytes32(bytes32 self) internal pure returns (string memory) { + return italic(vm.toString(self)); + } + + function underline(string memory self) internal pure returns (string memory) { + return styleConcat(UNDERLINE, self); + } + + function underline(uint256 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(int256 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(address self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underline(bool self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underlineBytes(bytes memory self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function underlineBytes32(bytes32 self) internal pure returns (string memory) { + return underline(vm.toString(self)); + } + + function inverse(string memory self) internal pure returns (string memory) { + return styleConcat(INVERSE, self); + } + + function inverse(uint256 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(int256 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(address self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverse(bool self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverseBytes(bytes memory self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } + + function inverseBytes32(bytes32 self) internal pure returns (string memory) { + return inverse(vm.toString(self)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol new file mode 100644 index 0000000..7ad3be2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {VmSafe} from "./Vm.sol"; + +// Helpers for parsing and writing TOML files +// To parse: +// ``` +// using stdToml for string; +// string memory toml = vm.readFile(""); +// toml.readUint(""); +// ``` +// To write: +// ``` +// using stdToml for string; +// string memory json = "json"; +// json.serialize("a", uint256(123)); +// string memory semiFinal = json.serialize("b", string("test")); +// string memory finalJson = json.serialize("c", semiFinal); +// finalJson.write(""); +// ``` + +library stdToml { + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function keyExists(string memory toml, string memory key) internal view returns (bool) { + return vm.keyExistsToml(toml, key); + } + + function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { + return vm.parseToml(toml, key); + } + + function readUint(string memory toml, string memory key) internal pure returns (uint256) { + return vm.parseTomlUint(toml, key); + } + + function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { + return vm.parseTomlUintArray(toml, key); + } + + function readInt(string memory toml, string memory key) internal pure returns (int256) { + return vm.parseTomlInt(toml, key); + } + + function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { + return vm.parseTomlIntArray(toml, key); + } + + function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { + return vm.parseTomlBytes32(toml, key); + } + + function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { + return vm.parseTomlBytes32Array(toml, key); + } + + function readString(string memory toml, string memory key) internal pure returns (string memory) { + return vm.parseTomlString(toml, key); + } + + function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { + return vm.parseTomlStringArray(toml, key); + } + + function readAddress(string memory toml, string memory key) internal pure returns (address) { + return vm.parseTomlAddress(toml, key); + } + + function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { + return vm.parseTomlAddressArray(toml, key); + } + + function readBool(string memory toml, string memory key) internal pure returns (bool) { + return vm.parseTomlBool(toml, key); + } + + function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { + return vm.parseTomlBoolArray(toml, key); + } + + function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { + return vm.parseTomlBytes(toml, key); + } + + function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { + return vm.parseTomlBytesArray(toml, key); + } + + function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { + return keyExists(toml, key) ? readUint(toml, key) : defaultValue; + } + + function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) + internal + view + returns (uint256[] memory) + { + return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; + } + + function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { + return keyExists(toml, key) ? readInt(toml, key) : defaultValue; + } + + function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) + internal + view + returns (int256[] memory) + { + return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; + } + + function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) + internal + view + returns (bytes32) + { + return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; + } + + function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) + internal + view + returns (bytes32[] memory) + { + return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; + } + + function readStringOr(string memory toml, string memory key, string memory defaultValue) + internal + view + returns (string memory) + { + return keyExists(toml, key) ? readString(toml, key) : defaultValue; + } + + function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) + internal + view + returns (string[] memory) + { + return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; + } + + function readAddressOr(string memory toml, string memory key, address defaultValue) + internal + view + returns (address) + { + return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; + } + + function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) + internal + view + returns (address[] memory) + { + return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; + } + + function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { + return keyExists(toml, key) ? readBool(toml, key) : defaultValue; + } + + function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) + internal + view + returns (bool[] memory) + { + return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; + } + + function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) + internal + view + returns (bytes memory) + { + return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; + } + + function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) + internal + view + returns (bytes[] memory) + { + return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; + } + + function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { + return vm.serializeJson(jsonKey, rootObject); + } + + function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bool[] memory value) + internal + returns (string memory) + { + return vm.serializeBool(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, uint256[] memory value) + internal + returns (string memory) + { + return vm.serializeUint(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, int256[] memory value) + internal + returns (string memory) + { + return vm.serializeInt(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, address[] memory value) + internal + returns (string memory) + { + return vm.serializeAddress(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes32[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes32(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, bytes[] memory value) + internal + returns (string memory) + { + return vm.serializeBytes(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function serialize(string memory jsonKey, string memory key, string[] memory value) + internal + returns (string memory) + { + return vm.serializeString(jsonKey, key, value); + } + + function write(string memory jsonKey, string memory path) internal { + vm.writeToml(jsonKey, path); + } + + function write(string memory jsonKey, string memory path, string memory valueKey) internal { + vm.writeToml(jsonKey, path, valueKey); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol new file mode 100644 index 0000000..5d12043 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +import {IMulticall3} from "./interfaces/IMulticall3.sol"; +import {MockERC20} from "./mocks/MockERC20.sol"; +import {MockERC721} from "./mocks/MockERC721.sol"; +import {VmSafe} from "./Vm.sol"; + +abstract contract StdUtils { + /*////////////////////////////////////////////////////////////////////////// + CONSTANTS + //////////////////////////////////////////////////////////////////////////*/ + + IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); + VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; + uint256 private constant INT256_MIN_ABS = + 57896044618658097711785492504343953926634992332820282019728792003956564819968; + uint256 private constant SECP256K1_ORDER = + 115792089237316195423570985008687907852837564279074904382605163141518161494337; + uint256 private constant UINT256_MAX = + 115792089237316195423570985008687907853269984665640564039457584007913129639935; + + // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. + address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + + /*////////////////////////////////////////////////////////////////////////// + INTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////////////////*/ + + function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { + require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); + // If x is between min and max, return x directly. This is to ensure that dictionary values + // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 + if (x >= min && x <= max) return x; + + uint256 size = max - min + 1; + + // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. + // This helps ensure coverage of the min/max values. + if (x <= 3 && size > x) return min + x; + if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); + + // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. + if (x > max) { + uint256 diff = x - max; + uint256 rem = diff % size; + if (rem == 0) return max; + result = min + rem - 1; + } else if (x < min) { + uint256 diff = min - x; + uint256 rem = diff % size; + if (rem == 0) return min; + result = max - rem + 1; + } + } + + function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { + result = _bound(x, min, max); + console2_log_StdUtils("Bound result", result); + } + + function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { + require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); + + // Shifting all int256 values to uint256 to use _bound function. The range of two types are: + // int256 : -(2**255) ~ (2**255 - 1) + // uint256: 0 ~ (2**256 - 1) + // So, add 2**255, INT256_MIN_ABS to the integer values. + // + // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. + // So, use `~uint256(x) + 1` instead. + uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); + uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); + uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); + + uint256 y = _bound(_x, _min, _max); + + // To move it back to int256 value, subtract INT256_MIN_ABS at here. + result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); + } + + function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { + result = _bound(x, min, max); + console2_log_StdUtils("Bound result", vm.toString(result)); + } + + function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { + result = _bound(privateKey, 1, SECP256K1_ORDER - 1); + } + + function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { + require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); + return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); + } + + /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce + /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) + function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { + console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); + return vm.computeCreateAddress(deployer, nonce); + } + + function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) + internal + pure + virtual + returns (address) + { + console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + return vm.computeCreate2Address(salt, initcodeHash, deployer); + } + + /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { + console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); + return vm.computeCreate2Address(salt, initCodeHash); + } + + /// @dev returns an initialized mock ERC20 contract + function deployMockERC20(string memory name, string memory symbol, uint8 decimals) + internal + returns (MockERC20 mock) + { + mock = new MockERC20(); + mock.initialize(name, symbol, decimals); + } + + /// @dev returns an initialized mock ERC721 contract + function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { + mock = new MockERC721(); + mock.initialize(name, symbol); + } + + /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments + /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode + function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { + return hashInitCode(creationCode, ""); + } + + /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 + /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode + /// @param args the ABI-encoded arguments to the constructor of C + function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(creationCode, args)); + } + + // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. + function getTokenBalances(address token, address[] memory addresses) + internal + virtual + returns (uint256[] memory balances) + { + uint256 tokenCodeSize; + assembly { + tokenCodeSize := extcodesize(token) + } + require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); + + // ABI encode the aggregate call to Multicall3. + uint256 length = addresses.length; + IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); + for (uint256 i = 0; i < length; ++i) { + // 0x70a08231 = bytes4("balanceOf(address)")) + calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); + } + + // Make the aggregate call. + (, bytes[] memory returnData) = multicall.aggregate(calls); + + // ABI decode the return data and return the balances. + balances = new uint256[](length); + for (uint256 i = 0; i < length; ++i) { + balances[i] = abi.decode(returnData[i], (uint256)); + } + } + + /*////////////////////////////////////////////////////////////////////////// + PRIVATE FUNCTIONS + //////////////////////////////////////////////////////////////////////////*/ + + function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { + return address(uint160(uint256(bytesValue))); + } + + // This section is used to prevent the compilation of console, which shortens the compilation time when console is + // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid + // any breaking changes to function signatures. + function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) + internal + pure + returns (function(bytes memory) internal pure fnOut) + { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castLogPayloadViewToPure(_sendLogPayloadView)(payload); + } + + function _sendLogPayloadView(bytes memory payload) private view { + uint256 payloadLength = payload.length; + address consoleAddress = CONSOLE2_ADDRESS; + /// @solidity memory-safe-assembly + assembly { + let payloadStart := add(payload, 32) + let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) + } + } + + function console2_log_StdUtils(string memory p0) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function console2_log_StdUtils(string memory p0, uint256 p1) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); + } + + function console2_log_StdUtils(string memory p0, string memory p1) private pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol new file mode 100644 index 0000000..5ff60ea --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +// 💬 ABOUT +// Forge Std's default Test. + +// 🧩 MODULES +import {console} from "./console.sol"; +import {console2} from "./console2.sol"; +import {safeconsole} from "./safeconsole.sol"; +import {StdAssertions} from "./StdAssertions.sol"; +import {StdChains} from "./StdChains.sol"; +import {StdCheats} from "./StdCheats.sol"; +import {stdError} from "./StdError.sol"; +import {StdInvariant} from "./StdInvariant.sol"; +import {stdJson} from "./StdJson.sol"; +import {stdMath} from "./StdMath.sol"; +import {StdStorage, stdStorage} from "./StdStorage.sol"; +import {StdStyle} from "./StdStyle.sol"; +import {stdToml} from "./StdToml.sol"; +import {StdUtils} from "./StdUtils.sol"; +import {Vm} from "./Vm.sol"; + +// 📦 BOILERPLATE +import {TestBase} from "./Base.sol"; + +// ⭐️ TEST +abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils { + // Note: IS_TEST() must return true. + bool public IS_TEST = true; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol new file mode 100644 index 0000000..591508c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol @@ -0,0 +1,1968 @@ +// Automatically @generated by scripts/vm.py. Do not modify manually. + +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may +/// result in Script simulations differing from on-chain execution. It is recommended to only use +/// these cheats in scripts. +interface VmSafe { + /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. + enum CallerMode { + // No caller modification is currently active. + None, + // A one time broadcast triggered by a `vm.broadcast()` call is currently active. + Broadcast, + // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. + RecurrentBroadcast, + // A one time prank triggered by a `vm.prank()` call is currently active. + Prank, + // A recurrent prank triggered by a `vm.startPrank()` call is currently active. + RecurrentPrank + } + + /// The kind of account access that occurred. + enum AccountAccessKind { + // The account was called. + Call, + // The account was called via delegatecall. + DelegateCall, + // The account was called via callcode. + CallCode, + // The account was called via staticcall. + StaticCall, + // The account was created. + Create, + // The account was selfdestructed. + SelfDestruct, + // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). + Resume, + // The account's balance was read. + Balance, + // The account's codesize was read. + Extcodesize, + // The account's codehash was read. + Extcodehash, + // The account's code was copied. + Extcodecopy + } + + /// Forge execution contexts. + enum ForgeContext { + // Test group execution context (test, coverage or snapshot). + TestGroup, + // `forge test` execution context. + Test, + // `forge coverage` execution context. + Coverage, + // `forge snapshot` execution context. + Snapshot, + // Script group execution context (dry run, broadcast or resume). + ScriptGroup, + // `forge script` execution context. + ScriptDryRun, + // `forge script --broadcast` execution context. + ScriptBroadcast, + // `forge script --resume` execution context. + ScriptResume, + // Unknown `forge` execution context. + Unknown + } + + /// An Ethereum log. Returned by `getRecordedLogs`. + struct Log { + // The topics of the log, including the signature, if any. + bytes32[] topics; + // The raw data of the log. + bytes data; + // The address of the log's emitter. + address emitter; + } + + /// An RPC URL and its alias. Returned by `rpcUrlStructs`. + struct Rpc { + // The alias of the RPC URL. + string key; + // The RPC URL. + string url; + } + + /// An RPC log object. Returned by `eth_getLogs`. + struct EthGetLogs { + // The address of the log's emitter. + address emitter; + // The topics of the log, including the signature, if any. + bytes32[] topics; + // The raw data of the log. + bytes data; + // The block hash. + bytes32 blockHash; + // The block number. + uint64 blockNumber; + // The transaction hash. + bytes32 transactionHash; + // The transaction index in the block. + uint64 transactionIndex; + // The log index. + uint256 logIndex; + // Whether the log was removed. + bool removed; + } + + /// A single entry in a directory listing. Returned by `readDir`. + struct DirEntry { + // The error message, if any. + string errorMessage; + // The path of the entry. + string path; + // The depth of the entry. + uint64 depth; + // Whether the entry is a directory. + bool isDir; + // Whether the entry is a symlink. + bool isSymlink; + } + + /// Metadata information about a file. + /// This structure is returned from the `fsMetadata` function and represents known + /// metadata about a file such as its permissions, size, modification + /// times, etc. + struct FsMetadata { + // True if this metadata is for a directory. + bool isDir; + // True if this metadata is for a symlink. + bool isSymlink; + // The size of the file, in bytes, this metadata is for. + uint256 length; + // True if this metadata is for a readonly (unwritable) file. + bool readOnly; + // The last modification time listed in this metadata. + uint256 modified; + // The last access time of this metadata. + uint256 accessed; + // The creation time listed in this metadata. + uint256 created; + } + + /// A wallet with a public and private key. + struct Wallet { + // The wallet's address. + address addr; + // The wallet's public key `X`. + uint256 publicKeyX; + // The wallet's public key `Y`. + uint256 publicKeyY; + // The wallet's private key. + uint256 privateKey; + } + + /// The result of a `tryFfi` call. + struct FfiResult { + // The exit code of the call. + int32 exitCode; + // The optionally hex-decoded `stdout` data. + bytes stdout; + // The `stderr` data. + bytes stderr; + } + + /// Information on the chain and fork. + struct ChainInfo { + // The fork identifier. Set to zero if no fork is active. + uint256 forkId; + // The chain ID of the current fork. + uint256 chainId; + } + + /// The result of a `stopAndReturnStateDiff` call. + struct AccountAccess { + // The chain and fork the access occurred. + ChainInfo chainInfo; + // The kind of account access that determines what the account is. + // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. + // If kind is Create, then the account is the newly created account. + // If kind is SelfDestruct, then the account is the selfdestruct recipient. + // If kind is a Resume, then account represents a account context that has resumed. + AccountAccessKind kind; + // The account that was accessed. + // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. + address account; + // What accessed the account. + address accessor; + // If the account was initialized or empty prior to the access. + // An account is considered initialized if it has code, a + // non-zero nonce, or a non-zero balance. + bool initialized; + // The previous balance of the accessed account. + uint256 oldBalance; + // The potential new balance of the accessed account. + // That is, all balance changes are recorded here, even if reverts occurred. + uint256 newBalance; + // Code of the account deployed by CREATE. + bytes deployedCode; + // Value passed along with the account access + uint256 value; + // Input data provided to the CREATE or CALL + bytes data; + // If this access reverted in either the current or parent context. + bool reverted; + // An ordered list of storage accesses made during an account access operation. + StorageAccess[] storageAccesses; + // Call depth traversed during the recording of state differences + uint64 depth; + } + + /// The storage accessed during an `AccountAccess`. + struct StorageAccess { + // The account whose storage was accessed. + address account; + // The slot that was accessed. + bytes32 slot; + // If the access was a write. + bool isWrite; + // The previous value of the slot. + bytes32 previousValue; + // The new value of the slot. + bytes32 newValue; + // If the access was reverted. + bool reverted; + } + + /// Gas used. Returned by `lastCallGas`. + struct Gas { + // The gas limit of the call. + uint64 gasLimit; + // The total gas used. + uint64 gasTotalUsed; + // DEPRECATED: The amount of gas used for memory expansion. Ref: + uint64 gasMemoryUsed; + // The amount of gas refunded. + int64 gasRefunded; + // The amount of gas remaining. + uint64 gasRemaining; + } + + // ======== Crypto ======== + + /// Derives a private key from the name, labels the account with that name, and returns the wallet. + function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key and returns the wallet. + function createWallet(uint256 privateKey) external returns (Wallet memory wallet); + + /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. + function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at the derivation path `m/44'/60'/0'/0/{index}`. + function deriveKey(string calldata mnemonic, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language + /// at `{derivationPath}{index}`. + function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) + external + pure + returns (uint256 privateKey); + + /// Derives secp256r1 public key from the provided `privateKey`. + function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); + + /// Adds a private key to the local forge wallet and returns the address. + function rememberKey(uint256 privateKey) external returns (address keyAddr); + + /// Signs data with a `Wallet`. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with `privateKey` using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + /// If `--sender` is provided, the signer with provided address is used, otherwise, + /// if exactly one signer is provided to the script, that signer is used. + /// Raises error if signer passed through `--sender` does not match any unlocked signers or + /// if `--sender` is not provided and not exactly one signer is passed to the script. + function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the + /// signature's `s` value, and the recovery id `v` in a single bytes32. + /// This format reduces the signature size from 65 to 64 bytes. + /// Raises error if none of the signers passed into the script have provided address. + function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + + /// Signs `digest` with `privateKey` using the secp256r1 curve. + function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); + + /// Signs data with a `Wallet`. + function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with `privateKey` using the secp256k1 curve. + function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// If `--sender` is provided, the signer with provided address is used, otherwise, + /// if exactly one signer is provided to the script, that signer is used. + /// Raises error if signer passed through `--sender` does not match any unlocked signers or + /// if `--sender` is not provided and not exactly one signer is passed to the script. + function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + /// Signs `digest` with signer provided to script using the secp256k1 curve. + /// Raises error if none of the signers passed into the script have provided address. + function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); + + // ======== Environment ======== + + /// Gets the environment variable `name` and parses it as `address`. + /// Reverts if the variable was not found or could not be parsed. + function envAddress(string calldata name) external view returns (address value); + + /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); + + /// Gets the environment variable `name` and parses it as `bool`. + /// Reverts if the variable was not found or could not be parsed. + function envBool(string calldata name) external view returns (bool value); + + /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); + + /// Gets the environment variable `name` and parses it as `bytes32`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes32(string calldata name) external view returns (bytes32 value); + + /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); + + /// Gets the environment variable `name` and parses it as `bytes`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes(string calldata name) external view returns (bytes memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); + + /// Gets the environment variable `name` and returns true if it exists, else returns false. + function envExists(string calldata name) external view returns (bool result); + + /// Gets the environment variable `name` and parses it as `int256`. + /// Reverts if the variable was not found or could not be parsed. + function envInt(string calldata name) external view returns (int256 value); + + /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); + + /// Gets the environment variable `name` and parses it as `bool`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bool defaultValue) external view returns (bool value); + + /// Gets the environment variable `name` and parses it as `uint256`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); + + /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) + external + view + returns (address[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) + external + view + returns (bytes32[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) + external + view + returns (string[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) + external + view + returns (bytes[] memory value); + + /// Gets the environment variable `name` and parses it as `int256`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); + + /// Gets the environment variable `name` and parses it as `address`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, address defaultValue) external view returns (address value); + + /// Gets the environment variable `name` and parses it as `bytes32`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); + + /// Gets the environment variable `name` and parses it as `string`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); + + /// Gets the environment variable `name` and parses it as `bytes`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); + + /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) + external + view + returns (bool[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) + external + view + returns (uint256[] memory value); + + /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. + /// Reverts if the variable could not be parsed. + /// Returns `defaultValue` if the variable was not found. + function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) + external + view + returns (int256[] memory value); + + /// Gets the environment variable `name` and parses it as `string`. + /// Reverts if the variable was not found or could not be parsed. + function envString(string calldata name) external view returns (string memory value); + + /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envString(string calldata name, string calldata delim) external view returns (string[] memory value); + + /// Gets the environment variable `name` and parses it as `uint256`. + /// Reverts if the variable was not found or could not be parsed. + function envUint(string calldata name) external view returns (uint256 value); + + /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. + /// Reverts if the variable was not found or could not be parsed. + function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); + + /// Returns true if `forge` command was executed in given context. + function isContext(ForgeContext context) external view returns (bool result); + + /// Sets environment variables. + function setEnv(string calldata name, string calldata value) external; + + // ======== EVM ======== + + /// Gets all accessed reads and write slot from a `vm.record` session, for a given address. + function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); + + /// Gets the address for a given private key. + function addr(uint256 privateKey) external pure returns (address keyAddr); + + /// Gets all the logs according to specified filter. + function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) + external + returns (EthGetLogs[] memory logs); + + /// Gets the current `block.blobbasefee`. + /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlobBaseFee() external view returns (uint256 blobBaseFee); + + /// Gets the current `block.number`. + /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlockNumber() external view returns (uint256 height); + + /// Gets the current `block.timestamp`. + /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, + /// and as a result will get optimized out by the compiler. + /// See https://github.com/foundry-rs/foundry/issues/6180 + function getBlockTimestamp() external view returns (uint256 timestamp); + + /// Gets the map key and parent of a mapping at a given slot, for a given address. + function getMappingKeyAndParentOf(address target, bytes32 elementSlot) + external + returns (bool found, bytes32 key, bytes32 parent); + + /// Gets the number of elements in the mapping at the given slot, for a given address. + function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); + + /// Gets the elements at index idx of the mapping at the given slot, for a given address. The + /// index must be less than the length of the mapping (i.e. the number of keys in the mapping). + function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); + + /// Gets the nonce of an account. + function getNonce(address account) external view returns (uint64 nonce); + + /// Get the nonce of a `Wallet`. + function getNonce(Wallet calldata wallet) external returns (uint64 nonce); + + /// Gets all the recorded logs. + function getRecordedLogs() external returns (Log[] memory logs); + + /// Gets the gas used in the last call. + function lastCallGas() external view returns (Gas memory gas); + + /// Loads a storage slot from an address. + function load(address target, bytes32 slot) external view returns (bytes32 data); + + /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. + function pauseGasMetering() external; + + /// Records all storage reads and writes. + function record() external; + + /// Record all the transaction logs. + function recordLogs() external; + + /// Reset gas metering (i.e. gas usage is set to gas limit). + function resetGasMetering() external; + + /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. + function resumeGasMetering() external; + + /// Performs an Ethereum JSON-RPC request to the current fork URL. + function rpc(string calldata method, string calldata params) external returns (bytes memory data); + + /// Performs an Ethereum JSON-RPC request to the given endpoint. + function rpc(string calldata urlOrAlias, string calldata method, string calldata params) + external + returns (bytes memory data); + + /// Starts recording all map SSTOREs for later retrieval. + function startMappingRecording() external; + + /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, + /// along with the context of the calls + function startStateDiffRecording() external; + + /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. + function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); + + /// Stops recording all map SSTOREs for later retrieval and clears the recorded data. + function stopMappingRecording() external; + + // ======== Filesystem ======== + + /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. + /// `path` is relative to the project root. + function closeFile(string calldata path) external; + + /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. + /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. + /// Both `from` and `to` are relative to the project root. + function copyFile(string calldata from, string calldata to) external returns (uint64 copied); + + /// Creates a new, empty directory at the provided path. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - User lacks permissions to modify `path`. + /// - A parent of the given path doesn't exist and `recursive` is false. + /// - `path` already exists and `recursive` is false. + /// `path` is relative to the project root. + function createDir(string calldata path, bool recursive) external; + + /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function deployCode(string calldata artifactPath) external returns (address deployedAddress); + + /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + /// Additionally accepts abi-encoded constructor arguments. + function deployCode(string calldata artifactPath, bytes calldata constructorArgs) + external + returns (address deployedAddress); + + /// Returns true if the given path points to an existing entity, else returns false. + function exists(string calldata path) external returns (bool result); + + /// Performs a foreign function call via the terminal. + function ffi(string[] calldata commandInput) external returns (bytes memory result); + + /// Given a path, query the file system to get information about a file, directory, etc. + function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); + + /// Gets the artifact path from code (aka. creation code). + function getArtifactPathByCode(bytes calldata code) external view returns (string memory path); + + /// Gets the artifact path from deployed code (aka. runtime code). + function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path); + + /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); + + /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the + /// artifact in the form of :: where and parts are optional. + function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); + + /// Returns true if the path exists on disk and is pointing at a directory, else returns false. + function isDir(string calldata path) external returns (bool result); + + /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. + function isFile(string calldata path) external returns (bool result); + + /// Get the path of the current project root. + function projectRoot() external view returns (string memory path); + + /// Prompts the user for a string value in the terminal. + function prompt(string calldata promptText) external returns (string memory input); + + /// Prompts the user for an address in the terminal. + function promptAddress(string calldata promptText) external returns (address); + + /// Prompts the user for a hidden string value in the terminal. + function promptSecret(string calldata promptText) external returns (string memory input); + + /// Prompts the user for hidden uint256 in the terminal (usually pk). + function promptSecretUint(string calldata promptText) external returns (uint256); + + /// Prompts the user for uint256 in the terminal. + function promptUint(string calldata promptText) external returns (uint256); + + /// Reads the directory at the given path recursively, up to `maxDepth`. + /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. + /// Follows symbolic links if `followLinks` is true. + function readDir(string calldata path) external view returns (DirEntry[] memory entries); + + /// See `readDir(string)`. + function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); + + /// See `readDir(string)`. + function readDir(string calldata path, uint64 maxDepth, bool followLinks) + external + view + returns (DirEntry[] memory entries); + + /// Reads the entire content of file to string. `path` is relative to the project root. + function readFile(string calldata path) external view returns (string memory data); + + /// Reads the entire content of file as binary. `path` is relative to the project root. + function readFileBinary(string calldata path) external view returns (bytes memory data); + + /// Reads next line of file to string. + function readLine(string calldata path) external view returns (string memory line); + + /// Reads a symbolic link, returning the path that the link points to. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` is not a symbolic link. + /// - `path` does not exist. + function readLink(string calldata linkPath) external view returns (string memory targetPath); + + /// Removes a directory at the provided path. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` doesn't exist. + /// - `path` isn't a directory. + /// - User lacks permissions to modify `path`. + /// - The directory is not empty and `recursive` is false. + /// `path` is relative to the project root. + function removeDir(string calldata path, bool recursive) external; + + /// Removes a file from the filesystem. + /// This cheatcode will revert in the following situations, but is not limited to just these cases: + /// - `path` points to a directory. + /// - The file doesn't exist. + /// - The user lacks permissions to remove the file. + /// `path` is relative to the project root. + function removeFile(string calldata path) external; + + /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. + function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); + + /// Returns the time since unix epoch in milliseconds. + function unixTime() external returns (uint256 milliseconds); + + /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. + /// `path` is relative to the project root. + function writeFile(string calldata path, string calldata data) external; + + /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. + /// `path` is relative to the project root. + function writeFileBinary(string calldata path, bytes calldata data) external; + + /// Writes line to file, creating a file if it does not exist. + /// `path` is relative to the project root. + function writeLine(string calldata path, string calldata data) external; + + // ======== JSON ======== + + /// Checks if `key` exists in a JSON object. + function keyExistsJson(string calldata json, string calldata key) external view returns (bool); + + /// Parses a string of JSON data at `key` and coerces it to `address`. + function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); + + /// Parses a string of JSON data at `key` and coerces it to `address[]`. + function parseJsonAddressArray(string calldata json, string calldata key) + external + pure + returns (address[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bool`. + function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); + + /// Parses a string of JSON data at `key` and coerces it to `bool[]`. + function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes`. + function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes32`. + function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); + + /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. + function parseJsonBytes32Array(string calldata json, string calldata key) + external + pure + returns (bytes32[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. + function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); + + /// Parses a string of JSON data at `key` and coerces it to `int256`. + function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); + + /// Parses a string of JSON data at `key` and coerces it to `int256[]`. + function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); + + /// Returns an array of all the keys in a JSON object. + function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); + + /// Parses a string of JSON data at `key` and coerces it to `string`. + function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); + + /// Parses a string of JSON data at `key` and coerces it to `string[]`. + function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); + + /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. + function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. + function parseJsonType(string calldata json, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. + function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of JSON data at `key` and coerces it to `uint256`. + function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); + + /// Parses a string of JSON data at `key` and coerces it to `uint256[]`. + function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); + + /// ABI-encodes a JSON object. + function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); + + /// ABI-encodes a JSON object at `key`. + function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); + + /// See `serializeJson`. + function serializeAddress(string calldata objectKey, string calldata valueKey, address value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBool(string calldata objectKey, string calldata valueKey, bool value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) + external + returns (string memory json); + + /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. + /// Returns the stringified version of the specific JSON file up to that moment. + function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); + + /// See `serializeJson`. + function serializeJsonType(string calldata typeDescription, bytes calldata value) + external + pure + returns (string memory json); + + /// See `serializeJson`. + function serializeJsonType( + string calldata objectKey, + string calldata valueKey, + string calldata typeDescription, + bytes calldata value + ) external returns (string memory json); + + /// See `serializeJson`. + function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) + external + returns (string memory json); + + /// See `serializeJson`. + function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) + external + returns (string memory json); + + /// Write a serialized JSON object to a file. If the file exists, it will be overwritten. + function writeJson(string calldata json, string calldata path) external; + + /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = + /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. + function writeJson(string calldata json, string calldata path, string calldata valueKey) external; + + /// Checks if `key` exists in a JSON object + /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. + function keyExists(string calldata json, string calldata key) external view returns (bool); + + // ======== Scripting ======== + + /// Takes a signed transaction and broadcasts it to the network. + function broadcastRawTransaction(bytes calldata data) external; + + /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. + /// Broadcasting address is determined by checking the following in order: + /// 1. If `--sender` argument was provided, that address is used. + /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. + /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. + function broadcast() external; + + /// Has the next call (at this call depth only) create a transaction with the address provided + /// as the sender that can later be signed and sent onchain. + function broadcast(address signer) external; + + /// Has the next call (at this call depth only) create a transaction with the private key + /// provided as the sender that can later be signed and sent onchain. + function broadcast(uint256 privateKey) external; + + /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. + /// Broadcasting address is determined by checking the following in order: + /// 1. If `--sender` argument was provided, that address is used. + /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. + /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. + function startBroadcast() external; + + /// Has all subsequent calls (at this call depth only) create transactions with the address + /// provided that can later be signed and sent onchain. + function startBroadcast(address signer) external; + + /// Has all subsequent calls (at this call depth only) create transactions with the private key + /// provided that can later be signed and sent onchain. + function startBroadcast(uint256 privateKey) external; + + /// Stops collecting onchain transactions. + function stopBroadcast() external; + + // ======== String ======== + + /// Returns the index of the first occurrence of a `key` in an `input` string. + /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. + /// Returns 0 in case of an empty `key`. + function indexOf(string calldata input, string calldata key) external pure returns (uint256); + + /// Parses the given `string` into an `address`. + function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); + + /// Parses the given `string` into a `bool`. + function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); + + /// Parses the given `string` into `bytes`. + function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); + + /// Parses the given `string` into a `bytes32`. + function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); + + /// Parses the given `string` into a `int256`. + function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); + + /// Parses the given `string` into a `uint256`. + function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); + + /// Replaces occurrences of `from` in the given `string` with `to`. + function replace(string calldata input, string calldata from, string calldata to) + external + pure + returns (string memory output); + + /// Splits the given `string` into an array of strings divided by the `delimiter`. + function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); + + /// Converts the given `string` value to Lowercase. + function toLowercase(string calldata input) external pure returns (string memory output); + + /// Converts the given value to a `string`. + function toString(address value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bytes calldata value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bytes32 value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(bool value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(uint256 value) external pure returns (string memory stringifiedValue); + + /// Converts the given value to a `string`. + function toString(int256 value) external pure returns (string memory stringifiedValue); + + /// Converts the given `string` value to Uppercase. + function toUppercase(string calldata input) external pure returns (string memory output); + + /// Trims leading and trailing whitespace from the given `string` value. + function trim(string calldata input) external pure returns (string memory output); + + // ======== Testing ======== + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. + function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqAbsDecimal( + uint256 left, + uint256 right, + uint256 maxDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. + function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqAbsDecimal( + int256 left, + int256 right, + uint256 maxDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; + + /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. + /// Includes error message into revert string on failure. + function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; + + /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. + /// Includes error message into revert string on failure. + function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. + function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) + external + pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqRelDecimal( + uint256 left, + uint256 right, + uint256 maxPercentDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. + function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) + external + pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertApproxEqRelDecimal( + int256 left, + int256 right, + uint256 maxPercentDelta, + uint256 decimals, + string calldata error + ) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; + + /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Includes error message into revert string on failure. + function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) + external + pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; + + /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. + /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% + /// Includes error message into revert string on failure. + function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) + external + pure; + + /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. + function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `bool` values are equal. + function assertEq(bool left, bool right) external pure; + + /// Asserts that two `bool` values are equal and includes error message into revert string on failure. + function assertEq(bool left, bool right, string calldata error) external pure; + + /// Asserts that two `string` values are equal. + function assertEq(string calldata left, string calldata right) external pure; + + /// Asserts that two `string` values are equal and includes error message into revert string on failure. + function assertEq(string calldata left, string calldata right, string calldata error) external pure; + + /// Asserts that two `bytes` values are equal. + function assertEq(bytes calldata left, bytes calldata right) external pure; + + /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. + function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bool` values are equal. + function assertEq(bool[] calldata left, bool[] calldata right) external pure; + + /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. + function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `uint256 values are equal. + function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; + + /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. + function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `int256` values are equal. + function assertEq(int256[] calldata left, int256[] calldata right) external pure; + + /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. + function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are equal. + function assertEq(uint256 left, uint256 right) external pure; + + /// Asserts that two arrays of `address` values are equal. + function assertEq(address[] calldata left, address[] calldata right) external pure; + + /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. + function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes32` values are equal. + function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; + + /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. + function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `string` values are equal. + function assertEq(string[] calldata left, string[] calldata right) external pure; + + /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. + function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes` values are equal. + function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; + + /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. + function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. + function assertEq(uint256 left, uint256 right, string calldata error) external pure; + + /// Asserts that two `int256` values are equal. + function assertEq(int256 left, int256 right) external pure; + + /// Asserts that two `int256` values are equal and includes error message into revert string on failure. + function assertEq(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `address` values are equal. + function assertEq(address left, address right) external pure; + + /// Asserts that two `address` values are equal and includes error message into revert string on failure. + function assertEq(address left, address right, string calldata error) external pure; + + /// Asserts that two `bytes32` values are equal. + function assertEq(bytes32 left, bytes32 right) external pure; + + /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. + function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; + + /// Asserts that the given condition is false. + function assertFalse(bool condition) external pure; + + /// Asserts that the given condition is false and includes error message into revert string on failure. + function assertFalse(bool condition, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. + function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + function assertGe(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than or equal to second. + /// Includes error message into revert string on failure. + function assertGe(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + function assertGe(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be greater than or equal to second. + /// Includes error message into revert string on failure. + function assertGe(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. + function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + function assertGt(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be greater than second. + /// Includes error message into revert string on failure. + function assertGt(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + function assertGt(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be greater than second. + /// Includes error message into revert string on failure. + function assertGt(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. + function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + function assertLe(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be less than or equal to second. + /// Includes error message into revert string on failure. + function assertLe(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + function assertLe(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be less than or equal to second. + /// Includes error message into revert string on failure. + function assertLe(int256 left, int256 right, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. + function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Formats values with decimals in failure message. Includes error message into revert string on failure. + function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + function assertLt(uint256 left, uint256 right) external pure; + + /// Compares two `uint256` values. Expects first value to be less than second. + /// Includes error message into revert string on failure. + function assertLt(uint256 left, uint256 right, string calldata error) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + function assertLt(int256 left, int256 right) external pure; + + /// Compares two `int256` values. Expects first value to be less than second. + /// Includes error message into revert string on failure. + function assertLt(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; + + /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; + + /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. + /// Includes error message into revert string on failure. + function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; + + /// Asserts that two `bool` values are not equal. + function assertNotEq(bool left, bool right) external pure; + + /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. + function assertNotEq(bool left, bool right, string calldata error) external pure; + + /// Asserts that two `string` values are not equal. + function assertNotEq(string calldata left, string calldata right) external pure; + + /// Asserts that two `string` values are not equal and includes error message into revert string on failure. + function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; + + /// Asserts that two `bytes` values are not equal. + function assertNotEq(bytes calldata left, bytes calldata right) external pure; + + /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bool` values are not equal. + function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; + + /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. + function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `uint256` values are not equal. + function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; + + /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. + function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `int256` values are not equal. + function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; + + /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. + function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal. + function assertNotEq(uint256 left, uint256 right) external pure; + + /// Asserts that two arrays of `address` values are not equal. + function assertNotEq(address[] calldata left, address[] calldata right) external pure; + + /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. + function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes32` values are not equal. + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; + + /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `string` values are not equal. + function assertNotEq(string[] calldata left, string[] calldata right) external pure; + + /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. + function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; + + /// Asserts that two arrays of `bytes` values are not equal. + function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; + + /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; + + /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. + function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; + + /// Asserts that two `int256` values are not equal. + function assertNotEq(int256 left, int256 right) external pure; + + /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. + function assertNotEq(int256 left, int256 right, string calldata error) external pure; + + /// Asserts that two `address` values are not equal. + function assertNotEq(address left, address right) external pure; + + /// Asserts that two `address` values are not equal and includes error message into revert string on failure. + function assertNotEq(address left, address right, string calldata error) external pure; + + /// Asserts that two `bytes32` values are not equal. + function assertNotEq(bytes32 left, bytes32 right) external pure; + + /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. + function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; + + /// Asserts that the given condition is true. + function assertTrue(bool condition) external pure; + + /// Asserts that the given condition is true and includes error message into revert string on failure. + function assertTrue(bool condition, string calldata error) external pure; + + /// If the condition is false, discard this run's fuzz inputs and generate new ones. + function assume(bool condition) external pure; + + /// Discard this run's fuzz inputs and generate new ones if next call reverted. + function assumeNoRevert() external pure; + + /// Writes a breakpoint to jump to in the debugger. + function breakpoint(string calldata char) external; + + /// Writes a conditional breakpoint to jump to in the debugger. + function breakpoint(string calldata char, bool value) external; + + /// Returns the Foundry version. + /// Format: ++ + /// Sample output: 0.2.0+faa94c384+202407110019 + /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. + /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) + /// to compare timestamps while ignoring minor time differences. + function getFoundryVersion() external view returns (string memory version); + + /// Returns the RPC url for the given alias. + function rpcUrl(string calldata rpcAlias) external view returns (string memory json); + + /// Returns all rpc urls and their aliases as structs. + function rpcUrlStructs() external view returns (Rpc[] memory urls); + + /// Returns all rpc urls and their aliases `[alias, url][]`. + function rpcUrls() external view returns (string[2][] memory urls); + + /// Suspends execution of the main thread for `duration` milliseconds. + function sleep(uint256 duration) external; + + // ======== Toml ======== + + /// Checks if `key` exists in a TOML table. + function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); + + /// Parses a string of TOML data at `key` and coerces it to `address`. + function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); + + /// Parses a string of TOML data at `key` and coerces it to `address[]`. + function parseTomlAddressArray(string calldata toml, string calldata key) + external + pure + returns (address[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bool`. + function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); + + /// Parses a string of TOML data at `key` and coerces it to `bool[]`. + function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes`. + function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes32`. + function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); + + /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. + function parseTomlBytes32Array(string calldata toml, string calldata key) + external + pure + returns (bytes32[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. + function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); + + /// Parses a string of TOML data at `key` and coerces it to `int256`. + function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); + + /// Parses a string of TOML data at `key` and coerces it to `int256[]`. + function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); + + /// Returns an array of all the keys in a TOML table. + function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); + + /// Parses a string of TOML data at `key` and coerces it to `string`. + function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); + + /// Parses a string of TOML data at `key` and coerces it to `string[]`. + function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); + + /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`. + function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. + function parseTomlType(string calldata toml, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. + function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) + external + pure + returns (bytes memory); + + /// Parses a string of TOML data at `key` and coerces it to `uint256`. + function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); + + /// Parses a string of TOML data at `key` and coerces it to `uint256[]`. + function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); + + /// ABI-encodes a TOML table. + function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); + + /// ABI-encodes a TOML table at `key`. + function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); + + /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. + function writeToml(string calldata json, string calldata path) external; + + /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = + /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. + function writeToml(string calldata json, string calldata path, string calldata valueKey) external; + + // ======== Utilities ======== + + /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) + external + pure + returns (address); + + /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. + function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); + + /// Compute the address a contract will be deployed at for a given deployer address and nonce. + function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); + + /// Utility cheatcode to copy storage of `from` contract to another `to` contract. + function copyStorage(address from, address to) external; + + /// Returns ENS namehash for provided string. + function ensNamehash(string calldata name) external pure returns (bytes32); + + /// Gets the label for the specified address. + function getLabel(address account) external view returns (string memory currentLabel); + + /// Labels an address in call traces. + function label(address account, string calldata newLabel) external; + + /// Pauses collection of call traces. Useful in cases when you want to skip tracing of + /// complex calls which are not useful for debugging. + function pauseTracing() external view; + + /// Returns a random `address`. + function randomAddress() external returns (address); + + /// Returns an random `bool`. + function randomBool() external view returns (bool); + + /// Returns an random byte array value of the given length. + function randomBytes(uint256 len) external view returns (bytes memory); + + /// Returns an random `int256` value. + function randomInt() external view returns (int256); + + /// Returns an random `int256` value of given bits. + function randomInt(uint256 bits) external view returns (int256); + + /// Returns a random uint256 value. + function randomUint() external returns (uint256); + + /// Returns random uint256 value between the provided range (=min..=max). + function randomUint(uint256 min, uint256 max) external returns (uint256); + + /// Returns an random `uint256` value of given bits. + function randomUint(uint256 bits) external view returns (uint256); + + /// Unpauses collection of call traces. + function resumeTracing() external view; + + /// Utility cheatcode to set arbitrary storage for given target address. + function setArbitraryStorage(address target) external; + + /// Encodes a `bytes` value to a base64url string. + function toBase64URL(bytes calldata data) external pure returns (string memory); + + /// Encodes a `string` value to a base64url string. + function toBase64URL(string calldata data) external pure returns (string memory); + + /// Encodes a `bytes` value to a base64 string. + function toBase64(bytes calldata data) external pure returns (string memory); + + /// Encodes a `string` value to a base64 string. + function toBase64(string calldata data) external pure returns (string memory); +} + +/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used +/// in tests, but it is not recommended to use these cheats in scripts. +interface Vm is VmSafe { + // ======== EVM ======== + + /// Returns the identifier of the currently active fork. Reverts if no fork is currently active. + function activeFork() external view returns (uint256 forkId); + + /// In forking mode, explicitly grant the given address cheatcode access. + function allowCheatcodes(address account) external; + + /// Sets `block.blobbasefee` + function blobBaseFee(uint256 newBlobBaseFee) external; + + /// Sets the blobhashes in the transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + function blobhashes(bytes32[] calldata hashes) external; + + /// Sets `block.chainid`. + function chainId(uint256 newChainId) external; + + /// Clears all mocked calls. + function clearMockedCalls() external; + + /// Sets `block.coinbase`. + function coinbase(address newCoinbase) external; + + /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. + function createFork(string calldata urlOrAlias) external returns (uint256 forkId); + + /// Creates a new fork with the given endpoint and block and returns the identifier of the fork. + function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); + + /// Creates a new fork with the given endpoint and at the block the given transaction was mined in, + /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. + function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); + + /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); + + /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); + + /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, + /// replays all transaction mined in the block before the transaction, returns the identifier of the fork. + function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); + + /// Sets an address' balance. + function deal(address account, uint256 newBalance) external; + + /// Removes the snapshot with the given ID created by `snapshot`. + /// Takes the snapshot ID to delete. + /// Returns `true` if the snapshot was successfully deleted. + /// Returns `false` if the snapshot does not exist. + function deleteSnapshot(uint256 snapshotId) external returns (bool success); + + /// Removes _all_ snapshots previously created by `snapshot`. + function deleteSnapshots() external; + + /// Sets `block.difficulty`. + /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. + /// Reverts if used on unsupported EVM versions. + function difficulty(uint256 newDifficulty) external; + + /// Dump a genesis JSON file's `allocs` to disk. + function dumpState(string calldata pathToStateJson) external; + + /// Sets an address' code. + function etch(address target, bytes calldata newRuntimeBytecode) external; + + /// Sets `block.basefee`. + function fee(uint256 newBasefee) external; + + /// Gets the blockhashes from the current transaction. + /// Not available on EVM versions before Cancun. + /// If used on unsupported EVM versions it will revert. + function getBlobhashes() external view returns (bytes32[] memory hashes); + + /// Returns true if the account is marked as persistent. + function isPersistent(address account) external view returns (bool persistent); + + /// Load a genesis JSON file's `allocs` into the in-memory revm state. + function loadAllocs(string calldata pathToAllocsJson) external; + + /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup + /// Meaning, changes made to the state of this account will be kept when switching forks. + function makePersistent(address account) external; + + /// See `makePersistent(address)`. + function makePersistent(address account0, address account1) external; + + /// See `makePersistent(address)`. + function makePersistent(address account0, address account1, address account2) external; + + /// See `makePersistent(address)`. + function makePersistent(address[] calldata accounts) external; + + /// Reverts a call to an address with specified revert data. + function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; + + /// Reverts a call to an address with a specific `msg.value`, with specified revert data. + function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) + external; + + /// Mocks a call to an address, returning specified data. + /// Calldata can either be strict or a partial match, e.g. if you only + /// pass a Solidity selector to the expected calldata, then the entire Solidity + /// function will be mocked. + function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; + + /// Mocks a call to an address with a specific `msg.value`, returning specified data. + /// Calldata match takes precedence over `msg.value` in case of ambiguity. + function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + + /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls + /// `target` with the same calldata. This functionality is similar to a delegate call made to + /// `target` contract from `callee`. + /// Can be used to substitute a call to a function with another implementation that captures + /// the primary logic of the original function but is easier to reason about. + /// If calldata is not a strict match then partial match by selector is attempted. + function mockFunction(address callee, address target, bytes calldata data) external; + + /// Sets the *next* call's `msg.sender` to be the input address. + function prank(address msgSender) external; + + /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. + function prank(address msgSender, address txOrigin) external; + + /// Sets `block.prevrandao`. + /// Not available on EVM versions before Paris. Use `difficulty` instead. + /// If used on unsupported EVM versions it will revert. + function prevrandao(bytes32 newPrevrandao) external; + + /// Sets `block.prevrandao`. + /// Not available on EVM versions before Paris. Use `difficulty` instead. + /// If used on unsupported EVM versions it will revert. + function prevrandao(uint256 newPrevrandao) external; + + /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. + function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); + + /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. + function resetNonce(address account) external; + + /// Revert the state of the EVM to a previous snapshot + /// Takes the snapshot ID to revert to. + /// Returns `true` if the snapshot was successfully reverted. + /// Returns `false` if the snapshot does not exist. + /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. + function revertTo(uint256 snapshotId) external returns (bool success); + + /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots + /// Takes the snapshot ID to revert to. + /// Returns `true` if the snapshot was successfully reverted and deleted. + /// Returns `false` if the snapshot does not exist. + function revertToAndDelete(uint256 snapshotId) external returns (bool success); + + /// Revokes persistent status from the address, previously added via `makePersistent`. + function revokePersistent(address account) external; + + /// See `revokePersistent(address)`. + function revokePersistent(address[] calldata accounts) external; + + /// Sets `block.height`. + function roll(uint256 newHeight) external; + + /// Updates the currently active fork to given block number + /// This is similar to `roll` but for the currently active fork. + function rollFork(uint256 blockNumber) external; + + /// Updates the currently active fork to given transaction. This will `rollFork` with the number + /// of the block the transaction was mined in and replays all transaction mined before it in the block. + function rollFork(bytes32 txHash) external; + + /// Updates the given fork to given block number. + function rollFork(uint256 forkId, uint256 blockNumber) external; + + /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. + function rollFork(uint256 forkId, bytes32 txHash) external; + + /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. + function selectFork(uint256 forkId) external; + + /// Set blockhash for the current block. + /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. + function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; + + /// Sets the nonce of an account. Must be higher than the current nonce of the account. + function setNonce(address account, uint64 newNonce) external; + + /// Sets the nonce of an account to an arbitrary value. + function setNonceUnsafe(address account, uint64 newNonce) external; + + /// Snapshot the current state of the evm. + /// Returns the ID of the snapshot that was created. + /// To revert a snapshot use `revertTo`. + function snapshot() external returns (uint256 snapshotId); + + /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. + function startPrank(address msgSender) external; + + /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. + function startPrank(address msgSender, address txOrigin) external; + + /// Resets subsequent calls' `msg.sender` to be `address(this)`. + function stopPrank() external; + + /// Stores a value to an address' storage slot. + function store(address target, bytes32 slot, bytes32 value) external; + + /// Fetches the given transaction from the active fork and executes it on the current state. + function transact(bytes32 txHash) external; + + /// Fetches the given transaction from the given fork and executes it on the current state. + function transact(uint256 forkId, bytes32 txHash) external; + + /// Sets `tx.gasprice`. + function txGasPrice(uint256 newGasPrice) external; + + /// Sets `block.timestamp`. + function warp(uint256 newTimestamp) external; + + // ======== Testing ======== + + /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. + function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; + + /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. + function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) + external; + + /// Expects a call to an address with the specified calldata. + /// Calldata can either be a strict or a partial match. + function expectCall(address callee, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified calldata. + function expectCall(address callee, bytes calldata data, uint64 count) external; + + /// Expects a call to an address with the specified `msg.value` and calldata. + function expectCall(address callee, uint256 msgValue, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified `msg.value` and calldata. + function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; + + /// Expect a call to an address with the specified `msg.value`, gas, and calldata. + function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; + + /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. + function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; + + /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). + /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). + function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) + external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmitAnonymous( + bool checkTopic0, + bool checkTopic1, + bool checkTopic2, + bool checkTopic3, + bool checkData, + address emitter + ) external; + + /// Prepare an expected anonymous log with all topic and data checks enabled. + /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data. + function expectEmitAnonymous() external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmitAnonymous(address emitter) external; + + /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). + /// Call this function, then emit an event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). + function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) + external; + + /// Prepare an expected log with all topic and data checks enabled. + /// Call this function, then emit an event, then call a function. Internally after the call, we check if + /// logs were emitted in the expected order with the expected topics and data. + function expectEmit() external; + + /// Same as the previous method, but also checks supplied address against emitting contract. + function expectEmit(address emitter) external; + + /// Expects an error on next call that starts with the revert data. + function expectPartialRevert(bytes4 revertData) external; + + /// Expects an error on next call to reverter address, that starts with the revert data. + function expectPartialRevert(bytes4 revertData, address reverter) external; + + /// Expects an error on next call with any revert data. + function expectRevert() external; + + /// Expects an error on next call that exactly matches the revert data. + function expectRevert(bytes4 revertData) external; + + /// Expects an error on next call that exactly matches the revert data. + function expectRevert(bytes calldata revertData) external; + + /// Expects an error with any revert data on next call to reverter address. + function expectRevert(address reverter) external; + + /// Expects an error from reverter address on next call, with any revert data. + function expectRevert(bytes4 revertData, address reverter) external; + + /// Expects an error from reverter address on next call, that exactly matches the revert data. + function expectRevert(bytes calldata revertData, address reverter) external; + + /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other + /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. + function expectSafeMemory(uint64 min, uint64 max) external; + + /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. + /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges + /// to the set. + function expectSafeMemoryCall(uint64 min, uint64 max) external; + + /// Marks a test as skipped. Must be called at the top level of a test. + function skip(bool skipTest) external; + + /// Marks a test as skipped with a reason. Must be called at the top level of a test. + function skip(bool skipTest, string calldata reason) external; + + /// Stops all safe memory expectation in the current subcontext. + function stopExpectSafeMemory() external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol new file mode 100644 index 0000000..4fdb667 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol @@ -0,0 +1,1560 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +library console { + address constant CONSOLE_ADDRESS = + 0x000000000000000000636F6e736F6c652e6c6f67; + + function _sendLogPayloadImplementation(bytes memory payload) internal view { + address consoleAddress = CONSOLE_ADDRESS; + /// @solidity memory-safe-assembly + assembly { + pop( + staticcall( + gas(), + consoleAddress, + add(payload, 32), + mload(payload), + 0, + 0 + ) + ) + } + } + + function _castToPure( + function(bytes memory) internal view fnIn + ) internal pure returns (function(bytes memory) pure fnOut) { + assembly { + fnOut := fnIn + } + } + + function _sendLogPayload(bytes memory payload) internal pure { + _castToPure(_sendLogPayloadImplementation)(payload); + } + + function log() internal pure { + _sendLogPayload(abi.encodeWithSignature("log()")); + } + + function logInt(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function logUint(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); + } + + function logString(string memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function logBool(bool p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function logAddress(address p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function logBytes(bytes memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); + } + + function logBytes1(bytes1 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); + } + + function logBytes2(bytes2 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); + } + + function logBytes3(bytes3 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); + } + + function logBytes4(bytes4 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); + } + + function logBytes5(bytes5 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); + } + + function logBytes6(bytes6 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); + } + + function logBytes7(bytes7 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); + } + + function logBytes8(bytes8 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); + } + + function logBytes9(bytes9 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); + } + + function logBytes10(bytes10 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); + } + + function logBytes11(bytes11 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); + } + + function logBytes12(bytes12 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); + } + + function logBytes13(bytes13 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); + } + + function logBytes14(bytes14 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); + } + + function logBytes15(bytes15 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); + } + + function logBytes16(bytes16 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); + } + + function logBytes17(bytes17 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); + } + + function logBytes18(bytes18 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); + } + + function logBytes19(bytes19 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); + } + + function logBytes20(bytes20 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); + } + + function logBytes21(bytes21 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); + } + + function logBytes22(bytes22 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); + } + + function logBytes23(bytes23 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); + } + + function logBytes24(bytes24 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); + } + + function logBytes25(bytes25 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); + } + + function logBytes26(bytes26 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); + } + + function logBytes27(bytes27 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); + } + + function logBytes28(bytes28 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); + } + + function logBytes29(bytes29 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); + } + + function logBytes30(bytes30 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); + } + + function logBytes31(bytes31 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); + } + + function logBytes32(bytes32 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); + } + + function log(uint256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); + } + + function log(int256 p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); + } + + function log(string memory p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); + } + + function log(bool p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); + } + + function log(address p0) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); + } + + function log(uint256 p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); + } + + function log(uint256 p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); + } + + function log(uint256 p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); + } + + function log(uint256 p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); + } + + function log(string memory p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); + } + + function log(string memory p0, int256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); + } + + function log(string memory p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); + } + + function log(string memory p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); + } + + function log(string memory p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); + } + + function log(bool p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); + } + + function log(bool p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); + } + + function log(bool p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); + } + + function log(bool p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); + } + + function log(address p0, uint256 p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); + } + + function log(address p0, string memory p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); + } + + function log(address p0, bool p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); + } + + function log(address p0, address p1) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); + } + + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); + } + + function log(uint256 p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); + } + + function log(uint256 p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); + } + + function log(uint256 p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); + } + + function log(string memory p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); + } + + function log(string memory p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); + } + + function log(string memory p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); + } + + function log(string memory p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); + } + + function log(string memory p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); + } + + function log(string memory p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); + } + + function log(string memory p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); + } + + function log(bool p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); + } + + function log(bool p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); + } + + function log(bool p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); + } + + function log(bool p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); + } + + function log(bool p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); + } + + function log(bool p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); + } + + function log(bool p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); + } + + function log(bool p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); + } + + function log(bool p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); + } + + function log(bool p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); + } + + function log(address p0, uint256 p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); + } + + function log(address p0, string memory p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); + } + + function log(address p0, string memory p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); + } + + function log(address p0, string memory p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); + } + + function log(address p0, string memory p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); + } + + function log(address p0, bool p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); + } + + function log(address p0, bool p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); + } + + function log(address p0, bool p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); + } + + function log(address p0, bool p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); + } + + function log(address p0, address p1, uint256 p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); + } + + function log(address p0, address p1, string memory p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); + } + + function log(address p0, address p1, bool p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); + } + + function log(address p0, address p1, address p2) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); + } + + function log(uint256 p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); + } + + function log(string memory p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); + } + + function log(bool p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, uint256 p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, string memory p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, bool p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, uint256 p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, string memory p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, bool p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, uint256 p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, string memory p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, bool p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); + } + + function log(address p0, address p1, address p2, address p3) internal pure { + _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol new file mode 100644 index 0000000..03531d9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.4.22 <0.9.0; + +import {console as console2} from "./console.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol new file mode 100644 index 0000000..f7dd2b4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC165.sol"; + +/// @title ERC-1155 Multi Token Standard +/// @dev See https://eips.ethereum.org/EIPS/eip-1155 +/// Note: The ERC-165 identifier for this interface is 0xd9b67a26. +interface IERC1155 is IERC165 { + /// @dev + /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). + /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). + /// - The `_from` argument MUST be the address of the holder whose balance is decreased. + /// - The `_to` argument MUST be the address of the recipient whose balance is increased. + /// - The `_id` argument MUST be the token type being transferred. + /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. + /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). + /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). + event TransferSingle( + address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value + ); + + /// @dev + /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). + /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). + /// - The `_from` argument MUST be the address of the holder whose balance is decreased. + /// - The `_to` argument MUST be the address of the recipient whose balance is increased. + /// - The `_ids` argument MUST be the list of tokens being transferred. + /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. + /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). + /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). + event TransferBatch( + address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values + ); + + /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + + /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. + /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". + event URI(string _value, uint256 indexed _id); + + /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). + /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). + /// - MUST revert if `_to` is the zero address. + /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent. + /// - MUST revert on any other error. + /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). + /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). + /// @param _from Source address + /// @param _to Target address + /// @param _id ID of the token type + /// @param _value Transfer amount + /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` + function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; + + /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). + /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). + /// - MUST revert if `_to` is the zero address. + /// - MUST revert if length of `_ids` is not the same as length of `_values`. + /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. + /// - MUST revert on any other error. + /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). + /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). + /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). + /// @param _from Source address + /// @param _to Target address + /// @param _ids IDs of each token type (order and length must match _values array) + /// @param _values Transfer amounts per token type (order and length must match _ids array) + /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` + function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) external; + + /// @notice Get the balance of an account's tokens. + /// @param _owner The address of the token holder + /// @param _id ID of the token + /// @return The _owner's balance of the token type requested + function balanceOf(address _owner, uint256 _id) external view returns (uint256); + + /// @notice Get the balance of multiple account/token pairs + /// @param _owners The addresses of the token holders + /// @param _ids ID of the tokens + /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + returns (uint256[] memory); + + /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. + /// @dev MUST emit the ApprovalForAll event on success. + /// @param _operator Address to add to the set of authorized operators + /// @param _approved True if the operator is approved, false to revoke approval + function setApprovalForAll(address _operator, bool _approved) external; + + /// @notice Queries the approval status of an operator for a given owner. + /// @param _owner The owner of the tokens + /// @param _operator Address of authorized operator + /// @return True if the operator is approved, false if not + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol new file mode 100644 index 0000000..9af4bf8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +interface IERC165 { + /// @notice Query if a contract implements an interface + /// @param interfaceID The interface identifier, as specified in ERC-165 + /// @dev Interface identification is specified in ERC-165. This function + /// uses less than 30,000 gas. + /// @return `true` if the contract implements `interfaceID` and + /// `interfaceID` is not 0xffffffff, `false` otherwise + function supportsInterface(bytes4 interfaceID) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol new file mode 100644 index 0000000..ba40806 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +/// @dev Interface of the ERC20 standard as defined in the EIP. +/// @dev This includes the optional name, symbol, and decimals metadata. +interface IERC20 { + /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). + event Transfer(address indexed from, address indexed to, uint256 value); + + /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` + /// is the new allowance. + event Approval(address indexed owner, address indexed spender, uint256 value); + + /// @notice Returns the amount of tokens in existence. + function totalSupply() external view returns (uint256); + + /// @notice Returns the amount of tokens owned by `account`. + function balanceOf(address account) external view returns (uint256); + + /// @notice Moves `amount` tokens from the caller's account to `to`. + function transfer(address to, uint256 amount) external returns (bool); + + /// @notice Returns the remaining number of tokens that `spender` is allowed + /// to spend on behalf of `owner` + function allowance(address owner, address spender) external view returns (uint256); + + /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. + /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + function approve(address spender, uint256 amount) external returns (bool); + + /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. + /// `amount` is then deducted from the caller's allowance. + function transferFrom(address from, address to, uint256 amount) external returns (bool); + + /// @notice Returns the name of the token. + function name() external view returns (string memory); + + /// @notice Returns the symbol of the token. + function symbol() external view returns (string memory); + + /// @notice Returns the decimals places of the token. + function decimals() external view returns (uint8); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol new file mode 100644 index 0000000..391eeb4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC20.sol"; + +/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in +/// https://eips.ethereum.org/EIPS/eip-4626 +interface IERC4626 is IERC20 { + event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); + + event Withdraw( + address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares + ); + + /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. + /// @dev + /// - MUST be an ERC-20 token contract. + /// - MUST NOT revert. + function asset() external view returns (address assetTokenAddress); + + /// @notice Returns the total amount of the underlying asset that is “managed” by Vault. + /// @dev + /// - SHOULD include any compounding that occurs from yield. + /// - MUST be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT revert. + function totalAssets() external view returns (uint256 totalManagedAssets); + + /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal + /// scenario where all the conditions are met. + /// @dev + /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT show any variations depending on the caller. + /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + /// - MUST NOT revert. + /// + /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + /// from. + function convertToShares(uint256 assets) external view returns (uint256 shares); + + /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal + /// scenario where all the conditions are met. + /// @dev + /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. + /// - MUST NOT show any variations depending on the caller. + /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. + /// - MUST NOT revert. + /// + /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the + /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and + /// from. + function convertToAssets(uint256 shares) external view returns (uint256 assets); + + /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, + /// through a deposit call. + /// @dev + /// - MUST return a limited value if receiver is subject to some deposit limit. + /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. + /// - MUST NOT revert. + function maxDeposit(address receiver) external view returns (uint256 maxAssets); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given + /// current on-chain conditions. + /// @dev + /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit + /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called + /// in the same transaction. + /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the + /// deposit would be accepted, regardless if the user has enough tokens approved, etc. + /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by depositing. + function previewDeposit(uint256 assets) external view returns (uint256 shares); + + /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. + /// @dev + /// - MUST emit the Deposit event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// deposit execution, and are accounted for during deposit. + /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not + /// approving enough underlying tokens to the Vault contract, etc). + /// + /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + function deposit(uint256 assets, address receiver) external returns (uint256 shares); + + /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. + /// @dev + /// - MUST return a limited value if receiver is subject to some mint limit. + /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. + /// - MUST NOT revert. + function maxMint(address receiver) external view returns (uint256 maxShares); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given + /// current on-chain conditions. + /// @dev + /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call + /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the + /// same transaction. + /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint + /// would be accepted, regardless if the user has enough tokens approved, etc. + /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by minting. + function previewMint(uint256 shares) external view returns (uint256 assets); + + /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. + /// @dev + /// - MUST emit the Deposit event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint + /// execution, and are accounted for during mint. + /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not + /// approving enough underlying tokens to the Vault contract, etc). + /// + /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. + function mint(uint256 shares, address receiver) external returns (uint256 assets); + + /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the + /// Vault, through a withdrawal call. + /// @dev + /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + /// - MUST NOT revert. + function maxWithdraw(address owner) external view returns (uint256 maxAssets); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, + /// given current on-chain conditions. + /// @dev + /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw + /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if + /// called + /// in the same transaction. + /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though + /// the withdrawal would be accepted, regardless if the user has enough shares, etc. + /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by depositing. + function previewWithdraw(uint256 assets) external view returns (uint256 shares); + + /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. + /// @dev + /// - MUST emit the Withdraw event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// withdraw execution, and are accounted for during withdrawal. + /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner + /// not having enough shares, etc). + /// + /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + /// Those methods should be performed separately. + function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); + + /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, + /// through a redeem call. + /// @dev + /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. + /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. + /// - MUST NOT revert. + function maxRedeem(address owner) external view returns (uint256 maxShares); + + /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, + /// given current on-chain conditions. + /// @dev + /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call + /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the + /// same transaction. + /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the + /// redemption would be accepted, regardless if the user has enough shares, etc. + /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. + /// - MUST NOT revert. + /// + /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in + /// share price or some other type of condition, meaning the depositor will lose assets by redeeming. + function previewRedeem(uint256 shares) external view returns (uint256 assets); + + /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. + /// @dev + /// - MUST emit the Withdraw event. + /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the + /// redeem execution, and are accounted for during redeem. + /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner + /// not having enough shares, etc). + /// + /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. + /// Those methods should be performed separately. + function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol new file mode 100644 index 0000000..0a16f45 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2; + +import "./IERC165.sol"; + +/// @title ERC-721 Non-Fungible Token Standard +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x80ac58cd. +interface IERC721 is IERC165 { + /// @dev This emits when ownership of any NFT changes by any mechanism. + /// This event emits when NFTs are created (`from` == 0) and destroyed + /// (`to` == 0). Exception: during contract creation, any number of NFTs + /// may be created and assigned without emitting Transfer. At the time of + /// any transfer, the approved address for that NFT (if any) is reset to none. + event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + + /// @dev This emits when the approved address for an NFT is changed or + /// reaffirmed. The zero address indicates there is no approved address. + /// When a Transfer event emits, this also indicates that the approved + /// address for that NFT (if any) is reset to none. + event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + + /// @dev This emits when an operator is enabled or disabled for an owner. + /// The operator can manage all NFTs of the owner. + event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + + /// @notice Count all NFTs assigned to an owner + /// @dev NFTs assigned to the zero address are considered invalid, and this + /// function throws for queries about the zero address. + /// @param _owner An address for whom to query the balance + /// @return The number of NFTs owned by `_owner`, possibly zero + function balanceOf(address _owner) external view returns (uint256); + + /// @notice Find the owner of an NFT + /// @dev NFTs assigned to zero address are considered invalid, and queries + /// about them do throw. + /// @param _tokenId The identifier for an NFT + /// @return The address of the owner of the NFT + function ownerOf(uint256 _tokenId) external view returns (address); + + /// @notice Transfers the ownership of an NFT from one address to another address + /// @dev Throws unless `msg.sender` is the current owner, an authorized + /// operator, or the approved address for this NFT. Throws if `_from` is + /// not the current owner. Throws if `_to` is the zero address. Throws if + /// `_tokenId` is not a valid NFT. When transfer is complete, this function + /// checks if `_to` is a smart contract (code size > 0). If so, it calls + /// `onERC721Received` on `_to` and throws if the return value is not + /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + /// @param data Additional data with no specified format, sent in call to `_to` + function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; + + /// @notice Transfers the ownership of an NFT from one address to another address + /// @dev This works identically to the other function with an extra data parameter, + /// except this function just sets data to "". + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; + + /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE + /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE + /// THEY MAY BE PERMANENTLY LOST + /// @dev Throws unless `msg.sender` is the current owner, an authorized + /// operator, or the approved address for this NFT. Throws if `_from` is + /// not the current owner. Throws if `_to` is the zero address. Throws if + /// `_tokenId` is not a valid NFT. + /// @param _from The current owner of the NFT + /// @param _to The new owner + /// @param _tokenId The NFT to transfer + function transferFrom(address _from, address _to, uint256 _tokenId) external payable; + + /// @notice Change or reaffirm the approved address for an NFT + /// @dev The zero address indicates there is no approved address. + /// Throws unless `msg.sender` is the current NFT owner, or an authorized + /// operator of the current owner. + /// @param _approved The new approved NFT controller + /// @param _tokenId The NFT to approve + function approve(address _approved, uint256 _tokenId) external payable; + + /// @notice Enable or disable approval for a third party ("operator") to manage + /// all of `msg.sender`'s assets + /// @dev Emits the ApprovalForAll event. The contract MUST allow + /// multiple operators per owner. + /// @param _operator Address to add to the set of authorized operators + /// @param _approved True if the operator is approved, false to revoke approval + function setApprovalForAll(address _operator, bool _approved) external; + + /// @notice Get the approved address for a single NFT + /// @dev Throws if `_tokenId` is not a valid NFT. + /// @param _tokenId The NFT to find the approved address for + /// @return The approved address for this NFT, or the zero address if there is none + function getApproved(uint256 _tokenId) external view returns (address); + + /// @notice Query if an address is an authorized operator for another address + /// @param _owner The address that owns the NFTs + /// @param _operator The address that acts on behalf of the owner + /// @return True if `_operator` is an approved operator for `_owner`, false otherwise + function isApprovedForAll(address _owner, address _operator) external view returns (bool); +} + +/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. +interface IERC721TokenReceiver { + /// @notice Handle the receipt of an NFT + /// @dev The ERC721 smart contract calls this function on the recipient + /// after a `transfer`. This function MAY throw to revert and reject the + /// transfer. Return of other than the magic value MUST result in the + /// transaction being reverted. + /// Note: the contract address is always the message sender. + /// @param _operator The address which called `safeTransferFrom` function + /// @param _from The address which previously owned the token + /// @param _tokenId The NFT identifier which is being transferred + /// @param _data Additional data with no specified format + /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` + /// unless throwing + function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) + external + returns (bytes4); +} + +/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x5b5e139f. +interface IERC721Metadata is IERC721 { + /// @notice A descriptive name for a collection of NFTs in this contract + function name() external view returns (string memory _name); + + /// @notice An abbreviated name for NFTs in this contract + function symbol() external view returns (string memory _symbol); + + /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. + /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC + /// 3986. The URI may point to a JSON file that conforms to the "ERC721 + /// Metadata JSON Schema". + function tokenURI(uint256 _tokenId) external view returns (string memory); +} + +/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension +/// @dev See https://eips.ethereum.org/EIPS/eip-721 +/// Note: the ERC-165 identifier for this interface is 0x780e9d63. +interface IERC721Enumerable is IERC721 { + /// @notice Count NFTs tracked by this contract + /// @return A count of valid NFTs tracked by this contract, where each one of + /// them has an assigned and queryable owner not equal to the zero address + function totalSupply() external view returns (uint256); + + /// @notice Enumerate valid NFTs + /// @dev Throws if `_index` >= `totalSupply()`. + /// @param _index A counter less than `totalSupply()` + /// @return The token identifier for the `_index`th NFT, + /// (sort order not specified) + function tokenByIndex(uint256 _index) external view returns (uint256); + + /// @notice Enumerate NFTs assigned to an owner + /// @dev Throws if `_index` >= `balanceOf(_owner)` or if + /// `_owner` is the zero address, representing invalid NFTs. + /// @param _owner An address where we are interested in NFTs owned by them + /// @param _index A counter less than `balanceOf(_owner)` + /// @return The token identifier for the `_index`th NFT assigned to `_owner`, + /// (sort order not specified) + function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol new file mode 100644 index 0000000..0d031b7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +pragma experimental ABIEncoderV2; + +interface IMulticall3 { + struct Call { + address target; + bytes callData; + } + + struct Call3 { + address target; + bool allowFailure; + bytes callData; + } + + struct Call3Value { + address target; + bool allowFailure; + uint256 value; + bytes callData; + } + + struct Result { + bool success; + bytes returnData; + } + + function aggregate(Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes[] memory returnData); + + function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); + + function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); + + function blockAndAggregate(Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); + + function getBasefee() external view returns (uint256 basefee); + + function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); + + function getBlockNumber() external view returns (uint256 blockNumber); + + function getChainId() external view returns (uint256 chainid); + + function getCurrentBlockCoinbase() external view returns (address coinbase); + + function getCurrentBlockDifficulty() external view returns (uint256 difficulty); + + function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); + + function getCurrentBlockTimestamp() external view returns (uint256 timestamp); + + function getEthBalance(address addr) external view returns (uint256 balance); + + function getLastBlockHash() external view returns (bytes32 blockHash); + + function tryAggregate(bool requireSuccess, Call[] calldata calls) + external + payable + returns (Result[] memory returnData); + + function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) + external + payable + returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol new file mode 100644 index 0000000..2a022fa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {IERC20} from "../interfaces/IERC20.sol"; + +/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. +/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol +contract MockERC20 is IERC20 { + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string internal _name; + + string internal _symbol; + + uint8 internal _decimals; + + function name() external view override returns (string memory) { + return _name; + } + + function symbol() external view override returns (string memory) { + return _symbol; + } + + function decimals() external view override returns (uint8) { + return _decimals; + } + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal _totalSupply; + + mapping(address => uint256) internal _balanceOf; + + mapping(address => mapping(address => uint256)) internal _allowance; + + function totalSupply() external view override returns (uint256) { + return _totalSupply; + } + + function balanceOf(address owner) external view override returns (uint256) { + return _balanceOf[owner]; + } + + function allowance(address owner, address spender) external view override returns (uint256) { + return _allowance[owner][spender]; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + INITIALIZE + //////////////////////////////////////////////////////////////*/ + + /// @dev A bool to track whether the contract has been initialized. + bool private initialized; + + /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and + /// syntaxes, we add an initialization function that can be called only once. + function initialize(string memory name_, string memory symbol_, uint8 decimals_) public { + require(!initialized, "ALREADY_INITIALIZED"); + + _name = name_; + _symbol = symbol_; + _decimals = decimals_; + + INITIAL_CHAIN_ID = _pureChainId(); + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + + initialized = true; + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public virtual override returns (bool) { + _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); + + _balanceOf[from] = _sub(_balanceOf[from], amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) + public + virtual + { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + _allowance[recoveredAddress][spender] = value; + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { + return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view virtual returns (bytes32) { + return keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(_name)), + keccak256("1"), + _pureChainId(), + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal virtual { + _totalSupply = _add(_totalSupply, amount); + _balanceOf[to] = _add(_balanceOf[to], amount); + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal virtual { + _balanceOf[from] = _sub(_balanceOf[from], amount); + _totalSupply = _sub(_totalSupply, amount); + + emit Transfer(from, address(0), amount); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL SAFE MATH LOGIC + //////////////////////////////////////////////////////////////*/ + + function _add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "ERC20: addition overflow"); + return c; + } + + function _sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(a >= b, "ERC20: subtraction underflow"); + return a - b; + } + + /*////////////////////////////////////////////////////////////// + HELPERS + //////////////////////////////////////////////////////////////*/ + + // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no + // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We + // can't simply access the chain ID in a normal view or pure function because the solc View Pure + // Checker changed `chainid` from pure to view in 0.8.0. + function _viewChainId() private view returns (uint256 chainId) { + // Assembly required since `block.chainid` was introduced in 0.8.0. + assembly { + chainId := chainid() + } + + address(this); // Silence warnings in older Solc versions. + } + + function _pureChainId() private pure returns (uint256 chainId) { + function() internal view returns (uint256) fnIn = _viewChainId; + function() internal pure returns (uint256) pureChainId; + assembly { + pureChainId := fnIn + } + chainId = pureChainId(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol new file mode 100644 index 0000000..7a4909e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol"; + +/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. +/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol +contract MockERC721 is IERC721Metadata { + /*////////////////////////////////////////////////////////////// + METADATA STORAGE/LOGIC + //////////////////////////////////////////////////////////////*/ + + string internal _name; + + string internal _symbol; + + function name() external view override returns (string memory) { + return _name; + } + + function symbol() external view override returns (string memory) { + return _symbol; + } + + function tokenURI(uint256 id) public view virtual override returns (string memory) {} + + /*////////////////////////////////////////////////////////////// + ERC721 BALANCE/OWNER STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) internal _ownerOf; + + mapping(address => uint256) internal _balanceOf; + + function ownerOf(uint256 id) public view virtual override returns (address owner) { + require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); + } + + function balanceOf(address owner) public view virtual override returns (uint256) { + require(owner != address(0), "ZERO_ADDRESS"); + + return _balanceOf[owner]; + } + + /*////////////////////////////////////////////////////////////// + ERC721 APPROVAL STORAGE + //////////////////////////////////////////////////////////////*/ + + mapping(uint256 => address) internal _getApproved; + + mapping(address => mapping(address => bool)) internal _isApprovedForAll; + + function getApproved(uint256 id) public view virtual override returns (address) { + return _getApproved[id]; + } + + function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { + return _isApprovedForAll[owner][operator]; + } + + /*////////////////////////////////////////////////////////////// + INITIALIZE + //////////////////////////////////////////////////////////////*/ + + /// @dev A bool to track whether the contract has been initialized. + bool private initialized; + + /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and + /// syntaxes, we add an initialization function that can be called only once. + function initialize(string memory name_, string memory symbol_) public { + require(!initialized, "ALREADY_INITIALIZED"); + + _name = name_; + _symbol = symbol_; + + initialized = true; + } + + /*////////////////////////////////////////////////////////////// + ERC721 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 id) public payable virtual override { + address owner = _ownerOf[id]; + + require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); + + _getApproved[id] = spender; + + emit Approval(owner, spender, id); + } + + function setApprovalForAll(address operator, bool approved) public virtual override { + _isApprovedForAll[msg.sender][operator] = approved; + + emit ApprovalForAll(msg.sender, operator, approved); + } + + function transferFrom(address from, address to, uint256 id) public payable virtual override { + require(from == _ownerOf[id], "WRONG_FROM"); + + require(to != address(0), "INVALID_RECIPIENT"); + + require( + msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], + "NOT_AUTHORIZED" + ); + + // Underflow of the sender's balance is impossible because we check for + // ownership above and the recipient's balance can't realistically overflow. + _balanceOf[from]--; + + _balanceOf[to]++; + + _ownerOf[id] = to; + + delete _getApproved[id]; + + emit Transfer(from, to, id); + } + + function safeTransferFrom(address from, address to, uint256 id) public payable virtual override { + transferFrom(from, to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function safeTransferFrom(address from, address to, uint256 id, bytes memory data) + public + payable + virtual + override + { + transferFrom(from, to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + /*////////////////////////////////////////////////////////////// + ERC165 LOGIC + //////////////////////////////////////////////////////////////*/ + + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 + || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 + || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 id) internal virtual { + require(to != address(0), "INVALID_RECIPIENT"); + + require(_ownerOf[id] == address(0), "ALREADY_MINTED"); + + // Counter overflow is incredibly unrealistic. + + _balanceOf[to]++; + + _ownerOf[id] = to; + + emit Transfer(address(0), to, id); + } + + function _burn(uint256 id) internal virtual { + address owner = _ownerOf[id]; + + require(owner != address(0), "NOT_MINTED"); + + _balanceOf[owner]--; + + delete _ownerOf[id]; + + delete _getApproved[id]; + + emit Transfer(owner, address(0), id); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL SAFE MINT LOGIC + //////////////////////////////////////////////////////////////*/ + + function _safeMint(address to, uint256 id) internal virtual { + _mint(to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + function _safeMint(address to, uint256 id, bytes memory data) internal virtual { + _mint(to, id); + + require( + !_isContract(to) + || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) + == IERC721TokenReceiver.onERC721Received.selector, + "UNSAFE_RECIPIENT" + ); + } + + /*////////////////////////////////////////////////////////////// + HELPERS + //////////////////////////////////////////////////////////////*/ + + function _isContract(address _addr) private view returns (bool) { + uint256 codeLength; + + // Assembly required for versions < 0.8.0 to check extcodesize. + assembly { + codeLength := extcodesize(_addr) + } + + return codeLength > 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol new file mode 100644 index 0000000..87c475a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol @@ -0,0 +1,13937 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.2 <0.9.0; + +/// @author philogy +/// @dev Code generated automatically by script. +library safeconsole { + uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; + + // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) + // for the view-to-pure log trick. + function _sendLogPayload(uint256 offset, uint256 size) private pure { + function(uint256, uint256) internal view fnIn = _sendLogPayloadView; + function(uint256, uint256) internal pure pureSendLogPayload; + /// @solidity memory-safe-assembly + assembly { + pureSendLogPayload := fnIn + } + pureSendLogPayload(offset, size); + } + + function _sendLogPayloadView(uint256 offset, uint256 size) private view { + /// @solidity memory-safe-assembly + assembly { + pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) + } + } + + function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { + function(uint256, uint256, uint256) internal view fnIn = _memcopyView; + function(uint256, uint256, uint256) internal pure pureMemcopy; + /// @solidity memory-safe-assembly + assembly { + pureMemcopy := fnIn + } + pureMemcopy(fromOffset, toOffset, length); + } + + function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { + /// @solidity memory-safe-assembly + assembly { + pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) + } + } + + function logMemory(uint256 offset, uint256 length) internal pure { + if (offset >= 0x60) { + // Sufficient memory before slice to prepare call header. + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(sub(offset, 0x60)) + m1 := mload(sub(offset, 0x40)) + m2 := mload(sub(offset, 0x20)) + // Selector of `log(bytes)`. + mstore(sub(offset, 0x60), 0x0be77f56) + mstore(sub(offset, 0x40), 0x20) + mstore(sub(offset, 0x20), length) + } + _sendLogPayload(offset - 0x44, length + 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(sub(offset, 0x60), m0) + mstore(sub(offset, 0x40), m1) + mstore(sub(offset, 0x20), m2) + } + } else { + // Insufficient space, so copy slice forward, add header and reverse. + bytes32 m0; + bytes32 m1; + bytes32 m2; + uint256 endOffset = offset + length; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(add(endOffset, 0x00)) + m1 := mload(add(endOffset, 0x20)) + m2 := mload(add(endOffset, 0x40)) + } + _memcopy(offset, offset + 0x60, length); + /// @solidity memory-safe-assembly + assembly { + // Selector of `log(bytes)`. + mstore(add(offset, 0x00), 0x0be77f56) + mstore(add(offset, 0x20), 0x20) + mstore(add(offset, 0x40), length) + } + _sendLogPayload(offset + 0x1c, length + 0x44); + _memcopy(offset + 0x60, offset, length); + /// @solidity memory-safe-assembly + assembly { + mstore(add(endOffset, 0x00), m0) + mstore(add(endOffset, 0x20), m1) + mstore(add(endOffset, 0x40), m2) + } + } + } + + function log(address p0) internal pure { + bytes32 m0; + bytes32 m1; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(address)`. + mstore(0x00, 0x2c2ecbc2) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(bool p0) internal pure { + bytes32 m0; + bytes32 m1; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(bool)`. + mstore(0x00, 0x32458eed) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(uint256 p0) internal pure { + bytes32 m0; + bytes32 m1; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + // Selector of `log(uint256)`. + mstore(0x00, 0xf82c50f1) + mstore(0x20, p0) + } + _sendLogPayload(0x1c, 0x24); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + } + } + + function log(bytes32 p0) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(string)`. + mstore(0x00, 0x41304fac) + mstore(0x20, 0x20) + writeString(0x40, p0) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,address)`. + mstore(0x00, 0xdaf0d4aa) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,bool)`. + mstore(0x00, 0x75b605d3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(address,uint256)`. + mstore(0x00, 0x8309e8a8) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(address p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,string)`. + mstore(0x00, 0x759f86bb) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,address)`. + mstore(0x00, 0x853c4849) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,bool)`. + mstore(0x00, 0x2a110e83) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(bool,uint256)`. + mstore(0x00, 0x399174d3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(bool p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,string)`. + mstore(0x00, 0x8feac525) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,address)`. + mstore(0x00, 0x69276c86) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,bool)`. + mstore(0x00, 0x1c9d7eb3) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + // Selector of `log(uint256,uint256)`. + mstore(0x00, 0xf666715a) + mstore(0x20, p0) + mstore(0x40, p1) + } + _sendLogPayload(0x1c, 0x44); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + } + } + + function log(uint256 p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,string)`. + mstore(0x00, 0x643fd0df) + mstore(0x20, p0) + mstore(0x40, 0x40) + writeString(0x60, p1) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, address p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,address)`. + mstore(0x00, 0x319af333) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, bool p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,bool)`. + mstore(0x00, 0xc3b55635) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, uint256 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(string,uint256)`. + mstore(0x00, 0xb60e72cc) + mstore(0x20, 0x40) + mstore(0x40, p1) + writeString(0x60, p0) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bytes32 p0, bytes32 p1) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,string)`. + mstore(0x00, 0x4b5c4277) + mstore(0x20, 0x40) + mstore(0x40, 0x80) + writeString(0x60, p0) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,address)`. + mstore(0x00, 0x018c84c2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,bool)`. + mstore(0x00, 0xf2a66286) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,address,uint256)`. + mstore(0x00, 0x17fe6185) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,address,string)`. + mstore(0x00, 0x007150be) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,address)`. + mstore(0x00, 0xf11699ed) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,bool)`. + mstore(0x00, 0xeb830c92) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,bool,uint256)`. + mstore(0x00, 0x9c4f99fb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,bool,string)`. + mstore(0x00, 0x212255cc) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,address)`. + mstore(0x00, 0x7bc0d848) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,bool)`. + mstore(0x00, 0x678209a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(address,uint256,uint256)`. + mstore(0x00, 0xb69bcaf6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(address p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,uint256,string)`. + mstore(0x00, 0xa1f2e8aa) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,address)`. + mstore(0x00, 0xf08744e8) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,bool)`. + mstore(0x00, 0xcf020fb1) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(address,string,uint256)`. + mstore(0x00, 0x67dd6ff1) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(address p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(address,string,string)`. + mstore(0x00, 0xfb772265) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bool p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,address)`. + mstore(0x00, 0xd2763667) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,bool)`. + mstore(0x00, 0x18c9c746) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,address,uint256)`. + mstore(0x00, 0x5f7b9afb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,address,string)`. + mstore(0x00, 0xde9a9270) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,address)`. + mstore(0x00, 0x1078f68d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,bool)`. + mstore(0x00, 0x50709698) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,bool,uint256)`. + mstore(0x00, 0x12f21602) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,bool,string)`. + mstore(0x00, 0x2555fa46) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,address)`. + mstore(0x00, 0x088ef9d2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,bool)`. + mstore(0x00, 0xe8defba9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(bool,uint256,uint256)`. + mstore(0x00, 0x37103367) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(bool p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,uint256,string)`. + mstore(0x00, 0xc3fc3970) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,address)`. + mstore(0x00, 0x9591b953) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,bool)`. + mstore(0x00, 0xdbb4c247) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(bool,string,uint256)`. + mstore(0x00, 0x1093ee11) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(bool,string,string)`. + mstore(0x00, 0xb076847f) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(uint256 p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,address)`. + mstore(0x00, 0xbcfd9be0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,bool)`. + mstore(0x00, 0x9b6ec042) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,address,uint256)`. + mstore(0x00, 0x5a9b5ed5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,address,string)`. + mstore(0x00, 0x63cb41f9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,address)`. + mstore(0x00, 0x35085f7b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,bool)`. + mstore(0x00, 0x20718650) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,bool,uint256)`. + mstore(0x00, 0x20098014) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,bool,string)`. + mstore(0x00, 0x85775021) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,address)`. + mstore(0x00, 0x5c96b331) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,bool)`. + mstore(0x00, 0x4766da72) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + // Selector of `log(uint256,uint256,uint256)`. + mstore(0x00, 0xd1ed7a3c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + } + _sendLogPayload(0x1c, 0x64); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,uint256,string)`. + mstore(0x00, 0x71d04af2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x60) + writeString(0x80, p2) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,address)`. + mstore(0x00, 0x7afac959) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,bool)`. + mstore(0x00, 0x4ceda75a) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(uint256,string,uint256)`. + mstore(0x00, 0x37aa7d4c) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, p2) + writeString(0x80, p1) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(uint256,string,string)`. + mstore(0x00, 0xb115611f) + mstore(0x20, p0) + mstore(0x40, 0x60) + mstore(0x60, 0xa0) + writeString(0x80, p1) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, address p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,address)`. + mstore(0x00, 0xfcec75e0) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,bool)`. + mstore(0x00, 0xc91d5ed4) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,address,uint256)`. + mstore(0x00, 0x0d26b925) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, address p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,address,string)`. + mstore(0x00, 0xe0e9ad4f) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bool p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,address)`. + mstore(0x00, 0x932bbb38) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,bool)`. + mstore(0x00, 0x850b7ad6) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,bool,uint256)`. + mstore(0x00, 0xc95958d6) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,bool,string)`. + mstore(0x00, 0xe298f47d) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, uint256 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,address)`. + mstore(0x00, 0x1c7ec448) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,bool)`. + mstore(0x00, 0xca7733b1) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + // Selector of `log(string,uint256,uint256)`. + mstore(0x00, 0xca47c4eb) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, p2) + writeString(0x80, p0) + } + _sendLogPayload(0x1c, 0xa4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,uint256,string)`. + mstore(0x00, 0x5970e089) + mstore(0x20, 0x60) + mstore(0x40, p1) + mstore(0x60, 0xa0) + writeString(0x80, p0) + writeString(0xc0, p2) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, address p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,address)`. + mstore(0x00, 0x95ed0195) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,bool)`. + mstore(0x00, 0xb0e0f9b5) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + // Selector of `log(string,string,uint256)`. + mstore(0x00, 0x5821efa1) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, p2) + writeString(0x80, p0) + writeString(0xc0, p1) + } + _sendLogPayload(0x1c, 0xe4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + // Selector of `log(string,string,string)`. + mstore(0x00, 0x2ced7cef) + mstore(0x20, 0x60) + mstore(0x40, 0xa0) + mstore(0x60, 0xe0) + writeString(0x80, p0) + writeString(0xc0, p1) + writeString(0x100, p2) + } + _sendLogPayload(0x1c, 0x124); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + } + } + + function log(address p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,address)`. + mstore(0x00, 0x665bf134) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,bool)`. + mstore(0x00, 0x0e378994) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,address,uint256)`. + mstore(0x00, 0x94250d77) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,address,string)`. + mstore(0x00, 0xf808da20) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,address)`. + mstore(0x00, 0x9f1bc36e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,bool)`. + mstore(0x00, 0x2cd4134a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,bool,uint256)`. + mstore(0x00, 0x3971e78c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,bool,string)`. + mstore(0x00, 0xaa6540c8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,address)`. + mstore(0x00, 0x8da6def5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,bool)`. + mstore(0x00, 0x9b4254e2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,address,uint256,uint256)`. + mstore(0x00, 0xbe553481) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,uint256,string)`. + mstore(0x00, 0xfdb4f990) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,address)`. + mstore(0x00, 0x8f736d16) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,bool)`. + mstore(0x00, 0x6f1a594e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,address,string,uint256)`. + mstore(0x00, 0xef1cefe7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,address,string,string)`. + mstore(0x00, 0x21bdaf25) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,address)`. + mstore(0x00, 0x660375dd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,bool)`. + mstore(0x00, 0xa6f50b0f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,address,uint256)`. + mstore(0x00, 0xa75c59de) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,address,string)`. + mstore(0x00, 0x2dd778e6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,address)`. + mstore(0x00, 0xcf394485) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,bool)`. + mstore(0x00, 0xcac43479) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,bool,uint256)`. + mstore(0x00, 0x8c4e5de6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,bool,string)`. + mstore(0x00, 0xdfc4a2e8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,address)`. + mstore(0x00, 0xccf790a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,bool)`. + mstore(0x00, 0xc4643e20) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,bool,uint256,uint256)`. + mstore(0x00, 0x386ff5f4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,uint256,string)`. + mstore(0x00, 0x0aa6cfad) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,address)`. + mstore(0x00, 0x19fd4956) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,bool)`. + mstore(0x00, 0x50ad461d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,bool,string,uint256)`. + mstore(0x00, 0x80e6a20b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,bool,string,string)`. + mstore(0x00, 0x475c5c33) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,address)`. + mstore(0x00, 0x478d1c62) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,bool)`. + mstore(0x00, 0xa1bcc9b3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,address,uint256)`. + mstore(0x00, 0x100f650e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,address,string)`. + mstore(0x00, 0x1da986ea) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,address)`. + mstore(0x00, 0xa31bfdcc) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,bool)`. + mstore(0x00, 0x3bf5e537) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,bool,uint256)`. + mstore(0x00, 0x22f6b999) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,bool,string)`. + mstore(0x00, 0xc5ad85f9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,address)`. + mstore(0x00, 0x20e3984d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,bool)`. + mstore(0x00, 0x66f1bc67) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(address,uint256,uint256,uint256)`. + mstore(0x00, 0x34f0e636) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,uint256,string)`. + mstore(0x00, 0x4a28c017) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,address)`. + mstore(0x00, 0x5c430d47) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,bool)`. + mstore(0x00, 0xcf18105c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,uint256,string,uint256)`. + mstore(0x00, 0xbf01f891) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,uint256,string,string)`. + mstore(0x00, 0x88a8c406) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,address)`. + mstore(0x00, 0x0d36fa20) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,bool)`. + mstore(0x00, 0x0df12b76) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,address,uint256)`. + mstore(0x00, 0x457fe3cf) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,address,string)`. + mstore(0x00, 0xf7e36245) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,address)`. + mstore(0x00, 0x205871c2) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,bool)`. + mstore(0x00, 0x5f1d5c9f) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,bool,uint256)`. + mstore(0x00, 0x515e38b6) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,bool,string)`. + mstore(0x00, 0xbc0b61fe) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,address)`. + mstore(0x00, 0x63183678) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,bool)`. + mstore(0x00, 0x0ef7e050) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(address,string,uint256,uint256)`. + mstore(0x00, 0x1dc8e1b8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,uint256,string)`. + mstore(0x00, 0x448830a8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,address)`. + mstore(0x00, 0xa04e2f87) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,bool)`. + mstore(0x00, 0x35a5071f) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(address,string,string,uint256)`. + mstore(0x00, 0x159f8927) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(address,string,string,string)`. + mstore(0x00, 0x5d02c50b) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bool p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,address)`. + mstore(0x00, 0x1d14d001) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,bool)`. + mstore(0x00, 0x46600be0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,address,uint256)`. + mstore(0x00, 0x0c66d1be) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,address,string)`. + mstore(0x00, 0xd812a167) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,address)`. + mstore(0x00, 0x1c41a336) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,bool)`. + mstore(0x00, 0x6a9c478b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,bool,uint256)`. + mstore(0x00, 0x07831502) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,bool,string)`. + mstore(0x00, 0x4a66cb34) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,address)`. + mstore(0x00, 0x136b05dd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,bool)`. + mstore(0x00, 0xd6019f1c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,address,uint256,uint256)`. + mstore(0x00, 0x7bf181a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,uint256,string)`. + mstore(0x00, 0x51f09ff8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,address)`. + mstore(0x00, 0x6f7c603e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,bool)`. + mstore(0x00, 0xe2bfd60b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,address,string,uint256)`. + mstore(0x00, 0xc21f64c7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,address,string,string)`. + mstore(0x00, 0xa73c1db6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,address)`. + mstore(0x00, 0xf4880ea4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,bool)`. + mstore(0x00, 0xc0a302d8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,address,uint256)`. + mstore(0x00, 0x4c123d57) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,address,string)`. + mstore(0x00, 0xa0a47963) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,address)`. + mstore(0x00, 0x8c329b1a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,bool)`. + mstore(0x00, 0x3b2a5ce0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,bool,uint256)`. + mstore(0x00, 0x6d7045c1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,bool,string)`. + mstore(0x00, 0x2ae408d4) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,address)`. + mstore(0x00, 0x54a7a9a0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,bool)`. + mstore(0x00, 0x619e4d0e) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,bool,uint256,uint256)`. + mstore(0x00, 0x0bb00eab) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,uint256,string)`. + mstore(0x00, 0x7dd4d0e0) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,address)`. + mstore(0x00, 0xf9ad2b89) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,bool)`. + mstore(0x00, 0xb857163a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,bool,string,uint256)`. + mstore(0x00, 0xe3a9ca2f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,bool,string,string)`. + mstore(0x00, 0x6d1e8751) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,address)`. + mstore(0x00, 0x26f560a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,bool)`. + mstore(0x00, 0xb4c314ff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,address,uint256)`. + mstore(0x00, 0x1537dc87) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,address,string)`. + mstore(0x00, 0x1bb3b09a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,address)`. + mstore(0x00, 0x9acd3616) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,bool)`. + mstore(0x00, 0xceb5f4d7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,bool,uint256)`. + mstore(0x00, 0x7f9bbca2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,bool,string)`. + mstore(0x00, 0x9143dbb1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,address)`. + mstore(0x00, 0x00dd87b9) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,bool)`. + mstore(0x00, 0xbe984353) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(bool,uint256,uint256,uint256)`. + mstore(0x00, 0x374bb4b2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,uint256,string)`. + mstore(0x00, 0x8e69fb5d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,address)`. + mstore(0x00, 0xfedd1fff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,bool)`. + mstore(0x00, 0xe5e70b2b) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,uint256,string,uint256)`. + mstore(0x00, 0x6a1199e2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,uint256,string,string)`. + mstore(0x00, 0xf5bc2249) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,address)`. + mstore(0x00, 0x2b2b18dc) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,bool)`. + mstore(0x00, 0x6dd434ca) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,address,uint256)`. + mstore(0x00, 0xa5cada94) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,address,string)`. + mstore(0x00, 0x12d6c788) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,address)`. + mstore(0x00, 0x538e06ab) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,bool)`. + mstore(0x00, 0xdc5e935b) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,bool,uint256)`. + mstore(0x00, 0x1606a393) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,bool,string)`. + mstore(0x00, 0x483d0416) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,address)`. + mstore(0x00, 0x1596a1ce) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,bool)`. + mstore(0x00, 0x6b0e5d53) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(bool,string,uint256,uint256)`. + mstore(0x00, 0x28863fcb) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,uint256,string)`. + mstore(0x00, 0x1ad96de6) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,address)`. + mstore(0x00, 0x97d394d8) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,bool)`. + mstore(0x00, 0x1e4b87e5) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(bool,string,string,uint256)`. + mstore(0x00, 0x7be0c3eb) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(bool,string,string,string)`. + mstore(0x00, 0x1762e32a) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(uint256 p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,address)`. + mstore(0x00, 0x2488b414) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,bool)`. + mstore(0x00, 0x091ffaf5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,address,uint256)`. + mstore(0x00, 0x736efbb6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,address,string)`. + mstore(0x00, 0x031c6f73) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,address)`. + mstore(0x00, 0xef72c513) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,bool)`. + mstore(0x00, 0xe351140f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,bool,uint256)`. + mstore(0x00, 0x5abd992a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,bool,string)`. + mstore(0x00, 0x90fb06aa) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,address)`. + mstore(0x00, 0x15c127b5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,bool)`. + mstore(0x00, 0x5f743a7c) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,address,uint256,uint256)`. + mstore(0x00, 0x0c9cd9c1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,uint256,string)`. + mstore(0x00, 0xddb06521) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,address)`. + mstore(0x00, 0x9cba8fff) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,bool)`. + mstore(0x00, 0xcc32ab07) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,address,string,uint256)`. + mstore(0x00, 0x46826b5d) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,address,string,string)`. + mstore(0x00, 0x3e128ca3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,address)`. + mstore(0x00, 0xa1ef4cbb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,bool)`. + mstore(0x00, 0x454d54a5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,address,uint256)`. + mstore(0x00, 0x078287f5) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,address,string)`. + mstore(0x00, 0xade052c7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,address)`. + mstore(0x00, 0x69640b59) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,bool)`. + mstore(0x00, 0xb6f577a1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,bool,uint256)`. + mstore(0x00, 0x7464ce23) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,bool,string)`. + mstore(0x00, 0xdddb9561) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,address)`. + mstore(0x00, 0x88cb6041) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,bool)`. + mstore(0x00, 0x91a02e2a) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,bool,uint256,uint256)`. + mstore(0x00, 0xc6acc7a8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,uint256,string)`. + mstore(0x00, 0xde03e774) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,address)`. + mstore(0x00, 0xef529018) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,bool)`. + mstore(0x00, 0xeb928d7f) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,bool,string,uint256)`. + mstore(0x00, 0x2c1d0746) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,bool,string,string)`. + mstore(0x00, 0x68c8b8bd) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,address)`. + mstore(0x00, 0x56a5d1b1) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,bool)`. + mstore(0x00, 0x15cac476) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,address,uint256)`. + mstore(0x00, 0x88f6e4b2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,address,string)`. + mstore(0x00, 0x6cde40b8) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,address)`. + mstore(0x00, 0x9a816a83) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,bool)`. + mstore(0x00, 0xab085ae6) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,bool,uint256)`. + mstore(0x00, 0xeb7f6fd2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,bool,string)`. + mstore(0x00, 0xa5b4fc99) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,address)`. + mstore(0x00, 0xfa8185af) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,bool)`. + mstore(0x00, 0xc598d185) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + /// @solidity memory-safe-assembly + assembly { + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + // Selector of `log(uint256,uint256,uint256,uint256)`. + mstore(0x00, 0x193fb800) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + } + _sendLogPayload(0x1c, 0x84); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + } + } + + function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,uint256,string)`. + mstore(0x00, 0x59cfcbe3) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0x80) + writeString(0xa0, p3) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,address)`. + mstore(0x00, 0x42d21db7) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,bool)`. + mstore(0x00, 0x7af6ab25) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,uint256,string,uint256)`. + mstore(0x00, 0x5da297eb) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, p3) + writeString(0xa0, p2) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,uint256,string,string)`. + mstore(0x00, 0x27d8afd2) + mstore(0x20, p0) + mstore(0x40, p1) + mstore(0x60, 0x80) + mstore(0x80, 0xc0) + writeString(0xa0, p2) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,address)`. + mstore(0x00, 0x6168ed61) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,bool)`. + mstore(0x00, 0x90c30a56) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,address,uint256)`. + mstore(0x00, 0xe8d3018d) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,address,string)`. + mstore(0x00, 0x9c3adfa1) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,address)`. + mstore(0x00, 0xae2ec581) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,bool)`. + mstore(0x00, 0xba535d9c) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,bool,uint256)`. + mstore(0x00, 0xcf009880) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,bool,string)`. + mstore(0x00, 0xd2d423cd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,address)`. + mstore(0x00, 0x3b2279b4) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,bool)`. + mstore(0x00, 0x691a8f74) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(uint256,string,uint256,uint256)`. + mstore(0x00, 0x82c25b74) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p1) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,uint256,string)`. + mstore(0x00, 0xb7b914ca) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p1) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,address)`. + mstore(0x00, 0xd583c602) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,bool)`. + mstore(0x00, 0xb3a6b6bd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(uint256,string,string,uint256)`. + mstore(0x00, 0xb028c9bd) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p1) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(uint256,string,string,string)`. + mstore(0x00, 0x21ad0683) + mstore(0x20, p0) + mstore(0x40, 0x80) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p1) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, address p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,address)`. + mstore(0x00, 0xed8f28f6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,bool)`. + mstore(0x00, 0xb59dbd60) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,address,uint256)`. + mstore(0x00, 0x8ef3f399) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,address,string)`. + mstore(0x00, 0x800a1c67) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,address)`. + mstore(0x00, 0x223603bd) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,bool)`. + mstore(0x00, 0x79884c2b) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,bool,uint256)`. + mstore(0x00, 0x3e9f866a) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,bool,string)`. + mstore(0x00, 0x0454c079) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,address)`. + mstore(0x00, 0x63fb8bc5) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,bool)`. + mstore(0x00, 0xfc4845f0) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,address,uint256,uint256)`. + mstore(0x00, 0xf8f51b1e) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,uint256,string)`. + mstore(0x00, 0x5a477632) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,address)`. + mstore(0x00, 0xaabc9a31) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,bool)`. + mstore(0x00, 0x5f15d28c) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,address,string,uint256)`. + mstore(0x00, 0x91d1112e) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,address,string,string)`. + mstore(0x00, 0x245986f2) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bool p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,address)`. + mstore(0x00, 0x33e9dd1d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,bool)`. + mstore(0x00, 0x958c28c6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,address,uint256)`. + mstore(0x00, 0x5d08bb05) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,address,string)`. + mstore(0x00, 0x2d8e33a4) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,address)`. + mstore(0x00, 0x7190a529) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,bool)`. + mstore(0x00, 0x895af8c5) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,bool,uint256)`. + mstore(0x00, 0x8e3f78a9) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,bool,string)`. + mstore(0x00, 0x9d22d5dd) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,address)`. + mstore(0x00, 0x935e09bf) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,bool)`. + mstore(0x00, 0x8af7cf8a) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,bool,uint256,uint256)`. + mstore(0x00, 0x64b5bb67) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,uint256,string)`. + mstore(0x00, 0x742d6ee7) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,address)`. + mstore(0x00, 0xe0625b29) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,bool)`. + mstore(0x00, 0x3f8a701d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,bool,string,uint256)`. + mstore(0x00, 0x24f91465) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,bool,string,string)`. + mstore(0x00, 0xa826caeb) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,address)`. + mstore(0x00, 0x5ea2b7ae) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,bool)`. + mstore(0x00, 0x82112a42) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,address,uint256)`. + mstore(0x00, 0x4f04fdc6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,address,string)`. + mstore(0x00, 0x9ffb2f93) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,address)`. + mstore(0x00, 0xe0e95b98) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,bool)`. + mstore(0x00, 0x354c36d6) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,bool,uint256)`. + mstore(0x00, 0xe41b6f6f) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,bool,string)`. + mstore(0x00, 0xabf73a98) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,address)`. + mstore(0x00, 0xe21de278) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,bool)`. + mstore(0x00, 0x7626db92) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + // Selector of `log(string,uint256,uint256,uint256)`. + mstore(0x00, 0xa7a87853) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + } + _sendLogPayload(0x1c, 0xc4); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + } + } + + function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,uint256,string)`. + mstore(0x00, 0x854b3496) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, p2) + mstore(0x80, 0xc0) + writeString(0xa0, p0) + writeString(0xe0, p3) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,address)`. + mstore(0x00, 0x7c4632a4) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,bool)`. + mstore(0x00, 0x7d24491d) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,uint256,string,uint256)`. + mstore(0x00, 0xc67ea9d1) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p2) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,uint256,string,string)`. + mstore(0x00, 0x5ab84e1f) + mstore(0x20, 0x80) + mstore(0x40, p1) + mstore(0x60, 0xc0) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p2) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,address)`. + mstore(0x00, 0x439c7bef) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,bool)`. + mstore(0x00, 0x5ccd4e37) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,address,uint256)`. + mstore(0x00, 0x7cc3c607) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,address,string)`. + mstore(0x00, 0xeb1bff80) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,address)`. + mstore(0x00, 0xc371c7db) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,bool)`. + mstore(0x00, 0x40785869) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,bool,uint256)`. + mstore(0x00, 0xd6aefad2) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,bool,string)`. + mstore(0x00, 0x5e84b0ea) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,address)`. + mstore(0x00, 0x1023f7b2) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,bool)`. + mstore(0x00, 0xc3a8a654) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + // Selector of `log(string,string,uint256,uint256)`. + mstore(0x00, 0xf45d7d2c) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + } + _sendLogPayload(0x1c, 0x104); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + } + } + + function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,uint256,string)`. + mstore(0x00, 0x5d1a971a) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, p2) + mstore(0x80, 0x100) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p3) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,address)`. + mstore(0x00, 0x6d572f44) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,bool)`. + mstore(0x00, 0x2c1754ed) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + // Selector of `log(string,string,string,uint256)`. + mstore(0x00, 0x8eafb02b) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, p3) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + } + _sendLogPayload(0x1c, 0x144); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + } + } + + function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { + bytes32 m0; + bytes32 m1; + bytes32 m2; + bytes32 m3; + bytes32 m4; + bytes32 m5; + bytes32 m6; + bytes32 m7; + bytes32 m8; + bytes32 m9; + bytes32 m10; + bytes32 m11; + bytes32 m12; + /// @solidity memory-safe-assembly + assembly { + function writeString(pos, w) { + let length := 0 + for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } + mstore(pos, length) + let shift := sub(256, shl(3, length)) + mstore(add(pos, 0x20), shl(shift, shr(shift, w))) + } + m0 := mload(0x00) + m1 := mload(0x20) + m2 := mload(0x40) + m3 := mload(0x60) + m4 := mload(0x80) + m5 := mload(0xa0) + m6 := mload(0xc0) + m7 := mload(0xe0) + m8 := mload(0x100) + m9 := mload(0x120) + m10 := mload(0x140) + m11 := mload(0x160) + m12 := mload(0x180) + // Selector of `log(string,string,string,string)`. + mstore(0x00, 0xde68f20a) + mstore(0x20, 0x80) + mstore(0x40, 0xc0) + mstore(0x60, 0x100) + mstore(0x80, 0x140) + writeString(0xa0, p0) + writeString(0xe0, p1) + writeString(0x120, p2) + writeString(0x160, p3) + } + _sendLogPayload(0x1c, 0x184); + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, m0) + mstore(0x20, m1) + mstore(0x40, m2) + mstore(0x60, m3) + mstore(0x80, m4) + mstore(0xa0, m5) + mstore(0xc0, m6) + mstore(0xe0, m7) + mstore(0x100, m8) + mstore(0x120, m9) + mstore(0x140, m10) + mstore(0x160, m11) + mstore(0x180, m12) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol new file mode 100644 index 0000000..988cf72 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) + +pragma solidity ^0.8.0; + +/** + * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM + * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to + * be specified by overriding the virtual {_implementation} function. + * + * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a + * different contract through the {_delegate} function. + * + * The success and return data of the delegated call will be returned back to the caller of the proxy. + */ +abstract contract Proxy { + /** + * @dev Delegates the current call to `implementation`. + * + * This function does not return to its internal call site, it will return directly to the external caller. + */ + function _delegate(address implementation) internal virtual { + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } + + /** + * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function + * and {_fallback} should delegate. + */ + function _implementation() internal view virtual returns (address); + + /** + * @dev Delegates the current call to the address returned by `_implementation()`. + * + * This function does not return to its internal call site, it will return directly to the external caller. + */ + function _fallback() internal virtual { + _beforeFallback(); + _delegate(_implementation()); + } + + /** + * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other + * function in the contract matches the call data. + */ + fallback() external payable virtual { + _fallback(); + } + + /** + * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data + * is empty. + */ + receive() external payable virtual { + _fallback(); + } + + /** + * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` + * call, or as part of the Solidity `fallback` or `receive` functions. + * + * If overridden should call `super._beforeFallback()`. + */ + function _beforeFallback() internal virtual {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol new file mode 100644 index 0000000..69f3bf8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) + +pragma solidity ^0.8.1; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev Returns true if `account` is a contract. + * + * [IMPORTANT] + * ==== + * It is unsafe to assume that an address for which this function returns + * false is an externally-owned account (EOA) and not a contract. + * + * Among others, `isContract` will return false for the following + * types of addresses: + * + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * ==== + * + * [IMPORTANT] + * ==== + * You shouldn't rely on `isContract` to protect against flash loan attacks! + * + * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets + * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract + * constructor. + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize/address.code.length, which returns 0 + // for contracts in construction, since the code is only stored at the end + // of the constructor execution. + + return account.code.length > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, "Address: insufficient balance"); + + (bool success, ) = recipient.call{value: amount}(""); + require(success, "Address: unable to send value, recipient may have reverted"); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, "Address: low-level call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require(address(this).balance >= value, "Address: insufficient balance for call"); + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { + return functionStaticCall(target, data, "Address: low-level static call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + return functionDelegateCall(target, data, "Address: low-level delegate call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling + * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. + * + * _Available since v4.8._ + */ + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata, + string memory errorMessage + ) internal view returns (bytes memory) { + if (success) { + if (returndata.length == 0) { + // only check isContract if the call was successful and the return data is empty + // otherwise we already know that it was a contract + require(isContract(target), "Address: call to non-contract"); + } + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + /** + * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the + * revert reason or using the provided one. + * + * _Available since v4.3._ + */ + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + function _revert(bytes memory returndata, string memory errorMessage) private pure { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol new file mode 100644 index 0000000..f304065 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol new file mode 100644 index 0000000..3557f36 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol @@ -0,0 +1,529 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol) + +pragma solidity ^0.8.0; + +import "./EnumerableSet.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - Entries are added, removed, and checked for existence in constant time + * (O(1)). + * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableMap for EnumerableMap.UintToAddressMap; + * + * // Declare a set state variable + * EnumerableMap.UintToAddressMap private myMap; + * } + * ``` + * + * The following map types are supported: + * + * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 + * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 + * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0 + * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 + * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an array of EnumerableMap. + * ==== + */ +library EnumerableMap { + using EnumerableSet for EnumerableSet.Bytes32Set; + + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Map type with + // bytes32 keys and values. + // The Map implementation uses private functions, and user-facing + // implementations (such as Uint256ToAddressMap) are just wrappers around + // the underlying Map. + // This means that we can only create new EnumerableMaps for types that fit + // in bytes32. + + struct Bytes32ToBytes32Map { + // Storage of keys + EnumerableSet.Bytes32Set _keys; + mapping(bytes32 => bytes32) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + Bytes32ToBytes32Map storage map, + bytes32 key, + bytes32 value + ) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + return map._keys.remove(key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { + bytes32 key = map._keys.at(index); + return (key, map._values[key]); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { + bytes32 value = map._values[key]; + if (value == bytes32(0)) { + return (contains(map, key), bytes32(0)); + } else { + return (true, value); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { + bytes32 value = map._values[key]; + require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); + return value; + } + + /** + * @dev Same as {_get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {_tryGet}. + */ + function get( + Bytes32ToBytes32Map storage map, + bytes32 key, + string memory errorMessage + ) internal view returns (bytes32) { + bytes32 value = map._values[key]; + require(value != 0 || contains(map, key), errorMessage); + return value; + } + + // UintToUintMap + + struct UintToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + UintToUintMap storage map, + uint256 key, + uint256 value + ) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + UintToUintMap storage map, + uint256 key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key), errorMessage)); + } + + // UintToAddressMap + + struct UintToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + UintToAddressMap storage map, + uint256 key, + address value + ) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), address(uint160(uint256(value)))); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + * + * _Available since v3.4._ + */ + function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, address(uint160(uint256(value)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key))))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + UintToAddressMap storage map, + uint256 key, + string memory errorMessage + ) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); + } + + // AddressToUintMap + + struct AddressToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + AddressToUintMap storage map, + address key, + uint256 value + ) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToUintMap storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToUintMap storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (address(uint160(uint256(key))), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToUintMap storage map, address key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + AddressToUintMap storage map, + address key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); + } + + // Bytes32ToUintMap + + struct Bytes32ToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + Bytes32ToUintMap storage map, + bytes32 key, + uint256 value + ) internal returns (bool) { + return set(map._inner, key, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { + return remove(map._inner, key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { + return contains(map._inner, key); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes32ToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (key, uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, key); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { + return uint256(get(map._inner, key)); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + Bytes32ToUintMap storage map, + bytes32 key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, key, errorMessage)); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol new file mode 100644 index 0000000..1d8029e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +pragma solidity ^0.8.0; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position of the value in the `values` array, plus 1 because index 0 + // means a value is not in the set. + mapping(bytes32 => uint256) _indexes; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._indexes[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We read and store the value's index to prevent multiple reads from the same storage slot + uint256 valueIndex = set._indexes[value]; + + if (valueIndex != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set._values.length - 1; + + if (lastIndex != toDeleteIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the last value to the index where the value to delete is + set._values[toDeleteIndex] = lastValue; + // Update the index for the moved value + set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the index for the deleted slot + delete set._indexes[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._indexes[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol new file mode 100644 index 0000000..4e388f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) + +pragma solidity ^0.8.0; + +import "./IAccessControl.sol"; +import "../utils/Context.sol"; +import "../utils/Strings.sol"; +import "../utils/introspection/ERC165.sol"; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +abstract contract AccessControl is Context, IAccessControl, ERC165 { + struct RoleData { + mapping(address => bool) members; + bytes32 adminRole; + } + + mapping(bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with a standardized message including the required role. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + * + * _Available since v4.1._ + */ + modifier onlyRole(bytes32 role) { + _checkRole(role); + _; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view virtual override returns (bool) { + return _roles[role].members[account]; + } + + /** + * @dev Revert with a standard message if `_msgSender()` is missing `role`. + * Overriding this function changes the behavior of the {onlyRole} modifier. + * + * Format of the revert message is described in {_checkRole}. + * + * _Available since v4.6._ + */ + function _checkRole(bytes32 role) internal view virtual { + _checkRole(role, _msgSender()); + } + + /** + * @dev Revert with a standard message if `account` is missing `role`. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + */ + function _checkRole(bytes32 role, address account) internal view virtual { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(account), + " is missing role ", + Strings.toHexString(uint256(role), 32) + ) + ) + ); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleGranted} event. + */ + function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleRevoked} event. + */ + function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been revoked `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + * + * May emit a {RoleRevoked} event. + */ + function renounceRole(bytes32 role, address account) public virtual override { + require(account == _msgSender(), "AccessControl: can only renounce roles for self"); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * May emit a {RoleGranted} event. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + * + * NOTE: This function is deprecated in favor of {_grantRole}. + */ + function _setupRole(bytes32 role, address account) internal virtual { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @dev Grants `role` to `account`. + * + * Internal function without access restriction. + * + * May emit a {RoleGranted} event. + */ + function _grantRole(bytes32 role, address account) internal virtual { + if (!hasRole(role, account)) { + _roles[role].members[account] = true; + emit RoleGranted(role, account, _msgSender()); + } + } + + /** + * @dev Revokes `role` from `account`. + * + * Internal function without access restriction. + * + * May emit a {RoleRevoked} event. + */ + function _revokeRole(bytes32 role, address account) internal virtual { + if (hasRole(role, account)) { + _roles[role].members[account] = false; + emit RoleRevoked(role, account, _msgSender()); + } + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol new file mode 100644 index 0000000..efb82a3 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) + +pragma solidity ^0.8.0; + +/** + * @dev External interface of AccessControl declared to support ERC165 detection. + */ +interface IAccessControl { + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {AccessControl-_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) external; +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol new file mode 100644 index 0000000..91bb8f8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) + +pragma solidity ^0.8.0; + +import "../utils/introspection/IERC165.sol"; \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol new file mode 100644 index 0000000..7c95dfc --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) + +pragma solidity ^0.8.0; + +import "../token/ERC20/IERC20.sol"; \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol new file mode 100644 index 0000000..84ac72c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** + * @dev Standard ERC20 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. + */ +interface IERC20Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC20InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC20InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. + * @param spender Address that may be allowed to operate on tokens without being their owner. + * @param allowance Amount of tokens a `spender` is allowed to operate with. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC20InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `spender` to be approved. Used in approvals. + * @param spender Address that may be allowed to operate on tokens without being their owner. + */ + error ERC20InvalidSpender(address spender); +} + +/** + * @dev Standard ERC721 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. + */ +interface IERC721Errors { + /** + * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. + * Used in balance queries. + * @param owner Address of the current owner of a token. + */ + error ERC721InvalidOwner(address owner); + + /** + * @dev Indicates a `tokenId` whose `owner` is the zero address. + * @param tokenId Identifier number of a token. + */ + error ERC721NonexistentToken(uint256 tokenId); + + /** + * @dev Indicates an error related to the ownership over a particular token. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param tokenId Identifier number of a token. + * @param owner Address of the current owner of a token. + */ + error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC721InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC721InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param tokenId Identifier number of a token. + */ + error ERC721InsufficientApproval(address operator, uint256 tokenId); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC721InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC721InvalidOperator(address operator); +} + +/** + * @dev Standard ERC1155 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. + */ +interface IERC1155Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + * @param tokenId Identifier number of a token. + */ + error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC1155InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC1155InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param owner Address of the current owner of a token. + */ + error ERC1155MissingApprovalForAll(address operator, address owner); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC1155InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC1155InvalidOperator(address operator); + + /** + * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. + * Used in batch transfers. + * @param idsLength Length of the array of token identifiers + * @param valuesLength Length of the array of token amounts + */ + error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol new file mode 100644 index 0000000..4db5eb2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/ERC20.sol"; + +// mock class using ERC20 +contract ERC20Mock is ERC20 { + constructor( + string memory name, + string memory symbol, + address initialAccount, + uint256 initialBalance + ) payable ERC20(name, symbol) { + _mint(initialAccount, initialBalance); + } + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function transferInternal( + address from, + address to, + uint256 value + ) public { + _transfer(from, to, value); + } + + function approveInternal( + address owner, + address spender, + uint256 value + ) public { + _approve(owner, spender, value); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol new file mode 100644 index 0000000..8cc49ec --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) + +pragma solidity ^0.8.0; + +import "../utils/Context.sol"; + +/** + * @dev Contract module which allows children to implement an emergency stop + * mechanism that can be triggered by an authorized account. + * + * This module is used through inheritance. It will make available the + * modifiers `whenNotPaused` and `whenPaused`, which can be applied to + * the functions of your contract. Note that they will not be pausable by + * simply including this module, only once the modifiers are put in place. + */ +abstract contract Pausable is Context { + /** + * @dev Emitted when the pause is triggered by `account`. + */ + event Paused(address account); + + /** + * @dev Emitted when the pause is lifted by `account`. + */ + event Unpaused(address account); + + bool private _paused; + + /** + * @dev Initializes the contract in unpaused state. + */ + constructor() { + _paused = false; + } + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + * + * Requirements: + * + * - The contract must be paused. + */ + modifier whenPaused() { + _requirePaused(); + _; + } + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() public view virtual returns (bool) { + return _paused; + } + + /** + * @dev Throws if the contract is paused. + */ + function _requireNotPaused() internal view virtual { + require(!paused(), "Pausable: paused"); + } + + /** + * @dev Throws if the contract is not paused. + */ + function _requirePaused() internal view virtual { + require(paused(), "Pausable: not paused"); + } + + /** + * @dev Triggers stopped state. + * + * Requirements: + * + * - The contract must not be paused. + */ + function _pause() internal virtual whenNotPaused { + _paused = true; + emit Paused(_msgSender()); + } + + /** + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. + */ + function _unpause() internal virtual whenPaused { + _paused = false; + emit Unpaused(_msgSender()); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol new file mode 100644 index 0000000..0e9b077 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "./IERC20.sol"; +import "./extensions/IERC20Metadata.sol"; +import "../../utils/Context.sol"; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20 is Context, IERC20, IERC20Metadata { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address to, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + * - the caller must have allowance for ``from``'s tokens of at least + * `amount`. + */ + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, amount); + _transfer(from, to, amount); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, allowance(owner, spender) + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + address owner = _msgSender(); + uint256 currentAllowance = allowance(owner, spender); + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(owner, spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `from` cannot be the zero address. + * - `to` cannot be the zero address. + * - `from` must have a balance of at least `amount`. + */ + function _transfer(address from, address to, uint256 amount) internal virtual { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(from, to, amount); + + uint256 fromBalance = _balances[from]; + require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[from] = fromBalance - amount; + // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by + // decrementing then incrementing. + _balances[to] += amount; + } + + emit Transfer(from, to, amount); + + _afterTokenTransfer(from, to, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + unchecked { + // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. + _balances[account] += amount; + } + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + // Overflow not possible: amount <= accountBalance <= totalSupply. + _totalSupply -= amount; + } + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 amount) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `amount`. + * + * Does not update the allowance amount in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Might emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + require(currentAllowance >= amount, "ERC20: insufficient allowance"); + unchecked { + _approve(owner, spender, currentAllowance - amount); + } + } + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol new file mode 100644 index 0000000..536ba0b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `from` to `to` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol new file mode 100644 index 0000000..e775272 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) + +pragma solidity ^0.8.0; + +import "../ERC20.sol"; +import "../../../utils/Context.sol"; + +/** + * @dev Extension of {ERC20} that allows token holders to destroy both their own + * tokens and those that they have an allowance for, in a way that can be + * recognized off-chain (via event analysis). + */ +abstract contract ERC20Burnable is Context, ERC20 { + /** + * @dev Destroys `amount` tokens from the caller. + * + * See {ERC20-_burn}. + */ + function burn(uint256 amount) public virtual { + _burn(_msgSender(), amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, deducting from the caller's + * allowance. + * + * See {ERC20-_burn} and {ERC20-allowance}. + * + * Requirements: + * + * - the caller must have allowance for ``accounts``'s tokens of at least + * `amount`. + */ + function burnFrom(address account, uint256 amount) public virtual { + _spendAllowance(account, _msgSender(), amount); + _burn(account, amount); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol new file mode 100644 index 0000000..6e29892 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) + +pragma solidity ^0.8.0; + +import "../IERC20.sol"; + +/** + * @dev Interface for the optional metadata functions from the ERC20 standard. + * + * _Available since v4.1._ + */ +interface IERC20Metadata is IERC20 { + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the decimals places of the token. + */ + function decimals() external view returns (uint8); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol new file mode 100644 index 0000000..3c29ed0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol) + +pragma solidity ^0.8.0; + +import "./draft-IERC20Permit.sol"; +import "../ERC20.sol"; +import "../../../utils/cryptography/ECDSA.sol"; +import "../../../utils/cryptography/EIP712.sol"; +import "../../../utils/Counters.sol"; + +/** + * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in + * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. + * + * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by + * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't + * need to send a transaction, and thus is not required to hold Ether at all. + * + * _Available since v3.4._ + */ +abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { + using Counters for Counters.Counter; + + mapping(address => Counters.Counter) private _nonces; + + // solhint-disable-next-line var-name-mixedcase + bytes32 private constant _PERMIT_TYPEHASH = + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + /** + * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. + * However, to ensure consistency with the upgradeable transpiler, we will continue + * to reserve a slot. + * @custom:oz-renamed-from _PERMIT_TYPEHASH + */ + // solhint-disable-next-line var-name-mixedcase + bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; + + /** + * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. + * + * It's a good idea to use the same `name` that is defined as the ERC20 token name. + */ + constructor(string memory name) EIP712(name, "1") {} + + /** + * @dev See {IERC20Permit-permit}. + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); + + bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); + + bytes32 hash = _hashTypedDataV4(structHash); + + address signer = ECDSA.recover(hash, v, r, s); + require(signer == owner, "ERC20Permit: invalid signature"); + + _approve(owner, spender, value); + } + + /** + * @dev See {IERC20Permit-nonces}. + */ + function nonces(address owner) public view virtual override returns (uint256) { + return _nonces[owner].current(); + } + + /** + * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. + */ + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view override returns (bytes32) { + return _domainSeparatorV4(); + } + + /** + * @dev "Consume a nonce": return the current value and increment. + * + * _Available since v4.1._ + */ + function _useNonce(address owner) internal virtual returns (uint256 current) { + Counters.Counter storage nonce = _nonces[owner]; + current = nonce.current(); + nonce.increment(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol new file mode 100644 index 0000000..b14bbfe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in + * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. + * + * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by + * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't + * need to send a transaction, and thus is not required to hold Ether at all. + */ +interface IERC20Permit { + /** + * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, + * given ``owner``'s signed approval. + * + * IMPORTANT: The same issues {IERC20-approve} has related to transaction + * ordering also apply here. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `deadline` must be a timestamp in the future. + * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` + * over the EIP712-formatted function arguments. + * - the signature must use ``owner``'s current nonce (see {nonces}). + * + * For more information on the signature format, see the + * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP + * section]. + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /** + * @dev Returns the current nonce for `owner`. This value must be + * included whenever a signature is generated for {permit}. + * + * Every successful call to {permit} increases ``owner``'s nonce by one. This + * prevents a signature from being used multiple times. + */ + function nonces(address owner) external view returns (uint256); + + /** + * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. + */ + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol new file mode 100644 index 0000000..2a6939e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) + +pragma solidity ^0.8.0; + +import "../IERC20.sol"; +import "../extensions/draft-IERC20Permit.sol"; +import "../../../utils/Address.sol"; + +/** + * @title SafeERC20 + * @dev Wrappers around ERC20 operations that throw on failure (when the token + * contract returns false). Tokens that return no value (and instead revert or + * throw on failure) are also supported, non-reverting calls are assumed to be + * successful. + * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + using Address for address; + + function safeTransfer(IERC20 token, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); + } + + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); + } + + /** + * @dev Deprecated. This function has issues similar to the ones found in + * {IERC20-approve}, and its usage is discouraged. + * + * Whenever possible, use {safeIncreaseAllowance} and + * {safeDecreaseAllowance} instead. + */ + function safeApprove(IERC20 token, address spender, uint256 value) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require( + (value == 0) || (token.allowance(address(this), spender) == 0), + "SafeERC20: approve from non-zero to non-zero allowance" + ); + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); + } + + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender) + value; + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); + } + + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + unchecked { + uint256 oldAllowance = token.allowance(address(this), spender); + require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); + uint256 newAllowance = oldAllowance - value; + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); + } + } + + function safePermit( + IERC20Permit token, + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) internal { + uint256 nonceBefore = token.nonces(owner); + token.permit(owner, spender, value, deadline, v, r, s); + uint256 nonceAfter = token.nonces(owner); + require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + */ + function _callOptionalReturn(IERC20 token, bytes memory data) private { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that + // the target address contains contract code and also asserts for success in the low-level call. + + bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); + if (returndata.length > 0) { + // Return data is optional + require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol new file mode 100644 index 0000000..d966c06 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) + +pragma solidity ^0.8.1; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev Returns true if `account` is a contract. + * + * [IMPORTANT] + * ==== + * It is unsafe to assume that an address for which this function returns + * false is an externally-owned account (EOA) and not a contract. + * + * Among others, `isContract` will return false for the following + * types of addresses: + * + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * ==== + * + * [IMPORTANT] + * ==== + * You shouldn't rely on `isContract` to protect against flash loan attacks! + * + * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets + * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract + * constructor. + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize/address.code.length, which returns 0 + // for contracts in construction, since the code is only stored at the end + // of the constructor execution. + + return account.code.length > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, "Address: insufficient balance"); + + (bool success, ) = recipient.call{value: amount}(""); + require(success, "Address: unable to send value, recipient may have reverted"); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, "Address: low-level call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { + return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require(address(this).balance >= value, "Address: insufficient balance for call"); + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { + return functionStaticCall(target, data, "Address: low-level static call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + return functionDelegateCall(target, data, "Address: low-level delegate call failed"); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResultFromTarget(target, success, returndata, errorMessage); + } + + /** + * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling + * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. + * + * _Available since v4.8._ + */ + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata, + string memory errorMessage + ) internal view returns (bytes memory) { + if (success) { + if (returndata.length == 0) { + // only check isContract if the call was successful and the return data is empty + // otherwise we already know that it was a contract + require(isContract(target), "Address: call to non-contract"); + } + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + /** + * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the + * revert reason or using the provided one. + * + * _Available since v4.3._ + */ + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + _revert(returndata, errorMessage); + } + } + + function _revert(bytes memory returndata, string memory errorMessage) private pure { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol new file mode 100644 index 0000000..357980f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol new file mode 100644 index 0000000..ea330e9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) + +pragma solidity ^0.8.0; + +/** + * @title Counters + * @author Matt Condon (@shrugs) + * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number + * of elements in a mapping, issuing ERC721 ids, or counting request ids. + * + * Include with `using Counters for Counters.Counter;` + */ +library Counters { + struct Counter { + // This variable should never be directly accessed by users of the library: interactions must be restricted to + // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add + // this feature: see https://github.com/ethereum/solidity/issues/4637 + uint256 _value; // default: 0 + } + + function current(Counter storage counter) internal view returns (uint256) { + return counter._value; + } + + function increment(Counter storage counter) internal { + unchecked { + counter._value += 1; + } + } + + function decrement(Counter storage counter) internal { + uint256 value = counter._value; + require(value > 0, "Counter: decrement overflow"); + unchecked { + counter._value = value - 1; + } + } + + function reset(Counter storage counter) internal { + counter._value = 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol new file mode 100644 index 0000000..7e91bc6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Library for reading and writing primitive types to specific storage slots. + * + * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. + * + * Example usage to set ERC1967 implementation slot: + * ``` + * contract ERC1967 { + * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + * + * function _getImplementation() internal view returns (address) { + * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + * } + * + * function _setImplementation(address newImplementation) internal { + * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); + * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; + * } + * } + * ``` + * + * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ + */ +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol new file mode 100644 index 0000000..377ba46 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) + +pragma solidity ^0.8.0; + +import "./math/Math.sol"; + +/** + * @dev String operations. + */ +library Strings { + bytes16 private constant _SYMBOLS = "0123456789abcdef"; + uint8 private constant _ADDRESS_LENGTH = 20; + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + unchecked { + uint256 length = Math.log10(value) + 1; + string memory buffer = new string(length); + uint256 ptr; + /// @solidity memory-safe-assembly + assembly { + ptr := add(buffer, add(32, length)) + } + while (true) { + ptr--; + /// @solidity memory-safe-assembly + assembly { + mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) + } + value /= 10; + if (value == 0) break; + } + return buffer; + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + unchecked { + return toHexString(value, Math.log256(value) + 1); + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = _SYMBOLS[value & 0xf]; + value >>= 4; + } + require(value == 0, "Strings: hex length insufficient"); + return string(buffer); + } + + /** + * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. + */ + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol new file mode 100644 index 0000000..65d4b81 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) + +pragma solidity ^0.8.0; + +import "../Strings.sol"; + +/** + * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. + * + * These functions can be used to verify that a message was signed by the holder + * of the private keys of a given address. + */ +library ECDSA { + enum RecoverError { + NoError, + InvalidSignature, + InvalidSignatureLength, + InvalidSignatureS, + InvalidSignatureV // Deprecated in v4.8 + } + + function _throwError(RecoverError error) private pure { + if (error == RecoverError.NoError) { + return; // no error: do nothing + } else if (error == RecoverError.InvalidSignature) { + revert("ECDSA: invalid signature"); + } else if (error == RecoverError.InvalidSignatureLength) { + revert("ECDSA: invalid signature length"); + } else if (error == RecoverError.InvalidSignatureS) { + revert("ECDSA: invalid signature 's' value"); + } + } + + /** + * @dev Returns the address that signed a hashed message (`hash`) with + * `signature` or error string. This address can then be used for verification purposes. + * + * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {toEthSignedMessageHash} on it. + * + * Documentation for signature generation: + * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] + * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] + * + * _Available since v4.3._ + */ + function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { + if (signature.length == 65) { + bytes32 r; + bytes32 s; + uint8 v; + // ecrecover takes the signature parameters, and the only way to get them + // currently is to use assembly. + /// @solidity memory-safe-assembly + assembly { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) + } + return tryRecover(hash, v, r, s); + } else { + return (address(0), RecoverError.InvalidSignatureLength); + } + } + + /** + * @dev Returns the address that signed a hashed message (`hash`) with + * `signature`. This address can then be used for verification purposes. + * + * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {toEthSignedMessageHash} on it. + */ + function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { + (address recovered, RecoverError error) = tryRecover(hash, signature); + _throwError(error); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. + * + * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] + * + * _Available since v4.3._ + */ + function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { + bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + uint8 v = uint8((uint256(vs) >> 255) + 27); + return tryRecover(hash, v, r, s); + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. + * + * _Available since v4.2._ + */ + function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { + (address recovered, RecoverError error) = tryRecover(hash, r, vs); + _throwError(error); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `v`, + * `r` and `s` signature fields separately. + * + * _Available since v4.3._ + */ + function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { + // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature + // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines + // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most + // signatures from current libraries generate a unique signature with an s-value in the lower half order. + // + // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value + // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or + // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept + // these malleable signatures as well. + if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { + return (address(0), RecoverError.InvalidSignatureS); + } + + // If the signature is valid (and not malleable), return the signer address + address signer = ecrecover(hash, v, r, s); + if (signer == address(0)) { + return (address(0), RecoverError.InvalidSignature); + } + + return (signer, RecoverError.NoError); + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `v`, + * `r` and `s` signature fields separately. + */ + function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { + (address recovered, RecoverError error) = tryRecover(hash, v, r, s); + _throwError(error); + return recovered; + } + + /** + * @dev Returns an Ethereum Signed Message, created from a `hash`. This + * produces hash corresponding to the one signed with the + * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] + * JSON-RPC method as part of EIP-191. + * + * See {recover}. + */ + function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { + // 32 is the length in bytes of hash, + // enforced by the type signature above + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + } + + /** + * @dev Returns an Ethereum Signed Message, created from `s`. This + * produces hash corresponding to the one signed with the + * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] + * JSON-RPC method as part of EIP-191. + * + * See {recover}. + */ + function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); + } + + /** + * @dev Returns an Ethereum Signed Typed Data, created from a + * `domainSeparator` and a `structHash`. This produces hash corresponding + * to the one signed with the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] + * JSON-RPC method as part of EIP-712. + * + * See {recover}. + */ + function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol new file mode 100644 index 0000000..6924570 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) + +pragma solidity ^0.8.0; + +import "./ECDSA.sol"; + +/** + * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. + * + * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, + * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding + * they need in their contracts using a combination of `abi.encode` and `keccak256`. + * + * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding + * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA + * ({_hashTypedDataV4}). + * + * The implementation of the domain separator was designed to be as efficient as possible while still properly updating + * the chain id to protect against replay attacks on an eventual fork of the chain. + * + * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method + * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. + * + * _Available since v3.4._ + */ +abstract contract EIP712 { + /* solhint-disable var-name-mixedcase */ + // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to + // invalidate the cached domain separator if the chain id changes. + bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; + uint256 private immutable _CACHED_CHAIN_ID; + address private immutable _CACHED_THIS; + + bytes32 private immutable _HASHED_NAME; + bytes32 private immutable _HASHED_VERSION; + bytes32 private immutable _TYPE_HASH; + + /* solhint-enable var-name-mixedcase */ + + /** + * @dev Initializes the domain separator and parameter caches. + * + * The meaning of `name` and `version` is specified in + * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: + * + * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. + * - `version`: the current major version of the signing domain. + * + * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart + * contract upgrade]. + */ + constructor(string memory name, string memory version) { + bytes32 hashedName = keccak256(bytes(name)); + bytes32 hashedVersion = keccak256(bytes(version)); + bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + _HASHED_NAME = hashedName; + _HASHED_VERSION = hashedVersion; + _CACHED_CHAIN_ID = block.chainid; + _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); + _CACHED_THIS = address(this); + _TYPE_HASH = typeHash; + } + + /** + * @dev Returns the domain separator for the current chain. + */ + function _domainSeparatorV4() internal view returns (bytes32) { + if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { + return _CACHED_DOMAIN_SEPARATOR; + } else { + return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); + } + } + + function _buildDomainSeparator( + bytes32 typeHash, + bytes32 nameHash, + bytes32 versionHash + ) private view returns (bytes32) { + return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); + } + + /** + * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this + * function returns the hash of the fully encoded EIP712 message for this domain. + * + * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: + * + * ```solidity + * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( + * keccak256("Mail(address to,string contents)"), + * mailTo, + * keccak256(bytes(mailContents)) + * ))); + * address signer = ECDSA.recover(digest, signature); + * ``` + */ + function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { + return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol new file mode 100644 index 0000000..c682b07 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) + +pragma solidity ^0.8.0; + +import "./IERC165.sol"; + +/** + * @dev Implementation of the {IERC165} interface. + * + * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check + * for the additional interface id that will be supported. For example: + * + * ```solidity + * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); + * } + * ``` + * + * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. + */ +abstract contract ERC165 is IERC165 { + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IERC165).interfaceId; + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol new file mode 100644 index 0000000..4daefc5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.2) (utils/introspection/ERC165Checker.sol) + +pragma solidity ^0.8.0; + +import "./IERC165.sol"; + +/** + * @dev Library used to query support of an interface declared via {IERC165}. + * + * Note that these functions return the actual result of the query: they do not + * `revert` if an interface is not supported. It is up to the caller to decide + * what to do in these cases. + */ +library ERC165Checker { + // As per the EIP-165 spec, no interface should ever match 0xffffffff + bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; + + /** + * @dev Returns true if `account` supports the {IERC165} interface. + */ + function supportsERC165(address account) internal view returns (bool) { + // Any contract that implements ERC165 must explicitly indicate support of + // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid + return + supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && + !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID); + } + + /** + * @dev Returns true if `account` supports the interface defined by + * `interfaceId`. Support for {IERC165} itself is queried automatically. + * + * See {IERC165-supportsInterface}. + */ + function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { + // query support of both ERC165 as per the spec and support of _interfaceId + return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); + } + + /** + * @dev Returns a boolean array where each value corresponds to the + * interfaces passed in and whether they're supported or not. This allows + * you to batch check interfaces for a contract where your expectation + * is that some interfaces may not be supported. + * + * See {IERC165-supportsInterface}. + * + * _Available since v3.4._ + */ + function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) + internal + view + returns (bool[] memory) + { + // an array of booleans corresponding to interfaceIds and whether they're supported or not + bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); + + // query support of ERC165 itself + if (supportsERC165(account)) { + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); + } + } + + return interfaceIdsSupported; + } + + /** + * @dev Returns true if `account` supports all the interfaces defined in + * `interfaceIds`. Support for {IERC165} itself is queried automatically. + * + * Batch-querying can lead to gas savings by skipping repeated checks for + * {IERC165} support. + * + * See {IERC165-supportsInterface}. + */ + function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { + // query support of ERC165 itself + if (!supportsERC165(account)) { + return false; + } + + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { + return false; + } + } + + // all interfaces supported + return true; + } + + /** + * @notice Query if a contract implements an interface, does not check ERC165 support + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return true if the contract at account indicates support of the interface with + * identifier interfaceId, false otherwise + * @dev Assumes that account contains a contract that supports ERC165, otherwise + * the behavior of this method is undefined. This precondition can be checked + * with {supportsERC165}. + * + * Some precompiled contracts will falsely indicate support for a given interface, so caution + * should be exercised when using this function. + * + * Interface identification is specified in ERC-165. + */ + function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { + // prepare call + bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); + + // perform static call + bool success; + uint256 returnSize; + uint256 returnValue; + assembly { + success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) + returnSize := returndatasize() + returnValue := mload(0x00) + } + + return success && returnSize >= 0x20 && returnValue > 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol new file mode 100644 index 0000000..5fa6551 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol new file mode 100644 index 0000000..7a79329 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Standard math utilities missing in the Solidity language. + */ +library Math { + enum Rounding { + Down, // Toward negative infinity + Up, // Toward infinity + Zero // Toward zero + } + + /** + * @dev Returns the largest of two numbers. + */ + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return a > b ? a : b; + } + + /** + * @dev Returns the smallest of two numbers. + */ + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + /** + * @dev Returns the average of two numbers. The result is rounded towards + * zero. + */ + function average(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b) / 2 can overflow. + return (a & b) + (a ^ b) / 2; + } + + /** + * @dev Returns the ceiling of the division of two numbers. + * + * This differs from standard division with `/` in that it rounds up instead + * of rounding down. + */ + function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b - 1) / b can overflow on addition, so we distribute. + return a == 0 ? 0 : (a - 1) / b + 1; + } + + /** + * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 + * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) + * with further edits by Uniswap Labs also under MIT license. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { + unchecked { + // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use + // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = prod1 * 2^256 + prod0. + uint256 prod0; // Least significant 256 bits of the product + uint256 prod1; // Most significant 256 bits of the product + assembly { + let mm := mulmod(x, y, not(0)) + prod0 := mul(x, y) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + // Handle non-overflow cases, 256 by 256 division. + if (prod1 == 0) { + return prod0 / denominator; + } + + // Make sure the result is less than 2^256. Also prevents denominator == 0. + require(denominator > prod1); + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [prod1 prod0]. + uint256 remainder; + assembly { + // Compute remainder using mulmod. + remainder := mulmod(x, y, denominator) + + // Subtract 256 bit number from 512 bit number. + prod1 := sub(prod1, gt(remainder, prod0)) + prod0 := sub(prod0, remainder) + } + + // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. + // See https://cs.stackexchange.com/q/138556/92363. + + // Does not overflow because the denominator cannot be zero at this stage in the function. + uint256 twos = denominator & (~denominator + 1); + assembly { + // Divide denominator by twos. + denominator := div(denominator, twos) + + // Divide [prod1 prod0] by twos. + prod0 := div(prod0, twos) + + // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. + twos := add(div(sub(0, twos), twos), 1) + } + + // Shift in bits from prod1 into prod0. + prod0 |= prod1 * twos; + + // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such + // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for + // four bits. That is, denominator * inv = 1 mod 2^4. + uint256 inverse = (3 * denominator) ^ 2; + + // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works + // in modular arithmetic, doubling the correct bits in each step. + inverse *= 2 - denominator * inverse; // inverse mod 2^8 + inverse *= 2 - denominator * inverse; // inverse mod 2^16 + inverse *= 2 - denominator * inverse; // inverse mod 2^32 + inverse *= 2 - denominator * inverse; // inverse mod 2^64 + inverse *= 2 - denominator * inverse; // inverse mod 2^128 + inverse *= 2 - denominator * inverse; // inverse mod 2^256 + + // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. + // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is + // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 + // is no longer required. + result = prod0 * inverse; + return result; + } + } + + /** + * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { + uint256 result = mulDiv(x, y, denominator); + if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { + result += 1; + } + return result; + } + + /** + * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. + * + * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). + */ + function sqrt(uint256 a) internal pure returns (uint256) { + if (a == 0) { + return 0; + } + + // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. + // + // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have + // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. + // + // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` + // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` + // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` + // + // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. + uint256 result = 1 << (log2(a) >> 1); + + // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, + // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at + // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision + // into the expected uint128 result. + unchecked { + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + return min(result, a / result); + } + } + + /** + * @notice Calculates sqrt(a), following the selected rounding direction. + */ + function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = sqrt(a); + return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); + } + } + + /** + * @dev Return the log in base 2, rounded down, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >> 128 > 0) { + value >>= 128; + result += 128; + } + if (value >> 64 > 0) { + value >>= 64; + result += 64; + } + if (value >> 32 > 0) { + value >>= 32; + result += 32; + } + if (value >> 16 > 0) { + value >>= 16; + result += 16; + } + if (value >> 8 > 0) { + value >>= 8; + result += 8; + } + if (value >> 4 > 0) { + value >>= 4; + result += 4; + } + if (value >> 2 > 0) { + value >>= 2; + result += 2; + } + if (value >> 1 > 0) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 2, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log2(value); + return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); + } + } + + /** + * @dev Return the log in base 10, rounded down, of a positive value. + * Returns 0 if given 0. + */ + function log10(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >= 10 ** 64) { + value /= 10 ** 64; + result += 64; + } + if (value >= 10 ** 32) { + value /= 10 ** 32; + result += 32; + } + if (value >= 10 ** 16) { + value /= 10 ** 16; + result += 16; + } + if (value >= 10 ** 8) { + value /= 10 ** 8; + result += 8; + } + if (value >= 10 ** 4) { + value /= 10 ** 4; + result += 4; + } + if (value >= 10 ** 2) { + value /= 10 ** 2; + result += 2; + } + if (value >= 10 ** 1) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 10, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log10(value); + return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); + } + } + + /** + * @dev Return the log in base 256, rounded down, of a positive value. + * Returns 0 if given 0. + * + * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. + */ + function log256(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >> 128 > 0) { + value >>= 128; + result += 16; + } + if (value >> 64 > 0) { + value >>= 64; + result += 8; + } + if (value >> 32 > 0) { + value >>= 32; + result += 4; + } + if (value >> 16 > 0) { + value >>= 16; + result += 2; + } + if (value >> 8 > 0) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 10, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log256(value); + return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol new file mode 100644 index 0000000..28c1111 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol @@ -0,0 +1,1136 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) +// This file was procedurally generated from scripts/generate/templates/SafeCast.js. + +pragma solidity ^0.8.0; + +/** + * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow + * checks. + * + * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can + * easily result in undesired exploitation or bugs, since developers usually + * assume that overflows raise errors. `SafeCast` restores this intuition by + * reverting the transaction when such an operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + * + * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing + * all math on `uint256` and `int256` and then downcasting. + */ +library SafeCast { + /** + * @dev Returns the downcasted uint248 from uint256, reverting on + * overflow (when the input is greater than largest uint248). + * + * Counterpart to Solidity's `uint248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + * + * _Available since v4.7._ + */ + function toUint248(uint256 value) internal pure returns (uint248) { + require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); + return uint248(value); + } + + /** + * @dev Returns the downcasted uint240 from uint256, reverting on + * overflow (when the input is greater than largest uint240). + * + * Counterpart to Solidity's `uint240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + * + * _Available since v4.7._ + */ + function toUint240(uint256 value) internal pure returns (uint240) { + require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); + return uint240(value); + } + + /** + * @dev Returns the downcasted uint232 from uint256, reverting on + * overflow (when the input is greater than largest uint232). + * + * Counterpart to Solidity's `uint232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + * + * _Available since v4.7._ + */ + function toUint232(uint256 value) internal pure returns (uint232) { + require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); + return uint232(value); + } + + /** + * @dev Returns the downcasted uint224 from uint256, reverting on + * overflow (when the input is greater than largest uint224). + * + * Counterpart to Solidity's `uint224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + * + * _Available since v4.2._ + */ + function toUint224(uint256 value) internal pure returns (uint224) { + require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); + return uint224(value); + } + + /** + * @dev Returns the downcasted uint216 from uint256, reverting on + * overflow (when the input is greater than largest uint216). + * + * Counterpart to Solidity's `uint216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + * + * _Available since v4.7._ + */ + function toUint216(uint256 value) internal pure returns (uint216) { + require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); + return uint216(value); + } + + /** + * @dev Returns the downcasted uint208 from uint256, reverting on + * overflow (when the input is greater than largest uint208). + * + * Counterpart to Solidity's `uint208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + * + * _Available since v4.7._ + */ + function toUint208(uint256 value) internal pure returns (uint208) { + require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); + return uint208(value); + } + + /** + * @dev Returns the downcasted uint200 from uint256, reverting on + * overflow (when the input is greater than largest uint200). + * + * Counterpart to Solidity's `uint200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + * + * _Available since v4.7._ + */ + function toUint200(uint256 value) internal pure returns (uint200) { + require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); + return uint200(value); + } + + /** + * @dev Returns the downcasted uint192 from uint256, reverting on + * overflow (when the input is greater than largest uint192). + * + * Counterpart to Solidity's `uint192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + * + * _Available since v4.7._ + */ + function toUint192(uint256 value) internal pure returns (uint192) { + require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); + return uint192(value); + } + + /** + * @dev Returns the downcasted uint184 from uint256, reverting on + * overflow (when the input is greater than largest uint184). + * + * Counterpart to Solidity's `uint184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + * + * _Available since v4.7._ + */ + function toUint184(uint256 value) internal pure returns (uint184) { + require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); + return uint184(value); + } + + /** + * @dev Returns the downcasted uint176 from uint256, reverting on + * overflow (when the input is greater than largest uint176). + * + * Counterpart to Solidity's `uint176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + * + * _Available since v4.7._ + */ + function toUint176(uint256 value) internal pure returns (uint176) { + require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); + return uint176(value); + } + + /** + * @dev Returns the downcasted uint168 from uint256, reverting on + * overflow (when the input is greater than largest uint168). + * + * Counterpart to Solidity's `uint168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + * + * _Available since v4.7._ + */ + function toUint168(uint256 value) internal pure returns (uint168) { + require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); + return uint168(value); + } + + /** + * @dev Returns the downcasted uint160 from uint256, reverting on + * overflow (when the input is greater than largest uint160). + * + * Counterpart to Solidity's `uint160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + * + * _Available since v4.7._ + */ + function toUint160(uint256 value) internal pure returns (uint160) { + require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); + return uint160(value); + } + + /** + * @dev Returns the downcasted uint152 from uint256, reverting on + * overflow (when the input is greater than largest uint152). + * + * Counterpart to Solidity's `uint152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + * + * _Available since v4.7._ + */ + function toUint152(uint256 value) internal pure returns (uint152) { + require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); + return uint152(value); + } + + /** + * @dev Returns the downcasted uint144 from uint256, reverting on + * overflow (when the input is greater than largest uint144). + * + * Counterpart to Solidity's `uint144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + * + * _Available since v4.7._ + */ + function toUint144(uint256 value) internal pure returns (uint144) { + require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); + return uint144(value); + } + + /** + * @dev Returns the downcasted uint136 from uint256, reverting on + * overflow (when the input is greater than largest uint136). + * + * Counterpart to Solidity's `uint136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + * + * _Available since v4.7._ + */ + function toUint136(uint256 value) internal pure returns (uint136) { + require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); + return uint136(value); + } + + /** + * @dev Returns the downcasted uint128 from uint256, reverting on + * overflow (when the input is greater than largest uint128). + * + * Counterpart to Solidity's `uint128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + * + * _Available since v2.5._ + */ + function toUint128(uint256 value) internal pure returns (uint128) { + require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); + return uint128(value); + } + + /** + * @dev Returns the downcasted uint120 from uint256, reverting on + * overflow (when the input is greater than largest uint120). + * + * Counterpart to Solidity's `uint120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + * + * _Available since v4.7._ + */ + function toUint120(uint256 value) internal pure returns (uint120) { + require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); + return uint120(value); + } + + /** + * @dev Returns the downcasted uint112 from uint256, reverting on + * overflow (when the input is greater than largest uint112). + * + * Counterpart to Solidity's `uint112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + * + * _Available since v4.7._ + */ + function toUint112(uint256 value) internal pure returns (uint112) { + require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); + return uint112(value); + } + + /** + * @dev Returns the downcasted uint104 from uint256, reverting on + * overflow (when the input is greater than largest uint104). + * + * Counterpart to Solidity's `uint104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + * + * _Available since v4.7._ + */ + function toUint104(uint256 value) internal pure returns (uint104) { + require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); + return uint104(value); + } + + /** + * @dev Returns the downcasted uint96 from uint256, reverting on + * overflow (when the input is greater than largest uint96). + * + * Counterpart to Solidity's `uint96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + * + * _Available since v4.2._ + */ + function toUint96(uint256 value) internal pure returns (uint96) { + require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); + return uint96(value); + } + + /** + * @dev Returns the downcasted uint88 from uint256, reverting on + * overflow (when the input is greater than largest uint88). + * + * Counterpart to Solidity's `uint88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + * + * _Available since v4.7._ + */ + function toUint88(uint256 value) internal pure returns (uint88) { + require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); + return uint88(value); + } + + /** + * @dev Returns the downcasted uint80 from uint256, reverting on + * overflow (when the input is greater than largest uint80). + * + * Counterpart to Solidity's `uint80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + * + * _Available since v4.7._ + */ + function toUint80(uint256 value) internal pure returns (uint80) { + require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); + return uint80(value); + } + + /** + * @dev Returns the downcasted uint72 from uint256, reverting on + * overflow (when the input is greater than largest uint72). + * + * Counterpart to Solidity's `uint72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + * + * _Available since v4.7._ + */ + function toUint72(uint256 value) internal pure returns (uint72) { + require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); + return uint72(value); + } + + /** + * @dev Returns the downcasted uint64 from uint256, reverting on + * overflow (when the input is greater than largest uint64). + * + * Counterpart to Solidity's `uint64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + * + * _Available since v2.5._ + */ + function toUint64(uint256 value) internal pure returns (uint64) { + require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); + return uint64(value); + } + + /** + * @dev Returns the downcasted uint56 from uint256, reverting on + * overflow (when the input is greater than largest uint56). + * + * Counterpart to Solidity's `uint56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + * + * _Available since v4.7._ + */ + function toUint56(uint256 value) internal pure returns (uint56) { + require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); + return uint56(value); + } + + /** + * @dev Returns the downcasted uint48 from uint256, reverting on + * overflow (when the input is greater than largest uint48). + * + * Counterpart to Solidity's `uint48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + * + * _Available since v4.7._ + */ + function toUint48(uint256 value) internal pure returns (uint48) { + require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); + return uint48(value); + } + + /** + * @dev Returns the downcasted uint40 from uint256, reverting on + * overflow (when the input is greater than largest uint40). + * + * Counterpart to Solidity's `uint40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + * + * _Available since v4.7._ + */ + function toUint40(uint256 value) internal pure returns (uint40) { + require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); + return uint40(value); + } + + /** + * @dev Returns the downcasted uint32 from uint256, reverting on + * overflow (when the input is greater than largest uint32). + * + * Counterpart to Solidity's `uint32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + * + * _Available since v2.5._ + */ + function toUint32(uint256 value) internal pure returns (uint32) { + require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); + return uint32(value); + } + + /** + * @dev Returns the downcasted uint24 from uint256, reverting on + * overflow (when the input is greater than largest uint24). + * + * Counterpart to Solidity's `uint24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + * + * _Available since v4.7._ + */ + function toUint24(uint256 value) internal pure returns (uint24) { + require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); + return uint24(value); + } + + /** + * @dev Returns the downcasted uint16 from uint256, reverting on + * overflow (when the input is greater than largest uint16). + * + * Counterpart to Solidity's `uint16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + * + * _Available since v2.5._ + */ + function toUint16(uint256 value) internal pure returns (uint16) { + require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); + return uint16(value); + } + + /** + * @dev Returns the downcasted uint8 from uint256, reverting on + * overflow (when the input is greater than largest uint8). + * + * Counterpart to Solidity's `uint8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + * + * _Available since v2.5._ + */ + function toUint8(uint256 value) internal pure returns (uint8) { + require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); + return uint8(value); + } + + /** + * @dev Converts a signed int256 into an unsigned uint256. + * + * Requirements: + * + * - input must be greater than or equal to 0. + * + * _Available since v3.0._ + */ + function toUint256(int256 value) internal pure returns (uint256) { + require(value >= 0, "SafeCast: value must be positive"); + return uint256(value); + } + + /** + * @dev Returns the downcasted int248 from int256, reverting on + * overflow (when the input is less than smallest int248 or + * greater than largest int248). + * + * Counterpart to Solidity's `int248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + * + * _Available since v4.7._ + */ + function toInt248(int256 value) internal pure returns (int248 downcasted) { + downcasted = int248(value); + require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); + } + + /** + * @dev Returns the downcasted int240 from int256, reverting on + * overflow (when the input is less than smallest int240 or + * greater than largest int240). + * + * Counterpart to Solidity's `int240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + * + * _Available since v4.7._ + */ + function toInt240(int256 value) internal pure returns (int240 downcasted) { + downcasted = int240(value); + require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); + } + + /** + * @dev Returns the downcasted int232 from int256, reverting on + * overflow (when the input is less than smallest int232 or + * greater than largest int232). + * + * Counterpart to Solidity's `int232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + * + * _Available since v4.7._ + */ + function toInt232(int256 value) internal pure returns (int232 downcasted) { + downcasted = int232(value); + require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); + } + + /** + * @dev Returns the downcasted int224 from int256, reverting on + * overflow (when the input is less than smallest int224 or + * greater than largest int224). + * + * Counterpart to Solidity's `int224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + * + * _Available since v4.7._ + */ + function toInt224(int256 value) internal pure returns (int224 downcasted) { + downcasted = int224(value); + require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); + } + + /** + * @dev Returns the downcasted int216 from int256, reverting on + * overflow (when the input is less than smallest int216 or + * greater than largest int216). + * + * Counterpart to Solidity's `int216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + * + * _Available since v4.7._ + */ + function toInt216(int256 value) internal pure returns (int216 downcasted) { + downcasted = int216(value); + require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); + } + + /** + * @dev Returns the downcasted int208 from int256, reverting on + * overflow (when the input is less than smallest int208 or + * greater than largest int208). + * + * Counterpart to Solidity's `int208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + * + * _Available since v4.7._ + */ + function toInt208(int256 value) internal pure returns (int208 downcasted) { + downcasted = int208(value); + require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); + } + + /** + * @dev Returns the downcasted int200 from int256, reverting on + * overflow (when the input is less than smallest int200 or + * greater than largest int200). + * + * Counterpart to Solidity's `int200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + * + * _Available since v4.7._ + */ + function toInt200(int256 value) internal pure returns (int200 downcasted) { + downcasted = int200(value); + require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); + } + + /** + * @dev Returns the downcasted int192 from int256, reverting on + * overflow (when the input is less than smallest int192 or + * greater than largest int192). + * + * Counterpart to Solidity's `int192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + * + * _Available since v4.7._ + */ + function toInt192(int256 value) internal pure returns (int192 downcasted) { + downcasted = int192(value); + require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); + } + + /** + * @dev Returns the downcasted int184 from int256, reverting on + * overflow (when the input is less than smallest int184 or + * greater than largest int184). + * + * Counterpart to Solidity's `int184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + * + * _Available since v4.7._ + */ + function toInt184(int256 value) internal pure returns (int184 downcasted) { + downcasted = int184(value); + require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); + } + + /** + * @dev Returns the downcasted int176 from int256, reverting on + * overflow (when the input is less than smallest int176 or + * greater than largest int176). + * + * Counterpart to Solidity's `int176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + * + * _Available since v4.7._ + */ + function toInt176(int256 value) internal pure returns (int176 downcasted) { + downcasted = int176(value); + require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); + } + + /** + * @dev Returns the downcasted int168 from int256, reverting on + * overflow (when the input is less than smallest int168 or + * greater than largest int168). + * + * Counterpart to Solidity's `int168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + * + * _Available since v4.7._ + */ + function toInt168(int256 value) internal pure returns (int168 downcasted) { + downcasted = int168(value); + require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); + } + + /** + * @dev Returns the downcasted int160 from int256, reverting on + * overflow (when the input is less than smallest int160 or + * greater than largest int160). + * + * Counterpart to Solidity's `int160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + * + * _Available since v4.7._ + */ + function toInt160(int256 value) internal pure returns (int160 downcasted) { + downcasted = int160(value); + require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); + } + + /** + * @dev Returns the downcasted int152 from int256, reverting on + * overflow (when the input is less than smallest int152 or + * greater than largest int152). + * + * Counterpart to Solidity's `int152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + * + * _Available since v4.7._ + */ + function toInt152(int256 value) internal pure returns (int152 downcasted) { + downcasted = int152(value); + require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); + } + + /** + * @dev Returns the downcasted int144 from int256, reverting on + * overflow (when the input is less than smallest int144 or + * greater than largest int144). + * + * Counterpart to Solidity's `int144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + * + * _Available since v4.7._ + */ + function toInt144(int256 value) internal pure returns (int144 downcasted) { + downcasted = int144(value); + require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); + } + + /** + * @dev Returns the downcasted int136 from int256, reverting on + * overflow (when the input is less than smallest int136 or + * greater than largest int136). + * + * Counterpart to Solidity's `int136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + * + * _Available since v4.7._ + */ + function toInt136(int256 value) internal pure returns (int136 downcasted) { + downcasted = int136(value); + require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); + } + + /** + * @dev Returns the downcasted int128 from int256, reverting on + * overflow (when the input is less than smallest int128 or + * greater than largest int128). + * + * Counterpart to Solidity's `int128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + * + * _Available since v3.1._ + */ + function toInt128(int256 value) internal pure returns (int128 downcasted) { + downcasted = int128(value); + require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); + } + + /** + * @dev Returns the downcasted int120 from int256, reverting on + * overflow (when the input is less than smallest int120 or + * greater than largest int120). + * + * Counterpart to Solidity's `int120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + * + * _Available since v4.7._ + */ + function toInt120(int256 value) internal pure returns (int120 downcasted) { + downcasted = int120(value); + require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); + } + + /** + * @dev Returns the downcasted int112 from int256, reverting on + * overflow (when the input is less than smallest int112 or + * greater than largest int112). + * + * Counterpart to Solidity's `int112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + * + * _Available since v4.7._ + */ + function toInt112(int256 value) internal pure returns (int112 downcasted) { + downcasted = int112(value); + require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); + } + + /** + * @dev Returns the downcasted int104 from int256, reverting on + * overflow (when the input is less than smallest int104 or + * greater than largest int104). + * + * Counterpart to Solidity's `int104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + * + * _Available since v4.7._ + */ + function toInt104(int256 value) internal pure returns (int104 downcasted) { + downcasted = int104(value); + require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); + } + + /** + * @dev Returns the downcasted int96 from int256, reverting on + * overflow (when the input is less than smallest int96 or + * greater than largest int96). + * + * Counterpart to Solidity's `int96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + * + * _Available since v4.7._ + */ + function toInt96(int256 value) internal pure returns (int96 downcasted) { + downcasted = int96(value); + require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); + } + + /** + * @dev Returns the downcasted int88 from int256, reverting on + * overflow (when the input is less than smallest int88 or + * greater than largest int88). + * + * Counterpart to Solidity's `int88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + * + * _Available since v4.7._ + */ + function toInt88(int256 value) internal pure returns (int88 downcasted) { + downcasted = int88(value); + require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); + } + + /** + * @dev Returns the downcasted int80 from int256, reverting on + * overflow (when the input is less than smallest int80 or + * greater than largest int80). + * + * Counterpart to Solidity's `int80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + * + * _Available since v4.7._ + */ + function toInt80(int256 value) internal pure returns (int80 downcasted) { + downcasted = int80(value); + require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); + } + + /** + * @dev Returns the downcasted int72 from int256, reverting on + * overflow (when the input is less than smallest int72 or + * greater than largest int72). + * + * Counterpart to Solidity's `int72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + * + * _Available since v4.7._ + */ + function toInt72(int256 value) internal pure returns (int72 downcasted) { + downcasted = int72(value); + require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); + } + + /** + * @dev Returns the downcasted int64 from int256, reverting on + * overflow (when the input is less than smallest int64 or + * greater than largest int64). + * + * Counterpart to Solidity's `int64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + * + * _Available since v3.1._ + */ + function toInt64(int256 value) internal pure returns (int64 downcasted) { + downcasted = int64(value); + require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); + } + + /** + * @dev Returns the downcasted int56 from int256, reverting on + * overflow (when the input is less than smallest int56 or + * greater than largest int56). + * + * Counterpart to Solidity's `int56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + * + * _Available since v4.7._ + */ + function toInt56(int256 value) internal pure returns (int56 downcasted) { + downcasted = int56(value); + require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); + } + + /** + * @dev Returns the downcasted int48 from int256, reverting on + * overflow (when the input is less than smallest int48 or + * greater than largest int48). + * + * Counterpart to Solidity's `int48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + * + * _Available since v4.7._ + */ + function toInt48(int256 value) internal pure returns (int48 downcasted) { + downcasted = int48(value); + require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); + } + + /** + * @dev Returns the downcasted int40 from int256, reverting on + * overflow (when the input is less than smallest int40 or + * greater than largest int40). + * + * Counterpart to Solidity's `int40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + * + * _Available since v4.7._ + */ + function toInt40(int256 value) internal pure returns (int40 downcasted) { + downcasted = int40(value); + require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); + } + + /** + * @dev Returns the downcasted int32 from int256, reverting on + * overflow (when the input is less than smallest int32 or + * greater than largest int32). + * + * Counterpart to Solidity's `int32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + * + * _Available since v3.1._ + */ + function toInt32(int256 value) internal pure returns (int32 downcasted) { + downcasted = int32(value); + require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); + } + + /** + * @dev Returns the downcasted int24 from int256, reverting on + * overflow (when the input is less than smallest int24 or + * greater than largest int24). + * + * Counterpart to Solidity's `int24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + * + * _Available since v4.7._ + */ + function toInt24(int256 value) internal pure returns (int24 downcasted) { + downcasted = int24(value); + require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); + } + + /** + * @dev Returns the downcasted int16 from int256, reverting on + * overflow (when the input is less than smallest int16 or + * greater than largest int16). + * + * Counterpart to Solidity's `int16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + * + * _Available since v3.1._ + */ + function toInt16(int256 value) internal pure returns (int16 downcasted) { + downcasted = int16(value); + require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); + } + + /** + * @dev Returns the downcasted int8 from int256, reverting on + * overflow (when the input is less than smallest int8 or + * greater than largest int8). + * + * Counterpart to Solidity's `int8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + * + * _Available since v3.1._ + */ + function toInt8(int256 value) internal pure returns (int8 downcasted) { + downcasted = int8(value); + require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); + } + + /** + * @dev Converts an unsigned uint256 into a signed int256. + * + * Requirements: + * + * - input must be less than or equal to maxInt256. + * + * _Available since v3.0._ + */ + function toInt256(uint256 value) internal pure returns (int256) { + // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive + require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); + return int256(value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol new file mode 100644 index 0000000..93524bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Standard signed math utilities missing in the Solidity language. + */ +library SignedMath { + /** + * @dev Returns the largest of two signed numbers. + */ + function max(int256 a, int256 b) internal pure returns (int256) { + return a > b ? a : b; + } + + /** + * @dev Returns the smallest of two signed numbers. + */ + function min(int256 a, int256 b) internal pure returns (int256) { + return a < b ? a : b; + } + + /** + * @dev Returns the average of two signed numbers without overflow. + * The result is rounded towards zero. + */ + function average(int256 a, int256 b) internal pure returns (int256) { + // Formula from the book "Hacker's Delight" + int256 x = (a & b) + ((a ^ b) >> 1); + return x + (int256(uint256(x) >> 255) & (a ^ b)); + } + + /** + * @dev Returns the absolute unsigned value of a signed value. + */ + function abs(int256 n) internal pure returns (uint256) { + unchecked { + // must be unchecked in order to support `n = type(int256).min` + return uint256(n >= 0 ? n : -n); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol new file mode 100644 index 0000000..7f4e911 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol @@ -0,0 +1,530 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableMap.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. + +pragma solidity ^0.8.0; + +import "./EnumerableSet.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - Entries are added, removed, and checked for existence in constant time + * (O(1)). + * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableMap for EnumerableMap.UintToAddressMap; + * + * // Declare a set state variable + * EnumerableMap.UintToAddressMap private myMap; + * } + * ``` + * + * The following map types are supported: + * + * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 + * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 + * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 + * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 + * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableMap. + * ==== + */ +library EnumerableMap { + using EnumerableSet for EnumerableSet.Bytes32Set; + + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Map type with + // bytes32 keys and values. + // The Map implementation uses private functions, and user-facing + // implementations (such as Uint256ToAddressMap) are just wrappers around + // the underlying Map. + // This means that we can only create new EnumerableMaps for types that fit + // in bytes32. + + struct Bytes32ToBytes32Map { + // Storage of keys + EnumerableSet.Bytes32Set _keys; + mapping(bytes32 => bytes32) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + Bytes32ToBytes32Map storage map, + bytes32 key, + bytes32 value + ) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + return map._keys.remove(key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { + bytes32 key = map._keys.at(index); + return (key, map._values[key]); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { + bytes32 value = map._values[key]; + if (value == bytes32(0)) { + return (contains(map, key), bytes32(0)); + } else { + return (true, value); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { + bytes32 value = map._values[key]; + require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); + return value; + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + Bytes32ToBytes32Map storage map, + bytes32 key, + string memory errorMessage + ) internal view returns (bytes32) { + bytes32 value = map._values[key]; + require(value != 0 || contains(map, key), errorMessage); + return value; + } + + // UintToUintMap + + struct UintToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + UintToUintMap storage map, + uint256 key, + uint256 value + ) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + UintToUintMap storage map, + uint256 key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key), errorMessage)); + } + + // UintToAddressMap + + struct UintToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + UintToAddressMap storage map, + uint256 key, + address value + ) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), address(uint160(uint256(value)))); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, address(uint160(uint256(value)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key))))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + UintToAddressMap storage map, + uint256 key, + string memory errorMessage + ) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); + } + + // AddressToUintMap + + struct AddressToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + AddressToUintMap storage map, + address key, + uint256 value + ) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToUintMap storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToUintMap storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (address(uint160(uint256(key))), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToUintMap storage map, address key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))))); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + AddressToUintMap storage map, + address key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); + } + + // Bytes32ToUintMap + + struct Bytes32ToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set( + Bytes32ToUintMap storage map, + bytes32 key, + uint256 value + ) internal returns (bool) { + return set(map._inner, key, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { + return remove(map._inner, key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { + return contains(map._inner, key); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes32ToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the set. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (key, uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, key); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { + return uint256(get(map._inner, key)); + } + + /** + * @dev Same as {get}, with a custom error message when `key` is not in the map. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryGet}. + */ + function get( + Bytes32ToUintMap storage map, + bytes32 key, + string memory errorMessage + ) internal view returns (uint256) { + return uint256(get(map._inner, key, errorMessage)); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol new file mode 100644 index 0000000..0bcbefe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +pragma solidity ^0.8.0; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position of the value in the `values` array, plus 1 because index 0 + // means a value is not in the set. + mapping(bytes32 => uint256) _indexes; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._indexes[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We read and store the value's index to prevent multiple reads from the same storage slot + uint256 valueIndex = set._indexes[value]; + + if (valueIndex != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set._values.length - 1; + + if (lastIndex != toDeleteIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the last value to the index where the value to delete is + set._values[toDeleteIndex] = lastValue; + // Update the index for the moved value + set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the index for the deleted slot + delete set._indexes[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._indexes[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol new file mode 100644 index 0000000..3e3341e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) + +pragma solidity ^0.8.20; + +import {IAccessControl} from "./IAccessControl.sol"; +import {Context} from "../utils/Context.sol"; +import {ERC165} from "../utils/introspection/ERC165.sol"; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ```solidity + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ```solidity + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} + * to enforce additional security measures for this role. + */ +abstract contract AccessControl is Context, IAccessControl, ERC165 { + struct RoleData { + mapping(address account => bool) hasRole; + bytes32 adminRole; + } + + mapping(bytes32 role => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with an {AccessControlUnauthorizedAccount} error including the required role. + */ + modifier onlyRole(bytes32 role) { + _checkRole(role); + _; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view virtual returns (bool) { + return _roles[role].hasRole[account]; + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` + * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. + */ + function _checkRole(bytes32 role) internal view virtual { + _checkRole(role, _msgSender()); + } + + /** + * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` + * is missing `role`. + */ + function _checkRole(bytes32 role, address account) internal view virtual { + if (!hasRole(role, account)) { + revert AccessControlUnauthorizedAccount(account, role); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleGranted} event. + */ + function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + * + * May emit a {RoleRevoked} event. + */ + function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been revoked `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + * + * May emit a {RoleRevoked} event. + */ + function renounceRole(bytes32 role, address callerConfirmation) public virtual { + if (callerConfirmation != _msgSender()) { + revert AccessControlBadConfirmation(); + } + + _revokeRole(role, callerConfirmation); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + /** + * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. + * + * Internal function without access restriction. + * + * May emit a {RoleGranted} event. + */ + function _grantRole(bytes32 role, address account) internal virtual returns (bool) { + if (!hasRole(role, account)) { + _roles[role].hasRole[account] = true; + emit RoleGranted(role, account, _msgSender()); + return true; + } else { + return false; + } + } + + /** + * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. + * + * Internal function without access restriction. + * + * May emit a {RoleRevoked} event. + */ + function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { + if (hasRole(role, account)) { + _roles[role].hasRole[account] = false; + emit RoleRevoked(role, account, _msgSender()); + return true; + } else { + return false; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol new file mode 100644 index 0000000..2ac89ca --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) + +pragma solidity ^0.8.20; + +/** + * @dev External interface of AccessControl declared to support ERC165 detection. + */ +interface IAccessControl { + /** + * @dev The `account` is missing a role. + */ + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + + /** + * @dev The caller of a function is not the expected one. + * + * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. + */ + error AccessControlBadConfirmation(); + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {AccessControl-_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `callerConfirmation`. + */ + function renounceRole(bytes32 role, address callerConfirmation) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol new file mode 100644 index 0000000..944dd0d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "../utils/introspection/IERC165.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol new file mode 100644 index 0000000..21d5a41 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "../token/ERC20/IERC20.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol new file mode 100644 index 0000000..47a9fd5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) + +pragma solidity ^0.8.20; + +interface IERC5267 { + /** + * @dev MAY be emitted to signal that the domain could have changed. + */ + event EIP712DomainChanged(); + + /** + * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 + * signature. + */ + function eip712Domain() + external + view + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol new file mode 100644 index 0000000..f6990e6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) +pragma solidity ^0.8.20; + +/** + * @dev Standard ERC20 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. + */ +interface IERC20Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC20InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC20InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. + * @param spender Address that may be allowed to operate on tokens without being their owner. + * @param allowance Amount of tokens a `spender` is allowed to operate with. + * @param needed Minimum amount required to perform a transfer. + */ + error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC20InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `spender` to be approved. Used in approvals. + * @param spender Address that may be allowed to operate on tokens without being their owner. + */ + error ERC20InvalidSpender(address spender); +} + +/** + * @dev Standard ERC721 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. + */ +interface IERC721Errors { + /** + * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. + * Used in balance queries. + * @param owner Address of the current owner of a token. + */ + error ERC721InvalidOwner(address owner); + + /** + * @dev Indicates a `tokenId` whose `owner` is the zero address. + * @param tokenId Identifier number of a token. + */ + error ERC721NonexistentToken(uint256 tokenId); + + /** + * @dev Indicates an error related to the ownership over a particular token. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param tokenId Identifier number of a token. + * @param owner Address of the current owner of a token. + */ + error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC721InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC721InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param tokenId Identifier number of a token. + */ + error ERC721InsufficientApproval(address operator, uint256 tokenId); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC721InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC721InvalidOperator(address operator); +} + +/** + * @dev Standard ERC1155 Errors + * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. + */ +interface IERC1155Errors { + /** + * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + * @param balance Current balance for the interacting account. + * @param needed Minimum amount required to perform a transfer. + * @param tokenId Identifier number of a token. + */ + error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); + + /** + * @dev Indicates a failure with the token `sender`. Used in transfers. + * @param sender Address whose tokens are being transferred. + */ + error ERC1155InvalidSender(address sender); + + /** + * @dev Indicates a failure with the token `receiver`. Used in transfers. + * @param receiver Address to which tokens are being transferred. + */ + error ERC1155InvalidReceiver(address receiver); + + /** + * @dev Indicates a failure with the `operator`’s approval. Used in transfers. + * @param operator Address that may be allowed to operate on tokens without being their owner. + * @param owner Address of the current owner of a token. + */ + error ERC1155MissingApprovalForAll(address operator, address owner); + + /** + * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. + * @param approver Address initiating an approval operation. + */ + error ERC1155InvalidApprover(address approver); + + /** + * @dev Indicates a failure with the `operator` to be approved. Used in approvals. + * @param operator Address that may be allowed to operate on tokens without being their owner. + */ + error ERC1155InvalidOperator(address operator); + + /** + * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. + * Used in batch transfers. + * @param idsLength Length of the array of token identifiers + * @param valuesLength Length of the array of token amounts + */ + error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol new file mode 100644 index 0000000..1fde527 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "./IERC20.sol"; +import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; +import {Context} from "../../utils/Context.sol"; +import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * + * TIP: For a detailed writeup see our guide + * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * The default value of {decimals} is 18. To change this, you should override + * this function so it returns a different value. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + */ +abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { + mapping(address account => uint256) private _balances; + + mapping(address account => mapping(address spender => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the default value returned by this function, unless + * it's overridden. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `to` cannot be the zero address. + * - the caller must have a balance of at least `value`. + */ + function transfer(address to, uint256 value) public virtual returns (bool) { + address owner = _msgSender(); + _transfer(owner, to, value); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on + * `transferFrom`. This is semantically equivalent to an infinite approval. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 value) public virtual returns (bool) { + address owner = _msgSender(); + _approve(owner, spender, value); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * NOTE: Does not update the allowance if the current allowance + * is the maximum `uint256`. + * + * Requirements: + * + * - `from` and `to` cannot be the zero address. + * - `from` must have a balance of at least `value`. + * - the caller must have allowance for ``from``'s tokens of at least + * `value`. + */ + function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { + address spender = _msgSender(); + _spendAllowance(from, spender, value); + _transfer(from, to, value); + return true; + } + + /** + * @dev Moves a `value` amount of tokens from `from` to `to`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _transfer(address from, address to, uint256 value) internal { + if (from == address(0)) { + revert ERC20InvalidSender(address(0)); + } + if (to == address(0)) { + revert ERC20InvalidReceiver(address(0)); + } + _update(from, to, value); + } + + /** + * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` + * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding + * this function. + * + * Emits a {Transfer} event. + */ + function _update(address from, address to, uint256 value) internal virtual { + if (from == address(0)) { + // Overflow check required: The rest of the code assumes that totalSupply never overflows + _totalSupply += value; + } else { + uint256 fromBalance = _balances[from]; + if (fromBalance < value) { + revert ERC20InsufficientBalance(from, fromBalance, value); + } + unchecked { + // Overflow not possible: value <= fromBalance <= totalSupply. + _balances[from] = fromBalance - value; + } + } + + if (to == address(0)) { + unchecked { + // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. + _totalSupply -= value; + } + } else { + unchecked { + // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. + _balances[to] += value; + } + } + + emit Transfer(from, to, value); + } + + /** + * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). + * Relies on the `_update` mechanism + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead. + */ + function _mint(address account, uint256 value) internal { + if (account == address(0)) { + revert ERC20InvalidReceiver(address(0)); + } + _update(address(0), account, value); + } + + /** + * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. + * Relies on the `_update` mechanism. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * NOTE: This function is not virtual, {_update} should be overridden instead + */ + function _burn(address account, uint256 value) internal { + if (account == address(0)) { + revert ERC20InvalidSender(address(0)); + } + _update(account, address(0), value); + } + + /** + * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + * + * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. + */ + function _approve(address owner, address spender, uint256 value) internal { + _approve(owner, spender, value, true); + } + + /** + * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. + * + * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by + * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any + * `Approval` event during `transferFrom` operations. + * + * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to + * true using the following override: + * ``` + * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { + * super._approve(owner, spender, value, true); + * } + * ``` + * + * Requirements are the same as {_approve}. + */ + function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { + if (owner == address(0)) { + revert ERC20InvalidApprover(address(0)); + } + if (spender == address(0)) { + revert ERC20InvalidSpender(address(0)); + } + _allowances[owner][spender] = value; + if (emitEvent) { + emit Approval(owner, spender, value); + } + } + + /** + * @dev Updates `owner` s allowance for `spender` based on spent `value`. + * + * Does not update the allowance value in case of infinite allowance. + * Revert if not enough allowance is available. + * + * Does not emit an {Approval} event. + */ + function _spendAllowance(address owner, address spender, uint256 value) internal virtual { + uint256 currentAllowance = allowance(owner, spender); + if (currentAllowance != type(uint256).max) { + if (currentAllowance < value) { + revert ERC20InsufficientAllowance(spender, currentAllowance, value); + } + unchecked { + _approve(owner, spender, currentAllowance - value, false); + } + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol new file mode 100644 index 0000000..db01cf4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); + + /** + * @dev Returns the value of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the value of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves a `value` amount of tokens from the caller's account to `to`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address to, uint256 value) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets a `value` amount of tokens as the allowance of `spender` over the + * caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 value) external returns (bool); + + /** + * @dev Moves a `value` amount of tokens from `from` to `to` using the + * allowance mechanism. `value` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address from, address to, uint256 value) external returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol new file mode 100644 index 0000000..4d482d8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) + +pragma solidity ^0.8.20; + +import {ERC20} from "../ERC20.sol"; +import {Context} from "../../../utils/Context.sol"; + +/** + * @dev Extension of {ERC20} that allows token holders to destroy both their own + * tokens and those that they have an allowance for, in a way that can be + * recognized off-chain (via event analysis). + */ +abstract contract ERC20Burnable is Context, ERC20 { + /** + * @dev Destroys a `value` amount of tokens from the caller. + * + * See {ERC20-_burn}. + */ + function burn(uint256 value) public virtual { + _burn(_msgSender(), value); + } + + /** + * @dev Destroys a `value` amount of tokens from `account`, deducting from + * the caller's allowance. + * + * See {ERC20-_burn} and {ERC20-allowance}. + * + * Requirements: + * + * - the caller must have allowance for ``accounts``'s tokens of at least + * `value`. + */ + function burnFrom(address account, uint256 value) public virtual { + _spendAllowance(account, _msgSender(), value); + _burn(account, value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol new file mode 100644 index 0000000..1a38cba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "../IERC20.sol"; + +/** + * @dev Interface for the optional metadata functions from the ERC20 standard. + */ +interface IERC20Metadata is IERC20 { + /** + * @dev Returns the name of the token. + */ + function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + */ + function symbol() external view returns (string memory); + + /** + * @dev Returns the decimals places of the token. + */ + function decimals() external view returns (uint8); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol new file mode 100644 index 0000000..5af4810 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in + * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. + * + * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by + * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't + * need to send a transaction, and thus is not required to hold Ether at all. + * + * ==== Security Considerations + * + * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature + * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be + * considered as an intention to spend the allowance in any specific way. The second is that because permits have + * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should + * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be + * generally recommended is: + * + * ```solidity + * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { + * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} + * doThing(..., value); + * } + * + * function doThing(..., uint256 value) public { + * token.safeTransferFrom(msg.sender, address(this), value); + * ... + * } + * ``` + * + * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of + * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also + * {SafeERC20-safeTransferFrom}). + * + * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so + * contracts should have entry points that don't rely on permit. + */ +interface IERC20Permit { + /** + * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, + * given ``owner``'s signed approval. + * + * IMPORTANT: The same issues {IERC20-approve} has related to transaction + * ordering also apply here. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `deadline` must be a timestamp in the future. + * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` + * over the EIP712-formatted function arguments. + * - the signature must use ``owner``'s current nonce (see {nonces}). + * + * For more information on the signature format, see the + * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP + * section]. + * + * CAUTION: See Security Considerations above. + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /** + * @dev Returns the current nonce for `owner`. This value must be + * included whenever a signature is generated for {permit}. + * + * Every successful call to {permit} increases ``owner``'s nonce by one. This + * prevents a signature from being used multiple times. + */ + function nonces(address owner) external view returns (uint256); + + /** + * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. + */ + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol new file mode 100644 index 0000000..bb65709 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) + +pragma solidity ^0.8.20; + +import {IERC20} from "../IERC20.sol"; +import {IERC20Permit} from "../extensions/IERC20Permit.sol"; +import {Address} from "../../../utils/Address.sol"; + +/** + * @title SafeERC20 + * @dev Wrappers around ERC20 operations that throw on failure (when the token + * contract returns false). Tokens that return no value (and instead revert or + * throw on failure) are also supported, non-reverting calls are assumed to be + * successful. + * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + using Address for address; + + /** + * @dev An operation with an ERC20 token failed. + */ + error SafeERC20FailedOperation(address token); + + /** + * @dev Indicates a failed `decreaseAllowance` request. + */ + error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); + + /** + * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, + * non-reverting calls are assumed to be successful. + */ + function safeTransfer(IERC20 token, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); + } + + /** + * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the + * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. + */ + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); + } + + /** + * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, + * non-reverting calls are assumed to be successful. + */ + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 oldAllowance = token.allowance(address(this), spender); + forceApprove(token, spender, oldAllowance + value); + } + + /** + * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no + * value, non-reverting calls are assumed to be successful. + */ + function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { + unchecked { + uint256 currentAllowance = token.allowance(address(this), spender); + if (currentAllowance < requestedDecrease) { + revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); + } + forceApprove(token, spender, currentAllowance - requestedDecrease); + } + } + + /** + * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, + * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval + * to be set to zero before setting it to a non-zero value, such as USDT. + */ + function forceApprove(IERC20 token, address spender, uint256 value) internal { + bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); + + if (!_callOptionalReturnBool(token, approvalCall)) { + _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); + _callOptionalReturn(token, approvalCall); + } + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + */ + function _callOptionalReturn(IERC20 token, bytes memory data) private { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that + // the target address contains contract code and also asserts for success in the low-level call. + + bytes memory returndata = address(token).functionCall(data); + if (returndata.length != 0 && !abi.decode(returndata, (bool))) { + revert SafeERC20FailedOperation(address(token)); + } + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + * + * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. + */ + function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false + // and not revert is the subcall reverts. + + (bool success, bytes memory returndata) = address(token).call(data); + return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol new file mode 100644 index 0000000..b7e3059 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev The ETH balance of the account is not enough to perform the operation. + */ + error AddressInsufficientBalance(address account); + + /** + * @dev There's no code at `target` (it is not a contract). + */ + error AddressEmptyCode(address target); + + /** + * @dev A call to an address target failed. The target may have reverted. + */ + error FailedInnerCall(); + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + if (address(this).balance < amount) { + revert AddressInsufficientBalance(address(this)); + } + + (bool success, ) = recipient.call{value: amount}(""); + if (!success) { + revert FailedInnerCall(); + } + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason or custom error, it is bubbled + * up by this function (like regular Solidity function calls). However, if + * the call reverted with no returned reason, this function reverts with a + * {FailedInnerCall} error. + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + */ + function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { + if (address(this).balance < value) { + revert AddressInsufficientBalance(address(this)); + } + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + */ + function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResultFromTarget(target, success, returndata); + } + + /** + * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target + * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an + * unsuccessful call. + */ + function verifyCallResultFromTarget( + address target, + bool success, + bytes memory returndata + ) internal view returns (bytes memory) { + if (!success) { + _revert(returndata); + } else { + // only check if target is a contract if the call was successful and the return data is empty + // otherwise we already know that it was a contract + if (returndata.length == 0 && target.code.length == 0) { + revert AddressEmptyCode(target); + } + return returndata; + } + } + + /** + * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the + * revert reason or with a default {FailedInnerCall} error. + */ + function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { + if (!success) { + _revert(returndata); + } else { + return returndata; + } + } + + /** + * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. + */ + function _revert(bytes memory returndata) private pure { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + /// @solidity memory-safe-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert FailedInnerCall(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol new file mode 100644 index 0000000..4e535fe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address) { + return msg.sender; + } + + function _msgData() internal view virtual returns (bytes calldata) { + return msg.data; + } + + function _contextSuffixLength() internal view virtual returns (uint256) { + return 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol new file mode 100644 index 0000000..312f1cb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) + +pragma solidity ^0.8.20; + +import {Context} from "../utils/Context.sol"; + +/** + * @dev Contract module which allows children to implement an emergency stop + * mechanism that can be triggered by an authorized account. + * + * This module is used through inheritance. It will make available the + * modifiers `whenNotPaused` and `whenPaused`, which can be applied to + * the functions of your contract. Note that they will not be pausable by + * simply including this module, only once the modifiers are put in place. + */ +abstract contract Pausable is Context { + bool private _paused; + + /** + * @dev Emitted when the pause is triggered by `account`. + */ + event Paused(address account); + + /** + * @dev Emitted when the pause is lifted by `account`. + */ + event Unpaused(address account); + + /** + * @dev The operation failed because the contract is paused. + */ + error EnforcedPause(); + + /** + * @dev The operation failed because the contract is not paused. + */ + error ExpectedPause(); + + /** + * @dev Initializes the contract in unpaused state. + */ + constructor() { + _paused = false; + } + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + modifier whenNotPaused() { + _requireNotPaused(); + _; + } + + /** + * @dev Modifier to make a function callable only when the contract is paused. + * + * Requirements: + * + * - The contract must be paused. + */ + modifier whenPaused() { + _requirePaused(); + _; + } + + /** + * @dev Returns true if the contract is paused, and false otherwise. + */ + function paused() public view virtual returns (bool) { + return _paused; + } + + /** + * @dev Throws if the contract is paused. + */ + function _requireNotPaused() internal view virtual { + if (paused()) { + revert EnforcedPause(); + } + } + + /** + * @dev Throws if the contract is not paused. + */ + function _requirePaused() internal view virtual { + if (!paused()) { + revert ExpectedPause(); + } + } + + /** + * @dev Triggers stopped state. + * + * Requirements: + * + * - The contract must not be paused. + */ + function _pause() internal virtual whenNotPaused { + _paused = true; + emit Paused(_msgSender()); + } + + /** + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. + */ + function _unpause() internal virtual whenPaused { + _paused = false; + emit Unpaused(_msgSender()); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol new file mode 100644 index 0000000..fdfe774 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) + +pragma solidity ^0.8.20; + +import {StorageSlot} from "./StorageSlot.sol"; + +// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | +// | length | 0x BB | +type ShortString is bytes32; + +/** + * @dev This library provides functions to convert short memory strings + * into a `ShortString` type that can be used as an immutable variable. + * + * Strings of arbitrary length can be optimized using this library if + * they are short enough (up to 31 bytes) by packing them with their + * length (1 byte) in a single EVM word (32 bytes). Additionally, a + * fallback mechanism can be used for every other case. + * + * Usage example: + * + * ```solidity + * contract Named { + * using ShortStrings for *; + * + * ShortString private immutable _name; + * string private _nameFallback; + * + * constructor(string memory contractName) { + * _name = contractName.toShortStringWithFallback(_nameFallback); + * } + * + * function name() external view returns (string memory) { + * return _name.toStringWithFallback(_nameFallback); + * } + * } + * ``` + */ +library ShortStrings { + // Used as an identifier for strings longer than 31 bytes. + bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; + + error StringTooLong(string str); + error InvalidShortString(); + + /** + * @dev Encode a string of at most 31 chars into a `ShortString`. + * + * This will trigger a `StringTooLong` error is the input string is too long. + */ + function toShortString(string memory str) internal pure returns (ShortString) { + bytes memory bstr = bytes(str); + if (bstr.length > 31) { + revert StringTooLong(str); + } + return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); + } + + /** + * @dev Decode a `ShortString` back to a "normal" string. + */ + function toString(ShortString sstr) internal pure returns (string memory) { + uint256 len = byteLength(sstr); + // using `new string(len)` would work locally but is not memory safe. + string memory str = new string(32); + /// @solidity memory-safe-assembly + assembly { + mstore(str, len) + mstore(add(str, 0x20), sstr) + } + return str; + } + + /** + * @dev Return the length of a `ShortString`. + */ + function byteLength(ShortString sstr) internal pure returns (uint256) { + uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; + if (result > 31) { + revert InvalidShortString(); + } + return result; + } + + /** + * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. + */ + function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { + if (bytes(value).length < 32) { + return toShortString(value); + } else { + StorageSlot.getStringSlot(store).value = value; + return ShortString.wrap(FALLBACK_SENTINEL); + } + } + + /** + * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. + */ + function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { + if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { + return toString(value); + } else { + return store; + } + } + + /** + * @dev Return the length of a string that was encoded to `ShortString` or written to storage using + * {setWithFallback}. + * + * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of + * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. + */ + function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { + if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { + return byteLength(value); + } else { + return bytes(store).length; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol new file mode 100644 index 0000000..0841832 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) +// This file was procedurally generated from scripts/generate/templates/StorageSlot.js. + +pragma solidity ^0.8.20; + +/** + * @dev Library for reading and writing primitive types to specific storage slots. + * + * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. + * This library helps with reading and writing to such slots without the need for inline assembly. + * + * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. + * + * Example usage to set ERC1967 implementation slot: + * ```solidity + * contract ERC1967 { + * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + * + * function _getImplementation() internal view returns (address) { + * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; + * } + * + * function _setImplementation(address newImplementation) internal { + * require(newImplementation.code.length > 0); + * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; + * } + * } + * ``` + */ +library StorageSlot { + struct AddressSlot { + address value; + } + + struct BooleanSlot { + bool value; + } + + struct Bytes32Slot { + bytes32 value; + } + + struct Uint256Slot { + uint256 value; + } + + struct StringSlot { + string value; + } + + struct BytesSlot { + bytes value; + } + + /** + * @dev Returns an `AddressSlot` with member `value` located at `slot`. + */ + function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `BooleanSlot` with member `value` located at `slot`. + */ + function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. + */ + function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `Uint256Slot` with member `value` located at `slot`. + */ + function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `StringSlot` with member `value` located at `slot`. + */ + function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `StringSlot` representation of the string storage pointer `store`. + */ + function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := store.slot + } + } + + /** + * @dev Returns an `BytesSlot` with member `value` located at `slot`. + */ + function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := slot + } + } + + /** + * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. + */ + function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { + /// @solidity memory-safe-assembly + assembly { + r.slot := store.slot + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol new file mode 100644 index 0000000..b2c0a40 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) + +pragma solidity ^0.8.20; + +import {Math} from "./math/Math.sol"; +import {SignedMath} from "./math/SignedMath.sol"; + +/** + * @dev String operations. + */ +library Strings { + bytes16 private constant HEX_DIGITS = "0123456789abcdef"; + uint8 private constant ADDRESS_LENGTH = 20; + + /** + * @dev The `value` string doesn't fit in the specified `length`. + */ + error StringsInsufficientHexLength(uint256 value, uint256 length); + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + unchecked { + uint256 length = Math.log10(value) + 1; + string memory buffer = new string(length); + uint256 ptr; + /// @solidity memory-safe-assembly + assembly { + ptr := add(buffer, add(32, length)) + } + while (true) { + ptr--; + /// @solidity memory-safe-assembly + assembly { + mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) + } + value /= 10; + if (value == 0) break; + } + return buffer; + } + } + + /** + * @dev Converts a `int256` to its ASCII `string` decimal representation. + */ + function toStringSigned(int256 value) internal pure returns (string memory) { + return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + unchecked { + return toHexString(value, Math.log256(value) + 1); + } + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + uint256 localValue = value; + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = "0"; + buffer[1] = "x"; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = HEX_DIGITS[localValue & 0xf]; + localValue >>= 4; + } + if (localValue != 0) { + revert StringsInsufficientHexLength(value, length); + } + return string(buffer); + } + + /** + * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal + * representation. + */ + function toHexString(address addr) internal pure returns (string memory) { + return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); + } + + /** + * @dev Returns true if the two strings are equal. + */ + function equal(string memory a, string memory b) internal pure returns (bool) { + return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol new file mode 100644 index 0000000..04b3e5e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. + * + * These functions can be used to verify that a message was signed by the holder + * of the private keys of a given address. + */ +library ECDSA { + enum RecoverError { + NoError, + InvalidSignature, + InvalidSignatureLength, + InvalidSignatureS + } + + /** + * @dev The signature derives the `address(0)`. + */ + error ECDSAInvalidSignature(); + + /** + * @dev The signature has an invalid length. + */ + error ECDSAInvalidSignatureLength(uint256 length); + + /** + * @dev The signature has an S value that is in the upper half order. + */ + error ECDSAInvalidSignatureS(bytes32 s); + + /** + * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not + * return address(0) without also returning an error description. Errors are documented using an enum (error type) + * and a bytes32 providing additional information about the error. + * + * If no error is returned, then the address can be used for verification purposes. + * + * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. + * + * Documentation for signature generation: + * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] + * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] + */ + function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { + if (signature.length == 65) { + bytes32 r; + bytes32 s; + uint8 v; + // ecrecover takes the signature parameters, and the only way to get them + // currently is to use assembly. + /// @solidity memory-safe-assembly + assembly { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + v := byte(0, mload(add(signature, 0x60))) + } + return tryRecover(hash, v, r, s); + } else { + return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); + } + } + + /** + * @dev Returns the address that signed a hashed message (`hash`) with + * `signature`. This address can then be used for verification purposes. + * + * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: + * this function rejects them by requiring the `s` value to be in the lower + * half order, and the `v` value to be either 27 or 28. + * + * IMPORTANT: `hash` _must_ be the result of a hash operation for the + * verification to be secure: it is possible to craft signatures that + * recover to arbitrary addresses for non-hashed data. A safe way to ensure + * this is by receiving a hash of the original message (which may otherwise + * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. + */ + function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. + * + * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] + */ + function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { + unchecked { + bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + // We do not check for an overflow here since the shift operation results in 0 or 1. + uint8 v = uint8((uint256(vs) >> 255) + 27); + return tryRecover(hash, v, r, s); + } + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. + */ + function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Overload of {ECDSA-tryRecover} that receives the `v`, + * `r` and `s` signature fields separately. + */ + function tryRecover( + bytes32 hash, + uint8 v, + bytes32 r, + bytes32 s + ) internal pure returns (address, RecoverError, bytes32) { + // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature + // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines + // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most + // signatures from current libraries generate a unique signature with an s-value in the lower half order. + // + // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value + // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or + // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept + // these malleable signatures as well. + if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { + return (address(0), RecoverError.InvalidSignatureS, s); + } + + // If the signature is valid (and not malleable), return the signer address + address signer = ecrecover(hash, v, r, s); + if (signer == address(0)) { + return (address(0), RecoverError.InvalidSignature, bytes32(0)); + } + + return (signer, RecoverError.NoError, bytes32(0)); + } + + /** + * @dev Overload of {ECDSA-recover} that receives the `v`, + * `r` and `s` signature fields separately. + */ + function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { + (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); + _throwError(error, errorArg); + return recovered; + } + + /** + * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. + */ + function _throwError(RecoverError error, bytes32 errorArg) private pure { + if (error == RecoverError.NoError) { + return; // no error: do nothing + } else if (error == RecoverError.InvalidSignature) { + revert ECDSAInvalidSignature(); + } else if (error == RecoverError.InvalidSignatureLength) { + revert ECDSAInvalidSignatureLength(uint256(errorArg)); + } else if (error == RecoverError.InvalidSignatureS) { + revert ECDSAInvalidSignatureS(errorArg); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol new file mode 100644 index 0000000..8e548cd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) + +pragma solidity ^0.8.20; + +import {MessageHashUtils} from "./MessageHashUtils.sol"; +import {ShortStrings, ShortString} from "../ShortStrings.sol"; +import {IERC5267} from "../../interfaces/IERC5267.sol"; + +/** + * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. + * + * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose + * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract + * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to + * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. + * + * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding + * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA + * ({_hashTypedDataV4}). + * + * The implementation of the domain separator was designed to be as efficient as possible while still properly updating + * the chain id to protect against replay attacks on an eventual fork of the chain. + * + * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method + * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. + * + * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain + * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the + * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. + * + * @custom:oz-upgrades-unsafe-allow state-variable-immutable + */ +abstract contract EIP712 is IERC5267 { + using ShortStrings for *; + + bytes32 private constant TYPE_HASH = + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); + + // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to + // invalidate the cached domain separator if the chain id changes. + bytes32 private immutable _cachedDomainSeparator; + uint256 private immutable _cachedChainId; + address private immutable _cachedThis; + + bytes32 private immutable _hashedName; + bytes32 private immutable _hashedVersion; + + ShortString private immutable _name; + ShortString private immutable _version; + string private _nameFallback; + string private _versionFallback; + + /** + * @dev Initializes the domain separator and parameter caches. + * + * The meaning of `name` and `version` is specified in + * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: + * + * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. + * - `version`: the current major version of the signing domain. + * + * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart + * contract upgrade]. + */ + constructor(string memory name, string memory version) { + _name = name.toShortStringWithFallback(_nameFallback); + _version = version.toShortStringWithFallback(_versionFallback); + _hashedName = keccak256(bytes(name)); + _hashedVersion = keccak256(bytes(version)); + + _cachedChainId = block.chainid; + _cachedDomainSeparator = _buildDomainSeparator(); + _cachedThis = address(this); + } + + /** + * @dev Returns the domain separator for the current chain. + */ + function _domainSeparatorV4() internal view returns (bytes32) { + if (address(this) == _cachedThis && block.chainid == _cachedChainId) { + return _cachedDomainSeparator; + } else { + return _buildDomainSeparator(); + } + } + + function _buildDomainSeparator() private view returns (bytes32) { + return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); + } + + /** + * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this + * function returns the hash of the fully encoded EIP712 message for this domain. + * + * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: + * + * ```solidity + * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( + * keccak256("Mail(address to,string contents)"), + * mailTo, + * keccak256(bytes(mailContents)) + * ))); + * address signer = ECDSA.recover(digest, signature); + * ``` + */ + function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { + return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); + } + + /** + * @dev See {IERC-5267}. + */ + function eip712Domain() + public + view + virtual + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ) + { + return ( + hex"0f", // 01111 + _EIP712Name(), + _EIP712Version(), + block.chainid, + address(this), + bytes32(0), + new uint256[](0) + ); + } + + /** + * @dev The name parameter for the EIP712 domain. + * + * NOTE: By default this function reads _name which is an immutable value. + * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). + */ + // solhint-disable-next-line func-name-mixedcase + function _EIP712Name() internal view returns (string memory) { + return _name.toStringWithFallback(_nameFallback); + } + + /** + * @dev The version parameter for the EIP712 domain. + * + * NOTE: By default this function reads _version which is an immutable value. + * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). + */ + // solhint-disable-next-line func-name-mixedcase + function _EIP712Version() internal view returns (string memory) { + return _version.toStringWithFallback(_versionFallback); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol new file mode 100644 index 0000000..8836693 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) + +pragma solidity ^0.8.20; + +import {Strings} from "../Strings.sol"; + +/** + * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. + * + * The library provides methods for generating a hash of a message that conforms to the + * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] + * specifications. + */ +library MessageHashUtils { + /** + * @dev Returns the keccak256 digest of an EIP-191 signed data with version + * `0x45` (`personal_sign` messages). + * + * The digest is calculated by prefixing a bytes32 `messageHash` with + * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the + * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. + * + * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with + * keccak256, although any bytes32 value can be safely used because the final digest will + * be re-hashed. + * + * See {ECDSA-recover}. + */ + function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { + /// @solidity memory-safe-assembly + assembly { + mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash + mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix + digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) + } + } + + /** + * @dev Returns the keccak256 digest of an EIP-191 signed data with version + * `0x45` (`personal_sign` messages). + * + * The digest is calculated by prefixing an arbitrary `message` with + * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the + * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. + * + * See {ECDSA-recover}. + */ + function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { + return + keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); + } + + /** + * @dev Returns the keccak256 digest of an EIP-191 signed data with version + * `0x00` (data with intended validator). + * + * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended + * `validator` address. Then hashing the result. + * + * See {ECDSA-recover}. + */ + function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(hex"19_00", validator, data)); + } + + /** + * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). + * + * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with + * `\x19\x01` and hashing the result. It corresponds to the hash signed by the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. + * + * See {ECDSA-recover}. + */ + function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { + /// @solidity memory-safe-assembly + assembly { + let ptr := mload(0x40) + mstore(ptr, hex"19_01") + mstore(add(ptr, 0x02), domainSeparator) + mstore(add(ptr, 0x22), structHash) + digest := keccak256(ptr, 0x42) + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol new file mode 100644 index 0000000..1e77b60 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "./IERC165.sol"; + +/** + * @dev Implementation of the {IERC165} interface. + * + * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check + * for the additional interface id that will be supported. For example: + * + * ```solidity + * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); + * } + * ``` + */ +abstract contract ERC165 is IERC165 { + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { + return interfaceId == type(IERC165).interfaceId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol new file mode 100644 index 0000000..7b52241 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165Checker.sol) + +pragma solidity ^0.8.20; + +import {IERC165} from "./IERC165.sol"; + +/** + * @dev Library used to query support of an interface declared via {IERC165}. + * + * Note that these functions return the actual result of the query: they do not + * `revert` if an interface is not supported. It is up to the caller to decide + * what to do in these cases. + */ +library ERC165Checker { + // As per the EIP-165 spec, no interface should ever match 0xffffffff + bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; + + /** + * @dev Returns true if `account` supports the {IERC165} interface. + */ + function supportsERC165(address account) internal view returns (bool) { + // Any contract that implements ERC165 must explicitly indicate support of + // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid + return + supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && + !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID); + } + + /** + * @dev Returns true if `account` supports the interface defined by + * `interfaceId`. Support for {IERC165} itself is queried automatically. + * + * See {IERC165-supportsInterface}. + */ + function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { + // query support of both ERC165 as per the spec and support of _interfaceId + return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); + } + + /** + * @dev Returns a boolean array where each value corresponds to the + * interfaces passed in and whether they're supported or not. This allows + * you to batch check interfaces for a contract where your expectation + * is that some interfaces may not be supported. + * + * See {IERC165-supportsInterface}. + */ + function getSupportedInterfaces( + address account, + bytes4[] memory interfaceIds + ) internal view returns (bool[] memory) { + // an array of booleans corresponding to interfaceIds and whether they're supported or not + bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); + + // query support of ERC165 itself + if (supportsERC165(account)) { + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); + } + } + + return interfaceIdsSupported; + } + + /** + * @dev Returns true if `account` supports all the interfaces defined in + * `interfaceIds`. Support for {IERC165} itself is queried automatically. + * + * Batch-querying can lead to gas savings by skipping repeated checks for + * {IERC165} support. + * + * See {IERC165-supportsInterface}. + */ + function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { + // query support of ERC165 itself + if (!supportsERC165(account)) { + return false; + } + + // query support of each interface in interfaceIds + for (uint256 i = 0; i < interfaceIds.length; i++) { + if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { + return false; + } + } + + // all interfaces supported + return true; + } + + /** + * @notice Query if a contract implements an interface, does not check ERC165 support + * @param account The address of the contract to query for support of an interface + * @param interfaceId The interface identifier, as specified in ERC-165 + * @return true if the contract at account indicates support of the interface with + * identifier interfaceId, false otherwise + * @dev Assumes that account contains a contract that supports ERC165, otherwise + * the behavior of this method is undefined. This precondition can be checked + * with {supportsERC165}. + * + * Some precompiled contracts will falsely indicate support for a given interface, so caution + * should be exercised when using this function. + * + * Interface identification is specified in ERC-165. + */ + function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { + // prepare call + bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId)); + + // perform static call + bool success; + uint256 returnSize; + uint256 returnValue; + assembly { + success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) + returnSize := returndatasize() + returnValue := mload(0x00) + } + + return success && returnSize >= 0x20 && returnValue > 0; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol new file mode 100644 index 0000000..c09f31f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol new file mode 100644 index 0000000..9681524 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Standard math utilities missing in the Solidity language. + */ +library Math { + /** + * @dev Muldiv operation overflow. + */ + error MathOverflowedMulDiv(); + + enum Rounding { + Floor, // Toward negative infinity + Ceil, // Toward positive infinity + Trunc, // Toward zero + Expand // Away from zero + } + + /** + * @dev Returns the addition of two unsigned integers, with an overflow flag. + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { + unchecked { + uint256 c = a + b; + if (c < a) return (false, 0); + return (true, c); + } + } + + /** + * @dev Returns the subtraction of two unsigned integers, with an overflow flag. + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { + unchecked { + if (b > a) return (false, 0); + return (true, a - b); + } + } + + /** + * @dev Returns the multiplication of two unsigned integers, with an overflow flag. + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { + unchecked { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) return (true, 0); + uint256 c = a * b; + if (c / a != b) return (false, 0); + return (true, c); + } + } + + /** + * @dev Returns the division of two unsigned integers, with a division by zero flag. + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { + unchecked { + if (b == 0) return (false, 0); + return (true, a / b); + } + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { + unchecked { + if (b == 0) return (false, 0); + return (true, a % b); + } + } + + /** + * @dev Returns the largest of two numbers. + */ + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return a > b ? a : b; + } + + /** + * @dev Returns the smallest of two numbers. + */ + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + /** + * @dev Returns the average of two numbers. The result is rounded towards + * zero. + */ + function average(uint256 a, uint256 b) internal pure returns (uint256) { + // (a + b) / 2 can overflow. + return (a & b) + (a ^ b) / 2; + } + + /** + * @dev Returns the ceiling of the division of two numbers. + * + * This differs from standard division with `/` in that it rounds towards infinity instead + * of rounding towards zero. + */ + function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { + if (b == 0) { + // Guarantee the same behavior as in a regular Solidity division. + return a / b; + } + + // (a + b - 1) / b can overflow on addition, so we distribute. + return a == 0 ? 0 : (a - 1) / b + 1; + } + + /** + * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or + * denominator == 0. + * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by + * Uniswap Labs also under MIT license. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { + unchecked { + // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use + // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 + // variables such that product = prod1 * 2^256 + prod0. + uint256 prod0 = x * y; // Least significant 256 bits of the product + uint256 prod1; // Most significant 256 bits of the product + assembly { + let mm := mulmod(x, y, not(0)) + prod1 := sub(sub(mm, prod0), lt(mm, prod0)) + } + + // Handle non-overflow cases, 256 by 256 division. + if (prod1 == 0) { + // Solidity will revert if denominator == 0, unlike the div opcode on its own. + // The surrounding unchecked block does not change this fact. + // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. + return prod0 / denominator; + } + + // Make sure the result is less than 2^256. Also prevents denominator == 0. + if (denominator <= prod1) { + revert MathOverflowedMulDiv(); + } + + /////////////////////////////////////////////// + // 512 by 256 division. + /////////////////////////////////////////////// + + // Make division exact by subtracting the remainder from [prod1 prod0]. + uint256 remainder; + assembly { + // Compute remainder using mulmod. + remainder := mulmod(x, y, denominator) + + // Subtract 256 bit number from 512 bit number. + prod1 := sub(prod1, gt(remainder, prod0)) + prod0 := sub(prod0, remainder) + } + + // Factor powers of two out of denominator and compute largest power of two divisor of denominator. + // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. + + uint256 twos = denominator & (0 - denominator); + assembly { + // Divide denominator by twos. + denominator := div(denominator, twos) + + // Divide [prod1 prod0] by twos. + prod0 := div(prod0, twos) + + // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. + twos := add(div(sub(0, twos), twos), 1) + } + + // Shift in bits from prod1 into prod0. + prod0 |= prod1 * twos; + + // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such + // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for + // four bits. That is, denominator * inv = 1 mod 2^4. + uint256 inverse = (3 * denominator) ^ 2; + + // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also + // works in modular arithmetic, doubling the correct bits in each step. + inverse *= 2 - denominator * inverse; // inverse mod 2^8 + inverse *= 2 - denominator * inverse; // inverse mod 2^16 + inverse *= 2 - denominator * inverse; // inverse mod 2^32 + inverse *= 2 - denominator * inverse; // inverse mod 2^64 + inverse *= 2 - denominator * inverse; // inverse mod 2^128 + inverse *= 2 - denominator * inverse; // inverse mod 2^256 + + // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. + // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is + // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 + // is no longer required. + result = prod0 * inverse; + return result; + } + } + + /** + * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. + */ + function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { + uint256 result = mulDiv(x, y, denominator); + if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { + result += 1; + } + return result; + } + + /** + * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded + * towards zero. + * + * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). + */ + function sqrt(uint256 a) internal pure returns (uint256) { + if (a == 0) { + return 0; + } + + // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. + // + // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have + // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. + // + // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` + // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` + // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` + // + // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. + uint256 result = 1 << (log2(a) >> 1); + + // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, + // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at + // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision + // into the expected uint128 result. + unchecked { + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + result = (result + a / result) >> 1; + return min(result, a / result); + } + } + + /** + * @notice Calculates sqrt(a), following the selected rounding direction. + */ + function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = sqrt(a); + return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); + } + } + + /** + * @dev Return the log in base 2 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log2(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >> 128 > 0) { + value >>= 128; + result += 128; + } + if (value >> 64 > 0) { + value >>= 64; + result += 64; + } + if (value >> 32 > 0) { + value >>= 32; + result += 32; + } + if (value >> 16 > 0) { + value >>= 16; + result += 16; + } + if (value >> 8 > 0) { + value >>= 8; + result += 8; + } + if (value >> 4 > 0) { + value >>= 4; + result += 4; + } + if (value >> 2 > 0) { + value >>= 2; + result += 2; + } + if (value >> 1 > 0) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 2, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log2(value); + return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); + } + } + + /** + * @dev Return the log in base 10 of a positive value rounded towards zero. + * Returns 0 if given 0. + */ + function log10(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >= 10 ** 64) { + value /= 10 ** 64; + result += 64; + } + if (value >= 10 ** 32) { + value /= 10 ** 32; + result += 32; + } + if (value >= 10 ** 16) { + value /= 10 ** 16; + result += 16; + } + if (value >= 10 ** 8) { + value /= 10 ** 8; + result += 8; + } + if (value >= 10 ** 4) { + value /= 10 ** 4; + result += 4; + } + if (value >= 10 ** 2) { + value /= 10 ** 2; + result += 2; + } + if (value >= 10 ** 1) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 10, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log10(value); + return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); + } + } + + /** + * @dev Return the log in base 256 of a positive value rounded towards zero. + * Returns 0 if given 0. + * + * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. + */ + function log256(uint256 value) internal pure returns (uint256) { + uint256 result = 0; + unchecked { + if (value >> 128 > 0) { + value >>= 128; + result += 16; + } + if (value >> 64 > 0) { + value >>= 64; + result += 8; + } + if (value >> 32 > 0) { + value >>= 32; + result += 4; + } + if (value >> 16 > 0) { + value >>= 16; + result += 2; + } + if (value >> 8 > 0) { + result += 1; + } + } + return result; + } + + /** + * @dev Return the log in base 256, following the selected rounding direction, of a positive value. + * Returns 0 if given 0. + */ + function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { + unchecked { + uint256 result = log256(value); + return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); + } + } + + /** + * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. + */ + function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { + return uint8(rounding) % 2 == 1; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol new file mode 100644 index 0000000..0ed458b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol @@ -0,0 +1,1153 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) +// This file was procedurally generated from scripts/generate/templates/SafeCast.js. + +pragma solidity ^0.8.20; + +/** + * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow + * checks. + * + * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can + * easily result in undesired exploitation or bugs, since developers usually + * assume that overflows raise errors. `SafeCast` restores this intuition by + * reverting the transaction when such an operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeCast { + /** + * @dev Value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); + + /** + * @dev An int value doesn't fit in an uint of `bits` size. + */ + error SafeCastOverflowedIntToUint(int256 value); + + /** + * @dev Value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); + + /** + * @dev An uint value doesn't fit in an int of `bits` size. + */ + error SafeCastOverflowedUintToInt(uint256 value); + + /** + * @dev Returns the downcasted uint248 from uint256, reverting on + * overflow (when the input is greater than largest uint248). + * + * Counterpart to Solidity's `uint248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toUint248(uint256 value) internal pure returns (uint248) { + if (value > type(uint248).max) { + revert SafeCastOverflowedUintDowncast(248, value); + } + return uint248(value); + } + + /** + * @dev Returns the downcasted uint240 from uint256, reverting on + * overflow (when the input is greater than largest uint240). + * + * Counterpart to Solidity's `uint240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toUint240(uint256 value) internal pure returns (uint240) { + if (value > type(uint240).max) { + revert SafeCastOverflowedUintDowncast(240, value); + } + return uint240(value); + } + + /** + * @dev Returns the downcasted uint232 from uint256, reverting on + * overflow (when the input is greater than largest uint232). + * + * Counterpart to Solidity's `uint232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toUint232(uint256 value) internal pure returns (uint232) { + if (value > type(uint232).max) { + revert SafeCastOverflowedUintDowncast(232, value); + } + return uint232(value); + } + + /** + * @dev Returns the downcasted uint224 from uint256, reverting on + * overflow (when the input is greater than largest uint224). + * + * Counterpart to Solidity's `uint224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toUint224(uint256 value) internal pure returns (uint224) { + if (value > type(uint224).max) { + revert SafeCastOverflowedUintDowncast(224, value); + } + return uint224(value); + } + + /** + * @dev Returns the downcasted uint216 from uint256, reverting on + * overflow (when the input is greater than largest uint216). + * + * Counterpart to Solidity's `uint216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toUint216(uint256 value) internal pure returns (uint216) { + if (value > type(uint216).max) { + revert SafeCastOverflowedUintDowncast(216, value); + } + return uint216(value); + } + + /** + * @dev Returns the downcasted uint208 from uint256, reverting on + * overflow (when the input is greater than largest uint208). + * + * Counterpart to Solidity's `uint208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toUint208(uint256 value) internal pure returns (uint208) { + if (value > type(uint208).max) { + revert SafeCastOverflowedUintDowncast(208, value); + } + return uint208(value); + } + + /** + * @dev Returns the downcasted uint200 from uint256, reverting on + * overflow (when the input is greater than largest uint200). + * + * Counterpart to Solidity's `uint200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toUint200(uint256 value) internal pure returns (uint200) { + if (value > type(uint200).max) { + revert SafeCastOverflowedUintDowncast(200, value); + } + return uint200(value); + } + + /** + * @dev Returns the downcasted uint192 from uint256, reverting on + * overflow (when the input is greater than largest uint192). + * + * Counterpart to Solidity's `uint192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toUint192(uint256 value) internal pure returns (uint192) { + if (value > type(uint192).max) { + revert SafeCastOverflowedUintDowncast(192, value); + } + return uint192(value); + } + + /** + * @dev Returns the downcasted uint184 from uint256, reverting on + * overflow (when the input is greater than largest uint184). + * + * Counterpart to Solidity's `uint184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toUint184(uint256 value) internal pure returns (uint184) { + if (value > type(uint184).max) { + revert SafeCastOverflowedUintDowncast(184, value); + } + return uint184(value); + } + + /** + * @dev Returns the downcasted uint176 from uint256, reverting on + * overflow (when the input is greater than largest uint176). + * + * Counterpart to Solidity's `uint176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toUint176(uint256 value) internal pure returns (uint176) { + if (value > type(uint176).max) { + revert SafeCastOverflowedUintDowncast(176, value); + } + return uint176(value); + } + + /** + * @dev Returns the downcasted uint168 from uint256, reverting on + * overflow (when the input is greater than largest uint168). + * + * Counterpart to Solidity's `uint168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toUint168(uint256 value) internal pure returns (uint168) { + if (value > type(uint168).max) { + revert SafeCastOverflowedUintDowncast(168, value); + } + return uint168(value); + } + + /** + * @dev Returns the downcasted uint160 from uint256, reverting on + * overflow (when the input is greater than largest uint160). + * + * Counterpart to Solidity's `uint160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toUint160(uint256 value) internal pure returns (uint160) { + if (value > type(uint160).max) { + revert SafeCastOverflowedUintDowncast(160, value); + } + return uint160(value); + } + + /** + * @dev Returns the downcasted uint152 from uint256, reverting on + * overflow (when the input is greater than largest uint152). + * + * Counterpart to Solidity's `uint152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toUint152(uint256 value) internal pure returns (uint152) { + if (value > type(uint152).max) { + revert SafeCastOverflowedUintDowncast(152, value); + } + return uint152(value); + } + + /** + * @dev Returns the downcasted uint144 from uint256, reverting on + * overflow (when the input is greater than largest uint144). + * + * Counterpart to Solidity's `uint144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toUint144(uint256 value) internal pure returns (uint144) { + if (value > type(uint144).max) { + revert SafeCastOverflowedUintDowncast(144, value); + } + return uint144(value); + } + + /** + * @dev Returns the downcasted uint136 from uint256, reverting on + * overflow (when the input is greater than largest uint136). + * + * Counterpart to Solidity's `uint136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toUint136(uint256 value) internal pure returns (uint136) { + if (value > type(uint136).max) { + revert SafeCastOverflowedUintDowncast(136, value); + } + return uint136(value); + } + + /** + * @dev Returns the downcasted uint128 from uint256, reverting on + * overflow (when the input is greater than largest uint128). + * + * Counterpart to Solidity's `uint128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toUint128(uint256 value) internal pure returns (uint128) { + if (value > type(uint128).max) { + revert SafeCastOverflowedUintDowncast(128, value); + } + return uint128(value); + } + + /** + * @dev Returns the downcasted uint120 from uint256, reverting on + * overflow (when the input is greater than largest uint120). + * + * Counterpart to Solidity's `uint120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toUint120(uint256 value) internal pure returns (uint120) { + if (value > type(uint120).max) { + revert SafeCastOverflowedUintDowncast(120, value); + } + return uint120(value); + } + + /** + * @dev Returns the downcasted uint112 from uint256, reverting on + * overflow (when the input is greater than largest uint112). + * + * Counterpart to Solidity's `uint112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toUint112(uint256 value) internal pure returns (uint112) { + if (value > type(uint112).max) { + revert SafeCastOverflowedUintDowncast(112, value); + } + return uint112(value); + } + + /** + * @dev Returns the downcasted uint104 from uint256, reverting on + * overflow (when the input is greater than largest uint104). + * + * Counterpart to Solidity's `uint104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toUint104(uint256 value) internal pure returns (uint104) { + if (value > type(uint104).max) { + revert SafeCastOverflowedUintDowncast(104, value); + } + return uint104(value); + } + + /** + * @dev Returns the downcasted uint96 from uint256, reverting on + * overflow (when the input is greater than largest uint96). + * + * Counterpart to Solidity's `uint96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toUint96(uint256 value) internal pure returns (uint96) { + if (value > type(uint96).max) { + revert SafeCastOverflowedUintDowncast(96, value); + } + return uint96(value); + } + + /** + * @dev Returns the downcasted uint88 from uint256, reverting on + * overflow (when the input is greater than largest uint88). + * + * Counterpart to Solidity's `uint88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toUint88(uint256 value) internal pure returns (uint88) { + if (value > type(uint88).max) { + revert SafeCastOverflowedUintDowncast(88, value); + } + return uint88(value); + } + + /** + * @dev Returns the downcasted uint80 from uint256, reverting on + * overflow (when the input is greater than largest uint80). + * + * Counterpart to Solidity's `uint80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toUint80(uint256 value) internal pure returns (uint80) { + if (value > type(uint80).max) { + revert SafeCastOverflowedUintDowncast(80, value); + } + return uint80(value); + } + + /** + * @dev Returns the downcasted uint72 from uint256, reverting on + * overflow (when the input is greater than largest uint72). + * + * Counterpart to Solidity's `uint72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toUint72(uint256 value) internal pure returns (uint72) { + if (value > type(uint72).max) { + revert SafeCastOverflowedUintDowncast(72, value); + } + return uint72(value); + } + + /** + * @dev Returns the downcasted uint64 from uint256, reverting on + * overflow (when the input is greater than largest uint64). + * + * Counterpart to Solidity's `uint64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toUint64(uint256 value) internal pure returns (uint64) { + if (value > type(uint64).max) { + revert SafeCastOverflowedUintDowncast(64, value); + } + return uint64(value); + } + + /** + * @dev Returns the downcasted uint56 from uint256, reverting on + * overflow (when the input is greater than largest uint56). + * + * Counterpart to Solidity's `uint56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toUint56(uint256 value) internal pure returns (uint56) { + if (value > type(uint56).max) { + revert SafeCastOverflowedUintDowncast(56, value); + } + return uint56(value); + } + + /** + * @dev Returns the downcasted uint48 from uint256, reverting on + * overflow (when the input is greater than largest uint48). + * + * Counterpart to Solidity's `uint48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toUint48(uint256 value) internal pure returns (uint48) { + if (value > type(uint48).max) { + revert SafeCastOverflowedUintDowncast(48, value); + } + return uint48(value); + } + + /** + * @dev Returns the downcasted uint40 from uint256, reverting on + * overflow (when the input is greater than largest uint40). + * + * Counterpart to Solidity's `uint40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toUint40(uint256 value) internal pure returns (uint40) { + if (value > type(uint40).max) { + revert SafeCastOverflowedUintDowncast(40, value); + } + return uint40(value); + } + + /** + * @dev Returns the downcasted uint32 from uint256, reverting on + * overflow (when the input is greater than largest uint32). + * + * Counterpart to Solidity's `uint32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toUint32(uint256 value) internal pure returns (uint32) { + if (value > type(uint32).max) { + revert SafeCastOverflowedUintDowncast(32, value); + } + return uint32(value); + } + + /** + * @dev Returns the downcasted uint24 from uint256, reverting on + * overflow (when the input is greater than largest uint24). + * + * Counterpart to Solidity's `uint24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toUint24(uint256 value) internal pure returns (uint24) { + if (value > type(uint24).max) { + revert SafeCastOverflowedUintDowncast(24, value); + } + return uint24(value); + } + + /** + * @dev Returns the downcasted uint16 from uint256, reverting on + * overflow (when the input is greater than largest uint16). + * + * Counterpart to Solidity's `uint16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toUint16(uint256 value) internal pure returns (uint16) { + if (value > type(uint16).max) { + revert SafeCastOverflowedUintDowncast(16, value); + } + return uint16(value); + } + + /** + * @dev Returns the downcasted uint8 from uint256, reverting on + * overflow (when the input is greater than largest uint8). + * + * Counterpart to Solidity's `uint8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toUint8(uint256 value) internal pure returns (uint8) { + if (value > type(uint8).max) { + revert SafeCastOverflowedUintDowncast(8, value); + } + return uint8(value); + } + + /** + * @dev Converts a signed int256 into an unsigned uint256. + * + * Requirements: + * + * - input must be greater than or equal to 0. + */ + function toUint256(int256 value) internal pure returns (uint256) { + if (value < 0) { + revert SafeCastOverflowedIntToUint(value); + } + return uint256(value); + } + + /** + * @dev Returns the downcasted int248 from int256, reverting on + * overflow (when the input is less than smallest int248 or + * greater than largest int248). + * + * Counterpart to Solidity's `int248` operator. + * + * Requirements: + * + * - input must fit into 248 bits + */ + function toInt248(int256 value) internal pure returns (int248 downcasted) { + downcasted = int248(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(248, value); + } + } + + /** + * @dev Returns the downcasted int240 from int256, reverting on + * overflow (when the input is less than smallest int240 or + * greater than largest int240). + * + * Counterpart to Solidity's `int240` operator. + * + * Requirements: + * + * - input must fit into 240 bits + */ + function toInt240(int256 value) internal pure returns (int240 downcasted) { + downcasted = int240(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(240, value); + } + } + + /** + * @dev Returns the downcasted int232 from int256, reverting on + * overflow (when the input is less than smallest int232 or + * greater than largest int232). + * + * Counterpart to Solidity's `int232` operator. + * + * Requirements: + * + * - input must fit into 232 bits + */ + function toInt232(int256 value) internal pure returns (int232 downcasted) { + downcasted = int232(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(232, value); + } + } + + /** + * @dev Returns the downcasted int224 from int256, reverting on + * overflow (when the input is less than smallest int224 or + * greater than largest int224). + * + * Counterpart to Solidity's `int224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toInt224(int256 value) internal pure returns (int224 downcasted) { + downcasted = int224(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(224, value); + } + } + + /** + * @dev Returns the downcasted int216 from int256, reverting on + * overflow (when the input is less than smallest int216 or + * greater than largest int216). + * + * Counterpart to Solidity's `int216` operator. + * + * Requirements: + * + * - input must fit into 216 bits + */ + function toInt216(int256 value) internal pure returns (int216 downcasted) { + downcasted = int216(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(216, value); + } + } + + /** + * @dev Returns the downcasted int208 from int256, reverting on + * overflow (when the input is less than smallest int208 or + * greater than largest int208). + * + * Counterpart to Solidity's `int208` operator. + * + * Requirements: + * + * - input must fit into 208 bits + */ + function toInt208(int256 value) internal pure returns (int208 downcasted) { + downcasted = int208(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(208, value); + } + } + + /** + * @dev Returns the downcasted int200 from int256, reverting on + * overflow (when the input is less than smallest int200 or + * greater than largest int200). + * + * Counterpart to Solidity's `int200` operator. + * + * Requirements: + * + * - input must fit into 200 bits + */ + function toInt200(int256 value) internal pure returns (int200 downcasted) { + downcasted = int200(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(200, value); + } + } + + /** + * @dev Returns the downcasted int192 from int256, reverting on + * overflow (when the input is less than smallest int192 or + * greater than largest int192). + * + * Counterpart to Solidity's `int192` operator. + * + * Requirements: + * + * - input must fit into 192 bits + */ + function toInt192(int256 value) internal pure returns (int192 downcasted) { + downcasted = int192(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(192, value); + } + } + + /** + * @dev Returns the downcasted int184 from int256, reverting on + * overflow (when the input is less than smallest int184 or + * greater than largest int184). + * + * Counterpart to Solidity's `int184` operator. + * + * Requirements: + * + * - input must fit into 184 bits + */ + function toInt184(int256 value) internal pure returns (int184 downcasted) { + downcasted = int184(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(184, value); + } + } + + /** + * @dev Returns the downcasted int176 from int256, reverting on + * overflow (when the input is less than smallest int176 or + * greater than largest int176). + * + * Counterpart to Solidity's `int176` operator. + * + * Requirements: + * + * - input must fit into 176 bits + */ + function toInt176(int256 value) internal pure returns (int176 downcasted) { + downcasted = int176(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(176, value); + } + } + + /** + * @dev Returns the downcasted int168 from int256, reverting on + * overflow (when the input is less than smallest int168 or + * greater than largest int168). + * + * Counterpart to Solidity's `int168` operator. + * + * Requirements: + * + * - input must fit into 168 bits + */ + function toInt168(int256 value) internal pure returns (int168 downcasted) { + downcasted = int168(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(168, value); + } + } + + /** + * @dev Returns the downcasted int160 from int256, reverting on + * overflow (when the input is less than smallest int160 or + * greater than largest int160). + * + * Counterpart to Solidity's `int160` operator. + * + * Requirements: + * + * - input must fit into 160 bits + */ + function toInt160(int256 value) internal pure returns (int160 downcasted) { + downcasted = int160(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(160, value); + } + } + + /** + * @dev Returns the downcasted int152 from int256, reverting on + * overflow (when the input is less than smallest int152 or + * greater than largest int152). + * + * Counterpart to Solidity's `int152` operator. + * + * Requirements: + * + * - input must fit into 152 bits + */ + function toInt152(int256 value) internal pure returns (int152 downcasted) { + downcasted = int152(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(152, value); + } + } + + /** + * @dev Returns the downcasted int144 from int256, reverting on + * overflow (when the input is less than smallest int144 or + * greater than largest int144). + * + * Counterpart to Solidity's `int144` operator. + * + * Requirements: + * + * - input must fit into 144 bits + */ + function toInt144(int256 value) internal pure returns (int144 downcasted) { + downcasted = int144(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(144, value); + } + } + + /** + * @dev Returns the downcasted int136 from int256, reverting on + * overflow (when the input is less than smallest int136 or + * greater than largest int136). + * + * Counterpart to Solidity's `int136` operator. + * + * Requirements: + * + * - input must fit into 136 bits + */ + function toInt136(int256 value) internal pure returns (int136 downcasted) { + downcasted = int136(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(136, value); + } + } + + /** + * @dev Returns the downcasted int128 from int256, reverting on + * overflow (when the input is less than smallest int128 or + * greater than largest int128). + * + * Counterpart to Solidity's `int128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toInt128(int256 value) internal pure returns (int128 downcasted) { + downcasted = int128(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(128, value); + } + } + + /** + * @dev Returns the downcasted int120 from int256, reverting on + * overflow (when the input is less than smallest int120 or + * greater than largest int120). + * + * Counterpart to Solidity's `int120` operator. + * + * Requirements: + * + * - input must fit into 120 bits + */ + function toInt120(int256 value) internal pure returns (int120 downcasted) { + downcasted = int120(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(120, value); + } + } + + /** + * @dev Returns the downcasted int112 from int256, reverting on + * overflow (when the input is less than smallest int112 or + * greater than largest int112). + * + * Counterpart to Solidity's `int112` operator. + * + * Requirements: + * + * - input must fit into 112 bits + */ + function toInt112(int256 value) internal pure returns (int112 downcasted) { + downcasted = int112(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(112, value); + } + } + + /** + * @dev Returns the downcasted int104 from int256, reverting on + * overflow (when the input is less than smallest int104 or + * greater than largest int104). + * + * Counterpart to Solidity's `int104` operator. + * + * Requirements: + * + * - input must fit into 104 bits + */ + function toInt104(int256 value) internal pure returns (int104 downcasted) { + downcasted = int104(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(104, value); + } + } + + /** + * @dev Returns the downcasted int96 from int256, reverting on + * overflow (when the input is less than smallest int96 or + * greater than largest int96). + * + * Counterpart to Solidity's `int96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toInt96(int256 value) internal pure returns (int96 downcasted) { + downcasted = int96(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(96, value); + } + } + + /** + * @dev Returns the downcasted int88 from int256, reverting on + * overflow (when the input is less than smallest int88 or + * greater than largest int88). + * + * Counterpart to Solidity's `int88` operator. + * + * Requirements: + * + * - input must fit into 88 bits + */ + function toInt88(int256 value) internal pure returns (int88 downcasted) { + downcasted = int88(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(88, value); + } + } + + /** + * @dev Returns the downcasted int80 from int256, reverting on + * overflow (when the input is less than smallest int80 or + * greater than largest int80). + * + * Counterpart to Solidity's `int80` operator. + * + * Requirements: + * + * - input must fit into 80 bits + */ + function toInt80(int256 value) internal pure returns (int80 downcasted) { + downcasted = int80(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(80, value); + } + } + + /** + * @dev Returns the downcasted int72 from int256, reverting on + * overflow (when the input is less than smallest int72 or + * greater than largest int72). + * + * Counterpart to Solidity's `int72` operator. + * + * Requirements: + * + * - input must fit into 72 bits + */ + function toInt72(int256 value) internal pure returns (int72 downcasted) { + downcasted = int72(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(72, value); + } + } + + /** + * @dev Returns the downcasted int64 from int256, reverting on + * overflow (when the input is less than smallest int64 or + * greater than largest int64). + * + * Counterpart to Solidity's `int64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toInt64(int256 value) internal pure returns (int64 downcasted) { + downcasted = int64(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(64, value); + } + } + + /** + * @dev Returns the downcasted int56 from int256, reverting on + * overflow (when the input is less than smallest int56 or + * greater than largest int56). + * + * Counterpart to Solidity's `int56` operator. + * + * Requirements: + * + * - input must fit into 56 bits + */ + function toInt56(int256 value) internal pure returns (int56 downcasted) { + downcasted = int56(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(56, value); + } + } + + /** + * @dev Returns the downcasted int48 from int256, reverting on + * overflow (when the input is less than smallest int48 or + * greater than largest int48). + * + * Counterpart to Solidity's `int48` operator. + * + * Requirements: + * + * - input must fit into 48 bits + */ + function toInt48(int256 value) internal pure returns (int48 downcasted) { + downcasted = int48(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(48, value); + } + } + + /** + * @dev Returns the downcasted int40 from int256, reverting on + * overflow (when the input is less than smallest int40 or + * greater than largest int40). + * + * Counterpart to Solidity's `int40` operator. + * + * Requirements: + * + * - input must fit into 40 bits + */ + function toInt40(int256 value) internal pure returns (int40 downcasted) { + downcasted = int40(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(40, value); + } + } + + /** + * @dev Returns the downcasted int32 from int256, reverting on + * overflow (when the input is less than smallest int32 or + * greater than largest int32). + * + * Counterpart to Solidity's `int32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toInt32(int256 value) internal pure returns (int32 downcasted) { + downcasted = int32(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(32, value); + } + } + + /** + * @dev Returns the downcasted int24 from int256, reverting on + * overflow (when the input is less than smallest int24 or + * greater than largest int24). + * + * Counterpart to Solidity's `int24` operator. + * + * Requirements: + * + * - input must fit into 24 bits + */ + function toInt24(int256 value) internal pure returns (int24 downcasted) { + downcasted = int24(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(24, value); + } + } + + /** + * @dev Returns the downcasted int16 from int256, reverting on + * overflow (when the input is less than smallest int16 or + * greater than largest int16). + * + * Counterpart to Solidity's `int16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toInt16(int256 value) internal pure returns (int16 downcasted) { + downcasted = int16(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(16, value); + } + } + + /** + * @dev Returns the downcasted int8 from int256, reverting on + * overflow (when the input is less than smallest int8 or + * greater than largest int8). + * + * Counterpart to Solidity's `int8` operator. + * + * Requirements: + * + * - input must fit into 8 bits + */ + function toInt8(int256 value) internal pure returns (int8 downcasted) { + downcasted = int8(value); + if (downcasted != value) { + revert SafeCastOverflowedIntDowncast(8, value); + } + } + + /** + * @dev Converts an unsigned uint256 into a signed int256. + * + * Requirements: + * + * - input must be less than or equal to maxInt256. + */ + function toInt256(uint256 value) internal pure returns (int256) { + // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive + if (value > uint256(type(int256).max)) { + revert SafeCastOverflowedUintToInt(value); + } + return int256(value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol new file mode 100644 index 0000000..66a6151 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) + +pragma solidity ^0.8.20; + +/** + * @dev Standard signed math utilities missing in the Solidity language. + */ +library SignedMath { + /** + * @dev Returns the largest of two signed numbers. + */ + function max(int256 a, int256 b) internal pure returns (int256) { + return a > b ? a : b; + } + + /** + * @dev Returns the smallest of two signed numbers. + */ + function min(int256 a, int256 b) internal pure returns (int256) { + return a < b ? a : b; + } + + /** + * @dev Returns the average of two signed numbers without overflow. + * The result is rounded towards zero. + */ + function average(int256 a, int256 b) internal pure returns (int256) { + // Formula from the book "Hacker's Delight" + int256 x = (a & b) + ((a ^ b) >> 1); + return x + (int256(uint256(x) >> 255) & (a ^ b)); + } + + /** + * @dev Returns the absolute unsigned value of a signed value. + */ + function abs(int256 n) internal pure returns (uint256) { + unchecked { + // must be unchecked in order to support `n = type(int256).min` + return uint256(n >= 0 ? n : -n); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol new file mode 100644 index 0000000..929ae7c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol @@ -0,0 +1,533 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableMap.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. + +pragma solidity ^0.8.20; + +import {EnumerableSet} from "./EnumerableSet.sol"; + +/** + * @dev Library for managing an enumerable variant of Solidity's + * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] + * type. + * + * Maps have the following properties: + * + * - Entries are added, removed, and checked for existence in constant time + * (O(1)). + * - Entries are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableMap for EnumerableMap.UintToAddressMap; + * + * // Declare a set state variable + * EnumerableMap.UintToAddressMap private myMap; + * } + * ``` + * + * The following map types are supported: + * + * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 + * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 + * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 + * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 + * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableMap. + * ==== + */ +library EnumerableMap { + using EnumerableSet for EnumerableSet.Bytes32Set; + + // To implement this library for multiple types with as little code repetition as possible, we write it in + // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, + // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. + // This means that we can only create new EnumerableMaps for types that fit in bytes32. + + /** + * @dev Query for a nonexistent map key. + */ + error EnumerableMapNonexistentKey(bytes32 key); + + struct Bytes32ToBytes32Map { + // Storage of keys + EnumerableSet.Bytes32Set _keys; + mapping(bytes32 key => bytes32) _values; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { + map._values[key] = value; + return map._keys.add(key); + } + + /** + * @dev Removes a key-value pair from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { + delete map._values[key]; + return map._keys.remove(key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { + return map._keys.contains(key); + } + + /** + * @dev Returns the number of key-value pairs in the map. O(1). + */ + function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { + return map._keys.length(); + } + + /** + * @dev Returns the key-value pair stored at position `index` in the map. O(1). + * + * Note that there are no guarantees on the ordering of entries inside the + * array, and it may change when more entries are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { + bytes32 key = map._keys.at(index); + return (key, map._values[key]); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { + bytes32 value = map._values[key]; + if (value == bytes32(0)) { + return (contains(map, key), bytes32(0)); + } else { + return (true, value); + } + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { + bytes32 value = map._values[key]; + if (value == 0 && !contains(map, key)) { + revert EnumerableMapNonexistentKey(key); + } + return value; + } + + /** + * @dev Return the an array containing all the keys + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { + return map._keys.values(); + } + + // UintToUintMap + + struct UintToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(key))); + } + + /** + * @dev Return the an array containing all the keys + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintToAddressMap + + struct UintToAddressMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { + return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { + return remove(map._inner, bytes32(key)); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { + return contains(map._inner, bytes32(key)); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(UintToAddressMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (uint256(key), address(uint160(uint256(value)))); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); + return (success, address(uint160(uint256(value)))); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { + return address(uint160(uint256(get(map._inner, bytes32(key))))); + } + + /** + * @dev Return the an array containing all the keys + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { + bytes32[] memory store = keys(map._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressToUintMap + + struct AddressToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { + return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(AddressToUintMap storage map, address key) internal returns (bool) { + return remove(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(AddressToUintMap storage map, address key) internal view returns (bool) { + return contains(map._inner, bytes32(uint256(uint160(key)))); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(AddressToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (address(uint160(uint256(key))), uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(AddressToUintMap storage map, address key) internal view returns (uint256) { + return uint256(get(map._inner, bytes32(uint256(uint160(key))))); + } + + /** + * @dev Return the an array containing all the keys + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(AddressToUintMap storage map) internal view returns (address[] memory) { + bytes32[] memory store = keys(map._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // Bytes32ToUintMap + + struct Bytes32ToUintMap { + Bytes32ToBytes32Map _inner; + } + + /** + * @dev Adds a key-value pair to a map, or updates the value for an existing + * key. O(1). + * + * Returns true if the key was added to the map, that is if it was not + * already present. + */ + function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { + return set(map._inner, key, bytes32(value)); + } + + /** + * @dev Removes a value from a map. O(1). + * + * Returns true if the key was removed from the map, that is if it was present. + */ + function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { + return remove(map._inner, key); + } + + /** + * @dev Returns true if the key is in the map. O(1). + */ + function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { + return contains(map._inner, key); + } + + /** + * @dev Returns the number of elements in the map. O(1). + */ + function length(Bytes32ToUintMap storage map) internal view returns (uint256) { + return length(map._inner); + } + + /** + * @dev Returns the element stored at position `index` in the map. O(1). + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { + (bytes32 key, bytes32 value) = at(map._inner, index); + return (key, uint256(value)); + } + + /** + * @dev Tries to returns the value associated with `key`. O(1). + * Does not revert if `key` is not in the map. + */ + function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { + (bool success, bytes32 value) = tryGet(map._inner, key); + return (success, uint256(value)); + } + + /** + * @dev Returns the value associated with `key`. O(1). + * + * Requirements: + * + * - `key` must be in the map. + */ + function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { + return uint256(get(map._inner, key)); + } + + /** + * @dev Return the an array containing all the keys + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { + bytes32[] memory store = keys(map._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol new file mode 100644 index 0000000..4c7fc5e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol @@ -0,0 +1,378 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +pragma solidity ^0.8.20; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol new file mode 100644 index 0000000..5c11137 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import "../../@ensdomains/buffer/v0.1.0/Buffer.sol"; + +/** +* @dev A library for populating CBOR encoded payload in Solidity. +* +* https://datatracker.ietf.org/doc/html/rfc7049 +* +* The library offers various write* and start* methods to encode values of different types. +* The resulted buffer can be obtained with data() method. +* Encoding of primitive types is staightforward, whereas encoding of sequences can result +* in an invalid CBOR if start/write/end flow is violated. +* For the purpose of gas saving, the library does not verify start/write/end flow internally, +* except for nested start/end pairs. +*/ + +library CBOR { + using Buffer for Buffer.buffer; + + struct CBORBuffer { + Buffer.buffer buf; + uint256 depth; + } + + uint8 private constant MAJOR_TYPE_INT = 0; + uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; + uint8 private constant MAJOR_TYPE_BYTES = 2; + uint8 private constant MAJOR_TYPE_STRING = 3; + uint8 private constant MAJOR_TYPE_ARRAY = 4; + uint8 private constant MAJOR_TYPE_MAP = 5; + uint8 private constant MAJOR_TYPE_TAG = 6; + uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; + + uint8 private constant TAG_TYPE_BIGNUM = 2; + uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; + + uint8 private constant CBOR_FALSE = 20; + uint8 private constant CBOR_TRUE = 21; + uint8 private constant CBOR_NULL = 22; + uint8 private constant CBOR_UNDEFINED = 23; + + function create(uint256 capacity) internal pure returns(CBORBuffer memory cbor) { + Buffer.init(cbor.buf, capacity); + cbor.depth = 0; + return cbor; + } + + function data(CBORBuffer memory buf) internal pure returns(bytes memory) { + require(buf.depth == 0, "Invalid CBOR"); + return buf.buf.buf; + } + + function writeUInt256(CBORBuffer memory buf, uint256 value) internal pure { + buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); + writeBytes(buf, abi.encode(value)); + } + + function writeInt256(CBORBuffer memory buf, int256 value) internal pure { + if (value < 0) { + buf.buf.appendUint8( + uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM) + ); + writeBytes(buf, abi.encode(uint256(-1 - value))); + } else { + writeUInt256(buf, uint256(value)); + } + } + + function writeUInt64(CBORBuffer memory buf, uint64 value) internal pure { + writeFixedNumeric(buf, MAJOR_TYPE_INT, value); + } + + function writeInt64(CBORBuffer memory buf, int64 value) internal pure { + if(value >= 0) { + writeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); + } else{ + writeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value)); + } + } + + function writeBytes(CBORBuffer memory buf, bytes memory value) internal pure { + writeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); + buf.buf.append(value); + } + + function writeString(CBORBuffer memory buf, string memory value) internal pure { + writeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); + buf.buf.append(bytes(value)); + } + + function writeBool(CBORBuffer memory buf, bool value) internal pure { + writeContentFree(buf, value ? CBOR_TRUE : CBOR_FALSE); + } + + function writeNull(CBORBuffer memory buf) internal pure { + writeContentFree(buf, CBOR_NULL); + } + + function writeUndefined(CBORBuffer memory buf) internal pure { + writeContentFree(buf, CBOR_UNDEFINED); + } + + function startArray(CBORBuffer memory buf) internal pure { + writeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); + buf.depth += 1; + } + + function startFixedArray(CBORBuffer memory buf, uint64 length) internal pure { + writeDefiniteLengthType(buf, MAJOR_TYPE_ARRAY, length); + } + + function startMap(CBORBuffer memory buf) internal pure { + writeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); + buf.depth += 1; + } + + function startFixedMap(CBORBuffer memory buf, uint64 length) internal pure { + writeDefiniteLengthType(buf, MAJOR_TYPE_MAP, length); + } + + function endSequence(CBORBuffer memory buf) internal pure { + writeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); + buf.depth -= 1; + } + + function writeKVString(CBORBuffer memory buf, string memory key, string memory value) internal pure { + writeString(buf, key); + writeString(buf, value); + } + + function writeKVBytes(CBORBuffer memory buf, string memory key, bytes memory value) internal pure { + writeString(buf, key); + writeBytes(buf, value); + } + + function writeKVUInt256(CBORBuffer memory buf, string memory key, uint256 value) internal pure { + writeString(buf, key); + writeUInt256(buf, value); + } + + function writeKVInt256(CBORBuffer memory buf, string memory key, int256 value) internal pure { + writeString(buf, key); + writeInt256(buf, value); + } + + function writeKVUInt64(CBORBuffer memory buf, string memory key, uint64 value) internal pure { + writeString(buf, key); + writeUInt64(buf, value); + } + + function writeKVInt64(CBORBuffer memory buf, string memory key, int64 value) internal pure { + writeString(buf, key); + writeInt64(buf, value); + } + + function writeKVBool(CBORBuffer memory buf, string memory key, bool value) internal pure { + writeString(buf, key); + writeBool(buf, value); + } + + function writeKVNull(CBORBuffer memory buf, string memory key) internal pure { + writeString(buf, key); + writeNull(buf); + } + + function writeKVUndefined(CBORBuffer memory buf, string memory key) internal pure { + writeString(buf, key); + writeUndefined(buf); + } + + function writeKVMap(CBORBuffer memory buf, string memory key) internal pure { + writeString(buf, key); + startMap(buf); + } + + function writeKVArray(CBORBuffer memory buf, string memory key) internal pure { + writeString(buf, key); + startArray(buf); + } + + function writeFixedNumeric( + CBORBuffer memory buf, + uint8 major, + uint64 value + ) private pure { + if (value <= 23) { + buf.buf.appendUint8(uint8((major << 5) | value)); + } else if (value <= 0xFF) { + buf.buf.appendUint8(uint8((major << 5) | 24)); + buf.buf.appendInt(value, 1); + } else if (value <= 0xFFFF) { + buf.buf.appendUint8(uint8((major << 5) | 25)); + buf.buf.appendInt(value, 2); + } else if (value <= 0xFFFFFFFF) { + buf.buf.appendUint8(uint8((major << 5) | 26)); + buf.buf.appendInt(value, 4); + } else { + buf.buf.appendUint8(uint8((major << 5) | 27)); + buf.buf.appendInt(value, 8); + } + } + + function writeIndefiniteLengthType(CBORBuffer memory buf, uint8 major) + private + pure + { + buf.buf.appendUint8(uint8((major << 5) | 31)); + } + + function writeDefiniteLengthType(CBORBuffer memory buf, uint8 major, uint64 length) + private + pure + { + writeFixedNumeric(buf, major, length); + } + + function writeContentFree(CBORBuffer memory buf, uint8 value) private pure { + buf.buf.appendUint8(uint8((MAJOR_TYPE_CONTENT_FREE << 5) | value)); + } +} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol new file mode 100644 index 0000000..4d49cf2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; + +abstract contract AuthorizedReceiver is IAuthorizedReceiver { + using EnumerableSet for EnumerableSet.AddressSet; + + event AuthorizedSendersChanged(address[] senders, address changedBy); + + error EmptySendersList(); + error UnauthorizedSender(); + error NotAllowedToSetSenders(); + + EnumerableSet.AddressSet private s_authorizedSenders; + address[] private s_authorizedSendersList; + + /** + * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. + * @param senders The addresses of the authorized Chainlink node + */ + function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter { + if (senders.length == 0) { + revert EmptySendersList(); + } + for (uint256 i = 0; i < s_authorizedSendersList.length; i++) { + s_authorizedSenders.remove(s_authorizedSendersList[i]); + } + for (uint256 i = 0; i < senders.length; i++) { + s_authorizedSenders.add(senders[i]); + } + s_authorizedSendersList = senders; + emit AuthorizedSendersChanged(senders, msg.sender); + } + + /** + * @notice Retrieve a list of authorized senders + * @return array of addresses + */ + function getAuthorizedSenders() public view override returns (address[] memory) { + return s_authorizedSendersList; + } + + /** + * @notice Use this to check if a node is authorized for fulfilling requests + * @param sender The address of the Chainlink node + * @return The authorization status of the node + */ + function isAuthorizedSender(address sender) public view override returns (bool) { + return s_authorizedSenders.contains(sender); + } + + /** + * @notice customizable guard of who can update the authorized sender list + * @return bool whether sender can update authorized sender list + */ + function _canSetAuthorizedSenders() internal virtual returns (bool); + + /** + * @notice validates the sender is an authorized sender + */ + function _validateIsAuthorizedSender() internal view { + if (!isAuthorizedSender(msg.sender)) { + revert UnauthorizedSender(); + } + } + + /** + * @notice prevents non-authorized addresses from calling this method + */ + modifier validateAuthorizedSender() { + _validateIsAuthorizedSender(); + _; + } + + /** + * @notice prevents non-authorized addresses from calling this method + */ + modifier validateAuthorizedSenderSetter() { + if (!_canSetAuthorizedSenders()) { + revert NotAllowedToSetSenders(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol new file mode 100644 index 0000000..cf29f14 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity 0.8.19; + +import {ChainSpecificUtil} from "../ChainSpecificUtil.sol"; + +/** + * @title BatchBlockhashStore + * @notice The BatchBlockhashStore contract acts as a proxy to write many blockhashes to the + * provided BlockhashStore contract efficiently in a single transaction. This results + * in plenty of gas savings and higher throughput of blockhash storage, which is desirable + * in times of high network congestion. + */ +contract BatchBlockhashStore { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStore public immutable BHS; + + constructor(address blockhashStoreAddr) { + BHS = BlockhashStore(blockhashStoreAddr); + } + + /** + * @notice stores blockhashes of the given block numbers in the configured blockhash store, assuming + * they are availble though the blockhash() instruction. + * @param blockNumbers the block numbers to store the blockhashes of. Must be available via the + * blockhash() instruction, otherwise this function call will revert. + */ + function store(uint256[] memory blockNumbers) public { + for (uint256 i = 0; i < blockNumbers.length; i++) { + // skip the block if it's not storeable, the caller will have to check + // after the transaction is mined to see if the blockhash was truly stored. + if (!_storeableBlock(blockNumbers[i])) { + continue; + } + BHS.store(blockNumbers[i]); + } + } + + /** + * @notice stores blockhashes after verifying blockheader of child/subsequent block + * @param blockNumbers the block numbers whose blockhashes should be stored, in decreasing order + * @param headers the rlp-encoded block headers of blockNumbers[i] + 1. + */ + function storeVerifyHeader(uint256[] memory blockNumbers, bytes[] memory headers) public { + // solhint-disable-next-line gas-custom-errors + require(blockNumbers.length == headers.length, "input array arg lengths mismatch"); + for (uint256 i = 0; i < blockNumbers.length; i++) { + BHS.storeVerifyHeader(blockNumbers[i], headers[i]); + } + } + + /** + * @notice retrieves blockhashes of all the given block numbers from the blockhash store, if available. + * @param blockNumbers array of block numbers to fetch blockhashes for + * @return blockhashes array of block hashes corresponding to each block number provided in the `blockNumbers` + * param. If the blockhash is not found, 0x0 is returned instead of the real blockhash, indicating + * that it is not in the blockhash store. + */ + function getBlockhashes(uint256[] memory blockNumbers) external view returns (bytes32[] memory) { + bytes32[] memory blockHashes = new bytes32[](blockNumbers.length); + for (uint256 i = 0; i < blockNumbers.length; i++) { + try BHS.getBlockhash(blockNumbers[i]) returns (bytes32 bh) { + blockHashes[i] = bh; + } catch Error(string memory /* reason */) { + blockHashes[i] = 0x0; + } + } + return blockHashes; + } + + /** + * @notice returns true if and only if the given block number's blockhash can be retrieved + * using the blockhash() instruction. + * @param blockNumber the block number to check if it's storeable with blockhash() + */ + function _storeableBlock(uint256 blockNumber) private view returns (bool) { + // handle edge case on simulated chains which possibly have < 256 blocks total. + return + ChainSpecificUtil._getBlockNumber() <= 256 ? true : blockNumber >= (ChainSpecificUtil._getBlockNumber() - 256); + } +} + +// solhint-disable-next-line interface-starts-with-i +interface BlockhashStore { + function storeVerifyHeader(uint256 n, bytes memory header) external; + + function store(uint256 n) external; + + function getBlockhash(uint256 n) external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol new file mode 100644 index 0000000..bcea106 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity 0.8.6; + +import {VRFTypes} from "./VRFTypes.sol"; + +/** + * @title BatchVRFCoordinatorV2 + * @notice The BatchVRFCoordinatorV2 contract acts as a proxy to write many random responses to the + * provided VRFCoordinatorV2 contract efficiently in a single transaction. + */ +contract BatchVRFCoordinatorV2 { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + VRFCoordinatorV2 public immutable COORDINATOR; + + event ErrorReturned(uint256 indexed requestId, string reason); + event RawErrorReturned(uint256 indexed requestId, bytes lowLevelData); + + constructor(address coordinatorAddr) { + COORDINATOR = VRFCoordinatorV2(coordinatorAddr); + } + + /** + * @notice fulfills multiple randomness requests with the provided proofs and commitments. + * @param proofs the randomness proofs generated by the VRF provider. + * @param rcs the request commitments corresponding to the randomness proofs. + */ + function fulfillRandomWords(VRFTypes.Proof[] calldata proofs, VRFTypes.RequestCommitment[] memory rcs) external { + // solhint-disable-next-line gas-custom-errors + require(proofs.length == rcs.length, "input array arg lengths mismatch"); + for (uint256 i = 0; i < proofs.length; i++) { + try COORDINATOR.fulfillRandomWords(proofs[i], rcs[i]) returns (uint96 /* payment */) { + continue; + } catch Error(string memory reason) { + uint256 requestId = _getRequestIdFromProof(proofs[i]); + emit ErrorReturned(requestId, reason); + } catch (bytes memory lowLevelData) { + uint256 requestId = _getRequestIdFromProof(proofs[i]); + emit RawErrorReturned(requestId, lowLevelData); + } + } + } + + /** + * @notice Returns the proving key hash associated with this public key. + * @param publicKey the key to return the hash of. + */ + function _hashOfKey(uint256[2] memory publicKey) internal pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Returns the request ID of the request associated with the given proof. + * @param proof the VRF proof provided by the VRF oracle. + */ + function _getRequestIdFromProof(VRFTypes.Proof memory proof) internal pure returns (uint256) { + bytes32 keyHash = _hashOfKey(proof.pk); + return uint256(keccak256(abi.encode(keyHash, proof.seed))); + } +} + +// solhint-disable-next-line interface-starts-with-i +interface VRFCoordinatorV2 { + function fulfillRandomWords( + VRFTypes.Proof calldata proof, + VRFTypes.RequestCommitment memory rc + ) external returns (uint96); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol new file mode 100644 index 0000000..161800f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "../automation/interfaces/AutomationCompatibleInterface.sol"; +import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; +import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; + +// solhint-disable chainlink-solidity/prefix-immutable-variables-with-i + +/** + * @title KeepersVRFConsumer + * @notice KeepersVRFConsumer is a Chainlink Keepers compatible contract that also acts as a + * VRF V2 requester and consumer. In particular, a random words request is made when `performUpkeep` + * is called in a cadence provided by the upkeep interval. + */ +contract KeepersVRFConsumer is KeeperCompatibleInterface, VRFConsumerBaseV2 { + // Upkeep interval in seconds. This contract's performUpkeep method will + // be called by the Keepers network roughly every UPKEEP_INTERVAL seconds. + uint256 public immutable UPKEEP_INTERVAL; + + // VRF V2 information, provided upon contract construction. + VRFCoordinatorV2Interface public immutable COORDINATOR; + uint64 public immutable SUBSCRIPTION_ID; + uint16 public immutable REQUEST_CONFIRMATIONS; + bytes32 public immutable KEY_HASH; + + // Contract state, updated in performUpkeep and fulfillRandomWords. + uint256 public s_lastTimeStamp; + uint256 public s_vrfRequestCounter; + uint256 public s_vrfResponseCounter; + + struct RequestRecord { + uint256 requestId; + bool fulfilled; + uint32 callbackGasLimit; + uint256 randomness; + } + mapping(uint256 => RequestRecord) public s_requests; /* request ID */ /* request record */ + + constructor( + address vrfCoordinator, + uint64 subscriptionId, + bytes32 keyHash, + uint16 requestConfirmations, + uint256 upkeepInterval + ) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + SUBSCRIPTION_ID = subscriptionId; + REQUEST_CONFIRMATIONS = requestConfirmations; + KEY_HASH = keyHash; + UPKEEP_INTERVAL = upkeepInterval; + + s_lastTimeStamp = block.timestamp; + s_vrfRequestCounter = 0; + s_vrfResponseCounter = 0; + } + + /** + * @notice Returns true if and only if at least UPKEEP_INTERVAL seconds have elapsed + * since the last upkeep or since construction of the contract. + * @return upkeepNeeded true if and only if at least UPKEEP_INTERVAL seconds have elapsed since the last upkeep or since construction + * of the contract. + */ + // solhint-disable-next-line chainlink-solidity/explicit-returns + function checkUpkeep( + bytes calldata /* checkData */ + ) external view override returns (bool upkeepNeeded, bytes memory /* performData */) { + upkeepNeeded = (block.timestamp - s_lastTimeStamp) > UPKEEP_INTERVAL; + } + + /** + * @notice Requests random words from the VRF coordinator if UPKEEP_INTERVAL seconds have elapsed + * since the last upkeep or since construction of the contract. + */ + function performUpkeep(bytes calldata /* performData */) external override { + if ((block.timestamp - s_lastTimeStamp) > UPKEEP_INTERVAL) { + s_lastTimeStamp = block.timestamp; + + _requestRandomWords(); + } + } + + /** + * @notice VRF callback implementation + * @param requestId the VRF V2 request ID, provided at request time. + * @param randomWords the randomness provided by Chainlink VRF. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + // Check that the request exists. If not, revert. + RequestRecord memory record = s_requests[requestId]; + // solhint-disable-next-line gas-custom-errors + require(record.requestId == requestId, "request ID not found in map"); + + // Update the randomness in the record, and increment the response counter. + s_requests[requestId].randomness = randomWords[0]; + s_vrfResponseCounter++; + } + + /** + * @notice Requests random words from Chainlink VRF. + */ + function _requestRandomWords() internal { + uint256 requestId = COORDINATOR.requestRandomWords( + KEY_HASH, + SUBSCRIPTION_ID, + REQUEST_CONFIRMATIONS, + 150000, // callback gas limit + 1 // num words + ); + s_requests[requestId] = RequestRecord({ + requestId: requestId, + fulfilled: false, + callbackGasLimit: 150000, + randomness: 0 + }); + s_vrfRequestCounter++; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol new file mode 100644 index 0000000..7f11569 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol @@ -0,0 +1,588 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** **************************************************************************** + * @notice Verification of verifiable-random-function (VRF) proofs, following + * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. + + * @dev Bibliographic references: + + * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft + * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 + + * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology + * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf + * **************************************************************************** + * @dev USAGE + + * @dev The main entry point is _randomValueFromVRFProof. See its docstring. + * **************************************************************************** + * @dev PURPOSE + + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is computationally indistinguishable to her from a uniform + * @dev random sample from the output space. + + * @dev The purpose of this contract is to perform that verification. + * **************************************************************************** + * @dev DESIGN NOTES + + * @dev The VRF algorithm verified here satisfies the full uniqueness, full + * @dev collision resistance, and full pseudo-randomness security properties. + * @dev See "SECURITY PROPERTIES" below, and + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 + + * @dev An elliptic curve point is generally represented in the solidity code + * @dev as a uint256[2], corresponding to its affine coordinates in + * @dev GF(FIELD_SIZE). + + * @dev For the sake of efficiency, this implementation deviates from the spec + * @dev in some minor ways: + + * @dev - Keccak hash rather than the SHA256 hash recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev Keccak costs much less gas on the EVM, and provides similar security. + + * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER + + * @dev - _hashToCurve recursively hashes until it finds a curve x-ordinate. On + * @dev the EVM, this is slightly more efficient than the recommendation in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + * @dev step 5, to concatenate with a nonce then hash, and rehash with the + * @dev nonce updated until a valid x-ordinate is found. + + * @dev - _hashToCurve does not include a cipher version string or the byte 0x1 + * @dev in the hash message, as recommended in step 5.B of the draft + * @dev standard. They are unnecessary here because no variation in the + * @dev cipher suite is allowed. + + * @dev - Similarly, the hash input in _scalarFromCurvePoints does not include a + * @dev commitment to the cipher suite, either, which differs from step 2 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + * @dev . Also, the hash input is the concatenation of the uncompressed + * @dev points, not the compressed points as recommended in step 3. + + * @dev - In the calculation of the challenge value "c", the "u" value (i.e. + * @dev the value computed by Reggie as the nonce times the secp256k1 + * @dev generator point, see steps 5 and 7 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the + * @dev keccak hash of the original u. This is because we only verify the + * @dev calculation of u up to its address, by abusing ECRECOVER. + * **************************************************************************** + * @dev SECURITY PROPERTIES + + * @dev Here are the security properties for this VRF: + + * @dev Full uniqueness: For any seed and valid VRF public key, there is + * @dev exactly one VRF output which can be proved to come from that seed, in + * @dev the sense that the proof will pass _verifyVRFProof. + + * @dev Full collision resistance: It's cryptographically infeasible to find + * @dev two seeds with same VRF output from a fixed, valid VRF key + + * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are + * @dev derived from a given seed, the outputs are computationally + * @dev indistinguishable from randomness. + + * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs + * @dev for these properties. + + * @dev For secp256k1, the key validation described in section + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 + * @dev is unnecessary, because secp256k1 has cofactor 1, and the + * @dev representation of the public key used here (affine x- and y-ordinates + * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to + * @dev the point at infinity. + * **************************************************************************** + * @dev OTHER SECURITY CONSIDERATIONS + * + * @dev The seed input to the VRF could in principle force an arbitrary amount + * @dev of work in _hashToCurve, by requiring extra rounds of hashing and + * @dev checking whether that's yielded the x ordinate of a secp256k1 point. + * @dev However, under the Random Oracle Model the probability of choosing a + * @dev point which forces n extra rounds in _hashToCurve is 2⁻ⁿ. The base cost + * @dev for calling _hashToCurve is about 25,000 gas, and each round of checking + * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for + * @dev which _hashToCurve would cost more than 2,017,000 gas, one would have to + * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any + * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) + + * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, + * @dev this means it is infeasible for an adversary to prevent correct + * @dev operation of this contract by choosing an adverse seed. + + * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for + * @dev _hashToCurve.) + + * @dev It may be possible to make a secure constant-time _hashToCurve function. + * @dev See notes in _hashToCurve docstring. +*/ +contract VRF { + // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. + // Number of points in Secp256k1 + uint256 private constant GROUP_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; + // Prime characteristic of the galois field over which Secp256k1 is defined + uint256 private constant FIELD_SIZE = + // solium-disable-next-line indentation + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; + uint256 private constant WORD_LENGTH_BYTES = 0x20; + + // (base^exponent) % FIELD_SIZE + // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 + function _bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { + uint256 callResult; + uint256[6] memory bigModExpContractInputs; + bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base + bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent + bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus + bigModExpContractInputs[3] = base; + bigModExpContractInputs[4] = exponent; + bigModExpContractInputs[5] = FIELD_SIZE; + uint256[1] memory output; + assembly { + callResult := staticcall( + not(0), // Gas cost: no limit + 0x05, // Bigmodexp contract address + bigModExpContractInputs, + 0xc0, // Length of input segment: 6*0x20-bytes + output, + 0x20 // Length of output segment + ) + } + if (callResult == 0) { + // solhint-disable-next-line gas-custom-errors + revert("bigModExp failure!"); + } + return output[0]; + } + + // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See + // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus + uint256 private constant SQRT_POWER = (FIELD_SIZE + 1) >> 2; + + // Computes a s.t. a^2 = x in the field. Assumes a exists + function _squareRoot(uint256 x) internal view returns (uint256) { + return _bigModExp(x, SQRT_POWER); + } + + // The value of y^2 given that (x,y) is on secp256k1. + function _ySquared(uint256 x) internal pure returns (uint256) { + // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf + uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); + return addmod(xCubed, 7, FIELD_SIZE); + } + + // True iff p is on secp256k1 + function _isOnCurve(uint256[2] memory p) internal pure returns (bool) { + // Section 2.3.6. in https://www.secg.org/sec1-v2.pdf + // requires each ordinate to be in [0, ..., FIELD_SIZE-1] + // solhint-disable-next-line gas-custom-errors + require(p[0] < FIELD_SIZE, "invalid x-ordinate"); + // solhint-disable-next-line gas-custom-errors + require(p[1] < FIELD_SIZE, "invalid y-ordinate"); + return _ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); + } + + // Hash x uniformly into {0, ..., FIELD_SIZE-1}. + function _fieldHash(bytes memory b) internal pure returns (uint256 x_) { + x_ = uint256(keccak256(b)); + // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of + // http://www.secg.org/sec1-v2.pdf , which is part of the definition of + // string_to_point in the IETF draft + while (x_ >= FIELD_SIZE) { + x_ = uint256(keccak256(abi.encodePacked(x_))); + } + return x_; + } + + // Hash b to a random point which hopefully lies on secp256k1. The y ordinate + // is always even, due to + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + // step 5.C, which references arbitrary_string_to_point, defined in + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as + // returning the point with given x ordinate, and even y ordinate. + function _newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { + unchecked { + p[0] = _fieldHash(b); + p[1] = _squareRoot(_ySquared(p[0])); + if (p[1] % 2 == 1) { + // Note that 0 <= p[1] < FIELD_SIZE + // so this cannot wrap, we use unchecked to save gas. + p[1] = FIELD_SIZE - p[1]; + } + } + return p; + } + + // Domain-separation tag for initial hash in _hashToCurve. Corresponds to + // vrf.go/hashToCurveHashPrefix + uint256 internal constant HASH_TO_CURVE_HASH_PREFIX = 1; + + // Cryptographic hash function onto the curve. + // + // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see + // DESIGN NOTES above for slight differences.) + // + // TODO(alx): Implement a bounded-computation hash-to-curve, as described in + // "Construction of Rational Points on Elliptic Curves over Finite Fields" + // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf + // and suggested by + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 + // (Though we can't used exactly that because secp256k1's j-invariant is 0.) + // + // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" + // https://www.pivotaltracker.com/story/show/171120900 + function _hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); + while (!_isOnCurve(rv)) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(rv[0])); + } + return rv; + } + + /** ********************************************************************* + * @notice Check that product==scalar*multiplicand + * + * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. + * + * @param multiplicand: secp256k1 point + * @param scalar: non-zero GF(GROUP_ORDER) scalar + * @param product: secp256k1 expected to be multiplier * multiplicand + * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability + */ + function _ecmulVerify( + uint256[2] memory multiplicand, + uint256 scalar, + uint256[2] memory product + ) internal pure returns (bool verifies) { + // solhint-disable-next-line gas-custom-errors + require(scalar != 0, "zero scalar"); // Rules out an ecrecover failure case + uint256 x = multiplicand[0]; // x ordinate of multiplicand + uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is + // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. + // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 + bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); + address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); + // Explicit conversion to address takes bottom 160 bits + address expected = address(uint160(uint256(keccak256(abi.encodePacked(product))))); + return (actual == expected); + } + + // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) + function _projectiveSub( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + unchecked { + uint256 num1 = mulmod(z2, x1, FIELD_SIZE); + // Note this cannot wrap since x2 is a point in [0, FIELD_SIZE-1] + // we use unchecked to save gas. + uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); + (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + } + return (x3, z3); + } + + // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) + function _projectiveMul( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + return (x3, z3); + } + + /** ************************************************************************** + @notice Computes elliptic-curve sum, in projective co-ordinates + + @dev Using projective coordinates avoids costly divisions + + @dev To use this with p and q in affine coordinates, call + @dev _projectiveECAdd(px, py, qx, qy). This will return + @dev the addition of (px, py, 1) and (qx, qy, 1), in the + @dev secp256k1 group. + + @dev This can be used to calculate the z which is the inverse to zInv + @dev in isValidVRFOutput. But consider using a faster + @dev re-implementation such as ProjectiveECAdd in the golang vrf package. + + @dev This function assumes [px,py,1],[qx,qy,1] are valid projective + coordinates of secp256k1 points. That is safe in this contract, + because this method is only used by _linearCombination, which checks + points are on the curve via ecrecover. + ************************************************************************** + @param px The first affine coordinate of the first summand + @param py The second affine coordinate of the first summand + @param qx The first affine coordinate of the second summand + @param qy The second affine coordinate of the second summand + + (px,py) and (qx,qy) must be distinct, valid secp256k1 points. + ************************************************************************** + Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points + on secp256k1, in P²(𝔽ₙ) + @return sx + @return sy + @return sz + */ + function _projectiveECAdd( + uint256 px, + uint256 py, + uint256 qx, + uint256 qy + ) internal pure returns (uint256 sx, uint256 sy, uint256 sz) { + unchecked { + // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, + // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone + // We take the equations there for (sx,sy), and homogenize them to + // projective coordinates. That way, no inverses are required, here, and we + // only need the one inverse in _affineECAdd. + + // We only need the "point addition" equations from Hankerson et al. Can + // skip the "point doubling" equations because p1 == p2 is cryptographically + // impossible, and required not to be the case in _linearCombination. + + // Add extra "projective coordinate" to the two points + (uint256 z1, uint256 z2) = (1, 1); + + // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. + // Cannot wrap since px and py are in [0, FIELD_SIZE-1] + uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); + uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); + + uint256 dx; // Accumulates denominator from sx calculation + // sx=((qy-py)/(qx-px))^2-px-qx + (sx, dx) = _projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 + (sx, dx) = _projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px + (sx, dx) = _projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx + + uint256 dy; // Accumulates denominator from sy calculation + // sy=((qy-py)/(qx-px))(px-sx)-py + (sy, dy) = _projectiveSub(px, z1, sx, dx); // px-sx + (sy, dy) = _projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) + (sy, dy) = _projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py + + if (dx != dy) { + // Cross-multiply to put everything over a common denominator + sx = mulmod(sx, dy, FIELD_SIZE); + sy = mulmod(sy, dx, FIELD_SIZE); + sz = mulmod(dx, dy, FIELD_SIZE); + } else { + // Already over a common denominator, use that for z ordinate + sz = dx; + } + } + return (sx, sy, sz); + } + + // p1+p2, as affine points on secp256k1. + // + // invZ must be the inverse of the z returned by _projectiveECAdd(p1, p2). + // It is computed off-chain to save gas. + // + // p1 and p2 must be distinct, because _projectiveECAdd doesn't handle + // point doubling. + function _affineECAdd( + uint256[2] memory p1, + uint256[2] memory p2, + uint256 invZ + ) internal pure returns (uint256[2] memory) { + uint256 x; + uint256 y; + uint256 z; + (x, y, z) = _projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); + // solhint-disable-next-line gas-custom-errors + require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); + // Clear the z ordinate of the projective representation by dividing through + // by it, to obtain the affine representation + return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; + } + + // True iff address(c*p+s*g) == lcWitness, where g is generator. (With + // cryptographically high probability.) + function _verifyLinearCombinationWithGenerator( + uint256 c, + uint256[2] memory p, + uint256 s, + address lcWitness + ) internal pure returns (bool) { + // Rule out ecrecover failure modes which return address 0. + unchecked { + // solhint-disable-next-line gas-custom-errors + require(lcWitness != address(0), "bad witness"); + uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p + // Note this cannot wrap (X - Y % X), but we use unchecked to save + // gas. + bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] + bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // The point corresponding to the address returned by + // ecrecover(-s*p[0],v,p[0],c*p[0]) is + // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. + // See https://crypto.stackexchange.com/a/18106 + // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v + address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); + return computed == lcWitness; + } + } + + // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also + // requires cp1Witness != sp2Witness (which is fine for this application, + // since it is cryptographically impossible for them to be equal. In the + // (cryptographically impossible) case that a prover accidentally derives + // a proof with equal c*p1 and s*p2, they should retry with a different + // proof nonce.) Assumes that all points are on secp256k1 + // (which is checked in _verifyVRFProof below.) + function _linearCombination( + uint256 c, + uint256[2] memory p1, + uint256[2] memory cp1Witness, + uint256 s, + uint256[2] memory p2, + uint256[2] memory sp2Witness, + uint256 zInv + ) internal pure returns (uint256[2] memory) { + unchecked { + // Note we are relying on the wrap around here + // solhint-disable-next-line gas-custom-errors + require((cp1Witness[0] % FIELD_SIZE) != (sp2Witness[0] % FIELD_SIZE), "points in sum must be distinct"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p1, c, cp1Witness), "First mul check failed"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p2, s, sp2Witness), "Second mul check failed"); + return _affineECAdd(cp1Witness, sp2Witness, zInv); + } + } + + // Domain-separation tag for the hash taken in _scalarFromCurvePoints. + // Corresponds to scalarFromCurveHashPrefix in vrf.go + uint256 internal constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; + + // Pseudo-random number from inputs. Matches vrf.go/_scalarFromCurvePoints, and + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + // The draft calls (in step 7, via the definition of string_to_int, in + // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the + // first hash without checking that it corresponds to a number less than the + // group order, which will lead to a slight bias in the sample. + // + // TODO(alx): We could save a bit of gas by following the standard here and + // using the compressed representation of the points, if we collated the y + // parities into a single bytes32. + // https://www.pivotaltracker.com/story/show/171120588 + function _scalarFromCurvePoints( + uint256[2] memory hash, + uint256[2] memory pk, + uint256[2] memory gamma, + address uWitness, + uint256[2] memory v + ) internal pure returns (uint256 s) { + return uint256(keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); + } + + // True if (gamma, c, s) is a correctly constructed randomness proof from pk + // and seed. zInv must be the inverse of the third ordinate from + // _projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to + // section 5.3 of the IETF draft. + // + // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass + // the x ordinate, and the parity of the y ordinate in the top bit of uWitness + // (which I could make a uint256 without using any extra space.) Would save + // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 + function _verifyVRFProof( + uint256[2] memory pk, + uint256[2] memory gamma, + uint256 c, + uint256 s, + uint256 seed, + address uWitness, + uint256[2] memory cGammaWitness, + uint256[2] memory sHashWitness, + uint256 zInv + ) internal view { + unchecked { + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(pk), "public key is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(gamma), "gamma is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(sHashWitness), "sHashWitness is not on curve"); + // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here + // we use the address of u instead of u itself. Also, here we add the + // terms instead of taking the difference, and in the proof construction in + // vrf.GenerateProof, we correspondingly take the difference instead of + // taking the sum as they do in step 7 of section 5.1.) + // solhint-disable-next-line gas-custom-errors + require(_verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)!=_uWitness"); + // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) + uint256[2] memory hash = _hashToCurve(pk, seed); + // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms + uint256[2] memory v = _linearCombination(c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); + // Steps 7. and 8. of IETF draft section 5.3 + uint256 derivedC = _scalarFromCurvePoints(hash, pk, gamma, uWitness, v); + // solhint-disable-next-line gas-custom-errors + require(c == derivedC, "invalid proof"); + } + } + + // Domain-separation tag for the hash used as the final VRF output. + // Corresponds to vrfRandomOutputHashPrefix in vrf.go + uint256 internal constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; + + struct Proof { + uint256[2] pk; + uint256[2] gamma; + uint256 c; + uint256 s; + uint256 seed; + address uWitness; + uint256[2] cGammaWitness; + uint256[2] sHashWitness; + uint256 zInv; + } + + /* *************************************************************************** + * @notice Returns proof's output, if proof is valid. Otherwise reverts + + * @param proof vrf proof components + * @param seed seed used to generate the vrf output + * + * Throws if proof is invalid, otherwise: + * @return output i.e., the random output implied by the proof + * *************************************************************************** + */ + function _randomValueFromVRFProof(Proof calldata proof, uint256 seed) internal view returns (uint256 output) { + _verifyVRFProof( + proof.pk, + proof.gamma, + proof.c, + proof.s, + seed, + proof.uWitness, + proof.cGammaWitness, + proof.sHashWitness, + proof.zInv + ); + output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, proof.gamma))); + return output; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol new file mode 100644 index 0000000..3d73b70 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; + +import {VRFRequestIDBase} from "./VRFRequestIDBase.sol"; + +/** **************************************************************************** + * @notice Interface for contracts using VRF randomness + * ***************************************************************************** + * @dev PURPOSE + * + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + * + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is indistinguishable to her from a uniform random sample + * @dev from the output space. + * + * @dev The purpose of this contract is to make it easy for unrelated contracts + * @dev to talk to Vera the verifier about the work Reggie is doing, to provide + * @dev simple access to a verifiable source of randomness. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFConsumerBase, and can + * @dev initialize VRFConsumerBase's attributes in their constructor as + * @dev shown: + * + * @dev contract VRFConsumer { + * @dev constructor(, address _vrfCoordinator, address _link) + * @dev VRFConsumerBase(_vrfCoordinator, _link) public { + * @dev + * @dev } + * @dev } + * + * @dev The oracle will have given you an ID for the VRF keypair they have + * @dev committed to (let's call it keyHash), and have told you the minimum LINK + * @dev price for VRF service. Make sure your contract has sufficient LINK, and + * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you + * @dev want to generate randomness from. + * + * @dev Once the VRFCoordinator has received and validated the oracle's response + * @dev to your request, it will call your contract's fulfillRandomness method. + * + * @dev The randomness argument to fulfillRandomness is the actual random value + * @dev generated from your seed. + * + * @dev The requestId argument is generated from the keyHash and the seed by + * @dev makeRequestId(keyHash, seed). If your contract could have concurrent + * @dev requests open, you can use the requestId to track which seed is + * @dev associated with which randomness. See VRFRequestIDBase.sol for more + * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, + * @dev if your contract could have multiple requests in flight simultaneously.) + * + * @dev Colliding `requestId`s are cryptographically impossible as long as seeds + * @dev differ. (Which is critical to making unpredictable randomness! See the + * @dev next section.) + * + * ***************************************************************************** + * @dev SECURITY CONSIDERATIONS + * + * @dev A method with the ability to call your fulfillRandomness method directly + * @dev could spoof a VRF response with any random value, so it's critical that + * @dev it cannot be directly called by anything other than this base contract + * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). + * + * @dev For your users to trust that your contract's random behavior is free + * @dev from malicious interference, it's best if you can write it so that all + * @dev behaviors implied by a VRF response are executed *during* your + * @dev fulfillRandomness method. If your contract must store the response (or + * @dev anything derived from it) and use it later, you must ensure that any + * @dev user-significant behavior which depends on that stored value cannot be + * @dev manipulated by a subsequent VRF request. + * + * @dev Similarly, both miners and the VRF oracle itself have some influence + * @dev over the order in which VRF responses appear on the blockchain, so if + * @dev your contract could have multiple VRF requests in flight simultaneously, + * @dev you must ensure that the order in which the VRF responses arrive cannot + * @dev be used to manipulate your contract's user-significant behavior. + * + * @dev Since the ultimate input to the VRF is mixed with the block hash of the + * @dev block in which the request is made, user-provided seeds have no impact + * @dev on its economic security properties. They are only included for API + * @dev compatability with previous versions of this contract. + * + * @dev Since the block hash of the block which contains the requestRandomness + * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful + * @dev miner could, in principle, fork the blockchain to evict the block + * @dev containing the request, forcing the request to be included in a + * @dev different block with a different hash, and therefore a different input + * @dev to the VRF. However, such an attack would incur a substantial economic + * @dev cost. This cost scales with the number of blocks the VRF oracle waits + * @dev until it calls responds to a request. + */ +abstract contract VRFConsumerBase is VRFRequestIDBase { + /** + * @notice fulfillRandomness handles the VRF response. Your contract must + * @notice implement it. See "SECURITY CONSIDERATIONS" above for important + * @notice principles to keep in mind when implementing your fulfillRandomness + * @notice method. + * + * @dev VRFConsumerBase expects its subcontracts to have a method with this + * @dev signature, and will call it once it has verified the proof + * @dev associated with the randomness. (It is triggered via a call to + * @dev rawFulfillRandomness, below.) + * + * @param requestId The Id initially returned by requestRandomness + * @param randomness the VRF output + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual; + + /** + * @dev In order to keep backwards compatibility we have kept the user + * seed field around. We remove the use of it because given that the blockhash + * enters later, it overrides whatever randomness the used seed provides. + * Given that it adds no security, and can easily lead to misunderstandings, + * we have removed it from usage and can now provide a simpler API. + */ + uint256 private constant USER_SEED_PLACEHOLDER = 0; + + /** + * @notice requestRandomness initiates a request for VRF output given _seed + * + * @dev The fulfillRandomness method receives the output, once it's provided + * @dev by the Oracle, and verified by the vrfCoordinator. + * + * @dev The _keyHash must already be registered with the VRFCoordinator, and + * @dev the _fee must exceed the fee specified during registration of the + * @dev _keyHash. + * + * @dev The _seed parameter is vestigial, and is kept only for API + * @dev compatibility with older versions. It can't *hurt* to mix in some of + * @dev your own randomness, here, but it's not necessary because the VRF + * @dev oracle will mix the hash of the block containing your request into the + * @dev VRF seed it ultimately uses. + * + * @param _keyHash ID of public key against which randomness is generated + * @param _fee The amount of LINK to send with the request + * + * @return requestId unique ID for this request + * + * @dev The returned requestId can be used to distinguish responses to + * @dev concurrent requests. It is passed as the first argument to + * @dev fulfillRandomness. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomness(bytes32 _keyHash, uint256 _fee) internal returns (bytes32 requestId) { + LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); + // This is the seed passed to VRFCoordinator. The oracle will mix this with + // the hash of the block containing this request to obtain the seed/input + // which is finally passed to the VRF cryptographic machinery. + uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); + // nonces[_keyHash] must stay in sync with + // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above + // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). + // This provides protection against the user repeating their input seed, + // which would result in a predictable/duplicate output, if multiple such + // requests appeared in the same block. + nonces[_keyHash] = nonces[_keyHash] + 1; + return makeRequestId(_keyHash, vRFSeed); + } + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + LinkTokenInterface internal immutable LINK; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address private immutable vrfCoordinator; + + // Nonces for each VRF key from which randomness has been requested. + // + // Must stay in sync with VRFCoordinator[_keyHash][this] + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + mapping(bytes32 => uint256) /* keyHash */ /* nonce */ private nonces; + + /** + * @param _vrfCoordinator address of VRFCoordinator contract + * @param _link address of LINK token contract + * + * @dev https://docs.chain.link/docs/link-token-contracts + */ + constructor(address _vrfCoordinator, address _link) { + vrfCoordinator = _vrfCoordinator; + LINK = LinkTokenInterface(_link); + } + + // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF + // proof. rawFulfillRandomness then calls fulfillRandomness, after validating + // the origin of the call + function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); + fulfillRandomness(requestId, randomness); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol new file mode 100644 index 0000000..ad7025f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/** **************************************************************************** + * @notice Interface for contracts using VRF randomness + * ***************************************************************************** + * @dev PURPOSE + * + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + * + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is indistinguishable to her from a uniform random sample + * @dev from the output space. + * + * @dev The purpose of this contract is to make it easy for unrelated contracts + * @dev to talk to Vera the verifier about the work Reggie is doing, to provide + * @dev simple access to a verifiable source of randomness. It ensures 2 things: + * @dev 1. The fulfillment came from the VRFCoordinator + * @dev 2. The consumer contract implements fulfillRandomWords. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFConsumerBase, and can + * @dev initialize VRFConsumerBase's attributes in their constructor as + * @dev shown: + * + * @dev contract VRFConsumer { + * @dev constructor(, address _vrfCoordinator, address _link) + * @dev VRFConsumerBase(_vrfCoordinator) public { + * @dev + * @dev } + * @dev } + * + * @dev The oracle will have given you an ID for the VRF keypair they have + * @dev committed to (let's call it keyHash). Create subscription, fund it + * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface + * @dev subscription management functions). + * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, + * @dev callbackGasLimit, numWords), + * @dev see (VRFCoordinatorInterface for a description of the arguments). + * + * @dev Once the VRFCoordinator has received and validated the oracle's response + * @dev to your request, it will call your contract's fulfillRandomWords method. + * + * @dev The randomness argument to fulfillRandomWords is a set of random words + * @dev generated from your requestId and the blockHash of the request. + * + * @dev If your contract could have concurrent requests open, you can use the + * @dev requestId returned from requestRandomWords to track which response is associated + * @dev with which randomness request. + * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, + * @dev if your contract could have multiple requests in flight simultaneously. + * + * @dev Colliding `requestId`s are cryptographically impossible as long as seeds + * @dev differ. + * + * ***************************************************************************** + * @dev SECURITY CONSIDERATIONS + * + * @dev A method with the ability to call your fulfillRandomness method directly + * @dev could spoof a VRF response with any random value, so it's critical that + * @dev it cannot be directly called by anything other than this base contract + * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). + * + * @dev For your users to trust that your contract's random behavior is free + * @dev from malicious interference, it's best if you can write it so that all + * @dev behaviors implied by a VRF response are executed *during* your + * @dev fulfillRandomness method. If your contract must store the response (or + * @dev anything derived from it) and use it later, you must ensure that any + * @dev user-significant behavior which depends on that stored value cannot be + * @dev manipulated by a subsequent VRF request. + * + * @dev Similarly, both miners and the VRF oracle itself have some influence + * @dev over the order in which VRF responses appear on the blockchain, so if + * @dev your contract could have multiple VRF requests in flight simultaneously, + * @dev you must ensure that the order in which the VRF responses arrive cannot + * @dev be used to manipulate your contract's user-significant behavior. + * + * @dev Since the block hash of the block which contains the requestRandomness + * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful + * @dev miner could, in principle, fork the blockchain to evict the block + * @dev containing the request, forcing the request to be included in a + * @dev different block with a different hash, and therefore a different input + * @dev to the VRF. However, such an attack would incur a substantial economic + * @dev cost. This cost scales with the number of blocks the VRF oracle waits + * @dev until it calls responds to a request. It is for this reason that + * @dev that you can signal to an oracle you'd like them to wait longer before + * @dev responding to the request (however this is not enforced in the contract + * @dev and so remains effective only in the case of unmodified oracle software). + */ +abstract contract VRFConsumerBaseV2 { + error OnlyCoordinatorCanFulfill(address have, address want); + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address private immutable vrfCoordinator; + + /** + * @param _vrfCoordinator address of VRFCoordinator contract + */ + constructor(address _vrfCoordinator) { + vrfCoordinator = _vrfCoordinator; + } + + /** + * @notice fulfillRandomness handles the VRF response. Your contract must + * @notice implement it. See "SECURITY CONSIDERATIONS" above for important + * @notice principles to keep in mind when implementing your fulfillRandomness + * @notice method. + * + * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this + * @dev signature, and will call it once it has verified the proof + * @dev associated with the randomness. (It is triggered via a call to + * @dev rawFulfillRandomness, below.) + * + * @param requestId The Id initially returned by requestRandomness + * @param randomWords the VRF output expanded to the requested number of words + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; + + // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF + // proof. rawFulfillRandomness then calls fulfillRandomness, after validating + // the origin of the call + function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { + if (msg.sender != vrfCoordinator) { + revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); + } + fulfillRandomWords(requestId, randomWords); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol new file mode 100644 index 0000000..717826a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol @@ -0,0 +1,840 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {BlockhashStoreInterface} from "./interfaces/BlockhashStoreInterface.sol"; +import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; +import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; +import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; +import {VRF} from "./VRF.sol"; +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; +contract VRFCoordinatorV2 is VRF, ConfirmedOwner, TypeAndVersionInterface, VRFCoordinatorV2Interface, IERC677Receiver { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + LinkTokenInterface public immutable LINK; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + AggregatorV3Interface public immutable LINK_ETH_FEED; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // We need to maintain a list of consuming addresses. + // This bound ensures we are able to loop over them as needed. + // Should a user require more consumers, they can use multiple subscriptions. + uint16 public constant MAX_CONSUMERS = 100; + error TooManyConsumers(); + error InsufficientBalance(); + error InvalidConsumer(uint64 subId, address consumer); + error InvalidSubscription(); + error OnlyCallableFromLink(); + error InvalidCalldata(); + error MustBeSubOwner(address owner); + error PendingRequestExists(); + error MustBeRequestedOwner(address proposedOwner); + error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen + event FundsRecovered(address to, uint256 amount); + // We use the subscription struct (1 word) + // at fulfillment time. + struct Subscription { + // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) + uint96 balance; // Common link balance used for all consumer requests. + uint64 reqCount; // For fee tiers + } + // We use the config for the mgmt APIs + struct SubscriptionConfig { + address owner; // Owner can fund/withdraw/cancel the sub. + address requestedOwner; // For safely transferring sub ownership. + // Maintains the list of keys in s_consumers. + // We do this for 2 reasons: + // 1. To be able to clean up all keys from s_consumers when canceling a subscription. + // 2. To be able to return the list of all consumers in getSubscription. + // Note that we need the s_consumers map to be able to directly check if a + // consumer is valid without reading all the consumers from storage. + address[] consumers; + } + // Note a nonce of 0 indicates an the consumer is not assigned to that subscription. + mapping(address => mapping(uint64 => uint64)) /* consumer */ /* subId */ /* nonce */ private s_consumers; + mapping(uint64 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ private s_subscriptionConfigs; + mapping(uint64 => Subscription) /* subId */ /* subscription */ private s_subscriptions; + // We make the sub count public so that its possible to + // get all the current subscriptions via getSubscription. + uint64 private s_currentSubId; + // s_totalBalance tracks the total link sent to/from + // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. + // A discrepancy with this contract's link balance indicates someone + // sent tokens using transfer and so we may need to use recoverFunds. + uint96 private s_totalBalance; + event SubscriptionCreated(uint64 indexed subId, address owner); + event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionConsumerAdded(uint64 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subId, address consumer); + event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); + event SubscriptionOwnerTransferRequested(uint64 indexed subId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subId, address from, address to); + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error InsufficientGasForConsumer(uint256 have, uint256 want); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error Reentrant(); + struct RequestCommitment { + uint64 blockNum; + uint64 subId; + uint32 callbackGasLimit; + uint32 numWords; + address sender; + } + mapping(bytes32 => address) /* keyHash */ /* oracle */ private s_provingKeys; + bytes32[] private s_provingKeyHashes; + mapping(address => uint96) /* oracle */ /* LINK balance */ private s_withdrawableTokens; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ private s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); + event ProvingKeyDeregistered(bytes32 keyHash, address indexed oracle); + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint64 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); + + struct Config { + uint16 minimumRequestConfirmations; + uint32 maxGasLimit; + // Reentrancy protection. + bool reentrancyLock; + // stalenessSeconds is how long before we consider the feed price to be stale + // and fallback to fallbackWeiPerUnitLink. + uint32 stalenessSeconds; + // Gas to cover oracle payment after we calculate the payment. + // We make it configurable in case those operations are repriced. + uint32 gasAfterPaymentCalculation; + } + int256 private s_fallbackWeiPerUnitLink; + Config private s_config; + FeeConfig private s_feeConfig; + struct FeeConfig { + // Flat fee charged per fulfillment in millionths of link + // So fee range is [0, 2^32/10^6]. + uint32 fulfillmentFlatFeeLinkPPMTier1; + uint32 fulfillmentFlatFeeLinkPPMTier2; + uint32 fulfillmentFlatFeeLinkPPMTier3; + uint32 fulfillmentFlatFeeLinkPPMTier4; + uint32 fulfillmentFlatFeeLinkPPMTier5; + uint24 reqsForTier2; + uint24 reqsForTier3; + uint24 reqsForTier4; + uint24 reqsForTier5; + } + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig feeConfig + ); + + constructor(address link, address blockhashStore, address linkEthFeed) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(link); + LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to an oracle. + * @param oracle address of the oracle + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh] != address(0)) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = oracle; + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, oracle); + } + + /** + * @notice Deregisters a proving key to an oracle. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + address oracle = s_provingKeys[kh]; + if (oracle == address(0)) { + revert NoSuchProvingKey(kh); + } + delete s_provingKeys[kh]; + for (uint256 i = 0; i < s_provingKeyHashes.length; i++) { + if (s_provingKeyHashes[i] == kh) { + bytes32 last = s_provingKeyHashes[s_provingKeyHashes.length - 1]; + // Copy last element and overwrite kh to be deleted with it + s_provingKeyHashes[i] = last; + s_provingKeyHashes.pop(); + } + } + emit ProvingKeyDeregistered(kh, oracle); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed + * @param feeConfig fee tier configuration + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig memory feeConfig + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false + }); + s_feeConfig = feeConfig; + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + s_feeConfig + ); + } + + function getConfig() + external + view + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ) + { + return ( + s_config.minimumRequestConfirmations, + s_config.maxGasLimit, + s_config.stalenessSeconds, + s_config.gasAfterPaymentCalculation + ); + } + + function getFeeConfig() + external + view + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ) + { + return ( + s_feeConfig.fulfillmentFlatFeeLinkPPMTier1, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier2, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier3, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier4, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier5, + s_feeConfig.reqsForTier2, + s_feeConfig.reqsForTier3, + s_feeConfig.reqsForTier4, + s_feeConfig.reqsForTier5 + ); + } + + function getTotalBalance() external view returns (uint256) { + return s_totalBalance; + } + + function getFallbackWeiPerUnitLink() external view returns (int256) { + return s_fallbackWeiPerUnitLink; + } + + /** + * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + * @param subId subscription id + * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + */ + function ownerCancelSubscription(uint64 subId) external onlyOwner { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + _cancelSubscriptionHelper(subId, s_subscriptionConfigs[subId].owner); + } + + /** + * @notice Recover link sent with transfer instead of transferAndCall. + * @param to address to send link to + */ + function recoverFunds(address to) external onlyOwner { + uint256 externalBalance = LINK.balanceOf(address(this)); + uint256 internalBalance = uint256(s_totalBalance); + if (internalBalance > externalBalance) { + revert BalanceInvariantViolated(internalBalance, externalBalance); + } + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + LINK.transfer(to, amount); + emit FundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function getRequestConfig() external view override returns (uint16, uint32, bytes32[] memory) { + return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function requestRandomWords( + bytes32 keyHash, + uint64 subId, + uint16 requestConfirmations, + uint32 callbackGasLimit, + uint32 numWords + ) external override nonReentrant returns (uint256) { + // Input validation using the subscription storage. + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + // A nonce of 0 indicates consumer is not allocated to the sub. + uint64 currentNonce = s_consumers[msg.sender][subId]; + if (currentNonce == 0) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + requestConfirmations < s_config.minimumRequestConfirmations || requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(callbackGasLimit, s_config.maxGasLimit); + } + if (numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(numWords, MAX_NUM_WORDS); + } + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + uint64 nonce = currentNonce + 1; + (uint256 requestId, uint256 preSeed) = _computeRequestId(keyHash, msg.sender, subId, nonce); + + s_requestCommitments[requestId] = keccak256( + abi.encode(requestId, ChainSpecificUtil._getBlockNumber(), subId, callbackGasLimit, numWords, msg.sender) + ); + emit RandomWordsRequested( + keyHash, + requestId, + preSeed, + subId, + requestConfirmations, + callbackGasLimit, + numWords, + msg.sender + ); + s_consumers[msg.sender][subId] = nonce; + + return requestId; + } + + /** + * @notice Get request commitment + * @param requestId id of request + * @dev used to determine if a request is fulfilled or not + */ + function getCommitment(uint256 requestId) external view returns (bytes32) { + return s_requestCommitments[requestId]; + } + + function _computeRequestId( + bytes32 keyHash, + address sender, + uint64 subId, + uint64 nonce + ) private pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + function _getRandomnessFromProof( + Proof calldata proof, + RequestCommitment memory rc + ) private view returns (bytes32 keyHash, uint256 requestId, uint256 randomness) { + keyHash = hashOfKey(proof.pk); + // Only registered proving keys are permitted. + address oracle = s_provingKeys[keyHash]; + if (oracle == address(0)) { + revert NoSuchProvingKey(keyHash); + } + requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + return (keyHash, requestId, randomness); + } + + /* + * @notice Compute fee based on the request count + * @param reqCount number of requests + * @return feePPM fee in LINK PPM + */ + function getFeeTier(uint64 reqCount) public view returns (uint32) { + FeeConfig memory fc = s_feeConfig; + if (0 <= reqCount && reqCount <= fc.reqsForTier2) { + return fc.fulfillmentFlatFeeLinkPPMTier1; + } + if (fc.reqsForTier2 < reqCount && reqCount <= fc.reqsForTier3) { + return fc.fulfillmentFlatFeeLinkPPMTier2; + } + if (fc.reqsForTier3 < reqCount && reqCount <= fc.reqsForTier4) { + return fc.fulfillmentFlatFeeLinkPPMTier3; + } + if (fc.reqsForTier4 < reqCount && reqCount <= fc.reqsForTier5) { + return fc.fulfillmentFlatFeeLinkPPMTier4; + } + return fc.fulfillmentFlatFeeLinkPPMTier5; + } + + /* + * @notice Fulfill a randomness request + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof calldata proof, + RequestCommitment memory rc + ) external nonReentrant returns (uint96) { + uint256 startGas = gasleft(); + (bytes32 keyHash, uint256 requestId, uint256 randomness) = _getRandomnessFromProof(proof, rc); + + uint256[] memory randomWords = new uint256[](rc.numWords); + for (uint256 i = 0; i < rc.numWords; i++) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + + delete s_requestCommitments[requestId]; + VRFConsumerBaseV2 v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + bool success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + + // Increment the req count for fee tier selection. + uint64 reqCount = s_subscriptions[rc.subId].reqCount; + s_subscriptions[rc.subId].reqCount += 1; + + // We want to charge users exactly for how much gas they use in their callback. + // The gasAfterPaymentCalculation is meant to cover these additional operations where we + // decrement the subscription balance and increment the oracles withdrawable balance. + // We also add the flat link fee to the payment amount. + // Its specified in millionths of link, if s_config.fulfillmentFlatFeeLinkPPM = 1 + // 1 link / 1e6 = 1e18 juels / 1e6 = 1e12 juels. + uint96 payment = _calculatePaymentAmount( + startGas, + s_config.gasAfterPaymentCalculation, + getFeeTier(reqCount), + tx.gasprice + ); + if (s_subscriptions[rc.subId].balance < payment) { + revert InsufficientBalance(); + } + s_subscriptions[rc.subId].balance -= payment; + s_withdrawableTokens[s_provingKeys[keyHash]] += payment; + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(requestId, randomness, payment, success); + return payment; + } + + // Get the amount of gas used for fulfillment + function _calculatePaymentAmount( + uint256 startGas, + uint256 gasAfterPaymentCalculation, + uint32 fulfillmentFlatFeeLinkPPM, + uint256 weiPerUnitGas + ) internal view returns (uint96) { + int256 weiPerUnitLink; + weiPerUnitLink = _getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256(weiPerUnitLink); + uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); + if (paymentNoFee > (1e27 - fee)) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return uint96(paymentNoFee + fee); + } + + function _getFeedData() private view returns (int256) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return weiPerUnitLink; + } + + /* + * @notice Oracle withdraw LINK earned through fulfilling requests + * @param recipient where to send the funds + * @param amount amount to withdraw + */ + function oracleWithdraw(address recipient, uint96 amount) external nonReentrant { + if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + s_totalBalance -= amount; + if (!LINK.transfer(recipient, amount)) { + revert InsufficientBalance(); + } + } + + function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { + if (msg.sender != address(LINK)) { + revert OnlyCallableFromLink(); + } + if (data.length != 32) { + revert InvalidCalldata(); + } + uint64 subId = abi.decode(data, (uint64)); + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // We do not check that the msg.sender is the subscription owner, + // anyone can fund a subscription. + uint256 oldBalance = s_subscriptions[subId].balance; + s_subscriptions[subId].balance += uint96(amount); + s_totalBalance += uint96(amount); + emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); + } + + function getCurrentSubId() external view returns (uint64) { + return s_currentSubId; + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function getSubscription( + uint64 subId + ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + return ( + s_subscriptions[subId].balance, + s_subscriptions[subId].reqCount, + s_subscriptionConfigs[subId].owner, + s_subscriptionConfigs[subId].consumers + ); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function createSubscription() external override nonReentrant returns (uint64) { + s_currentSubId++; + uint64 currentSubId = s_currentSubId; + address[] memory consumers = new address[](0); + s_subscriptions[currentSubId] = Subscription({balance: 0, reqCount: 0}); + s_subscriptionConfigs[currentSubId] = SubscriptionConfig({ + owner: msg.sender, + requestedOwner: address(0), + consumers: consumers + }); + + emit SubscriptionCreated(currentSubId, msg.sender); + return currentSubId; + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function requestSubscriptionOwnerTransfer( + uint64 subId, + address newOwner + ) external override onlySubOwner(subId) nonReentrant { + // Proposing to address(0) would never be claimable so don't need to check. + if (s_subscriptionConfigs[subId].requestedOwner != newOwner) { + s_subscriptionConfigs[subId].requestedOwner = newOwner; + emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); + } + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function acceptSubscriptionOwnerTransfer(uint64 subId) external override nonReentrant { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { + revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); + } + address oldOwner = s_subscriptionConfigs[subId].owner; + s_subscriptionConfigs[subId].owner = msg.sender; + s_subscriptionConfigs[subId].requestedOwner = address(0); + emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function removeConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + if (s_consumers[consumer][subId] == 0) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] memory consumers = s_subscriptionConfigs[subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; i++) { + if (consumers[i] == consumer) { + address last = consumers[lastConsumerIndex]; + // Storage write to preserve last element + s_subscriptionConfigs[subId].consumers[i] = last; + // Storage remove last element + s_subscriptionConfigs[subId].consumers.pop(); + break; + } + } + delete s_consumers[consumer][subId]; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function addConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + // Already maxed, cannot add any more consumers. + if (s_subscriptionConfigs[subId].consumers.length == MAX_CONSUMERS) { + revert TooManyConsumers(); + } + if (s_consumers[consumer][subId] != 0) { + // Idempotence - do nothing if already added. + // Ensures uniqueness in s_subscriptions[subId].consumers. + return; + } + // Initialize the nonce to 1, indicating the consumer is allocated. + s_consumers[consumer][subId] = 1; + s_subscriptionConfigs[subId].consumers.push(consumer); + + emit SubscriptionConsumerAdded(subId, consumer); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function cancelSubscription(uint64 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + _cancelSubscriptionHelper(subId, to); + } + + function _cancelSubscriptionHelper(uint64 subId, address to) private nonReentrant { + SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; + Subscription memory sub = s_subscriptions[subId]; + uint96 balance = sub.balance; + // Note bounded by MAX_CONSUMERS; + // If no consumers, does nothing. + for (uint256 i = 0; i < subConfig.consumers.length; i++) { + delete s_consumers[subConfig.consumers[i]][subId]; + } + delete s_subscriptionConfigs[subId]; + delete s_subscriptions[subId]; + s_totalBalance -= balance; + if (!LINK.transfer(to, uint256(balance))) { + revert InsufficientBalance(); + } + emit SubscriptionCanceled(subId, to, balance); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + * @dev Looping is bounded to MAX_CONSUMERS*(number of keyhashes). + * @dev Used to disable subscription canceling while outstanding request are present. + */ + function pendingRequestExists(uint64 subId) public view override returns (bool) { + SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; + for (uint256 i = 0; i < subConfig.consumers.length; i++) { + for (uint256 j = 0; j < s_provingKeyHashes.length; j++) { + (uint256 reqId, ) = _computeRequestId( + s_provingKeyHashes[j], + subConfig.consumers[i], + subId, + s_consumers[subConfig.consumers[i]][subId] + ); + if (s_requestCommitments[reqId] != 0) { + return true; + } + } + } + return false; + } + + modifier onlySubOwner(uint64 subId) { + address owner = s_subscriptionConfigs[subId].owner; + if (owner == address(0)) { + revert InvalidSubscription(); + } + if (msg.sender != owner) { + revert MustBeSubOwner(owner); + } + _; + } + + modifier nonReentrant() { + if (s_config.reentrancyLock) { + revert Reentrant(); + } + _; + } + + /** + * @notice The type and version of this contract + * @return Type and version string + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "VRFCoordinatorV2 1.0.0"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol new file mode 100644 index 0000000..6b6b22b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity ^0.8.6; + +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; +import {VRFTypes} from "./VRFTypes.sol"; + +// Taken from VRFCoordinatorV2.sol +// Must be abi-compatible with what's there +struct FeeConfig { + // Flat fee charged per fulfillment in millionths of link + // So fee range is [0, 2^32/10^6]. + uint32 fulfillmentFlatFeeLinkPPMTier1; + uint32 fulfillmentFlatFeeLinkPPMTier2; + uint32 fulfillmentFlatFeeLinkPPMTier3; + uint32 fulfillmentFlatFeeLinkPPMTier4; + uint32 fulfillmentFlatFeeLinkPPMTier5; + uint24 reqsForTier2; + uint24 reqsForTier3; + uint24 reqsForTier4; + uint24 reqsForTier5; +} + +// Taken from VRFCoordinatorV2.sol +// Must be abi-compatible with what's there +struct Config { + uint16 minimumRequestConfirmations; + uint32 maxGasLimit; + // stalenessSeconds is how long before we consider the feed price to be stale + // and fallback to fallbackWeiPerUnitLink. + uint32 stalenessSeconds; + // Gas to cover oracle payment after we calculate the payment. + // We make it configurable in case those operations are repriced. + uint32 gasAfterPaymentCalculation; + int256 fallbackWeiPerUnitLink; + FeeConfig feeConfig; +} + +/// @dev IVRFCoordinatorV2 is the set of functions on the VRF coordinator V2 +/// @dev that are used in the VRF Owner contract below. +interface IVRFCoordinatorV2 { + function acceptOwnership() external; + + function transferOwnership(address to) external; + + function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external; + + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external; + + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig memory feeConfig + ) external; + + function getConfig() + external + view + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ); + + function getFeeConfig() + external + view + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ); + + function getFallbackWeiPerUnitLink() external view returns (int256); + + function ownerCancelSubscription(uint64 subId) external; + + function recoverFunds(address to) external; + + function hashOfKey(uint256[2] memory publicKey) external pure returns (bytes32); + + function fulfillRandomWords( + VRFTypes.Proof calldata proof, + VRFTypes.RequestCommitment memory rc + ) external returns (uint96); +} + +/** + * @notice VRFOwner is a contract that acts as the owner of the VRF + * @notice coordinator, with some useful utilities in the event extraordinary + * @notice things happen on-chain (i.e ETH/LINK price wildly fluctuates, and + * @notice a VRF fulfillment reverts on-chain). + */ +contract VRFOwner is ConfirmedOwner, AuthorizedReceiver { + int256 private constant MAX_INT256 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + IVRFCoordinatorV2 internal s_vrfCoordinator; + + event RandomWordsForced(uint256 indexed requestId, uint64 indexed subId, address indexed sender); + + constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) { + // solhint-disable-next-line gas-custom-errors + require(_vrfCoordinator != address(0), "vrf coordinator address must be non-zero"); + s_vrfCoordinator = IVRFCoordinatorV2(_vrfCoordinator); + } + + /** + * @notice Accepts ownership of the VRF coordinator if transferred to us. + */ + function acceptVRFOwnership() external onlyOwner { + s_vrfCoordinator.acceptOwnership(); + } + + /** + * @notice Transfers ownership of the VRF coordinator to the specified address. + * @param to the address to transfer ownership of the VRF Coordinator to. + */ + function transferVRFOwnership(address to) external onlyOwner { + s_vrfCoordinator.transferOwnership(to); + } + + /** + * @notice Returns the address of the VRF coordinator reference in this contract. + * @return The address of the VRF coordinator reference in this contract. + */ + function getVRFCoordinator() public view returns (address) { + return address(s_vrfCoordinator); + } + + /** + * @notice Registers a proving key to an oracle. + * @param oracle address of the oracle + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { + s_vrfCoordinator.registerProvingKey(oracle, publicProvingKey); + } + + /** + * @notice Deregisters a proving key to an oracle. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + s_vrfCoordinator.deregisterProvingKey(publicProvingKey); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed + * @param feeConfig fee tier configuration + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig memory feeConfig + ) public onlyOwner { + s_vrfCoordinator.setConfig( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + feeConfig + ); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator - only to be used from within fulfillRandomWords. + * @dev The reason plain setConfig cannot be used is that it is marked as onlyOwner. Since fulfillRandomWords + * @dev is gated by authorized senders, and the authorized senders are not necessarily owners, the call will + * @dev always fail if the caller of fulfillRandomWords is not the owner, which is not what we want. + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed + * @param feeConfig fee tier configuration + */ + function _setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig memory feeConfig + ) private { + s_vrfCoordinator.setConfig( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + feeConfig + ); + } + + /** + * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + * @param subId subscription id + * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + */ + function ownerCancelSubscription(uint64 subId) external onlyOwner { + s_vrfCoordinator.ownerCancelSubscription(subId); + } + + /** + * @notice Recover link sent with transfer instead of transferAndCall. + * @param to address to send link to + */ + function recoverFunds(address to) external onlyOwner { + s_vrfCoordinator.recoverFunds(to); + } + + /** + * @notice Get all relevant configs from the VRF coordinator. + * @dev This is done in a separate function to avoid the "stack too deep" issue + * @dev when too many local variables are in the same scope. + * @return Config struct containing all relevant configs from the VRF coordinator. + */ + function _getConfigs() private view returns (Config memory) { + ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ) = s_vrfCoordinator.getConfig(); + ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ) = s_vrfCoordinator.getFeeConfig(); + int256 fallbackWeiPerUnitLink = s_vrfCoordinator.getFallbackWeiPerUnitLink(); + return + Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + fallbackWeiPerUnitLink: fallbackWeiPerUnitLink, + feeConfig: FeeConfig({ + fulfillmentFlatFeeLinkPPMTier1: fulfillmentFlatFeeLinkPPMTier1, + fulfillmentFlatFeeLinkPPMTier2: fulfillmentFlatFeeLinkPPMTier2, + fulfillmentFlatFeeLinkPPMTier3: fulfillmentFlatFeeLinkPPMTier3, + fulfillmentFlatFeeLinkPPMTier4: fulfillmentFlatFeeLinkPPMTier4, + fulfillmentFlatFeeLinkPPMTier5: fulfillmentFlatFeeLinkPPMTier5, + reqsForTier2: reqsForTier2, + reqsForTier3: reqsForTier3, + reqsForTier4: reqsForTier4, + reqsForTier5: reqsForTier5 + }) + }); + } + + /** + * @notice Fulfill a randomness request + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + */ + function fulfillRandomWords( + VRFTypes.Proof calldata proof, + VRFTypes.RequestCommitment memory rc + ) external validateAuthorizedSender { + uint256 requestId = _requestIdFromProof(proof.pk, proof.seed); + + // Get current configs to restore them to original values after + // calling _setConfig. + Config memory cfg = _getConfigs(); + + // call _setConfig with the appropriate params in order to fulfill + // an accidentally-underfunded request. + _setConfig( + cfg.minimumRequestConfirmations, + cfg.maxGasLimit, + 1, // stalenessSeconds + 0, // gasAfterPaymentCalculation + MAX_INT256, // fallbackWeiPerUnitLink + FeeConfig({ + fulfillmentFlatFeeLinkPPMTier1: 0, + fulfillmentFlatFeeLinkPPMTier2: 0, + fulfillmentFlatFeeLinkPPMTier3: 0, + fulfillmentFlatFeeLinkPPMTier4: 0, + fulfillmentFlatFeeLinkPPMTier5: 0, + reqsForTier2: 0, + reqsForTier3: 0, + reqsForTier4: 0, + reqsForTier5: 0 + }) + ); + + s_vrfCoordinator.fulfillRandomWords(proof, rc); + + // reset configuration back to old values. + _setConfig( + cfg.minimumRequestConfirmations, + cfg.maxGasLimit, + cfg.stalenessSeconds, + cfg.gasAfterPaymentCalculation, + cfg.fallbackWeiPerUnitLink, + cfg.feeConfig + ); + + emit RandomWordsForced(requestId, rc.subId, rc.sender); + } + + /** + * @notice Concrete implementation of AuthorizedReceiver + * @return bool of whether sender is authorized + */ + function _canSetAuthorizedSenders() internal view override returns (bool) { + return owner() == msg.sender; + } + + /** + * @notice Returns the request for corresponding to the given public key and proof seed. + * @param publicKey the VRF public key associated with the proof + * @param proofSeed the proof seed + * @dev Refer to VRFCoordinatorV2.getRandomnessFromProof for original implementation. + */ + function _requestIdFromProof(uint256[2] memory publicKey, uint256 proofSeed) private view returns (uint256) { + bytes32 keyHash = s_vrfCoordinator.hashOfKey(publicKey); + uint256 requestId = uint256(keccak256(abi.encode(keyHash, proofSeed))); + return requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol new file mode 100644 index 0000000..ce0f6b1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract VRFRequestIDBase { + /** + * @notice returns the seed which is actually input to the VRF coordinator + * + * @dev To prevent repetition of VRF output due to repetition of the + * @dev user-supplied seed, that seed is combined in a hash with the + * @dev user-specific nonce, and the address of the consuming contract. The + * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in + * @dev the final seed, but the nonce does protect against repetition in + * @dev requests which are included in a single block. + * + * @param _userSeed VRF seed input provided by user + * @param _requester Address of the requesting contract + * @param _nonce User-specific nonce at the time of the request + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function makeVRFInputSeed( + bytes32 _keyHash, + uint256 _userSeed, + address _requester, + uint256 _nonce + ) internal pure returns (uint256) { + return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); + } + + /** + * @notice Returns the id for this request + * @param _keyHash The serviceAgreement ID to be used for this request + * @param _vRFInputSeed The seed to be passed directly to the VRF + * @return The id for this request + * + * @dev Note that _vRFInputSeed is not the seed passed by the consuming + * @dev contract, but the one generated by makeVRFInputSeed + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function makeRequestId(bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol new file mode 100644 index 0000000..d1b35a2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +/** + * @title VRFTypes + * @notice The VRFTypes library is a collection of types that is required to fulfill VRF requests + * on-chain. They must be ABI-compatible with the types used by the coordinator contracts. + */ +library VRFTypes { + // ABI-compatible with VRF.Proof. + // This proof is used for VRF V2 and V2Plus. + struct Proof { + uint256[2] pk; + uint256[2] gamma; + uint256 c; + uint256 s; + uint256 seed; + address uWitness; + uint256[2] cGammaWitness; + uint256[2] sHashWitness; + uint256 zInv; + } + + // ABI-compatible with VRFCoordinatorV2.RequestCommitment. + // This is only used for VRF V2. + struct RequestCommitment { + uint64 blockNum; + uint64 subId; + uint32 callbackGasLimit; + uint32 numWords; + address sender; + } + + // ABI-compatible with VRFCoordinatorV2Plus.RequestCommitment. + // This is only used for VRF V2Plus. + struct RequestCommitmentV2Plus { + uint64 blockNum; + uint256 subId; + uint32 callbackGasLimit; + uint32 numWords; + address sender; + bytes extraArgs; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol new file mode 100644 index 0000000..a656ef0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity ^0.8.6; + +import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; +import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol"; +import {VRFV2WrapperConsumerBase} from "./VRFV2WrapperConsumerBase.sol"; +import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; + +/** + * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off + * @notice requests for randomness. + */ +contract VRFV2Wrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2, VRFV2WrapperInterface { + event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + LinkTokenInterface public immutable LINK; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + AggregatorV3Interface public immutable LINK_ETH_FEED; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + ExtendedVRFCoordinatorV2Interface public immutable COORDINATOR; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + uint64 public immutable SUBSCRIPTION_ID; + /// @dev this is the size of a VRF v2 fulfillment's calldata abi-encoded in bytes. + /// @dev proofSize = 13 words = 13 * 256 = 3328 bits + /// @dev commitmentSize = 5 words = 5 * 256 = 1280 bits + /// @dev dataSize = proofSize + commitmentSize = 4608 bits + /// @dev selector = 32 bits + /// @dev total data size = 4608 bits + 32 bits = 4640 bits = 580 bytes + uint32 public s_fulfillmentTxSizeBytes = 580; + + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + + // lastRequestId is the request ID of the most recent VRF V2 request made by this wrapper. This + // should only be relied on within the same transaction the request was made. + uint256 public override lastRequestId; + + // Configuration fetched from VRFCoordinatorV2 + + // s_configured tracks whether this contract has been configured. If not configured, randomness + // requests cannot be made. + bool public s_configured; + + // s_disabled disables the contract when true. When disabled, new VRF requests cannot be made + // but existing ones can still be fulfilled. + bool public s_disabled; + + // s_fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed is + // stale. + int256 private s_fallbackWeiPerUnitLink; + + // s_stalenessSeconds is the number of seconds before we consider the feed price to be stale and + // fallback to fallbackWeiPerUnitLink. + uint32 private s_stalenessSeconds; + + // s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 + // charges. + uint32 private s_fulfillmentFlatFeeLinkPPM; + + // Other configuration + + // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + // function. The cost for this gas is passed to the user. + uint32 private s_wrapperGasOverhead; + + // s_coordinatorGasOverhead reflects the gas overhead of the coordinator's fulfillRandomWords + // function. The cost for this gas is billed to the subscription, and must therefor be included + // in the pricing for wrapped requests. This includes the gas costs of proof verification and + // payment calculation in the coordinator. + uint32 private s_coordinatorGasOverhead; + + // s_wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 + // indicates no premium. A value of 15 indicates a 15 percent premium. + uint8 private s_wrapperPremiumPercentage; + + // s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas + // fees, so this should be set to the highest gas lane on the network. + bytes32 internal s_keyHash; + + // s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request. + uint8 internal s_maxNumWords; + + struct Callback { + address callbackAddress; + uint32 callbackGasLimit; + uint256 requestGasPrice; + int256 requestWeiPerUnitLink; + uint256 juelsPaid; + } + mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; + + constructor( + address _link, + address _linkEthFeed, + address _coordinator + ) ConfirmedOwner(msg.sender) VRFConsumerBaseV2(_coordinator) { + LINK = LinkTokenInterface(_link); + LINK_ETH_FEED = AggregatorV3Interface(_linkEthFeed); + COORDINATOR = ExtendedVRFCoordinatorV2Interface(_coordinator); + + // Create this wrapper's subscription and add itself as a consumer. + uint64 subId = ExtendedVRFCoordinatorV2Interface(_coordinator).createSubscription(); + SUBSCRIPTION_ID = subId; + ExtendedVRFCoordinatorV2Interface(_coordinator).addConsumer(subId, address(this)); + } + + /** + * @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes. + * @param size is the size of the fulfillment transaction in bytes. + */ + function setFulfillmentTxSize(uint32 size) external onlyOwner { + s_fulfillmentTxSizeBytes = size; + } + + /** + * @notice setConfig configures VRFV2Wrapper. + * + * @dev Sets wrapper-specific configuration based on the given parameters, and fetches any needed + * @dev VRFCoordinatorV2 configuration from the coordinator. + * + * @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + * function. + * + * @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's + * fulfillRandomWords function. + * + * @param _wrapperPremiumPercentage is the premium ratio in percentage for wrapper requests. + * + * @param _keyHash to use for requesting randomness. + */ + function setConfig( + uint32 _wrapperGasOverhead, + uint32 _coordinatorGasOverhead, + uint8 _wrapperPremiumPercentage, + bytes32 _keyHash, + uint8 _maxNumWords + ) external onlyOwner { + s_wrapperGasOverhead = _wrapperGasOverhead; + s_coordinatorGasOverhead = _coordinatorGasOverhead; + s_wrapperPremiumPercentage = _wrapperPremiumPercentage; + s_keyHash = _keyHash; + s_maxNumWords = _maxNumWords; + s_configured = true; + + // Get other configuration from coordinator + (, , s_stalenessSeconds, ) = COORDINATOR.getConfig(); + s_fallbackWeiPerUnitLink = COORDINATOR.getFallbackWeiPerUnitLink(); + (s_fulfillmentFlatFeeLinkPPM, , , , , , , , ) = COORDINATOR.getFeeConfig(); + } + + /** + * @notice getConfig returns the current VRFV2Wrapper configuration. + * + * @return fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed + * is stale. + * + * @return stalenessSeconds is the number of seconds before we consider the feed price to be stale + * and fallback to fallbackWeiPerUnitLink. + * + * @return fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 + * charges. + * + * @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + * function. The cost for this gas is passed to the user. + * + * @return coordinatorGasOverhead reflects the gas overhead of the coordinator's + * fulfillRandomWords function. + * + * @return wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 + * indicates no premium. A value of 15 indicates a 15 percent premium. + * + * @return keyHash is the key hash to use when requesting randomness. Fees are paid based on + * current gas fees, so this should be set to the highest gas lane on the network. + * + * @return maxNumWords is the max number of words that can be requested in a single wrapped VRF + * request. + */ + function getConfig() + external + view + returns ( + int256 fallbackWeiPerUnitLink, + uint32 stalenessSeconds, + uint32 fulfillmentFlatFeeLinkPPM, + uint32 wrapperGasOverhead, + uint32 coordinatorGasOverhead, + uint8 wrapperPremiumPercentage, + bytes32 keyHash, + uint8 maxNumWords + ) + { + return ( + s_fallbackWeiPerUnitLink, + s_stalenessSeconds, + s_fulfillmentFlatFeeLinkPPM, + s_wrapperGasOverhead, + s_coordinatorGasOverhead, + s_wrapperPremiumPercentage, + s_keyHash, + s_maxNumWords + ); + } + + /** + * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + */ + function calculateRequestPrice( + uint32 _callbackGasLimit + ) external view override onlyConfiguredNotDisabled returns (uint256) { + int256 weiPerUnitLink = _getFeedData(); + return _calculateRequestPrice(_callbackGasLimit, tx.gasprice, weiPerUnitLink); + } + + /** + * @notice Estimates the price of a VRF request with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPrice( + uint32 _callbackGasLimit, + uint256 _requestGasPriceWei + ) external view override onlyConfiguredNotDisabled returns (uint256) { + int256 weiPerUnitLink = _getFeedData(); + return _calculateRequestPrice(_callbackGasLimit, _requestGasPriceWei, weiPerUnitLink); + } + + function _calculateRequestPrice( + uint256 _gas, + uint256 _requestGasPrice, + int256 _weiPerUnitLink + ) internal view returns (uint256) { + // costWei is the base fee denominated in wei (native) + // costWei takes into account the L1 posting costs of the VRF fulfillment + // transaction, if we are on an L2. + uint256 costWei = (_requestGasPrice * + (_gas + s_wrapperGasOverhead + s_coordinatorGasOverhead) + + ChainSpecificUtil._getL1CalldataGasCost(s_fulfillmentTxSizeBytes)); + // (1e18 juels/link) * ((wei/gas * (gas)) + l1wei) / (wei/link) == 1e18 juels * wei/link / (wei/link) == 1e18 juels * wei/link * link/wei == juels + // baseFee is the base fee denominated in juels (link) + uint256 baseFee = (1e18 * costWei) / uint256(_weiPerUnitLink); + // feeWithPremium is the fee after the percentage premium is applied + uint256 feeWithPremium = (baseFee * (s_wrapperPremiumPercentage + 100)) / 100; + // feeWithFlatFee is the fee after the flat fee is applied on top of the premium + uint256 feeWithFlatFee = feeWithPremium + (1e12 * uint256(s_fulfillmentFlatFeeLinkPPM)); + + return feeWithFlatFee; + } + + /** + * @notice onTokenTransfer is called by LinkToken upon payment for a VRF request. + * + * @dev Reverts if payment is too low. + * + * @param _sender is the sender of the payment, and the address that will receive a VRF callback + * upon fulfillment. + * + * @param _amount is the amount of LINK paid in Juels. + * + * @param _data is the abi-encoded VRF request parameters: uint32 callbackGasLimit, + * uint16 requestConfirmations, and uint32 numWords. + */ + function onTokenTransfer(address _sender, uint256 _amount, bytes calldata _data) external onlyConfiguredNotDisabled { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == address(LINK), "only callable from LINK"); + + (uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords) = abi.decode( + _data, + (uint32, uint16, uint32) + ); + uint32 eip150Overhead = _getEIP150Overhead(callbackGasLimit); + int256 weiPerUnitLink = _getFeedData(); + uint256 price = _calculateRequestPrice(callbackGasLimit, tx.gasprice, weiPerUnitLink); + // solhint-disable-next-line gas-custom-errors + require(_amount >= price, "fee too low"); + // solhint-disable-next-line gas-custom-errors + require(numWords <= s_maxNumWords, "numWords too high"); + + uint256 requestId = COORDINATOR.requestRandomWords( + s_keyHash, + SUBSCRIPTION_ID, + requestConfirmations, + callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, + numWords + ); + s_callbacks[requestId] = Callback({ + callbackAddress: _sender, + callbackGasLimit: callbackGasLimit, + requestGasPrice: tx.gasprice, + requestWeiPerUnitLink: weiPerUnitLink, + juelsPaid: _amount + }); + lastRequestId = requestId; + } + + /** + * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw LINK revenue. + * + * @param _recipient is the address that should receive the LINK funds. + * + * @param _amount is the amount of LINK in Juels that should be withdrawn. + */ + function withdraw(address _recipient, uint256 _amount) external onlyOwner { + LINK.transfer(_recipient, _amount); + } + + /** + * @notice enable this contract so that new requests can be accepted. + */ + function enable() external onlyOwner { + s_disabled = false; + } + + /** + * @notice disable this contract so that new requests will be rejected. When disabled, new requests + * @notice will revert but existing requests can still be fulfilled. + */ + function disable() external onlyOwner { + s_disabled = true; + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + Callback memory callback = s_callbacks[_requestId]; + delete s_callbacks[_requestId]; + // solhint-disable-next-line gas-custom-errors + require(callback.callbackAddress != address(0), "request not found"); // This should never happen + + VRFV2WrapperConsumerBase c; + bytes memory resp = abi.encodeWithSelector(c.rawFulfillRandomWords.selector, _requestId, _randomWords); + + bool success = _callWithExactGas(callback.callbackGasLimit, callback.callbackAddress, resp); + if (!success) { + emit WrapperFulfillmentFailed(_requestId, callback.callbackAddress); + } + } + + function _getFeedData() private view returns (int256) { + bool staleFallback = s_stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (staleFallback && s_stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + // solhint-disable-next-line gas-custom-errors + require(weiPerUnitLink >= 0, "Invalid LINK wei price"); + return weiPerUnitLink; + } + + /** + * @dev Calculates extra amount of gas required for running an assembly call() post-EIP150. + */ + function _getEIP150Overhead(uint32 gas) private pure returns (uint32) { + return gas / 63 + 1; + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + function typeAndVersion() external pure virtual override returns (string memory) { + return "VRFV2Wrapper 1.0.0"; + } + + modifier onlyConfiguredNotDisabled() { + // solhint-disable-next-line gas-custom-errors + require(s_configured, "wrapper is not configured"); + // solhint-disable-next-line gas-custom-errors + require(!s_disabled, "wrapper is disabled"); + _; + } +} + +// solhint-disable-next-line interface-starts-with-i +interface ExtendedVRFCoordinatorV2Interface is VRFCoordinatorV2Interface { + function getConfig() + external + view + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ); + + function getFallbackWeiPerUnitLink() external view returns (int256); + + function getFeeConfig() + external + view + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol new file mode 100644 index 0000000..7910431 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; +import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol"; + +/** ******************************************************************************* + * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper + * ******************************************************************************** + * @dev PURPOSE + * + * @dev Create VRF V2 requests without the need for subscription management. Rather than creating + * @dev and funding a VRF V2 subscription, a user can use this wrapper to create one off requests, + * @dev paying up front rather than at fulfillment. + * + * @dev Since the price is determined using the gas price of the request transaction rather than + * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas + * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFV2WrapperConsumerBase. The consumer must be funded + * @dev with enough LINK to make the request, otherwise requests will revert. To request randomness, + * @dev call the 'requestRandomness' function with the desired VRF parameters. This function handles + * @dev paying for the request based on the current pricing. + * + * @dev Consumers must implement the fullfillRandomWords function, which will be called during + * @dev fulfillment with the randomness result. + */ +abstract contract VRFV2WrapperConsumerBase { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + LinkTokenInterface internal immutable LINK; + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; + + /** + * @param _link is the address of LinkToken + * @param _vrfV2Wrapper is the address of the VRFV2Wrapper contract + */ + constructor(address _link, address _vrfV2Wrapper) { + LINK = LinkTokenInterface(_link); + VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); + } + + /** + * @dev Requests randomness from the VRF V2 wrapper. + * + * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's + * fulfillRandomWords function. + * @param _requestConfirmations is the number of confirmations to wait before fulfilling the + * request. A higher number of confirmations increases security by reducing the likelihood + * that a chain re-org changes a published randomness outcome. + * @param _numWords is the number of random words to request. + * + * @return requestId is the VRF V2 request ID of the newly created randomness request. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomness( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) internal returns (uint256 requestId) { + LINK.transferAndCall( + address(VRF_V2_WRAPPER), + VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit), + abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) + ); + return VRF_V2_WRAPPER.lastRequestId(); + } + + /** + * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must + * @notice implement it. + * + * @param _requestId is the VRF V2 request ID. + * @param _randomWords is the randomness result. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; + + function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == address(VRF_V2_WRAPPER), "only VRF V2 wrapper can fulfill"); + fulfillRandomWords(_requestId, _randomWords); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol new file mode 100644 index 0000000..e03736d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; + +/// @dev An abstract contract that provides Arbitrum specific L1 fee calculations. +// solhint-disable-next-line contract-name-camelcase +abstract contract ArbitrumL1Fees { + /// @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); + + /** + * @notice Returns the L1 fees that will be paid for the current transaction, given any calldata + * @notice for the current transaction. It uses ArbGas.getCurrentTxL1GasFees to get the fees. + */ + function _getL1CostWeiForCalldata() internal view returns (uint256) { + return ARBGAS.getCurrentTxL1GasFees(); + } + + /** + * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted to L1 + */ + function _getL1CostWeiForCalldataSize(uint256 calldataSizeBytes) internal view returns (uint256) { + (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); + // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from + // for the justification behind the 140 number. + return l1PricePerByte * (calldataSizeBytes + 140); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol new file mode 100644 index 0000000..69e0c2a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +// solhint-disable-next-line one-contract-per-file +pragma solidity 0.8.19; + +import {VRFTypes} from "../VRFTypes.sol"; + +/** + * @title BatchVRFCoordinatorV2Plus + * @notice The BatchVRFCoordinatorV2Plus contract acts as a proxy to write many random responses to the + * @notice provided VRFCoordinatorV2Plus contract efficiently in a single transaction. + */ +contract BatchVRFCoordinatorV2Plus { + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + IVRFCoordinatorV2PlusFulfill public immutable COORDINATOR; + + event ErrorReturned(uint256 indexed requestId, string reason); + event RawErrorReturned(uint256 indexed requestId, bytes lowLevelData); + + constructor(address coordinatorAddr) { + COORDINATOR = IVRFCoordinatorV2PlusFulfill(coordinatorAddr); + } + + /** + * @notice fulfills multiple randomness requests with the provided proofs and commitments. + * @param proofs the randomness proofs generated by the VRF provider. + * @param rcs the request commitments corresponding to the randomness proofs. + */ + function fulfillRandomWords( + VRFTypes.Proof[] calldata proofs, + VRFTypes.RequestCommitmentV2Plus[] calldata rcs + ) external { + // solhint-disable-next-line gas-custom-errors + require(proofs.length == rcs.length, "input array arg lengths mismatch"); + for (uint256 i = 0; i < proofs.length; ++i) { + try COORDINATOR.fulfillRandomWords(proofs[i], rcs[i], false) returns (uint96 /* payment */) { + continue; + } catch Error(string memory reason) { + uint256 requestId = _getRequestIdFromProof(proofs[i]); + emit ErrorReturned(requestId, reason); + } catch (bytes memory lowLevelData) { + uint256 requestId = _getRequestIdFromProof(proofs[i]); + emit RawErrorReturned(requestId, lowLevelData); + } + } + } + + /** + * @notice Returns the proving key hash associated with this public key. + * @param publicKey the key to return the hash of. + */ + function _hashOfKey(uint256[2] memory publicKey) internal pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Returns the request ID of the request associated with the given proof. + * @param proof the VRF proof provided by the VRF oracle. + */ + function _getRequestIdFromProof(VRFTypes.Proof memory proof) internal pure returns (uint256) { + bytes32 keyHash = _hashOfKey(proof.pk); + return uint256(keccak256(abi.encode(keyHash, proof.seed))); + } +} + +interface IVRFCoordinatorV2PlusFulfill { + function fulfillRandomWords( + VRFTypes.Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc, + bool onlyPremium + ) external returns (uint96); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol new file mode 100644 index 0000000..0bef7ae --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; + +/** + * @title BlockhashStore + * @notice This contract provides a way to access blockhashes older than + * the 256 block limit imposed by the BLOCKHASH opcode. + * You may assume that any blockhash stored by the contract is correct. + * Note that the contract depends on the format of serialized Ethereum + * blocks. If a future hardfork of Ethereum changes that format, the + * logic in this contract may become incorrect and an updated version + * would have to be deployed. + */ +contract BlockhashStore { + mapping(uint256 => bytes32) internal s_blockhashes; + + /** + * @notice stores blockhash of a given block, assuming it is available through BLOCKHASH + * @param n the number of the block whose blockhash should be stored + */ + function store(uint256 n) public { + bytes32 h = ChainSpecificUtil._getBlockhash(uint64(n)); + // solhint-disable-next-line gas-custom-errors + require(h != 0x0, "blockhash(n) failed"); + s_blockhashes[n] = h; + } + + /** + * @notice stores blockhash of the earliest block still available through BLOCKHASH. + */ + function storeEarliest() external { + store(ChainSpecificUtil._getBlockNumber() - 256); + } + + /** + * @notice stores blockhash after verifying blockheader of child/subsequent block + * @param n the number of the block whose blockhash should be stored + * @param header the rlp-encoded blockheader of block n+1. We verify its correctness by checking + * that it hashes to a stored blockhash, and then extract parentHash to get the n-th blockhash. + */ + function storeVerifyHeader(uint256 n, bytes memory header) public { + // solhint-disable-next-line gas-custom-errors + require(keccak256(header) == s_blockhashes[n + 1], "header has unknown blockhash"); + + // At this point, we know that header is the correct blockheader for block n+1. + + // The header is an rlp-encoded list. The head item of that list is the 32-byte blockhash of the parent block. + // Based on how rlp works, we know that blockheaders always have the following form: + // 0xf9____a0PARENTHASH... + // ^ ^ ^ + // | | | + // | | +--- PARENTHASH is 32 bytes. rlpenc(PARENTHASH) is 0xa || PARENTHASH. + // | | + // | +--- 2 bytes containing the sum of the lengths of the encoded list items + // | + // +--- 0xf9 because we have a list and (sum of lengths of encoded list items) fits exactly into two bytes. + // + // As a consequence, the PARENTHASH is always at offset 4 of the rlp-encoded block header. + + bytes32 parentHash; + assembly { + parentHash := mload(add(header, 36)) // 36 = 32 byte offset for length prefix of ABI-encoded array + // + 4 byte offset of PARENTHASH (see above) + } + + s_blockhashes[n] = parentHash; + } + + /** + * @notice gets a blockhash from the store. If no hash is known, this function reverts. + * @param n the number of the block whose blockhash should be returned + */ + function getBlockhash(uint256 n) external view returns (bytes32) { + bytes32 h = s_blockhashes[n]; + // solhint-disable-next-line gas-custom-errors + require(h != 0x0, "blockhash not found in store"); + return h; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol new file mode 100644 index 0000000..999e181 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; + +/// @dev An abstract contract that provides Optimism specific L1 fee calculations. +// solhint-disable-next-line contract-name-camelcase +abstract contract OptimismL1Fees is ConfirmedOwner { + /// @dev This is the padding size for unsigned RLP-encoded transaction without the signature data + /// @dev The padding size was estimated based on hypothetical max RLP-encoded transaction size + uint256 internal constant L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE = 71; + /// @dev Signature data size used in the GasPriceOracle predeploy + /// @dev reference: https://github.com/ethereum-optimism/optimism/blob/a96cbe7c8da144d79d4cec1303d8ae60a64e681e/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol#L145 + uint256 internal constant L1_TX_SIGNATURE_DATA_BYTES_SIZE = 68; + /// @dev L1_FEE_DATA_PADDING includes 71 bytes for L1 data padding for Optimism + bytes internal constant L1_FEE_DATA_PADDING = + hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload + /// @dev This option is only available for the Coordinator contract + uint8 internal constant L1_GAS_FEES_MODE = 0; + /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected + /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; + /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; + + uint8 public s_l1FeeCalculationMode = L1_GAS_FEES_MODE; + + /// @dev L1 fee coefficient can be applied to options 2 or 3 to reduce possibly inflated gas price + uint8 public s_l1FeeCoefficient = 100; + + error InvalidL1FeeCalculationMode(uint8 mode); + error InvalidL1FeeCoefficient(uint8 coefficient); + + event L1FeeCalculationSet(uint8 mode, uint8 coefficient); + + function setL1FeeCalculation(uint8 mode, uint8 coefficient) external virtual onlyOwner { + _setL1FeeCalculationInternal(mode, coefficient); + } + + function _setL1FeeCalculationInternal(uint8 mode, uint8 coefficient) internal { + if (mode >= 3) { + revert InvalidL1FeeCalculationMode(mode); + } + if (coefficient == 0 || coefficient > 100) { + revert InvalidL1FeeCoefficient(coefficient); + } + + s_l1FeeCalculationMode = mode; + s_l1FeeCoefficient = coefficient; + + emit L1FeeCalculationSet(mode, coefficient); + } + + function _getL1CostWeiForCalldata(bytes calldata data) internal view returns (uint256) { + if (s_l1FeeCalculationMode == L1_GAS_FEES_MODE) { + return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(data, L1_FEE_DATA_PADDING)); + } + return _getL1CostWeiForCalldataSize(data.length); + } + + function _getL1CostWeiForCalldataSize(uint256 calldataSizeBytes) internal view returns (uint256) { + uint8 l1FeeCalculationMode = s_l1FeeCalculationMode; + if (l1FeeCalculationMode == L1_CALLDATA_GAS_COST_MODE) { + // estimate based on unsigned fully RLP-encoded transaction size so we have to account for paddding bytes as well + return + (s_l1FeeCoefficient * _calculateOptimismL1DataFee(calldataSizeBytes + L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE)) / + 100; + } else if (l1FeeCalculationMode == L1_GAS_FEES_UPPER_BOUND_MODE) { + // getL1FeeUpperBound expects unsigned fully RLP-encoded transaction size so we have to account for paddding bytes as well + return + (s_l1FeeCoefficient * + OVM_GASPRICEORACLE.getL1FeeUpperBound(calldataSizeBytes + L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE)) / 100; + } + revert InvalidL1FeeCalculationMode(l1FeeCalculationMode); + } + + function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { + // reference: https://docs.optimism.io/stack/transactions/fees#ecotone + // also: https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/exec-engine.md#ecotone-l1-cost-fee-changes-eip-4844-da + // we treat all bytes in the calldata payload as non-zero bytes (cost: 16 gas) because accurate estimation is too expensive + // we also have to account for the signature data size + uint256 l1GasUsed = (calldataSizeBytes + L1_TX_SIGNATURE_DATA_BYTES_SIZE) * 16; + uint256 scaledBaseFee = OVM_GASPRICEORACLE.baseFeeScalar() * 16 * OVM_GASPRICEORACLE.l1BaseFee(); + uint256 scaledBlobBaseFee = OVM_GASPRICEORACLE.blobBaseFeeScalar() * OVM_GASPRICEORACLE.blobBaseFee(); + uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee); + return fee / (16 * 10 ** OVM_GASPRICEORACLE.decimals()); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol new file mode 100644 index 0000000..7614d7d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol @@ -0,0 +1,475 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {IVRFSubscriptionV2Plus} from "./interfaces/IVRFSubscriptionV2Plus.sol"; + +abstract contract SubscriptionAPI is ConfirmedOwner, IERC677Receiver, IVRFSubscriptionV2Plus { + using EnumerableSet for EnumerableSet.UintSet; + + /// @dev may not be provided upon construction on some chains due to lack of availability + LinkTokenInterface public LINK; + /// @dev may not be provided upon construction on some chains due to lack of availability + AggregatorV3Interface public LINK_NATIVE_FEED; + + // We need to maintain a list of consuming addresses. + // This bound ensures we are able to loop over them as needed. + // Should a user require more consumers, they can use multiple subscriptions. + uint16 public constant MAX_CONSUMERS = 100; + error TooManyConsumers(); + error InsufficientBalance(); + error InvalidConsumer(uint256 subId, address consumer); + error InvalidSubscription(); + error OnlyCallableFromLink(); + error InvalidCalldata(); + error MustBeSubOwner(address owner); + error PendingRequestExists(); + error MustBeRequestedOwner(address proposedOwner); + error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen + event FundsRecovered(address to, uint256 amount); + event NativeFundsRecovered(address to, uint256 amount); + error LinkAlreadySet(); + error FailedToSendNative(); + error FailedToTransferLink(); + error IndexOutOfRange(); + error LinkNotSet(); + + // We use the subscription struct (1 word) + // at fulfillment time. + struct Subscription { + // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) + uint96 balance; // Common link balance used for all consumer requests. + // a uint96 is large enough to hold around ~8e28 wei, or 80 billion ether. + // That should be enough to cover most (if not all) subscriptions. + uint96 nativeBalance; // Common native balance used for all consumer requests. + uint64 reqCount; + } + // We use the config for the mgmt APIs + struct SubscriptionConfig { + address owner; // Owner can fund/withdraw/cancel the sub. + address requestedOwner; // For safely transferring sub ownership. + // Maintains the list of keys in s_consumers. + // We do this for 2 reasons: + // 1. To be able to clean up all keys from s_consumers when canceling a subscription. + // 2. To be able to return the list of all consumers in getSubscription. + // Note that we need the s_consumers map to be able to directly check if a + // consumer is valid without reading all the consumers from storage. + address[] consumers; + } + struct ConsumerConfig { + bool active; + uint64 nonce; + uint64 pendingReqCount; + } + // Note a nonce of 0 indicates the consumer is not assigned to that subscription. + mapping(address => mapping(uint256 => ConsumerConfig)) /* consumerAddress */ /* subId */ /* consumerConfig */ + internal s_consumers; + mapping(uint256 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ internal s_subscriptionConfigs; + mapping(uint256 => Subscription) /* subId */ /* subscription */ internal s_subscriptions; + // subscription nonce used to construct subId. Rises monotonically + uint64 public s_currentSubNonce; + // track all subscription id's that were created by this contract + // note: access should be through the getActiveSubscriptionIds() view function + // which takes a starting index and a max number to fetch in order to allow + // "pagination" of the subscription ids. in the event a very large number of + // subscription id's are stored in this set, they cannot be retrieved in a + // single RPC call without violating various size limits. + EnumerableSet.UintSet internal s_subIds; + // s_totalBalance tracks the total link sent to/from + // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. + // A discrepancy with this contract's link balance indicates someone + // sent tokens using transfer and so we may need to use recoverFunds. + uint96 public s_totalBalance; + // s_totalNativeBalance tracks the total native sent to/from + // this contract through fundSubscription, cancelSubscription and oracleWithdrawNative. + // A discrepancy with this contract's native balance indicates someone + // sent native using transfer and so we may need to use recoverNativeFunds. + uint96 public s_totalNativeBalance; + uint96 internal s_withdrawableTokens; + uint96 internal s_withdrawableNative; + + event SubscriptionCreated(uint256 indexed subId, address owner); + event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); + event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); + event SubscriptionOwnerTransferRequested(uint256 indexed subId, address from, address to); + event SubscriptionOwnerTransferred(uint256 indexed subId, address from, address to); + + struct Config { + uint16 minimumRequestConfirmations; + uint32 maxGasLimit; + // Reentrancy protection. + bool reentrancyLock; + // stalenessSeconds is how long before we consider the feed price to be stale + // and fallback to fallbackWeiPerUnitLink. + uint32 stalenessSeconds; + // Gas to cover oracle payment after we calculate the payment. + // We make it configurable in case those operations are repriced. + // The recommended number is below, though it may vary slightly + // if certain chains do not implement certain EIP's. + // 21000 + // base cost of the transaction + // 100 + 5000 + // warm subscription balance read and update. See https://eips.ethereum.org/EIPS/eip-2929 + // 2*2100 + 5000 - // cold read oracle address and oracle balance and first time oracle balance update, note first time will be 20k, but 5k subsequently + // 4800 + // request delete refund (refunds happen after execution), note pre-london fork was 15k. See https://eips.ethereum.org/EIPS/eip-3529 + // 6685 + // Positive static costs of argument encoding etc. note that it varies by +/- x*12 for every x bytes of non-zero data in the proof. + // Total: 37,185 gas. + uint32 gasAfterPaymentCalculation; + // Flat fee charged per fulfillment in millionths of native. + // So fee range is [0, 2^32/10^6]. + uint32 fulfillmentFlatFeeNativePPM; + // Discount relative to fulfillmentFlatFeeNativePPM for link payment in millionths of native + // Should not exceed fulfillmentFlatFeeNativePPM + // So fee range is [0, 2^32/10^6]. + uint32 fulfillmentFlatFeeLinkDiscountPPM; + // nativePremiumPercentage is the percentage of the total gas costs that is added to the final premium for native payment + // nativePremiumPercentage = 10 means 10% of the total gas costs is added. only integral percentage is allowed + uint8 nativePremiumPercentage; + // linkPremiumPercentage is the percentage of total gas costs that is added to the final premium for link payment + // linkPremiumPercentage = 10 means 10% of the total gas costs is added. only integral percentage is allowed + uint8 linkPremiumPercentage; + } + Config public s_config; + + error Reentrant(); + modifier nonReentrant() { + _nonReentrant(); + _; + } + + function _nonReentrant() internal view { + if (s_config.reentrancyLock) { + revert Reentrant(); + } + } + + function _requireSufficientBalance(bool condition) internal pure { + if (!condition) { + revert InsufficientBalance(); + } + } + + function _requireValidSubscription(address subOwner) internal pure { + if (subOwner == address(0)) { + revert InvalidSubscription(); + } + } + constructor() ConfirmedOwner(msg.sender) {} + + /** + * @notice set the LINK token contract and link native feed to be + * used by this coordinator + * @param link - address of link token + * @param linkNativeFeed address of the link native feed + */ + function setLINKAndLINKNativeFeed(address link, address linkNativeFeed) external onlyOwner { + // Disallow re-setting link token because the logic wouldn't really make sense + if (address(LINK) != address(0)) { + revert LinkAlreadySet(); + } + LINK = LinkTokenInterface(link); + LINK_NATIVE_FEED = AggregatorV3Interface(linkNativeFeed); + } + + /** + * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + * @param subId subscription id + * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + */ + function ownerCancelSubscription(uint256 subId) external onlyOwner { + address subOwner = s_subscriptionConfigs[subId].owner; + _requireValidSubscription(subOwner); + _cancelSubscriptionHelper(subId, subOwner); + } + + /** + * @notice Recover link sent with transfer instead of transferAndCall. + * @param to address to send link to + */ + function recoverFunds(address to) external onlyOwner { + // If LINK is not set, we cannot recover funds. + // It is possible that this coordinator address was funded with LINK + // by accident by a user but the LINK token needs to be set first + // before we can recover it. + if (address(LINK) == address(0)) { + revert LinkNotSet(); + } + + uint256 externalBalance = LINK.balanceOf(address(this)); + uint256 internalBalance = uint256(s_totalBalance); + if (internalBalance > externalBalance) { + revert BalanceInvariantViolated(internalBalance, externalBalance); + } + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + if (!LINK.transfer(to, amount)) { + revert FailedToTransferLink(); + } + emit FundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + /** + * @notice Recover native sent with transfer/call/send instead of fundSubscription. + * @param to address to send native to + */ + function recoverNativeFunds(address payable to) external onlyOwner { + uint256 externalBalance = address(this).balance; + uint256 internalBalance = uint256(s_totalNativeBalance); + if (internalBalance > externalBalance) { + revert BalanceInvariantViolated(internalBalance, externalBalance); + } + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + (bool sent, ) = to.call{value: amount}(""); + if (!sent) { + revert FailedToSendNative(); + } + emit NativeFundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + /* + * @notice withdraw LINK earned through fulfilling requests + * @param recipient where to send the funds + * @param amount amount to withdraw + */ + function withdraw(address recipient) external nonReentrant onlyOwner { + if (address(LINK) == address(0)) { + revert LinkNotSet(); + } + uint96 amount = s_withdrawableTokens; + _requireSufficientBalance(amount > 0); + s_withdrawableTokens = 0; + s_totalBalance -= amount; + _requireSufficientBalance(LINK.transfer(recipient, amount)); + } + + /* + * @notice withdraw native earned through fulfilling requests + * @param recipient where to send the funds + * @param amount amount to withdraw + */ + function withdrawNative(address payable recipient) external nonReentrant onlyOwner { + uint96 amount = s_withdrawableNative; + _requireSufficientBalance(amount > 0); + // Prevent re-entrancy by updating state before transfer. + s_withdrawableNative = 0; + s_totalNativeBalance -= amount; + _mustSendNative(recipient, amount); + } + + function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { + if (msg.sender != address(LINK)) { + revert OnlyCallableFromLink(); + } + if (data.length != 32) { + revert InvalidCalldata(); + } + uint256 subId = abi.decode(data, (uint256)); + _requireValidSubscription(s_subscriptionConfigs[subId].owner); + // We do not check that the sender is the subscription owner, + // anyone can fund a subscription. + uint256 oldBalance = s_subscriptions[subId].balance; + s_subscriptions[subId].balance += uint96(amount); + s_totalBalance += uint96(amount); + emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function fundSubscriptionWithNative(uint256 subId) external payable override nonReentrant { + _requireValidSubscription(s_subscriptionConfigs[subId].owner); + // We do not check that the msg.sender is the subscription owner, + // anyone can fund a subscription. + // We also do not check that msg.value > 0, since that's just a no-op + // and would be a waste of gas on the caller's part. + uint256 oldNativeBalance = s_subscriptions[subId].nativeBalance; + s_subscriptions[subId].nativeBalance += uint96(msg.value); + s_totalNativeBalance += uint96(msg.value); + emit SubscriptionFundedWithNative(subId, oldNativeBalance, oldNativeBalance + msg.value); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function getSubscription( + uint256 subId + ) + public + view + override + returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address subOwner, address[] memory consumers) + { + subOwner = s_subscriptionConfigs[subId].owner; + _requireValidSubscription(subOwner); + return ( + s_subscriptions[subId].balance, + s_subscriptions[subId].nativeBalance, + s_subscriptions[subId].reqCount, + subOwner, + s_subscriptionConfigs[subId].consumers + ); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function getActiveSubscriptionIds( + uint256 startIndex, + uint256 maxCount + ) external view override returns (uint256[] memory ids) { + uint256 numSubs = s_subIds.length(); + if (startIndex >= numSubs) revert IndexOutOfRange(); + uint256 endIndex = startIndex + maxCount; + endIndex = endIndex > numSubs || maxCount == 0 ? numSubs : endIndex; + uint256 idsLength = endIndex - startIndex; + ids = new uint256[](idsLength); + for (uint256 idx = 0; idx < idsLength; ++idx) { + ids[idx] = s_subIds.at(idx + startIndex); + } + return ids; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function createSubscription() external override nonReentrant returns (uint256 subId) { + // Generate a subscription id that is globally unique. + uint64 currentSubNonce = s_currentSubNonce; + subId = uint256( + keccak256(abi.encodePacked(msg.sender, blockhash(block.number - 1), address(this), currentSubNonce)) + ); + // Increment the subscription nonce counter. + s_currentSubNonce = currentSubNonce + 1; + // Initialize storage variables. + address[] memory consumers = new address[](0); + s_subscriptions[subId] = Subscription({balance: 0, nativeBalance: 0, reqCount: 0}); + s_subscriptionConfigs[subId] = SubscriptionConfig({ + owner: msg.sender, + requestedOwner: address(0), + consumers: consumers + }); + // Update the s_subIds set, which tracks all subscription ids created in this contract. + s_subIds.add(subId); + + emit SubscriptionCreated(subId, msg.sender); + return subId; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function requestSubscriptionOwnerTransfer( + uint256 subId, + address newOwner + ) external override onlySubOwner(subId) nonReentrant { + // Proposing to address(0) would never be claimable so don't need to check. + SubscriptionConfig storage subscriptionConfig = s_subscriptionConfigs[subId]; + if (subscriptionConfig.requestedOwner != newOwner) { + subscriptionConfig.requestedOwner = newOwner; + emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); + } + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function acceptSubscriptionOwnerTransfer(uint256 subId) external override nonReentrant { + address oldOwner = s_subscriptionConfigs[subId].owner; + _requireValidSubscription(oldOwner); + if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { + revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); + } + s_subscriptionConfigs[subId].owner = msg.sender; + s_subscriptionConfigs[subId].requestedOwner = address(0); + emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function addConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + ConsumerConfig storage consumerConfig = s_consumers[consumer][subId]; + if (consumerConfig.active) { + // Idempotence - do nothing if already added. + // Ensures uniqueness in s_subscriptions[subId].consumers. + return; + } + // Already maxed, cannot add any more consumers. + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + if (consumers.length == MAX_CONSUMERS) { + revert TooManyConsumers(); + } + // consumerConfig.nonce is 0 if the consumer had never sent a request to this subscription + // otherwise, consumerConfig.nonce is non-zero + // in both cases, use consumerConfig.nonce as is and set active status to true + consumerConfig.active = true; + consumers.push(consumer); + + emit SubscriptionConsumerAdded(subId, consumer); + } + + function _deleteSubscription(uint256 subId) internal returns (uint96 balance, uint96 nativeBalance) { + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + balance = s_subscriptions[subId].balance; + nativeBalance = s_subscriptions[subId].nativeBalance; + // Note bounded by MAX_CONSUMERS; + // If no consumers, does nothing. + uint256 consumersLength = consumers.length; + for (uint256 i = 0; i < consumersLength; ++i) { + delete s_consumers[consumers[i]][subId]; + } + delete s_subscriptionConfigs[subId]; + delete s_subscriptions[subId]; + s_subIds.remove(subId); + if (balance != 0) { + s_totalBalance -= balance; + } + if (nativeBalance != 0) { + s_totalNativeBalance -= nativeBalance; + } + return (balance, nativeBalance); + } + + function _cancelSubscriptionHelper(uint256 subId, address to) internal { + (uint96 balance, uint96 nativeBalance) = _deleteSubscription(subId); + + // Only withdraw LINK if the token is active and there is a balance. + if (address(LINK) != address(0) && balance != 0) { + _requireSufficientBalance(LINK.transfer(to, uint256(balance))); + } + + // send native to the "to" address using call + _mustSendNative(to, uint256(nativeBalance)); + emit SubscriptionCanceled(subId, to, balance, nativeBalance); + } + + modifier onlySubOwner(uint256 subId) { + _onlySubOwner(subId); + _; + } + + function _onlySubOwner(uint256 subId) internal view { + address subOwner = s_subscriptionConfigs[subId].owner; + _requireValidSubscription(subOwner); + if (msg.sender != subOwner) { + revert MustBeSubOwner(subOwner); + } + } + + function _mustSendNative(address to, uint256 amount) internal { + (bool success, ) = to.call{value: amount}(""); + if (!success) { + revert FailedToSendNative(); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol new file mode 100644 index 0000000..b3b77c8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {BlockhashStore} from "./BlockhashStore.sol"; + +contract TrustedBlockhashStore is ConfirmedOwner, BlockhashStore { + error NotInWhitelist(); + error InvalidTrustedBlockhashes(); + error InvalidRecentBlockhash(); + + mapping(address => bool) public s_whitelistStatus; + address[] public s_whitelist; + + constructor(address[] memory whitelist) ConfirmedOwner(msg.sender) { + setWhitelist(whitelist); + } + + /** + * @notice sets the whitelist of addresses that can store blockhashes + * @param whitelist the whitelist of addresses that can store blockhashes + */ + function setWhitelist(address[] memory whitelist) public onlyOwner { + address[] memory previousWhitelist = s_whitelist; + s_whitelist = whitelist; + + // Unset whitelist status for all addresses in the previous whitelist, + // and set whitelist status for all addresses in the new whitelist. + for (uint256 i = 0; i < previousWhitelist.length; i++) { + s_whitelistStatus[previousWhitelist[i]] = false; + } + for (uint256 i = 0; i < whitelist.length; i++) { + s_whitelistStatus[whitelist[i]] = true; + } + } + + /** + * @notice stores a list of blockhashes and their respective blocks, only callable + * by a whitelisted address + * @param blockhashes the list of blockhashes and their respective blocks + */ + function storeTrusted( + uint256[] calldata blockNums, + bytes32[] calldata blockhashes, + uint256 recentBlockNumber, + bytes32 recentBlockhash + ) external { + bytes32 onChainHash = ChainSpecificUtil._getBlockhash(uint64(recentBlockNumber)); + if (onChainHash != recentBlockhash) { + revert InvalidRecentBlockhash(); + } + + if (!s_whitelistStatus[msg.sender]) { + revert NotInWhitelist(); + } + + if (blockNums.length != blockhashes.length) { + revert InvalidTrustedBlockhashes(); + } + + for (uint256 i = 0; i < blockNums.length; i++) { + s_blockhashes[blockNums[i]] = blockhashes[i]; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol new file mode 100644 index 0000000..83600b6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IVRFCoordinatorV2Plus} from "./interfaces/IVRFCoordinatorV2Plus.sol"; +import {IVRFMigratableConsumerV2Plus} from "./interfaces/IVRFMigratableConsumerV2Plus.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +/** **************************************************************************** + * @notice Interface for contracts using VRF randomness + * ***************************************************************************** + * @dev PURPOSE + * + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + * + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is indistinguishable to her from a uniform random sample + * @dev from the output space. + * + * @dev The purpose of this contract is to make it easy for unrelated contracts + * @dev to talk to Vera the verifier about the work Reggie is doing, to provide + * @dev simple access to a verifiable source of randomness. It ensures 2 things: + * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus. + * @dev 2. The consumer contract implements fulfillRandomWords. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can + * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as + * @dev shown: + * + * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { + * @dev constructor(, address _vrfCoordinator, address _subOwner) + * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public { + * @dev + * @dev } + * @dev } + * + * @dev The oracle will have given you an ID for the VRF keypair they have + * @dev committed to (let's call it keyHash). Create a subscription, fund it + * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface + * @dev subscription management functions). + * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, + * @dev callbackGasLimit, numWords, extraArgs), + * @dev see (IVRFCoordinatorV2Plus for a description of the arguments). + * + * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response + * @dev to your request, it will call your contract's fulfillRandomWords method. + * + * @dev The randomness argument to fulfillRandomWords is a set of random words + * @dev generated from your requestId and the blockHash of the request. + * + * @dev If your contract could have concurrent requests open, you can use the + * @dev requestId returned from requestRandomWords to track which response is associated + * @dev with which randomness request. + * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, + * @dev if your contract could have multiple requests in flight simultaneously. + * + * @dev Colliding `requestId`s are cryptographically impossible as long as seeds + * @dev differ. + * + * ***************************************************************************** + * @dev SECURITY CONSIDERATIONS + * + * @dev A method with the ability to call your fulfillRandomness method directly + * @dev could spoof a VRF response with any random value, so it's critical that + * @dev it cannot be directly called by anything other than this base contract + * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method). + * + * @dev For your users to trust that your contract's random behavior is free + * @dev from malicious interference, it's best if you can write it so that all + * @dev behaviors implied by a VRF response are executed *during* your + * @dev fulfillRandomness method. If your contract must store the response (or + * @dev anything derived from it) and use it later, you must ensure that any + * @dev user-significant behavior which depends on that stored value cannot be + * @dev manipulated by a subsequent VRF request. + * + * @dev Similarly, both miners and the VRF oracle itself have some influence + * @dev over the order in which VRF responses appear on the blockchain, so if + * @dev your contract could have multiple VRF requests in flight simultaneously, + * @dev you must ensure that the order in which the VRF responses arrive cannot + * @dev be used to manipulate your contract's user-significant behavior. + * + * @dev Since the block hash of the block which contains the requestRandomness + * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful + * @dev miner could, in principle, fork the blockchain to evict the block + * @dev containing the request, forcing the request to be included in a + * @dev different block with a different hash, and therefore a different input + * @dev to the VRF. However, such an attack would incur a substantial economic + * @dev cost. This cost scales with the number of blocks the VRF oracle waits + * @dev until it calls responds to a request. It is for this reason that + * @dev that you can signal to an oracle you'd like them to wait longer before + * @dev responding to the request (however this is not enforced in the contract + * @dev and so remains effective only in the case of unmodified oracle software). + */ +abstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner { + error OnlyCoordinatorCanFulfill(address have, address want); + error OnlyOwnerOrCoordinator(address have, address owner, address coordinator); + error ZeroAddress(); + + // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator + // so that coordinator reference is updated after migration + IVRFCoordinatorV2Plus public s_vrfCoordinator; + + /** + * @param _vrfCoordinator address of VRFCoordinator contract + */ + constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) { + if (_vrfCoordinator == address(0)) { + revert ZeroAddress(); + } + s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); + } + + /** + * @notice fulfillRandomness handles the VRF response. Your contract must + * @notice implement it. See "SECURITY CONSIDERATIONS" above for important + * @notice principles to keep in mind when implementing your fulfillRandomness + * @notice method. + * + * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this + * @dev signature, and will call it once it has verified the proof + * @dev associated with the randomness. (It is triggered via a call to + * @dev rawFulfillRandomness, below.) + * + * @param requestId The Id initially returned by requestRandomness + * @param randomWords the VRF output expanded to the requested number of words + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual; + + // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF + // proof. rawFulfillRandomness then calls fulfillRandomness, after validating + // the origin of the call + function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external { + if (msg.sender != address(s_vrfCoordinator)) { + revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator)); + } + fulfillRandomWords(requestId, randomWords); + } + + /** + * @inheritdoc IVRFMigratableConsumerV2Plus + */ + function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator { + if (_vrfCoordinator == address(0)) { + revert ZeroAddress(); + } + s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); + + emit CoordinatorSet(_vrfCoordinator); + } + + modifier onlyOwnerOrCoordinator() { + if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) { + revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator)); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol new file mode 100644 index 0000000..0de1b42 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/** **************************************************************************** + * @notice Interface for contracts using VRF randomness + * ***************************************************************************** + * @dev PURPOSE + * + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + * + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is indistinguishable to her from a uniform random sample + * @dev from the output space. + * + * @dev The purpose of this contract is to make it easy for unrelated contracts + * @dev to talk to Vera the verifier about the work Reggie is doing, to provide + * @dev simple access to a verifiable source of randomness. It ensures 2 things: + * @dev 1. The fulfillment came from the VRFCoordinator + * @dev 2. The consumer contract implements fulfillRandomWords. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFConsumerBase, and can + * @dev initialize VRFConsumerBase's attributes in their respective initializer as + * @dev shown: + * + * @dev import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + * @dev contract VRFConsumer is Initializable, VRFConsumerBaseV2Upgradeable { + * @dev initialize(, address _vrfCoordinator) public initializer { + * @dev __VRFConsumerBaseV2_init(_vrfCoordinator); + * @dev + * @dev } + * @dev } + * + * @dev The oracle will have given you an ID for the VRF keypair they have + * @dev committed to (let's call it keyHash). Create subscription, fund it + * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface + * @dev subscription management functions). + * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, + * @dev callbackGasLimit, numWords), + * @dev see (VRFCoordinatorInterface for a description of the arguments). + * + * @dev Once the VRFCoordinator has received and validated the oracle's response + * @dev to your request, it will call your contract's fulfillRandomWords method. + * + * @dev The randomness argument to fulfillRandomWords is a set of random words + * @dev generated from your requestId and the blockHash of the request. + * + * @dev If your contract could have concurrent requests open, you can use the + * @dev requestId returned from requestRandomWords to track which response is associated + * @dev with which randomness request. + * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, + * @dev if your contract could have multiple requests in flight simultaneously. + * + * @dev Colliding `requestId`s are cryptographically impossible as long as seeds + * @dev differ. + * + * ***************************************************************************** + * @dev SECURITY CONSIDERATIONS + * + * @dev A method with the ability to call your fulfillRandomness method directly + * @dev could spoof a VRF response with any random value, so it's critical that + * @dev it cannot be directly called by anything other than this base contract + * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). + * + * @dev For your users to trust that your contract's random behavior is free + * @dev from malicious interference, it's best if you can write it so that all + * @dev behaviors implied by a VRF response are executed *during* your + * @dev fulfillRandomness method. If your contract must store the response (or + * @dev anything derived from it) and use it later, you must ensure that any + * @dev user-significant behavior which depends on that stored value cannot be + * @dev manipulated by a subsequent VRF request. + * + * @dev Similarly, both miners and the VRF oracle itself have some influence + * @dev over the order in which VRF responses appear on the blockchain, so if + * @dev your contract could have multiple VRF requests in flight simultaneously, + * @dev you must ensure that the order in which the VRF responses arrive cannot + * @dev be used to manipulate your contract's user-significant behavior. + * + * @dev Since the block hash of the block which contains the requestRandomness + * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful + * @dev miner could, in principle, fork the blockchain to evict the block + * @dev containing the request, forcing the request to be included in a + * @dev different block with a different hash, and therefore a different input + * @dev to the VRF. However, such an attack would incur a substantial economic + * @dev cost. This cost scales with the number of blocks the VRF oracle waits + * @dev until it calls responds to a request. It is for this reason that + * @dev that you can signal to an oracle you'd like them to wait longer before + * @dev responding to the request (however this is not enforced in the contract + * @dev and so remains effective only in the case of unmodified oracle software). + */ + +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +/** + * @dev The VRFConsumerBaseV2Upgradable is an upgradable variant of VRFConsumerBaseV2 + * @dev (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable). + * @dev It's semantics are identical to VRFConsumerBaseV2 and can be inherited from + * @dev to create an upgradeable VRF consumer contract. + */ +abstract contract VRFConsumerBaseV2Upgradeable is Initializable { + error OnlyCoordinatorCanFulfill(address have, address want); + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + address private vrfCoordinator; + + // See https://github.com/OpenZeppelin/openzeppelin-sdk/issues/37. + // Each uint256 covers a single storage slot, see https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html. + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + uint256[49] private __gap; + + /** + * @param _vrfCoordinator the VRFCoordinatorV2 address. + * @dev See https://docs.chain.link/docs/vrf/v2/supported-networks/ for coordinator + * @dev addresses on your preferred network. + */ + // solhint-disable-next-line func-name-mixedcase + function __VRFConsumerBaseV2_init(address _vrfCoordinator) internal onlyInitializing { + if (_vrfCoordinator == address(0)) { + // solhint-disable-next-line gas-custom-errors + revert("must give valid coordinator address"); + } + + vrfCoordinator = _vrfCoordinator; + } + + /** + * @notice fulfillRandomness handles the VRF response. Your contract must + * @notice implement it. See "SECURITY CONSIDERATIONS" above for important + * @notice principles to keep in mind when implementing your fulfillRandomness + * @notice method. + * + * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this + * @dev signature, and will call it once it has verified the proof + * @dev associated with the randomness. (It is triggered via a call to + * @dev rawFulfillRandomness, below.) + * + * @param requestId The Id initially returned by requestRandomness + * @param randomWords the VRF output expanded to the requested number of words + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; + + // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF + // proof. rawFulfillRandomness then calls fulfillRandomness, after validating + // the origin of the call + function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { + if (msg.sender != vrfCoordinator) { + revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); + } + fulfillRandomWords(requestId, randomWords); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol new file mode 100644 index 0000000..53d19c1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol @@ -0,0 +1,791 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BlockhashStoreInterface} from "../interfaces/BlockhashStoreInterface.sol"; +import {VRF} from "../../vrf/VRF.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "./VRFConsumerBaseV2Plus.sol"; +import {SubscriptionAPI} from "./SubscriptionAPI.sol"; +import {VRFV2PlusClient} from "./libraries/VRFV2PlusClient.sol"; +import {IVRFCoordinatorV2PlusMigration} from "./interfaces/IVRFCoordinatorV2PlusMigration.sol"; +// solhint-disable-next-line no-unused-import +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "./interfaces/IVRFCoordinatorV2Plus.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { + /// @dev should always be available + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error MsgDataTooBig(uint256 have, uint32 max); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error InvalidExtraArgsTag(); + error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); + + struct ProvingKey { + bool exists; // proving key exists + uint64 maxGas; // gas lane max gas price for fulfilling requests + } + + mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; + bytes32[] public s_provingKeyHashes; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); + event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + event L1GasFee(uint256 fee); + + int256 public s_fallbackWeiPerUnitLink; + + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ); + + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + + constructor(address blockhashStore) SubscriptionAPI() { + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh].exists) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, maxGas); + } + + /** + * @notice Deregisters a proving key. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + ProvingKey memory key = s_provingKeys[kh]; + if (!key.exists) { + revert NoSuchProvingKey(kh); + } + delete s_provingKeys[kh]; + uint256 s_provingKeyHashesLength = s_provingKeyHashes.length; + for (uint256 i = 0; i < s_provingKeyHashesLength; ++i) { + if (s_provingKeyHashes[i] == kh) { + // Copy last element and overwrite kh to be deleted with it + s_provingKeyHashes[i] = s_provingKeyHashes[s_provingKeyHashesLength - 1]; + s_provingKeyHashes.pop(); + break; + } + } + emit ProvingKeyDeregistered(kh, key.maxGas); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] calldata publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed + * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment + * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native + * @param nativePremiumPercentage native premium percentage + * @param linkPremiumPercentage link premium percentage + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); + } + if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage: nativePremiumPercentage, + linkPremiumPercentage: linkPremiumPercentage + }); + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage, + linkPremiumPercentage + ); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + /** + * @notice Request a set of random words. + * @param req - a struct containing following fiels for randomness request: + * keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * requestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * extraArgs - Encoded extra arguments that has a boolean flag for whether payment + * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata req + ) external override nonReentrant returns (uint256 requestId) { + // Input validation using the subscription storage. + uint256 subId = req.subId; + _requireValidSubscription(s_subscriptionConfigs[subId].owner); + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; + ConsumerConfig memory consumerConfig = consumerConfigs[subId]; + if (!consumerConfig.active) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + req.requestConfirmations < s_config.minimumRequestConfirmations || + req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + req.requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (req.callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); + } + if (req.numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); + } + + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + ++consumerConfig.nonce; + ++consumerConfig.pendingReqCount; + uint256 preSeed; + (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); + s_requestCommitments[requestId] = keccak256( + abi.encode(requestId, _getBlockNumber(), subId, req.callbackGasLimit, req.numWords, msg.sender, extraArgsBytes) + ); + emit RandomWordsRequested( + req.keyHash, + requestId, + preSeed, + subId, + req.requestConfirmations, + req.callbackGasLimit, + req.numWords, + extraArgsBytes, + msg.sender + ); + consumerConfigs[subId] = consumerConfig; + + return requestId; + } + + function _computeRequestId( + bytes32 keyHash, + address sender, + uint256 subId, + uint64 nonce + ) internal pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + struct Output { + ProvingKey provingKey; + uint256 requestId; + uint256 randomness; + } + + function _getRandomnessFromProof( + Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc + ) internal view returns (Output memory) { + bytes32 keyHash = hashOfKey(proof.pk); + ProvingKey memory key = s_provingKeys[keyHash]; + // Only registered proving keys are permitted. + if (!key.exists) { + revert NoSuchProvingKey(keyHash); + } + uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != + keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = _getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + uint256 randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + return Output(key, requestId, randomness); + } + + function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { + if (tx.gasprice > gasLaneMaxGas) { + if (onlyPremium) { + // if only the premium amount needs to be billed, then the premium is capped by the gas lane max + return uint256(gasLaneMaxGas); + } else { + // Ensure gas price does not exceed the gas lane max gas price + revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); + } + } + return tx.gasprice; + } + + function _deliverRandomness( + uint256 requestId, + VRFTypes.RequestCommitmentV2Plus calldata rc, + uint256[] memory randomWords + ) internal returns (bool success) { + VRFConsumerBaseV2Plus v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + return success; + } + + /* + * @notice Fulfill a randomness request. + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @param onlyPremium only charge premium + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc, + bool onlyPremium + ) external nonReentrant returns (uint96 payment) { + uint256 startGas = gasleft(); + // fulfillRandomWords msg.data has 772 bytes and with an additional + // buffer of 32 bytes, we get 804 bytes. + /* Data size split: + * fulfillRandomWords function signature - 4 bytes + * proof - 416 bytes + * pk - 64 bytes + * gamma - 64 bytes + * c - 32 bytes + * s - 32 bytes + * seed - 32 bytes + * uWitness - 32 bytes + * cGammaWitness - 64 bytes + * sHashWitness - 64 bytes + * zInv - 32 bytes + * requestCommitment - 320 bytes + * blockNum - 32 bytes + * subId - 32 bytes + * callbackGasLimit - 32 bytes + * numWords - 32 bytes + * sender - 32 bytes + * extraArgs - 128 bytes + * onlyPremium - 32 bytes + */ + if (msg.data.length > 804) { + revert MsgDataTooBig(msg.data.length, 804); + } + Output memory output = _getRandomnessFromProof(proof, rc); + uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); + + uint256[] memory randomWords; + uint256 randomness = output.randomness; + // stack too deep error + { + uint256 numWords = rc.numWords; + randomWords = new uint256[](numWords); + for (uint256 i = 0; i < numWords; ++i) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + } + + delete s_requestCommitments[output.requestId]; + bool success = _deliverRandomness(output.requestId, rc, randomWords); + + // Increment the req count for the subscription. + ++s_subscriptions[rc.subId].reqCount; + // Decrement the pending req count for the consumer. + --s_consumers[rc.sender][rc.subId].pendingReqCount; + + bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; + + // stack too deep error + { + // We want to charge users exactly for how much gas they use in their callback with + // an additional premium. If onlyPremium is true, only premium is charged without + // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional + // operations where we decrement the subscription balance and increment the + // withdrawable balance. + bool isFeedStale; + (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); + } + } + + _chargePayment(payment, nativePayment, rc.subId); + + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); + + return payment; + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + _requireSufficientBalance(prevBal >= payment); + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + _requireSufficientBalance(prevBal >= payment); + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + function _calculatePaymentAmount( + uint256 startGas, + uint256 weiPerUnitGas, + bool nativePayment, + bool onlyPremium + ) internal returns (uint96, bool) { + if (nativePayment) { + return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); + } + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } + + function _calculatePaymentAmountNative( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal returns (uint96) { + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = _getL1CostWei(msg.data); + // calculate the payment without the premium + uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); + // calculate flat fee in native + uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); + // emit this event only if this is an L2 chain that needs to cover for L1 gas fees + if (l1CostWei > 0) { + emit L1GasFee(l1CostWei); + } + if (onlyPremium) { + return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } else { + return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } + } + + // Get the amount of gas used for fulfillment + function _calculatePaymentAmountLink( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal returns (uint96, bool) { + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = _getL1CostWei(msg.data); + // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * + (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256(weiPerUnitLink); + // calculate the flat fee in wei + uint256 flatFeeWei = 1e12 * + uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); + uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); + // emit this event only if this is an L2 chain that needs to cover for L1 gas fees + if (l1CostWei > 0) { + emit L1GasFee(l1CostWei); + } + uint256 payment; + if (onlyPremium) { + payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } else { + payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } + if (payment > 1e27) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return (uint96(payment), isFeedStale); + } + + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + uint256 timestamp; + (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return (weiPerUnitLink, isFeedStale); + } + + /** + * @notice Returns the block number of the current block by using specific opcode. + * @notice Override this function in chain specific way if needed (L2 chains). + */ + function _getBlockNumber() internal view virtual returns (uint256) { + return block.number; + } + + /** + * @notice Returns the blockhash for the given blockNumber by using specific opcode. + * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. + * @notice Override this function in chain specific way if needed (L2 chains). + */ + function _getBlockhash(uint64 blockNumber) internal view virtual returns (bytes32) { + return blockhash(blockNumber); + } + + /** + * @notice Returns the L1 fee for the calldata payload (always return 0 on L1 chains). + * @notice Override this function in chain specific way for L2 chains. + */ + function _getL1CostWei(bytes calldata /* data */) internal view virtual returns (uint256) { + return 0; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function pendingRequestExists(uint256 subId) public view override returns (bool) { + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = consumers.length; + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { + return true; + } + } + return false; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + if (!s_consumers[consumer][subId].active) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] storage s_subscriptionConsumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = s_subscriptionConsumers.length; + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_subscriptionConsumers[i] == consumer) { + // Storage write to preserve last element + s_subscriptionConsumers[i] = s_subscriptionConsumers[consumersLength - 1]; + // Storage remove last element + s_subscriptionConsumers.pop(); + break; + } + } + s_consumers[consumer][subId].active = false; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + _cancelSubscriptionHelper(subId, to); + } + + /*************************************************************************** + * Section: Migration + ***************************************************************************/ + + address[] internal s_migrationTargets; + + /// @dev Emitted when new coordinator is registered as migratable target + event CoordinatorRegistered(address coordinatorAddress); + + /// @dev Emitted when new coordinator is deregistered + event CoordinatorDeregistered(address coordinatorAddress); + + /// @notice emitted when migration to new coordinator completes successfully + /// @param newCoordinator coordinator address after migration + /// @param subId subscription ID + event MigrationCompleted(address newCoordinator, uint256 subId); + + /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target + error CoordinatorNotRegistered(address coordinatorAddress); + + /// @notice emitted when migrate() is called and given coordinator is registered as migratable target + error CoordinatorAlreadyRegistered(address coordinatorAddress); + + /// @dev encapsulates data to be migrated from current coordinator + // solhint-disable-next-line gas-struct-packing + struct V1MigrationData { + uint8 fromVersion; + uint256 subId; + address subOwner; + address[] consumers; + uint96 linkBalance; + uint96 nativeBalance; + } + + function _isTargetRegistered(address target) internal view returns (bool) { + uint256 migrationTargetsLength = s_migrationTargets.length; + for (uint256 i = 0; i < migrationTargetsLength; ++i) { + if (s_migrationTargets[i] == target) { + return true; + } + } + return false; + } + + function registerMigratableCoordinator(address target) external onlyOwner { + if (_isTargetRegistered(target)) { + revert CoordinatorAlreadyRegistered(target); + } + s_migrationTargets.push(target); + emit CoordinatorRegistered(target); + } + + function deregisterMigratableCoordinator(address target) external onlyOwner { + uint256 nTargets = s_migrationTargets.length; + for (uint256 i = 0; i < nTargets; ++i) { + if (s_migrationTargets[i] == target) { + s_migrationTargets[i] = s_migrationTargets[nTargets - 1]; + s_migrationTargets.pop(); + emit CoordinatorDeregistered(target); + return; + } + } + revert CoordinatorNotRegistered(target); + } + + function migrate(uint256 subId, address newCoordinator) external nonReentrant { + if (!_isTargetRegistered(newCoordinator)) { + revert CoordinatorNotRegistered(newCoordinator); + } + (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); + if (subOwner != msg.sender) { + revert MustBeSubOwner(subOwner); + } + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + + V1MigrationData memory migrationData = V1MigrationData({ + fromVersion: 1, + subId: subId, + subOwner: subOwner, + consumers: consumers, + linkBalance: balance, + nativeBalance: nativeBalance + }); + bytes memory encodedData = abi.encode(migrationData); + _deleteSubscription(subId); + IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); + + // Only transfer LINK if the token is active and there is a balance. + if (address(LINK) != address(0) && balance != 0) { + _requireSufficientBalance(LINK.transfer(address(newCoordinator), balance)); + } + + // despite the fact that we follow best practices this is still probably safest + // to prevent any re-entrancy possibilities. + s_config.reentrancyLock = true; + uint256 consumersLength = consumers.length; + for (uint256 i = 0; i < consumersLength; ++i) { + IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); + } + s_config.reentrancyLock = false; + + emit MigrationCompleted(newCoordinator, subId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol new file mode 100644 index 0000000..9b2357c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {VRFCoordinatorV2_5} from "./VRFCoordinatorV2_5.sol"; +import {ArbitrumL1Fees} from "./ArbitrumL1Fees.sol"; + +/// @dev VRFCoordinatorV2_5_Arbitrum combines VRFCoordinatorV2_5 base contract with +/// @dev Arbitrum specific opcodes and L1 gas fee calculations. +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorV2_5_Arbitrum is VRFCoordinatorV2_5, ArbitrumL1Fees { + /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); + + constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} + + /** + * @notice Override getBlockhash from VRFCoordinatorV2_5 + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. + */ + function _getBlockhash(uint64 blockNumber) internal view override returns (bytes32) { + uint64 currentBlockNumber = uint64(_getBlockNumber()); + if (blockNumber >= currentBlockNumber || (currentBlockNumber - blockNumber) > 256) { + return ""; + } + return ARBSYS.arbBlockHash(blockNumber); + } + + /** + * @notice Override getBlockNumber from VRFCoordinatorV2_5 + * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. + */ + function _getBlockNumber() internal view override returns (uint256) { + return ARBSYS.arbBlockNumber(); + } + + /// @notice Override getL1CostWei function from VRFCoordinatorV2_5 to activate Arbitrum getL1Fee computation + function _getL1CostWei(bytes calldata /* data */) internal view override returns (uint256) { + return _getL1CostWeiForCalldata(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol new file mode 100644 index 0000000..ce5abbe --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {VRFCoordinatorV2_5} from "./VRFCoordinatorV2_5.sol"; +import {OptimismL1Fees} from "./OptimismL1Fees.sol"; + +/// @dev VRFCoordinatorV2_5_Optimism combines VRFCoordinatorV2_5 base contract with +/// @dev Optimism specific opcodes and L1 gas fee calculations. +/// @dev This coordinator contract is used for all chains in the OP stack (e.g. Base). +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorV2_5_Optimism is VRFCoordinatorV2_5, OptimismL1Fees { + constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} + + /// @notice no need to override getBlockhash and getBlockNumber from VRFCoordinatorV2_5 + /// @notice on OP stack, they will work with the default implementation + + /// @notice Override getL1CostWei function from VRFCoordinatorV2_5 to activate Optimism getL1Fee computation + function _getL1CostWei(bytes calldata data) internal view override returns (uint256) { + return _getL1CostWeiForCalldata(data); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol new file mode 100644 index 0000000..58dd25c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "../../automation/interfaces/AutomationCompatibleInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; + +/** + * @title The VRFSubscriptionBalanceMonitor contract. + * @notice A keeper-compatible contract that monitors and funds VRF subscriptions. + */ +contract VRFSubscriptionBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { + VRFCoordinatorV2Interface public COORDINATOR; + LinkTokenInterface public LINKTOKEN; + + uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; + + event FundsAdded(uint256 amountAdded, uint256 newBalance, address sender); + event FundsWithdrawn(uint256 amountWithdrawn, address payee); + event TopUpSucceeded(uint64 indexed subscriptionId); + event TopUpFailed(uint64 indexed subscriptionId); + event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); + event VRFCoordinatorV2AddressUpdated(address oldAddress, address newAddress); + event LinkTokenAddressUpdated(address oldAddress, address newAddress); + event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); + event OutOfGas(uint256 lastId); + + error InvalidWatchList(); + error OnlyKeeperRegistry(); + error DuplicateSubcriptionId(uint64 duplicate); + + struct Target { + bool isActive; + uint96 minBalanceJuels; + uint96 topUpAmountJuels; + uint56 lastTopUpTimestamp; + } + + address public s_keeperRegistryAddress; // the address of the keeper registry + uint256 public s_minWaitPeriodSeconds; // minimum time to wait between top-ups + uint64[] public s_watchList; // the watchlist on which subscriptions are stored + mapping(uint64 => Target) internal s_targets; + + /** + * @param linkTokenAddress the Link token address + * @param coordinatorAddress the address of the vrf coordinator contract + * @param keeperRegistryAddress the address of the keeper registry contract + * @param minWaitPeriodSeconds the minimum wait period for addresses between funding + */ + constructor( + address linkTokenAddress, + address coordinatorAddress, + address keeperRegistryAddress, + uint256 minWaitPeriodSeconds + ) ConfirmedOwner(msg.sender) { + setLinkTokenAddress(linkTokenAddress); + setVRFCoordinatorV2Address(coordinatorAddress); + setKeeperRegistryAddress(keeperRegistryAddress); + setMinWaitPeriodSeconds(minWaitPeriodSeconds); + } + + /** + * @notice Sets the list of subscriptions to watch and their funding parameters. + * @param subscriptionIds the list of subscription ids to watch + * @param minBalancesJuels the minimum balances for each subscription + * @param topUpAmountsJuels the amount to top up each subscription + */ + function setWatchList( + uint64[] calldata subscriptionIds, + uint96[] calldata minBalancesJuels, + uint96[] calldata topUpAmountsJuels + ) external onlyOwner { + if (subscriptionIds.length != minBalancesJuels.length || subscriptionIds.length != topUpAmountsJuels.length) { + revert InvalidWatchList(); + } + uint64[] memory oldWatchList = s_watchList; + for (uint256 idx = 0; idx < oldWatchList.length; idx++) { + s_targets[oldWatchList[idx]].isActive = false; + } + for (uint256 idx = 0; idx < subscriptionIds.length; idx++) { + if (s_targets[subscriptionIds[idx]].isActive) { + revert DuplicateSubcriptionId(subscriptionIds[idx]); + } + if (subscriptionIds[idx] == 0) { + revert InvalidWatchList(); + } + if (topUpAmountsJuels[idx] <= minBalancesJuels[idx]) { + revert InvalidWatchList(); + } + s_targets[subscriptionIds[idx]] = Target({ + isActive: true, + minBalanceJuels: minBalancesJuels[idx], + topUpAmountJuels: topUpAmountsJuels[idx], + lastTopUpTimestamp: 0 + }); + } + s_watchList = subscriptionIds; + } + + /** + * @notice Gets a list of subscriptions that are underfunded. + * @return list of subscriptions that are underfunded + */ + function getUnderfundedSubscriptions() public view returns (uint64[] memory) { + uint64[] memory watchList = s_watchList; + uint64[] memory needsFunding = new uint64[](watchList.length); + uint256 count = 0; + uint256 minWaitPeriod = s_minWaitPeriodSeconds; + uint256 contractBalance = LINKTOKEN.balanceOf(address(this)); + Target memory target; + for (uint256 idx = 0; idx < watchList.length; idx++) { + target = s_targets[watchList[idx]]; + (uint96 subscriptionBalance, , , ) = COORDINATOR.getSubscription(watchList[idx]); + if ( + target.lastTopUpTimestamp + minWaitPeriod <= block.timestamp && + contractBalance >= target.topUpAmountJuels && + subscriptionBalance < target.minBalanceJuels + ) { + needsFunding[count] = watchList[idx]; + count++; + contractBalance -= target.topUpAmountJuels; + } + } + if (count < watchList.length) { + assembly { + mstore(needsFunding, count) + } + } + return needsFunding; + } + + /** + * @notice Send funds to the subscriptions provided. + * @param needsFunding the list of subscriptions to fund + */ + function topUp(uint64[] memory needsFunding) public whenNotPaused { + uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; + uint256 contractBalance = LINKTOKEN.balanceOf(address(this)); + Target memory target; + for (uint256 idx = 0; idx < needsFunding.length; idx++) { + target = s_targets[needsFunding[idx]]; + (uint96 subscriptionBalance, , , ) = COORDINATOR.getSubscription(needsFunding[idx]); + if ( + target.isActive && + target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && + subscriptionBalance < target.minBalanceJuels && + contractBalance >= target.topUpAmountJuels + ) { + bool success = LINKTOKEN.transferAndCall( + address(COORDINATOR), + target.topUpAmountJuels, + abi.encode(needsFunding[idx]) + ); + if (success) { + s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); + contractBalance -= target.topUpAmountJuels; + emit TopUpSucceeded(needsFunding[idx]); + } else { + emit TopUpFailed(needsFunding[idx]); + } + } + if (gasleft() < MIN_GAS_FOR_TRANSFER) { + emit OutOfGas(idx); + return; + } + } + } + + /** + * @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. + * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds + */ + function checkUpkeep( + bytes calldata + ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { + uint64[] memory needsFunding = getUnderfundedSubscriptions(); + upkeepNeeded = needsFunding.length > 0; + performData = abi.encode(needsFunding); + return (upkeepNeeded, performData); + } + + /** + * @notice Called by the keeper to send funds to underfunded addresses. + * @param performData the abi encoded list of addresses to fund + */ + function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { + uint64[] memory needsFunding = abi.decode(performData, (uint64[])); + topUp(needsFunding); + } + + /** + * @notice Withdraws the contract balance in LINK. + * @param amount the amount of LINK (in juels) to withdraw + * @param payee the address to pay + */ + function withdraw(uint256 amount, address payable payee) external onlyOwner { + // solhint-disable-next-line gas-custom-errors, reason-string + require(payee != address(0)); + emit FundsWithdrawn(amount, payee); + LINKTOKEN.transfer(payee, amount); + } + + /** + * @notice Sets the LINK token address. + */ + function setLinkTokenAddress(address linkTokenAddress) public onlyOwner { + // solhint-disable-next-line gas-custom-errors, reason-string + require(linkTokenAddress != address(0)); + emit LinkTokenAddressUpdated(address(LINKTOKEN), linkTokenAddress); + LINKTOKEN = LinkTokenInterface(linkTokenAddress); + } + + /** + * @notice Sets the VRF coordinator address. + */ + function setVRFCoordinatorV2Address(address coordinatorAddress) public onlyOwner { + // solhint-disable-next-line gas-custom-errors, reason-string + require(coordinatorAddress != address(0)); + emit VRFCoordinatorV2AddressUpdated(address(COORDINATOR), coordinatorAddress); + COORDINATOR = VRFCoordinatorV2Interface(coordinatorAddress); + } + + /** + * @notice Sets the keeper registry address. + */ + function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { + // solhint-disable-next-line gas-custom-errors, reason-string + require(keeperRegistryAddress != address(0)); + emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); + s_keeperRegistryAddress = keeperRegistryAddress; + } + + /** + * @notice Sets the minimum wait period (in seconds) for subscription ids between funding. + */ + function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { + emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); + s_minWaitPeriodSeconds = period; + } + + /** + * @notice Gets configuration information for a subscription on the watchlist. + */ + function getSubscriptionInfo( + uint64 subscriptionId + ) external view returns (bool isActive, uint96 minBalanceJuels, uint96 topUpAmountJuels, uint56 lastTopUpTimestamp) { + Target memory target = s_targets[subscriptionId]; + return (target.isActive, target.minBalanceJuels, target.topUpAmountJuels, target.lastTopUpTimestamp); + } + + /** + * @notice Gets the list of subscription ids being watched. + */ + function getWatchList() external view returns (uint64[] memory) { + return s_watchList; + } + + /** + * @notice Pause the contract, which prevents executing performUpkeep. + */ + function pause() external onlyOwner { + _pause(); + } + + /** + * @notice Unpause the contract. + */ + function unpause() external onlyOwner { + _unpause(); + } + + modifier onlyKeeperRegistry() { + if (msg.sender != s_keeperRegistryAddress) { + revert OnlyKeeperRegistry(); + } + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol new file mode 100644 index 0000000..40fd8a9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {VRFConsumerBaseV2Plus} from "./VRFConsumerBaseV2Plus.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {VRFV2PlusClient} from "./libraries/VRFV2PlusClient.sol"; +import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol"; +import {VRFV2PlusWrapperConsumerBase} from "./VRFV2PlusWrapperConsumerBase.sol"; + +/** + * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off + * @notice requests for randomness. + */ +// solhint-disable-next-line max-states-count +contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2Plus, IVRFV2PlusWrapper { + event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); + + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; + + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + uint16 private constant EXPECTED_MIN_LENGTH = 36; + + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + uint256 public immutable SUBSCRIPTION_ID; + LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_link_native_feed; + + event FulfillmentTxSizeSet(uint32 size); + event ConfigSet( + uint32 wrapperGasOverhead, + uint32 coordinatorGasOverheadNative, + uint32 coordinatorGasOverheadLink, + uint16 coordinatorGasOverheadPerWord, + uint8 coordinatorNativePremiumPercentage, + uint8 coordinatorLinkPremiumPercentage, + bytes32 keyHash, + uint8 maxNumWords, + uint32 stalenessSeconds, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM + ); + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + event Withdrawn(address indexed to, uint256 amount); + event NativeWithdrawn(address indexed to, uint256 amount); + event Enabled(); + event Disabled(); + + error LinkAlreadySet(); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); + error FailedToTransferLink(); + error IncorrectExtraArgsLength(uint16 expectedMinimumLength, uint16 actualLength); + error NativePaymentInOnTokenTransfer(); + error LINKPaymentInRequestRandomWordsInNative(); + error SubscriptionIdMissing(); + + /* Storage Slot 1: BEGIN */ + // 20 bytes used by VRFConsumerBaseV2Plus.s_vrfCoordinator + + // s_configured tracks whether this contract has been configured. If not configured, randomness + // requests cannot be made. + bool public s_configured; + + // s_disabled disables the contract when true. When disabled, new VRF requests cannot be made + // but existing ones can still be fulfilled. + bool public s_disabled; + + // s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request. + uint8 internal s_maxNumWords; + + // 9 bytes left + /* Storage Slot 1: END */ + + /* Storage Slot 2: BEGIN */ + // s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas + // fees, so this should be set to the highest gas lane on the network. + bytes32 internal s_keyHash; + /* Storage Slot 2: END */ + + /* Storage Slot 3: BEGIN */ + // lastRequestId is the request ID of the most recent VRF V2 request made by this wrapper. This + // should only be relied on within the same transaction the request was made. + uint256 public override lastRequestId; + /* Storage Slot 3: END */ + + /* Storage Slot 4: BEGIN */ + // s_fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed is + // stale. + int256 private s_fallbackWeiPerUnitLink; + /* Storage Slot 4: END */ + + /* Storage Slot 5: BEGIN */ + // s_stalenessSeconds is the number of seconds before we consider the feed price to be stale and + // fallback to fallbackWeiPerUnitLink. + uint32 private s_stalenessSeconds; + + // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + // function. The cost for this gas is passed to the user. + uint32 private s_wrapperGasOverhead; + + // Configuration fetched from VRFCoordinatorV2_5 + + /// @dev this is the size of a VRF v2plus fulfillment's calldata abi-encoded in bytes. + /// @dev proofSize = 13 words = 13 * 256 = 3328 bits + /// @dev commitmentSize = 10 words = 10 * 256 = 2560 bits + /// @dev onlyPremiumParameterSize = 256 bits + /// @dev dataSize = proofSize + commitmentSize + onlyPremiumParameterSize = 6144 bits + /// @dev function selector = 32 bits + /// @dev total data size = 6144 bits + 32 bits = 6176 bits = 772 bytes + uint32 public s_fulfillmentTxSizeBytes = 772; + + // s_coordinatorGasOverheadNative reflects the gas overhead of the coordinator's fulfillRandomWords + // function for native payment. The cost for this gas is billed to the subscription, and must therefor be included + // in the pricing for wrapped requests. This includes the gas costs of proof verification and + // payment calculation in the coordinator. + uint32 private s_coordinatorGasOverheadNative; + + // s_coordinatorGasOverheadLink reflects the gas overhead of the coordinator's fulfillRandomWords + // function for link payment. The cost for this gas is billed to the subscription, and must therefor be included + // in the pricing for wrapped requests. This includes the gas costs of proof verification and + // payment calculation in the coordinator. + uint32 private s_coordinatorGasOverheadLink; + + uint16 private s_coordinatorGasOverheadPerWord; + + // s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of native that VRFCoordinatorV2 + // charges for native payment. + uint32 private s_fulfillmentFlatFeeNativePPM; + + // s_fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2 + // charges for link payment. + uint32 private s_fulfillmentFlatFeeLinkDiscountPPM; + + // s_coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for native payment. + // For example, a value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. + // Wrapper has no premium. This premium is for VRFCoordinator. + uint8 private s_coordinatorNativePremiumPercentage; + + // s_coordinatorLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a + // value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. + // Wrapper has no premium. This premium is for VRFCoordinator. + uint8 private s_coordinatorLinkPremiumPercentage; + /* Storage Slot 5: END */ + + struct Callback { + address callbackAddress; + uint32 callbackGasLimit; + // Reducing requestGasPrice from uint256 to uint64 slots Callback struct + // into a single word, thus saving an entire SSTORE and leading to 21K + // gas cost saving. 18 ETH would be the max gas price we can process. + // GasPrice is unlikely to be more than 14 ETH on most chains + uint64 requestGasPrice; + } + /* Storage Slot 6: BEGIN */ + mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; + /* Storage Slot 6: END */ + + constructor( + address _link, + address _linkNativeFeed, + address _coordinator, + uint256 _subId + ) VRFConsumerBaseV2Plus(_coordinator) { + i_link = LinkTokenInterface(_link); + i_link_native_feed = AggregatorV3Interface(_linkNativeFeed); + + if (_subId == 0) { + revert SubscriptionIdMissing(); + } + + // Sanity check: should revert if the subscription does not exist + s_vrfCoordinator.getSubscription(_subId); + + // Subscription for the wrapper is created and managed by an external account. + // Expectation is that wrapper contract address will be added as a consumer + // to this subscription by the external account (owner of the subscription). + // Migration of the wrapper's subscription to the new coordinator has to be + // handled by the external account (owner of the subscription). + SUBSCRIPTION_ID = _subId; + } + + /** + * @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes. + * @param _size is the size of the fulfillment transaction in bytes. + */ + function setFulfillmentTxSize(uint32 _size) external onlyOwner { + s_fulfillmentTxSizeBytes = _size; + + emit FulfillmentTxSizeSet(_size); + } + + /** + * @notice setConfig configures VRFV2Wrapper. + * + * @dev Sets wrapper-specific configuration based on the given parameters, and fetches any needed + * @dev VRFCoordinatorV2 configuration from the coordinator. + * + * @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + * function. + * + * @param _coordinatorGasOverheadNative reflects the gas overhead of the coordinator's + * fulfillRandomWords function for native payment. + * + * @param _coordinatorGasOverheadLink reflects the gas overhead of the coordinator's + * fulfillRandomWords function for link payment. + * + * @param _coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's + * fulfillRandomWords function. + * + * @param _coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for requests paid in native. + * + * @param _coordinatorLinkPremiumPercentage is the coordinator's premium ratio in percentage for requests paid in link. + * + * @param _keyHash to use for requesting randomness. + * @param _maxNumWords is the max number of words that can be requested in a single wrapped VRF request + * @param _stalenessSeconds is the number of seconds before we consider the feed price to be stale + * and fallback to fallbackWeiPerUnitLink. + * + * @param _fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed + * is stale. + * + * @param _fulfillmentFlatFeeNativePPM is the flat fee in millionths of native that VRFCoordinatorV2Plus + * charges for native payment. + * + * @param _fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2Plus + * charges for link payment. + */ + /// @dev This function while having only 12 parameters is causing a Stack too deep error when running forge coverage. + function setConfig( + uint32 _wrapperGasOverhead, + uint32 _coordinatorGasOverheadNative, + uint32 _coordinatorGasOverheadLink, + uint16 _coordinatorGasOverheadPerWord, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, + bytes32 _keyHash, + uint8 _maxNumWords, + uint32 _stalenessSeconds, + int256 _fallbackWeiPerUnitLink, + uint32 _fulfillmentFlatFeeNativePPM, + uint32 _fulfillmentFlatFeeLinkDiscountPPM + ) external onlyOwner { + if (_fulfillmentFlatFeeLinkDiscountPPM > _fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(_fulfillmentFlatFeeLinkDiscountPPM, _fulfillmentFlatFeeNativePPM); + } + if (_coordinatorNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(_coordinatorNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (_coordinatorLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(_coordinatorLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + + s_wrapperGasOverhead = _wrapperGasOverhead; + s_coordinatorGasOverheadNative = _coordinatorGasOverheadNative; + s_coordinatorGasOverheadLink = _coordinatorGasOverheadLink; + s_coordinatorGasOverheadPerWord = _coordinatorGasOverheadPerWord; + s_coordinatorNativePremiumPercentage = _coordinatorNativePremiumPercentage; + s_coordinatorLinkPremiumPercentage = _coordinatorLinkPremiumPercentage; + s_keyHash = _keyHash; + s_maxNumWords = _maxNumWords; + s_configured = true; + + // Get other configuration from coordinator + s_stalenessSeconds = _stalenessSeconds; + s_fallbackWeiPerUnitLink = _fallbackWeiPerUnitLink; + s_fulfillmentFlatFeeNativePPM = _fulfillmentFlatFeeNativePPM; + s_fulfillmentFlatFeeLinkDiscountPPM = _fulfillmentFlatFeeLinkDiscountPPM; + + emit ConfigSet( + _wrapperGasOverhead, + _coordinatorGasOverheadNative, + _coordinatorGasOverheadLink, + _coordinatorGasOverheadPerWord, + _coordinatorNativePremiumPercentage, + _coordinatorLinkPremiumPercentage, + _keyHash, + _maxNumWords, + _stalenessSeconds, + _fallbackWeiPerUnitLink, + _fulfillmentFlatFeeNativePPM, + s_fulfillmentFlatFeeLinkDiscountPPM + ); + } + + /** + * @notice getConfig returns the current VRFV2Wrapper configuration. + * + * @return fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed + * is stale. + * + * @return stalenessSeconds is the number of seconds before we consider the feed price to be stale + * and fallback to fallbackWeiPerUnitLink. + * + * @return fulfillmentFlatFeeNativePPM is the flat fee in millionths of native that VRFCoordinatorV2Plus + * charges for native payment. + * + * @return fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2Plus + * charges for link payment. + * + * @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords + * function. The cost for this gas is passed to the user. + * + * @return coordinatorGasOverheadNative reflects the gas overhead of the coordinator's + * fulfillRandomWords function for native payment. + * + * @return coordinatorGasOverheadLink reflects the gas overhead of the coordinator's + * fulfillRandomWords function for link payment. + * + * @return coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's + * fulfillRandomWords function. + * + * @return wrapperNativePremiumPercentage is the premium ratio in percentage for native payment. For example, a value of 0 + * indicates no premium. A value of 15 indicates a 15 percent premium. + * + * @return wrapperLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a value of 0 + * indicates no premium. A value of 15 indicates a 15 percent premium. + * + * @return keyHash is the key hash to use when requesting randomness. Fees are paid based on + * current gas fees, so this should be set to the highest gas lane on the network. + * + * @return maxNumWords is the max number of words that can be requested in a single wrapped VRF + * request. + */ + function getConfig() + external + view + returns ( + int256 fallbackWeiPerUnitLink, + uint32 stalenessSeconds, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint32 wrapperGasOverhead, + uint32 coordinatorGasOverheadNative, + uint32 coordinatorGasOverheadLink, + uint16 coordinatorGasOverheadPerWord, + uint8 wrapperNativePremiumPercentage, + uint8 wrapperLinkPremiumPercentage, + bytes32 keyHash, + uint8 maxNumWords + ) + { + return ( + s_fallbackWeiPerUnitLink, + s_stalenessSeconds, + s_fulfillmentFlatFeeNativePPM, + s_fulfillmentFlatFeeLinkDiscountPPM, + s_wrapperGasOverhead, + s_coordinatorGasOverheadNative, + s_coordinatorGasOverheadLink, + s_coordinatorGasOverheadPerWord, + s_coordinatorNativePremiumPercentage, + s_coordinatorLinkPremiumPercentage, + s_keyHash, + s_maxNumWords + ); + } + + /** + * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + */ + function calculateRequestPrice( + uint32 _callbackGasLimit, + uint32 _numWords + ) external view override onlyConfiguredNotDisabled returns (uint256) { + (int256 weiPerUnitLink, ) = _getFeedData(); + return _calculateRequestPrice(_callbackGasLimit, _numWords, tx.gasprice, weiPerUnitLink); + } + + function calculateRequestPriceNative( + uint32 _callbackGasLimit, + uint32 _numWords + ) external view override onlyConfiguredNotDisabled returns (uint256) { + return _calculateRequestPriceNative(_callbackGasLimit, _numWords, tx.gasprice); + } + + /** + * @notice Estimates the price of a VRF request with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPrice( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view override onlyConfiguredNotDisabled returns (uint256) { + (int256 weiPerUnitLink, ) = _getFeedData(); + return _calculateRequestPrice(_callbackGasLimit, _numWords, _requestGasPriceWei, weiPerUnitLink); + } + + function estimateRequestPriceNative( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view override onlyConfiguredNotDisabled returns (uint256) { + return _calculateRequestPriceNative(_callbackGasLimit, _numWords, _requestGasPriceWei); + } + + /** + * @notice Returns the L1 fee for the fulfillment calldata payload (always return 0 on L1 chains). + * @notice Override this function in chain specific way for L2 chains. + */ + function _getL1CostWei() internal view virtual returns (uint256) { + return 0; + } + + function _calculateRequestPriceNative( + uint256 _gas, + uint32 _numWords, + uint256 _requestGasPrice + ) internal view returns (uint256) { + // costWei is the base fee denominated in wei (native) + // (wei/gas) * gas + uint256 wrapperCostWei = _requestGasPrice * s_wrapperGasOverhead; + + // coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2. + // (wei/gas) * gas + l1wei + uint256 coordinatorCostWei = _requestGasPrice * + (_gas + _getCoordinatorGasOverhead(_numWords, true)) + + _getL1CostWei(); + + // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied + // coordinator cost * premium multiplier + flat fee + uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * + (s_coordinatorNativePremiumPercentage + 100)) / 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM)); + + return wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei; + } + + function _calculateRequestPrice( + uint256 _gas, + uint32 _numWords, + uint256 _requestGasPrice, + int256 _weiPerUnitLink + ) internal view returns (uint256) { + // costWei is the base fee denominated in wei (native) + // (wei/gas) * gas + uint256 wrapperCostWei = _requestGasPrice * s_wrapperGasOverhead; + + // coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2. + // (wei/gas) * gas + l1wei + uint256 coordinatorCostWei = _requestGasPrice * + (_gas + _getCoordinatorGasOverhead(_numWords, false)) + + _getL1CostWei(); + + // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied + // coordinator cost * premium multiplier + flat fee + uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * + (s_coordinatorLinkPremiumPercentage + 100)) / 100) + + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM)); + + // requestPrice is denominated in juels (link) + // (1e18 juels/link) * wei / (wei/link) = juels + return (1e18 * (wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei)) / uint256(_weiPerUnitLink); + } + + /** + * @notice onTokenTransfer is called by LinkToken upon payment for a VRF request. + * + * @dev Reverts if payment is too low. + * + * @param _sender is the sender of the payment, and the address that will receive a VRF callback + * upon fulfillment. + * + * @param _amount is the amount of LINK paid in Juels. + * + * @param _data is the abi-encoded VRF request parameters: uint32 callbackGasLimit, + * uint16 requestConfirmations, and uint32 numWords. + */ + function onTokenTransfer(address _sender, uint256 _amount, bytes calldata _data) external onlyConfiguredNotDisabled { + // solhint-disable-next-line gas-custom-errors + require(msg.sender == address(i_link), "only callable from LINK"); + + (uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords, bytes memory extraArgs) = abi.decode( + _data, + (uint32, uint16, uint32, bytes) + ); + checkPaymentMode(extraArgs, true); + uint32 eip150Overhead = _getEIP150Overhead(callbackGasLimit); + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); + uint256 price = _calculateRequestPrice(callbackGasLimit, numWords, tx.gasprice, weiPerUnitLink); + // solhint-disable-next-line gas-custom-errors + require(_amount >= price, "fee too low"); + // solhint-disable-next-line gas-custom-errors + require(numWords <= s_maxNumWords, "numWords too high"); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: s_keyHash, + subId: SUBSCRIPTION_ID, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, + numWords: numWords, + extraArgs: extraArgs // empty extraArgs defaults to link payment + }); + uint256 requestId = s_vrfCoordinator.requestRandomWords(req); + s_callbacks[requestId] = Callback({ + callbackAddress: _sender, + callbackGasLimit: callbackGasLimit, + requestGasPrice: uint64(tx.gasprice) + }); + lastRequestId = requestId; + + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(requestId, s_fallbackWeiPerUnitLink); + } + } + + function checkPaymentMode(bytes memory extraArgs, bool isLinkMode) public pure { + // If extraArgs is empty, payment mode is LINK by default + if (extraArgs.length == 0) { + if (!isLinkMode) { + revert LINKPaymentInRequestRandomWordsInNative(); + } + return; + } + if (extraArgs.length < EXPECTED_MIN_LENGTH) { + revert IncorrectExtraArgsLength(EXPECTED_MIN_LENGTH, uint16(extraArgs.length)); + } + // ExtraArgsV1 only has struct {bool nativePayment} as of now + // The following condition checks if nativePayment in abi.encode of + // ExtraArgsV1 matches the appropriate function call (onTokenTransfer + // for LINK and requestRandomWordsInNative for Native payment) + bool nativePayment = extraArgs[35] == hex"01"; + if (nativePayment && isLinkMode) { + revert NativePaymentInOnTokenTransfer(); + } + if (!nativePayment && !isLinkMode) { + revert LINKPaymentInRequestRandomWordsInNative(); + } + } + + function requestRandomWordsInNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes calldata extraArgs + ) external payable override onlyConfiguredNotDisabled returns (uint256 requestId) { + checkPaymentMode(extraArgs, false); + + uint32 eip150Overhead = _getEIP150Overhead(_callbackGasLimit); + uint256 price = _calculateRequestPriceNative(_callbackGasLimit, _numWords, tx.gasprice); + // solhint-disable-next-line gas-custom-errors + require(msg.value >= price, "fee too low"); + // solhint-disable-next-line gas-custom-errors + require(_numWords <= s_maxNumWords, "numWords too high"); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: s_keyHash, + subId: SUBSCRIPTION_ID, + requestConfirmations: _requestConfirmations, + callbackGasLimit: _callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, + numWords: _numWords, + extraArgs: extraArgs + }); + requestId = s_vrfCoordinator.requestRandomWords(req); + s_callbacks[requestId] = Callback({ + callbackAddress: msg.sender, + callbackGasLimit: _callbackGasLimit, + requestGasPrice: uint64(tx.gasprice) + }); + + return requestId; + } + + /** + * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw LINK revenue. + * + * @param _recipient is the address that should receive the LINK funds. + */ + function withdraw(address _recipient) external onlyOwner { + uint256 amount = i_link.balanceOf(address(this)); + if (!i_link.transfer(_recipient, amount)) { + revert FailedToTransferLink(); + } + + emit Withdrawn(_recipient, amount); + } + + /** + * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw native revenue. + * + * @param _recipient is the address that should receive the native funds. + */ + function withdrawNative(address _recipient) external onlyOwner { + uint256 amount = address(this).balance; + (bool success, ) = payable(_recipient).call{value: amount}(""); + // solhint-disable-next-line gas-custom-errors + require(success, "failed to withdraw native"); + + emit NativeWithdrawn(_recipient, amount); + } + + /** + * @notice enable this contract so that new requests can be accepted. + */ + function enable() external onlyOwner { + s_disabled = false; + + emit Enabled(); + } + + /** + * @notice disable this contract so that new requests will be rejected. When disabled, new requests + * @notice will revert but existing requests can still be fulfilled. + */ + function disable() external onlyOwner { + s_disabled = true; + + emit Disabled(); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override { + Callback memory callback = s_callbacks[_requestId]; + delete s_callbacks[_requestId]; + + address callbackAddress = callback.callbackAddress; + // solhint-disable-next-line gas-custom-errors + require(callbackAddress != address(0), "request not found"); // This should never happen + + VRFV2PlusWrapperConsumerBase c; + bytes memory resp = abi.encodeWithSelector(c.rawFulfillRandomWords.selector, _requestId, _randomWords); + + bool success = _callWithExactGas(callback.callbackGasLimit, callbackAddress, resp); + if (!success) { + emit WrapperFulfillmentFailed(_requestId, callbackAddress); + } + } + + function link() external view override returns (address) { + return address(i_link); + } + + function linkNativeFeed() external view override returns (address) { + return address(i_link_native_feed); + } + + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { + uint32 stalenessSeconds = s_stalenessSeconds; + uint256 timestamp; + (, weiPerUnitLink, , timestamp, ) = i_link_native_feed.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + // solhint-disable-next-line gas-custom-errors + require(weiPerUnitLink >= 0, "Invalid LINK wei price"); + return (weiPerUnitLink, isFeedStale); + } + + /** + * @dev Calculates extra amount of gas required for running an assembly call() post-EIP150. + */ + function _getEIP150Overhead(uint32 gas) private pure returns (uint32) { + return gas / 63 + 1; + } + + function _getCoordinatorGasOverhead(uint32 numWords, bool nativePayment) internal view returns (uint32) { + if (nativePayment) { + return s_coordinatorGasOverheadNative + numWords * s_coordinatorGasOverheadPerWord; + } else { + return s_coordinatorGasOverheadLink + numWords * s_coordinatorGasOverheadPerWord; + } + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + function typeAndVersion() external pure virtual override returns (string memory) { + return "VRFV2PlusWrapper 1.0.0"; + } + + modifier onlyConfiguredNotDisabled() { + // solhint-disable-next-line gas-custom-errors + require(s_configured, "wrapper is not configured"); + // solhint-disable-next-line gas-custom-errors + require(!s_disabled, "wrapper is disabled"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol new file mode 100644 index 0000000..89a7dcb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol"; + +/** + * + * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper + * ******************************************************************************** + * @dev PURPOSE + * + * @dev Create VRF V2+ requests without the need for subscription management. Rather than creating + * @dev and funding a VRF V2+ subscription, a user can use this wrapper to create one off requests, + * @dev paying up front rather than at fulfillment. + * + * @dev Since the price is determined using the gas price of the request transaction rather than + * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas + * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. + * ***************************************************************************** + * @dev USAGE + * + * @dev Calling contracts must inherit from VRFV2PlusWrapperConsumerBase. The consumer must be funded + * @dev with enough LINK or ether to make the request, otherwise requests will revert. To request randomness, + * @dev call the 'requestRandomWords' function with the desired VRF parameters. This function handles + * @dev paying for the request based on the current pricing. + * + * @dev Consumers must implement the fullfillRandomWords function, which will be called during + * @dev fulfillment with the randomness result. + */ +abstract contract VRFV2PlusWrapperConsumerBase { + error OnlyVRFWrapperCanFulfill(address have, address want); + + LinkTokenInterface internal immutable i_linkToken; + IVRFV2PlusWrapper public immutable i_vrfV2PlusWrapper; + + /** + * @param _vrfV2PlusWrapper is the address of the VRFV2Wrapper contract + */ + constructor(address _vrfV2PlusWrapper) { + IVRFV2PlusWrapper vrfV2PlusWrapper = IVRFV2PlusWrapper(_vrfV2PlusWrapper); + + i_linkToken = LinkTokenInterface(vrfV2PlusWrapper.link()); + i_vrfV2PlusWrapper = vrfV2PlusWrapper; + } + + /** + * @dev Requests randomness from the VRF V2+ wrapper. + * + * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's + * fulfillRandomWords function. + * @param _requestConfirmations is the number of confirmations to wait before fulfilling the + * request. A higher number of confirmations increases security by reducing the likelihood + * that a chain re-org changes a published randomness outcome. + * @param _numWords is the number of random words to request. + * + * @return requestId is the VRF V2+ request ID of the newly created randomness request. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomness( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes memory extraArgs + ) internal returns (uint256 requestId, uint256 reqPrice) { + reqPrice = i_vrfV2PlusWrapper.calculateRequestPrice(_callbackGasLimit, _numWords); + i_linkToken.transferAndCall( + address(i_vrfV2PlusWrapper), + reqPrice, + abi.encode(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs) + ); + return (i_vrfV2PlusWrapper.lastRequestId(), reqPrice); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function requestRandomnessPayInNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes memory extraArgs + ) internal returns (uint256 requestId, uint256 requestPrice) { + requestPrice = i_vrfV2PlusWrapper.calculateRequestPriceNative(_callbackGasLimit, _numWords); + return ( + i_vrfV2PlusWrapper.requestRandomWordsInNative{value: requestPrice}( + _callbackGasLimit, + _requestConfirmations, + _numWords, + extraArgs + ), + requestPrice + ); + } + + /** + * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must + * @notice implement it. + * + * @param _requestId is the VRF V2 request ID. + * @param _randomWords is the randomness result. + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; + + function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { + address vrfWrapperAddr = address(i_vrfV2PlusWrapper); + if (msg.sender != vrfWrapperAddr) { + revert OnlyVRFWrapperCanFulfill(msg.sender, vrfWrapperAddr); + } + fulfillRandomWords(_requestId, _randomWords); + } + + /// @notice getBalance returns the native balance of the consumer contract + function getBalance() public view returns (uint256) { + return address(this).balance; + } + + /// @notice getLinkToken returns the link token contract + function getLinkToken() public view returns (LinkTokenInterface) { + return i_linkToken; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol new file mode 100644 index 0000000..1ab5e8b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {ArbitrumL1Fees} from "./ArbitrumL1Fees.sol"; +import {VRFV2PlusWrapper} from "./VRFV2PlusWrapper.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract VRFV2PlusWrapper_Arbitrum is VRFV2PlusWrapper, ArbitrumL1Fees { + constructor( + address _link, + address _linkNativeFeed, + address _coordinator, + uint256 _subId + ) VRFV2PlusWrapper(_link, _linkNativeFeed, _coordinator, _subId) {} + + /** + * @notice Returns estimated L1 gas fee cost for fulfillment calldata payload once + * @notice the request has been made through VRFV2PlusWrapper (direct funding model). + */ + function _getL1CostWei() internal view override returns (uint256) { + return ArbitrumL1Fees._getL1CostWeiForCalldataSize(s_fulfillmentTxSizeBytes); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol new file mode 100644 index 0000000..6913b2f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {OptimismL1Fees} from "./OptimismL1Fees.sol"; +import {VRFV2PlusWrapper} from "./VRFV2PlusWrapper.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract VRFV2PlusWrapper_Optimism is VRFV2PlusWrapper, OptimismL1Fees { + error UnsupportedL1FeeCalculationMode(uint8 mode); + + constructor( + address _link, + address _linkNativeFeed, + address _coordinator, + uint256 _subId + ) VRFV2PlusWrapper(_link, _linkNativeFeed, _coordinator, _subId) { + // default calculation mode from OptimismL1Fees is not supported on the wrapper + // switch to the next available one + s_l1FeeCalculationMode = L1_CALLDATA_GAS_COST_MODE; + } + + /** + * @notice Overriding the setL1FeeCalculation function in VRFV2PlusWrapper for Optimism + * @notice ensures that L1_GAS_FEES_MODE can't be set for the wrapper contract. + */ + function setL1FeeCalculation(uint8 mode, uint8 coefficient) external override onlyOwner { + if (mode == L1_GAS_FEES_MODE) { + revert UnsupportedL1FeeCalculationMode(mode); + } + OptimismL1Fees._setL1FeeCalculationInternal(mode, coefficient); + } + + /** + * @notice Returns estimated L1 gas fee cost for fulfillment calldata payload once + * @notice the request has been made through VRFV2PlusWrapper (direct funding model). + */ + function _getL1CostWei() internal view override returns (uint256) { + return OptimismL1Fees._getL1CostWeiForCalldataSize(s_fulfillmentTxSizeBytes); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol new file mode 100644 index 0000000..b0d5a80 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; +import {IVRFSubscriptionV2Plus} from "./IVRFSubscriptionV2Plus.sol"; + +// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades +// This interface is supported by subsequent versions of VRFCoordinatorV2Plus +interface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus { + /** + * @notice Request a set of random words. + * @param req - a struct containing following fields for randomness request: + * keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * requestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * extraArgs - abi-encoded extra args + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol new file mode 100644 index 0000000..22e714c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IVRFCoordinatorV2Plus} from "./IVRFCoordinatorV2Plus.sol"; + +// IVRFCoordinatorV2PlusInternal is the interface used by chainlink core and should +// not be used by consumer conracts +// Future versions of VRF V2plus must conform to this interface +// VRF coordinator doesn't directly inherit from this interface because solidity +// imposes interface methods be external, whereas methods implementated VRF coordinator +// are public. This is OK because IVRFCoordinatorV2PlusInternal doesn't have any solidity +// use case. It is only used to generate gethwrappers +interface IVRFCoordinatorV2PlusInternal is IVRFCoordinatorV2Plus { + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool success, + bool onlyPremium + ); + + struct RequestCommitment { + uint64 blockNum; + uint256 subId; + uint32 callbackGasLimit; + uint32 numWords; + address sender; + bytes extraArgs; + } + + struct Proof { + uint256[2] pk; + uint256[2] gamma; + uint256 c; + uint256 s; + uint256 seed; + address uWitness; + uint256[2] cGammaWitness; + uint256[2] sHashWitness; + uint256 zInv; + } + + // solhint-disable-next-line func-name-mixedcase + function s_requestCommitments(uint256 requestID) external view returns (bytes32); + + function fulfillRandomWords( + Proof calldata proof, + RequestCommitment memory rc, + bool onlyPremium + ) external returns (uint96); + + // solhint-disable-next-line func-name-mixedcase + function LINK_NATIVE_FEED() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol new file mode 100644 index 0000000..f77aaa7 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +// Future versions of VRFCoordinatorV2Plus must implement IVRFCoordinatorV2PlusMigration +// to support migrations from previous versions +interface IVRFCoordinatorV2PlusMigration { + /** + * @notice called by older versions of coordinator for migration. + * @notice only callable by older versions of coordinator + * @notice supports transfer of native currency + * @param encodedData - user data from older version of coordinator + */ + function onMigration(bytes calldata encodedData) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol new file mode 100644 index 0000000..67d12b8 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice The IVRFMigratableConsumerV2Plus interface defines the +/// @notice method required to be implemented by all V2Plus consumers. +/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus. +interface IVRFMigratableConsumerV2Plus { + event CoordinatorSet(address vrfCoordinator); + + /// @notice Sets the VRF Coordinator address + /// @notice This method should only be callable by the coordinator or contract owner + function setCoordinator(address vrfCoordinator) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol new file mode 100644 index 0000000..b178ffb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice The IVRFSubscriptionV2Plus interface defines the subscription +/// @notice related methods implemented by the V2Plus coordinator. +interface IVRFSubscriptionV2Plus { + /** + * @notice Add a consumer to a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - New consumer which can use the subscription + */ + function addConsumer(uint256 subId, address consumer) external; + + /** + * @notice Remove a consumer from a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - Consumer to remove from the subscription + */ + function removeConsumer(uint256 subId, address consumer) external; + + /** + * @notice Cancel a subscription + * @param subId - ID of the subscription + * @param to - Where to send the remaining LINK to + */ + function cancelSubscription(uint256 subId, address to) external; + + /** + * @notice Accept subscription owner transfer. + * @param subId - ID of the subscription + * @dev will revert if original owner of subId has + * not requested that msg.sender become the new owner. + */ + function acceptSubscriptionOwnerTransfer(uint256 subId) external; + + /** + * @notice Request subscription owner transfer. + * @param subId - ID of the subscription + * @param newOwner - proposed new owner of the subscription + */ + function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external; + + /** + * @notice Create a VRF subscription. + * @return subId - A unique subscription id. + * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + * @dev Note to fund the subscription with LINK, use transferAndCall. For example + * @dev LINKTOKEN.transferAndCall( + * @dev address(COORDINATOR), + * @dev amount, + * @dev abi.encode(subId)); + * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure + * @dev to send Native with the call, for example: + * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId); + */ + function createSubscription() external returns (uint256 subId); + + /** + * @notice Get a VRF subscription. + * @param subId - ID of the subscription + * @return balance - LINK balance of the subscription in juels. + * @return nativeBalance - native balance of the subscription in wei. + * @return reqCount - Requests count of subscription. + * @return owner - owner of the subscription. + * @return consumers - list of consumer address which are able to use this subscription. + */ + function getSubscription( + uint256 subId + ) + external + view + returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers); + + /* + * @notice Check to see if there exists a request commitment consumers + * for all consumers and keyhashes for a given sub. + * @param subId - ID of the subscription + * @return true if there exists at least one unfulfilled request for the subscription, false + * otherwise. + */ + function pendingRequestExists(uint256 subId) external view returns (bool); + + /** + * @notice Paginate through all active VRF subscriptions. + * @param startIndex index of the subscription to start from + * @param maxCount maximum number of subscriptions to return, 0 to return all + * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one + * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state + */ + function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); + + /** + * @notice Fund a subscription with native. + * @param subId - ID of the subscription + * @notice This method expects msg.value to be greater than or equal to 0. + */ + function fundSubscriptionWithNative(uint256 subId) external payable; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol new file mode 100644 index 0000000..e1a755f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice This interface is implemented by all VRF V2+ coordinators that can +/// @notice migrate subscription data to new coordinators. +interface IVRFV2PlusMigrate { + /** + * @notice migrate the provided subscription ID to the provided VRF coordinator + * @notice msg.sender must be the subscription owner and newCoordinator must + * @notice implement IVRFCoordinatorV2PlusMigration. + * @param subId the subscription ID to migrate + * @param newCoordinator the vrf coordinator to migrate to + */ + function migrate(uint256 subId, address newCoordinator) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol new file mode 100644 index 0000000..85b0c47 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IVRFV2PlusWrapper { + /** + * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only + * be relied option within the same transaction that the request was made. + */ + function lastRequestId() external view returns (uint256); + + /** + * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + */ + function calculateRequestPrice(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256); + + /** + * @notice Calculates the price of a VRF request in native with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + */ + function calculateRequestPriceNative(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256); + + /** + * @notice Estimates the price of a VRF request with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPrice( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view returns (uint256); + + /** + * @notice Estimates the price of a VRF request in native with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _numWords is the number of words to request. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPriceNative( + uint32 _callbackGasLimit, + uint32 _numWords, + uint256 _requestGasPriceWei + ) external view returns (uint256); + + /** + * @notice Requests randomness from the VRF V2 wrapper, paying in native token. + * + * @param _callbackGasLimit is the gas limit for the request. + * @param _requestConfirmations number of request confirmations to wait before serving a request. + * @param _numWords is the number of words to request. + */ + function requestRandomWordsInNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + bytes calldata extraArgs + ) external payable returns (uint256 requestId); + + function link() external view returns (address); + function linkNativeFeed() external view returns (address); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol new file mode 100644 index 0000000..31ed4de --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +// End consumer library. +library VRFV2PlusClient { + // extraArgs will evolve to support new features + bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1")); + struct ExtraArgsV1 { + bool nativePayment; + } + + struct RandomWordsRequest { + bytes32 keyHash; + uint256 subId; + uint16 requestConfirmations; + uint32 callbackGasLimit; + uint32 numWords; + bytes extraArgs; + } + + function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { + return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol new file mode 100644 index 0000000..1e781d1 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {VRFCoordinatorV2_5} from "../VRFCoordinatorV2_5.sol"; +import {VRFTypes} from "../../VRFTypes.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract ExposedVRFCoordinatorV2_5 is VRFCoordinatorV2_5 { + using EnumerableSet for EnumerableSet.UintSet; + + constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} + + function computeRequestIdExternal( + bytes32 keyHash, + address sender, + uint256 subId, + uint64 nonce + ) external pure returns (uint256, uint256) { + return _computeRequestId(keyHash, sender, subId, nonce); + } + + function isTargetRegisteredExternal(address target) external view returns (bool) { + return _isTargetRegistered(target); + } + + function getRandomnessFromProofExternal( + Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc + ) external view returns (Output memory) { + return _getRandomnessFromProof(proof, rc); + } + + function getActiveSubscriptionIdsLength() external view returns (uint256) { + return s_subIds.length(); + } + + function getSubscriptionConfig(uint256 subId) external view returns (SubscriptionConfig memory) { + return s_subscriptionConfigs[subId]; + } + + function getSubscriptionStruct(uint256 subId) external view returns (Subscription memory) { + return s_subscriptions[subId]; + } + + function setTotalBalanceTestingOnlyXXX(uint96 newBalance) external { + s_totalBalance = newBalance; + } + + function setTotalNativeBalanceTestingOnlyXXX(uint96 newBalance) external { + s_totalNativeBalance = newBalance; + } + + function setWithdrawableTokensTestingOnlyXXX(uint96 newBalance) external { + s_withdrawableTokens = newBalance; + } + + function getWithdrawableTokensTestingOnlyXXX() external view returns (uint96) { + return s_withdrawableTokens; + } + + function setWithdrawableNativeTestingOnlyXXX(uint96 newBalance) external { + s_withdrawableNative = newBalance; + } + + function getWithdrawableNativeTestingOnlyXXX() external view returns (uint96) { + return s_withdrawableNative; + } + + function calculatePaymentAmount( + uint256 startGas, + uint256 weiPerUnitGas, + bool nativePayment, + bool onlyPremium + ) external returns (uint96, bool) { + return _calculatePaymentAmount(startGas, weiPerUnitGas, nativePayment, onlyPremium); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol new file mode 100644 index 0000000..4f816db --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {VRFCoordinatorV2_5_Arbitrum} from "../VRFCoordinatorV2_5_Arbitrum.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract ExposedVRFCoordinatorV2_5_Arbitrum is VRFCoordinatorV2_5_Arbitrum { + constructor(address blockhashStore) VRFCoordinatorV2_5_Arbitrum(blockhashStore) {} + + function getBlockNumberExternal() external view returns (uint256) { + return _getBlockNumber(); + } + + function getBlockhashExternal(uint64 blockNumber) external view returns (bytes32) { + return _getBlockhash(blockNumber); + } + + function calculatePaymentAmountNativeExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) external returns (uint96) { + return _calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium); + } + + function calculatePaymentAmountLinkExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) external returns (uint96, bool) { + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol new file mode 100644 index 0000000..3732a1e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {VRFCoordinatorV2_5_Optimism} from "../VRFCoordinatorV2_5_Optimism.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract ExposedVRFCoordinatorV2_5_Optimism is VRFCoordinatorV2_5_Optimism { + constructor(address blockhashStore) VRFCoordinatorV2_5_Optimism(blockhashStore) {} + + function getBlockNumberExternal() external view returns (uint256) { + return _getBlockNumber(); + } + + function getBlockhashExternal(uint64 blockNumber) external view returns (bytes32) { + return _getBlockhash(blockNumber); + } + + function calculatePaymentAmountNativeExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) external returns (uint96) { + return _calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium); + } + + function calculatePaymentAmountLinkExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) external returns (uint96, bool) { + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol new file mode 100644 index 0000000..65a88df --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFConsumerBaseV2Upgradeable} from "../VRFConsumerBaseV2Upgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +contract VRFConsumerV2PlusUpgradeableExample is Initializable, VRFConsumerBaseV2Upgradeable { + uint256[] public s_randomWords; + uint256 public s_requestId; + IVRFCoordinatorV2Plus public COORDINATOR; + LinkTokenInterface public LINKTOKEN; + uint256 public s_subId; + uint256 public s_gasAvailable; + + function initialize(address _vrfCoordinator, address _link) public initializer { + __VRFConsumerBaseV2_init(_vrfCoordinator); + COORDINATOR = IVRFCoordinatorV2Plus(_vrfCoordinator); + LINKTOKEN = LinkTokenInterface(_link); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness( + bytes32 keyHash, + uint256 subId, + uint16 minReqConfs, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256) { + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: subId, + requestConfirmations: minReqConfs, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: "" // empty extraArgs defaults to link payment + }); + s_requestId = COORDINATOR.requestRandomWords(req); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol new file mode 100644 index 0000000..2e9c4a2 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol @@ -0,0 +1,773 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface.sol"; +import {VRFOld} from "./VRFOld.sol"; +import {VRFTypes} from "../../VRFTypes.sol"; +import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {SubscriptionAPI} from "../SubscriptionAPI.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; +import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; +// solhint-disable-next-line no-unused-import +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; + +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorTestV2_5 is VRFOld, SubscriptionAPI, IVRFCoordinatorV2Plus { + /// @dev should always be available + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error MsgDataTooBig(uint256 have, uint32 max); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error InvalidExtraArgsTag(); + error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); + + struct ProvingKey { + bool exists; // proving key exists + uint64 maxGas; // gas lane max gas price for fulfilling requests + } + + mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; + bytes32[] public s_provingKeyHashes; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); + event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + int256 public s_fallbackWeiPerUnitLink; + + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ); + + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + + constructor(address blockhashStore) SubscriptionAPI() { + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh].exists) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, maxGas); + } + + /** + * @notice Deregisters a proving key. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + ProvingKey memory key = s_provingKeys[kh]; + if (!key.exists) { + revert NoSuchProvingKey(kh); + } + delete s_provingKeys[kh]; + uint256 s_provingKeyHashesLength = s_provingKeyHashes.length; + for (uint256 i = 0; i < s_provingKeyHashesLength; ++i) { + if (s_provingKeyHashes[i] == kh) { + // Copy last element and overwrite kh to be deleted with it + s_provingKeyHashes[i] = s_provingKeyHashes[s_provingKeyHashesLength - 1]; + s_provingKeyHashes.pop(); + break; + } + } + emit ProvingKeyDeregistered(kh, key.maxGas); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed + * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment + * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native + * @param nativePremiumPercentage native premium percentage + * @param linkPremiumPercentage link premium percentage + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); + } + if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage: nativePremiumPercentage, + linkPremiumPercentage: linkPremiumPercentage + }); + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage, + linkPremiumPercentage + ); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + /** + * @notice Request a set of random words. + * @param req - a struct containing following fiels for randomness request: + * keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * requestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * extraArgs - Encoded extra arguments that has a boolean flag for whether payment + * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata req + ) external override nonReentrant returns (uint256 requestId) { + // Input validation using the subscription storage. + uint256 subId = req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; + ConsumerConfig memory consumerConfig = consumerConfigs[subId]; + if (!consumerConfig.active) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + req.requestConfirmations < s_config.minimumRequestConfirmations || + req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + req.requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (req.callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); + } + if (req.numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); + } + + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + ++consumerConfig.nonce; + ++consumerConfig.pendingReqCount; + uint256 preSeed; + (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); + s_requestCommitments[requestId] = keccak256( + abi.encode( + requestId, + ChainSpecificUtil._getBlockNumber(), + subId, + req.callbackGasLimit, + req.numWords, + msg.sender, + extraArgsBytes + ) + ); + emit RandomWordsRequested( + req.keyHash, + requestId, + preSeed, + subId, + req.requestConfirmations, + req.callbackGasLimit, + req.numWords, + extraArgsBytes, + msg.sender + ); + consumerConfigs[subId] = consumerConfig; + + return requestId; + } + + function _computeRequestId( + bytes32 keyHash, + address sender, + uint256 subId, + uint64 nonce + ) internal pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + struct Output { + ProvingKey provingKey; + uint256 requestId; + uint256 randomness; + } + + function _getRandomnessFromProof( + Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc + ) internal view returns (Output memory) { + bytes32 keyHash = hashOfKey(proof.pk); + ProvingKey memory key = s_provingKeys[keyHash]; + // Only registered proving keys are permitted. + if (!key.exists) { + revert NoSuchProvingKey(keyHash); + } + uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != + keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + uint256 randomness = VRFOld._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + return Output(key, requestId, randomness); + } + + function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { + if (tx.gasprice > gasLaneMaxGas) { + if (onlyPremium) { + // if only the premium amount needs to be billed, then the premium is capped by the gas lane max + return uint256(gasLaneMaxGas); + } else { + // Ensure gas price does not exceed the gas lane max gas price + revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); + } + } + return tx.gasprice; + } + + function _deliverRandomness( + uint256 requestId, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256[] memory randomWords + ) internal returns (bool success) { + VRFConsumerBaseV2Plus v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + return success; + } + + /* + * @notice Fulfill a randomness request. + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @param onlyPremium only charge premium + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + bool onlyPremium + ) external nonReentrant returns (uint96 payment) { + uint256 startGas = gasleft(); + // fulfillRandomWords msg.data has 772 bytes and with an additional + // buffer of 32 bytes, we get 804 bytes. + /* Data size split: + * fulfillRandomWords function signature - 4 bytes + * proof - 416 bytes + * pk - 64 bytes + * gamma - 64 bytes + * c - 32 bytes + * s - 32 bytes + * seed - 32 bytes + * uWitness - 32 bytes + * cGammaWitness - 64 bytes + * sHashWitness - 64 bytes + * zInv - 32 bytes + * requestCommitment - 320 bytes + * blockNum - 32 bytes + * subId - 32 bytes + * callbackGasLimit - 32 bytes + * numWords - 32 bytes + * sender - 32 bytes + * extraArgs - 128 bytes + * onlyPremium - 32 bytes + */ + if (msg.data.length > 804) { + revert MsgDataTooBig(msg.data.length, 804); + } + Output memory output = _getRandomnessFromProof(proof, rc); + uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); + + uint256[] memory randomWords; + uint256 randomness = output.randomness; + // stack too deep error + { + uint256 numWords = rc.numWords; + randomWords = new uint256[](numWords); + for (uint256 i = 0; i < numWords; ++i) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + } + + delete s_requestCommitments[output.requestId]; + bool success = _deliverRandomness(output.requestId, rc, randomWords); + + // Increment the req count for the subscription. + ++s_subscriptions[rc.subId].reqCount; + // Decrement the pending req count for the consumer. + --s_consumers[rc.sender][rc.subId].pendingReqCount; + + bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; + + // stack too deep error + { + // We want to charge users exactly for how much gas they use in their callback with + // an additional premium. If onlyPremium is true, only premium is charged without + // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional + // operations where we decrement the subscription balance and increment the + // withdrawable balance. + bool isFeedStale; + (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); + } + } + + _chargePayment(payment, nativePayment, rc.subId); + + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); + + return payment; + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + function _calculatePaymentAmount( + uint256 startGas, + uint256 weiPerUnitGas, + bool nativePayment, + bool onlyPremium + ) internal view returns (uint96, bool) { + if (nativePayment) { + return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); + } + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } + + function _calculatePaymentAmountNative( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96) { + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // calculate the payment without the premium + uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); + // calculate flat fee in native + uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); + if (onlyPremium) { + return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } else { + return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } + } + + // Get the amount of gas used for fulfillment + function _calculatePaymentAmountLink( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96, bool) { + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * + (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256(weiPerUnitLink); + // calculate the flat fee in wei + uint256 flatFeeWei = 1e12 * + uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); + uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); + uint256 payment; + if (onlyPremium) { + payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } else { + payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } + if (payment > 1e27) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return (uint96(payment), isFeedStale); + } + + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + uint256 timestamp; + (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return (weiPerUnitLink, isFeedStale); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function pendingRequestExists(uint256 subId) public view override returns (bool) { + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = consumers.length; + if (consumersLength == 0) { + return false; + } + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { + return true; + } + } + return false; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + if (!s_consumers[consumer][subId].active) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] memory consumers = s_subscriptionConfigs[subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == consumer) { + address last = consumers[lastConsumerIndex]; + // Storage write to preserve last element + s_subscriptionConfigs[subId].consumers[i] = last; + // Storage remove last element + s_subscriptionConfigs[subId].consumers.pop(); + break; + } + } + s_consumers[consumer][subId].active = false; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + _cancelSubscriptionHelper(subId, to); + } + + /*************************************************************************** + * Section: Migration + ***************************************************************************/ + + address[] internal s_migrationTargets; + + /// @dev Emitted when new coordinator is registered as migratable target + event CoordinatorRegistered(address coordinatorAddress); + + /// @dev Emitted when new coordinator is deregistered + event CoordinatorDeregistered(address coordinatorAddress); + + /// @notice emitted when migration to new coordinator completes successfully + /// @param newCoordinator coordinator address after migration + /// @param subId subscription ID + event MigrationCompleted(address newCoordinator, uint256 subId); + + /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target + error CoordinatorNotRegistered(address coordinatorAddress); + + /// @notice emitted when migrate() is called and given coordinator is registered as migratable target + error CoordinatorAlreadyRegistered(address coordinatorAddress); + + /// @dev encapsulates data to be migrated from current coordinator + // solhint-disable-next-line gas-struct-packing + struct V1MigrationData { + uint8 fromVersion; + uint256 subId; + address subOwner; + address[] consumers; + uint96 linkBalance; + uint96 nativeBalance; + } + + function _isTargetRegistered(address target) internal view returns (bool) { + uint256 migrationTargetsLength = s_migrationTargets.length; + for (uint256 i = 0; i < migrationTargetsLength; ++i) { + if (s_migrationTargets[i] == target) { + return true; + } + } + return false; + } + + function registerMigratableCoordinator(address target) external onlyOwner { + if (_isTargetRegistered(target)) { + revert CoordinatorAlreadyRegistered(target); + } + s_migrationTargets.push(target); + emit CoordinatorRegistered(target); + } + + function deregisterMigratableCoordinator(address target) external onlyOwner { + uint256 nTargets = s_migrationTargets.length; + for (uint256 i = 0; i < nTargets; ++i) { + if (s_migrationTargets[i] == target) { + s_migrationTargets[i] = s_migrationTargets[nTargets - 1]; + s_migrationTargets.pop(); + emit CoordinatorDeregistered(target); + return; + } + } + revert CoordinatorNotRegistered(target); + } + + function migrate(uint256 subId, address newCoordinator) external nonReentrant { + if (!_isTargetRegistered(newCoordinator)) { + revert CoordinatorNotRegistered(newCoordinator); + } + (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); + // solhint-disable-next-line gas-custom-errors + require(subOwner == msg.sender, "Not subscription owner"); + // solhint-disable-next-line gas-custom-errors + require(!pendingRequestExists(subId), "Pending request exists"); + + V1MigrationData memory migrationData = V1MigrationData({ + fromVersion: 1, + subId: subId, + subOwner: subOwner, + consumers: consumers, + linkBalance: balance, + nativeBalance: nativeBalance + }); + bytes memory encodedData = abi.encode(migrationData); + _deleteSubscription(subId); + IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); + + // Only transfer LINK if the token is active and there is a balance. + if (address(LINK) != address(0) && balance != 0) { + // solhint-disable-next-line gas-custom-errors + require(LINK.transfer(address(newCoordinator), balance), "insufficient funds"); + } + + // despite the fact that we follow best practices this is still probably safest + // to prevent any re-entrancy possibilities. + s_config.reentrancyLock = true; + for (uint256 i = 0; i < consumers.length; ++i) { + IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); + } + s_config.reentrancyLock = false; + + emit MigrationCompleted(newCoordinator, subId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol new file mode 100644 index 0000000..af5c56b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol @@ -0,0 +1,809 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface.sol"; +// solhint-disable-next-line no-unused-import +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRF} from "../../../vrf/VRF.sol"; +import {VRFTypes} from "../../VRFTypes.sol"; +import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {SubscriptionAPI} from "../SubscriptionAPI.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; +import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; + +contract VRFCoordinatorV2PlusUpgradedVersion is + VRF, + SubscriptionAPI, + IVRFCoordinatorV2PlusMigration, + IVRFCoordinatorV2Plus +{ + using EnumerableSet for EnumerableSet.UintSet; + /// @dev should always be available + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error MsgDataTooBig(uint256 have, uint32 max); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error InvalidExtraArgsTag(); + error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); + /// @notice emitted when version in the request doesn't match expected version + error InvalidVersion(uint8 requestVersion, uint8 expectedVersion); + /// @notice emitted when transferred balance (msg.value) does not match the metadata in V1MigrationData + error InvalidNativeBalance(uint256 transferredValue, uint96 expectedValue); + error SubscriptionIDCollisionFound(); + + struct ProvingKey { + bool exists; // proving key exists + uint64 maxGas; // gas lane max gas price for fulfilling requests + } + + mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; + bytes32[] public s_provingKeyHashes; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + int256 public s_fallbackWeiPerUnitLink; + + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ); + + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + + constructor(address blockhashStore) SubscriptionAPI() { + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh].exists) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, maxGas); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed + * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment + * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native + * @param nativePremiumPercentage native premium percentage + * @param linkPremiumPercentage link premium percentage + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, + uint8 nativePremiumPercentage, + uint8 linkPremiumPercentage + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); + } + if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage: nativePremiumPercentage, + linkPremiumPercentage: linkPremiumPercentage + }); + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM, + nativePremiumPercentage, + linkPremiumPercentage + ); + } + + /** + * @notice Get configuration relevant for making requests + * @return minimumRequestConfirmations global min for request confirmations + * @return maxGasLimit global max for request gas limit + * @return s_provingKeyHashes list of registered key hashes + */ + function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory) { + return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + /** + * @notice Request a set of random words. + * @param req - a struct containing following fiels for randomness request: + * keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * requestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * extraArgs - Encoded extra arguments that has a boolean flag for whether payment + * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata req + ) external override nonReentrant returns (uint256 requestId) { + // Input validation using the subscription storage. + uint256 subId = req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; + ConsumerConfig memory consumerConfig = consumerConfigs[subId]; + if (!consumerConfig.active) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + req.requestConfirmations < s_config.minimumRequestConfirmations || + req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + req.requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (req.callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); + } + if (req.numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); + } + + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + ++consumerConfig.nonce; + ++consumerConfig.pendingReqCount; + uint256 preSeed; + (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); + s_requestCommitments[requestId] = keccak256( + abi.encode( + requestId, + ChainSpecificUtil._getBlockNumber(), + subId, + req.callbackGasLimit, + req.numWords, + msg.sender, + extraArgsBytes + ) + ); + emit RandomWordsRequested( + req.keyHash, + requestId, + preSeed, + subId, + req.requestConfirmations, + req.callbackGasLimit, + req.numWords, + extraArgsBytes, + msg.sender + ); + consumerConfigs[subId] = consumerConfig; + + return requestId; + } + + function _computeRequestId( + bytes32 keyHash, + address sender, + uint256 subId, + uint64 nonce + ) internal pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + struct Output { + ProvingKey provingKey; + uint256 requestId; + uint256 randomness; + } + + function _getRandomnessFromProof( + Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc + ) internal view returns (Output memory) { + bytes32 keyHash = hashOfKey(proof.pk); + ProvingKey memory key = s_provingKeys[keyHash]; + // Only registered proving keys are permitted. + if (!key.exists) { + revert NoSuchProvingKey(keyHash); + } + uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != + keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + uint256 randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + return Output(key, requestId, randomness); + } + + function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { + if (tx.gasprice > gasLaneMaxGas) { + if (onlyPremium) { + // if only the premium amount needs to be billed, then the premium is capped by the gas lane max + return uint256(gasLaneMaxGas); + } else { + // Ensure gas price does not exceed the gas lane max gas price + revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); + } + } + return tx.gasprice; + } + + function _deliverRandomness( + uint256 requestId, + VRFTypes.RequestCommitmentV2Plus calldata rc, + uint256[] memory randomWords + ) internal returns (bool success) { + VRFConsumerBaseV2Plus v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + return success; + } + + /* + * @notice Fulfill a randomness request. + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @param onlyPremium only charge premium + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof calldata proof, + VRFTypes.RequestCommitmentV2Plus calldata rc, + bool onlyPremium + ) external nonReentrant returns (uint96 payment) { + uint256 startGas = gasleft(); + // fulfillRandomWords msg.data has 772 bytes and with an additional + // buffer of 32 bytes, we get 804 bytes. + /* Data size split: + * fulfillRandomWords function signature - 4 bytes + * proof - 416 bytes + * pk - 64 bytes + * gamma - 64 bytes + * c - 32 bytes + * s - 32 bytes + * seed - 32 bytes + * uWitness - 32 bytes + * cGammaWitness - 64 bytes + * sHashWitness - 64 bytes + * zInv - 32 bytes + * requestCommitment - 320 bytes + * blockNum - 32 bytes + * subId - 32 bytes + * callbackGasLimit - 32 bytes + * numWords - 32 bytes + * sender - 32 bytes + * extraArgs - 128 bytes + * onlyPremium - 32 bytes + */ + if (msg.data.length > 804) { + revert MsgDataTooBig(msg.data.length, 804); + } + Output memory output = _getRandomnessFromProof(proof, rc); + uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); + + uint256[] memory randomWords; + uint256 randomness = output.randomness; + // stack too deep error + { + uint256 numWords = rc.numWords; + randomWords = new uint256[](numWords); + for (uint256 i = 0; i < numWords; ++i) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + } + + delete s_requestCommitments[output.requestId]; + bool success = _deliverRandomness(output.requestId, rc, randomWords); + + // Increment the req count for the subscription. + ++s_subscriptions[rc.subId].reqCount; + // Decrement the pending req count for the consumer. + --s_consumers[rc.sender][rc.subId].pendingReqCount; + + bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; + + // stack too deep error + { + // We want to charge users exactly for how much gas they use in their callback with + // an additional premium. If onlyPremium is true, only premium is charged without + // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional + // operations where we decrement the subscription balance and increment the + // withdrawable balance. + bool isFeedStale; + (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); + } + } + + _chargePayment(payment, nativePayment, rc.subId); + + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); + + return payment; + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + function _calculatePaymentAmount( + uint256 startGas, + uint256 weiPerUnitGas, + bool nativePayment, + bool onlyPremium + ) internal view returns (uint96, bool) { + if (nativePayment) { + return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); + } + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); + } + + function _calculatePaymentAmountNative( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96) { + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // calculate the payment without the premium + uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); + // calculate flat fee in native + uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); + if (onlyPremium) { + return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } else { + return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } + } + + // Get the amount of gas used for fulfillment + function _calculatePaymentAmountLink( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96, bool) { + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // Will return non-zero on chains that have this enabled + uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); + // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * + (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256(weiPerUnitLink); + // calculate the flat fee in wei + uint256 flatFeeWei = 1e12 * + uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); + uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); + uint256 payment; + if (onlyPremium) { + payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } else { + payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } + if (payment > 1e27) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return (uint96(payment), isFeedStale); + } + + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + uint256 timestamp; + (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return (weiPerUnitLink, isFeedStale); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function pendingRequestExists(uint256 subId) public view override returns (bool) { + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = consumers.length; + if (consumersLength == 0) { + return false; + } + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { + return true; + } + } + return false; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + if (!s_consumers[consumer][subId].active) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] memory consumers = s_subscriptionConfigs[subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == consumer) { + address last = consumers[lastConsumerIndex]; + // Storage write to preserve last element + s_subscriptionConfigs[subId].consumers[i] = last; + // Storage remove last element + s_subscriptionConfigs[subId].consumers.pop(); + break; + } + } + s_consumers[consumer][subId].active = false; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + _cancelSubscriptionHelper(subId, to); + } + + /*************************************************************************** + * Section: Migration + ***************************************************************************/ + + address[] internal s_migrationTargets; + + /// @dev Emitted when new coordinator is registered as migratable target + event CoordinatorRegistered(address coordinatorAddress); + + /// @notice emitted when migration to new coordinator completes successfully + /// @param newCoordinator coordinator address after migration + /// @param subId subscription ID + event MigrationCompleted(address newCoordinator, uint256 subId); + + /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target + error CoordinatorNotRegistered(address coordinatorAddress); + + /// @notice emitted when migrate() is called and given coordinator is registered as migratable target + error CoordinatorAlreadyRegistered(address coordinatorAddress); + + /// @dev encapsulates data to be migrated from current coordinator + // solhint-disable-next-line gas-struct-packing + struct V1MigrationData { + uint8 fromVersion; + uint256 subId; + address subOwner; + address[] consumers; + uint96 linkBalance; + uint96 nativeBalance; + } + + function _isTargetRegistered(address target) internal view returns (bool) { + uint256 migrationTargetsLength = s_migrationTargets.length; + for (uint256 i = 0; i < migrationTargetsLength; ++i) { + if (s_migrationTargets[i] == target) { + return true; + } + } + return false; + } + + function registerMigratableCoordinator(address target) external onlyOwner { + if (_isTargetRegistered(target)) { + revert CoordinatorAlreadyRegistered(target); + } + s_migrationTargets.push(target); + emit CoordinatorRegistered(target); + } + + function migrate(uint256 subId, address newCoordinator) external nonReentrant { + if (!_isTargetRegistered(newCoordinator)) { + revert CoordinatorNotRegistered(newCoordinator); + } + (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); + // solhint-disable-next-line gas-custom-errors + require(subOwner == msg.sender, "Not subscription owner"); + // solhint-disable-next-line gas-custom-errors + require(!pendingRequestExists(subId), "Pending request exists"); + + V1MigrationData memory migrationData = V1MigrationData({ + fromVersion: 1, + subId: subId, + subOwner: subOwner, + consumers: consumers, + linkBalance: balance, + nativeBalance: nativeBalance + }); + bytes memory encodedData = abi.encode(migrationData); + _deleteSubscription(subId); + IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); + + // Only transfer LINK if the token is active and there is a balance. + if (address(LINK) != address(0) && balance != 0) { + // solhint-disable-next-line gas-custom-errors + require(LINK.transfer(address(newCoordinator), balance), "insufficient funds"); + } + + // despite the fact that we follow best practices this is still probably safest + // to prevent any re-entrancy possibilities. + s_config.reentrancyLock = true; + for (uint256 i = 0; i < consumers.length; ++i) { + IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); + } + s_config.reentrancyLock = false; + + emit MigrationCompleted(newCoordinator, subId); + } + + function migrationVersion() public pure returns (uint8 version) { + return 2; + } + + /** + * @inheritdoc IVRFCoordinatorV2PlusMigration + */ + function onMigration(bytes calldata encodedData) external payable override { + V1MigrationData memory migrationData = abi.decode(encodedData, (V1MigrationData)); + + if (migrationData.fromVersion != 1) { + revert InvalidVersion(migrationData.fromVersion, 1); + } + + if (msg.value != uint256(migrationData.nativeBalance)) { + revert InvalidNativeBalance(msg.value, migrationData.nativeBalance); + } + + // it should be impossible to have a subscription id collision, for two reasons: + // 1. the subscription ID is calculated using inputs that cannot be replicated under different + // conditions. + // 2. once a subscription is migrated it is deleted from the previous coordinator, so it cannot + // be migrated again. + // however, we should have this check here in case the `migrate` function on + // future coordinators "forgets" to delete subscription data allowing re-migration of the same + // subscription. + if (s_subscriptionConfigs[migrationData.subId].owner != address(0)) { + revert SubscriptionIDCollisionFound(); + } + + for (uint256 i = 0; i < migrationData.consumers.length; i++) { + s_consumers[migrationData.consumers[i]][migrationData.subId] = ConsumerConfig({ + active: true, + nonce: 0, + pendingReqCount: 0 + }); + } + + s_subscriptions[migrationData.subId] = Subscription({ + nativeBalance: migrationData.nativeBalance, + balance: migrationData.linkBalance, + reqCount: 0 + }); + s_subscriptionConfigs[migrationData.subId] = SubscriptionConfig({ + owner: migrationData.subOwner, + consumers: migrationData.consumers, + requestedOwner: address(0) + }); + + s_totalBalance += uint96(migrationData.linkBalance); + s_totalNativeBalance += uint96(migrationData.nativeBalance); + + s_subIds.add(migrationData.subId); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol new file mode 100644 index 0000000..1a2ed50 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +/// @dev this contract is only meant for testing migration +/// @dev it is a simplified example of future version (V2) of VRFCoordinatorV2Plus +// solhint-disable-next-line contract-name-camelcase +contract VRFCoordinatorV2Plus_V2Example is IVRFCoordinatorV2PlusMigration { + error SubscriptionIDCollisionFound(); + + struct Subscription { + uint96 linkBalance; + uint96 nativeBalance; + uint64 reqCount; + address owner; + address[] consumers; + } + + mapping(uint256 => Subscription) public s_subscriptions; /* subId */ /* subscription */ + mapping(uint256 => address) public s_requestConsumerMapping; /* RequestId */ /* consumer address */ + + uint96 public s_totalLinkBalance; + uint96 public s_totalNativeBalance; + // request ID nonce + uint256 public s_requestId = 0; + + // older version of coordinator, from which migration is supported + address public s_prevCoordinator; + address public s_link; + + constructor(address link, address prevCoordinator) { + s_link = link; + s_prevCoordinator = prevCoordinator; + } + + /*************************************************************************** + * Section: Subscription + **************************************************************************/ + + /// @dev Emitted when a subscription for a given ID cannot be found + error InvalidSubscription(); + + function getSubscription( + uint256 subId + ) + public + view + returns (uint96 linkBalance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers) + { + if (s_subscriptions[subId].owner == address(0)) { + revert InvalidSubscription(); + } + return ( + s_subscriptions[subId].linkBalance, + s_subscriptions[subId].nativeBalance, + s_subscriptions[subId].reqCount, + s_subscriptions[subId].owner, + s_subscriptions[subId].consumers + ); + } + + /*************************************************************************** + * Section: Migration + **************************************************************************/ + + /// @notice emitted when caller is not a previous version of VRF coordinator + /// @param sender caller + /// @param previousCoordinator expected coordinator address + error MustBePreviousCoordinator(address sender, address previousCoordinator); + + /// @notice emitted when version in the request doesn't match expected version + error InvalidVersion(uint8 requestVersion, uint8 expectedVersion); + + /// @notice emitted when transferred balance (msg.value) does not match the metadata in V1MigrationData + error InvalidNativeBalance(uint256 transferredValue, uint96 expectedValue); + + /// @dev encapsulates data migrated over from previous coordinator + // solhint-disable-next-line gas-struct-packing + struct V1MigrationData { + uint8 fromVersion; + uint256 subId; + address subOwner; + address[] consumers; + uint96 linkBalance; + uint96 nativeBalance; + } + + /** + * @inheritdoc IVRFCoordinatorV2PlusMigration + */ + function onMigration(bytes calldata encodedData) external payable override { + if (msg.sender != s_prevCoordinator) { + revert MustBePreviousCoordinator(msg.sender, s_prevCoordinator); + } + + V1MigrationData memory migrationData = abi.decode(encodedData, (V1MigrationData)); + + if (migrationData.fromVersion != 1) { + revert InvalidVersion(migrationData.fromVersion, 1); + } + + if (msg.value != uint256(migrationData.nativeBalance)) { + revert InvalidNativeBalance(msg.value, migrationData.nativeBalance); + } + + // it should be impossible to have a subscription id collision, for two reasons: + // 1. the subscription ID is calculated using inputs that cannot be replicated under different + // conditions. + // 2. once a subscription is migrated it is deleted from the previous coordinator, so it cannot + // be migrated again. + // however, we should have this check here in case the `migrate` function on + // future coordinators "forgets" to delete subscription data allowing re-migration of the same + // subscription. + if (s_subscriptions[migrationData.subId].owner != address(0)) { + revert SubscriptionIDCollisionFound(); + } + + s_subscriptions[migrationData.subId] = Subscription({ + nativeBalance: migrationData.nativeBalance, + linkBalance: migrationData.linkBalance, + reqCount: 0, + owner: migrationData.subOwner, + consumers: migrationData.consumers + }); + s_totalNativeBalance += migrationData.nativeBalance; + s_totalLinkBalance += migrationData.linkBalance; + } + + /*************************************************************************** + * Section: Request/Response + **************************************************************************/ + + function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId) { + Subscription memory sub = s_subscriptions[req.subId]; + sub.reqCount = sub.reqCount + 1; + return _handleRequest(msg.sender); + } + + function _handleRequest(address requester) private returns (uint256) { + s_requestId = s_requestId + 1; + uint256 requestId = s_requestId; + s_requestConsumerMapping[s_requestId] = requester; + return requestId; + } + + function generateFakeRandomness(uint256 requestID) public pure returns (uint256[] memory) { + uint256[] memory randomness = new uint256[](1); + randomness[0] = uint256(keccak256(abi.encode(requestID, "not random"))); + return randomness; + } + + function fulfillRandomWords(uint256 requestId) external { + VRFConsumerBaseV2Plus consumer = VRFConsumerBaseV2Plus(s_requestConsumerMapping[requestId]); + consumer.rawFulfillRandomWords(requestId, generateFakeRandomness(requestId)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol new file mode 100644 index 0000000..f638b97 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +contract VRFMaliciousConsumerV2Plus is VRFConsumerBaseV2Plus { + uint256[] public s_randomWords; + uint256 public s_requestId; + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + LinkTokenInterface internal LINKTOKEN; + uint256 public s_gasAvailable; + uint256 internal s_subId; + bytes32 internal s_keyHash; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + LINKTOKEN = LinkTokenInterface(link); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + s_requestId = requestId; + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: s_keyHash, + subId: s_subId, + requestConfirmations: 1, + callbackGasLimit: 200000, + numWords: 1, + extraArgs: "" // empty extraArgs defaults to link payment + }); + // Should revert + s_vrfCoordinator.requestRandomWords(req); + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = s_vrfCoordinator.createSubscription(); + s_vrfCoordinator.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + s_vrfCoordinator.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness(bytes32 keyHash) external returns (uint256) { + s_keyHash = keyHash; + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: s_subId, + requestConfirmations: 1, + callbackGasLimit: 500000, + numWords: 1, + extraArgs: "" // empty extraArgs defaults to link payment + }); + return s_vrfCoordinator.requestRandomWords(req); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol new file mode 100644 index 0000000..137235f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol @@ -0,0 +1,588 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/** **************************************************************************** + * @notice Verification of verifiable-random-function (VRF) proofs, following + * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. + + * @dev Bibliographic references: + + * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft + * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 + + * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology + * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf + * **************************************************************************** + * @dev USAGE + + * @dev The main entry point is _randomValueFromVRFProof. See its docstring. + * **************************************************************************** + * @dev PURPOSE + + * @dev Reggie the Random Oracle (not his real job) wants to provide randomness + * @dev to Vera the verifier in such a way that Vera can be sure he's not + * @dev making his output up to suit himself. Reggie provides Vera a public key + * @dev to which he knows the secret key. Each time Vera provides a seed to + * @dev Reggie, he gives back a value which is computed completely + * @dev deterministically from the seed and the secret key. + + * @dev Reggie provides a proof by which Vera can verify that the output was + * @dev correctly computed once Reggie tells it to her, but without that proof, + * @dev the output is computationally indistinguishable to her from a uniform + * @dev random sample from the output space. + + * @dev The purpose of this contract is to perform that verification. + * **************************************************************************** + * @dev DESIGN NOTES + + * @dev The VRF algorithm verified here satisfies the full uniqueness, full + * @dev collision resistance, and full pseudo-randomness security properties. + * @dev See "SECURITY PROPERTIES" below, and + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 + + * @dev An elliptic curve point is generally represented in the solidity code + * @dev as a uint256[2], corresponding to its affine coordinates in + * @dev GF(FIELD_SIZE). + + * @dev For the sake of efficiency, this implementation deviates from the spec + * @dev in some minor ways: + + * @dev - Keccak hash rather than the SHA256 hash recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev Keccak costs much less gas on the EVM, and provides similar security. + + * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 + * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER + + * @dev - _hashToCurve recursively hashes until it finds a curve x-ordinate. On + * @dev the EVM, this is slightly more efficient than the recommendation in + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + * @dev step 5, to concatenate with a nonce then hash, and rehash with the + * @dev nonce updated until a valid x-ordinate is found. + + * @dev - _hashToCurve does not include a cipher version string or the byte 0x1 + * @dev in the hash message, as recommended in step 5.B of the draft + * @dev standard. They are unnecessary here because no variation in the + * @dev cipher suite is allowed. + + * @dev - Similarly, the hash input in _scalarFromCurvePoints does not include a + * @dev commitment to the cipher suite, either, which differs from step 2 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + * @dev . Also, the hash input is the concatenation of the uncompressed + * @dev points, not the compressed points as recommended in step 3. + + * @dev - In the calculation of the challenge value "c", the "u" value (i.e. + * @dev the value computed by Reggie as the nonce times the secp256k1 + * @dev generator point, see steps 5 and 7 of + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 + * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the + * @dev keccak hash of the original u. This is because we only verify the + * @dev calculation of u up to its address, by abusing ECRECOVER. + * **************************************************************************** + * @dev SECURITY PROPERTIES + + * @dev Here are the security properties for this VRF: + + * @dev Full uniqueness: For any seed and valid VRF public key, there is + * @dev exactly one VRF output which can be proved to come from that seed, in + * @dev the sense that the proof will pass _verifyVRFProof. + + * @dev Full collision resistance: It's cryptographically infeasible to find + * @dev two seeds with same VRF output from a fixed, valid VRF key + + * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are + * @dev derived from a given seed, the outputs are computationally + * @dev indistinguishable from randomness. + + * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs + * @dev for these properties. + + * @dev For secp256k1, the key validation described in section + * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 + * @dev is unnecessary, because secp256k1 has cofactor 1, and the + * @dev representation of the public key used here (affine x- and y-ordinates + * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to + * @dev the point at infinity. + * **************************************************************************** + * @dev OTHER SECURITY CONSIDERATIONS + * + * @dev The seed input to the VRF could in principle force an arbitrary amount + * @dev of work in _hashToCurve, by requiring extra rounds of hashing and + * @dev checking whether that's yielded the x ordinate of a secp256k1 point. + * @dev However, under the Random Oracle Model the probability of choosing a + * @dev point which forces n extra rounds in _hashToCurve is 2⁻ⁿ. The base cost + * @dev for calling _hashToCurve is about 25,000 gas, and each round of checking + * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for + * @dev which _hashToCurve would cost more than 2,017,000 gas, one would have to + * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any + * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) + + * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, + * @dev this means it is infeasible for an adversary to prevent correct + * @dev operation of this contract by choosing an adverse seed. + + * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for + * @dev _hashToCurve.) + + * @dev It may be possible to make a secure constant-time _hashToCurve function. + * @dev See notes in _hashToCurve docstring. +*/ +contract VRFOld { + // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. + // Number of points in Secp256k1 + uint256 private constant GROUP_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; + // Prime characteristic of the galois field over which Secp256k1 is defined + uint256 private constant FIELD_SIZE = + // solium-disable-next-line indentation + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; + uint256 private constant WORD_LENGTH_BYTES = 0x20; + + // (base^exponent) % FIELD_SIZE + // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 + function _bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { + uint256 callResult; + uint256[6] memory bigModExpContractInputs; + bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base + bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent + bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus + bigModExpContractInputs[3] = base; + bigModExpContractInputs[4] = exponent; + bigModExpContractInputs[5] = FIELD_SIZE; + uint256[1] memory output; + assembly { + callResult := staticcall( + not(0), // Gas cost: no limit + 0x05, // Bigmodexp contract address + bigModExpContractInputs, + 0xc0, // Length of input segment: 6*0x20-bytes + output, + 0x20 // Length of output segment + ) + } + if (callResult == 0) { + // solhint-disable-next-line gas-custom-errors + revert("bigModExp failure!"); + } + return output[0]; + } + + // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See + // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus + uint256 private constant SQRT_POWER = (FIELD_SIZE + 1) >> 2; + + // Computes a s.t. a^2 = x in the field. Assumes a exists + function _squareRoot(uint256 x) internal view returns (uint256) { + return _bigModExp(x, SQRT_POWER); + } + + // The value of y^2 given that (x,y) is on secp256k1. + function _ySquared(uint256 x) internal pure returns (uint256) { + // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf + uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); + return addmod(xCubed, 7, FIELD_SIZE); + } + + // True iff p is on secp256k1 + function _isOnCurve(uint256[2] memory p) internal pure returns (bool) { + // Section 2.3.6. in https://www.secg.org/sec1-v2.pdf + // requires each ordinate to be in [0, ..., FIELD_SIZE-1] + // solhint-disable-next-line gas-custom-errors + require(p[0] < FIELD_SIZE, "invalid x-ordinate"); + // solhint-disable-next-line gas-custom-errors + require(p[1] < FIELD_SIZE, "invalid y-ordinate"); + return _ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); + } + + // Hash x uniformly into {0, ..., FIELD_SIZE-1}. + function _fieldHash(bytes memory b) internal pure returns (uint256 x_) { + x_ = uint256(keccak256(b)); + // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of + // http://www.secg.org/sec1-v2.pdf , which is part of the definition of + // string_to_point in the IETF draft + while (x_ >= FIELD_SIZE) { + x_ = uint256(keccak256(abi.encodePacked(x_))); + } + return x_; + } + + // Hash b to a random point which hopefully lies on secp256k1. The y ordinate + // is always even, due to + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 + // step 5.C, which references arbitrary_string_to_point, defined in + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as + // returning the point with given x ordinate, and even y ordinate. + function _newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { + unchecked { + p[0] = _fieldHash(b); + p[1] = _squareRoot(_ySquared(p[0])); + if (p[1] % 2 == 1) { + // Note that 0 <= p[1] < FIELD_SIZE + // so this cannot wrap, we use unchecked to save gas. + p[1] = FIELD_SIZE - p[1]; + } + } + return p; + } + + // Domain-separation tag for initial hash in _hashToCurve. Corresponds to + // vrf.go/hashToCurveHashPrefix + uint256 internal constant HASH_TO_CURVE_HASH_PREFIX = 1; + + // Cryptographic hash function onto the curve. + // + // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see + // DESIGN NOTES above for slight differences.) + // + // TODO(alx): Implement a bounded-computation hash-to-curve, as described in + // "Construction of Rational Points on Elliptic Curves over Finite Fields" + // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf + // and suggested by + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 + // (Though we can't used exactly that because secp256k1's j-invariant is 0.) + // + // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" + // https://www.pivotaltracker.com/story/show/171120900 + function _hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); + while (!_isOnCurve(rv)) { + rv = _newCandidateSecp256k1Point(abi.encodePacked(rv[0])); + } + return rv; + } + + /** ********************************************************************* + * @notice Check that product==scalar*multiplicand + * + * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. + * + * @param multiplicand: secp256k1 point + * @param scalar: non-zero GF(GROUP_ORDER) scalar + * @param product: secp256k1 expected to be multiplier * multiplicand + * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability + */ + function _ecmulVerify( + uint256[2] memory multiplicand, + uint256 scalar, + uint256[2] memory product + ) internal pure returns (bool verifies) { + // solhint-disable-next-line gas-custom-errors + require(scalar != 0, "zero scalar"); // Rules out an ecrecover failure case + uint256 x = multiplicand[0]; // x ordinate of multiplicand + uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is + // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. + // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 + bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); + address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); + // Explicit conversion to address takes bottom 160 bits + address expected = address(uint160(uint256(keccak256(abi.encodePacked(product))))); + return (actual == expected); + } + + // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) + function _projectiveSub( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + unchecked { + uint256 num1 = mulmod(z2, x1, FIELD_SIZE); + // Note this cannot wrap since x2 is a point in [0, FIELD_SIZE-1] + // we use unchecked to save gas. + uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); + (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + } + return (x3, z3); + } + + // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) + function _projectiveMul( + uint256 x1, + uint256 z1, + uint256 x2, + uint256 z2 + ) internal pure returns (uint256 x3, uint256 z3) { + (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); + return (x3, z3); + } + + /** ************************************************************************** + @notice Computes elliptic-curve sum, in projective co-ordinates + + @dev Using projective coordinates avoids costly divisions + + @dev To use this with p and q in affine coordinates, call + @dev _projectiveECAdd(px, py, qx, qy). This will return + @dev the addition of (px, py, 1) and (qx, qy, 1), in the + @dev secp256k1 group. + + @dev This can be used to calculate the z which is the inverse to zInv + @dev in isValidVRFOutput. But consider using a faster + @dev re-implementation such as ProjectiveECAdd in the golang vrf package. + + @dev This function assumes [px,py,1],[qx,qy,1] are valid projective + coordinates of secp256k1 points. That is safe in this contract, + because this method is only used by _linearCombination, which checks + points are on the curve via ecrecover. + ************************************************************************** + @param px The first affine coordinate of the first summand + @param py The second affine coordinate of the first summand + @param qx The first affine coordinate of the second summand + @param qy The second affine coordinate of the second summand + + (px,py) and (qx,qy) must be distinct, valid secp256k1 points. + ************************************************************************** + Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points + on secp256k1, in P²(𝔽ₙ) + @return sx + @return sy + @return sz + */ + function _projectiveECAdd( + uint256 px, + uint256 py, + uint256 qx, + uint256 qy + ) internal pure returns (uint256 sx, uint256 sy, uint256 sz) { + unchecked { + // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, + // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone + // We take the equations there for (sx,sy), and homogenize them to + // projective coordinates. That way, no inverses are required, here, and we + // only need the one inverse in _affineECAdd. + + // We only need the "point addition" equations from Hankerson et al. Can + // skip the "point doubling" equations because p1 == p2 is cryptographically + // impossible, and required not to be the case in _linearCombination. + + // Add extra "projective coordinate" to the two points + (uint256 z1, uint256 z2) = (1, 1); + + // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. + // Cannot wrap since px and py are in [0, FIELD_SIZE-1] + uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); + uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); + + uint256 dx; // Accumulates denominator from sx calculation + // sx=((qy-py)/(qx-px))^2-px-qx + (sx, dx) = _projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 + (sx, dx) = _projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px + (sx, dx) = _projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx + + uint256 dy; // Accumulates denominator from sy calculation + // sy=((qy-py)/(qx-px))(px-sx)-py + (sy, dy) = _projectiveSub(px, z1, sx, dx); // px-sx + (sy, dy) = _projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) + (sy, dy) = _projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py + + if (dx != dy) { + // Cross-multiply to put everything over a common denominator + sx = mulmod(sx, dy, FIELD_SIZE); + sy = mulmod(sy, dx, FIELD_SIZE); + sz = mulmod(dx, dy, FIELD_SIZE); + } else { + // Already over a common denominator, use that for z ordinate + sz = dx; + } + } + return (sx, sy, sz); + } + + // p1+p2, as affine points on secp256k1. + // + // invZ must be the inverse of the z returned by _projectiveECAdd(p1, p2). + // It is computed off-chain to save gas. + // + // p1 and p2 must be distinct, because _projectiveECAdd doesn't handle + // point doubling. + function _affineECAdd( + uint256[2] memory p1, + uint256[2] memory p2, + uint256 invZ + ) internal pure returns (uint256[2] memory) { + uint256 x; + uint256 y; + uint256 z; + (x, y, z) = _projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); + // solhint-disable-next-line gas-custom-errors + require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); + // Clear the z ordinate of the projective representation by dividing through + // by it, to obtain the affine representation + return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; + } + + // True iff address(c*p+s*g) == lcWitness, where g is generator. (With + // cryptographically high probability.) + function _verifyLinearCombinationWithGenerator( + uint256 c, + uint256[2] memory p, + uint256 s, + address lcWitness + ) internal pure returns (bool) { + // Rule out ecrecover failure modes which return address 0. + unchecked { + // solhint-disable-next-line gas-custom-errors + require(lcWitness != address(0), "bad witness"); + uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p + // Note this cannot wrap (X - Y % X), but we use unchecked to save + // gas. + bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] + bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] + // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 + // The point corresponding to the address returned by + // ecrecover(-s*p[0],v,p[0],c*p[0]) is + // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. + // See https://crypto.stackexchange.com/a/18106 + // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v + address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); + return computed == lcWitness; + } + } + + // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also + // requires cp1Witness != sp2Witness (which is fine for this application, + // since it is cryptographically impossible for them to be equal. In the + // (cryptographically impossible) case that a prover accidentally derives + // a proof with equal c*p1 and s*p2, they should retry with a different + // proof nonce.) Assumes that all points are on secp256k1 + // (which is checked in _verifyVRFProof below.) + function _linearCombination( + uint256 c, + uint256[2] memory p1, + uint256[2] memory cp1Witness, + uint256 s, + uint256[2] memory p2, + uint256[2] memory sp2Witness, + uint256 zInv + ) internal pure returns (uint256[2] memory) { + unchecked { + // Note we are relying on the wrap around here + // solhint-disable-next-line gas-custom-errors + require((cp1Witness[0] % FIELD_SIZE) != (sp2Witness[0] % FIELD_SIZE), "points in sum must be distinct"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p1, c, cp1Witness), "First mul check failed"); + // solhint-disable-next-line gas-custom-errors + require(_ecmulVerify(p2, s, sp2Witness), "Second mul check failed"); + return _affineECAdd(cp1Witness, sp2Witness, zInv); + } + } + + // Domain-separation tag for the hash taken in _scalarFromCurvePoints. + // Corresponds to scalarFromCurveHashPrefix in vrf.go + uint256 internal constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; + + // Pseudo-random number from inputs. Matches vrf.go/_scalarFromCurvePoints, and + // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 + // The draft calls (in step 7, via the definition of string_to_int, in + // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the + // first hash without checking that it corresponds to a number less than the + // group order, which will lead to a slight bias in the sample. + // + // TODO(alx): We could save a bit of gas by following the standard here and + // using the compressed representation of the points, if we collated the y + // parities into a single bytes32. + // https://www.pivotaltracker.com/story/show/171120588 + function _scalarFromCurvePoints( + uint256[2] memory hash, + uint256[2] memory pk, + uint256[2] memory gamma, + address uWitness, + uint256[2] memory v + ) internal pure returns (uint256 s) { + return uint256(keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); + } + + // True if (gamma, c, s) is a correctly constructed randomness proof from pk + // and seed. zInv must be the inverse of the third ordinate from + // _projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to + // section 5.3 of the IETF draft. + // + // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass + // the x ordinate, and the parity of the y ordinate in the top bit of uWitness + // (which I could make a uint256 without using any extra space.) Would save + // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 + function _verifyVRFProof( + uint256[2] memory pk, + uint256[2] memory gamma, + uint256 c, + uint256 s, + uint256 seed, + address uWitness, + uint256[2] memory cGammaWitness, + uint256[2] memory sHashWitness, + uint256 zInv + ) internal view { + unchecked { + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(pk), "public key is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(gamma), "gamma is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); + // solhint-disable-next-line gas-custom-errors + require(_isOnCurve(sHashWitness), "sHashWitness is not on curve"); + // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here + // we use the address of u instead of u itself. Also, here we add the + // terms instead of taking the difference, and in the proof construction in + // vrf.GenerateProof, we correspondingly take the difference instead of + // taking the sum as they do in step 7 of section 5.1.) + // solhint-disable-next-line gas-custom-errors + require(_verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)!=_uWitness"); + // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) + uint256[2] memory hash = _hashToCurve(pk, seed); + // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms + uint256[2] memory v = _linearCombination(c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); + // Steps 7. and 8. of IETF draft section 5.3 + uint256 derivedC = _scalarFromCurvePoints(hash, pk, gamma, uWitness, v); + // solhint-disable-next-line gas-custom-errors + require(c == derivedC, "invalid proof"); + } + } + + // Domain-separation tag for the hash used as the final VRF output. + // Corresponds to vrfRandomOutputHashPrefix in vrf.go + uint256 internal constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; + + struct Proof { + uint256[2] pk; + uint256[2] gamma; + uint256 c; + uint256 s; + uint256 seed; + address uWitness; + uint256[2] cGammaWitness; + uint256[2] sHashWitness; + uint256 zInv; + } + + /* *************************************************************************** + * @notice Returns proof's output, if proof is valid. Otherwise reverts + + * @param proof vrf proof components + * @param seed seed used to generate the vrf output + * + * Throws if proof is invalid, otherwise: + * @return output i.e., the random output implied by the proof + * *************************************************************************** + */ + function _randomValueFromVRFProof(Proof memory proof, uint256 seed) internal view returns (uint256 output) { + _verifyVRFProof( + proof.pk, + proof.gamma, + proof.c, + proof.s, + seed, + proof.uWitness, + proof.cGammaWitness, + proof.sHashWitness, + proof.zInv + ); + output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, proof.gamma))); + return output; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol new file mode 100644 index 0000000..d142f50 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +/// @notice This contract is used for testing only and should not be used for production. +contract VRFV2PlusConsumerExample is ConfirmedOwner, VRFConsumerBaseV2Plus { + LinkTokenInterface public s_linkToken; + uint256 public s_recentRequestId; + IVRFCoordinatorV2Plus public s_vrfCoordinatorApiV1; + uint256 public s_subId; + + struct Response { + bool fulfilled; + address requester; + uint256 requestId; + uint256[] randomWords; + } + mapping(uint256 /* request id */ => Response /* response */) public s_requests; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + s_vrfCoordinatorApiV1 = IVRFCoordinatorV2Plus(vrfCoordinator); + s_linkToken = LinkTokenInterface(link); + } + + function getRandomness(uint256 requestId, uint256 idx) public view returns (uint256 randomWord) { + Response memory resp = s_requests[requestId]; + // solhint-disable-next-line gas-custom-errors + require(resp.requestId != 0, "request ID is incorrect"); + return resp.randomWords[idx]; + } + + function _subscribe() internal returns (uint256) { + if (s_subId == 0) { + s_subId = s_vrfCoordinatorApiV1.createSubscription(); + s_vrfCoordinatorApiV1.addConsumer(s_subId, address(this)); + } + return s_subId; + } + + function createSubscriptionAndFundNative() external payable { + _subscribe(); + s_vrfCoordinatorApiV1.fundSubscriptionWithNative{value: msg.value}(s_subId); + } + + function createSubscriptionAndFund(uint96 amount) external { + _subscribe(); + // Approve the link transfer. + s_linkToken.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "sub not set"); + s_linkToken.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); + } + + function topUpSubscriptionNative() external payable { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "sub not set"); + s_vrfCoordinatorApiV1.fundSubscriptionWithNative{value: msg.value}(s_subId); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(requestId == s_recentRequestId, "request ID is incorrect"); + s_requests[requestId].randomWords = randomWords; + s_requests[requestId].fulfilled = true; + } + + function requestRandomWords( + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash, + bool nativePayment + ) external { + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: s_subId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) + }); + uint256 requestId = s_vrfCoordinator.requestRandomWords(req); + Response memory resp = Response({ + requestId: requestId, + randomWords: new uint256[](0), + fulfilled: false, + requester: msg.sender + }); + s_requests[requestId] = resp; + s_recentRequestId = requestId; + } + + function updateSubscription(address[] memory consumers) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + s_vrfCoordinatorApiV1.addConsumer(s_subId, consumers[i]); + } + } + + function setSubId(uint256 subId) external { + s_subId = subId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol new file mode 100644 index 0000000..8eb2261 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +/// @notice This contract is used for testing only and should not be used for production. +contract VRFV2PlusExternalSubOwnerExample is VRFConsumerBaseV2Plus { + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + LinkTokenInterface internal LINKTOKEN; + + uint256[] public s_randomWords; + uint256 public s_requestId; + address internal s_owner; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + LINKTOKEN = LinkTokenInterface(link); + s_owner = msg.sender; + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(requestId == s_requestId, "request ID is incorrect"); + s_randomWords = randomWords; + } + + function requestRandomWords( + uint256 subId, + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash, + bool nativePayment + ) external onlyOwner { + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: subId, + requestConfirmations: requestConfirmations, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) + }); + // Will revert if subscription is not funded. + s_requestId = s_vrfCoordinator.requestRandomWords(req); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol new file mode 100644 index 0000000..87e70f6 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +/** + * @title The VRFLoadTestExternalSubOwner contract. + * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. + */ +contract VRFV2PlusLoadTestWithMetrics is VRFConsumerBaseV2Plus { + uint256 public s_responseCount; + uint256 public s_requestCount; + uint256 public s_averageResponseTimeInBlocksMillions = 0; // in millions for better precision + uint256 public s_slowestResponseTimeInBlocks = 0; + uint256 public s_fastestResponseTimeInBlocks = 999; + uint256 public s_slowestResponseTimeInSeconds = 0; + uint256 public s_fastestResponseTimeInSeconds = 999; + uint256 public s_averageResponseTimeInSecondsMillions = 0; + + uint256 public s_lastRequestId; + + uint32[] public s_requestBlockTimes; + + struct RequestStatus { + bool fulfilled; + uint256[] randomWords; + uint256 requestTimestamp; + uint256 fulfilmentTimestamp; + uint256 requestBlockNumber; + uint256 fulfilmentBlockNumber; + } + + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor(address _vrfCoordinator) VRFConsumerBaseV2Plus(_vrfCoordinator) {} + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override { + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + s_requests[_requestId].fulfilmentTimestamp = block.timestamp; + s_requests[_requestId].fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); + + uint256 responseTimeInBlocks = s_requests[_requestId].fulfilmentBlockNumber - + s_requests[_requestId].requestBlockNumber; + uint256 responseTimeInSeconds = s_requests[_requestId].fulfilmentTimestamp - + s_requests[_requestId].requestTimestamp; + + ( + s_slowestResponseTimeInBlocks, + s_fastestResponseTimeInBlocks, + s_averageResponseTimeInBlocksMillions + ) = _calculateMetrics( + responseTimeInBlocks, + s_fastestResponseTimeInBlocks, + s_slowestResponseTimeInBlocks, + s_averageResponseTimeInBlocksMillions, + s_responseCount + ); + ( + s_slowestResponseTimeInSeconds, + s_fastestResponseTimeInSeconds, + s_averageResponseTimeInSecondsMillions + ) = _calculateMetrics( + responseTimeInSeconds, + s_fastestResponseTimeInSeconds, + s_slowestResponseTimeInSeconds, + s_averageResponseTimeInSecondsMillions, + s_responseCount + ); + + s_responseCount++; + + s_requestBlockTimes.push(uint32(responseTimeInBlocks)); + } + + function requestRandomWords( + uint256 _subId, + uint16 _requestConfirmations, + bytes32 _keyHash, + uint32 _callbackGasLimit, + bool _nativePayment, + uint32 _numWords, + uint16 _requestCount + ) external { + for (uint16 i = 0; i < _requestCount; i++) { + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: _keyHash, + subId: _subId, + requestConfirmations: _requestConfirmations, + callbackGasLimit: _callbackGasLimit, + numWords: _numWords, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: _nativePayment})) + }); + // Will revert if subscription is not funded. + uint256 requestId = s_vrfCoordinator.requestRandomWords(req); + + s_lastRequestId = requestId; + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + s_requests[requestId] = RequestStatus({ + randomWords: new uint256[](0), + fulfilled: false, + requestTimestamp: block.timestamp, + fulfilmentTimestamp: 0, + requestBlockNumber: requestBlockNumber, + fulfilmentBlockNumber: 0 + }); + s_requestCount++; + } + } + + function reset() external { + s_averageResponseTimeInBlocksMillions = 0; // in millions for better precision + s_slowestResponseTimeInBlocks = 0; + s_fastestResponseTimeInBlocks = 999; + s_averageResponseTimeInSecondsMillions = 0; // in millions for better precision + s_slowestResponseTimeInSeconds = 0; + s_fastestResponseTimeInSeconds = 999; + s_requestCount = 0; + s_responseCount = 0; + delete s_requestBlockTimes; + } + + function getRequestStatus( + uint256 _requestId + ) + external + view + returns ( + bool fulfilled, + uint256[] memory randomWords, + uint256 requestTimestamp, + uint256 fulfilmentTimestamp, + uint256 requestBlockNumber, + uint256 fulfilmentBlockNumber + ) + { + RequestStatus memory request = s_requests[_requestId]; + return ( + request.fulfilled, + request.randomWords, + request.requestTimestamp, + request.fulfilmentTimestamp, + request.requestBlockNumber, + request.fulfilmentBlockNumber + ); + } + + function _calculateMetrics( + uint256 _responseTime, + uint256 _fastestResponseTime, + uint256 _slowestResponseTime, + uint256 _averageInMillions, + uint256 _responseCount + ) internal pure returns (uint256 slowest, uint256 fastest, uint256 average) { + uint256 _requestDelayInMillions = _responseTime * 1_000_000; + if (_responseTime > _slowestResponseTime) { + _slowestResponseTime = _responseTime; + } + _fastestResponseTime = _responseTime < _fastestResponseTime ? _responseTime : _fastestResponseTime; + uint256 averageInMillions = _responseCount > 0 + ? (_averageInMillions * _responseCount + _requestDelayInMillions) / (_responseCount + 1) + : _requestDelayInMillions; + + return (_slowestResponseTime, _fastestResponseTime, averageInMillions); + } + + function getRequestBlockTimes(uint256 offset, uint256 quantity) external view returns (uint32[] memory) { + uint256 end = offset + quantity; + if (end > s_requestBlockTimes.length) { + end = s_requestBlockTimes.length; + } + + uint32[] memory blockTimes = new uint32[](end - offset); + for (uint256 i = offset; i < end; i++) { + blockTimes[i - offset] = s_requestBlockTimes[i]; + } + + return blockTimes; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol new file mode 100644 index 0000000..16797bb --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import {IVRFMigratableConsumerV2Plus} from "../interfaces/IVRFMigratableConsumerV2Plus.sol"; +import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +contract VRFV2PlusMaliciousMigrator is IVRFMigratableConsumerV2Plus { + IVRFCoordinatorV2Plus internal s_vrfCoordinator; + + constructor(address _vrfCoordinator) { + s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); + } + + /** + * @inheritdoc IVRFMigratableConsumerV2Plus + */ + function setCoordinator(address /* _vrfCoordinator */) public override { + // try to re-enter, should revert + // args don't really matter + s_vrfCoordinator.requestRandomWords( + VRFV2PlusClient.RandomWordsRequest({ + keyHash: bytes32(0), + subId: 0, + requestConfirmations: 0, + callbackGasLimit: 0, + numWords: 0, + extraArgs: "" + }) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol new file mode 100644 index 0000000..e52369b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +// VRFV2RevertingExample will always revert. Used for testing only, useless in prod. +contract VRFV2PlusRevertingExample is VRFConsumerBaseV2Plus { + uint256[] public s_randomWords; + uint256 public s_requestId; + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + LinkTokenInterface internal LINKTOKEN; + uint256 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + LINKTOKEN = LinkTokenInterface(link); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256, uint256[] calldata) internal pure override { + // solhint-disable-next-line gas-custom-errors, reason-string + revert(); + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = s_vrfCoordinator.createSubscription(); + s_vrfCoordinator.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + s_vrfCoordinator.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness( + bytes32 keyHash, + uint256 subId, + uint16 minReqConfs, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256) { + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: keyHash, + subId: subId, + requestConfirmations: minReqConfs, + callbackGasLimit: callbackGasLimit, + numWords: numWords, + extraArgs: "" // empty extraArgs defaults to link payment + }); + s_requestId = s_vrfCoordinator.requestRandomWords(req); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol new file mode 100644 index 0000000..2ae45db --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: MIT +// Example of a single consumer contract which owns the subscription. +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +/// @notice This contract is used for testing only and should not be used for production. +contract VRFV2PlusSingleConsumerExample is VRFConsumerBaseV2Plus { + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + LinkTokenInterface internal LINKTOKEN; + + // solhint-disable-next-line gas-struct-packing + struct RequestConfig { + uint256 subId; + uint32 callbackGasLimit; + uint16 requestConfirmations; + uint32 numWords; + bytes32 keyHash; + bool nativePayment; + } + RequestConfig public s_requestConfig; + uint256[] public s_randomWords; + uint256 public s_requestId; + address internal s_owner; + + constructor( + address vrfCoordinator, + address link, + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash, + bool nativePayment + ) VRFConsumerBaseV2Plus(vrfCoordinator) { + LINKTOKEN = LinkTokenInterface(link); + s_owner = msg.sender; + s_requestConfig = RequestConfig({ + subId: 0, // Unset initially + callbackGasLimit: callbackGasLimit, + requestConfirmations: requestConfirmations, + numWords: numWords, + keyHash: keyHash, + nativePayment: nativePayment + }); + subscribe(); + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(requestId == s_requestId, "request ID is incorrect"); + s_randomWords = randomWords; + } + + // Assumes the subscription is funded sufficiently. + function requestRandomWords() external onlyOwner { + RequestConfig memory rc = s_requestConfig; + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: rc.keyHash, + subId: rc.subId, + requestConfirmations: rc.requestConfirmations, + callbackGasLimit: rc.callbackGasLimit, + numWords: rc.numWords, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: rc.nativePayment})) + }); + // Will revert if subscription is not set and funded. + s_requestId = s_vrfCoordinator.requestRandomWords(req); + } + + // Assumes this contract owns link + // This method is analogous to VRFv1, except the amount + // should be selected based on the keyHash (each keyHash functions like a "gas lane" + // with different link costs). + function fundAndRequestRandomWords(uint256 amount) external onlyOwner { + RequestConfig memory rc = s_requestConfig; + LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_requestConfig.subId)); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: rc.keyHash, + subId: rc.subId, + requestConfirmations: rc.requestConfirmations, + callbackGasLimit: rc.callbackGasLimit, + numWords: rc.numWords, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: rc.nativePayment})) + }); + // Will revert if subscription is not set and funded. + s_requestId = s_vrfCoordinator.requestRandomWords(req); + } + + // Assumes this contract owns link + function topUpSubscription(uint256 amount) external onlyOwner { + LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_requestConfig.subId)); + } + + function withdraw(uint256 amount, address to) external onlyOwner { + LINKTOKEN.transfer(to, amount); + } + + function unsubscribe(address to) external onlyOwner { + // Returns funds to this address + s_vrfCoordinator.cancelSubscription(s_requestConfig.subId, to); + s_requestConfig.subId = 0; + } + + // Keep this separate in case the contract want to unsubscribe and then + // resubscribe. + function subscribe() public onlyOwner { + // Create a subscription, current subId + address[] memory consumers = new address[](1); + consumers[0] = address(this); + s_requestConfig.subId = s_vrfCoordinator.createSubscription(); + s_vrfCoordinator.addConsumer(s_requestConfig.subId, consumers[0]); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol new file mode 100644 index 0000000..9510b1b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2PlusWrapperConsumerBase} from "../VRFV2PlusWrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +contract VRFV2PlusWrapperConsumerExample is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { + event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); + event WrapperRequestMade(uint256 indexed requestId, uint256 paid); + + // solhint-disable-next-line gas-struct-packing + struct RequestStatus { + uint256 paid; + bool fulfilled; + uint256[] randomWords; + bool native; + } + + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor(address _vrfV2Wrapper) ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(_vrfV2Wrapper) {} + + function makeRequest( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) external onlyOwner returns (uint256 requestId) { + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); + uint256 paid; + (requestId, paid) = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs); + s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: false}); + emit WrapperRequestMade(requestId, paid); + return requestId; + } + + function makeRequestNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) external onlyOwner returns (uint256 requestId) { + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); + uint256 paid; + (requestId, paid) = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs); + s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: true}); + emit WrapperRequestMade(requestId, paid); + return requestId; + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); + } + + function getRequestStatus( + uint256 _requestId + ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + RequestStatus memory request = s_requests[_requestId]; + return (request.paid, request.fulfilled, request.randomWords); + } + + /// @notice withdrawLink withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in juels + function withdrawLink(uint256 amount) external onlyOwner { + i_linkToken.transfer(owner(), amount); + } + + /// @notice withdrawNative withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in wei + function withdrawNative(uint256 amount) external onlyOwner { + (bool success, ) = payable(owner()).call{value: amount}(""); + // solhint-disable-next-line gas-custom-errors + require(success, "withdrawNative failed"); + } + + event Received(address, uint256); + + receive() external payable { + emit Received(msg.sender, msg.value); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol new file mode 100644 index 0000000..6935723 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2PlusWrapperConsumerBase} from "../VRFV2PlusWrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; +import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; + +contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { + uint256 public s_responseCount; + uint256 public s_requestCount; + uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision + uint256 public s_slowestFulfillment = 0; + uint256 public s_fastestFulfillment = 999; + uint256 public s_lastRequestId; + uint32[] public s_requestBlockTimes; + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made + + event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); + event WrapperRequestMade(uint256 indexed requestId, uint256 paid); + + // solhint-disable-next-line gas-struct-packing + struct RequestStatus { + uint256 paid; + bool fulfilled; + uint256[] randomWords; + uint256 requestTimestamp; + uint256 fulfilmentTimestamp; + uint256 requestBlockNumber; + uint256 fulfilmentBlockNumber; + bool native; + } + + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor(address _vrfV2PlusWrapper) ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(_vrfV2PlusWrapper) {} + + function makeRequests( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + uint16 _requestCount + ) external { + for (uint16 i = 0; i < _requestCount; i++) { + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); + (uint256 requestId, uint256 paid) = requestRandomness( + _callbackGasLimit, + _requestConfirmations, + _numWords, + extraArgs + ); + s_lastRequestId = requestId; + + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + s_requests[requestId] = RequestStatus({ + paid: paid, + fulfilled: false, + randomWords: new uint256[](0), + requestTimestamp: block.timestamp, + requestBlockNumber: requestBlockNumber, + fulfilmentTimestamp: 0, + fulfilmentBlockNumber: 0, + native: false + }); + s_requestCount++; + requestHeights[requestId] = requestBlockNumber; + emit WrapperRequestMade(requestId, paid); + } + } + + function makeRequestsNative( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + uint16 _requestCount + ) external { + for (uint16 i = 0; i < _requestCount; i++) { + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); + (uint256 requestId, uint256 paid) = requestRandomnessPayInNative( + _callbackGasLimit, + _requestConfirmations, + _numWords, + extraArgs + ); + s_lastRequestId = requestId; + + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + s_requests[requestId] = RequestStatus({ + paid: paid, + fulfilled: false, + randomWords: new uint256[](0), + requestTimestamp: block.timestamp, + requestBlockNumber: requestBlockNumber, + fulfilmentTimestamp: 0, + fulfilmentBlockNumber: 0, + native: true + }); + s_requestCount++; + requestHeights[requestId] = requestBlockNumber; + emit WrapperRequestMade(requestId, paid); + } + } + + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); + uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; + uint256 requestDelayInMillions = requestDelay * 1_000_000; + + if (requestDelay > s_slowestFulfillment) { + s_slowestFulfillment = requestDelay; + } + s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; + s_averageFulfillmentInMillions = s_responseCount > 0 + ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) + : requestDelayInMillions; + + s_responseCount++; + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + s_requests[_requestId].fulfilmentTimestamp = block.timestamp; + s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; + + s_requestBlockTimes.push(uint32(requestDelay)); + + emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); + } + + function getRequestStatus( + uint256 _requestId + ) + external + view + returns ( + uint256 paid, + bool fulfilled, + uint256[] memory randomWords, + uint256 requestTimestamp, + uint256 fulfilmentTimestamp, + uint256 requestBlockNumber, + uint256 fulfilmentBlockNumber + ) + { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + RequestStatus memory request = s_requests[_requestId]; + return ( + request.paid, + request.fulfilled, + request.randomWords, + request.requestTimestamp, + request.fulfilmentTimestamp, + request.requestBlockNumber, + request.fulfilmentBlockNumber + ); + } + + function getRequestBlockTimes(uint256 offset, uint256 quantity) external view returns (uint32[] memory) { + uint256 end = offset + quantity; + if (end > s_requestBlockTimes.length) { + end = s_requestBlockTimes.length; + } + + uint32[] memory blockTimes = new uint32[](end - offset); + for (uint256 i = offset; i < end; i++) { + blockTimes[i - offset] = s_requestBlockTimes[i]; + } + + return blockTimes; + } + + function reset() external { + s_averageFulfillmentInMillions = 0; // in millions for better precision + s_slowestFulfillment = 0; + s_fastestFulfillment = 999; + s_requestCount = 0; + s_responseCount = 0; + delete s_requestBlockTimes; + } + + /// @notice withdrawLink withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in juels + function withdrawLink(uint256 amount) external onlyOwner { + i_linkToken.transfer(owner(), amount); + } + + /// @notice withdrawNative withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in wei + function withdrawNative(uint256 amount) external onlyOwner { + (bool success, ) = payable(owner()).call{value: amount}(""); + // solhint-disable-next-line gas-custom-errors + require(success, "withdrawNative failed"); + } + + receive() external payable {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol new file mode 100644 index 0000000..6a42b5b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface BlockhashStoreInterface { + function getBlockhash(uint256 number) external view returns (bytes32); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol new file mode 100644 index 0000000..78140d5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IAuthorizedReceiver { + function isAuthorizedSender(address sender) external view returns (bool); + + function getAuthorizedSenders() external returns (address[] memory); + + function setAuthorizedSenders(address[] calldata senders) external; +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol new file mode 100644 index 0000000..3cb9934 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface VRFCoordinatorV2Interface { + /** + * @notice Get configuration relevant for making requests + * @return minimumRequestConfirmations global min for request confirmations + * @return maxGasLimit global max for request gas limit + * @return s_provingKeyHashes list of registered key hashes + */ + function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory); + + /** + * @notice Request a set of random words. + * @param keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * @param subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * @param minimumRequestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * @param callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * @param numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + bytes32 keyHash, + uint64 subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256 requestId); + + /** + * @notice Create a VRF subscription. + * @return subId - A unique subscription id. + * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + * @dev Note to fund the subscription, use transferAndCall. For example + * @dev LINKTOKEN.transferAndCall( + * @dev address(COORDINATOR), + * @dev amount, + * @dev abi.encode(subId)); + */ + function createSubscription() external returns (uint64 subId); + + /** + * @notice Get a VRF subscription. + * @param subId - ID of the subscription + * @return balance - LINK balance of the subscription in juels. + * @return reqCount - number of requests for this subscription, determines fee tier. + * @return owner - owner of the subscription. + * @return consumers - list of consumer address which are able to use this subscription. + */ + function getSubscription( + uint64 subId + ) external view returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers); + + /** + * @notice Request subscription owner transfer. + * @param subId - ID of the subscription + * @param newOwner - proposed new owner of the subscription + */ + function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; + + /** + * @notice Request subscription owner transfer. + * @param subId - ID of the subscription + * @dev will revert if original owner of subId has + * not requested that msg.sender become the new owner. + */ + function acceptSubscriptionOwnerTransfer(uint64 subId) external; + + /** + * @notice Add a consumer to a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - New consumer which can use the subscription + */ + function addConsumer(uint64 subId, address consumer) external; + + /** + * @notice Remove a consumer from a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - Consumer to remove from the subscription + */ + function removeConsumer(uint64 subId, address consumer) external; + + /** + * @notice Cancel a subscription + * @param subId - ID of the subscription + * @param to - Where to send the remaining LINK to + */ + function cancelSubscription(uint64 subId, address to) external; + + /* + * @notice Check to see if there exists a request commitment consumers + * for all consumers and keyhashes for a given sub. + * @param subId - ID of the subscription + * @return true if there exists at least one unfulfilled request for the subscription, false + * otherwise. + */ + function pendingRequestExists(uint64 subId) external view returns (bool); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol new file mode 100644 index 0000000..daac158 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// solhint-disable-next-line interface-starts-with-i +interface VRFV2WrapperInterface { + /** + * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only + * be relied option within the same transaction that the request was made. + */ + function lastRequestId() external view returns (uint256); + + /** + * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current + * @notice block. + * + * @dev This function relies on the transaction gas price which is not automatically set during + * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + */ + function calculateRequestPrice(uint32 _callbackGasLimit) external view returns (uint256); + + /** + * @notice Estimates the price of a VRF request with a specific gas limit and gas price. + * + * @dev This is a convenience function that can be called in simulation to better understand + * @dev pricing. + * + * @param _callbackGasLimit is the gas limit used to estimate the price. + * @param _requestGasPriceWei is the gas price in wei used for the estimation. + */ + function estimateRequestPrice(uint32 _callbackGasLimit, uint256 _requestGasPriceWei) external view returns (uint256); +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol new file mode 100644 index 0000000..e192f74 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFConsumerBase} from "../../vrf/VRFConsumerBase.sol"; + +// solhint-disable gas-custom-errors + +contract VRFCoordinatorMock { + LinkTokenInterface public LINK; + + event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); + + constructor(address linkAddress) { + LINK = LinkTokenInterface(linkAddress); + } + + function onTokenTransfer(address sender, uint256 fee, bytes memory _data) public onlyLINK { + (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); + emit RandomnessRequest(sender, keyHash, seed, fee); + } + + function callBackWithRandomness(bytes32 requestId, uint256 randomness, address consumerContract) public { + VRFConsumerBase v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomness.selector, requestId, randomness); + uint256 b = 206000; + require(gasleft() >= b, "not enough gas for consumer"); + // solhint-disable-next-line avoid-low-level-calls, no-unused-vars + (bool success, ) = consumerContract.call(resp); + } + + modifier onlyLINK() { + require(msg.sender == address(LINK), "Must use LINK token"); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol new file mode 100644 index 0000000..9617b76 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: MIT +// A mock for testing code that relies on VRFCoordinatorV2. +pragma solidity ^0.8.4; + +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +// solhint-disable chainlink-solidity/prefix-immutable-variables-with-i +// solhint-disable gas-custom-errors +// solhint-disable avoid-low-level-calls + +contract VRFCoordinatorV2Mock is VRFCoordinatorV2Interface, ConfirmedOwner { + uint96 public immutable BASE_FEE; + uint96 public immutable GAS_PRICE_LINK; + uint16 public immutable MAX_CONSUMERS = 100; + + error InvalidSubscription(); + error InsufficientBalance(); + error MustBeSubOwner(address owner); + error TooManyConsumers(); + error InvalidConsumer(); + error InvalidRandomWords(); + error Reentrant(); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint64 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); + event SubscriptionCreated(uint64 indexed subId, address owner); + event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); + event ConsumerAdded(uint64 indexed subId, address consumer); + event ConsumerRemoved(uint64 indexed subId, address consumer); + event ConfigSet(); + + struct Config { + // Reentrancy protection. + bool reentrancyLock; + } + Config private s_config; + uint64 internal s_currentSubId; + uint256 internal s_nextRequestId = 1; + uint256 internal s_nextPreSeed = 100; + struct Subscription { + address owner; + uint96 balance; + } + mapping(uint64 => Subscription) internal s_subscriptions; /* subId */ /* subscription */ + mapping(uint64 => address[]) internal s_consumers; /* subId */ /* consumers */ + + struct Request { + uint64 subId; + uint32 callbackGasLimit; + uint32 numWords; + } + mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ + + constructor(uint96 _baseFee, uint96 _gasPriceLink) ConfirmedOwner(msg.sender) { + BASE_FEE = _baseFee; + GAS_PRICE_LINK = _gasPriceLink; + setConfig(); + } + + /** + * @notice Sets the configuration of the vrfv2 mock coordinator + */ + function setConfig() public onlyOwner { + s_config = Config({reentrancyLock: false}); + emit ConfigSet(); + } + + function consumerIsAdded(uint64 _subId, address _consumer) public view returns (bool) { + address[] memory consumers = s_consumers[_subId]; + for (uint256 i = 0; i < consumers.length; i++) { + if (consumers[i] == _consumer) { + return true; + } + } + return false; + } + + modifier onlyValidConsumer(uint64 _subId, address _consumer) { + if (!consumerIsAdded(_subId, _consumer)) { + revert InvalidConsumer(); + } + _; + } + + /** + * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied + * @notice consumer. + * + * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does + * @dev not account for all edge cases handled in the real VRF coordinator. When making requests + * @dev against the real coordinator a small amount of additional LINK is required. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + */ + function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { + fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); + } + + /** + * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + * @param _words user-provided random words + */ + function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { + uint256 startGas = gasleft(); + if (s_requests[_requestId].subId == 0) { + revert("nonexistent request"); + } + Request memory req = s_requests[_requestId]; + + if (_words.length == 0) { + _words = new uint256[](req.numWords); + for (uint256 i = 0; i < req.numWords; i++) { + _words[i] = uint256(keccak256(abi.encode(_requestId, i))); + } + } else if (_words.length != req.numWords) { + revert InvalidRandomWords(); + } + + VRFConsumerBaseV2 v; + bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); + s_config.reentrancyLock = true; + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); + s_config.reentrancyLock = false; + + uint96 payment = uint96(BASE_FEE + ((startGas - gasleft()) * GAS_PRICE_LINK)); + if (s_subscriptions[req.subId].balance < payment) { + revert InsufficientBalance(); + } + s_subscriptions[req.subId].balance -= payment; + delete (s_requests[_requestId]); + emit RandomWordsFulfilled(_requestId, _requestId, payment, success); + } + + /** + * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. + * + * @param _subId the subscription to fund + * @param _amount the amount to fund + */ + function fundSubscription(uint64 _subId, uint96 _amount) public { + if (s_subscriptions[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + uint96 oldBalance = s_subscriptions[_subId].balance; + s_subscriptions[_subId].balance += _amount; + emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); + } + + function requestRandomWords( + bytes32 _keyHash, + uint64 _subId, + uint16 _minimumRequestConfirmations, + uint32 _callbackGasLimit, + uint32 _numWords + ) external override nonReentrant onlyValidConsumer(_subId, msg.sender) returns (uint256) { + if (s_subscriptions[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + + uint256 requestId = s_nextRequestId++; + uint256 preSeed = s_nextPreSeed++; + + s_requests[requestId] = Request({subId: _subId, callbackGasLimit: _callbackGasLimit, numWords: _numWords}); + + emit RandomWordsRequested( + _keyHash, + requestId, + preSeed, + _subId, + _minimumRequestConfirmations, + _callbackGasLimit, + _numWords, + msg.sender + ); + return requestId; + } + + function createSubscription() external override returns (uint64 _subId) { + s_currentSubId++; + s_subscriptions[s_currentSubId] = Subscription({owner: msg.sender, balance: 0}); + emit SubscriptionCreated(s_currentSubId, msg.sender); + return s_currentSubId; + } + + function getSubscription( + uint64 _subId + ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { + if (s_subscriptions[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + return (s_subscriptions[_subId].balance, 0, s_subscriptions[_subId].owner, s_consumers[_subId]); + } + + function cancelSubscription(uint64 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { + emit SubscriptionCanceled(_subId, _to, s_subscriptions[_subId].balance); + delete (s_subscriptions[_subId]); + } + + modifier onlySubOwner(uint64 _subId) { + address owner = s_subscriptions[_subId].owner; + if (owner == address(0)) { + revert InvalidSubscription(); + } + if (msg.sender != owner) { + revert MustBeSubOwner(owner); + } + _; + } + + function getRequestConfig() external pure override returns (uint16, uint32, bytes32[] memory) { + return (3, 2000000, new bytes32[](0)); + } + + function addConsumer(uint64 _subId, address _consumer) external override onlySubOwner(_subId) { + if (s_consumers[_subId].length == MAX_CONSUMERS) { + revert TooManyConsumers(); + } + + if (consumerIsAdded(_subId, _consumer)) { + return; + } + + s_consumers[_subId].push(_consumer); + emit ConsumerAdded(_subId, _consumer); + } + + function removeConsumer( + uint64 _subId, + address _consumer + ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { + address[] storage consumers = s_consumers[_subId]; + for (uint256 i = 0; i < consumers.length; i++) { + if (consumers[i] == _consumer) { + address last = consumers[consumers.length - 1]; + consumers[i] = last; + consumers.pop(); + break; + } + } + + emit ConsumerRemoved(_subId, _consumer); + } + + function getConfig() + external + pure + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ) + { + return (4, 2_500_000, 2_700, 33285); + } + + function getFeeConfig() + external + pure + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ) + { + return ( + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 100000, // 0.1 LINK + 0, + 0, + 0, + 0 + ); + } + + modifier nonReentrant() { + if (s_config.reentrancyLock) { + revert Reentrant(); + } + _; + } + + function getFallbackWeiPerUnitLink() external pure returns (int256) { + return 4000000000000000; // 0.004 Ether + } + + function requestSubscriptionOwnerTransfer(uint64 /*_subId*/, address /*_newOwner*/) external pure override { + revert("not implemented"); + } + + function acceptSubscriptionOwnerTransfer(uint64 /*_subId*/) external pure override { + revert("not implemented"); + } + + function pendingRequestExists(uint64 /*subId*/) public pure override returns (bool) { + revert("not implemented"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol new file mode 100644 index 0000000..823cd43 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: MIT +// A mock for testing code that relies on VRFCoordinatorV2_5. +pragma solidity ^0.8.19; + +// solhint-disable-next-line no-unused-import +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; + +contract VRFCoordinatorV2_5Mock is SubscriptionAPI, IVRFCoordinatorV2Plus { + uint96 public immutable i_base_fee; + uint96 public immutable i_gas_price; + int256 public immutable i_wei_per_unit_link; + + error InvalidRequest(); + error InvalidRandomWords(); + error InvalidExtraArgsTag(); + error NotImplemented(); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + event ConfigSet(); + + uint64 internal s_currentSubId; + uint256 internal s_nextRequestId = 1; + uint256 internal s_nextPreSeed = 100; + + struct Request { + uint256 subId; + uint32 callbackGasLimit; + uint32 numWords; + bytes extraArgs; + } + mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ + + constructor(uint96 _baseFee, uint96 _gasPrice, int256 _weiPerUnitLink) SubscriptionAPI() { + i_base_fee = _baseFee; + i_gas_price = _gasPrice; + i_wei_per_unit_link = _weiPerUnitLink; + setConfig(); + } + + /** + * @notice Sets the configuration of the vrfv2 mock coordinator + */ + function setConfig() public onlyOwner { + s_config = Config({ + minimumRequestConfirmations: 0, + maxGasLimit: 0, + stalenessSeconds: 0, + gasAfterPaymentCalculation: 0, + reentrancyLock: false, + fulfillmentFlatFeeNativePPM: 0, + fulfillmentFlatFeeLinkDiscountPPM: 0, + nativePremiumPercentage: 0, + linkPremiumPercentage: 0 + }); + emit ConfigSet(); + } + + function consumerIsAdded(uint256 _subId, address _consumer) public view returns (bool) { + return s_consumers[_consumer][_subId].active; + } + + modifier onlyValidConsumer(uint256 _subId, address _consumer) { + if (!consumerIsAdded(_subId, _consumer)) { + revert InvalidConsumer(_subId, _consumer); + } + _; + } + + /** + * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied + * @notice consumer. + * + * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does + * @dev not account for all edge cases handled in the real VRF coordinator. When making requests + * @dev against the real coordinator a small amount of additional LINK is required. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + */ + function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { + fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); + } + + /** + * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. + * + * @param _requestId the request to fulfill + * @param _consumer the VRF randomness consumer to send the result to + * @param _words user-provided random words + */ + function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { + uint256 startGas = gasleft(); + if (s_requests[_requestId].subId == 0) { + revert InvalidRequest(); + } + Request memory req = s_requests[_requestId]; + + if (_words.length == 0) { + _words = new uint256[](req.numWords); + for (uint256 i = 0; i < req.numWords; i++) { + _words[i] = uint256(keccak256(abi.encode(_requestId, i))); + } + } else if (_words.length != req.numWords) { + revert InvalidRandomWords(); + } + + VRFConsumerBaseV2Plus v; + bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); + s_config.reentrancyLock = true; + // solhint-disable-next-line avoid-low-level-calls, no-unused-vars + (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); + s_config.reentrancyLock = false; + + bool nativePayment = uint8(req.extraArgs[req.extraArgs.length - 1]) == 1; + + uint256 rawPayment = i_base_fee + ((startGas - gasleft()) * i_gas_price); + if (!nativePayment) { + rawPayment = (1e18 * rawPayment) / uint256(i_wei_per_unit_link); + } + uint96 payment = uint96(rawPayment); + + _chargePayment(payment, nativePayment, req.subId); + + delete (s_requests[_requestId]); + emit RandomWordsFulfilled(_requestId, _requestId, req.subId, payment, nativePayment, success, false); + } + + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; + } + } + + /** + * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. + * + * @param _subId the subscription to fund + * @param _amount the amount to fund + */ + function fundSubscription(uint256 _subId, uint256 _amount) public { + if (s_subscriptionConfigs[_subId].owner == address(0)) { + revert InvalidSubscription(); + } + uint256 oldBalance = s_subscriptions[_subId].balance; + s_subscriptions[_subId].balance += uint96(_amount); + s_totalBalance += uint96(_amount); + emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @return The extra args struct + function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { + if (extraArgs.length == 0) { + return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); + } + if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); + } + + function requestRandomWords( + VRFV2PlusClient.RandomWordsRequest calldata _req + ) external override nonReentrant onlyValidConsumer(_req.subId, msg.sender) returns (uint256) { + uint256 subId = _req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + + uint256 requestId = s_nextRequestId++; + uint256 preSeed = s_nextPreSeed++; + + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(_req.extraArgs)); + s_requests[requestId] = Request({ + subId: _req.subId, + callbackGasLimit: _req.callbackGasLimit, + numWords: _req.numWords, + extraArgs: _req.extraArgs + }); + + emit RandomWordsRequested( + _req.keyHash, + requestId, + preSeed, + _req.subId, + _req.requestConfirmations, + _req.callbackGasLimit, + _req.numWords, + extraArgsBytes, + msg.sender + ); + return requestId; + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function removeConsumer( + uint256 _subId, + address _consumer + ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { + if (!s_consumers[_consumer][_subId].active) { + revert InvalidConsumer(_subId, _consumer); + } + address[] memory consumers = s_subscriptionConfigs[_subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; ++i) { + if (consumers[i] == _consumer) { + address last = consumers[lastConsumerIndex]; + s_subscriptionConfigs[_subId].consumers[i] = last; + s_subscriptionConfigs[_subId].consumers.pop(); + break; + } + } + s_consumers[_consumer][_subId].active = false; + emit SubscriptionConsumerRemoved(_subId, _consumer); + } + + /** + * @inheritdoc IVRFSubscriptionV2Plus + */ + function cancelSubscription(uint256 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { + (uint96 balance, uint96 nativeBalance) = _deleteSubscription(_subId); + + (bool success, ) = _to.call{value: uint256(nativeBalance)}(""); + if (!success) { + revert FailedToSendNative(); + } + emit SubscriptionCanceled(_subId, _to, balance, nativeBalance); + } + + function pendingRequestExists(uint256 /*subId*/) public pure override returns (bool) { + revert NotImplemented(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol new file mode 100644 index 0000000..1ae2869 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol @@ -0,0 +1,34 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + // Set msg.sender to OWNER until changePrank or stopPrank is called + vm.startPrank(OWNER); + } + + function getRandomAddresses(uint256 length) internal returns (address[] memory) { + address[] memory addresses = new address[](length); + for (uint256 i = 0; i < length; ++i) { + addresses[i] = address(uint160(uint(keccak256(abi.encodePacked(i))))); + } + return addresses; + } + + function addressIsIn(address addr, address[] memory addresses) internal returns (bool) { + for (uint256 i = 0; i < addresses.length; ++i) { + if (addresses[i] == addr) { + return true; + } + } + return false; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol new file mode 100644 index 0000000..4197073 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol @@ -0,0 +1,196 @@ +pragma solidity 0.8.19; + +import {console} from "forge-std/console.sol"; +import {VRF} from "../VRF.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {BatchVRFCoordinatorV2Plus} from "../dev/BatchVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import "./BaseTest.t.sol"; +import {FixtureVRFCoordinatorV2_5} from "./FixtureVRFCoordinatorV2_5.t.sol"; + +contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { + BatchVRFCoordinatorV2Plus private s_batchCoordinator; + + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + function setUp() public override { + FixtureVRFCoordinatorV2_5.setUp(); + + s_batchCoordinator = new BatchVRFCoordinatorV2Plus(address(s_coordinator)); + } + + function test_fulfillRandomWords() public { + _setUpConfig(); + _setUpProvingKey(); + _setUpSubscription(); + + uint32 requestBlock = 10; + vm.roll(requestBlock); + + vm.startPrank(SUBSCRIPTION_OWNER); + vm.deal(SUBSCRIPTION_OWNER, 10 ether); + s_coordinator.fundSubscriptionWithNative{value: 10 ether}(s_subId); + + // Request random words. + s_consumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, true); + vm.stopPrank(); + + // Move on to the next block. + // Store the previous block's blockhash. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); + + VRFTypes.Proof[] memory proofs = new VRFTypes.Proof[](2); + VRFTypes.RequestCommitmentV2Plus[] memory rcs = new VRFTypes.RequestCommitmentV2Plus[](2); + + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. + // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 4430852740828987645228960511496023658059009607317025880962658187812299131155 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ + -block-num 10 \ + -sender 0xdc90e8ce61c1af8a638b95264037c8e67ee5765c \ + -native-payment true + + */ + proofs[0] = VRFTypes.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 26762213923453052192184693334574145607290366984305044804336172347176490943606, + 70503534560525619072578237689732581746976650376431765635714023643649039207077 + ], + c: 10992233996918874905152274435276937088064589467016709044984819613170049539489, + s: 79662863379962724455809192044326025082567113176696761949197261107120333769102, + seed: 4430852740828987645228960511496023658059009607317025880962658187812299131155, + uWitness: 0x421A52Fb797d76Fb610aA1a0c020346fC1Ee2DeB, + cGammaWitness: [ + 50748523246052507241857300891945475679319243536065937584940024494820365165901, + 85746856994474260612851047426766648416105284284185975301552792881940939754570 + ], + sHashWitness: [ + 78637275871978664522379716948105702461748200460627087255706483027519919611423, + 82219236913923465822780520561305604064850823877720616893986252854976640396959 + ], + zInv: 60547558497534848069125896511700272238016171243048151035528198622956754542730 + }); + rcs[0] = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: s_subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: 1, + sender: address(s_consumer), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + + VRFCoordinatorV2_5.Output memory output = s_coordinator.getRandomnessFromProofExternal( + abi.decode(abi.encode(proofs[0]), (VRF.Proof)), + rcs[0] + ); + + requestBlock = 20; + vm.roll(requestBlock); + + vm.startPrank(SUBSCRIPTION_OWNER); + s_linkToken.setBalance(address(SUBSCRIPTION_OWNER), 10 ether); + s_linkToken.transferAndCall(address(s_coordinator), 10 ether, abi.encode(s_subId)); + + // Request random words. + s_consumer1.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, false); + vm.stopPrank(); + + // Move on to the next block. + // Store the previous block's blockhash. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); + + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. + // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 14541556911652758131165474365357244907354309169650401973525070879190071151266 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ + -block-num 20 \ + -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ + -native-payment false + */ + proofs[1] = VRFTypes.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 97658842840420719674383370910135023062422561858595941631054490821636116883585, + 44255438468488339528368406358785988551798314198954634050943346751039644360856 + ], + c: 5233652943248967403606766735502925802264855214922758107203237169366748118852, + s: 87931642435666855739510477620068257005869145374865238974094299759068218698655, + seed: 14541556911652758131165474365357244907354309169650401973525070879190071151266, + uWitness: 0x0A87a9CB71983cE0F2C4bA41D0c1A6Fb1785c46A, + cGammaWitness: [ + 54062743217909816783918413821204010151082432359411822104552882037459289383418, + 67491004534731980264926765871774299056809003077448271411776926359153820235981 + ], + sHashWitness: [ + 7745933951617569731026754652291310837540252155195826133994719499558406927394, + 58405861596456412358325504621101233475720292237067230796670629212111423924259 + ], + zInv: 44253513765558903217330502897662324213800000485156126961643960636269885275795 + }); + rcs[1] = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: s_subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: 1, + sender: address(s_consumer1), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) + }); + + VRFCoordinatorV2_5.Output memory output1 = s_coordinator.getRandomnessFromProofExternal( + abi.decode(abi.encode(proofs[1]), (VRF.Proof)), + rcs[1] + ); + + // The payments are NOT pre-calculated and simply copied from the actual event. + // We can assert and ignore the payment field but the code will be considerably longer. + vm.expectEmit(true, true, false, true, address(s_coordinator)); + emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143261, true, true, false); + vm.expectEmit(true, true, false, true, address(s_coordinator)); + emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000312358, false, true, false); + + // Fulfill the requests. + s_batchCoordinator.fulfillRandomWords(proofs, rcs); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol new file mode 100644 index 0000000..efeb902 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol @@ -0,0 +1,196 @@ +pragma solidity 0.8.6; + +import "./BaseTest.t.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; + +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; + +contract ChainSpecificUtilTest is BaseTest { + // ------------ Start Arbitrum Constants ------------ + + /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); + + /// @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); + + uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; + uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; + uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; + + // ------------ 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 OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + uint256 private constant OP_MAINNET_CHAIN_ID = 10; + uint256 private constant OP_GOERLI_CHAIN_ID = 420; + uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; + + /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. + uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; + uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; + + // ------------ End Optimism Constants ------------ + + function setUp() public override { + BaseTest.setUp(); + vm.clearMockedCalls(); + } + + function testGetBlockhashArbitrum() public { + uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; + bytes32[3] memory expectedBlockHashes = [keccak256("mainnet"), keccak256("goerli"), keccak256("sepolia")]; + uint256[3] memory expectedBlockNumbers = [uint256(10), 11, 12]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + bytes32 expectedBlockHash = expectedBlockHashes[i]; + uint256 expectedBlockNumber = expectedBlockNumbers[i]; + vm.mockCall( + ARBSYS_ADDR, + abi.encodeWithSelector(ArbSys.arbBlockNumber.selector), + abi.encode(expectedBlockNumber + 1) + ); + vm.mockCall( + ARBSYS_ADDR, + abi.encodeWithSelector(ArbSys.arbBlockHash.selector, expectedBlockNumber), + abi.encodePacked(expectedBlockHash) + ); + bytes32 actualBlockHash = ChainSpecificUtil._getBlockhash(uint64(expectedBlockNumber)); + assertEq(expectedBlockHash, actualBlockHash, "incorrect blockhash"); + } + } + + function testGetBlockhashOptimism() public { + // Optimism L2 block hash is simply blockhash() + bytes32 actualBlockhash = ChainSpecificUtil._getBlockhash(uint64(block.number - 1)); + assertEq(blockhash(block.number - 1), actualBlockhash); + } + + function testGetBlockNumberArbitrum() public { + uint256[2] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID]; + uint256[3] memory expectedBlockNumbers = [uint256(10), 11, 12]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + uint256 expectedBlockNumber = expectedBlockNumbers[i]; + vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ArbSys.arbBlockNumber.selector), abi.encode(expectedBlockNumber)); + uint256 actualBlockNumber = ChainSpecificUtil._getBlockNumber(); + assertEq(expectedBlockNumber, actualBlockNumber, "incorrect block number"); + } + } + + function testGetBlockNumberOptimism() public { + // Optimism L2 block number is simply block.number + uint256 actualBlockNumber = ChainSpecificUtil._getBlockNumber(); + assertEq(block.number, actualBlockNumber); + } + + function testGetCurrentTxL1GasFeesArbitrum() public { + uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; + uint256[3] memory expectedGasFees = [uint256(10 gwei), 12 gwei, 14 gwei]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + uint256 expectedGasFee = expectedGasFees[i]; + vm.mockCall( + ARBGAS_ADDR, + abi.encodeWithSelector(ArbGasInfo.getCurrentTxL1GasFees.selector), + abi.encode(expectedGasFee) + ); + uint256 actualGasFee = ChainSpecificUtil._getCurrentTxL1GasFees(""); + assertEq(expectedGasFee, actualGasFee, "incorrect gas fees"); + } + } + + function testGetCurrentTxL1GasFeesOptimism() public { + // set optimism chain id + uint256[5] memory chainIds = [ + OP_MAINNET_CHAIN_ID, + OP_GOERLI_CHAIN_ID, + OP_SEPOLIA_CHAIN_ID, + BASE_MAINNET_CHAIN_ID, + BASE_GOERLI_CHAIN_ID + ]; + uint256[5] memory expectedGasFees = [uint256(10 gwei), 12 gwei, 14 gwei, 16 gwei, 18 gwei]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + uint256 expectedL1Fee = expectedGasFees[i]; + bytes memory someCalldata = abi.encode(address(0), "blah", uint256(1)); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector, bytes.concat(someCalldata, L1_FEE_DATA_PADDING)), + abi.encode(expectedL1Fee) + ); + uint256 actualL1Fee = ChainSpecificUtil._getCurrentTxL1GasFees(someCalldata); + assertEq(expectedL1Fee, actualL1Fee, "incorrect gas fees"); + } + } + + function testGetL1CalldataGasCostArbitrum() public { + uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + vm.mockCall( + ARBGAS_ADDR, + abi.encodeWithSelector(ArbGasInfo.getPricesInWei.selector), + abi.encode(0, 10, 0, 0, 0, 0) + ); + + // fee = l1PricePerByte * (calldataSizeBytes + 140) + // fee = 10 * (10 + 140) = 1500 + uint256 dataFee = ChainSpecificUtil._getL1CalldataGasCost(10); + assertEq(dataFee, 1500); + } + } + + function testGetL1CalldataGasCostOptimism() public { + uint256[5] memory chainIds = [ + OP_MAINNET_CHAIN_ID, + OP_GOERLI_CHAIN_ID, + OP_SEPOLIA_CHAIN_ID, + BASE_MAINNET_CHAIN_ID, + BASE_GOERLI_CHAIN_ID + ]; + for (uint256 i = 0; i < chainIds.length; i++) { + vm.chainId(chainIds[i]); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(hex"519b4bd3")), // l1BaseFee() + abi.encode(10) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(hex"0c18c162")), // overhead() + abi.encode(160) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(hex"f45e65d8")), // scalar() + abi.encode(500_000) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(hex"313ce567")), // decimals() + abi.encode(6) + ); + + // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 + // tx_data_gas = 0 * 4 + 10 * 16 = 160 + // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead + // l1_data_fee = 10 * (160 + 160) * 500_000 / 1_000_000 = 1600 + uint256 dataFee = ChainSpecificUtil._getL1CalldataGasCost(10); + assertEq(dataFee, 1600); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol new file mode 100644 index 0000000..c1c2c7e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol @@ -0,0 +1,134 @@ +pragma solidity ^0.8.19; + +import {console} from "forge-std/console.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; +import {VRF} from "../VRF.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import "./BaseTest.t.sol"; + +contract FixtureVRFCoordinatorV2_5 is BaseTest, VRF { + address internal SUBSCRIPTION_OWNER = makeAddr("SUBSCRIPTION_OWNER"); + + uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; + uint16 internal constant MIN_CONFIRMATIONS = 0; + uint32 internal constant CALLBACK_GAS_LIMIT = 1_000_000; + uint32 internal constant NUM_WORDS = 1; + + // VRF KeyV2 generated from a node; not sensitive information. + // The secret key used to generate this key is: 10. + bytes internal constant VRF_UNCOMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; + bytes internal constant VRF_COMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; + bytes32 internal constant VRF_KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + BlockhashStore internal s_bhs; + ExposedVRFCoordinatorV2_5 internal s_coordinator; + + // Use multiple consumers because VRFV2PlusConsumerExample cannot have multiple pending requests. + uint256 internal s_subId; + VRFV2PlusConsumerExample internal s_consumer; + VRFV2PlusConsumerExample internal s_consumer1; + + MockLinkToken internal s_linkToken; + MockV3Aggregator internal s_linkNativeFeed; + + function setUp() public virtual override { + BaseTest.setUp(); + vm.stopPrank(); + + vm.startPrank(OWNER); + s_bhs = new BlockhashStore(); + + // Deploy coordinator. + s_coordinator = new ExposedVRFCoordinatorV2_5(address(s_bhs)); + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Configure the coordinator. + s_coordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + vm.stopPrank(); + + // Deploy consumers. + vm.startPrank(SUBSCRIPTION_OWNER); + s_consumer = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); + s_consumer1 = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); + vm.stopPrank(); + } + + function _setUpConfig() internal { + vm.prank(OWNER); + s_coordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function _setUpProvingKey() internal { + uint256[2] memory uncompressedKeyParts = this._getProvingKeyParts(VRF_UNCOMPRESSED_PUBLIC_KEY); + vm.prank(OWNER); + s_coordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + } + + function _setUpSubscription() internal { + vm.startPrank(SUBSCRIPTION_OWNER); + s_subId = s_coordinator.createSubscription(); + s_coordinator.addConsumer(s_subId, address(s_consumer)); + s_consumer.setSubId(s_subId); + s_coordinator.addConsumer(s_subId, address(s_consumer1)); + s_consumer1.setSubId(s_subId); + vm.stopPrank(); + } + + // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and + // index over the byte array. + function _getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { + uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); + uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); + return [keyPart1, keyPart2]; + } + + /** + * Prints the command to generate a proof for a VRF request. + * + * This function provides a convenient way to generate the proof off-chain to be copied into the tests. + * + * An example of the command looks like this: + * go run . generate-proof-v2-plus \ + * -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + * -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ + * -block-hash 0x14 \ + * -block-num 20 \ + * -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ + * -native-payment false + */ + function _printGenerateProofV2PlusCommand( + address sender, + uint64 nonce, + uint256 requestBlock, + bool nativePayment + ) internal { + (, uint256 preSeed) = s_coordinator.computeRequestIdExternal(VRF_KEY_HASH, sender, s_subId, nonce); + + console.log("go run . generate-proof-v2-plus \\"); + console.log(string.concat(" -key-hash ", Strings.toHexString(uint256(VRF_KEY_HASH)), " \\")); + console.log(string.concat(" -pre-seed ", Strings.toString(preSeed), " \\")); + console.log(string.concat(" -block-hash ", Strings.toHexString(uint256(blockhash(requestBlock))), " \\")); + console.log(string.concat(" -block-num ", Strings.toString(requestBlock), " \\")); + console.log(string.concat(" -sender ", Strings.toHexString(sender), " \\")); + console.log(string.concat(" -native-payment ", nativePayment ? "true" : "false")); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol new file mode 100644 index 0000000..ec47f48 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol @@ -0,0 +1,89 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {TrustedBlockhashStore} from "../dev/TrustedBlockhashStore.sol"; +import {console} from "forge-std/console.sol"; + +contract TrustedBlockhashStoreTest is BaseTest { + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + address internal constant LINK_WHALE_2 = 0xe9b2C5A6D9bA93dD354783a9De0a265da7551a20; + TrustedBlockhashStore bhs; + uint256 unreachableBlockNumber = 5; + bytes32 unreachableBlockhash; + + function setUp() public override { + BaseTest.setUp(); + + // Get the blockhash for a block that later becomes unreachable in the EVM. + vm.roll(10); + unreachableBlockhash = blockhash(unreachableBlockNumber); + + // Fund our users. + vm.roll(1000); + vm.deal(LINK_WHALE, 10_000 ether); + changePrank(LINK_WHALE); + + address[] memory whitelist = new address[](1); + whitelist[0] = LINK_WHALE; + bhs = new TrustedBlockhashStore(whitelist); + } + + function testGenericBHSFunctions() public { + // Should store. + uint256 blockNumber = 999; + bhs.store(blockNumber); + assertEq(bhs.getBlockhash(blockNumber), blockhash(blockNumber)); + + // Should store earliest. + uint256 earliestBlockNumber = block.number - 256; + bhs.storeEarliest(); + assertEq(bhs.getBlockhash(earliestBlockNumber), blockhash(earliestBlockNumber)); + } + + function testTrustedBHSFunctions() public { + uint256 recentBlockNumber = 999; + + // Assume that the EVM cannot access the blockhash for block 5. + uint256 unreachableBlock = 5; + assertEq(blockhash(unreachableBlock), 0); + + // Store blockhash from whitelisted address; + uint256[] memory invalidBlockNums = new uint256[](0); + uint256[] memory blockNums = new uint256[](1); + blockNums[0] = unreachableBlock; + bytes32[] memory blockhashes = new bytes32[](1); + blockhashes[0] = unreachableBlockhash; + + // Should not be able to store with invalid recent blockhash + vm.expectRevert(TrustedBlockhashStore.InvalidRecentBlockhash.selector); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(998)); + + // Should not be able to store or change whitelist for non-whitelisted address. + changePrank(LINK_WHALE_2); + vm.expectRevert(TrustedBlockhashStore.NotInWhitelist.selector); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + vm.expectRevert("Only callable by owner"); + bhs.setWhitelist(new address[](0)); + + // Should not store for a mismatched list of block numbers and hashes. + changePrank(LINK_WHALE); + vm.expectRevert(TrustedBlockhashStore.InvalidTrustedBlockhashes.selector); + bhs.storeTrusted(invalidBlockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + + // Should store unreachable blocks via whitelisted address. + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + assertEq(bhs.getBlockhash(unreachableBlock), unreachableBlockhash); + + // Change whitelist. Assert that the old whitelisted address can no longer store, + // but the new one can. + address[] memory newWhitelist = new address[](1); + newWhitelist[0] = LINK_WHALE_2; + bhs.setWhitelist(newWhitelist); + + vm.expectRevert(TrustedBlockhashStore.NotInWhitelist.selector); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + + changePrank(LINK_WHALE_2); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol new file mode 100644 index 0000000..1716118 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol @@ -0,0 +1,381 @@ +pragma solidity 0.8.6; + +import "./BaseTest.t.sol"; +import {VRF} from "../VRF.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {VRFCoordinatorV2Mock} from "../mocks/VRFCoordinatorV2Mock.sol"; +import {VRFConsumerV2} from "../testhelpers/VRFConsumerV2.sol"; + +contract VRFCoordinatorV2MockTest is BaseTest { + MockLinkToken internal s_linkToken; + MockV3Aggregator internal s_linkEthFeed; + VRFCoordinatorV2Mock internal s_vrfCoordinatorV2Mock; + VRFConsumerV2 internal s_vrfConsumerV2; + address internal s_subOwner = address(1234); + address internal s_randomOwner = address(4567); + + // VRF KeyV2 generated from a node; not sensitive information. + // The secret key used to generate this key is: 10. + bytes internal constant UNCOMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; + bytes internal constant COMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; + bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; + uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; + uint32 internal constant DEFAULT_NUM_WORDS = 1; + + uint96 pointOneLink = 0.1 ether; + uint96 oneLink = 1 ether; + + event SubscriptionCreated(uint64 indexed subId, address owner); + event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); + event ConsumerAdded(uint64 indexed subId, address consumer); + event ConsumerRemoved(uint64 indexed subId, address consumer); + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint64 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(OWNER, 10_000 ether); + vm.deal(s_subOwner, 20 ether); + + // Deploy link token and link/eth feed. + s_linkToken = new MockLinkToken(); + s_linkEthFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Deploy coordinator and consumer. + s_vrfCoordinatorV2Mock = new VRFCoordinatorV2Mock( + pointOneLink, + 1_000_000_000 // 0.000000001 LINK per gas + ); + address coordinatorAddr = address(s_vrfCoordinatorV2Mock); + s_vrfConsumerV2 = new VRFConsumerV2(coordinatorAddr, address(s_linkToken)); + + s_vrfCoordinatorV2Mock.setConfig(); + } + + function testCreateSubscription() public { + vm.startPrank(s_subOwner); + vm.expectEmit( + true, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit SubscriptionCreated(1, s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + assertEq(subId, 1); + + (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2Mock + .getSubscription(subId); + assertEq(balance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 0); + // s_testCoordinator.fundSubscriptionWithEth{value: 10 ether}(subId); + + // Test if subId increments + vm.expectEmit(true, false, false, true); + emit SubscriptionCreated(2, s_subOwner); + subId = s_vrfCoordinatorV2Mock.createSubscription(); + assertEq(subId, 2); + vm.stopPrank(); + } + + function testAddConsumer() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + vm.expectEmit(true, false, false, true); + emit ConsumerAdded(subId, address(s_vrfConsumerV2)); + s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); + + (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2Mock + .getSubscription(subId); + assertEq(balance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2)); + vm.stopPrank(); + } + + // cannot add a consumer to a nonexistent subscription + function testAddConsumerToInvalidSub() public { + vm.startPrank(s_subOwner); + bytes4 reason = bytes4(keccak256("InvalidSubscription()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.addConsumer(1, address(s_vrfConsumerV2)); + vm.stopPrank(); + } + + // cannot add more than the consumer maximum + function testAddMaxConsumers() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + // Add 100 consumers + for (uint64 i = 101; i <= 200; ++i) { + s_vrfCoordinatorV2Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); + } + // Adding 101th consumer should revert + bytes4 reason = bytes4(keccak256("TooManyConsumers()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); + vm.stopPrank(); + } + + // can remove a consumer from a subscription + function testRemoveConsumerFromSub() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); + + (, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2)); + + vm.expectEmit(true, false, false, true); + emit ConsumerRemoved(subId, address(s_vrfConsumerV2)); + s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); + + vm.stopPrank(); + } + + // cannot remove a consumer from a nonexistent subscription + function testRemoveConsumerFromInvalidSub() public { + vm.startPrank(s_subOwner); + bytes4 reason = bytes4(keccak256("InvalidSubscription()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.removeConsumer(1, address(s_vrfConsumerV2)); + vm.stopPrank(); + } + + // cannot remove a consumer after it is already removed + function testRemoveConsumerAgain() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); + + (, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2)); + + vm.expectEmit(true, false, false, true); + emit ConsumerRemoved(subId, address(s_vrfConsumerV2)); + s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); + + // Removing consumer again should revert with InvalidConsumer + bytes4 reason = bytes4(keccak256("InvalidConsumer()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); + vm.stopPrank(); + } + + // can fund a subscription + function testFundSubscription() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, oneLink); + s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); + + (uint96 balance, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); + assertEq(balance, oneLink); + assertEq(consumers.length, 0); + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFundInvalidSubscription() public { + vm.startPrank(s_subOwner); + + // Removing consumer again should revert with InvalidConsumer + bytes4 reason = bytes4(keccak256("InvalidSubscription()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.removeConsumer(1, address(s_vrfConsumerV2)); + + vm.stopPrank(); + } + + // can cancel a subscription + function testCancelSubscription() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, oneLink); + s_vrfCoordinatorV2Mock.cancelSubscription(subId, s_subOwner); + + bytes4 reason = bytes4(keccak256("InvalidSubscription()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // fails to fulfill without being a valid consumer + function testRequestRandomWordsInvalidConsumer() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); + + bytes4 reason = bytes4(keccak256("InvalidConsumer()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.requestRandomWords( + KEY_HASH, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS + ); + vm.stopPrank(); + } + + // fails to fulfill with insufficient funds + function testRequestRandomWordsInsufficientFunds() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + address consumerAddr = address(s_vrfConsumerV2); + s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); + + vm.stopPrank(); + + vm.startPrank(consumerAddr); + + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + address(s_subOwner) + ); + uint256 reqId = s_vrfCoordinatorV2Mock.requestRandomWords( + KEY_HASH, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS + ); + + bytes4 reason = bytes4(keccak256("InsufficientBalance()")); + vm.expectRevert(toBytes(reason)); + s_vrfCoordinatorV2Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function testRequestRandomWordsHappyPath() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); + + address consumerAddr = address(s_vrfConsumerV2); + s_vrfCoordinatorV2Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + address(s_subOwner) + ); + uint256 reqId = s_vrfConsumerV2.requestRandomness( + KEY_HASH, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS + ); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, 100090236000000000, true); + s_vrfCoordinatorV2Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] + function testRequestRandomWordsUserOverride() public { + vm.startPrank(s_subOwner); + uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); + + s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); + + address consumerAddr = address(s_vrfConsumerV2); + s_vrfCoordinatorV2Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 2, + address(s_subOwner) + ); + uint256 reqId = s_vrfConsumerV2.requestRandomness( + KEY_HASH, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 2 + ); + + bytes4 reason = bytes4(keccak256("InvalidRandomWords()")); + vm.expectRevert(toBytes(reason)); + uint256[] memory words1 = new uint256[](5); + words1[0] = 1; + words1[1] = 2; + words1[2] = 3; + words1[3] = 4; + words1[4] = 5; + s_vrfCoordinatorV2Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); + + vm.expectEmit(true, false, false, true); + uint256[] memory words2 = new uint256[](2); + words1[0] = 2533; + words1[1] = 1768; + emit RandomWordsFulfilled(reqId, 1, 100072314000000000, true); + s_vrfCoordinatorV2Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); + + vm.stopPrank(); + } + + function toBytes(bytes4 _data) public pure returns (bytes memory) { + return abi.encodePacked(_data); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol new file mode 100644 index 0000000..ad23959 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol @@ -0,0 +1,352 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {VRFV2PlusMaliciousMigrator} from "../dev/testhelpers/VRFV2PlusMaliciousMigrator.sol"; + +contract VRFCoordinatorV2Plus_Migration is BaseTest { + uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 LINK + uint256 internal constant DEFAULT_NATIVE_FUNDING = 50 ether; // 50 ETH + uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 50_000; + uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; + uint32 internal constant DEFAULT_NUM_WORDS = 1; + // VRF KeyV2 generated from a node; not sensitive information. + // The secret key used to generate this key is: 10. + bytes internal constant UNCOMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; + bytes internal constant COMPRESSED_PUBLIC_KEY = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; + bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; + + ExposedVRFCoordinatorV2_5 v1Coordinator; + VRFCoordinatorV2Plus_V2Example v2Coordinator; + ExposedVRFCoordinatorV2_5 v1Coordinator_noLink; + VRFCoordinatorV2Plus_V2Example v2Coordinator_noLink; + uint256 subId; + uint256 subId_noLink; + VRFV2PlusConsumerExample testConsumer; + VRFV2PlusConsumerExample testConsumer_noLink; + MockLinkToken linkToken; + address linkTokenAddr; + MockV3Aggregator linkNativeFeed; + address v1CoordinatorAddr; + address v2CoordinatorAddr; + address v1CoordinatorAddr_noLink; + address v2CoordinatorAddr_noLink; + + event CoordinatorRegistered(address coordinatorAddress); + event CoordinatorDeregistered(address coordinatorAddress); + event MigrationCompleted(address newCoordinator, uint256 subId); + + function setUp() public override { + BaseTest.setUp(); + vm.deal(OWNER, 100 ether); + address bhs = makeAddr("bhs"); + v1Coordinator = new ExposedVRFCoordinatorV2_5(bhs); + v1Coordinator_noLink = new ExposedVRFCoordinatorV2_5(bhs); + subId = v1Coordinator.createSubscription(); + subId_noLink = v1Coordinator_noLink.createSubscription(); + linkToken = new MockLinkToken(); + linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + v1Coordinator.setLINKAndLINKNativeFeed(address(linkToken), address(linkNativeFeed)); + linkTokenAddr = address(linkToken); + v2Coordinator = new VRFCoordinatorV2Plus_V2Example(address(linkToken), address(v1Coordinator)); + v2Coordinator_noLink = new VRFCoordinatorV2Plus_V2Example(address(0), address(v1Coordinator_noLink)); + v1CoordinatorAddr = address(v1Coordinator); + v2CoordinatorAddr = address(v2Coordinator); + v1CoordinatorAddr_noLink = address(v1Coordinator_noLink); + v2CoordinatorAddr_noLink = address(v2Coordinator_noLink); + + vm.expectEmit( + false, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit CoordinatorRegistered(v2CoordinatorAddr); + v1Coordinator.registerMigratableCoordinator(v2CoordinatorAddr); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + + vm.expectEmit( + false, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit CoordinatorRegistered(v2CoordinatorAddr_noLink); + v1Coordinator_noLink.registerMigratableCoordinator(v2CoordinatorAddr_noLink); + assertTrue(v1Coordinator_noLink.isTargetRegisteredExternal(v2CoordinatorAddr_noLink)); + + testConsumer = new VRFV2PlusConsumerExample(address(v1Coordinator), address(linkToken)); + testConsumer_noLink = new VRFV2PlusConsumerExample(address(v1Coordinator_noLink), address(0)); + v1Coordinator.setConfig( + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 600, + 10_000, + 20_000, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + v1Coordinator_noLink.setConfig( + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 600, + 10_000, + 20_000, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + registerProvingKey(); + testConsumer.setCoordinator(v1CoordinatorAddr); + testConsumer_noLink.setCoordinator(v1CoordinatorAddr_noLink); + } + + function testDeregister() public { + vm.expectEmit( + false, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit CoordinatorDeregistered(v2CoordinatorAddr); + v1Coordinator.deregisterMigratableCoordinator(v2CoordinatorAddr); + assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.CoordinatorNotRegistered.selector, v2CoordinatorAddr)); + v1Coordinator.migrate(subId, v2CoordinatorAddr); + + // test register/deregister multiple coordinators + address v3CoordinatorAddr = makeAddr("v3Coordinator"); + v1Coordinator.registerMigratableCoordinator(v2CoordinatorAddr); + v1Coordinator.registerMigratableCoordinator(v3CoordinatorAddr); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); + + v1Coordinator.deregisterMigratableCoordinator(v3CoordinatorAddr); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + assertFalse(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); + + v1Coordinator.registerMigratableCoordinator(v3CoordinatorAddr); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); + + v1Coordinator.deregisterMigratableCoordinator(v2CoordinatorAddr); + assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); + + v1Coordinator.deregisterMigratableCoordinator(v3CoordinatorAddr); + assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); + assertFalse(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); + } + + function testMigration() public { + linkToken.transferAndCall(v1CoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(subId)); + v1Coordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(subId); + v1Coordinator.addConsumer(subId, address(testConsumer)); + + // subscription exists in V1 coordinator before migration + (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers) = v1Coordinator + .getSubscription(subId); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(owner, address(OWNER)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(testConsumer)); + + assertEq(v1Coordinator.s_totalBalance(), DEFAULT_LINK_FUNDING); + assertEq(v1Coordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + + // Update consumer to point to the new coordinator + vm.expectEmit( + false, // no first indexed field + false, // no second indexed field + false, // no third indexed field + true // check data fields + ); + emit MigrationCompleted(v2CoordinatorAddr, subId); + v1Coordinator.migrate(subId, v2CoordinatorAddr); + + // subscription no longer exists in v1 coordinator after migration + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + v1Coordinator.getSubscription(subId); + assertEq(v1Coordinator.s_totalBalance(), 0); + assertEq(v1Coordinator.s_totalNativeBalance(), 0); + assertEq(linkToken.balanceOf(v1CoordinatorAddr), 0); + assertEq(v1CoordinatorAddr.balance, 0); + + // subscription exists in v2 coordinator + (balance, nativeBalance, reqCount, owner, consumers) = v2Coordinator.getSubscription(subId); + assertEq(owner, address(OWNER)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(testConsumer)); + assertEq(reqCount, 0); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(v2Coordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); + assertEq(v2Coordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + assertEq(linkToken.balanceOf(v2CoordinatorAddr), DEFAULT_LINK_FUNDING); + assertEq(v2CoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); + + // calling migrate again on V1 coordinator should fail + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + v1Coordinator.migrate(subId, v2CoordinatorAddr); + + // test request still works after migration + testConsumer.requestRandomWords( + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_NUM_WORDS, + KEY_HASH, + false + ); + assertEq(testConsumer.s_recentRequestId(), 1); + + v2Coordinator.fulfillRandomWords(testConsumer.s_recentRequestId()); + assertEq( + testConsumer.getRandomness(testConsumer.s_recentRequestId(), 0), + v2Coordinator.generateFakeRandomness(testConsumer.s_recentRequestId())[0] + ); + } + + function testMigrationNoLink() public { + v1Coordinator_noLink.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(subId_noLink); + v1Coordinator_noLink.addConsumer(subId_noLink, address(testConsumer_noLink)); + + // subscription exists in V1 coordinator before migration + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = v1Coordinator_noLink.getSubscription(subId_noLink); + assertEq(balance, 0); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(owner, address(OWNER)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(testConsumer_noLink)); + + assertEq(v1Coordinator_noLink.s_totalBalance(), 0); + assertEq(v1Coordinator_noLink.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + + // Update consumer to point to the new coordinator + vm.expectEmit( + false, // no first indexed field + false, // no second indexed field + false, // no third indexed field + true // check data fields + ); + emit MigrationCompleted(v2CoordinatorAddr_noLink, subId_noLink); + v1Coordinator_noLink.migrate(subId_noLink, v2CoordinatorAddr_noLink); + + // subscription no longer exists in v1 coordinator after migration + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + v1Coordinator_noLink.getSubscription(subId); + assertEq(v1Coordinator_noLink.s_totalBalance(), 0); + assertEq(v1Coordinator_noLink.s_totalNativeBalance(), 0); + assertEq(linkToken.balanceOf(v1CoordinatorAddr_noLink), 0); + assertEq(v1CoordinatorAddr_noLink.balance, 0); + + // subscription exists in v2 coordinator + (balance, nativeBalance, reqCount, owner, consumers) = v2Coordinator_noLink.getSubscription(subId_noLink); + assertEq(owner, address(OWNER)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(testConsumer_noLink)); + assertEq(reqCount, 0); + assertEq(balance, 0); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(v2Coordinator_noLink.s_totalLinkBalance(), 0); + assertEq(v2Coordinator_noLink.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + assertEq(linkToken.balanceOf(v2CoordinatorAddr_noLink), 0); + assertEq(v2CoordinatorAddr_noLink.balance, DEFAULT_NATIVE_FUNDING); + + // calling migrate again on V1 coordinator should fail + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + v1Coordinator_noLink.migrate(subId_noLink, v2CoordinatorAddr_noLink); + + // test request still works after migration + testConsumer_noLink.requestRandomWords( + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_NUM_WORDS, + KEY_HASH, + false + ); + assertEq(testConsumer_noLink.s_recentRequestId(), 1); + + v2Coordinator_noLink.fulfillRandomWords(testConsumer_noLink.s_recentRequestId()); + assertEq( + testConsumer_noLink.getRandomness(testConsumer_noLink.s_recentRequestId(), 0), + v2Coordinator_noLink.generateFakeRandomness(testConsumer_noLink.s_recentRequestId())[0] + ); + } + + function testMigrateRevertsWhenInvalidCoordinator() external { + address invalidCoordinator = makeAddr("invalidCoordinator"); + + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.CoordinatorNotRegistered.selector, address(invalidCoordinator)) + ); + v1Coordinator.migrate(subId, invalidCoordinator); + } + + function testMigrateRevertsWhenInvalidCaller() external { + changePrank(makeAddr("invalidCaller")); + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.MustBeSubOwner.selector, OWNER)); + v1Coordinator.migrate(subId, v2CoordinatorAddr); + } + + function testMigrateRevertsWhenPendingFulfillment() external { + v1Coordinator.addConsumer(subId, address(testConsumer)); + testConsumer.setSubId(subId); + testConsumer.requestRandomWords( + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_NUM_WORDS, + KEY_HASH, + false + ); + + vm.expectRevert(SubscriptionAPI.PendingRequestExists.selector); + v1Coordinator.migrate(subId, v2CoordinatorAddr); + } + + function testMigrateRevertsWhenReentrant() public { + // deploy malicious contracts, subscriptions + address maliciousUser = makeAddr("maliciousUser"); + changePrank(maliciousUser); + uint256 maliciousSubId = v1Coordinator.createSubscription(); + VRFV2PlusMaliciousMigrator prankster = new VRFV2PlusMaliciousMigrator(address(v1Coordinator)); + v1Coordinator.addConsumer(maliciousSubId, address(prankster)); + + // try to migrate malicious subscription, should fail + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.Reentrant.selector)); + v1Coordinator.migrate(maliciousSubId, v2CoordinatorAddr); + } + + function registerProvingKey() public { + uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(UNCOMPRESSED_PUBLIC_KEY); + v1Coordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + v1Coordinator_noLink.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + } + + // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and + // index over the byte array. + function getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { + uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); + uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); + return [keyPart1, keyPart2]; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol new file mode 100644 index 0000000..75c763c --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol @@ -0,0 +1,511 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFCoordinatorV2_5Mock} from "../mocks/VRFCoordinatorV2_5Mock.sol"; +import {VRFConsumerV2Plus} from "../testhelpers/VRFConsumerV2Plus.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; + +contract VRFCoordinatorV2_5MockTest is BaseTest { + MockLinkToken internal s_linkToken; + VRFCoordinatorV2_5Mock internal s_vrfCoordinatorV2_5Mock; + VRFConsumerV2Plus internal s_vrfConsumerV2Plus; + address internal s_subOwner = address(1234); + + bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; + uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; + uint32 internal constant DEFAULT_NUM_WORDS = 1; + + uint96 internal constant oneNative = 1 ether; + uint96 internal constant twoLink = 2 ether; + + event SubscriptionCreated(uint256 indexed subId, address owner); + event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); + event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subId, + uint96 payment, + bool nativePayment, + bool success, + bool onlyPremium + ); + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(OWNER, 10_000 ether); + vm.deal(s_subOwner, 20 ether); + + // Deploy link token and link/eth feed. + s_linkToken = new MockLinkToken(); + + // Deploy coordinator and consumer. + s_vrfCoordinatorV2_5Mock = new VRFCoordinatorV2_5Mock(0.002 ether, 40 gwei, 0.004 ether); + address coordinatorAddr = address(s_vrfCoordinatorV2_5Mock); + s_vrfConsumerV2Plus = new VRFConsumerV2Plus(coordinatorAddr, address(s_linkToken)); + + s_vrfCoordinatorV2_5Mock.setConfig(); + } + + function test_CreateSubscription() public { + vm.startPrank(s_subOwner); + uint256 expectedSubId = uint256( + keccak256( + abi.encodePacked( + s_subOwner, + blockhash(block.number - 1), + address(s_vrfCoordinatorV2_5Mock), + s_vrfCoordinatorV2_5Mock.s_currentSubNonce() + ) + ) + ); + vm.expectEmit( + true, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + emit SubscriptionCreated(expectedSubId, s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + assertEq(subId, expectedSubId); + + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, 0); + assertEq(nativeBalance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 0); + vm.stopPrank(); + } + + function test_AddConsumer() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (uint96 balance, , uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2_5Mock + .getSubscription(subId); + assertEq(balance, 0); + assertEq(reqCount, 0); + assertEq(owner, s_subOwner); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add a consumer to a nonexistent subscription + function test_AddConsumerToInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot add more than the consumer maximum + function test_AddMaxConsumers() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + // Add 100 consumers + for (uint64 i = 101; i <= 200; ++i) { + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); + } + // Adding 101th consumer should revert + vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can remove a consumer from a subscription + function test_RemoveConsumerFromSub() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + } + + // cannot remove a consumer from a nonexistent subscription + function test_RemoveConsumerFromInvalidSub() public { + vm.startPrank(s_subOwner); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.removeConsumer(1, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // cannot remove a consumer after it is already removed + function test_RemoveConsumerAgain() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_vrfConsumerV2Plus)); + + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + + // Removing consumer again should revert with InvalidConsumer + vm.expectRevert( + abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) + ); + s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); + vm.stopPrank(); + } + + // can fund a subscription + function test_FundSubscription() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, twoLink); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + (uint96 balance, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(balance, twoLink); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), twoLink); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscription_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.stopPrank(); + } + + // can fund a subscription with native + function test_FundSubscriptionWithNative() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, oneNative); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + (, uint256 nativeBalance, , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); + assertEq(nativeBalance, oneNative); + assertEq(consumers.length, 0); + + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), oneNative); + + vm.stopPrank(); + } + + // cannot fund a nonexistent subscription + function testFuzz_FundSubscriptionWithNative_RevertIfInvalidSubscription(uint256 subId) public { + vm.startPrank(s_subOwner); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Link() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + uint256 totalBalance = s_vrfCoordinatorV2_5Mock.s_totalBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, twoLink, 0); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), totalBalance - twoLink); + + // sub owner balance did not increase as no actual token is involved + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // can cancel a subscription + function test_CancelSubscription_Native() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + uint256 balance = address(s_subOwner).balance; + uint256 totalNativeBalance = s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(); + + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, s_subOwner, 0, oneNative); + s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); + + // check coordinator balance decreased + assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), totalNativeBalance - oneNative); + + // check sub owner balance increased + assertEq(address(s_subOwner).balance, balance + oneNative); + + // check subscription removed + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_vrfCoordinatorV2_5Mock.getSubscription(subId); + + vm.stopPrank(); + } + + // fails to fulfill without being a valid consumer + function testFuzz_RequestRandomWords_RevertIfInvalidConsumer(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_subOwner))); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) + }); + s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + vm.stopPrank(); + } + + // fails to fulfill with insufficient funds + function testFuzz_RequestRandomWords_RevertIfInsufficientFunds(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); + + vm.stopPrank(); + + vm.startPrank(consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfCoordinatorV2_5Mock.requestRandomWords(req); + + vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Link_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 1432960000000000000, false, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // can request and fulfill [ @skip-coverage ] + function test_RequestRandomWords_Native_HappyPath() public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + vm.expectEmit(true, false, false, true); + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + DEFAULT_NUM_WORDS, + extraArgs, + address(s_subOwner) + ); + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: DEFAULT_NUM_WORDS, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectEmit(true, false, false, true); + emit RandomWordsFulfilled(reqId, 1, subId, 5731840000000000, true, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); + + vm.stopPrank(); + } + + // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] + function testFuzz_RequestRandomWordsUserOverride(bool nativePayment) public { + vm.startPrank(s_subOwner); + uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); + + uint96 expectedPayment; + if (nativePayment) { + expectedPayment = 5011440000000000; + s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); + } else { + expectedPayment = 1252860000000000000; + s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); + } + + address consumerAddr = address(s_vrfConsumerV2Plus); + s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); + + bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); + vm.expectEmit(true, false, false, true); + emit RandomWordsRequested( + KEY_HASH, + 1, + 100, + subId, + DEFAULT_REQUEST_CONFIRMATIONS, + DEFAULT_CALLBACK_GAS_LIMIT, + 2, + extraArgs, + address(s_subOwner) + ); + + VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ + keyHash: KEY_HASH, + subId: subId, + requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, + callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, + numWords: 2, + extraArgs: extraArgs + }); + uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); + + vm.expectRevert(VRFCoordinatorV2_5Mock.InvalidRandomWords.selector); + uint256[] memory words1 = new uint256[](5); + words1[0] = 1; + words1[1] = 2; + words1[2] = 3; + words1[3] = 4; + words1[4] = 5; + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); + + vm.expectEmit(true, false, false, true); + uint256[] memory words2 = new uint256[](2); + words1[0] = 2533; + words1[1] = 1768; + emit RandomWordsFulfilled(reqId, 1, subId, expectedPayment, nativePayment, true, false); + s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); + + vm.stopPrank(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol new file mode 100644 index 0000000..8e47b80 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol @@ -0,0 +1,179 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {VmSafe} from "forge-std/Vm.sol"; + +contract VRFV2CoordinatorV2_5_Arbitrum is BaseTest { + /// @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 ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. + /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 + address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); + ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); + + address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + + BlockhashStore s_bhs; + ExposedVRFCoordinatorV2_5_Arbitrum s_testCoordinator; + MockLinkToken s_linkToken; + MockV3Aggregator s_linkNativeFeed; + + uint256 s_startGas = 0.0038 gwei; + uint256 s_weiPerUnitGas = 0.003 gwei; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(DEPLOYER, 10_000 ether); + changePrank(DEPLOYER); + + vm.txGasPrice(100 gwei); + + // Instantiate BHS. + s_bhs = new BlockhashStore(); + + // Deploy coordinator, LINK token and LINK/Native feed. + s_testCoordinator = new ExposedVRFCoordinatorV2_5_Arbitrum(address(s_bhs)); + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Configure the coordinator. + s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + s_testCoordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function _encodeCalculatePaymentAmountNativeExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + ExposedVRFCoordinatorV2_5_Arbitrum.calculatePaymentAmountNativeExternal.selector, + startGas, + weiPerUnitGas, + onlyPremium + ); + } + + function _encodeCalculatePaymentAmountLinkExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + ExposedVRFCoordinatorV2_5_Arbitrum.calculatePaymentAmountLinkExternal.selector, + startGas, + weiPerUnitGas, + onlyPremium + ); + } + + function _checkL1GasFeeEmittedLogs(uint256 expectedL1GasFee) internal { + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries.length, 1); + assertEq(entries[0].topics.length, 1); + assertEq(entries[0].topics[0], keccak256("L1GasFee(uint256)")); + // 1e15 is less than 1 percent discrepancy + uint256 actualL1GasFee = abi.decode(entries[0].data, (uint256)); + assertApproxEqAbs(expectedL1GasFee, actualL1GasFee, 1e15); + } + + function test_getBlockNumber() public { + // sanity check that Arbitrum will use ArbSys to get the block number + vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockNumber.selector), abi.encode(33691)); + assertEq(33691, s_testCoordinator.getBlockNumberExternal()); + } + + function test_getBlockhash() public { + // for blocks within 256 blocks from the current block return the blockhash using ArbSys + bytes32 testBlockHash = bytes32(keccak256("testBlock")); + vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockNumber.selector), abi.encode(45830)); + vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockHash.selector, 45825), abi.encode(testBlockHash)); + assertEq(testBlockHash, s_testCoordinator.getBlockhashExternal(45825)); + // for blocks outside 256 blocks from the current block return nothing + assertEq("", s_testCoordinator.getBlockhashExternal(33830)); + // for blocks greater than the current block return nothing + assertEq("", s_testCoordinator.getBlockhashExternal(50550)); + } + + function test_calculatePaymentAmountNative() public { + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + vm.mockCall(ARBGAS_ADDR, abi.encodeWithSelector(ARBGAS.getCurrentTxL1GasFees.selector), abi.encode(10 gwei)); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(10 gwei)); + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.000129 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(10 gwei)); + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.000017 * 1e17, 1e15); + } + + function test_calculatePaymentAmountLink() public { + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + vm.mockCall(ARBGAS_ADDR, abi.encodeWithSelector(ARBGAS.getCurrentTxL1GasFees.selector), abi.encode(10 gwei)); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(10 gwei)); + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.00024772 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(10 gwei)); + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.00002252 * 1e17, 1e15); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol new file mode 100644 index 0000000..b54dbba --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol @@ -0,0 +1,413 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; +import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; +import {VmSafe} from "forge-std/Vm.sol"; + +contract VRFV2CoordinatorV2_5_Optimism is BaseTest { + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + /// @dev L1_FEE_DATA_PADDING includes 71 bytes for L1 data padding for Optimism + bytes internal constant L1_FEE_DATA_PADDING = + hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + + address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + + BlockhashStore s_bhs; + ExposedVRFCoordinatorV2_5_Optimism s_testCoordinator; + MockLinkToken s_linkToken; + MockV3Aggregator s_linkNativeFeed; + + uint256 s_startGas = 0.0038 gwei; + uint256 s_weiPerUnitGas = 0.003 gwei; + + /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload + /// @dev This option is only available for the Coordinator contract + uint8 internal constant L1_GAS_FEES_MODE = 0; + /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected + /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; + /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(DEPLOYER, 10_000 ether); + changePrank(DEPLOYER); + + vm.txGasPrice(100 gwei); + + // Instantiate BHS. + s_bhs = new BlockhashStore(); + + // Deploy coordinator, LINK token and LINK/Native feed. + s_testCoordinator = new ExposedVRFCoordinatorV2_5_Optimism(address(s_bhs)); + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Configure the coordinator. + s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + s_testCoordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function _encodeCalculatePaymentAmountNativeExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + ExposedVRFCoordinatorV2_5_Optimism.calculatePaymentAmountNativeExternal.selector, + startGas, + weiPerUnitGas, + onlyPremium + ); + } + + function _encodeCalculatePaymentAmountLinkExternal( + uint256 startGas, + uint256 weiPerUnitGas, + bool onlyPremium + ) internal pure returns (bytes memory) { + return + abi.encodeWithSelector( + ExposedVRFCoordinatorV2_5_Optimism.calculatePaymentAmountLinkExternal.selector, + startGas, + weiPerUnitGas, + onlyPremium + ); + } + + function _mockGasOraclePriceGetL1FeeUpperBoundCall() internal { + // 171 bytes is the size of tx.data we are sending in this test + // this is not expected fulfillment tx size! + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(OVM_GasPriceOracle.getL1FeeUpperBound.selector, 171), + abi.encode(uint256(0.02 ether)) + ); + } + + function _mockGasOraclePriceFeeMethods() internal { + // these values are taken from an example transaction on Base Sepolia + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("l1BaseFee()"))), + abi.encode(64273426165) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("baseFeeScalar()"))), + abi.encode(1101) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("blobBaseFeeScalar()"))), + abi.encode(659851) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("blobBaseFee()"))), + abi.encode(2126959908362) + ); + vm.mockCall(OVM_GASPRICEORACLE_ADDR, abi.encodeWithSelector(bytes4(keccak256("decimals()"))), abi.encode(6)); + } + + function _mockGasOraclePriceGetL1FeeCall(bytes memory txMsgData) internal { + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector, bytes.concat(txMsgData, L1_FEE_DATA_PADDING)), + abi.encode(uint256(0.001 ether)) + ); + } + + function _checkL1GasFeeEmittedLogs(uint256 expectedL1GasFee) internal { + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries.length, 1); + assertEq(entries[0].topics.length, 1); + assertEq(entries[0].topics[0], keccak256("L1GasFee(uint256)")); + // 1e15 is less than 1 percent discrepancy + uint256 actualL1GasFee = abi.decode(entries[0].data, (uint256)); + assertApproxEqAbs(expectedL1GasFee, actualL1GasFee, 1e15); + } + + function _checkL1FeeCalculationSetEmittedLogs(uint8 expectedMode, uint8 expectedCoefficient) internal { + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries.length, 1); + assertEq(entries[0].topics.length, 1); + assertEq(entries[0].topics[0], keccak256("L1FeeCalculationSet(uint8,uint8)")); + (uint8 actualMode, uint8 actualCoefficient) = abi.decode(entries[0].data, (uint8, uint8)); + assertEq(expectedMode, actualMode); + assertEq(expectedCoefficient, actualCoefficient); + } + + function test_setL1FeePaymentMethod() public { + // check default settings after contract deployment + assertEq(uint256(L1_GAS_FEES_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); + assertEq(100, uint256(s_testCoordinator.s_l1FeeCoefficient())); + vm.recordLogs(); + + s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); + + _checkL1FeeCalculationSetEmittedLogs(L1_CALLDATA_GAS_COST_MODE, 70); + assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); + assertEq(70, uint256(s_testCoordinator.s_l1FeeCoefficient())); + + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 30); + + _checkL1FeeCalculationSetEmittedLogs(L1_GAS_FEES_UPPER_BOUND_MODE, 30); + assertEq(uint256(L1_GAS_FEES_UPPER_BOUND_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); + assertEq(30, uint256(s_testCoordinator.s_l1FeeCoefficient())); + + // should revert if invalid L1 fee calculation mode is used + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCalculationMode.selector, 4)); + s_testCoordinator.setL1FeeCalculation(4, 100); + + // should revert if invalid coefficient is used (equal to zero, this would disable L1 fees completely) + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 0)); + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 0); + + // should revert if invalid coefficient is used (larger than 100%) + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 150)); + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 150); + } + + function test_getBlockNumber() public { + // sanity check that OP stack will use block.number directly + vm.roll(1589); + assertEq(1589, s_testCoordinator.getBlockNumberExternal()); + } + + function test_getBlockhash() public { + // sanity check that OP stack will use blockhash() directly + vm.roll(1589); + bytes32 blockHash = blockhash(1589); + assertEq(blockHash, s_testCoordinator.getBlockhashExternal(1589)); + } + + // payment calculation depends on the L1 gas cost for fulfillment transaction payload + // both calculatePayment functions use msg.data passed down from the fulfillRandomWords function and + // in that case, msg.data contains the fulfillment transaction payload (calldata) + // it's not easy to simulate this in tests below plus we only want to concentrate on the payment part + // since we don't have to test with the correct payload, we can use any kind of payload for msg.data + // in the case of tests below, msg.data will carry calculatePayment function selectors and parameters + + function test_calculatePaymentAmountNativeUsingL1GasFeesMode() public { + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeCall(txMsgData); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.0162937 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeCall(txMsgData); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.0015168 * 1e17, 1e15); + } + + function test_calculatePaymentAmountLinkUsingL1GasFeesMode() public { + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeCall(txMsgData); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.0222475 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeCall(txMsgData); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.0020225 * 1e17, 1e15); + } + + function test_calculatePaymentAmountNativeUsingCalldataGasCostMode() public { + // for this type of cost calculation we are applying coefficient to reduce the inflated gas price + s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceFeeMethods(); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.002834 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceFeeMethods(); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.00037 * 1e17, 1e15); + } + + function test_calculatePaymentAmountLinkUsingCalldataGasCostMode() public { + // for this type of cost calculation we are applying coefficient to reduce the inflated gas price + s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceFeeMethods(); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.0054219 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceFeeMethods(); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.0004929 * 1e17, 1e15); + } + + function test_calculatePaymentAmountNativeUsingL1GasFeesUpperBoundMode() public { + // for this type of cost calculation we are applying coefficient to reduce the inflated gas price + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 50); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.115129 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.015017 * 1e17, 1e15); + } + + function test_calculatePaymentAmountLinkUsingL1GasFeesUpperBoundMode() public { + // for this type of cost calculation we are applying coefficient to reduce the inflated gas price + s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 50); + + // first we test premium and flat fee payment combined + bool onlyPremium = false; + bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + vm.recordLogs(); + + uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation + (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) + + uint96 payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.2202475 * 1e17, 1e15); + + // now we test only premium payment + onlyPremium = true; + txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + + (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); + assertTrue(success); + _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) + + payment = abi.decode(returnData, (uint96)); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.0200225 * 1e17, 1e15); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol new file mode 100644 index 0000000..dd3f54b --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol @@ -0,0 +1,1160 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {VRF} from "../VRF.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFTypes} from "../VRFTypes.sol"; +import {console} from "forge-std/console.sol"; +import {VmSafe} from "forge-std/Vm.sol"; +import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; +import "@openzeppelin/contracts/utils/math/Math.sol"; // for Math.ceilDiv + +/* + * USAGE INSTRUCTIONS: + * To add new tests/proofs, uncomment the "console.sol" import from foundry, and gather key fields + * from your VRF request. + * Then, pass your request info into the generate-proof-v2-plus script command + * located in /core/scripts/vrfv2/testnet/proofs.go to generate a proof that can be tested on-chain. + **/ + +contract VRFV2Plus is BaseTest { + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; + uint16 internal constant MIN_CONFIRMATIONS = 0; + uint32 internal constant CALLBACK_GAS_LIMIT = 1_000_000; + uint32 internal constant NUM_WORDS = 1; + + // Bytecode for a VRFV2PlusConsumerExample contract. + // to calculate: console.logBytes(type(VRFV2PlusConsumerExample).creationCode); + bytes constant initializeCode = + hex"60806040523480156200001157600080fd5b5060405162001377380380620013778339810160408190526200003491620001cc565b8133806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000103565b5050600280546001600160a01b03199081166001600160a01b0394851617909155600580548216958416959095179094555060038054909316911617905562000204565b6001600160a01b0381163314156200015e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001c757600080fd5b919050565b60008060408385031215620001e057600080fd5b620001eb83620001af565b9150620001fb60208401620001af565b90509250929050565b61116380620002146000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80638098004311610097578063cf62c8ab11610066578063cf62c8ab14610242578063de367c8e14610255578063eff2701714610268578063f2fde38b1461027b57600080fd5b806380980043146101ab5780638da5cb5b146101be5780638ea98117146101cf578063a168fa89146101e257600080fd5b80635d7d53e3116100d35780635d7d53e314610166578063706da1ca1461016f5780637725135b1461017857806379ba5097146101a357600080fd5b80631fe543e31461010557806329e5d8311461011a5780632fa4e4421461014057806336bfffed14610153575b600080fd5b610118610113366004610e4e565b61028e565b005b61012d610128366004610ef2565b6102fa565b6040519081526020015b60405180910390f35b61011861014e366004610f7f565b610410565b610118610161366004610d5b565b6104bc565b61012d60045481565b61012d60065481565b60035461018b906001600160a01b031681565b6040516001600160a01b039091168152602001610137565b6101186105c0565b6101186101b9366004610e1c565b600655565b6000546001600160a01b031661018b565b6101186101dd366004610d39565b61067e565b61021d6101f0366004610e1c565b6007602052600090815260409020805460019091015460ff82169161010090046001600160a01b03169083565b6040805193151584526001600160a01b03909216602084015290820152606001610137565b610118610250366004610f7f565b61073d565b60055461018b906001600160a01b031681565b610118610276366004610f14565b610880565b610118610289366004610d39565b610a51565b6002546001600160a01b031633146102ec576002546040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b6102f68282610a65565b5050565b60008281526007602090815260408083208151608081018352815460ff81161515825261010090046001600160a01b0316818501526001820154818401526002820180548451818702810187019095528085528695929460608601939092919083018282801561038957602002820191906000526020600020905b815481526020019060010190808311610375575b50505050508152505090508060400151600014156103e95760405162461bcd60e51b815260206004820152601760248201527f7265717565737420494420697320696e636f727265637400000000000000000060448201526064016102e3565b806060015183815181106103ff576103ff61111c565b602002602001015191505092915050565b6003546002546006546040805160208101929092526001600160a01b0393841693634000aea09316918591015b6040516020818303038152906040526040518463ffffffff1660e01b815260040161046a93929190610ffa565b602060405180830381600087803b15801561048457600080fd5b505af1158015610498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f69190610dff565b60065461050b5760405162461bcd60e51b815260206004820152600d60248201527f7375624944206e6f74207365740000000000000000000000000000000000000060448201526064016102e3565b60005b81518110156102f65760055460065483516001600160a01b039092169163bec4c08c91908590859081106105445761054461111c565b60200260200101516040518363ffffffff1660e01b815260040161057b9291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b15801561059557600080fd5b505af11580156105a9573d6000803e3d6000fd5b5050505080806105b8906110f3565b91505061050e565b6001546001600160a01b0316331461061a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102e3565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b031633148015906106a457506002546001600160a01b03163314155b1561070e57336106bc6000546001600160a01b031690565b6002546040517f061db9c10000000000000000000000000000000000000000000000000000000081526001600160a01b03938416600482015291831660248301529190911660448201526064016102e3565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60065461041057600560009054906101000a90046001600160a01b03166001600160a01b031663a21a23e46040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561079457600080fd5b505af11580156107a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cc9190610e35565b60068190556005546040517fbec4c08c00000000000000000000000000000000000000000000000000000000815260048101929092523060248301526001600160a01b03169063bec4c08c90604401600060405180830381600087803b15801561083557600080fd5b505af1158015610849573d6000803e3d6000fd5b505050506003546002546006546040516001600160a01b0393841693634000aea0931691859161043d919060200190815260200190565b60006040518060c0016040528084815260200160065481526020018661ffff1681526020018763ffffffff1681526020018563ffffffff1681526020016108d66040518060200160405280861515815250610af8565b90526002546040517f9b1c385e0000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b0390911690639b1c385e90610927908590600401611039565b602060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109799190610e35565b604080516080810182526000808252336020808401918252838501868152855184815280830187526060860190815287855260078352959093208451815493517fffffffffffffffffffffff0000000000000000000000000000000000000000009094169015157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16176101006001600160a01b039094169390930292909217825591516001820155925180519495509193849392610a3f926002850192910190610ca9565b50505060049190915550505050505050565b610a59610b96565b610a6281610bf2565b50565b6004548214610ab65760405162461bcd60e51b815260206004820152601760248201527f7265717565737420494420697320696e636f727265637400000000000000000060448201526064016102e3565b60008281526007602090815260409091208251610adb92600290920191840190610ca9565b50506000908152600760205260409020805460ff19166001179055565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401610b3191511515815260200190565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b6000546001600160a01b03163314610bf05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e3565b565b6001600160a01b038116331415610c4b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e3565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610ce4579160200282015b82811115610ce4578251825591602001919060010190610cc9565b50610cf0929150610cf4565b5090565b5b80821115610cf05760008155600101610cf5565b80356001600160a01b0381168114610d2057600080fd5b919050565b803563ffffffff81168114610d2057600080fd5b600060208284031215610d4b57600080fd5b610d5482610d09565b9392505050565b60006020808385031215610d6e57600080fd5b823567ffffffffffffffff811115610d8557600080fd5b8301601f81018513610d9657600080fd5b8035610da9610da4826110cf565b61109e565b80828252848201915084840188868560051b8701011115610dc957600080fd5b600094505b83851015610df357610ddf81610d09565b835260019490940193918501918501610dce565b50979650505050505050565b600060208284031215610e1157600080fd5b8151610d5481611148565b600060208284031215610e2e57600080fd5b5035919050565b600060208284031215610e4757600080fd5b5051919050565b60008060408385031215610e6157600080fd5b8235915060208084013567ffffffffffffffff811115610e8057600080fd5b8401601f81018613610e9157600080fd5b8035610e9f610da4826110cf565b80828252848201915084840189868560051b8701011115610ebf57600080fd5b600094505b83851015610ee2578035835260019490940193918501918501610ec4565b5080955050505050509250929050565b60008060408385031215610f0557600080fd5b50508035926020909101359150565b600080600080600060a08688031215610f2c57600080fd5b610f3586610d25565b9450602086013561ffff81168114610f4c57600080fd5b9350610f5a60408701610d25565b9250606086013591506080860135610f7181611148565b809150509295509295909350565b600060208284031215610f9157600080fd5b81356bffffffffffffffffffffffff81168114610d5457600080fd5b6000815180845260005b81811015610fd357602081850181015186830182015201610fb7565b81811115610fe5576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03841681526bffffffffffffffffffffffff831660208201526060604082015260006110306060830184610fad565b95945050505050565b60208152815160208201526020820151604082015261ffff60408301511660608201526000606083015163ffffffff80821660808501528060808601511660a0850152505060a083015160c08084015261109660e0840182610fad565b949350505050565b604051601f8201601f1916810167ffffffffffffffff811182821017156110c7576110c7611132565b604052919050565b600067ffffffffffffffff8211156110e9576110e9611132565b5060051b60200190565b600060001982141561111557634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610a6257600080fdfea164736f6c6343000806000a"; + + BlockhashStore s_bhs; + ExposedVRFCoordinatorV2_5 s_testCoordinator; + ExposedVRFCoordinatorV2_5 s_testCoordinator_noLink; + VRFV2PlusConsumerExample s_testConsumer; + MockLinkToken s_linkToken; + MockV3Aggregator s_linkNativeFeed; + + // VRF KeyV2 generated from a node; not sensitive information. + // The secret key used to generate this key is: 10. + bytes vrfUncompressedPublicKey = + hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; + bytes vrfCompressedPublicKey = hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; + bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(LINK_WHALE, 10_000 ether); + changePrank(LINK_WHALE); + + vm.txGasPrice(100 gwei); + + // Instantiate BHS. + s_bhs = new BlockhashStore(); + + // Deploy coordinator and consumer. + // Note: adding contract deployments to this section will require the VRF proofs be regenerated. + s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(s_bhs)); + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Use create2 to deploy our consumer, so that its address is always the same + // and surrounding changes do not alter our generated proofs. + bytes memory consumerInitCode = bytes.concat( + initializeCode, + abi.encode(address(s_testCoordinator), address(s_linkToken)) + ); + bytes32 abiEncodedOwnerAddress = bytes32(uint256(uint160(LINK_WHALE)) << 96); + address consumerCreate2Address; + assembly { + consumerCreate2Address := create2( + 0, // value - left at zero here + add(0x20, consumerInitCode), // initialization bytecode (excluding first memory slot which contains its length) + mload(consumerInitCode), // length of initialization bytecode + abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses + ) + } + s_testConsumer = VRFV2PlusConsumerExample(consumerCreate2Address); + + s_testCoordinator_noLink = new ExposedVRFCoordinatorV2_5(address(s_bhs)); + + // Configure the coordinator. + s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + } + + function setConfig() internal { + s_testCoordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function testSetConfig() public { + // Should setConfig successfully. + setConfig(); + + // Test that setting requestConfirmations above MAX_REQUEST_CONFIRMATIONS reverts. + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidRequestConfirmations.selector, 500, 500, 200)); + s_testCoordinator.setConfig( + 500, + 2_500_000, + 1, + 50_000, + 50000000000000000, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + + // Test that setting fallbackWeiPerUnitLink to zero reverts. + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidLinkWeiPrice.selector, 0)); + + s_testCoordinator.setConfig( + 0, + 2_500_000, + 1, + 50_000, + 0, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + + // Test that setting link discount flat fee higher than native flat fee reverts + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.LinkDiscountTooHigh.selector, uint32(501), uint32(500))); + + s_testCoordinator.setConfig( + 0, + 2_500_000, + 1, + 50_000, + 500, + 500, // fulfillmentFlatFeeNativePPM + 501, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + + // // Test that setting link discount flat fee equal to native flat fee does not revert + s_testCoordinator.setConfig( + 0, + 2_500_000, + 1, + 50_000, + 500, + 450, // fulfillmentFlatFeeNativePPM + 450, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + + // Test that setting native premium percentage higher than 155 will revert + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155)) + ); + + s_testCoordinator.setConfig( + 0, + 2_500_000, + 1, + 50_000, + 500, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 156, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + + // Test that setting LINK premium percentage higher than 155 will revert + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155)) + ); + + s_testCoordinator.setConfig( + 0, + 2_500_000, + 1, + 50_000, + 500, + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 202 // linkPremiumPercentage + ); + } + + function testRegisterProvingKey() public { + // Should set the proving key successfully. + registerProvingKey(); + + // Should revert when already registered. + uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.ProvingKeyAlreadyRegistered.selector, vrfKeyHash)); + s_testCoordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + } + + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); + event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); + + function registerProvingKey() public { + uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); + bytes32 keyHash = keccak256(abi.encode(uncompressedKeyParts)); + vm.expectEmit( + false, // no indexed args to check for + false, // no indexed args to check for + false, // no indexed args to check for + true + ); // check data fields: keyHash and maxGas + emit ProvingKeyRegistered(keyHash, GAS_LANE_MAX_GAS); + s_testCoordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); + (bool exists, uint64 maxGas) = s_testCoordinator.s_provingKeys(keyHash); + assertTrue(exists); + assertEq(GAS_LANE_MAX_GAS, maxGas); + assertEq(s_testCoordinator.s_provingKeyHashes(0), keyHash); + assertEq(keyHash, vrfKeyHash); + } + + function testDeregisterProvingKey() public { + // Should set the proving key successfully. + registerProvingKey(); + + bytes + memory unregisteredPubKey = hex"6d919e4ed6add6c34b2af77eb6b2d2f5d27db11ba004e70734b23bd4321ea234ff8577a063314bead6d88c1b01849289a5542767a5138924f38fed551a7773db"; + + // Should revert when given pubkey is not registered + uint256[2] memory unregisteredKeyParts = this.getProvingKeyParts(unregisteredPubKey); + bytes32 unregisterdKeyHash = keccak256(abi.encode(unregisteredKeyParts)); + vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.NoSuchProvingKey.selector, unregisterdKeyHash)); + s_testCoordinator.deregisterProvingKey(unregisteredKeyParts); + + // correctly deregister pubkey + uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); + bytes32 keyHash = keccak256(abi.encode(uncompressedKeyParts)); + vm.expectEmit( + false, // no indexed args to check for + false, // no indexed args to check for + false, // no indexed args to check for + true + ); // check data fields: keyHash and maxGas + emit ProvingKeyDeregistered(keyHash, GAS_LANE_MAX_GAS); + s_testCoordinator.deregisterProvingKey(uncompressedKeyParts); + (bool exists, uint64 maxGas) = s_testCoordinator.s_provingKeys(keyHash); + assertFalse(exists); + assertEq(0, maxGas); + } + + // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and + // index over the byte array. + function getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { + uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); + uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); + return [keyPart1, keyPart2]; + } + + function testCreateSubscription() public { + uint256 subId = s_testCoordinator.createSubscription(); + s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); + } + + function testCancelSubWithNoLink() public { + uint256 subId = s_testCoordinator_noLink.createSubscription(); + s_testCoordinator_noLink.fundSubscriptionWithNative{value: 1000 ether}(subId); + + assertEq(LINK_WHALE.balance, 9000 ether); + s_testCoordinator_noLink.cancelSubscription(subId, LINK_WHALE); + assertEq(LINK_WHALE.balance, 10_000 ether); + + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_testCoordinator_noLink.getSubscription(subId); + } + + function testGetActiveSubscriptionIds() public { + uint numSubs = 40; + for (uint i = 0; i < numSubs; i++) { + s_testCoordinator.createSubscription(); + } + // get all subscriptions, assert length is correct + uint256[] memory allSubs = s_testCoordinator.getActiveSubscriptionIds(0, 0); + assertEq(allSubs.length, s_testCoordinator.getActiveSubscriptionIdsLength()); + + // paginate through subscriptions, batching by 10. + // we should eventually get all the subscriptions this way. + uint256[][] memory subIds = paginateSubscriptions(s_testCoordinator, 10); + // check that all subscriptions were returned + uint actualNumSubs = 0; + for (uint batchIdx = 0; batchIdx < subIds.length; batchIdx++) { + for (uint subIdx = 0; subIdx < subIds[batchIdx].length; subIdx++) { + s_testCoordinator.getSubscription(subIds[batchIdx][subIdx]); + actualNumSubs++; + } + } + assertEq(actualNumSubs, s_testCoordinator.getActiveSubscriptionIdsLength()); + + // cancel a bunch of subscriptions, assert that they are not returned + uint256[] memory subsToCancel = new uint256[](3); + for (uint i = 0; i < 3; i++) { + subsToCancel[i] = subIds[0][i]; + } + for (uint i = 0; i < subsToCancel.length; i++) { + s_testCoordinator.cancelSubscription(subsToCancel[i], LINK_WHALE); + } + uint256[][] memory newSubIds = paginateSubscriptions(s_testCoordinator, 10); + // check that all subscriptions were returned + // and assert that none of the canceled subscriptions are returned + actualNumSubs = 0; + for (uint batchIdx = 0; batchIdx < newSubIds.length; batchIdx++) { + for (uint subIdx = 0; subIdx < newSubIds[batchIdx].length; subIdx++) { + for (uint i = 0; i < subsToCancel.length; i++) { + assertFalse(newSubIds[batchIdx][subIdx] == subsToCancel[i]); + } + s_testCoordinator.getSubscription(newSubIds[batchIdx][subIdx]); + actualNumSubs++; + } + } + assertEq(actualNumSubs, s_testCoordinator.getActiveSubscriptionIdsLength()); + } + + function paginateSubscriptions( + ExposedVRFCoordinatorV2_5 coordinator, + uint256 batchSize + ) internal view returns (uint256[][] memory) { + uint arrIndex = 0; + uint startIndex = 0; + uint256 numSubs = coordinator.getActiveSubscriptionIdsLength(); + uint256[][] memory subIds = new uint256[][](Math.ceilDiv(numSubs, batchSize)); + while (startIndex < numSubs) { + subIds[arrIndex] = coordinator.getActiveSubscriptionIds(startIndex, batchSize); + startIndex += batchSize; + arrIndex++; + } + return subIds; + } + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + event RandomWordsFulfilled( + uint256 indexed requestId, + uint256 outputSeed, + uint256 indexed subID, + uint96 payment, + bytes extraArgs, + bool success + ); + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + + function testRequestAndFulfillRandomWordsNative() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256 subId, + uint256 requestId + ) = setupSubAndRequestRandomnessNativePayment(); + (, uint96 nativeBalanceBefore, , , ) = s_testCoordinator.getSubscription(subId); + + uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; + vm.recordLogs(); + uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, false); + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries[0].topics[1], bytes32(uint256(requestId))); + assertEq(entries[0].topics[2], bytes32(uint256(subId))); + (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); + assertEq(loggedOutputSeed, outputSeed); + assertEq(loggedSuccess, true); + + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, true); + + // The cost of fulfillRandomWords is approximately 70_000 gas. + // gasAfterPaymentCalculation is 50_000. + // + // The cost of the VRF fulfillment charged to the user is: + // baseFeeWei = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + // baseFeeWei = 1e11 * (50_000 + 70_000) + // baseFeeWei = 1.2e16 + // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM) + // flatFeeWei = 1e12 * 500_000 = 5e17 + // ... + // billed_fee = baseFeeWei * (100 + linkPremiumPercentage / 100) + 5e17 + // billed_fee = 1.2e16 * 1.15 + 5e17 + // billed_fee = 5.138e+17 + (, uint96 nativeBalanceAfter, , , ) = s_testCoordinator.getSubscription(subId); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.138 * 1e17, 1e15); + assertApproxEqAbs(nativeBalanceAfter, nativeBalanceBefore - 5.138 * 1e17, 1e15); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestAndFulfillRandomWordsLINK() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256 subId, + uint256 requestId + ) = setupSubAndRequestRandomnessLINKPayment(); + (uint96 linkBalanceBefore, , , , ) = s_testCoordinator.getSubscription(subId); + + uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; + vm.recordLogs(); + uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, false); + + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries[0].topics[1], bytes32(uint256(requestId))); + assertEq(entries[0].topics[2], bytes32(uint256(subId))); + (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); + assertEq(loggedOutputSeed, outputSeed); + assertEq(loggedSuccess, true); + + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, true); + + // The cost of fulfillRandomWords is approximately 86_000 gas. + // gasAfterPaymentCalculation is 50_000. + // + // The cost of the VRF fulfillment charged to the user is: + // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) + // paymentNoFee = (1e11 * (50_000 + 86_000 + 0)) / .5 + // paymentNoFee = 2.72e16 + // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) + // flatFeeWei = 1e12 * (500_000 - 100_000) + // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio + // flatFeeJuels = 4e17 / 0.5 = 8e17 + // billed_fee = paymentNoFee * ((100 + 10) / 100) + 8e17 + // billed_fee = 2.72e16 * 1.1 + 8e17 + // billed_fee = 2.992e16 + 8e17 = 8.2992e17 + // note: delta is doubled from the native test to account for more variance due to the link/native ratio + (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 8.2992 * 1e17, 1e15); + assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 8.2992 * 1e17, 1e15); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestAndFulfillRandomWordsLINK_FallbackWeiPerUnitLinkUsed() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + , + uint256 requestId + ) = setupSubAndRequestRandomnessLINKPayment(); + + (, , , uint32 stalenessSeconds, , , , , ) = s_testCoordinator.s_config(); + int256 fallbackWeiPerUnitLink = s_testCoordinator.s_fallbackWeiPerUnitLink(); + + // Set the link feed to be stale. + (uint80 roundId, int256 answer, uint256 startedAt, , ) = s_linkNativeFeed.latestRoundData(); + uint256 timestamp = block.timestamp - stalenessSeconds - 1; + s_linkNativeFeed.updateRoundData(roundId, answer, timestamp, startedAt); + + vm.expectEmit(false, false, false, true, address(s_testCoordinator)); + emit FallbackWeiPerUnitLinkUsed(requestId, fallbackWeiPerUnitLink); + s_testCoordinator.fulfillRandomWords(proof, rc, false); + } + + function setupSubAndRequestRandomnessLINKPayment() + internal + returns (VRF.Proof memory proof, VRFTypes.RequestCommitmentV2Plus memory rc, uint256 subId, uint256 requestId) + { + uint32 requestBlock = 20; + vm.roll(requestBlock); + s_linkToken.transfer(address(s_testConsumer), 10 ether); + s_testConsumer.createSubscriptionAndFund(10 ether); + subId = s_testConsumer.s_subId(); + + // Apply basic configs to contract. + setConfig(); + registerProvingKey(); + + // Request random words. + vm.expectEmit(true, true, false, true); + uint256 preSeed; + (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(s_testConsumer), subId, 1); + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + subId, + MIN_CONFIRMATIONS, + CALLBACK_GAS_LIMIT, + NUM_WORDS, + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // nativePayment, // nativePayment + address(s_testConsumer) // requester + ); + s_testConsumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, vrfKeyHash, false); + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, false); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + + // Move on to the next block. + // Store the previous block's blockhash, and assert that it is as expected. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); + + // Fulfill the request. + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 77134414723242246520332717536018735794426514244521954002798799849127623496871 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ + -block-num 20 \ + -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ + -native-payment false + */ + proof = VRF.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 103927982338770370318312316555080928288985522873495041111817988974598585393796, + 56789421278806198480964888112155620425048056183534931202752833185923411715624 + ], + c: 23645475075665525321781505993434124657388421977074956645288621921391376468128, + s: 106817081950846808215350231311242951539230271757396902089035477907017240898689, + seed: 77134414723242246520332717536018735794426514244521954002798799849127623496871, + uWitness: 0xD6899602060d574DE03FE1cf76fDf66afE12d549, + cGammaWitness: [ + 9892458071712426452033749279561067220589549155902380165087951541202159693388, + 61235995320721681444549354910430438435754757626312862714628885100042911955139 + ], + sHashWitness: [ + 101478618362722903511580105256015180591690884037598276249676652094434483808775, + 82512235485399822034680598942438982472006937353405384896956013889074719896188 + ], + zInv: 82281039329215616805111360985152709712368762415186906218863971780664103705723 + }); + rc = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: subId, + callbackGasLimit: 1000000, + numWords: 1, + sender: address(s_testConsumer), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) + }); + return (proof, rc, subId, requestId); + } + + function setupSubAndRequestRandomnessNativePayment() + internal + returns (VRF.Proof memory proof, VRFTypes.RequestCommitmentV2Plus memory rc, uint256 subId, uint256 requestId) + { + uint32 requestBlock = 10; + vm.roll(requestBlock); + s_testConsumer.createSubscriptionAndFund(0); + subId = s_testConsumer.s_subId(); + s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); + + // Apply basic configs to contract. + setConfig(); + registerProvingKey(); + + // Request random words. + vm.expectEmit(true, true, true, true); + uint256 preSeed; + (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(s_testConsumer), subId, 1); + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + subId, + MIN_CONFIRMATIONS, + CALLBACK_GAS_LIMIT, + NUM_WORDS, + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), // nativePayment + address(s_testConsumer) // requester + ); + s_testConsumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, vrfKeyHash, true); + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, false); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + + // Move on to the next block. + // Store the previous block's blockhash, and assert that it is as expected. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); + + // Fulfill the request. + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 88177119495082281213609405072572269421661478022189589823108119237563684383163 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ + -block-num 10 \ + -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ + -native-payment true + */ + proof = VRF.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 102142782721757938350759722545721736888276217484353597703162772276193136052353, + 87167280284008869627768921028415708350806510214000539818296353518495698939660 + ], + c: 78738462581063211677832865654743924688552792392007862664964608134754001810280, + s: 97066881804257970453329086439696419448135613089654606517271688187030953014593, + seed: 88177119495082281213609405072572269421661478022189589823108119237563684383163, + uWitness: 0xa335ea8dF652d5331a276B60b16c9733435D4f73, + cGammaWitness: [ + 114435126227922602743444254494036972095649501991695809092954325430947992864624, + 63032211040463927862594425238691911311087931119674607521158894139074063158678 + ], + sHashWitness: [ + 105043781471073183057173130563345930784924139079040814418442661347864735908726, + 68696469914696211053833437482938344908217760552761185546164836556562945431554 + ], + zInv: 73325637847357165955904789471972164751975373195750497508525598331798833112175 + }); + rc = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: 1, + sender: address(s_testConsumer), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + + return (proof, rc, subId, requestId); + } + + function testRequestAndFulfillRandomWords_NetworkGasPriceExceedsGasLane() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + , + + ) = setupSubAndRequestRandomnessNativePayment(); + + // network gas is higher than gas lane max gas + uint256 networkGasPrice = GAS_LANE_MAX_GAS + 1; + vm.txGasPrice(networkGasPrice); + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.GasPriceExceeded.selector, networkGasPrice, GAS_LANE_MAX_GAS) + ); + s_testCoordinator.fulfillRandomWords(proof, rc, false); + } + + function testRequestAndFulfillRandomWords_OnlyPremium_NativePayment() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256 subId, + uint256 requestId + ) = setupSubAndRequestRandomnessNativePayment(); + (, uint96 nativeBalanceBefore, , , ) = s_testCoordinator.getSubscription(subId); + + // network gas is twice the gas lane max gas + uint256 networkGasPrice = GAS_LANE_MAX_GAS * 2; + vm.txGasPrice(networkGasPrice); + + uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; + vm.recordLogs(); + uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries[0].topics[1], bytes32(uint256(requestId))); + assertEq(entries[0].topics[2], bytes32(uint256(subId))); + (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); + assertEq(loggedOutputSeed, outputSeed); + assertEq(loggedSuccess, true); + + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, true); + + // The cost of fulfillRandomWords is approximately 72_100 gas. + // gasAfterPaymentCalculation is 50_000. + // + // The cost of the VRF fulfillment charged to the user is: + // baseFeeWei = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + // network gas price is capped at gas lane max gas (5000 gwei) + // baseFeeWei = 5e12 * (50_000 + 72_100) + // baseFeeWei = 6.11e17 + // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM) + // flatFeeWei = 1e12 * 500_000 = 5e17 + // ... + // billed_fee = baseFeeWei * (linkPremiumPercentage / 100) + 5e17 + // billed_fee = 6.11e17 * 0.15 + 5e17 + // billed_fee = 5.9157e+17 + (, uint96 nativeBalanceAfter, , , ) = s_testCoordinator.getSubscription(subId); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 5.9157 * 1e17, 1e15); + assertApproxEqAbs(nativeBalanceAfter, nativeBalanceBefore - 5.9157 * 1e17, 1e15); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestAndFulfillRandomWords_OnlyPremium_LinkPayment() public { + ( + VRF.Proof memory proof, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256 subId, + uint256 requestId + ) = setupSubAndRequestRandomnessLINKPayment(); + (uint96 linkBalanceBefore, , , , ) = s_testCoordinator.getSubscription(subId); + + // network gas is twice the gas lane max gas + uint256 networkGasPrice = GAS_LANE_MAX_GAS * 5; + vm.txGasPrice(networkGasPrice); + + uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; + vm.recordLogs(); + uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); + + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries[0].topics[1], bytes32(uint256(requestId))); + assertEq(entries[0].topics[2], bytes32(uint256(subId))); + (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); + assertEq(loggedOutputSeed, outputSeed); + assertEq(loggedSuccess, true); + + (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); + assertEq(fulfilled, true); + + // The cost of fulfillRandomWords is approximately 89_100 gas. + // gasAfterPaymentCalculation is 50_000. + // + // The cost of the VRF fulfillment charged to the user is: + // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) + // network gas price is capped at gas lane max gas (5000 gwei) + // paymentNoFee = (5e12 * (50_000 + 89_100 + 0)) / .5 + // paymentNoFee = 1.391e+18 + // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) + // flatFeeWei = 1e12 * (500_000 - 100_000) + // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio + // flatFeeJuels = 4e17 / 0.5 = 8e17 + // billed_fee = paymentNoFee * (10 / 100) + 8e17 + // billed_fee = 1.391e+18 * 0.1 + 8e17 + // billed_fee = 9.391e+17 + // note: delta is doubled from the native test to account for more variance due to the link/native ratio + (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(payment, 9.391 * 1e17, 1e15); + assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.391 * 1e17, 1e15); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestRandomWords_InvalidConsumer() public { + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint256 subId = s_testCoordinator.createSubscription(); + VRFV2PlusLoadTestWithMetrics consumer = new VRFV2PlusLoadTestWithMetrics(address(s_testCoordinator)); + + // consumer is not added to the subscription + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); + consumer.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + true, + NUM_WORDS, + 1 /* requestCount */ + ); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestRandomWords_ReAddConsumer_AssertRequestID() public { + // 1. setup consumer and subscription + setConfig(); + registerProvingKey(); + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint256 subId = s_testCoordinator.createSubscription(); + VRFV2PlusLoadTestWithMetrics consumer = createAndAddLoadTestWithMetricsConsumer(subId); + uint32 requestBlock = 10; + vm.roll(requestBlock); + changePrank(LINK_WHALE); + s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); + + // 2. Request random words. + changePrank(subOwner); + vm.expectEmit(true, true, false, true); + uint256 requestId; + uint256 preSeed; + (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(consumer), subId, 1); + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + subId, + MIN_CONFIRMATIONS, + CALLBACK_GAS_LIMIT, + NUM_WORDS, + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), + address(consumer) // requester + ); + consumer.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + true /* nativePayment */, + NUM_WORDS, + 1 /* requestCount */ + ); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + + // Move on to the next block. + // Store the previous block's blockhash, and assert that it is as expected. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); + + // 3. Fulfill the request above + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ + -block-num 10 \ + -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ + -native-payment true + */ + VRF.Proof memory proof = VRF.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 + ], + c: 96524997218413735279221574381819903278651909890109201564980667824986706861580, + s: 32941032142956097592442894642111025677491308239274769364799856748447418202313, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0xda613621Dc2347d9A6670a1cBA812d52A7ec3A3A, + cGammaWitness: [ + 6776842114900054689355891239487365968068230823400902903493665825747641410781, + 753482930067864853610521010650481816782338376846697006021590704037205560592 + ], + sHashWitness: [ + 76619528582417858778905184311764104068650968652636772643050945629834129417915, + 27947566794040118487986033070014357750801611688958204148187927873566412002355 + ], + zInv: 77351076831418813780936064446565588198113457019145030499544500588309236458362 + }); + VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: NUM_WORDS, + sender: address(consumer), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + + // 4. remove consumer and verify request random words doesn't work + s_testCoordinator.removeConsumer(subId, address(consumer)); + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); + consumer.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + false /* nativePayment */, + NUM_WORDS, + 1 /* requestCount */ + ); + + // 5. re-add consumer and assert requestID nonce starts from 2 (nonce 1 was used before consumer removal) + s_testCoordinator.addConsumer(subId, address(consumer)); + vm.expectEmit(true, true, false, true); + uint256 requestId2; + uint256 preSeed2; + (requestId2, preSeed2) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(consumer), subId, 2); + emit RandomWordsRequested( + vrfKeyHash, + requestId2, + preSeed2, + subId, + MIN_CONFIRMATIONS, + CALLBACK_GAS_LIMIT, + NUM_WORDS, + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // nativePayment, // nativePayment + address(consumer) // requester + ); + consumer.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + false /* nativePayment */, + NUM_WORDS, + 1 /* requestCount */ + ); + assertNotEq(requestId, requestId2); + assertNotEq(preSeed, preSeed2); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + } + + function testRequestRandomWords_MultipleConsumers_PendingRequestExists() public { + // 1. setup consumer and subscription + setConfig(); + registerProvingKey(); + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint256 subId = s_testCoordinator.createSubscription(); + VRFV2PlusLoadTestWithMetrics consumer1 = createAndAddLoadTestWithMetricsConsumer(subId); + VRFV2PlusLoadTestWithMetrics consumer2 = createAndAddLoadTestWithMetricsConsumer(subId); + uint32 requestBlock = 10; + vm.roll(requestBlock); + changePrank(LINK_WHALE); + s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); + + // 2. Request random words. + changePrank(subOwner); + (uint256 requestId1, uint256 preSeed1) = s_testCoordinator.computeRequestIdExternal( + vrfKeyHash, + address(consumer1), + subId, + 1 + ); + (uint256 requestId2, uint256 preSeed2) = s_testCoordinator.computeRequestIdExternal( + vrfKeyHash, + address(consumer2), + subId, + 1 + ); + assertNotEq(requestId1, requestId2); + assertNotEq(preSeed1, preSeed2); + consumer1.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + true /* nativePayment */, + NUM_WORDS, + 1 /* requestCount */ + ); + consumer2.requestRandomWords( + subId, + MIN_CONFIRMATIONS, + vrfKeyHash, + CALLBACK_GAS_LIMIT, + true /* nativePayment */, + NUM_WORDS, + 1 /* requestCount */ + ); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + + // Move on to the next block. + // Store the previous block's blockhash, and assert that it is as expected. + vm.roll(requestBlock + 1); + s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); + + // 3. Fulfill the 1st request above + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ + -block-num 10 \ + -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ + -native-payment true + */ + VRF.Proof memory proof = VRF.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 + ], + c: 103296526941774692908067234360350834482645116475454593803823148315342533216203, + s: 50291245814080656739779812653411869801334231723444391096753849942661931376590, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0x38500711AdcB471ac1A566c4b915759eb9cBCE2F, + cGammaWitness: [ + 56476970720509547210740928951846471668018949971632948991136782499758110143588, + 44326075300781389077656415325167171692706436527877070415603658305817367373598 + ], + sHashWitness: [ + 109524696164787283409393383708118913934136014139634321235031691839206768278439, + 52690039857779635909051684567562068782378693408005554345469129234366171822741 + ], + zInv: 108537983043800425266290112227943788107669768716438017124275578856644517258573 + }); + VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: NUM_WORDS, + sender: address(consumer1), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); + assertTrue(s_testCoordinator.pendingRequestExists(subId)); + + // 4. Fulfill the 2nd request + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. + /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet + go run . generate-proof-v2-plus \ + -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ + -pre-seed 53330100288105770463016865504321558518073051667771993294213115153676065708950 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ + -block-num 10 \ + -sender 0xf5a165378E120f93784395aDF1E08a437e902865 \ + -native-payment true + */ + proof = VRF.Proof({ + pk: [ + 72488970228380509287422715226575535698893157273063074627791787432852706183111, + 62070622898698443831883535403436258712770888294397026493185421712108624767191 + ], + gamma: [ + 7260273098301741284457725182313945178888499328441106869722941415453613782770, + 91648498042618923465107471165504200585847250228048015102713552756245653299952 + ], + c: 64987886290696558870328339791409334400119338012796549091587853494368167422332, + s: 69469162696695326295567645789624554797683340898724555794078876350372084267572, + seed: 53330100288105770463016865504321558518073051667771993294213115153676065708950, + uWitness: 0xa6ce21aD47eC5E90Ac7a2c6152D9710234Afe8ab, + cGammaWitness: [ + 57318358662553647785891634403735348577492991113152343207139729697842283565417, + 57942043484796308689103390068712967247519265087617809262260051163954389512396 + ], + sHashWitness: [ + 113345999157319332195230171660555736547709417795439282230372737104445523493539, + 113358219039155973560933190466797830695088313506343976960055230355894888727567 + ], + zInv: 68349552569605209428774574139615352877146713490794995768725549089572297658255 + }); + rc = VRFTypes.RequestCommitmentV2Plus({ + blockNum: requestBlock, + subId: subId, + callbackGasLimit: CALLBACK_GAS_LIMIT, + numWords: NUM_WORDS, + sender: address(consumer2), + extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) + }); + s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); + assertFalse(s_testCoordinator.pendingRequestExists(subId)); + } + + function createAndAddLoadTestWithMetricsConsumer(uint256 subId) internal returns (VRFV2PlusLoadTestWithMetrics) { + VRFV2PlusLoadTestWithMetrics consumer = new VRFV2PlusLoadTestWithMetrics(address(s_testCoordinator)); + s_testCoordinator.addConsumer(subId, address(consumer)); + return consumer; + } + + function test_RemoveConsumer() public { + uint256 subId = s_testCoordinator.createSubscription(); + uint256 consumersLength = s_testCoordinator.MAX_CONSUMERS(); + address[] memory consumers = getRandomAddresses(consumersLength); + for (uint256 i = 0; i < consumersLength; ++i) { + s_testCoordinator.addConsumer(subId, consumers[i]); + } + + // test remove consumers from multiple positions to have better gas distribution + address earlyConsumerAddress = consumers[0]; + s_testCoordinator.removeConsumer(subId, earlyConsumerAddress); + (, , , , consumers) = s_testCoordinator.getSubscription(subId); + assertEq(consumers.length, consumersLength - 1); + assertFalse(addressIsIn(earlyConsumerAddress, consumers)); + + consumersLength = consumers.length; + address middleConsumerAddress = consumers[consumersLength / 2]; + s_testCoordinator.removeConsumer(subId, middleConsumerAddress); + (, , , , consumers) = s_testCoordinator.getSubscription(subId); + assertEq(consumers.length, consumersLength - 1); + assertFalse(addressIsIn(middleConsumerAddress, consumers)); + + consumersLength = consumers.length; + address lateConsumerAddress = consumers[consumersLength - 1]; + s_testCoordinator.removeConsumer(subId, lateConsumerAddress); + (, , , , consumers) = s_testCoordinator.getSubscription(subId); + assertEq(consumers.length, consumersLength - 1); + assertFalse(addressIsIn(lateConsumerAddress, consumers)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol new file mode 100644 index 0000000..4fbb44e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol @@ -0,0 +1,649 @@ +pragma solidity 0.8.19; + +import "./BaseTest.t.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; // for Strings.toString +import {VmSafe} from "forge-std/Vm.sol"; + +contract VRFV2PlusSubscriptionAPITest is BaseTest { + event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); + event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); + event FundsRecovered(address to, uint256 amountLink); + event NativeFundsRecovered(address to, uint256 amountNative); + event SubscriptionOwnerTransferRequested(uint256 indexed subId, address from, address to); + event SubscriptionOwnerTransferred(uint256 indexed subId, address from, address to); + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); + + ExposedVRFCoordinatorV2_5 s_subscriptionAPI; + + function setUp() public override { + BaseTest.setUp(); + address bhs = makeAddr("bhs"); + s_subscriptionAPI = new ExposedVRFCoordinatorV2_5(bhs); + } + + function testDefaultState() public { + assertEq(address(s_subscriptionAPI.LINK()), address(0)); + assertEq(address(s_subscriptionAPI.LINK_NATIVE_FEED()), address(0)); + assertEq(s_subscriptionAPI.s_currentSubNonce(), 0); + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); + assertEq(s_subscriptionAPI.s_totalBalance(), 0); + assertEq(s_subscriptionAPI.s_totalNativeBalance(), 0); + } + + function testSetLINKAndLINKNativeFeed() public { + address link = makeAddr("link"); + address linkNativeFeed = makeAddr("linkNativeFeed"); + s_subscriptionAPI.setLINKAndLINKNativeFeed(link, linkNativeFeed); + assertEq(address(s_subscriptionAPI.LINK()), link); + assertEq(address(s_subscriptionAPI.LINK_NATIVE_FEED()), linkNativeFeed); + + // try setting it again, should revert + vm.expectRevert(SubscriptionAPI.LinkAlreadySet.selector); + s_subscriptionAPI.setLINKAndLINKNativeFeed(link, linkNativeFeed); + } + + function testOwnerCancelSubscriptionNoFunds() public { + // CASE: new subscription w/ no funds at all + // Should cancel trivially + + // Note that the link token is not set, but this should still + // not fail in that case. + + // Create the subscription from a separate address + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // change back to owner and cancel the subscription + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, subOwner, 0, 0); + s_subscriptionAPI.ownerCancelSubscription(subId); + + // assert that the subscription no longer exists + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); + // no point in checking s_subscriptions because all fields are zeroed out + // due to no balance and no requests made + } + + function testOwnerCancelSubscriptionNativeFundsOnly() public { + // CASE: new subscription with native funds only + // no link funds. + // should cancel and return the native funds + + // Create the subscription from a separate address + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with ether + vm.deal(subOwner, 10 ether); + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, 5 ether); + s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); + + // change back to owner and cancel the subscription + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, subOwner, 0 /* link balance */, 5 ether /* native balance */); + s_subscriptionAPI.ownerCancelSubscription(subId); + + // assert that the subscription no longer exists + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 0); + + // check the native balance of the subOwner, should be 10 ether + assertEq(address(subOwner).balance, 10 ether); + } + + function testOwnerCancelSubscriptionLinkFundsOnly() public { + // CASE: new subscription with link funds only + // no native funds. + // should cancel and return the link funds + + // Create link token and set the link token on the subscription api object + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // Create the subscription from a separate address + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with link + // can do it from the owner acct because anyone can fund a subscription + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, 5 ether); + bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); + assertTrue(success, "failed link transfer and call"); + + // change back to owner and cancel the subscription + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, subOwner, 5 ether /* link balance */, 0 /* native balance */); + s_subscriptionAPI.ownerCancelSubscription(subId); + + // assert that the subscription no longer exists + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 0); + + // check the link balance of the sub owner, should be 5 LINK + assertEq(linkToken.balanceOf(subOwner), 5 ether); + } + + function testOwnerCancelSubscriptionNativeAndLinkFunds() public { + // CASE: new subscription with link and native funds + // should cancel and return both link and native funds + + // Create link token and set the link token on the subscription api object + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // Create the subscription from a separate address + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with link + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, 5 ether); + bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); + assertTrue(success, "failed link transfer and call"); + + // fund the subscription with ether + vm.deal(subOwner, 10 ether); + changePrank(subOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, 5 ether); + s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); + + // change back to owner and cancel the subscription + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionCanceled(subId, subOwner, 5 ether /* link balance */, 5 ether /* native balance */); + s_subscriptionAPI.ownerCancelSubscription(subId); + + // assert that the subscription no longer exists + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 0); + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 0); + + // check the link balance of the sub owner, should be 5 LINK + assertEq(linkToken.balanceOf(subOwner), 5 ether, "link balance incorrect"); + // check the ether balance of the sub owner, should be 10 ether + assertEq(address(subOwner).balance, 10 ether, "native balance incorrect"); + } + + function testRecoverFundsLINKNotSet() public { + // CASE: link token not set + // should revert with error LinkNotSet + + // call recoverFunds + vm.expectRevert(SubscriptionAPI.LinkNotSet.selector); + s_subscriptionAPI.recoverFunds(OWNER); + } + + function testRecoverFundsBalanceInvariantViolated() public { + // CASE: link token set + // and internal balance is greater than external balance + + // Create link token and set the link token on the subscription api object + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // set the total balance to be greater than the external balance + // so that we trigger the invariant violation + // note that this field is not modifiable in the actual contracts + // other than through onTokenTransfer or similar functions + s_subscriptionAPI.setTotalBalanceTestingOnlyXXX(100 ether); + + // call recoverFunds + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.BalanceInvariantViolated.selector, 100 ether, 0)); + s_subscriptionAPI.recoverFunds(OWNER); + } + + function testRecoverFundsAmountToTransfer() public { + // CASE: link token set + // and internal balance is less than external balance + // (i.e invariant is not violated) + // should recover funds successfully + + // Create link token and set the link token on the subscription api object + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // transfer 10 LINK to the contract to recover + bool success = linkToken.transfer(address(s_subscriptionAPI), 10 ether); + assertTrue(success, "failed link transfer"); + + // call recoverFunds + vm.expectEmit(true, false, false, true); + emit FundsRecovered(OWNER, 10 ether); + s_subscriptionAPI.recoverFunds(OWNER); + } + + function testRecoverFundsNothingToTransfer() public { + // CASE: link token set + // and there is nothing to transfer + // should do nothing at all + + // Create link token and set the link token on the subscription api object + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // create a subscription and fund it with 5 LINK + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with link + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, 5 ether); + bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); + assertTrue(success, "failed link transfer and call"); + + // call recoverFunds, nothing should happen because external balance == internal balance + s_subscriptionAPI.recoverFunds(OWNER); + assertEq(linkToken.balanceOf(address(s_subscriptionAPI)), s_subscriptionAPI.s_totalBalance()); + } + + function testRecoverNativeFundsBalanceInvariantViolated() public { + // set the total balance to be greater than the external balance + // so that we trigger the invariant violation + // note that this field is not modifiable in the actual contracts + // other than through onTokenTransfer or similar functions + s_subscriptionAPI.setTotalNativeBalanceTestingOnlyXXX(100 ether); + + // call recoverFunds + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.BalanceInvariantViolated.selector, 100 ether, 0)); + s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); + } + + function testRecoverNativeFundsAmountToTransfer() public { + // transfer 10 LINK to the contract to recover + vm.deal(address(s_subscriptionAPI), 10 ether); + + // call recoverFunds + vm.expectEmit(true, false, false, true); + emit NativeFundsRecovered(OWNER, 10 ether); + s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); + } + + function testRecoverNativeFundsNothingToTransfer() public { + // create a subscription and fund it with 5 ether + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with ether + vm.deal(subOwner, 5 ether); + changePrank(subOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, 5 ether); + s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); + + // call recoverNativeFunds, nothing should happen because external balance == internal balance + changePrank(OWNER); + s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); + assertEq(address(s_subscriptionAPI).balance, s_subscriptionAPI.s_totalNativeBalance()); + } + + function testWithdrawNoLink() public { + // CASE: no link token set + vm.expectRevert(SubscriptionAPI.LinkNotSet.selector); + s_subscriptionAPI.withdraw(OWNER); + } + + function testWithdrawInsufficientBalance() public { + // CASE: link token set, trying to withdraw + // more than balance + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // call withdraw + vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); + s_subscriptionAPI.withdraw(OWNER); + } + + function testWithdrawSufficientBalanceLinkSet() public { + // CASE: link token set, trying to withdraw + // less than balance + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // transfer 10 LINK to the contract to withdraw + bool success = linkToken.transfer(address(s_subscriptionAPI), 10 ether); + assertTrue(success, "failed link transfer"); + + // set the withdrawable tokens of the contract to be 1 ether + s_subscriptionAPI.setWithdrawableTokensTestingOnlyXXX(1 ether); + assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 1 ether); + + // set the total balance to be the same as the link balance for consistency + // (this is not necessary for the test, but just to be sane) + s_subscriptionAPI.setTotalBalanceTestingOnlyXXX(10 ether); + + // call Withdraw from owner address + uint256 ownerBalance = linkToken.balanceOf(OWNER); + changePrank(OWNER); + s_subscriptionAPI.withdraw(OWNER); + // assert link balance of owner + assertEq(linkToken.balanceOf(OWNER) - ownerBalance, 1 ether, "owner link balance incorrect"); + // assert state of subscription api + assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 0, "owner withdrawable tokens incorrect"); + // assert that total balance is changed by the withdrawn amount + assertEq(s_subscriptionAPI.s_totalBalance(), 9 ether, "total balance incorrect"); + } + + function testWithdrawNativeInsufficientBalance() public { + // CASE: trying to withdraw more than balance + // should revert with InsufficientBalance + + // call WithdrawNative + changePrank(OWNER); + vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + } + + function testWithdrawLinkInvalidOwner() public { + address invalidAddress = makeAddr("invalidAddress"); + changePrank(invalidAddress); + vm.expectRevert("Only callable by owner"); + s_subscriptionAPI.withdraw(payable(OWNER)); + } + + function testWithdrawNativeInvalidOwner() public { + address invalidAddress = makeAddr("invalidAddress"); + changePrank(invalidAddress); + vm.expectRevert("Only callable by owner"); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + } + + function testWithdrawNativeSufficientBalance() public { + // CASE: trying to withdraw less than balance + // should withdraw successfully + + // transfer 10 ether to the contract to withdraw + vm.deal(address(s_subscriptionAPI), 10 ether); + + // set the withdrawable eth of the contract to be 1 ether + s_subscriptionAPI.setWithdrawableNativeTestingOnlyXXX(1 ether); + assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 1 ether); + + // set the total balance to be the same as the eth balance for consistency + // (this is not necessary for the test, but just to be sane) + s_subscriptionAPI.setTotalNativeBalanceTestingOnlyXXX(10 ether); + + // call WithdrawNative from owner address + changePrank(OWNER); + s_subscriptionAPI.withdrawNative(payable(OWNER)); + // assert native balance + assertEq(address(OWNER).balance, 1 ether, "owner native balance incorrect"); + // assert state of subscription api + assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 0, "owner withdrawable native incorrect"); + // assert that total balance is changed by the withdrawn amount + assertEq(s_subscriptionAPI.s_totalNativeBalance(), 9 ether, "total native balance incorrect"); + } + + function testOnTokenTransferCallerNotLink() public { + vm.expectRevert(SubscriptionAPI.OnlyCallableFromLink.selector); + s_subscriptionAPI.onTokenTransfer(makeAddr("someaddress"), 1 ether, abi.encode(uint256(1))); + } + + function testOnTokenTransferInvalidCalldata() public { + // create and set link token on subscription api + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // call link.transferAndCall with invalid calldata + vm.expectRevert(SubscriptionAPI.InvalidCalldata.selector); + linkToken.transferAndCall(address(s_subscriptionAPI), 1 ether, abi.encode(uint256(1), address(1))); + } + + function testOnTokenTransferInvalidSubscriptionId() public { + // create and set link token on subscription api + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // generate bogus sub id + uint256 subId = uint256(keccak256("idontexist")); + + // try to fund bogus sub id + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + linkToken.transferAndCall(address(s_subscriptionAPI), 1 ether, abi.encode(subId)); + } + + function testOnTokenTransferSuccess() public { + // happy path link funding test + // create and set link token on subscription api + MockLinkToken linkToken = new MockLinkToken(); + s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); + assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); + + // create a subscription and fund it with 5 LINK + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with link + changePrank(OWNER); + vm.expectEmit(true, false, false, true); + emit SubscriptionFunded(subId, 0, 5 ether); + bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); + assertTrue(success, "failed link transfer and call"); + + // assert that the subscription is funded + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 5 ether); + } + + function testFundSubscriptionWithNativeInvalidSubscriptionId() public { + // CASE: invalid subscription id + // should revert with InvalidSubscription + + uint256 subId = uint256(keccak256("idontexist")); + + // try to fund the subscription with native, should fail + address funder = makeAddr("funder"); + vm.deal(funder, 5 ether); + changePrank(funder); + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); + } + + function testFundSubscriptionWithNative() public { + // happy path test + // funding subscription with native + + // create a subscription and fund it with native + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + + // fund the subscription with native + vm.deal(subOwner, 5 ether); + changePrank(subOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionFundedWithNative(subId, 0, 5 ether); + s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); + + // assert that the subscription is funded + assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 5 ether); + } + + function testCreateSubscription() public { + // test that the subscription is created successfully + // and test the initial state of the subscription + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 1); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, subOwner); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).requestedOwner, address(0)); + } + + function testCreateSubscriptionRecreate() public { + // create two subscriptions from the same eoa + // they should never be the same due to nonce incrementation + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); + uint256 subId1 = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); + uint256 subId2 = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 2); + assertTrue(subId1 != subId2); + } + + function testSubscriptionOwnershipTransfer() public { + // create two eoa's, and create a subscription from one of them + // and transfer ownership to the other + // assert that the subscription is now owned by the other eoa + address oldOwner = makeAddr("oldOwner"); + address newOwner = makeAddr("newOwner"); + + // create sub + changePrank(oldOwner); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, oldOwner); + + // request ownership transfer + changePrank(oldOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionOwnerTransferRequested(subId, oldOwner, newOwner); + s_subscriptionAPI.requestSubscriptionOwnerTransfer(subId, newOwner); + + // accept ownership transfer from newOwner + changePrank(newOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionOwnerTransferred(subId, oldOwner, newOwner); + s_subscriptionAPI.acceptSubscriptionOwnerTransfer(subId); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).requestedOwner, address(0)); + } + + function testAddConsumerTooManyConsumers() public { + // add 100 consumers to a sub and then + // try adding one more and see the revert + address subOwner = makeAddr("subOwner"); + changePrank(subOwner); + uint256 subId = s_subscriptionAPI.createSubscription(); + for (uint256 i = 0; i < 100; i++) { + address consumer = makeAddr(Strings.toString(i)); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, consumer); + s_subscriptionAPI.addConsumer(subId, consumer); + } + + // try adding one more consumer, should revert + address lastConsumer = makeAddr("consumer"); + changePrank(subOwner); + vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); + s_subscriptionAPI.addConsumer(subId, lastConsumer); + } + + function testAddConsumerReaddSameConsumer() public { + // try adding the same consumer twice + // should be a no-op + // assert state is unchanged after the 2nd add + address subOwner = makeAddr("subOwner"); + address consumer = makeAddr("consumer"); + changePrank(subOwner); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); + changePrank(subOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, consumer); + s_subscriptionAPI.addConsumer(subId, consumer); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); + + // add consumer again, should be no-op + changePrank(subOwner); + VmSafe.Log[] memory events = vm.getRecordedLogs(); + s_subscriptionAPI.addConsumer(subId, consumer); + assertEq(events.length, 0); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); + + // remove consumer + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerRemoved(subId, consumer); + s_subscriptionAPI.removeConsumer(subId, consumer); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); + + // removing consumer twice should revert + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); + s_subscriptionAPI.removeConsumer(subId, consumer); + + //re-add consumer + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, consumer); + s_subscriptionAPI.addConsumer(subId, consumer); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); + } + + function testAddConsumer() public { + // create a subscription and add a consumer + // assert subscription state afterwards + address subOwner = makeAddr("subOwner"); + address consumer = makeAddr("consumer"); + changePrank(subOwner); + uint256 subId = s_subscriptionAPI.createSubscription(); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); + + // only subscription owner can add a consumer + address notSubOwner = makeAddr("notSubOwner"); + changePrank(notSubOwner); + vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.MustBeSubOwner.selector, subOwner)); + s_subscriptionAPI.addConsumer(subId, consumer); + + // subscription owner is able to add a consumer + changePrank(subOwner); + vm.expectEmit(true, false, false, true); + emit SubscriptionConsumerAdded(subId, consumer); + s_subscriptionAPI.addConsumer(subId, consumer); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); + assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol new file mode 100644 index 0000000..4b3a893 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol @@ -0,0 +1,488 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; + +contract VRFV2PlusWrapperTest is BaseTest { + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint32 private wrapperGasOverhead = 100_000; + uint32 private coordinatorGasOverheadNative = 200_000; + uint32 private coordinatorGasOverheadLink = 220_000; + uint256 private s_wrapperSubscriptionId; + + ExposedVRFCoordinatorV2_5 private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper private s_wrapper; + VRFV2PlusWrapperConsumerExample private s_consumer; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(LINK_WHALE, 10_000 ether); + vm.stopPrank(); + vm.startPrank(LINK_WHALE); + + // Deploy link token and link/native feed. + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Deploy coordinator. + s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(0)); + + // Create subscription for all future wrapper contracts. + s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); + + // Deploy wrapper. + s_wrapper = new VRFV2PlusWrapper( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + uint256(s_wrapperSubscriptionId) + ); + assertEq(address(s_linkToken), address(s_wrapper.link())); + assertEq(address(s_linkNativeFeed), address(s_wrapper.linkNativeFeed())); + + // Add wrapper as a consumer to the wrapper's subscription. + s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); + + // Deploy consumer. + s_consumer = new VRFV2PlusWrapperConsumerExample(address(s_wrapper)); + + // Configure the coordinator. + s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + setConfigCoordinator(); + setConfigWrapper(); + + s_testCoordinator.s_config(); + } + + function setConfigCoordinator() internal { + s_testCoordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 0, // fulfillmentFlatFeeNativePPM + 0, // fulfillmentFlatFeeLinkDiscountPPM + 0, // nativePremiumPercentage + 0 // linkPremiumPercentage + ); + } + + function setConfigWrapper() internal { + vm.expectEmit(false, false, false, true, address(s_wrapper)); + emit ConfigSet( + wrapperGasOverhead, + coordinatorGasOverheadNative, + coordinatorGasOverheadLink, + 0, + 0, + 0, + vrfKeyHash, + 10, + 1, + 50000000000000000, + 0, + 0 + ); + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 0, // native premium percentage, + 0, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 0, // fulfillmentFlatFeeNativePPM + 0 // fulfillmentFlatFeeLinkDiscountPPM + ); + ( + , + , + , + , + uint32 _wrapperGasOverhead, + uint32 _coordinatorGasOverheadNative, + uint32 _coordinatorGasOverheadLink, + uint16 _coordinatorGasOverheadPerWord, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, + bytes32 _keyHash, + uint8 _maxNumWords + ) = s_wrapper.getConfig(); + assertEq(_wrapperGasOverhead, wrapperGasOverhead); + assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative); + assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink); + assertEq(0, _coordinatorGasOverheadPerWord); + assertEq(0, _coordinatorNativePremiumPercentage); + assertEq(0, _coordinatorLinkPremiumPercentage); + assertEq(vrfKeyHash, _keyHash); + assertEq(10, _maxNumWords); + } + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + // IVRFV2PlusWrapper events + event LinkNativeFeedSet(address linkNativeFeed); + event FulfillmentTxSizeSet(uint32 size); + event ConfigSet( + uint32 wrapperGasOverhead, + uint32 coordinatorGasOverheadNative, + uint32 coordinatorGasOverheadLink, + uint16 coordinatorGasOverheadPerWord, + uint8 coordinatorNativePremiumPercentage, + uint8 coordinatorLinkPremiumPercentage, + bytes32 keyHash, + uint8 maxNumWords, + uint32 stalenessSeconds, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM + ); + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + event Withdrawn(address indexed to, uint256 amount); + event NativeWithdrawn(address indexed to, uint256 amount); + event Enabled(); + event Disabled(); + + // VRFV2PlusWrapperConsumerBase events + event LinkTokenSet(address link); + + // SubscriptionAPI events + event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); + + function testVRFV2PlusWrapperZeroAddress() public { + vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(0), uint256(0)); + } + + function testCreationOfANewVRFV2PlusWrapper() public { + // second wrapper contract will simply add itself to the same subscription + VRFV2PlusWrapper nextWrapper = new VRFV2PlusWrapper( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + s_wrapperSubscriptionId + ); + assertEq(s_wrapperSubscriptionId, nextWrapper.SUBSCRIPTION_ID()); + } + + function testVRFV2PlusWrapperWithZeroSubscriptionId() public { + vm.expectRevert(VRFV2PlusWrapper.SubscriptionIdMissing.selector); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(0)); + } + + function testVRFV2PlusWrapperWithInvalidSubscriptionId() public { + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(123456)); + } + + function testSetFulfillmentTxSize() public { + uint32 fulfillmentTxSize = 100_000; + vm.expectEmit(false, false, false, true, address(s_wrapper)); + emit FulfillmentTxSizeSet(fulfillmentTxSize); + s_wrapper.setFulfillmentTxSize(fulfillmentTxSize); + assertEq(s_wrapper.s_fulfillmentTxSizeBytes(), fulfillmentTxSize); + } + + function testSetCoordinatorZeroAddress() public { + vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); + s_wrapper.setCoordinator(address(0)); + } + + function testRequestAndFulfillRandomWordsNativeWrapper() public { + // Fund subscription. + s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(s_wrapper.SUBSCRIPTION_ID()); + vm.deal(address(s_consumer), 10 ether); + + // Get type and version. + assertEq(s_wrapper.typeAndVersion(), "VRFV2PlusWrapper 1.0.0"); + + // Cannot make request while disabled. + vm.expectEmit(false, false, false, true, address(s_wrapper)); + emit Disabled(); + s_wrapper.disable(); + vm.expectRevert("wrapper is disabled"); + s_consumer.makeRequestNative(100_000, 0, 0); + vm.expectEmit(false, false, false, true, address(s_wrapper)); + emit Enabled(); + s_wrapper.enable(); + + // Request randomness from wrapper. + uint32 callbackGasLimit = 1_000_000; + vm.expectEmit(true, true, true, true); + (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( + vrfKeyHash, + address(s_wrapper), + s_wrapper.SUBSCRIPTION_ID(), + 1 + ); + uint32 EIP150Overhead = callbackGasLimit / 63 + 1; + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + s_wrapper.SUBSCRIPTION_ID(), // subId + 0, // minConfirmations + callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 + 1, // numWords + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), // extraArgs + address(s_wrapper) // requester + ); + requestId = s_consumer.makeRequestNative(callbackGasLimit, 0, 1); + + (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); + uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative; + uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0); + assertEq(paid, expectedPaid); + assertEq(uint256(paid), wrapperNativeCostEstimate); + assertEq(wrapperNativeCostEstimate, wrapperCostCalculation); + assertEq(fulfilled, false); + assertEq(native, true); + assertEq(address(s_consumer).balance, 10 ether - expectedPaid); + + (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); + assertEq(gasLimit, callbackGasLimit); + + changePrank(address(s_testCoordinator)); + uint256[] memory words = new uint256[](1); + words[0] = 123; + s_wrapper.rawFulfillRandomWords(requestId, words); + (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); + assertEq(nowFulfilled, true); + assertEq(storedWords[0], 123); + + // Withdraw funds from wrapper. + changePrank(LINK_WHALE); + uint256 priorWhaleBalance = LINK_WHALE.balance; + vm.expectEmit(true, false, false, true, address(s_wrapper)); + emit NativeWithdrawn(LINK_WHALE, paid); + s_wrapper.withdrawNative(LINK_WHALE); + assertEq(LINK_WHALE.balance, priorWhaleBalance + paid); + assertEq(address(s_wrapper).balance, 0); + } + + function testSetConfigFulfillmentFlatFee_LinkDiscountTooHigh() public { + // Test that setting link discount flat fee higher than native flat fee reverts + vm.expectRevert(abi.encodeWithSelector(VRFV2PlusWrapper.LinkDiscountTooHigh.selector, uint32(501), uint32(500))); + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 0, // native premium percentage, + 0, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 500, // fulfillmentFlatFeeNativePPM + 501 // fulfillmentFlatFeeLinkDiscountPPM + ); + } + + function testSetConfigFulfillmentFlatFee_LinkDiscountEqualsNative() public { + // Test that setting link discount flat fee equal to native flat fee does not revert + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 0, // native premium percentage, + 0, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 450, // fulfillmentFlatFeeNativePPM + 450 // fulfillmentFlatFeeLinkDiscountPPM + ); + } + + function testSetConfigNativePremiumPercentageInvalidPremiumPercentage() public { + // Test that setting native premium percentage higher than 155 will revert + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155)) + ); + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 156, // native premium percentage, + 0, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 0, // fulfillmentFlatFeeNativePPM + 0 // fulfillmentFlatFeeLinkDiscountPPM + ); + } + + function testSetConfigLinkPremiumPercentageInvalidPremiumPercentage() public { + // Test that setting LINK premium percentage higher than 155 will revert + vm.expectRevert( + abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155)) + ); + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 15, // native premium percentage, + 202, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 0, // fulfillmentFlatFeeNativePPM + 0 // fulfillmentFlatFeeLinkDiscountPPM + ); + } + + function testRequestAndFulfillRandomWordsLINKWrapper() public { + // Fund subscription. + s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID())); + s_linkToken.transfer(address(s_consumer), 10 ether); + + // Request randomness from wrapper. + uint32 callbackGasLimit = 1_000_000; + vm.expectEmit(true, true, true, true); + (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( + vrfKeyHash, + address(s_wrapper), + s_wrapper.SUBSCRIPTION_ID(), + 1 + ); + uint32 EIP150Overhead = callbackGasLimit / 63 + 1; + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + s_wrapper.SUBSCRIPTION_ID(), // subId + 0, // minConfirmations + callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 + 1, // numWords + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // extraArgs + address(s_wrapper) // requester + ); + s_consumer.makeRequest(callbackGasLimit, 0, 1); + + // Assert that the request was made correctly. + (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); + uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2; + uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); + assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio + assertEq(uint256(paid), wrapperCostEstimate); + assertEq(wrapperCostEstimate, wrapperCostCalculation); + assertEq(fulfilled, false); + assertEq(native, false); + assertEq(s_linkToken.balanceOf(address(s_consumer)), 10 ether - expectedPaid); + (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); + assertEq(gasLimit, callbackGasLimit); + + // Fulfill the request. + changePrank(address(s_testCoordinator)); + uint256[] memory words = new uint256[](1); + words[0] = 456; + s_wrapper.rawFulfillRandomWords(requestId, words); + (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); + assertEq(nowFulfilled, true); + assertEq(storedWords[0], 456); + + // Withdraw funds from wrapper. + changePrank(LINK_WHALE); + uint256 priorWhaleBalance = s_linkToken.balanceOf(LINK_WHALE); + vm.expectEmit(true, false, false, true, address(s_wrapper)); + emit Withdrawn(LINK_WHALE, paid); + s_wrapper.withdraw(LINK_WHALE); + assertEq(s_linkToken.balanceOf(LINK_WHALE), priorWhaleBalance + paid); + assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); + } + + function testRequestRandomWordsLINKWrapperFallbackWeiPerUnitLinkUsed() public { + // Fund subscription. + s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID())); + s_linkToken.transfer(address(s_consumer), 10 ether); + + // Set the link feed to be stale. + (, , , uint32 stalenessSeconds, , , , , ) = s_testCoordinator.s_config(); + int256 fallbackWeiPerUnitLink = s_testCoordinator.s_fallbackWeiPerUnitLink(); + (uint80 roundId, int256 answer, uint256 startedAt, , ) = s_linkNativeFeed.latestRoundData(); + uint256 timestamp = block.timestamp - stalenessSeconds - 1; + s_linkNativeFeed.updateRoundData(roundId, answer, timestamp, startedAt); + + // Request randomness from wrapper. + uint32 callbackGasLimit = 1_000_000; + (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( + vrfKeyHash, + address(s_wrapper), + s_wrapper.SUBSCRIPTION_ID(), + 1 + ); + uint32 EIP150Overhead = callbackGasLimit / 63 + 1; + vm.expectEmit(true, true, true, true); + emit FallbackWeiPerUnitLinkUsed(requestId, fallbackWeiPerUnitLink); + emit RandomWordsRequested( + vrfKeyHash, + requestId, + preSeed, + s_wrapper.SUBSCRIPTION_ID(), // subId + 0, // minConfirmations + callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 + 1, // numWords + VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // extraArgs + address(s_wrapper) // requester + ); + s_consumer.makeRequest(callbackGasLimit, 0, 1); + } + + function testRequestRandomWordsInNativeNotConfigured() public { + VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + uint256(s_wrapperSubscriptionId) + ); + + vm.expectRevert("wrapper is not configured"); + wrapper.requestRandomWordsInNative(500_000, 0, 1, ""); + } + + function testRequestRandomWordsInNativeDisabled() public { + s_wrapper.disable(); + + vm.expectRevert("wrapper is disabled"); + s_wrapper.requestRandomWordsInNative(500_000, 0, 1, ""); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol new file mode 100644 index 0000000..96f1484 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; +import {VRFV2PlusWrapper_Arbitrum} from "../dev/VRFV2PlusWrapper_Arbitrum.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; + +contract VRFV2PlusWrapperArbitrumTest is BaseTest { + /// @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); + + address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint256 private s_wrapperSubscriptionId; + + ExposedVRFCoordinatorV2_5_Arbitrum private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper_Arbitrum private s_wrapper; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(DEPLOYER, 10_000 ether); + vm.stopPrank(); + vm.startPrank(DEPLOYER); + + // Deploy link token and link/native feed. + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Deploy coordinator. + s_testCoordinator = new ExposedVRFCoordinatorV2_5_Arbitrum(address(0)); + + // Create subscription for all future wrapper contracts. + s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); + + // Deploy wrapper. + s_wrapper = new VRFV2PlusWrapper_Arbitrum( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + uint256(s_wrapperSubscriptionId) + ); + + // Configure the wrapper. + s_wrapper.setConfig( + 100_000, // wrapper gas overhead + 200_000, // coordinator gas overhead native + 220_000, // coordinator gas overhead link + 500, // coordinator gas overhead per word + 15, // native premium percentage, + 10, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000 // fulfillmentFlatFeeLinkDiscountPPM + ); + + // Add wrapper as a consumer to the wrapper's subscription. + s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); + } + + function _mockArbGasGetPricesInWei() internal { + // return gas prices in wei, assuming the specified aggregator is used + // ( + // per L2 tx, + // per L1 calldata unit, (zero byte = 4 units, nonzero byte = 16 units) + // per storage allocation, + // per ArbGas base, + // per ArbGas congestion, + // per ArbGas total + // ) + vm.mockCall( + ARBGAS_ADDR, + abi.encodeWithSelector(ARBGAS.getPricesInWei.selector), + abi.encode(1 gwei, 250 gwei, 1 gwei, 1 gwei, 1 gwei, 1 gwei) + ); + } + + function test_calculateRequestPriceNativeOnArbitrumWrapper() public { + vm.txGasPrice(1 gwei); + _mockArbGasGetPricesInWei(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 5.01483 * 1e17, 1e15); + } + + function test_calculateRequestPriceLinkOnArbitrumWrapper() public { + vm.txGasPrice(1 gwei); + _mockArbGasGetPricesInWei(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 8.02846 * 1e17, 1e15); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol new file mode 100644 index 0000000..ba77686 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; +import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; + +contract VRFV2PlusWrapper_MigrationTest is BaseTest { + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + uint256 internal constant DEFAULT_NATIVE_FUNDING = 7 ether; // 7 ETH + uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 ETH + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint32 private wrapperGasOverhead = 10_000; + uint32 private coordinatorGasOverheadNative = 20_000; + uint32 private coordinatorGasOverheadLink = 40_000; + uint256 private s_wrapperSubscriptionId; + + ExposedVRFCoordinatorV2_5 private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper private s_wrapper; + VRFV2PlusWrapperConsumerExample private s_consumer; + + VRFCoordinatorV2Plus_V2Example private s_newCoordinator; + + event CoordinatorRegistered(address coordinatorAddress); + event MigrationCompleted(address newCoordinator, uint256 subId); + event WrapperRequestMade(uint256 indexed requestId, uint256 paid); + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(LINK_WHALE, 10_000 ether); + changePrank(LINK_WHALE); + + // Deploy link token and link/native feed. + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Deploy coordinator. + s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(0)); + + // Create subscription for all future wrapper contracts. + s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); + + // Deploy wrapper. + s_wrapper = new VRFV2PlusWrapper( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + uint256(s_wrapperSubscriptionId) + ); + + // Add wrapper as a consumer to the wrapper's subscription. + s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); + + // Deploy consumer. + s_consumer = new VRFV2PlusWrapperConsumerExample(address(s_wrapper)); + + // Configure the coordinator. + s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); + setConfigCoordinator(); + setConfigWrapper(); + + s_testCoordinator.s_config(); + + // Data structures for Migrateable Wrapper + s_newCoordinator = new VRFCoordinatorV2Plus_V2Example(address(0), address(s_testCoordinator)); + vm.expectEmit( + false, // no first indexed topic + false, // no second indexed topic + false, // no third indexed topic + true // check data (target coordinator address) + ); + address newCoordinatorAddr = address(s_newCoordinator); + emit CoordinatorRegistered(newCoordinatorAddr); + s_testCoordinator.registerMigratableCoordinator(newCoordinatorAddr); + assertTrue(s_testCoordinator.isTargetRegisteredExternal(newCoordinatorAddr)); + } + + function setConfigCoordinator() internal { + s_testCoordinator.setConfig( + 0, // minRequestConfirmations + 2_500_000, // maxGasLimit + 1, // stalenessSeconds + 50_000, // gasAfterPaymentCalculation + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000, // fulfillmentFlatFeeLinkDiscountPPM + 15, // nativePremiumPercentage + 10 // linkPremiumPercentage + ); + } + + function setConfigWrapper() internal { + s_wrapper.setConfig( + wrapperGasOverhead, // wrapper gas overhead + coordinatorGasOverheadNative, // coordinator gas overhead native + coordinatorGasOverheadLink, // coordinator gas overhead link + 0, // coordinator gas overhead per word + 0, // native premium percentage, + 0, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 0, // fulfillmentFlatFeeNativePPM + 0 // fulfillmentFlatFeeLinkDiscountPPM + ); + ( + , + , + , + , + uint32 _wrapperGasOverhead, + uint32 _coordinatorGasOverheadNative, + uint32 _coordinatorGasOverheadLink, + uint16 _coordinatorGasOverheadPerWord, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, + bytes32 _keyHash, + uint8 _maxNumWords + ) = s_wrapper.getConfig(); + assertEq(_wrapperGasOverhead, wrapperGasOverhead); + assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative); + assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink); + assertEq(0, _coordinatorGasOverheadPerWord); + assertEq(0, _coordinatorNativePremiumPercentage); + assertEq(0, _coordinatorLinkPremiumPercentage); + assertEq(vrfKeyHash, _keyHash); + assertEq(10, _maxNumWords); + } + + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint256 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + bytes extraArgs, + address indexed sender + ); + + // IVRFV2PlusWrapper events + event Withdrawn(address indexed to, uint256 amount); + event NativeWithdrawn(address indexed to, uint256 amount); + + // IVRFMigratableConsumerV2Plus events + event CoordinatorSet(address vrfCoordinator); + + function testMigrateWrapperLINKPayment() public { + s_linkToken.transfer(address(s_consumer), DEFAULT_LINK_FUNDING); + + assertEq(uint256(s_wrapperSubscriptionId), uint256(s_wrapper.SUBSCRIPTION_ID())); + address oldCoordinatorAddr = address(s_testCoordinator); + assertEq(address(oldCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); + + // Fund subscription with native and LINK payment to check + // if funds are transferred to new subscription after call + // migration to new coordinator + s_linkToken.transferAndCall(oldCoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(s_wrapperSubscriptionId)); + s_testCoordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(s_wrapperSubscriptionId); + + // subscription exists in V1 coordinator before migration + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = s_testCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(reqCount, 0); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(owner, address(LINK_WHALE)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_wrapper)); + + // Update wrapper to point to the new coordinator + vm.expectEmit( + false, // no first indexed field + false, // no second indexed field + false, // no third indexed field + true // check data fields + ); + address newCoordinatorAddr = address(s_newCoordinator); + emit MigrationCompleted(newCoordinatorAddr, s_wrapperSubscriptionId); + + // old coordinator has to migrate wrapper's subscription to the new coordinator + s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); + assertEq(address(newCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); + + // subscription no longer exists in v1 coordinator after migration + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_testCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(s_testCoordinator.s_totalBalance(), 0); + assertEq(s_testCoordinator.s_totalNativeBalance(), 0); + assertEq(s_linkToken.balanceOf(oldCoordinatorAddr), 0); + assertEq(oldCoordinatorAddr.balance, 0); + + // subscription exists in v2 coordinator + (balance, nativeBalance, reqCount, owner, consumers) = s_newCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(owner, address(LINK_WHALE)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_wrapper)); + assertEq(reqCount, 0); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(s_newCoordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); + assertEq(s_newCoordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + assertEq(s_linkToken.balanceOf(newCoordinatorAddr), DEFAULT_LINK_FUNDING); + assertEq(newCoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); + + // calling migrate again on V1 coordinator should fail + vm.expectRevert(); + s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); + + // Request randomness from wrapper. + uint32 callbackGasLimit = 1_000_000; + uint256 wrapperCost = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); + vm.expectEmit(true, true, true, true); + emit WrapperRequestMade(1, wrapperCost); + uint256 requestId = s_consumer.makeRequest(callbackGasLimit, 0, 1); + assertEq(requestId, 1); + + (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); + uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2; + uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); + assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio + assertEq(uint256(paid), wrapperCostEstimate); + assertEq(wrapperCostEstimate, wrapperCostCalculation); + assertEq(fulfilled, false); + assertEq(native, false); + assertEq(s_linkToken.balanceOf(address(s_consumer)), DEFAULT_LINK_FUNDING - expectedPaid); + + (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); + assertEq(gasLimit, callbackGasLimit); + + vm.stopPrank(); + + vm.startPrank(newCoordinatorAddr); + + uint256[] memory words = new uint256[](1); + words[0] = 123; + s_wrapper.rawFulfillRandomWords(requestId, words); + (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); + assertEq(nowFulfilled, true); + assertEq(storedWords[0], 123); + + vm.stopPrank(); + + /// Withdraw funds from wrapper. + vm.startPrank(LINK_WHALE); + uint256 priorWhaleBalance = s_linkToken.balanceOf(LINK_WHALE); + vm.expectEmit(true, false, false, true, address(s_wrapper)); + emit Withdrawn(LINK_WHALE, paid); + s_wrapper.withdraw(LINK_WHALE); + assertEq(s_linkToken.balanceOf(LINK_WHALE), priorWhaleBalance + paid); + assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); + + vm.stopPrank(); + } + + function testMigrateWrapperNativePayment() public { + vm.deal(address(s_consumer), DEFAULT_NATIVE_FUNDING); + + assertEq(uint256(s_wrapperSubscriptionId), uint256(s_wrapper.SUBSCRIPTION_ID())); + address oldCoordinatorAddr = address(s_testCoordinator); + assertEq(address(oldCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); + + // Fund subscription with native and LINK payment to check + // if funds are transferred to new subscription after call + // migration to new coordinator + s_linkToken.transferAndCall(oldCoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(s_wrapperSubscriptionId)); + s_testCoordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(s_wrapperSubscriptionId); + + // subscription exists in V1 coordinator before migration + ( + uint96 balance, + uint96 nativeBalance, + uint64 reqCount, + address owner, + address[] memory consumers + ) = s_testCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(reqCount, 0); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(owner, address(LINK_WHALE)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_wrapper)); + + // Update wrapper to point to the new coordinator + vm.expectEmit( + false, // no first indexed field + false, // no second indexed field + false, // no third indexed field + true // check data fields + ); + address newCoordinatorAddr = address(s_newCoordinator); + emit MigrationCompleted(newCoordinatorAddr, s_wrapperSubscriptionId); + + // old coordinator has to migrate wrapper's subscription to the new coordinator + s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); + assertEq(address(newCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); + + // subscription no longer exists in v1 coordinator after migration + vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); + s_testCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(s_testCoordinator.s_totalBalance(), 0); + assertEq(s_testCoordinator.s_totalNativeBalance(), 0); + assertEq(s_linkToken.balanceOf(oldCoordinatorAddr), 0); + assertEq(oldCoordinatorAddr.balance, 0); + + // subscription exists in v2 coordinator + (balance, nativeBalance, reqCount, owner, consumers) = s_newCoordinator.getSubscription(s_wrapperSubscriptionId); + assertEq(owner, address(LINK_WHALE)); + assertEq(consumers.length, 1); + assertEq(consumers[0], address(s_wrapper)); + assertEq(reqCount, 0); + assertEq(balance, DEFAULT_LINK_FUNDING); + assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); + assertEq(s_newCoordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); + assertEq(s_newCoordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); + assertEq(s_linkToken.balanceOf(newCoordinatorAddr), DEFAULT_LINK_FUNDING); + assertEq(newCoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); + + // calling migrate again on V1 coordinator should fail + vm.expectRevert(); + s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); + + // Request randomness from wrapper. + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 1; + vm.expectEmit(true, true, true, true); + uint256 wrapperCost = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); + emit WrapperRequestMade(1, wrapperCost); + uint256 requestId = s_consumer.makeRequestNative(callbackGasLimit, 0, numWords); + assertEq(requestId, 1); + + (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); + uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative; + uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0); + assertEq(paid, expectedPaid); + assertEq(uint256(paid), wrapperNativeCostEstimate); + assertEq(wrapperNativeCostEstimate, wrapperCostCalculation); + assertEq(fulfilled, false); + assertEq(native, true); + assertEq(address(s_consumer).balance, DEFAULT_NATIVE_FUNDING - expectedPaid); + + (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); + assertEq(gasLimit, callbackGasLimit); + + vm.stopPrank(); + + vm.startPrank(newCoordinatorAddr); + + uint256[] memory words = new uint256[](1); + words[0] = 123; + s_wrapper.rawFulfillRandomWords(requestId, words); + (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); + assertEq(nowFulfilled, true); + assertEq(storedWords[0], 123); + + vm.stopPrank(); + + // Withdraw funds from wrapper. + vm.startPrank(LINK_WHALE); + uint256 priorWhaleBalance = LINK_WHALE.balance; + vm.expectEmit(true, false, false, true, address(s_wrapper)); + emit NativeWithdrawn(LINK_WHALE, paid); + s_wrapper.withdrawNative(LINK_WHALE); + assertEq(LINK_WHALE.balance, priorWhaleBalance + paid); + assertEq(address(s_wrapper).balance, 0); + + vm.stopPrank(); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol new file mode 100644 index 0000000..a8a97a5 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; +import {VRFV2PlusWrapper_Optimism} from "../dev/VRFV2PlusWrapper_Optimism.sol"; +import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; +import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; +import {VmSafe} from "forge-std/Vm.sol"; + +contract VRFV2PlusWrapperOptimismAndBaseTest is BaseTest { + /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); + OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); + + address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint256 private s_wrapperSubscriptionId; + + ExposedVRFCoordinatorV2_5_Optimism private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper_Optimism private s_wrapper; + + /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload + /// @dev This option is only available for the Coordinator contract + uint8 internal constant L1_GAS_FEES_MODE = 0; + /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected + /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; + /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) + /// @dev This option is available for the Coordinator and the Wrapper contract + uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; + + function setUp() public override { + BaseTest.setUp(); + + // Fund our users. + vm.roll(1); + vm.deal(DEPLOYER, 10_000 ether); + vm.stopPrank(); + vm.startPrank(DEPLOYER); + + // Deploy link token and link/native feed. + s_linkToken = new MockLinkToken(); + s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) + + // Deploy coordinator. + s_testCoordinator = new ExposedVRFCoordinatorV2_5_Optimism(address(0)); + + // Create subscription for all future wrapper contracts. + s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); + + // Deploy wrapper. + s_wrapper = new VRFV2PlusWrapper_Optimism( + address(s_linkToken), + address(s_linkNativeFeed), + address(s_testCoordinator), + uint256(s_wrapperSubscriptionId) + ); + + // Configure the wrapper. + s_wrapper.setConfig( + 100_000, // wrapper gas overhead + 200_000, // coordinator gas overhead native + 220_000, // coordinator gas overhead link + 500, // coordinator gas overhead per word + 15, // native premium percentage, + 10, // link premium percentage + vrfKeyHash, // keyHash + 10, // max number of words, + 1, // stalenessSeconds + 50000000000000000, // fallbackWeiPerUnitLink + 500_000, // fulfillmentFlatFeeNativePPM + 100_000 // fulfillmentFlatFeeLinkDiscountPPM + ); + + // Add wrapper as a consumer to the wrapper's subscription. + s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); + } + + function _mockGasOraclePriceGetL1FeeUpperBoundCall() internal { + // fullfillment tx calldata size = 772 bytes + // RLP-encoded unsigned tx headers (approx padding size) = 71 bytes + // total = 843 bytes + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(OVM_GasPriceOracle.getL1FeeUpperBound.selector, 843), + abi.encode(uint256(0.02 ether)) + ); + } + + function _mockGasOraclePriceFeeMethods() internal { + // these values are taken from an example transaction on Base Sepolia + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("l1BaseFee()"))), + abi.encode(64273426165) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("baseFeeScalar()"))), + abi.encode(1101) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("blobBaseFeeScalar()"))), + abi.encode(659851) + ); + vm.mockCall( + OVM_GASPRICEORACLE_ADDR, + abi.encodeWithSelector(bytes4(keccak256("blobBaseFee()"))), + abi.encode(2126959908362) + ); + vm.mockCall(OVM_GASPRICEORACLE_ADDR, abi.encodeWithSelector(bytes4(keccak256("decimals()"))), abi.encode(6)); + } + + function _checkL1FeeCalculationSetEmittedLogs(uint8 expectedMode, uint8 expectedCoefficient) internal { + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + assertEq(entries.length, 1); + assertEq(entries[0].topics.length, 1); + assertEq(entries[0].topics[0], keccak256("L1FeeCalculationSet(uint8,uint8)")); + (uint8 actualMode, uint8 actualCoefficient) = abi.decode(entries[0].data, (uint8, uint8)); + assertEq(expectedMode, actualMode); + assertEq(expectedCoefficient, actualCoefficient); + } + + function test_setL1FeePaymentMethodOnOptimismWrapper() public { + // check default settings after contract deployment + assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); + assertEq(100, uint256(s_wrapper.s_l1FeeCoefficient())); + + vm.recordLogs(); + s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); + + _checkL1FeeCalculationSetEmittedLogs(L1_CALLDATA_GAS_COST_MODE, 70); + assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); + assertEq(70, uint256(s_wrapper.s_l1FeeCoefficient())); + + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 30); + + _checkL1FeeCalculationSetEmittedLogs(L1_GAS_FEES_UPPER_BOUND_MODE, 30); + assertEq(uint256(L1_GAS_FEES_UPPER_BOUND_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); + assertEq(30, uint256(s_wrapper.s_l1FeeCoefficient())); + + // VRFWrapper doesn't support this mode + vm.expectRevert( + abi.encodeWithSelector(VRFV2PlusWrapper_Optimism.UnsupportedL1FeeCalculationMode.selector, L1_GAS_FEES_MODE) + ); + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); + + // should revert if invalid L1 fee calculation mode is used + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCalculationMode.selector, 6)); + s_wrapper.setL1FeeCalculation(6, 100); + + // should revert if invalid coefficient is used (equal to zero, this would disable L1 fees completely) + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 0)); + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 0); + + // should revert if invalid coefficient is used (larger than 100%) + vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 101)); + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 101); + } + + function test_calculateRequestPriceNativeOnOptimismWrapper_UsingCalldataCostCall() public { + s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 80); + + vm.txGasPrice(1 gwei); + _mockGasOraclePriceFeeMethods(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 5.02575 * 1e17, 1e15); + } + + function test_calculateRequestPriceLinkOnOptimismWrapper_UsingCalldataCostCall() public { + s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 80); + + vm.txGasPrice(1 gwei); + _mockGasOraclePriceFeeMethods(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 8.04934 * 1e17, 1e15); + } + + function test_calculateRequestPriceNativeOnOptimismWrapper_UsingGetL1FeeUpperBoundCall() public { + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 60); + + vm.txGasPrice(1 gwei); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 5.15283 * 1e17, 1e15); + } + + function test_calculateRequestPriceLinkOnOptimismWrapper_UsingGetL1FeeUpperBoundCall() public { + s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 60); + + vm.txGasPrice(1 gwei); + _mockGasOraclePriceGetL1FeeUpperBoundCall(); + uint32 callbackGasLimit = 1_000_000; + uint32 numWords = 5; + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); + // 1e15 is less than 1 percent discrepancy + assertApproxEqAbs(wrapperCostCalculation, 8.29246 * 1e17, 1e15); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol new file mode 100644 index 0000000..16a157e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; + +/// @dev A helper contract that exposes ChainSpecificUtil methods for testing +contract ChainSpecificUtilHelper { + function getBlockhash(uint64 blockNumber) external view returns (bytes32) { + return ChainSpecificUtil._getBlockhash(blockNumber); + } + + function getBlockNumber() external view returns (uint256) { + return ChainSpecificUtil._getBlockNumber(); + } + + function getCurrentTxL1GasFees(string memory txCallData) external view returns (uint256) { + return ChainSpecificUtil._getCurrentTxL1GasFees(bytes(txCallData)); + } + + function getL1CalldataGasCost(uint256 calldataSize) external view returns (uint256) { + return ChainSpecificUtil._getL1CalldataGasCost(calldataSize); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol new file mode 100644 index 0000000..1ceb789 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +contract Counter { + error AlwaysRevert(); + + uint256 public count = 0; + + function increment() public returns (uint256) { + count += 1; + return count; + } + + function reset() public { + count = 0; + } + + function alwaysRevert() public pure { + revert AlwaysRevert(); + } + + function alwaysRevertWithString() public pure { + revert("always revert"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol new file mode 100644 index 0000000..eaac0be --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFConsumerBase} from "../VRFConsumerBase.sol"; + +contract VRFConsumer is VRFConsumerBase { + uint256 public randomnessOutput; + bytes32 public requestId; + + constructor( + address vrfCoordinator, + address link + ) + // solhint-disable-next-line no-empty-blocks + VRFConsumerBase(vrfCoordinator, link) + { + /* empty */ + } + + function fulfillRandomness(bytes32 /* requestId */, uint256 randomness) internal override { + randomnessOutput = randomness; + requestId = requestId; + } + + function doRequestRandomness(bytes32 keyHash, uint256 fee) external returns (bytes32) { + return requestRandomness(keyHash, fee); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol new file mode 100644 index 0000000..e2502fa --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +contract VRFConsumerV2 is VRFConsumerBaseV2 { + uint256[] public s_randomWords; + uint256 public s_requestId; + VRFCoordinatorV2Interface internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint64 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness( + bytes32 keyHash, + uint64 subId, + uint16 minReqConfs, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol new file mode 100644 index 0000000..f0acade --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; + +contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { + uint256[] public s_randomWords; + uint256 public s_requestId; + IVRFCoordinatorV2Plus internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint256 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { + COORDINATOR = IVRFCoordinatorV2Plus(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(req); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol new file mode 100644 index 0000000..930cebf --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2Upgradeable} from "../dev/VRFConsumerBaseV2Upgradeable.sol"; +import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +contract VRFConsumerV2UpgradeableExample is Initializable, VRFConsumerBaseV2Upgradeable { + uint256[] public s_randomWords; + uint256 public s_requestId; + VRFCoordinatorV2Interface public COORDINATOR; + LinkTokenInterface public LINKTOKEN; + uint64 public s_subId; + uint256 public s_gasAvailable; + + function initialize(address _vrfCoordinator, address _link) public initializer { + __VRFConsumerBaseV2_init(_vrfCoordinator); + COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); + LINKTOKEN = LinkTokenInterface(_link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness( + bytes32 keyHash, + uint64 subId, + uint16 minReqConfs, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol new file mode 100644 index 0000000..5774b77 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol @@ -0,0 +1,840 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {BlockhashStoreInterface} from "../interfaces/BlockhashStoreInterface.sol"; +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; +import {VRF} from "../VRF.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +contract VRFCoordinatorTestV2 is + VRF, + ConfirmedOwner, + TypeAndVersionInterface, + VRFCoordinatorV2Interface, + IERC677Receiver +{ + LinkTokenInterface public immutable LINK; + AggregatorV3Interface public immutable LINK_ETH_FEED; + BlockhashStoreInterface public immutable BLOCKHASH_STORE; + + // We need to maintain a list of consuming addresses. + // This bound ensures we are able to loop over them as needed. + // Should a user require more consumers, they can use multiple subscriptions. + uint16 public constant MAX_CONSUMERS = 100; + + error TooManyConsumers(); + error InsufficientBalance(); + error InvalidConsumer(uint64 subId, address consumer); + error InvalidSubscription(); + error OnlyCallableFromLink(); + error InvalidCalldata(); + error MustBeSubOwner(address owner); + error PendingRequestExists(); + error MustBeRequestedOwner(address proposedOwner); + error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen + event FundsRecovered(address to, uint256 amount); + // We use the subscription struct (1 word) + // at fulfillment time. + struct Subscription { + // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) + uint96 balance; // Common link balance used for all consumer requests. + uint64 reqCount; // For fee tiers + } + // We use the config for the mgmt APIs + struct SubscriptionConfig { + address owner; // Owner can fund/withdraw/cancel the sub. + address requestedOwner; // For safely transferring sub ownership. + // Maintains the list of keys in s_consumers. + // We do this for 2 reasons: + // 1. To be able to clean up all keys from s_consumers when canceling a subscription. + // 2. To be able to return the list of all consumers in getSubscription. + // Note that we need the s_consumers map to be able to directly check if a + // consumer is valid without reading all the consumers from storage. + address[] consumers; + } + // Note a nonce of 0 indicates an the consumer is not assigned to that subscription. + mapping(address => mapping(uint64 => uint64)) /* consumer */ /* subId */ /* nonce */ private s_consumers; + mapping(uint64 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ private s_subscriptionConfigs; + mapping(uint64 => Subscription) /* subId */ /* subscription */ private s_subscriptions; + // We make the sub count public so that its possible to + // get all the current subscriptions via getSubscription. + uint64 private s_currentSubId; + // s_totalBalance tracks the total link sent to/from + // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. + // A discrepancy with this contract's link balance indicates someone + // sent tokens using transfer and so we may need to use recoverFunds. + uint96 private s_totalBalance; + event SubscriptionCreated(uint64 indexed subId, address owner); + event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); + event SubscriptionConsumerAdded(uint64 indexed subId, address consumer); + event SubscriptionConsumerRemoved(uint64 indexed subId, address consumer); + event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); + event SubscriptionOwnerTransferRequested(uint64 indexed subId, address from, address to); + event SubscriptionOwnerTransferred(uint64 indexed subId, address from, address to); + + // Set this maximum to 200 to give us a 56 block window to fulfill + // the request before requiring the block hash feeder. + uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; + uint32 public constant MAX_NUM_WORDS = 500; + // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) + // and some arithmetic operations. + uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); + error GasLimitTooBig(uint32 have, uint32 want); + error NumWordsTooBig(uint32 have, uint32 want); + error ProvingKeyAlreadyRegistered(bytes32 keyHash); + error NoSuchProvingKey(bytes32 keyHash); + error InvalidLinkWeiPrice(int256 linkWei); + error InsufficientGasForConsumer(uint256 have, uint256 want); + error NoCorrespondingRequest(); + error IncorrectCommitment(); + error BlockhashNotInStore(uint256 blockNum); + error PaymentTooLarge(); + error Reentrant(); + + struct RequestCommitment { + uint64 blockNum; + uint64 subId; + uint32 callbackGasLimit; + uint32 numWords; + address sender; + } + mapping(bytes32 => address) /* keyHash */ /* oracle */ private s_provingKeys; + bytes32[] private s_provingKeyHashes; + mapping(address => uint96) /* oracle */ /* LINK balance */ private s_withdrawableTokens; + mapping(uint256 => bytes32) /* requestID */ /* commitment */ private s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); + event ProvingKeyDeregistered(bytes32 keyHash, address indexed oracle); + event RandomWordsRequested( + bytes32 indexed keyHash, + uint256 requestId, + uint256 preSeed, + uint64 indexed subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords, + address indexed sender + ); + event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); + + struct Config { + uint16 minimumRequestConfirmations; + uint32 maxGasLimit; + // Reentrancy protection. + bool reentrancyLock; + // stalenessSeconds is how long before we consider the feed price to be stale + // and fallback to fallbackWeiPerUnitLink. + uint32 stalenessSeconds; + // Gas to cover oracle payment after we calculate the payment. + // We make it configurable in case those operations are repriced. + uint32 gasAfterPaymentCalculation; + } + int256 private s_fallbackWeiPerUnitLink; + Config private s_config; + FeeConfig private s_feeConfig; + struct FeeConfig { + // Flat fee charged per fulfillment in millionths of link + // So fee range is [0, 2^32/10^6]. + uint32 fulfillmentFlatFeeLinkPPMTier1; + uint32 fulfillmentFlatFeeLinkPPMTier2; + uint32 fulfillmentFlatFeeLinkPPMTier3; + uint32 fulfillmentFlatFeeLinkPPMTier4; + uint32 fulfillmentFlatFeeLinkPPMTier5; + uint24 reqsForTier2; + uint24 reqsForTier3; + uint24 reqsForTier4; + uint24 reqsForTier5; + } + event ConfigSet( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig feeConfig + ); + + constructor(address link, address blockhashStore, address linkEthFeed) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(link); + LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); + BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); + } + + /** + * @notice Registers a proving key to an oracle. + * @param oracle address of the oracle + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + if (s_provingKeys[kh] != address(0)) { + revert ProvingKeyAlreadyRegistered(kh); + } + s_provingKeys[kh] = oracle; + s_provingKeyHashes.push(kh); + emit ProvingKeyRegistered(kh, oracle); + } + + /** + * @notice Deregisters a proving key to an oracle. + * @param publicProvingKey key that oracle can use to submit vrf fulfillments + */ + function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + bytes32 kh = hashOfKey(publicProvingKey); + address oracle = s_provingKeys[kh]; + if (oracle == address(0)) { + revert NoSuchProvingKey(kh); + } + delete s_provingKeys[kh]; + for (uint256 i = 0; i < s_provingKeyHashes.length; i++) { + if (s_provingKeyHashes[i] == kh) { + bytes32 last = s_provingKeyHashes[s_provingKeyHashes.length - 1]; + // Copy last element and overwrite kh to be deleted with it + s_provingKeyHashes[i] = last; + s_provingKeyHashes.pop(); + } + } + emit ProvingKeyDeregistered(kh, oracle); + } + + /** + * @notice Returns the proving key hash key associated with this public key + * @param publicKey the key to return the hash of + */ + function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { + return keccak256(abi.encode(publicKey)); + } + + /** + * @notice Sets the configuration of the vrfv2 coordinator + * @param minimumRequestConfirmations global min for request confirmations + * @param maxGasLimit global max for request gas limit + * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price + * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement + * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed + * @param feeConfig fee tier configuration + */ + function setConfig( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation, + int256 fallbackWeiPerUnitLink, + FeeConfig memory feeConfig + ) external onlyOwner { + if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { + revert InvalidRequestConfirmations( + minimumRequestConfirmations, + minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + if (fallbackWeiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); + } + s_config = Config({ + minimumRequestConfirmations: minimumRequestConfirmations, + maxGasLimit: maxGasLimit, + stalenessSeconds: stalenessSeconds, + gasAfterPaymentCalculation: gasAfterPaymentCalculation, + reentrancyLock: false + }); + s_feeConfig = feeConfig; + s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; + emit ConfigSet( + minimumRequestConfirmations, + maxGasLimit, + stalenessSeconds, + gasAfterPaymentCalculation, + fallbackWeiPerUnitLink, + s_feeConfig + ); + } + + function getConfig() + external + view + returns ( + uint16 minimumRequestConfirmations, + uint32 maxGasLimit, + uint32 stalenessSeconds, + uint32 gasAfterPaymentCalculation + ) + { + return ( + s_config.minimumRequestConfirmations, + s_config.maxGasLimit, + s_config.stalenessSeconds, + s_config.gasAfterPaymentCalculation + ); + } + + function getFeeConfig() + external + view + returns ( + uint32 fulfillmentFlatFeeLinkPPMTier1, + uint32 fulfillmentFlatFeeLinkPPMTier2, + uint32 fulfillmentFlatFeeLinkPPMTier3, + uint32 fulfillmentFlatFeeLinkPPMTier4, + uint32 fulfillmentFlatFeeLinkPPMTier5, + uint24 reqsForTier2, + uint24 reqsForTier3, + uint24 reqsForTier4, + uint24 reqsForTier5 + ) + { + return ( + s_feeConfig.fulfillmentFlatFeeLinkPPMTier1, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier2, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier3, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier4, + s_feeConfig.fulfillmentFlatFeeLinkPPMTier5, + s_feeConfig.reqsForTier2, + s_feeConfig.reqsForTier3, + s_feeConfig.reqsForTier4, + s_feeConfig.reqsForTier5 + ); + } + + function getTotalBalance() external view returns (uint256) { + return s_totalBalance; + } + + function getFallbackWeiPerUnitLink() external view returns (int256) { + return s_fallbackWeiPerUnitLink; + } + + /** + * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. + * @param subId subscription id + * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain + */ + function ownerCancelSubscription(uint64 subId) external onlyOwner { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + cancelSubscriptionHelper(subId, s_subscriptionConfigs[subId].owner); + } + + /** + * @notice Recover link sent with transfer instead of transferAndCall. + * @param to address to send link to + */ + function recoverFunds(address to) external onlyOwner { + uint256 externalBalance = LINK.balanceOf(address(this)); + uint256 internalBalance = uint256(s_totalBalance); + if (internalBalance > externalBalance) { + revert BalanceInvariantViolated(internalBalance, externalBalance); + } + if (internalBalance < externalBalance) { + uint256 amount = externalBalance - internalBalance; + LINK.transfer(to, amount); + emit FundsRecovered(to, amount); + } + // If the balances are equal, nothing to be done. + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function getRequestConfig() external view override returns (uint16, uint32, bytes32[] memory) { + return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function requestRandomWords( + bytes32 keyHash, + uint64 subId, + uint16 requestConfirmations, + uint32 callbackGasLimit, + uint32 numWords + ) external override nonReentrant returns (uint256) { + // Input validation using the subscription storage. + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // Its important to ensure that the consumer is in fact who they say they + // are, otherwise they could use someone else's subscription balance. + // A nonce of 0 indicates consumer is not allocated to the sub. + uint64 currentNonce = s_consumers[msg.sender][subId]; + if (currentNonce == 0) { + revert InvalidConsumer(subId, msg.sender); + } + // Input validation using the config storage word. + if ( + requestConfirmations < s_config.minimumRequestConfirmations || requestConfirmations > MAX_REQUEST_CONFIRMATIONS + ) { + revert InvalidRequestConfirmations( + requestConfirmations, + s_config.minimumRequestConfirmations, + MAX_REQUEST_CONFIRMATIONS + ); + } + // No lower bound on the requested gas limit. A user could request 0 + // and they would simply be billed for the proof verification and wouldn't be + // able to do anything with the random value. + if (callbackGasLimit > s_config.maxGasLimit) { + revert GasLimitTooBig(callbackGasLimit, s_config.maxGasLimit); + } + if (numWords > MAX_NUM_WORDS) { + revert NumWordsTooBig(numWords, MAX_NUM_WORDS); + } + // Note we do not check whether the keyHash is valid to save gas. + // The consequence for users is that they can send requests + // for invalid keyHashes which will simply not be fulfilled. + uint64 nonce = currentNonce + 1; + (uint256 requestId, uint256 preSeed) = computeRequestId(keyHash, msg.sender, subId, nonce); + + s_requestCommitments[requestId] = keccak256( + abi.encode(requestId, block.number, subId, callbackGasLimit, numWords, msg.sender) + ); + emit RandomWordsRequested( + keyHash, + requestId, + preSeed, + subId, + requestConfirmations, + callbackGasLimit, + numWords, + msg.sender + ); + s_consumers[msg.sender][subId] = nonce; + + return requestId; + } + + /** + * @notice Get request commitment + * @param requestId id of request + * @dev used to determine if a request is fulfilled or not + */ + function getCommitment(uint256 requestId) external view returns (bytes32) { + return s_requestCommitments[requestId]; + } + + function computeRequestId( + bytes32 keyHash, + address sender, + uint64 subId, + uint64 nonce + ) private pure returns (uint256, uint256) { + uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); + return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); + } + + /** + * @dev calls target address with exactly gasAmount gas and data as calldata + * or reverts if at least gasAmount gas is not available. + */ + function callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { + // solhint-disable-next-line no-inline-assembly + assembly { + let g := gas() + // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow + // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). + // We want to ensure that we revert if gasAmount > 63//64*gas available + // as we do not want to provide them with less, however that check itself costs + // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able + // to revert if gasAmount > 63//64*gas available. + if lt(g, GAS_FOR_CALL_EXACT_CHECK) { + revert(0, 0) + } + g := sub(g, GAS_FOR_CALL_EXACT_CHECK) + // if g - g//64 <= gasAmount, revert + // (we subtract g//64 because of EIP-150) + if iszero(gt(sub(g, div(g, 64)), gasAmount)) { + revert(0, 0) + } + // solidity calls check that a contract actually exists at the destination, so we do the same + if iszero(extcodesize(target)) { + revert(0, 0) + } + // call and return whether we succeeded. ignore return data + // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) + success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) + } + return success; + } + + function getRandomnessFromProof( + Proof calldata proof, + RequestCommitment calldata rc + ) private view returns (bytes32 keyHash, uint256 requestId, uint256 randomness) { + keyHash = hashOfKey(proof.pk); + // Only registered proving keys are permitted. + address oracle = s_provingKeys[keyHash]; + if (oracle == address(0)) { + revert NoSuchProvingKey(keyHash); + } + requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); + bytes32 commitment = s_requestCommitments[requestId]; + if (commitment == 0) { + revert NoCorrespondingRequest(); + } + if ( + commitment != keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender)) + ) { + revert IncorrectCommitment(); + } + + bytes32 blockHash = blockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); + if (blockHash == bytes32(0)) { + revert BlockhashNotInStore(rc.blockNum); + } + } + + // The seed actually used by the VRF machinery, mixing in the blockhash + uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); + randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure + } + + /* + * @notice Compute fee based on the request count + * @param reqCount number of requests + * @return feePPM fee in LINK PPM + */ + function getFeeTier(uint64 reqCount) public view returns (uint32) { + FeeConfig memory fc = s_feeConfig; + if (0 <= reqCount && reqCount <= fc.reqsForTier2) { + return fc.fulfillmentFlatFeeLinkPPMTier1; + } + if (fc.reqsForTier2 < reqCount && reqCount <= fc.reqsForTier3) { + return fc.fulfillmentFlatFeeLinkPPMTier2; + } + if (fc.reqsForTier3 < reqCount && reqCount <= fc.reqsForTier4) { + return fc.fulfillmentFlatFeeLinkPPMTier3; + } + if (fc.reqsForTier4 < reqCount && reqCount <= fc.reqsForTier5) { + return fc.fulfillmentFlatFeeLinkPPMTier4; + } + return fc.fulfillmentFlatFeeLinkPPMTier5; + } + + /* + * @notice Fulfill a randomness request + * @param proof contains the proof and randomness + * @param rc request commitment pre-image, committed to at request time + * @return payment amount billed to the subscription + * @dev simulated offchain to determine if sufficient balance is present to fulfill the request + */ + function fulfillRandomWords( + Proof calldata proof, + RequestCommitment calldata rc + ) external nonReentrant returns (uint96) { + uint256 startGas = gasleft(); + (bytes32 keyHash, uint256 requestId, uint256 randomness) = getRandomnessFromProof(proof, rc); + + uint256[] memory randomWords = new uint256[](rc.numWords); + for (uint256 i = 0; i < rc.numWords; i++) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } + + delete s_requestCommitments[requestId]; + VRFConsumerBaseV2 v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + bool success = callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + + // Increment the req count for fee tier selection. + uint64 reqCount = s_subscriptions[rc.subId].reqCount; + s_subscriptions[rc.subId].reqCount += 1; + + // We want to charge users exactly for how much gas they use in their callback. + // The gasAfterPaymentCalculation is meant to cover these additional operations where we + // decrement the subscription balance and increment the oracles withdrawable balance. + // We also add the flat link fee to the payment amount. + // Its specified in millionths of link, if s_config.fulfillmentFlatFeeLinkPPM = 1 + // 1 link / 1e6 = 1e18 juels / 1e6 = 1e12 juels. + uint96 payment = calculatePaymentAmount( + startGas, + s_config.gasAfterPaymentCalculation, + getFeeTier(reqCount), + tx.gasprice + ); + if (s_subscriptions[rc.subId].balance < payment) { + revert InsufficientBalance(); + } + s_subscriptions[rc.subId].balance -= payment; + s_withdrawableTokens[s_provingKeys[keyHash]] += payment; + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(requestId, randomness, payment, success); + return payment; + } + + // Get the amount of gas used for fulfillment + function calculatePaymentAmount( + uint256 startGas, + uint256 gasAfterPaymentCalculation, + uint32 fulfillmentFlatFeeLinkPPM, + uint256 weiPerUnitGas + ) internal view returns (uint96) { + int256 weiPerUnitLink; + weiPerUnitLink = getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // (1e18 juels/link) (wei/gas * gas) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft())) / + uint256(weiPerUnitLink); + uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); + if (paymentNoFee > (1e27 - fee)) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return uint96(paymentNoFee + fee); + } + + function getFeedData() private view returns (int256) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return weiPerUnitLink; + } + + /* + * @notice Oracle withdraw LINK earned through fulfilling requests + * @param recipient where to send the funds + * @param amount amount to withdraw + */ + function oracleWithdraw(address recipient, uint96 amount) external nonReentrant { + if (s_withdrawableTokens[msg.sender] < amount) { + revert InsufficientBalance(); + } + s_withdrawableTokens[msg.sender] -= amount; + s_totalBalance -= amount; + if (!LINK.transfer(recipient, amount)) { + revert InsufficientBalance(); + } + } + + function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { + if (msg.sender != address(LINK)) { + revert OnlyCallableFromLink(); + } + if (data.length != 32) { + revert InvalidCalldata(); + } + uint64 subId = abi.decode(data, (uint64)); + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + // We do not check that the msg.sender is the subscription owner, + // anyone can fund a subscription. + uint256 oldBalance = s_subscriptions[subId].balance; + s_subscriptions[subId].balance += uint96(amount); + s_totalBalance += uint96(amount); + emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); + } + + function getCurrentSubId() external view returns (uint64) { + return s_currentSubId; + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function getSubscription( + uint64 subId + ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + return ( + s_subscriptions[subId].balance, + s_subscriptions[subId].reqCount, + s_subscriptionConfigs[subId].owner, + s_subscriptionConfigs[subId].consumers + ); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function createSubscription() external override nonReentrant returns (uint64) { + s_currentSubId++; + uint64 currentSubId = s_currentSubId; + address[] memory consumers = new address[](0); + s_subscriptions[currentSubId] = Subscription({balance: 0, reqCount: 0}); + s_subscriptionConfigs[currentSubId] = SubscriptionConfig({ + owner: msg.sender, + requestedOwner: address(0), + consumers: consumers + }); + + emit SubscriptionCreated(currentSubId, msg.sender); + return currentSubId; + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function requestSubscriptionOwnerTransfer( + uint64 subId, + address newOwner + ) external override onlySubOwner(subId) nonReentrant { + // Proposing to address(0) would never be claimable so don't need to check. + if (s_subscriptionConfigs[subId].requestedOwner != newOwner) { + s_subscriptionConfigs[subId].requestedOwner = newOwner; + emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); + } + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function acceptSubscriptionOwnerTransfer(uint64 subId) external override nonReentrant { + if (s_subscriptionConfigs[subId].owner == address(0)) { + revert InvalidSubscription(); + } + if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { + revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); + } + address oldOwner = s_subscriptionConfigs[subId].owner; + s_subscriptionConfigs[subId].owner = msg.sender; + s_subscriptionConfigs[subId].requestedOwner = address(0); + emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function removeConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + if (s_consumers[consumer][subId] == 0) { + revert InvalidConsumer(subId, consumer); + } + // Note bounded by MAX_CONSUMERS + address[] memory consumers = s_subscriptionConfigs[subId].consumers; + uint256 lastConsumerIndex = consumers.length - 1; + for (uint256 i = 0; i < consumers.length; i++) { + if (consumers[i] == consumer) { + address last = consumers[lastConsumerIndex]; + // Storage write to preserve last element + s_subscriptionConfigs[subId].consumers[i] = last; + // Storage remove last element + s_subscriptionConfigs[subId].consumers.pop(); + break; + } + } + delete s_consumers[consumer][subId]; + emit SubscriptionConsumerRemoved(subId, consumer); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function addConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { + // Already maxed, cannot add any more consumers. + if (s_subscriptionConfigs[subId].consumers.length == MAX_CONSUMERS) { + revert TooManyConsumers(); + } + if (s_consumers[consumer][subId] != 0) { + // Idempotence - do nothing if already added. + // Ensures uniqueness in s_subscriptions[subId].consumers. + return; + } + // Initialize the nonce to 1, indicating the consumer is allocated. + s_consumers[consumer][subId] = 1; + s_subscriptionConfigs[subId].consumers.push(consumer); + + emit SubscriptionConsumerAdded(subId, consumer); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + */ + function cancelSubscription(uint64 subId, address to) external override onlySubOwner(subId) nonReentrant { + if (pendingRequestExists(subId)) { + revert PendingRequestExists(); + } + cancelSubscriptionHelper(subId, to); + } + + function cancelSubscriptionHelper(uint64 subId, address to) private nonReentrant { + SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; + Subscription memory sub = s_subscriptions[subId]; + uint96 balance = sub.balance; + // Note bounded by MAX_CONSUMERS; + // If no consumers, does nothing. + for (uint256 i = 0; i < subConfig.consumers.length; i++) { + delete s_consumers[subConfig.consumers[i]][subId]; + } + delete s_subscriptionConfigs[subId]; + delete s_subscriptions[subId]; + s_totalBalance -= balance; + if (!LINK.transfer(to, uint256(balance))) { + revert InsufficientBalance(); + } + emit SubscriptionCanceled(subId, to, balance); + } + + /** + * @inheritdoc VRFCoordinatorV2Interface + * @dev Looping is bounded to MAX_CONSUMERS*(number of keyhashes). + * @dev Used to disable subscription canceling while outstanding request are present. + */ + function pendingRequestExists(uint64 subId) public view override returns (bool) { + SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; + for (uint256 i = 0; i < subConfig.consumers.length; i++) { + for (uint256 j = 0; j < s_provingKeyHashes.length; j++) { + (uint256 reqId, ) = computeRequestId( + s_provingKeyHashes[j], + subConfig.consumers[i], + subId, + s_consumers[subConfig.consumers[i]][subId] + ); + if (s_requestCommitments[reqId] != 0) { + return true; + } + } + } + return false; + } + + modifier onlySubOwner(uint64 subId) { + address owner = s_subscriptionConfigs[subId].owner; + if (owner == address(0)) { + revert InvalidSubscription(); + } + if (msg.sender != owner) { + revert MustBeSubOwner(owner); + } + _; + } + + modifier nonReentrant() { + if (s_config.reentrancyLock) { + revert Reentrant(); + } + _; + } + + /** + * @notice The type and version of this contract + * @return Type and version string + */ + function typeAndVersion() external pure virtual override returns (string memory) { + return "VRFCoordinatorV2 1.0.0"; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol new file mode 100644 index 0000000..c5d1d90 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; + +// Ideally this contract should inherit from VRFCoordinatorV2 and delegate calls to VRFCoordinatorV2 +// However, due to exceeding contract size limit, the logic from VRFCoordinatorV2 is ported over to this contract +contract VRFCoordinatorV2TestHelper { + uint96 internal s_paymentAmount; + + AggregatorV3Interface public immutable LINK_ETH_FEED; + + struct Config { + uint16 minimumRequestConfirmations; + uint32 maxGasLimit; + // Reentrancy protection. + bool reentrancyLock; + // stalenessSeconds is how long before we consider the feed price to be stale + // and fallback to fallbackWeiPerUnitLink. + uint32 stalenessSeconds; + // Gas to cover oracle payment after we calculate the payment. + // We make it configurable in case those operations are repriced. + uint32 gasAfterPaymentCalculation; + } + int256 private s_fallbackWeiPerUnitLink; + Config private s_config; + + constructor( + address linkEthFeed // solhint-disable-next-line no-empty-blocks + ) { + LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); + } + + function calculatePaymentAmountTest( + uint256 gasAfterPaymentCalculation, + uint32 fulfillmentFlatFeeLinkPPM, + uint256 weiPerUnitGas + ) external { + s_paymentAmount = calculatePaymentAmount( + gasleft(), + gasAfterPaymentCalculation, + fulfillmentFlatFeeLinkPPM, + weiPerUnitGas + ); + } + + error InvalidLinkWeiPrice(int256 linkWei); + error PaymentTooLarge(); + + function getFeedData() private view returns (int256) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); + // solhint-disable-next-line not-rely-on-time + if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_fallbackWeiPerUnitLink; + } + return weiPerUnitLink; + } + + // Get the amount of gas used for fulfillment + function calculatePaymentAmount( + uint256 startGas, + uint256 gasAfterPaymentCalculation, + uint32 fulfillmentFlatFeeLinkPPM, + uint256 weiPerUnitGas + ) internal view returns (uint96) { + int256 weiPerUnitLink; + weiPerUnitLink = getFeedData(); + if (weiPerUnitLink <= 0) { + revert InvalidLinkWeiPrice(weiPerUnitLink); + } + // (1e18 juels/link) (wei/gas * gas) / (wei/link) = juels + uint256 paymentNoFee = (1e18 * weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft())) / + uint256(weiPerUnitLink); + uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); + if (paymentNoFee > (1e27 - fee)) { + revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. + } + return uint96(paymentNoFee + fee); + } + + function getPaymentAmount() public view returns (uint96) { + return s_paymentAmount; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol new file mode 100644 index 0000000..ee2a71d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +contract VRFExternalSubOwnerExample is VRFConsumerBaseV2 { + VRFCoordinatorV2Interface internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + + uint256[] public s_randomWords; + uint256 public s_requestId; + address internal s_owner; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + s_owner = msg.sender; + } + + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + s_randomWords = randomWords; + } + + function requestRandomWords( + uint64 subId, + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash + ) external onlyOwner { + // Will revert if subscription is not funded. + s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, requestConfirmations, callbackGasLimit, numWords); + } + + function transferOwnership(address newOwner) external onlyOwner { + s_owner = newOwner; + } + + modifier onlyOwner() { + require(msg.sender == s_owner); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol new file mode 100644 index 0000000..0193e3f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +/** + * @title The VRFLoadTestExternalSubOwner contract. + * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. + */ +contract VRFLoadTestExternalSubOwner is VRFConsumerBaseV2, ConfirmedOwner { + VRFCoordinatorV2Interface public immutable COORDINATOR; + LinkTokenInterface public immutable LINK; + + uint256 public s_responseCount; + + constructor(address _vrfCoordinator, address _link) VRFConsumerBaseV2(_vrfCoordinator) ConfirmedOwner(msg.sender) { + COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); + LINK = LinkTokenInterface(_link); + } + + function fulfillRandomWords(uint256, uint256[] memory) internal override { + s_responseCount++; + } + + function requestRandomWords( + uint64 _subId, + uint16 _requestConfirmations, + bytes32 _keyHash, + uint16 _requestCount + ) external onlyOwner { + for (uint16 i = 0; i < _requestCount; i++) { + COORDINATOR.requestRandomWords(_keyHash, _subId, _requestConfirmations, 50_000, 1); + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol new file mode 100644 index 0000000..a967c8a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFConsumerBase} from "../VRFConsumerBase.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; + +/** + * @title The VRFLoadTestOwnerlessConsumer contract. + * @notice Allows making many VRF V1 randomness requests in a single transaction for load testing. + */ +contract VRFLoadTestOwnerlessConsumer is VRFConsumerBase, IERC677Receiver { + // The price of each VRF request in Juels. 1 LINK = 1e18 Juels. + uint256 public immutable PRICE; + + uint256 public s_responseCount; + + constructor(address _vrfCoordinator, address _link, uint256 _price) VRFConsumerBase(_vrfCoordinator, _link) { + PRICE = _price; + } + + function fulfillRandomness(bytes32, uint256) internal override { + s_responseCount++; + } + + /** + * @dev Creates as many randomness requests as can be made with the funds transferred. + * @param _amount The amount of LINK transferred to pay for these requests. + * @param _data The data passed to transferAndCall on LinkToken. Must be an abi-encoded key hash. + */ + function onTokenTransfer(address, uint256 _amount, bytes calldata _data) external override { + if (msg.sender != address(LINK)) { + revert("only callable from LINK"); + } + bytes32 keyHash = abi.decode(_data, (bytes32)); + + uint256 spent = 0; + while (spent + PRICE <= _amount) { + requestRandomness(keyHash, PRICE); + spent += PRICE; + } + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol new file mode 100644 index 0000000..be416e9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +contract VRFMaliciousConsumerV2 is VRFConsumerBaseV2 { + uint256[] public s_randomWords; + uint256 public s_requestId; + VRFCoordinatorV2Interface internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint64 public s_subId; + uint256 public s_gasAvailable; + bytes32 internal s_keyHash; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + s_gasAvailable = gasleft(); + s_randomWords = randomWords; + s_requestId = requestId; + // Should revert + COORDINATOR.requestRandomWords(s_keyHash, s_subId, 1, 200000, 1); + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness(bytes32 keyHash) external returns (uint256) { + s_keyHash = keyHash; + return COORDINATOR.requestRandomWords(keyHash, s_subId, 1, 500000, 1); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol new file mode 100644 index 0000000..4052c0d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "../../shared/interfaces/AggregatorV3Interface.sol"; + +contract VRFMockETHLINKAggregator is AggregatorV3Interface { + int256 public answer; + uint256 private blockTimestampDeduction = 0; + + constructor(int256 _answer) { + answer = _answer; + } + + function decimals() external pure override returns (uint8) { + return 18; + } + + function description() external pure override returns (string memory) { + return "VRFMockETHLINKAggregator"; + } + + function version() external pure override returns (uint256) { + return 1; + } + + function getRoundData( + uint80 /*_roundId*/ + ) + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function latestRoundData() + external + view + override + returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) + { + return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); + } + + function getDeductedBlockTimestamp() internal view returns (uint256) { + return block.timestamp - blockTimestampDeduction; + } + + function setBlockTimestampDeduction(uint256 _blockTimestampDeduction) external { + blockTimestampDeduction = _blockTimestampDeduction; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol new file mode 100644 index 0000000..a641267 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// An example VRF V1 consumer contract that can be triggered using a transferAndCall from the link +// contract. +pragma solidity ^0.8.4; + +import {VRFConsumerBase} from "../VRFConsumerBase.sol"; +import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; + +contract VRFOwnerlessConsumerExample is VRFConsumerBase, IERC677Receiver { + uint256 public s_randomnessOutput; + bytes32 public s_requestId; + + error OnlyCallableFromLink(); + + constructor(address _vrfCoordinator, address _link) VRFConsumerBase(_vrfCoordinator, _link) { + /* empty */ + } + + function fulfillRandomness(bytes32 requestId, uint256 _randomness) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + s_randomnessOutput = _randomness; + } + + /** + * @dev Creates a new randomness request. This function can only be used by calling + * transferAndCall on the LinkToken contract. + * @param _amount The amount of LINK transferred to pay for this request. + * @param _data The data passed to transferAndCall on LinkToken. Must be an abi-encoded key hash. + */ + function onTokenTransfer(address /* sender */, uint256 _amount, bytes calldata _data) external override { + if (msg.sender != address(LINK)) { + revert OnlyCallableFromLink(); + } + + bytes32 keyHash = abi.decode(_data, (bytes32)); + s_requestId = requestRandomness(keyHash, _amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol new file mode 100644 index 0000000..344797f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFRequestIDBase} from "../VRFRequestIDBase.sol"; + +contract VRFRequestIDBaseTestHelper is VRFRequestIDBase { + function makeVRFInputSeed_( + bytes32 _keyHash, + uint256 _userSeed, + address _requester, + uint256 _nonce + ) public pure returns (uint256) { + return makeVRFInputSeed(_keyHash, _userSeed, _requester, _nonce); + } + + function makeRequestId_(bytes32 _keyHash, uint256 _vRFInputSeed) public pure returns (bytes32) { + return makeRequestId(_keyHash, _vRFInputSeed); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol new file mode 100644 index 0000000..303394e --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT +// Example of a single consumer contract which owns the subscription. +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +contract VRFSingleConsumerExample is VRFConsumerBaseV2 { + VRFCoordinatorV2Interface internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + + struct RequestConfig { + uint64 subId; + uint32 callbackGasLimit; + uint16 requestConfirmations; + uint32 numWords; + bytes32 keyHash; + } + RequestConfig public s_requestConfig; + uint256[] public s_randomWords; + uint256 public s_requestId; + address s_owner; + + constructor( + address vrfCoordinator, + address link, + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash + ) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + s_owner = msg.sender; + s_requestConfig = RequestConfig({ + subId: 0, // Unset initially + callbackGasLimit: callbackGasLimit, + requestConfirmations: requestConfirmations, + numWords: numWords, + keyHash: keyHash + }); + subscribe(); + } + + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + require(requestId == s_requestId, "request ID is incorrect"); + s_randomWords = randomWords; + } + + // Assumes the subscription is funded sufficiently. + function requestRandomWords() external onlyOwner { + RequestConfig memory rc = s_requestConfig; + // Will revert if subscription is not set and funded. + s_requestId = COORDINATOR.requestRandomWords( + rc.keyHash, + rc.subId, + rc.requestConfirmations, + rc.callbackGasLimit, + rc.numWords + ); + } + + // Assumes this contract owns link + // This method is analogous to VRFv1, except the amount + // should be selected based on the keyHash (each keyHash functions like a "gas lane" + // with different link costs). + function fundAndRequestRandomWords(uint256 amount) external onlyOwner { + RequestConfig memory rc = s_requestConfig; + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_requestConfig.subId)); + // Will revert if subscription is not set and funded. + s_requestId = COORDINATOR.requestRandomWords( + rc.keyHash, + rc.subId, + rc.requestConfirmations, + rc.callbackGasLimit, + rc.numWords + ); + } + + // Assumes this contract owns link + function topUpSubscription(uint256 amount) external onlyOwner { + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_requestConfig.subId)); + } + + function withdraw(uint256 amount, address to) external onlyOwner { + LINKTOKEN.transfer(to, amount); + } + + function unsubscribe(address to) external onlyOwner { + // Returns funds to this address + COORDINATOR.cancelSubscription(s_requestConfig.subId, to); + s_requestConfig.subId = 0; + } + + // Keep this separate in case the contract want to unsubscribe and then + // resubscribe. + function subscribe() public onlyOwner { + // Create a subscription, current subId + address[] memory consumers = new address[](1); + consumers[0] = address(this); + s_requestConfig.subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_requestConfig.subId, consumers[0]); + } + + modifier onlyOwner() { + require(msg.sender == s_owner); + _; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol new file mode 100644 index 0000000..471b6f9 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.6; + +import {VRFSubscriptionBalanceMonitor} from "../dev/VRFSubscriptionBalanceMonitor.sol"; + +contract VRFSubscriptionBalanceMonitorExposed is VRFSubscriptionBalanceMonitor { + constructor( + address linkTokenAddress, + address coordinatorAddress, + address keeperRegistryAddress, + uint256 minWaitPeriodSeconds + ) VRFSubscriptionBalanceMonitor(linkTokenAddress, coordinatorAddress, keeperRegistryAddress, minWaitPeriodSeconds) {} + + function setLastTopUpXXXTestOnly(uint64 target, uint56 lastTopUpTimestamp) external { + s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol new file mode 100644 index 0000000..4b794d4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRF} from "../VRF.sol"; + +/** *********************************************************************** + @notice Testing harness for VRF.sol, exposing its internal methods. Not to + @notice be used for production. +*/ +contract VRFTestHelper is VRF { + function bigModExp_(uint256 base, uint256 exponent) public view returns (uint256) { + return super._bigModExp(base, exponent); + } + + function squareRoot_(uint256 x) public view returns (uint256) { + return super._squareRoot(x); + } + + function ySquared_(uint256 x) public pure returns (uint256) { + return super._ySquared(x); + } + + function fieldHash_(bytes memory b) public pure returns (uint256) { + return super._fieldHash(b); + } + + function hashToCurve_(uint256[2] memory pk, uint256 x) public view returns (uint256[2] memory) { + return super._hashToCurve(pk, x); + } + + function ecmulVerify_(uint256[2] memory x, uint256 scalar, uint256[2] memory q) public pure returns (bool) { + return super._ecmulVerify(x, scalar, q); + } + + function projectiveECAdd_( + uint256 px, + uint256 py, + uint256 qx, + uint256 qy + ) public pure returns (uint256, uint256, uint256) { + return super._projectiveECAdd(px, py, qx, qy); + } + + function affineECAdd_( + uint256[2] memory p1, + uint256[2] memory p2, + uint256 invZ + ) public pure returns (uint256[2] memory) { + return super._affineECAdd(p1, p2, invZ); + } + + function verifyLinearCombinationWithGenerator_( + uint256 c, + uint256[2] memory p, + uint256 s, + address lcWitness + ) public pure returns (bool) { + return super._verifyLinearCombinationWithGenerator(c, p, s, lcWitness); + } + + function linearCombination_( + uint256 c, + uint256[2] memory p1, + uint256[2] memory cp1Witness, + uint256 s, + uint256[2] memory p2, + uint256[2] memory sp2Witness, + uint256 zInv + ) public pure returns (uint256[2] memory) { + return super._linearCombination(c, p1, cp1Witness, s, p2, sp2Witness, zInv); + } + + function scalarFromCurvePoints_( + uint256[2] memory hash, + uint256[2] memory pk, + uint256[2] memory gamma, + address uWitness, + uint256[2] memory v + ) public pure returns (uint256) { + return super._scalarFromCurvePoints(hash, pk, gamma, uWitness, v); + } + + function isOnCurve_(uint256[2] memory p) public pure returns (bool) { + return super._isOnCurve(p); + } + + function verifyVRFProof_( + uint256[2] memory pk, + uint256[2] memory gamma, + uint256 c, + uint256 s, + uint256 seed, + address uWitness, + uint256[2] memory cGammaWitness, + uint256[2] memory sHashWitness, + uint256 zInv + ) public view { + super._verifyVRFProof(pk, gamma, c, s, seed, uWitness, cGammaWitness, sHashWitness, zInv); + } + + function randomValueFromVRFProof_(Proof calldata proof, uint256 seed) public view returns (uint256 output) { + return super._randomValueFromVRFProof(proof, seed); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol new file mode 100644 index 0000000..b4d0104 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; + +/** + * @title The VRFLoadTestExternalSubOwner contract. + * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. + */ +contract VRFV2LoadTestWithMetrics is VRFConsumerBaseV2 { + VRFCoordinatorV2Interface public immutable COORDINATOR; + LinkTokenInterface public LINKTOKEN; + uint256 public s_responseCount; + uint256 public s_requestCount; + uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision + uint256 public s_slowestFulfillment = 0; + uint256 public s_fastestFulfillment = 999; + uint256 public s_lastRequestId; + mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made + + event SubscriptionCreatedFundedAndConsumerAdded(uint64 subId, address consumer, uint256 amount); + + struct RequestStatus { + bool fulfilled; + uint256[] randomWords; + uint requestTimestamp; + uint fulfilmentTimestamp; + uint256 requestBlockNumber; + uint256 fulfilmentBlockNumber; + } + + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor(address _vrfCoordinator) VRFConsumerBaseV2(_vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); + } + + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); + uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; + uint256 requestDelayInMillions = requestDelay * 1_000_000; + + if (requestDelay > s_slowestFulfillment) { + s_slowestFulfillment = requestDelay; + } + s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; + s_averageFulfillmentInMillions = s_responseCount > 0 + ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) + : requestDelayInMillions; + + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + s_requests[_requestId].fulfilmentTimestamp = block.timestamp; + s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; + + s_responseCount++; + } + + function requestRandomWords( + uint64 _subId, + uint16 _requestConfirmations, + bytes32 _keyHash, + uint32 _callbackGasLimit, + uint32 _numWords, + uint16 _requestCount + ) external { + _makeLoadTestRequests(_subId, _requestConfirmations, _keyHash, _callbackGasLimit, _numWords, _requestCount); + } + + function requestRandomWordsWithForceFulfill( + uint16 _requestConfirmations, + bytes32 _keyHash, + uint32 _callbackGasLimit, + uint32 _numWords, + uint16 _requestCount, + uint256 _subTopUpAmount, + address _link + ) external { + // create a subscription, address(this) will be the owner + uint64 _subId = COORDINATOR.createSubscription(); + // add address(this) as a consumer on the subscription + COORDINATOR.addConsumer(_subId, address(this)); + topUpSubscription(_subId, _subTopUpAmount, _link); + emit SubscriptionCreatedFundedAndConsumerAdded(_subId, address(this), _subTopUpAmount); + + _makeLoadTestRequests(_subId, _requestConfirmations, _keyHash, _callbackGasLimit, _numWords, _requestCount); + + COORDINATOR.removeConsumer(_subId, address(this)); + COORDINATOR.cancelSubscription(_subId, msg.sender); + } + + function reset() external { + s_averageFulfillmentInMillions = 0; // in millions for better precision + s_slowestFulfillment = 0; + s_fastestFulfillment = 999; + s_requestCount = 0; + s_responseCount = 0; + } + + function getRequestStatus( + uint256 _requestId + ) + external + view + returns ( + bool fulfilled, + uint256[] memory randomWords, + uint requestTimestamp, + uint fulfilmentTimestamp, + uint256 requestBlockNumber, + uint256 fulfilmentBlockNumber + ) + { + RequestStatus memory request = s_requests[_requestId]; + return ( + request.fulfilled, + request.randomWords, + request.requestTimestamp, + request.fulfilmentTimestamp, + request.requestBlockNumber, + request.fulfilmentBlockNumber + ); + } + + function _makeLoadTestRequests( + uint64 _subId, + uint16 _requestConfirmations, + bytes32 _keyHash, + uint32 _callbackGasLimit, + uint32 _numWords, + uint16 _requestCount + ) internal { + for (uint16 i = 0; i < _requestCount; i++) { + uint256 requestId = COORDINATOR.requestRandomWords( + _keyHash, + _subId, + _requestConfirmations, + _callbackGasLimit, + _numWords + ); + s_lastRequestId = requestId; + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + s_requests[requestId] = RequestStatus({ + randomWords: new uint256[](0), + fulfilled: false, + requestTimestamp: block.timestamp, + fulfilmentTimestamp: 0, + requestBlockNumber: requestBlockNumber, + fulfilmentBlockNumber: 0 + }); + s_requestCount++; + requestHeights[requestId] = requestBlockNumber; + } + } + + function topUpSubscription(uint64 _subId, uint256 _amount, address _link) public { + LINKTOKEN = LinkTokenInterface(_link); + LINKTOKEN.transferAndCall(address(COORDINATOR), _amount, abi.encode(_subId)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol new file mode 100644 index 0000000..8f1b275 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; + +contract VRFV2OwnerTestConsumer is VRFConsumerBaseV2, ConfirmedOwner { + VRFCoordinatorV2Interface public COORDINATOR; + LinkTokenInterface public LINKTOKEN; + uint64 public subId; + uint256 public s_responseCount; + uint256 public s_requestCount; + uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision + uint256 public s_slowestFulfillment = 0; + uint256 public s_fastestFulfillment = 999; + uint256 public s_lastRequestId; + mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made + + event SubscriptionCreatedFundedAndConsumerAdded(uint64 subId, address consumer, uint256 amount); + + struct RequestStatus { + bool fulfilled; + uint256[] randomWords; + uint requestTimestamp; + uint fulfilmentTimestamp; + uint256 requestBlockNumber; + uint256 fulfilmentBlockNumber; + } + + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor(address _vrfCoordinator, address _link) VRFConsumerBaseV2(_vrfCoordinator) ConfirmedOwner(msg.sender) { + COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); + LINKTOKEN = LinkTokenInterface(_link); + } + + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); + uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; + uint256 requestDelayInMillions = requestDelay * 1_000_000; + + if (requestDelay > s_slowestFulfillment) { + s_slowestFulfillment = requestDelay; + } + s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; + s_averageFulfillmentInMillions = s_responseCount > 0 + ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) + : requestDelayInMillions; + + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + s_requests[_requestId].fulfilmentTimestamp = block.timestamp; + s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; + + s_responseCount++; + } + + function requestRandomWords( + uint16 _requestConfirmations, + bytes32 _keyHash, + uint32 _callbackGasLimit, + uint32 _numWords, + uint16 _requestCount, + uint256 _subTopUpAmount + ) external onlyOwner { + // create a subscription, address(this) will be the owner + subId = COORDINATOR.createSubscription(); + // add address(this) as a consumer on the subscription + COORDINATOR.addConsumer(subId, address(this)); + topUpSubscription(_subTopUpAmount); + emit SubscriptionCreatedFundedAndConsumerAdded(subId, address(this), _subTopUpAmount); + + for (uint16 i = 0; i < _requestCount; i++) { + uint256 requestId = COORDINATOR.requestRandomWords( + _keyHash, + subId, + _requestConfirmations, + _callbackGasLimit, + _numWords + ); + s_lastRequestId = requestId; + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + s_requests[requestId] = RequestStatus({ + randomWords: new uint256[](0), + fulfilled: false, + requestTimestamp: block.timestamp, + fulfilmentTimestamp: 0, + requestBlockNumber: requestBlockNumber, + fulfilmentBlockNumber: 0 + }); + s_requestCount++; + requestHeights[requestId] = requestBlockNumber; + } + + COORDINATOR.removeConsumer(subId, address(this)); + COORDINATOR.cancelSubscription(subId, msg.sender); + } + + function reset() external { + s_averageFulfillmentInMillions = 0; // in millions for better precision + s_slowestFulfillment = 0; + s_fastestFulfillment = 999; + s_requestCount = 0; + s_responseCount = 0; + } + + function getRequestStatus( + uint256 _requestId + ) + external + view + returns ( + bool fulfilled, + uint256[] memory randomWords, + uint requestTimestamp, + uint fulfilmentTimestamp, + uint256 requestBlockNumber, + uint256 fulfilmentBlockNumber + ) + { + RequestStatus memory request = s_requests[_requestId]; + return ( + request.fulfilled, + request.randomWords, + request.requestTimestamp, + request.fulfilmentTimestamp, + request.requestBlockNumber, + request.fulfilmentBlockNumber + ); + } + + function topUpSubscription(uint256 amount) public onlyOwner { + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(subId)); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol new file mode 100644 index 0000000..4b0a7fd --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; + +contract VRFV2ProxyAdmin is ProxyAdmin { + // Nothing here, this is just to generate the gethwrapper for tests. +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol new file mode 100644 index 0000000..3d9cf30 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; + +// VRFV2RevertingExample will always revert. Used for testing only, useless in prod. +contract VRFV2RevertingExample is VRFConsumerBaseV2 { + uint256[] public s_randomWords; + uint256 public s_requestId; + VRFCoordinatorV2Interface internal COORDINATOR; + LinkTokenInterface internal LINKTOKEN; + uint64 public s_subId; + uint256 public s_gasAvailable; + + constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + } + + function fulfillRandomWords(uint256, uint256[] memory) internal pure override { + // solhint-disable-next-line gas-custom-errors, reason-string + revert(); + } + + function createSubscriptionAndFund(uint96 amount) external { + if (s_subId == 0) { + s_subId = COORDINATOR.createSubscription(); + COORDINATOR.addConsumer(s_subId, address(this)); + } + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function topUpSubscription(uint96 amount) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "sub not set"); + // Approve the link transfer. + LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); + } + + function updateSubscription(address[] memory consumers) external { + // solhint-disable-next-line gas-custom-errors + require(s_subId != 0, "subID not set"); + for (uint256 i = 0; i < consumers.length; i++) { + COORDINATOR.addConsumer(s_subId, consumers[i]); + } + } + + function requestRandomness( + bytes32 keyHash, + uint64 subId, + uint16 minReqConfs, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256) { + s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); + return s_requestId; + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol new file mode 100644 index 0000000..f3364d0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +contract VRFV2TransparentUpgradeableProxy is TransparentUpgradeableProxy { + // Nothing special here, this is just to generate the gethwrapper for tests. + constructor( + address _logic, + address admin_, + bytes memory _data + ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol new file mode 100644 index 0000000..924e3e4 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +contract VRFV2WrapperConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { + event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); + event WrapperRequestMade(uint256 indexed requestId, uint256 paid); + + struct RequestStatus { + uint256 paid; + bool fulfilled; + uint256[] randomWords; + } + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + constructor( + address _link, + address _vrfV2Wrapper + ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} + + function makeRequest( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) external onlyOwner returns (uint256 requestId) { + requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); + uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); + s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false}); + emit WrapperRequestMade(requestId, paid); + return requestId; + } + + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); + } + + function getRequestStatus( + uint256 _requestId + ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + RequestStatus memory request = s_requests[_requestId]; + return (request.paid, request.fulfilled, request.randomWords); + } + + /// @notice withdrawLink withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in juels + function withdrawLink(uint256 amount) external onlyOwner { + LINK.transfer(owner(), amount); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol new file mode 100644 index 0000000..3da8f17 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; +import {VRFV2WrapperInterface} from "../interfaces/VRFV2WrapperInterface.sol"; + +contract VRFV2WrapperLoadTestConsumer is VRFV2WrapperConsumerBase, ConfirmedOwner { + VRFV2WrapperInterface public immutable i_vrfV2Wrapper; + uint256 public s_responseCount; + uint256 public s_requestCount; + uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision + uint256 public s_slowestFulfillment = 0; + uint256 public s_fastestFulfillment = 999; + uint256 public s_lastRequestId; + // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore + mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made + mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; + + event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); + event WrapperRequestMade(uint256 indexed requestId, uint256 paid); + + struct RequestStatus { + uint256 paid; + bool fulfilled; + uint256[] randomWords; + uint256 requestTimestamp; + uint256 fulfilmentTimestamp; + uint256 requestBlockNumber; + uint256 fulfilmentBlockNumber; + } + + constructor( + address _link, + address _vrfV2Wrapper + ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) { + i_vrfV2Wrapper = VRFV2WrapperInterface(_vrfV2Wrapper); + } + + function makeRequests( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords, + uint16 _requestCount + ) external { + for (uint16 i = 0; i < _requestCount; i++) { + uint256 requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); + s_lastRequestId = requestId; + uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); + uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); + s_requests[requestId] = RequestStatus({ + paid: paid, + fulfilled: false, + randomWords: new uint256[](0), + requestTimestamp: block.timestamp, + fulfilmentTimestamp: 0, + requestBlockNumber: requestBlockNumber, + fulfilmentBlockNumber: 0 + }); + s_requestCount++; + requestHeights[requestId] = requestBlockNumber; + emit WrapperRequestMade(requestId, paid); + } + } + + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); + uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; + uint256 requestDelayInMillions = requestDelay * 1_000_000; + + if (requestDelay > s_slowestFulfillment) { + s_slowestFulfillment = requestDelay; + } + if (requestDelay < s_fastestFulfillment) { + s_fastestFulfillment = requestDelay; + } + s_averageFulfillmentInMillions = s_responseCount > 0 + ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) + : requestDelayInMillions; + + s_responseCount++; + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + s_requests[_requestId].fulfilmentTimestamp = block.timestamp; + s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; + + emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); + } + + function getRequestStatus( + uint256 _requestId + ) + external + view + returns ( + uint256 paid, + bool fulfilled, + uint256[] memory randomWords, + uint256 requestTimestamp, + uint256 fulfilmentTimestamp, + uint256 requestBlockNumber, + uint256 fulfilmentBlockNumber + ) + { + // solhint-disable-next-line gas-custom-errors + require(s_requests[_requestId].paid > 0, "request not found"); + RequestStatus memory request = s_requests[_requestId]; + return ( + request.paid, + request.fulfilled, + request.randomWords, + request.requestTimestamp, + request.fulfilmentTimestamp, + request.requestBlockNumber, + request.fulfilmentBlockNumber + ); + } + + /// @notice withdrawLink withdraws the amount specified in amount to the owner + /// @param amount the amount to withdraw, in juels + function withdrawLink(uint256 amount) external onlyOwner { + LINK.transfer(owner(), amount); + } + + function reset() external { + s_averageFulfillmentInMillions = 0; + s_slowestFulfillment = 0; + s_fastestFulfillment = 999; + s_requestCount = 0; + s_responseCount = 0; + } + + receive() external payable {} +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol new file mode 100644 index 0000000..353027d --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +contract VRFV2WrapperOutOfGasConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { + constructor( + address _link, + address _vrfV2Wrapper + ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} + + function makeRequest( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) external onlyOwner returns (uint256 requestId) { + return requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); + } + + function fulfillRandomWords(uint256 /* _requestId */, uint256[] memory /* _randomWords */) internal view override { + while (gasleft() > 0) {} + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol new file mode 100644 index 0000000..d78992a --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.6; + +import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; + +contract VRFV2WrapperRevertingConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { + constructor( + address _link, + address _vrfV2Wrapper + ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} + + function makeRequest( + uint32 _callbackGasLimit, + uint16 _requestConfirmations, + uint32 _numWords + ) external onlyOwner returns (uint256 requestId) { + return requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); + } + + function fulfillRandomWords(uint256 /* _requestId */, uint256[] memory /* _randomWords */) internal pure override { + revert("reverting example"); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol new file mode 100644 index 0000000..3bae36f --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {VRFV2WrapperInterface} from "../interfaces/VRFV2WrapperInterface.sol"; + +contract VRFV2WrapperUnderFundingConsumer is ConfirmedOwner { + LinkTokenInterface internal immutable LINK; + VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; + + constructor(address _link, address _vrfV2Wrapper) ConfirmedOwner(msg.sender) { + LINK = LinkTokenInterface(_link); + VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); + } + + function makeRequest(uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords) external onlyOwner { + LINK.transferAndCall( + address(VRF_V2_WRAPPER), + // Pay less than the needed amount + VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit) - 1, + abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) + ); + } +} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol new file mode 100644 index 0000000..4ec7ad0 --- /dev/null +++ b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +// An example of a consumer contract that relies on a subscription for funding. +pragma solidity 0.8.6; + +import "../interfaces/VRFCoordinatorV2Interface.sol"; +import "../VRFConsumerBaseV2.sol"; +import "../../shared/access/ConfirmedOwner.sol"; + +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + +contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner { + event RequestSent(uint256 requestId, uint32 numWords); + event RequestFulfilled(uint256 requestId, uint256[] randomWords); + + struct RequestStatus { + bool fulfilled; // whether the request has been successfully fulfilled + bool exists; // whether a requestId exists + uint256[] randomWords; + } + mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ + VRFCoordinatorV2Interface COORDINATOR; + + // past requests Id. + uint256[] public requestIds; + uint256 public lastRequestId; + + constructor(address vrfCoordinator) VRFConsumerBaseV2(vrfCoordinator) ConfirmedOwner(msg.sender) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + } + + // Assumes the subscription is funded sufficiently. + function requestRandomWords( + uint64 subId, + uint32 callbackGasLimit, + uint16 requestConfirmations, + uint32 numWords, + bytes32 keyHash + ) external onlyOwner returns (uint256 requestId) { + // Will revert if subscription is not set and funded. + requestId = COORDINATOR.requestRandomWords(keyHash, subId, requestConfirmations, callbackGasLimit, numWords); + s_requests[requestId] = RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false}); + requestIds.push(requestId); + lastRequestId = requestId; + emit RequestSent(requestId, numWords); + return requestId; + } + + function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { + require(s_requests[_requestId].exists, "request not found"); + s_requests[_requestId].fulfilled = true; + s_requests[_requestId].randomWords = _randomWords; + emit RequestFulfilled(_requestId, _randomWords); + } + + function getRequestStatus(uint256 _requestId) external view returns (bool fulfilled, uint256[] memory randomWords) { + require(s_requests[_requestId].exists, "request not found"); + RequestStatus memory request = s_requests[_requestId]; + return (request.fulfilled, request.randomWords); + } +} diff --git a/packages/foundry/lib/foundry-chainlink-toolkit b/packages/foundry/lib/foundry-chainlink-toolkit deleted file mode 160000 index d610ec9..0000000 --- a/packages/foundry/lib/foundry-chainlink-toolkit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d610ec9ef54c325de7de1a5622c19933b2ae26cf diff --git a/packages/foundry/remappings.txt b/packages/foundry/remappings.txt index 466e4ce..bb98326 100644 --- a/packages/foundry/remappings.txt +++ b/packages/foundry/remappings.txt @@ -4,4 +4,5 @@ forge-std/=lib/v4-core/lib/forge-std/src/ permit2/=lib/v4-periphery/lib/permit2/ solmate/=lib/v4-core/lib/solmate/ v4-core/=lib/v4-core/ -@v4-periphery/=lib/v4-periphery/ \ No newline at end of file +@v4-periphery/=lib/v4-periphery/ +@chainlink/=lib/chainlink/ \ No newline at end of file diff --git a/packages/foundry/src/EtfHook.sol b/packages/foundry/src/EtfHook.sol index 19fe889..6e27172 100644 --- a/packages/foundry/src/EtfHook.sol +++ b/packages/foundry/src/EtfHook.sol @@ -10,6 +10,7 @@ import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol"; import {BalanceDelta} from "v4-core/src/types/BalanceDelta.sol"; import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "v4-core/src/types/BeforeSwapDelta.sol"; import {ETFManager} from "./EtfToken.sol"; +import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; // Copied from [chronicle-std](https://github.com/chronicleprotocol/chronicle-std/blob/main/src/IChronicle.sol). @@ -117,12 +118,18 @@ contract ETFHook is ETFManager, BaseHook { return BaseHook.beforeRemoveLiquidity.selector; } - // returns each token prices from oracle + // returns each token prices from chronicle oracle function chroniclegetPrices() public view returns (uint256[2] memory prices) { // TODO: use chainlink, pyth, chronicle return [IChronicle(Chronicle_ETH_USD_3).read(), IChronicle(Chronicle_BTC_USD_3).read()]; } + // returns each token prices from chainlink oracle + function chainlinkgetPrices() public view returns (uint256[2] memory prices) { + return [AggregatorV3Interface(Chainlink_ETH_USD).latestRoundData(), AggregatorV3Interface(Chainlink_BTC_USD).latestRoundData()]; + } + + function checkIfRebalanceNeeded() private returns (bool) { uint256[2] memory prices = getPrices(); diff --git a/yarn.lock b/yarn.lock index 46b7fe6..6d17831 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,6 +26,46 @@ __metadata: languageName: node linkType: hard +"@arbitrum/nitro-contracts@npm:1.1.1": + version: 1.1.1 + resolution: "@arbitrum/nitro-contracts@npm:1.1.1" + dependencies: + "@offchainlabs/upgrade-executor": 1.1.0-beta.0 + "@openzeppelin/contracts": 4.5.0 + "@openzeppelin/contracts-upgradeable": 4.5.2 + patch-package: ^6.4.7 + checksum: 3e457098b5b0e70fc7444d2a1cf4471868301c0511deef67c4947f6cb63367766744ddb7b46239cb65d58d9f3ad08818089a243067c1b7dd207b1293060cc843 + languageName: node + linkType: hard + +"@arbitrum/nitro-contracts@npm:^1.0.0-beta.8": + version: 1.3.0 + resolution: "@arbitrum/nitro-contracts@npm:1.3.0" + dependencies: + "@offchainlabs/upgrade-executor": 1.1.0-beta.0 + "@openzeppelin/contracts": 4.5.0 + "@openzeppelin/contracts-upgradeable": 4.5.2 + patch-package: ^6.4.7 + checksum: 9f3d7080301851609fb190d79df4c2b37ac10408db58992687732d94f1a0138badb63afec03a2b611b0b634e6b37dfbe65abcbbf9f68ca70126a6ea0021a9c9f + languageName: node + linkType: hard + +"@arbitrum/token-bridge-contracts@npm:1.1.2": + version: 1.1.2 + resolution: "@arbitrum/token-bridge-contracts@npm:1.1.2" + dependencies: + "@arbitrum/nitro-contracts": ^1.0.0-beta.8 + "@offchainlabs/upgrade-executor": 1.1.0-beta.0 + "@openzeppelin/contracts": 4.8.3 + "@openzeppelin/contracts-upgradeable": 4.8.3 + "@openzeppelin/upgrades-core": ^1.24.1 + dependenciesMeta: + "@openzeppelin/upgrades-core": + optional: true + checksum: 526aafb541df793635c30a9a0a2b358274f450e2ccbb15eb0df52279f4fa845c3ba1511b886e21f1eba52baeb262c9e27e66ba8aca977a2461ddfe854aa799c7 + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.25.9": version: 7.26.2 resolution: "@babel/code-frame@npm:7.26.2" @@ -123,7 +163,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2": +"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.19.4, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.5.5": version: 7.26.0 resolution: "@babel/runtime@npm:7.26.0" dependencies: @@ -181,6 +221,279 @@ __metadata: languageName: node linkType: hard +"@chainlink/contracts@npm:^1.3.0": + version: 1.3.0 + resolution: "@chainlink/contracts@npm:1.3.0" + dependencies: + "@arbitrum/nitro-contracts": 1.1.1 + "@arbitrum/token-bridge-contracts": 1.1.2 + "@changesets/changelog-github": ^0.5.0 + "@changesets/cli": ~2.27.8 + "@eth-optimism/contracts": 0.6.0 + "@openzeppelin/contracts": 4.9.3 + "@openzeppelin/contracts-upgradeable": 4.9.3 + "@scroll-tech/contracts": 0.1.0 + "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9" + semver: ^7.6.3 + checksum: 170da3a3275074934608f992b5b392e7774d110480ab5d143ea4048d6deaeded129ffd092f00534098119dd03563337321aa2100d8d0d378a38195912c05c7f1 + languageName: node + linkType: hard + +"@changesets/apply-release-plan@npm:^7.0.5": + version: 7.0.5 + resolution: "@changesets/apply-release-plan@npm:7.0.5" + dependencies: + "@changesets/config": ^3.0.3 + "@changesets/get-version-range-type": ^0.4.0 + "@changesets/git": ^3.0.1 + "@changesets/should-skip-package": ^0.1.1 + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + detect-indent: ^6.0.0 + fs-extra: ^7.0.1 + lodash.startcase: ^4.4.0 + outdent: ^0.5.0 + prettier: ^2.7.1 + resolve-from: ^5.0.0 + semver: ^7.5.3 + checksum: f6a1b90d89fd08b46c11fad05d5fee510ff8a1888c163fd6221ccfb045eab013fa57c0c32c5697d6406852a39cf4df01b44f3ecca4746f30bd610bec54aa9abf + languageName: node + linkType: hard + +"@changesets/assemble-release-plan@npm:^6.0.4": + version: 6.0.4 + resolution: "@changesets/assemble-release-plan@npm:6.0.4" + dependencies: + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.1.2 + "@changesets/should-skip-package": ^0.1.1 + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + semver: ^7.5.3 + checksum: 948066a8ca8e12390599f641a0439b6a4d6c1c2a9958f58596aa50cf68d7d594b28acc1eb6bd0ad17df2025f0614006e44728a2614fad2a3d54c669568bf6d65 + languageName: node + linkType: hard + +"@changesets/changelog-git@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/changelog-git@npm:0.2.0" + dependencies: + "@changesets/types": ^6.0.0 + checksum: 132660f7fdabbdda00ac803cc822d6427a1a38a17a5f414e87ad32f6dc4cbef5280a147ecdc087a28dc06c8bd0762f8d6e7132d01b8a4142b59fbe1bc2177034 + languageName: node + linkType: hard + +"@changesets/changelog-github@npm:^0.5.0": + version: 0.5.0 + resolution: "@changesets/changelog-github@npm:0.5.0" + dependencies: + "@changesets/get-github-info": ^0.6.0 + "@changesets/types": ^6.0.0 + dotenv: ^8.1.0 + checksum: 4ab43d8104693f970d878f2b1657ff67b4d4dcb7452ddf118575153bab74286cdfd125381c2ab92b205bce4b2c653c36552138bf2900f7165ac39a868b7fe22c + languageName: node + linkType: hard + +"@changesets/cli@npm:~2.27.8": + version: 2.27.9 + resolution: "@changesets/cli@npm:2.27.9" + dependencies: + "@changesets/apply-release-plan": ^7.0.5 + "@changesets/assemble-release-plan": ^6.0.4 + "@changesets/changelog-git": ^0.2.0 + "@changesets/config": ^3.0.3 + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.1.2 + "@changesets/get-release-plan": ^4.0.4 + "@changesets/git": ^3.0.1 + "@changesets/logger": ^0.1.1 + "@changesets/pre": ^2.0.1 + "@changesets/read": ^0.6.1 + "@changesets/should-skip-package": ^0.1.1 + "@changesets/types": ^6.0.0 + "@changesets/write": ^0.3.2 + "@manypkg/get-packages": ^1.1.3 + ansi-colors: ^4.1.3 + ci-info: ^3.7.0 + enquirer: ^2.3.0 + external-editor: ^3.1.0 + fs-extra: ^7.0.1 + mri: ^1.2.0 + p-limit: ^2.2.0 + package-manager-detector: ^0.2.0 + picocolors: ^1.1.0 + resolve-from: ^5.0.0 + semver: ^7.5.3 + spawndamnit: ^2.0.0 + term-size: ^2.1.0 + bin: + changeset: bin.js + checksum: 4bd36c152f9f93716b001f3ed849717588d2a9eb97f058e86f95ba6a43d8e4311073174251150aabb96f0a1ab5f8ab5ee6a32f85fc9248363f92b3826227cb9d + languageName: node + linkType: hard + +"@changesets/config@npm:^3.0.3": + version: 3.0.3 + resolution: "@changesets/config@npm:3.0.3" + dependencies: + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.1.2 + "@changesets/logger": ^0.1.1 + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + fs-extra: ^7.0.1 + micromatch: ^4.0.2 + checksum: f216f497e09c0fcdd4c397fc3998d1651a171b89981d2bed2a6c23c0f55ffa4e240cadbd13902bf91c218686165689a5183674a5b4682d80d3d5b8b9c569f5f1 + languageName: node + linkType: hard + +"@changesets/errors@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/errors@npm:0.2.0" + dependencies: + extendable-error: ^0.1.5 + checksum: 4b79373f92287af4f723e8dbbccaf0299aa8735fc043243d0ad587f04a7614615ea50180be575d4438b9f00aa82d1cf85e902b77a55bdd3e0a8dd97e77b18c60 + languageName: node + linkType: hard + +"@changesets/get-dependents-graph@npm:^2.1.2": + version: 2.1.2 + resolution: "@changesets/get-dependents-graph@npm:2.1.2" + dependencies: + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + picocolors: ^1.1.0 + semver: ^7.5.3 + checksum: 38446343e43f9b8731098e3b42d2525d5399d59cfccc09bdb62c9a48de60c7a893882050202badca3b5cab8405e6deb82e88258a56a318e42749fa60d96d874a + languageName: node + linkType: hard + +"@changesets/get-github-info@npm:^0.6.0": + version: 0.6.0 + resolution: "@changesets/get-github-info@npm:0.6.0" + dependencies: + dataloader: ^1.4.0 + node-fetch: ^2.5.0 + checksum: 753173bda536aa79cb0502f59ce13889b23ae8463d04893d43ff22966818060837d9db4052b6cbfbd95dfb242fbfd38890a38c56832948e83bf358a47812b708 + languageName: node + linkType: hard + +"@changesets/get-release-plan@npm:^4.0.4": + version: 4.0.4 + resolution: "@changesets/get-release-plan@npm:4.0.4" + dependencies: + "@changesets/assemble-release-plan": ^6.0.4 + "@changesets/config": ^3.0.3 + "@changesets/pre": ^2.0.1 + "@changesets/read": ^0.6.1 + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + checksum: 7217347f5bfaa56f97d3964e28e23a109d60c42b7c879c0cab6934feb30bdbdebb6dd0e81b4ecb5ec414be442d566b6af90d9224f6a48a52b6c5269c337f54a6 + languageName: node + linkType: hard + +"@changesets/get-version-range-type@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/get-version-range-type@npm:0.4.0" + checksum: 2e8c511e658e193f48de7f09522649c4cf072932f0cbe0f252a7f2703d7775b0b90b632254526338795d0658e340be9dff3879cfc8eba4534b8cd6071efff8c9 + languageName: node + linkType: hard + +"@changesets/git@npm:^3.0.1": + version: 3.0.1 + resolution: "@changesets/git@npm:3.0.1" + dependencies: + "@changesets/errors": ^0.2.0 + "@manypkg/get-packages": ^1.1.3 + is-subdir: ^1.1.1 + micromatch: ^4.0.2 + spawndamnit: ^2.0.0 + checksum: 46d780fecd3dbdafde7c96dde7fe35a8461bc6edbff1de92d490971a99f021d60c5b4606a1d4fb778567146810090ede6610cf89407c14bde88edaa246801539 + languageName: node + linkType: hard + +"@changesets/logger@npm:^0.1.1": + version: 0.1.1 + resolution: "@changesets/logger@npm:0.1.1" + dependencies: + picocolors: ^1.1.0 + checksum: acca50ef6bf6e446b46eb576b32f1955bf4579dbf4bbc316768ed2c1d4ba4066c9c73b114eedefaa1b3e360b1060a020e6bd3dbdbc44b74da732df92307beab0 + languageName: node + linkType: hard + +"@changesets/parse@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/parse@npm:0.4.0" + dependencies: + "@changesets/types": ^6.0.0 + js-yaml: ^3.13.1 + checksum: 3dd970b244479746233ebd357cfff3816cf9f344ebf2cf0c7c55ce8579adfd3f506978e86ad61222dc3acf1548a2105ffdd8b3e940b3f82b225741315cee2bf0 + languageName: node + linkType: hard + +"@changesets/pre@npm:^2.0.1": + version: 2.0.1 + resolution: "@changesets/pre@npm:2.0.1" + dependencies: + "@changesets/errors": ^0.2.0 + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + fs-extra: ^7.0.1 + checksum: fbe94283dce0223ee79c12fa221105752ac89eb885b77e300ec755682cb06cc0145e10335f4bc6cb26d63473e549556c2b1c8c866242419aee5e41986379652a + languageName: node + linkType: hard + +"@changesets/read@npm:^0.6.1": + version: 0.6.1 + resolution: "@changesets/read@npm:0.6.1" + dependencies: + "@changesets/git": ^3.0.1 + "@changesets/logger": ^0.1.1 + "@changesets/parse": ^0.4.0 + "@changesets/types": ^6.0.0 + fs-extra: ^7.0.1 + p-filter: ^2.1.0 + picocolors: ^1.1.0 + checksum: d00a18a3d04af5c76e7b763096650ebe16589864ab04eaf9e99c88aa77542f64de547b585037fc204d2055f9dd47fae94c789e2f173d3507a4e29dbe6609dd5b + languageName: node + linkType: hard + +"@changesets/should-skip-package@npm:^0.1.1": + version: 0.1.1 + resolution: "@changesets/should-skip-package@npm:0.1.1" + dependencies: + "@changesets/types": ^6.0.0 + "@manypkg/get-packages": ^1.1.3 + checksum: d187ef22495deb63e678d0ff65e8627701e2b52c25bd59dde10ce8646be8d605c0ed0a6af020dd825b137c2fc748fdc6cef52e7774bad4c7a4f404bf182a85cf + languageName: node + linkType: hard + +"@changesets/types@npm:^4.0.1": + version: 4.1.0 + resolution: "@changesets/types@npm:4.1.0" + checksum: 72c1f58044178ca867dd9349ecc4b7c233ce3781bb03b5b72a70c3166fbbab54a2f2cb19a81f96b4649ba004442c8734569fba238be4dd737fb4624a135c6098 + languageName: node + linkType: hard + +"@changesets/types@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/types@npm:6.0.0" + checksum: d528b5d712f62c26ea422c7d34ccf6eac57a353c0733d96716db3c796ecd9bba5d496d48b37d5d46b784dc45b69c06ce3345fa3515df981bb68456cad68e6465 + languageName: node + linkType: hard + +"@changesets/write@npm:^0.3.2": + version: 0.3.2 + resolution: "@changesets/write@npm:0.3.2" + dependencies: + "@changesets/types": ^6.0.0 + fs-extra: ^7.0.1 + human-id: ^1.0.2 + prettier: ^2.7.1 + checksum: 553ed0ba6bd6397784f5e0e2921794bd7417a3c4fb810f1abb15e7072bf9d312af74308ff743161c6ea01478884cebcaf9cee02e5c70e2c7552b2774960ee07c + languageName: node + linkType: hard + "@coinbase/wallet-sdk@npm:4.1.0": version: 4.1.0 resolution: "@coinbase/wallet-sdk@npm:4.1.0" @@ -297,6 +610,43 @@ __metadata: languageName: node linkType: hard +"@eth-optimism/contracts@npm:0.6.0": + version: 0.6.0 + resolution: "@eth-optimism/contracts@npm:0.6.0" + dependencies: + "@eth-optimism/core-utils": 0.12.0 + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/abstract-signer": ^5.7.0 + peerDependencies: + ethers: ^5 + checksum: 52e9a6cc6ad9bf3ab085d3be501fa4c89e48865baa8aee01aff39c2b007b69600304c7e8f8f4e00d67396e48a0dbfe3a260437efd3a4d7216424cece52639870 + languageName: node + linkType: hard + +"@eth-optimism/core-utils@npm:0.12.0": + version: 0.12.0 + resolution: "@eth-optimism/core-utils@npm:0.12.0" + dependencies: + "@ethersproject/abi": ^5.7.0 + "@ethersproject/abstract-provider": ^5.7.0 + "@ethersproject/address": ^5.7.0 + "@ethersproject/bignumber": ^5.7.0 + "@ethersproject/bytes": ^5.7.0 + "@ethersproject/constants": ^5.7.0 + "@ethersproject/contracts": ^5.7.0 + "@ethersproject/hash": ^5.7.0 + "@ethersproject/keccak256": ^5.7.0 + "@ethersproject/properties": ^5.7.0 + "@ethersproject/providers": ^5.7.0 + "@ethersproject/rlp": ^5.7.0 + "@ethersproject/transactions": ^5.7.0 + "@ethersproject/web": ^5.7.0 + bufio: ^1.0.7 + chai: ^4.3.4 + checksum: 1c820107c44bdbb46becb1b00fd0dabb44f3ac8f54e6da7872a5a134411fad26f53b193225da55e79d6a8d7f0d01cc16a123db5d41ebaf02ca78360249a4b52a + languageName: node + linkType: hard + "@ethereumjs/common@npm:^3.2.0": version: 3.2.0 resolution: "@ethereumjs/common@npm:3.2.0" @@ -339,7 +689,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.7.0": +"@ethersproject/abi@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abi@npm:5.7.0" dependencies: @@ -356,7 +706,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:5.7.0, @ethersproject/abstract-provider@npm:^5.7.0": +"@ethersproject/abstract-provider@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-provider@npm:5.7.0" dependencies: @@ -371,7 +721,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.7.0": +"@ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/abstract-signer@npm:5.7.0" dependencies: @@ -384,7 +734,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -397,7 +747,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:5.7.0, @ethersproject/base64@npm:^5.7.0": +"@ethersproject/base64@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/base64@npm:5.7.0" dependencies: @@ -406,7 +756,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.7.0": +"@ethersproject/basex@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/basex@npm:5.7.0" dependencies: @@ -416,7 +766,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -427,7 +777,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -436,7 +786,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:^5.7.0": +"@ethersproject/constants@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/constants@npm:5.7.0" dependencies: @@ -445,7 +795,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/contracts@npm:5.7.0": +"@ethersproject/contracts@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/contracts@npm:5.7.0" dependencies: @@ -463,7 +813,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:^5.7.0": +"@ethersproject/hash@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/hash@npm:5.7.0" dependencies: @@ -480,47 +830,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.7.0, @ethersproject/hdnode@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/hdnode@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/basex": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/pbkdf2": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/sha2": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/wordlists": ^5.7.0 - checksum: bfe5ca2d89a42de73655f853170ef4766b933c5f481cddad709b3aca18823275b096e572f92d1602a052f80b426edde44ad6b9d028799775a7dad4a5bbed2133 - languageName: node - linkType: hard - -"@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/json-wallets@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hdnode": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/pbkdf2": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/random": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - checksum: f583458d22db62efaaf94d38dd243482776a45bf90f9f3882fbad5aa0b8fd288b41eb7c1ff8ec0b99c9b751088e43d6173530db64dd33c59f9d8daa8d7ad5aa2 - languageName: node - linkType: hard - "@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" @@ -531,14 +840,14 @@ __metadata: languageName: node linkType: hard -"@ethersproject/logger@npm:5.7.0, @ethersproject/logger@npm:^5.7.0": +"@ethersproject/logger@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/logger@npm:5.7.0" checksum: 075ab2f605f1fd0813f2e39c3308f77b44a67732b36e712d9bc085f22a84aac4da4f71b39bee50fe78da3e1c812673fadc41180c9970fe5e486e91ea17befe0d languageName: node linkType: hard -"@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.7.0": +"@ethersproject/networks@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/networks@npm:5.7.1" dependencies: @@ -547,17 +856,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.7.0, @ethersproject/pbkdf2@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/pbkdf2@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/sha2": ^5.7.0 - checksum: b895adb9e35a8a127e794f7aadc31a2424ef355a70e51cde10d457e3e888bb8102373199a540cf61f2d6b9a32e47358f9c65b47d559f42bf8e596b5fd67901e9 - languageName: node - linkType: hard - -"@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:^5.7.0": +"@ethersproject/properties@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/properties@npm:5.7.0" dependencies: @@ -566,7 +865,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2": +"@ethersproject/providers@npm:^5.7.0": version: 5.7.2 resolution: "@ethersproject/providers@npm:5.7.2" dependencies: @@ -594,7 +893,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.7.0": +"@ethersproject/random@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/random@npm:5.7.0" dependencies: @@ -604,7 +903,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.7.0": +"@ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" dependencies: @@ -614,7 +913,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:5.7.0, @ethersproject/sha2@npm:^5.7.0": +"@ethersproject/sha2@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/sha2@npm:5.7.0" dependencies: @@ -625,7 +924,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.7.0": +"@ethersproject/signing-key@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/signing-key@npm:5.7.0" dependencies: @@ -639,7 +938,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.0.9": +"@ethersproject/solidity@npm:^5.0.9": version: 5.7.0 resolution: "@ethersproject/solidity@npm:5.7.0" dependencies: @@ -664,7 +963,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.7.0": +"@ethersproject/transactions@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/transactions@npm:5.7.0" dependencies: @@ -681,41 +980,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/units@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/units@npm:5.7.0" - dependencies: - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - checksum: 304714f848cd32e57df31bf545f7ad35c2a72adae957198b28cbc62166daa929322a07bff6e9c9ac4577ab6aa0de0546b065ed1b2d20b19e25748b7d475cb0fc - languageName: node - linkType: hard - -"@ethersproject/wallet@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/wallet@npm:5.7.0" - dependencies: - "@ethersproject/abstract-provider": ^5.7.0 - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/hdnode": ^5.7.0 - "@ethersproject/json-wallets": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/random": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/wordlists": ^5.7.0 - checksum: a4009bf7331eddab38e3015b5e9101ef92de7f705b00a6196b997db0e5635b6d83561674d46c90c6f77b87c0500fe4a6b0183ba13749efc22db59c99deb82fbd - languageName: node - linkType: hard - -"@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.7.0": +"@ethersproject/web@npm:^5.7.0": version: 5.7.1 resolution: "@ethersproject/web@npm:5.7.1" dependencies: @@ -728,19 +993,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/wordlists@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - checksum: 30eb6eb0731f9ef5faa44bf9c0c6e950bcaaef61e4d2d9ce0ae6d341f4e2d6d1f4ab4f8880bfce03b7aac4b862fb740e1421170cfbf8e2aafc359277d49e6e97 - languageName: node - linkType: hard - "@fastify/busboy@npm:^2.0.0": version: 2.1.1 resolution: "@fastify/busboy@npm:2.1.1" @@ -864,6 +1116,32 @@ __metadata: languageName: node linkType: hard +"@manypkg/find-root@npm:^1.1.0": + version: 1.1.0 + resolution: "@manypkg/find-root@npm:1.1.0" + dependencies: + "@babel/runtime": ^7.5.5 + "@types/node": ^12.7.1 + find-up: ^4.1.0 + fs-extra: ^8.1.0 + checksum: f0fd881a5a81a351cb6561cd24117e8ee9481bbf3b6d1c7d9d10bef1f4744ca2ba3d064713e83c0a0574416d1e5b4a4c6c414aad91913c4a1c6040d87283ac50 + languageName: node + linkType: hard + +"@manypkg/get-packages@npm:^1.1.3": + version: 1.1.3 + resolution: "@manypkg/get-packages@npm:1.1.3" + dependencies: + "@babel/runtime": ^7.5.5 + "@changesets/types": ^4.0.1 + "@manypkg/find-root": ^1.1.0 + fs-extra: ^8.1.0 + globby: ^11.0.0 + read-yaml-file: ^1.1.0 + checksum: f5a756e5a659e0e1c33f48852d56826d170d5b10a3cdea89ce4fcaa77678d8799aa4004b30e1985c87b73dbc390b95bb6411b78336dd1e0db87c08c74b5c0e74 + languageName: node + linkType: hard + "@mapbox/node-pre-gyp@npm:^1.0.5": version: 1.0.11 resolution: "@mapbox/node-pre-gyp@npm:1.0.11" @@ -1381,6 +1659,86 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/slang-darwin-arm64@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-darwin-arm64@npm:0.17.0" + checksum: 70bc42222b019e79331fd698e6d490d9a1df3b55080951b7f87a83869296851b8176281c9b85b98f083c36a94daa86559238be3c8686f68e64000afae89b62db + languageName: node + linkType: hard + +"@nomicfoundation/slang-darwin-x64@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-darwin-x64@npm:0.17.0" + checksum: 4b133230fef4dac591d5677cf00186b02999129f7ea4df55eb6f5d6884a12cc43392df7b50a440d66d33bc99fe4939cb834d55c25828ee1ce5a976eb8225bb77 + languageName: node + linkType: hard + +"@nomicfoundation/slang-linux-arm64-gnu@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-linux-arm64-gnu@npm:0.17.0" + checksum: 02e7627977dcd52d2f90da2d7fa9d8964bca9c78831d696ac4b361a51534751ee9f79ddb898087da46f6121f38fc0fe290188d1dda542302483dde8b6aef11ed + languageName: node + linkType: hard + +"@nomicfoundation/slang-linux-arm64-musl@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-linux-arm64-musl@npm:0.17.0" + checksum: f62ebda232c9eada67c0497bd12f11a5443c36e922322d26f34f52277e8f494b0804504da217e61522871b5cc7cf295ec8a40e7e2b912e551f1a64a9052c5c37 + languageName: node + linkType: hard + +"@nomicfoundation/slang-linux-x64-gnu@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-linux-x64-gnu@npm:0.17.0" + checksum: 2c0431ac1ef0536bde5183a5275711274bf0e9016c9df9a4297c4680b1d80572bb6eb031c5a2db5f00f62d80ebbe0f671c0e04d289f8a4ff72df966d953bce1d + languageName: node + linkType: hard + +"@nomicfoundation/slang-linux-x64-musl@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-linux-x64-musl@npm:0.17.0" + checksum: c87be70b99eafc6a387e6c6a2c863e735d9ba70c039ade52b88091a4b6bb013b7dde292d1432127a67b63d70e7cd8321e10cf996a5e2939b12718287b5fea83f + languageName: node + linkType: hard + +"@nomicfoundation/slang-win32-arm64-msvc@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-win32-arm64-msvc@npm:0.17.0" + checksum: d375fa211748278c583b1304ab0058446f48864bffab4c5f5da6491accce879a3bb7b9058c158a6f8017e3aa4708ff9aea2ba2321d8a3c0dc482e2aaac1ce70e + languageName: node + linkType: hard + +"@nomicfoundation/slang-win32-ia32-msvc@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-win32-ia32-msvc@npm:0.17.0" + checksum: 9bd53a13f74b22456371ac33f8174e74efc2cd70458bf8bc9b1f4f79995a07644e2d8fd32c6a7f3bd2bb57ce896a5be42c4d9ca9d2fa3db43358ef1fd035596d + languageName: node + linkType: hard + +"@nomicfoundation/slang-win32-x64-msvc@npm:0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang-win32-x64-msvc@npm:0.17.0" + checksum: 7990aca40bc6022a26cdf62cbc3bfd1e8de78dd86cc0c059f35fae91946ba1caa29652c776dbff8875eea5440406111f7c5d21531f1146ad6e9927de1bb6e366 + languageName: node + linkType: hard + +"@nomicfoundation/slang@npm:^0.17.0": + version: 0.17.0 + resolution: "@nomicfoundation/slang@npm:0.17.0" + dependencies: + "@nomicfoundation/slang-darwin-arm64": 0.17.0 + "@nomicfoundation/slang-darwin-x64": 0.17.0 + "@nomicfoundation/slang-linux-arm64-gnu": 0.17.0 + "@nomicfoundation/slang-linux-arm64-musl": 0.17.0 + "@nomicfoundation/slang-linux-x64-gnu": 0.17.0 + "@nomicfoundation/slang-linux-x64-musl": 0.17.0 + "@nomicfoundation/slang-win32-arm64-msvc": 0.17.0 + "@nomicfoundation/slang-win32-ia32-msvc": 0.17.0 + "@nomicfoundation/slang-win32-x64-msvc": 0.17.0 + checksum: 6363b5ed627fff62c7bed4fbd1c0b481ee021e52c9db35cedba198c1e2285b6d227b39a513ce321ce8d9a7687a8e9eaa51ef321d41c517711ab6136aa7d54a95 + languageName: node + linkType: hard + "@npmcli/agent@npm:^2.0.0": version: 2.2.2 resolution: "@npmcli/agent@npm:2.2.2" @@ -1394,12 +1752,98 @@ __metadata: languageName: node linkType: hard -"@npmcli/fs@npm:^3.1.0": - version: 3.1.1 - resolution: "@npmcli/fs@npm:3.1.1" +"@npmcli/fs@npm:^3.1.0": + version: 3.1.1 + resolution: "@npmcli/fs@npm:3.1.1" + dependencies: + semver: ^7.3.5 + checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 + languageName: node + linkType: hard + +"@offchainlabs/upgrade-executor@npm:1.1.0-beta.0": + version: 1.1.0-beta.0 + resolution: "@offchainlabs/upgrade-executor@npm:1.1.0-beta.0" + dependencies: + "@openzeppelin/contracts": 4.7.3 + "@openzeppelin/contracts-upgradeable": 4.7.3 + checksum: b3c27bb2ff3f2ee0d7fbb955e2bc7f1dda29a7a409ea88348e3da627e91bb921b0bc8f8028caa7ecd087fe63f740dfda8fd7ead569eaeff5a282e83df1039bf6 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.5.2": + version: 4.5.2 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.5.2" + checksum: bd6a12eb83d8e3194e0847ffb248a1063668e2bf723afd21066316090de9b02e95af6057086a95fa21b0d09a2ef0ea057459bb5f5645dfff298e59e8c3267692 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.7.3" + checksum: c9ffb40cb847a975d440204fc6a811f43af960050242f707332b984d29bd16dc242ffa0935de61867aeb9e0357fadedb16b09b276deda5e9775582face831021 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.8.3": + version: 4.8.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.8.3" + checksum: 022c99bac4828980e771ddf3426a58b5a6f27932a1b1ec93dd2ed3f11c89d8e407867b845bedd0660bdd11c683971d566737c10504db8a1f144f61daec8b5ed6 + languageName: node + linkType: hard + +"@openzeppelin/contracts-upgradeable@npm:4.9.3": + version: 4.9.3 + resolution: "@openzeppelin/contracts-upgradeable@npm:4.9.3" + checksum: bda0240b1d44c913ec5a4e109c622f216c2bbd7b468d210822f75782a5f7fe0609d08bf03b78b253333625e99e507cf2f75212f1de3b274bd9fc64ae967aeec3 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.5.0": + version: 4.5.0 + resolution: "@openzeppelin/contracts@npm:4.5.0" + checksum: 1c9c5dff041905771d2a83ac29c64dbf0b48603de43f74a34fb1358813d7c7bf259efe2f64e2112b410c5cca7a0b41aaedd882368be5f01a6d50a3ee0740f962 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.7.3": + version: 4.7.3 + resolution: "@openzeppelin/contracts@npm:4.7.3" + checksum: 18382fcacf7cfd652f5dd0e70c08f08ea74eaa8ff11e9f9850639ada70198ae01a3f9493d89a52d724f2db394e9616bf6258017804612ba273167cf657fbb073 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.8.3": + version: 4.8.3 + resolution: "@openzeppelin/contracts@npm:4.8.3" + checksum: aea130d38d46840c5cbe3adbaa9a7ac645e4bd66ad3f3baf2fa78588c408d1a686170b3408c9e2e5e05530fba22ecdc00d7efb6b27852a8b29f91accbc0af255 + languageName: node + linkType: hard + +"@openzeppelin/contracts@npm:4.9.3": + version: 4.9.3 + resolution: "@openzeppelin/contracts@npm:4.9.3" + checksum: 4932063e733b35fa7669b9fe2053f69b062366c5c208b0c6cfa1ac451712100c78acff98120c3a4b88d94154c802be05d160d71f37e7d74cadbe150964458838 + languageName: node + linkType: hard + +"@openzeppelin/upgrades-core@npm:^1.24.1": + version: 1.40.0 + resolution: "@openzeppelin/upgrades-core@npm:1.40.0" dependencies: - semver: ^7.3.5 - checksum: d960cab4b93adcb31ce223bfb75c5714edbd55747342efb67dcc2f25e023d930a7af6ece3e75f2f459b6f38fc14d031c766f116cd124fdc937fd33112579e820 + "@nomicfoundation/slang": ^0.17.0 + cbor: ^9.0.0 + chalk: ^4.1.0 + compare-versions: ^6.0.0 + debug: ^4.1.1 + ethereumjs-util: ^7.0.3 + minimatch: ^9.0.5 + minimist: ^1.2.7 + proper-lockfile: ^4.1.1 + solidity-ast: ^0.4.51 + bin: + openzeppelin-upgrades-core: dist/cli/cli.js + checksum: 64fd7cedd213b3ed11f1bba982aedcd6cb0b6c79828f38935aec0e7bb2244e386a12c7d25d151cdd96d47a7becdc2f3c73f255ebd86d097e56f4b2286ef62c35 languageName: node linkType: hard @@ -1665,6 +2109,13 @@ __metadata: languageName: node linkType: hard +"@scroll-tech/contracts@npm:0.1.0": + version: 0.1.0 + resolution: "@scroll-tech/contracts@npm:0.1.0" + checksum: 61aa3ca76043276dd38dfb2ed67c019fcd1bf42c8b5d33726e6addfa95cad96ba057988cc00572159c47fcdbbad6fbd1da4821c82f512f5a8704f7807820a04b + languageName: node + linkType: hard + "@scure/base@npm:^1.1.3, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.2, @scure/base@npm:~1.1.6, @scure/base@npm:~1.1.7, @scure/base@npm:~1.1.8": version: 1.1.9 resolution: "@scure/base@npm:1.1.9" @@ -1735,20 +2186,6 @@ __metadata: languageName: node linkType: hard -"@se-2/foundry@workspace:packages/foundry": - version: 0.0.0-use.local - resolution: "@se-2/foundry@workspace:packages/foundry" - dependencies: - dotenv: ~16.3.1 - envfile: ~6.18.0 - ethers: ~5.7.1 - prettier: ~2.8.8 - qrcode: ~1.5.3 - shx: ~0.3.4 - toml: ~3.0.0 - languageName: unknown - linkType: soft - "@se-2/nextjs@workspace:packages/nextjs": version: 0.0.0-use.local resolution: "@se-2/nextjs@workspace:packages/nextjs" @@ -2078,6 +2515,15 @@ __metadata: languageName: node linkType: hard +"@types/bn.js@npm:^5.1.0": + version: 5.1.6 + resolution: "@types/bn.js@npm:5.1.6" + dependencies: + "@types/node": "*" + checksum: 887411126d40e3d28aef2df8075cda2832db2b0e926bb4046039bbb026f2e3cfbcf1a3ce90bd935be0fcc039f8009e32026dfbb84a11c1f5d051cd7f8194ba23 + languageName: node + linkType: hard + "@types/debug@npm:^4.1.7": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" @@ -2108,6 +2554,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:*": + version: 22.9.0 + resolution: "@types/node@npm:22.9.0" + dependencies: + undici-types: ~6.19.8 + checksum: c014eb3b8a110f1b87b614a40ef288d13e6b08ae9d5dafbd38951a2eebc24d352dc55330ed9d00c97ee9e64483c3cc14c4aa914c5df7ca7b9eaa1a30b2340dbd + languageName: node + linkType: hard + "@types/node@npm:16.18.11": version: 16.18.11 resolution: "@types/node@npm:16.18.11" @@ -2115,6 +2570,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^12.7.1": + version: 12.20.55 + resolution: "@types/node@npm:12.20.55" + checksum: e4f86785f4092706e0d3b0edff8dca5a13b45627e4b36700acd8dfe6ad53db71928c8dee914d4276c7fd3b6ccd829aa919811c9eb708a2c8e4c6eb3701178c37 + languageName: node + linkType: hard + "@types/node@npm:~18.19.50": version: 18.19.64 resolution: "@types/node@npm:18.19.64" @@ -2124,6 +2586,15 @@ __metadata: languageName: node linkType: hard +"@types/pbkdf2@npm:^3.0.0": + version: 3.1.2 + resolution: "@types/pbkdf2@npm:3.1.2" + dependencies: + "@types/node": "*" + checksum: bebe1e596cbbe5f7d2726a58859e61986c5a42459048e29cb7f2d4d764be6bbb0844572fd5d70ca8955a8a17e8b4ed80984fc4903e165d9efb8807a3fbb051aa + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.13 resolution: "@types/prop-types@npm:15.7.13" @@ -2141,6 +2612,15 @@ __metadata: languageName: node linkType: hard +"@types/secp256k1@npm:^4.0.1": + version: 4.0.6 + resolution: "@types/secp256k1@npm:4.0.6" + dependencies: + "@types/node": "*" + checksum: 984494caf49a4ce99fda2b9ea1840eb47af946b8c2737314108949bcc0c06b4880e871296bd49ed6ea4c8423e3a302ad79fec43abfc987330e7eb98f0c4e8ba4 + languageName: node + linkType: hard + "@types/semver@npm:^7.3.12": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" @@ -3103,6 +3583,20 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/lockfile@npm:^1.1.0": + version: 1.1.0 + resolution: "@yarnpkg/lockfile@npm:1.1.0" + checksum: 05b881b4866a3546861fee756e6d3812776ea47fa6eb7098f983d6d0eefa02e12b66c3fff931574120f196286a7ad4879ce02743c8bb2be36c6a576c7852083a + languageName: node + linkType: hard + +"@zksync/contracts@git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9": + version: 0.1.0 + resolution: "@zksync/contracts@https://github.com/matter-labs/era-contracts.git#commit=446d391d34bdb48255d5f8fef8a8248925fc98b9" + checksum: 0d582eab35063dc856580ecb7fcaff321e709597dd5bd179d90fc28d0b87a4d610ce9862a9b9b55d7a1395e25c551d2ab59c7a1600feca6cf1605e0270a43ed1 + languageName: node + linkType: hard + "abbrev@npm:1": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -3207,13 +3701,6 @@ __metadata: languageName: node linkType: hard -"aes-js@npm:3.0.0": - version: 3.0.0 - resolution: "aes-js@npm:3.0.0" - checksum: 251e26d533cd1a915b44896b17d5ed68c24a02484cfdd2e74ec700a309267db96651ea4eb657bf20aac32a3baa61f6e34edf8e2fec2de440a655da9942d334b8 - languageName: node - linkType: hard - "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -3266,6 +3753,13 @@ __metadata: languageName: node linkType: hard +"ansi-colors@npm:^4.1.1, ansi-colors@npm:^4.1.3": + version: 4.1.3 + resolution: "ansi-colors@npm:4.1.3" + checksum: a9c2ec842038a1fabc7db9ece7d3177e2fe1c5dc6f0c51ecfbf5f39911427b89c00b5dc6b8bd95f82a26e9b16aaae2e83d45f060e98070ce4d1333038edceb0e + languageName: node + linkType: hard + "ansi-escapes@npm:^4.3.0": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" @@ -3360,6 +3854,15 @@ __metadata: languageName: node linkType: hard +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: ~1.0.2 + checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -3486,6 +3989,13 @@ __metadata: languageName: node linkType: hard +"assertion-error@npm:^1.1.0": + version: 1.1.0 + resolution: "assertion-error@npm:1.1.0" + checksum: fd9429d3a3d4fd61782eb3962ae76b6d08aa7383123fca0596020013b3ebd6647891a85b05ce821c47d1471ed1271f00b0545cf6a4326cf2fc91efcc3b0fbecf + languageName: node + linkType: hard + "ast-types-flow@npm:^0.0.8": version: 0.0.8 resolution: "ast-types-flow@npm:0.0.8" @@ -3537,6 +4047,13 @@ __metadata: languageName: node linkType: hard +"at-least-node@npm:^1.0.0": + version: 1.0.0 + resolution: "at-least-node@npm:1.0.0" + checksum: 463e2f8e43384f1afb54bc68485c436d7622acec08b6fad269b421cb1d29cebb5af751426793d0961ed243146fe4dc983402f6d5a51b720b277818dbf6f2e49e + languageName: node + linkType: hard + "atomic-sleep@npm:^1.0.0": version: 1.0.0 resolution: "atomic-sleep@npm:1.0.0" @@ -3592,6 +4109,15 @@ __metadata: languageName: node linkType: hard +"base-x@npm:^3.0.2": + version: 3.0.10 + resolution: "base-x@npm:3.0.10" + dependencies: + safe-buffer: ^5.0.1 + checksum: 52307739559e81d9980889de2359cb4f816cc0eb9a463028fa3ab239ab913d9044a1b47b4520f98e68453df32a457b8ba58b8d0ee7e757fc3fb971f3fa7a1482 + languageName: node + linkType: hard + "base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -3606,6 +4132,15 @@ __metadata: languageName: node linkType: hard +"better-path-resolve@npm:1.0.0": + version: 1.0.0 + resolution: "better-path-resolve@npm:1.0.0" + dependencies: + is-windows: ^1.0.0 + checksum: 5392dbe04e7fe68b944eb37961d9dfa147aaac3ee9ee3f6e13d42e2c9fbe949e68d16e896c14ee9016fa5f8e6e53ec7fd8b5f01b50a32067a7d94ac9cfb9a050 + languageName: node + linkType: hard + "big.js@npm:^5.2.2": version: 5.2.2 resolution: "big.js@npm:5.2.2" @@ -3629,6 +4164,13 @@ __metadata: languageName: node linkType: hard +"blakejs@npm:^1.1.0": + version: 1.2.1 + resolution: "blakejs@npm:1.2.1" + checksum: d699ba116cfa21d0b01d12014a03e484dd76d483133e6dc9eb415aa70a119f08beb3bcefb8c71840106a00b542cba77383f8be60cd1f0d4589cb8afb922eefbe + languageName: node + linkType: hard + "blo@npm:~1.2.0": version: 1.2.0 resolution: "blo@npm:1.2.0" @@ -3643,7 +4185,7 @@ __metadata: languageName: node linkType: hard -"bn.js@npm:^5.2.1": +"bn.js@npm:^5.1.2, bn.js@npm:^5.2.0, bn.js@npm:^5.2.1": version: 5.2.1 resolution: "bn.js@npm:5.2.1" checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 @@ -3692,6 +4234,20 @@ __metadata: languageName: node linkType: hard +"browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: ^1.0.3 + cipher-base: ^1.0.0 + create-hash: ^1.1.0 + evp_bytestokey: ^1.0.3 + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 4a17c3eb55a2aa61c934c286f34921933086bf6d67f02d4adb09fcc6f2fc93977b47d9d884c25619144fccd47b3b3a399e1ad8b3ff5a346be47270114bcf7104 + languageName: node + linkType: hard + "browserslist@npm:^4.23.3": version: 4.24.2 resolution: "browserslist@npm:4.24.2" @@ -3706,6 +4262,26 @@ __metadata: languageName: node linkType: hard +"bs58@npm:^4.0.0": + version: 4.0.1 + resolution: "bs58@npm:4.0.1" + dependencies: + base-x: ^3.0.2 + checksum: b3c5365bb9e0c561e1a82f1a2d809a1a692059fae016be233a6127ad2f50a6b986467c3a50669ce4c18929dcccb297c5909314dd347a25a68c21b68eb3e95ac2 + languageName: node + linkType: hard + +"bs58check@npm:^2.1.2": + version: 2.1.2 + resolution: "bs58check@npm:2.1.2" + dependencies: + bs58: ^4.0.0 + create-hash: ^1.1.0 + safe-buffer: ^5.1.2 + checksum: 43bdf08a5dd04581b78f040bc4169480e17008da482ffe2a6507327bbc4fc5c28de0501f7faf22901cfe57fbca79cbb202ca529003fedb4cb8dccd265b38e54d + languageName: node + linkType: hard + "buffer-crc32@npm:~0.2.3": version: 0.2.13 resolution: "buffer-crc32@npm:0.2.13" @@ -3713,6 +4289,13 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c520df29d62fa6e785e2800e586a20fc4f6dfad84bcdbd12e1e8a83856de1cb75c7ebd7abe6d036bbfab738a6cf18a3ae9c8e5a2e2eb3167ca7399ce65373a + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -3733,6 +4316,13 @@ __metadata: languageName: node linkType: hard +"bufio@npm:^1.0.7": + version: 1.2.2 + resolution: "bufio@npm:1.2.2" + checksum: 8768f558bdb0cf905377efec3641a670d89068722c7fcb1ae0c606e3f172acfd78e2d4cf89e20ed621b9416241b9dae6fa4ede32c1426e3824c9d4d1001dbb0f + languageName: node + linkType: hard + "burner-connector@npm:~0.0.8": version: 0.0.8 resolution: "burner-connector@npm:0.0.8" @@ -3821,6 +4411,15 @@ __metadata: languageName: node linkType: hard +"cbor@npm:^9.0.0": + version: 9.0.2 + resolution: "cbor@npm:9.0.2" + dependencies: + nofilter: ^3.1.0 + checksum: 925edae7bf964be5a26dba1b7ba6311ac12b6a66234dc958958997a0576cdc740632dc19852a5b84d8a75101936bea1fe122dc22539d6e11f4539c731853ba2e + languageName: node + linkType: hard + "cbw-sdk@npm:@coinbase/wallet-sdk@3.9.3": version: 3.9.3 resolution: "@coinbase/wallet-sdk@npm:3.9.3" @@ -3838,6 +4437,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.3.4": + version: 4.5.0 + resolution: "chai@npm:4.5.0" + dependencies: + assertion-error: ^1.1.0 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 + pathval: ^1.1.1 + type-detect: ^4.1.0 + checksum: 70e5a8418a39e577e66a441cc0ce4f71fd551a650a71de30dd4e3e31e75ed1f5aa7119cf4baf4a2cb5e85c0c6befdb4d8a05811fad8738c1a6f3aa6a23803821 + languageName: node + linkType: hard + "chalk@npm:5.2.0": version: 5.2.0 resolution: "chalk@npm:5.2.0" @@ -3845,7 +4459,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0, chalk@npm:^4.1.1": +"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.1, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -3855,6 +4469,22 @@ __metadata: languageName: node linkType: hard +"chardet@npm:^0.7.0": + version: 0.7.0 + resolution: "chardet@npm:0.7.0" + checksum: 6fd5da1f5d18ff5712c1e0aed41da200d7c51c28f11b36ee3c7b483f3696dabc08927fc6b227735eb8f0e1215c9a8abd8154637f3eff8cada5959df7f58b024d + languageName: node + linkType: hard + +"check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 + languageName: node + linkType: hard + "chokidar@npm:3.3.1": version: 3.3.1 resolution: "chokidar@npm:3.3.1" @@ -3907,6 +4537,30 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^2.0.0": + version: 2.0.0 + resolution: "ci-info@npm:2.0.0" + checksum: 3b374666a85ea3ca43fa49aa3a048d21c9b475c96eb13c133505d2324e7ae5efd6a454f41efe46a152269e9b6a00c9edbe63ec7fa1921957165aae16625acd67 + languageName: node + linkType: hard + +"ci-info@npm:^3.7.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 + languageName: node + linkType: hard + +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.4 + resolution: "cipher-base@npm:1.0.4" + dependencies: + inherits: ^2.0.1 + safe-buffer: ^5.0.1 + checksum: 47d3568dbc17431a339bad1fe7dff83ac0891be8206911ace3d3b818fc695f376df809bea406e759cdea07fff4b454fa25f1013e648851bec790c1d75763032e + languageName: node + linkType: hard + "citty@npm:^0.1.5, citty@npm:^0.1.6": version: 0.1.6 resolution: "citty@npm:0.1.6" @@ -4062,6 +4716,13 @@ __metadata: languageName: node linkType: hard +"compare-versions@npm:^6.0.0": + version: 6.1.1 + resolution: "compare-versions@npm:6.1.1" + checksum: 73fe6c4f52d22efe28f0a3be10df2afd704e10b3593360cd963e86b33a7a263c263b41a1361b69c30a0fe68bfa70fef90860c1cf2ef41502629d4402890fcd57 + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -4136,6 +4797,33 @@ __metadata: languageName: node linkType: hard +"create-hash@npm:^1.1.0, create-hash@npm:^1.1.2, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: ^1.0.1 + inherits: ^2.0.1 + md5.js: ^1.3.4 + ripemd160: ^2.0.1 + sha.js: ^2.4.0 + checksum: 02a6ae3bb9cd4afee3fabd846c1d8426a0e6b495560a977ba46120c473cb283be6aa1cace76b5f927cf4e499c6146fb798253e48e83d522feba807d6b722eaa9 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: ^1.0.3 + create-hash: ^1.1.0 + inherits: ^2.0.1 + ripemd160: ^2.0.0 + safe-buffer: ^5.0.1 + sha.js: ^2.4.8 + checksum: ba12bb2257b585a0396108c72830e85f882ab659c3320c83584b1037f8ab72415095167ced80dc4ce8e446a8ecc4b2acf36d87befe0707d73b26cf9dc77440ed + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1" @@ -4161,6 +4849,30 @@ __metadata: languageName: node linkType: hard +"cross-spawn@npm:^5.1.0": + version: 5.1.0 + resolution: "cross-spawn@npm:5.1.0" + dependencies: + lru-cache: ^4.0.1 + shebang-command: ^1.2.0 + which: ^1.2.9 + checksum: 726939c9954fc70c20e538923feaaa33bebc253247d13021737c3c7f68cdc3e0a57f720c0fe75057c0387995349f3f12e20e9bfdbf12274db28019c7ea4ec166 + languageName: node + linkType: hard + +"cross-spawn@npm:^6.0.5": + version: 6.0.5 + resolution: "cross-spawn@npm:6.0.5" + dependencies: + nice-try: ^1.0.4 + path-key: ^2.0.1 + semver: ^5.5.0 + shebang-command: ^1.2.0 + which: ^1.2.9 + checksum: f893bb0d96cd3d5751d04e67145bdddf25f99449531a72e82dcbbd42796bbc8268c1076c6b3ea51d4d455839902804b94bc45dfb37ecbb32ea8e54a6741c3ab9 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.5 resolution: "cross-spawn@npm:7.0.5" @@ -4273,6 +4985,13 @@ __metadata: languageName: node linkType: hard +"dataloader@npm:^1.4.0": + version: 1.4.0 + resolution: "dataloader@npm:1.4.0" + checksum: e2c93d43afde68980efc0cd9ff48e9851116e27a9687f863e02b56d46f7e7868cc762cd6dcbaf4197e1ca850a03651510c165c2ae24b8e9843fd894002ad0e20 + languageName: node + linkType: hard + "date-fns@npm:^2.29.3": version: 2.30.0 resolution: "date-fns@npm:2.30.0" @@ -4282,7 +5001,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:~4.3.1, debug@npm:~4.3.2": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:~4.3.1, debug@npm:~4.3.2": version: 4.3.7 resolution: "debug@npm:4.3.7" dependencies: @@ -4345,6 +5064,15 @@ __metadata: languageName: node linkType: hard +"deep-eql@npm:^4.1.3": + version: 4.1.4 + resolution: "deep-eql@npm:4.1.4" + dependencies: + type-detect: ^4.0.0 + checksum: 01c3ca78ff40d79003621b157054871411f94228ceb9b2cab78da913c606631c46e8aa79efc4aa0faf3ace3092acd5221255aab3ef0e8e7b438834f0ca9a16c7 + languageName: node + linkType: hard + "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -4423,6 +5151,13 @@ __metadata: languageName: node linkType: hard +"detect-indent@npm:^6.0.0": + version: 6.1.0 + resolution: "detect-indent@npm:6.1.0" + checksum: ab953a73c72dbd4e8fc68e4ed4bfd92c97eb6c43734af3900add963fd3a9316f3bc0578b018b24198d4c31a358571eff5f0656e81a1f3b9ad5c547d58b2d093d + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -4501,10 +5236,10 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:~16.3.1": - version: 16.3.2 - resolution: "dotenv@npm:16.3.2" - checksum: 917b27eeb654b95846484009326b1c52af7a7c25f7b09e2939ed49de8f98cb9895dcc04f13a39cdb078d247985e21147311ccb5bfbf2fd151afb20fa8f96de15 +"dotenv@npm:^8.1.0": + version: 8.6.0 + resolution: "dotenv@npm:8.6.0" + checksum: 38e902c80b0666ab59e9310a3d24ed237029a7ce34d976796349765ac96b8d769f6df19090f1f471b77a25ca391971efde8a1ea63bb83111bd8bec8e5cc9b2cd languageName: node linkType: hard @@ -4673,6 +5408,16 @@ __metadata: languageName: node linkType: hard +"enquirer@npm:^2.3.0": + version: 2.4.1 + resolution: "enquirer@npm:2.4.1" + dependencies: + ansi-colors: ^4.1.1 + strip-ansi: ^6.0.1 + checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -4680,15 +5425,6 @@ __metadata: languageName: node linkType: hard -"envfile@npm:~6.18.0": - version: 6.18.0 - resolution: "envfile@npm:6.18.0" - bin: - envfile: bin.cjs - checksum: 3a3762994d7b84ccf0293c1269cdfa5ea8971bdbbf7e3571fb686a6415eee2029e43d3faf36ed4222a83eaaf38fbc4fa37b3f50b77ea417ca35561e0e54059c1 - languageName: node - linkType: hard - "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -5366,6 +6102,16 @@ __metadata: languageName: node linkType: hard +"esprima@npm:^4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + "esquery@npm:^1.4.2": version: 1.6.0 resolution: "esquery@npm:1.6.0" @@ -5464,6 +6210,29 @@ __metadata: languageName: node linkType: hard +"ethereum-cryptography@npm:^0.1.3": + version: 0.1.3 + resolution: "ethereum-cryptography@npm:0.1.3" + dependencies: + "@types/pbkdf2": ^3.0.0 + "@types/secp256k1": ^4.0.1 + blakejs: ^1.1.0 + browserify-aes: ^1.2.0 + bs58check: ^2.1.2 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + hash.js: ^1.1.7 + keccak: ^3.0.0 + pbkdf2: ^3.0.17 + randombytes: ^2.1.0 + safe-buffer: ^5.1.2 + scrypt-js: ^3.0.0 + secp256k1: ^4.0.1 + setimmediate: ^1.0.5 + checksum: 54bae7a4a96bd81398cdc35c91cfcc74339f71a95ed1b5b694663782e69e8e3afd21357de3b8bac9ff4877fd6f043601e200a7ad9133d94be6fd7d898ee0a449 + languageName: node + linkType: hard + "ethereum-cryptography@npm:^2.0.0": version: 2.2.1 resolution: "ethereum-cryptography@npm:2.2.1" @@ -5476,41 +6245,16 @@ __metadata: languageName: node linkType: hard -"ethers@npm:~5.7.1": - version: 5.7.2 - resolution: "ethers@npm:5.7.2" - dependencies: - "@ethersproject/abi": 5.7.0 - "@ethersproject/abstract-provider": 5.7.0 - "@ethersproject/abstract-signer": 5.7.0 - "@ethersproject/address": 5.7.0 - "@ethersproject/base64": 5.7.0 - "@ethersproject/basex": 5.7.0 - "@ethersproject/bignumber": 5.7.0 - "@ethersproject/bytes": 5.7.0 - "@ethersproject/constants": 5.7.0 - "@ethersproject/contracts": 5.7.0 - "@ethersproject/hash": 5.7.0 - "@ethersproject/hdnode": 5.7.0 - "@ethersproject/json-wallets": 5.7.0 - "@ethersproject/keccak256": 5.7.0 - "@ethersproject/logger": 5.7.0 - "@ethersproject/networks": 5.7.1 - "@ethersproject/pbkdf2": 5.7.0 - "@ethersproject/properties": 5.7.0 - "@ethersproject/providers": 5.7.2 - "@ethersproject/random": 5.7.0 - "@ethersproject/rlp": 5.7.0 - "@ethersproject/sha2": 5.7.0 - "@ethersproject/signing-key": 5.7.0 - "@ethersproject/solidity": 5.7.0 - "@ethersproject/strings": 5.7.0 - "@ethersproject/transactions": 5.7.0 - "@ethersproject/units": 5.7.0 - "@ethersproject/wallet": 5.7.0 - "@ethersproject/web": 5.7.1 - "@ethersproject/wordlists": 5.7.0 - checksum: b7c08cf3e257185a7946117dbbf764433b7ba0e77c27298dec6088b3bc871aff711462b0621930c56880ff0a7ceb8b1d3a361ffa259f93377b48e34107f62553 +"ethereumjs-util@npm:^7.0.3": + version: 7.1.5 + resolution: "ethereumjs-util@npm:7.1.5" + dependencies: + "@types/bn.js": ^5.1.0 + bn.js: ^5.1.2 + create-hash: ^1.1.2 + ethereum-cryptography: ^0.1.3 + rlp: ^2.2.4 + checksum: 27a3c79d6e06b2df34b80d478ce465b371c8458b58f5afc14d91c8564c13363ad336e6e83f57eb0bd719fde94d10ee5697ceef78b5aa932087150c5287b286d1 languageName: node linkType: hard @@ -5549,6 +6293,17 @@ __metadata: languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: ^1.3.4 + node-gyp: latest + safe-buffer: ^5.1.1 + checksum: ad4e1577f1a6b721c7800dcc7c733fe01f6c310732bb5bf2240245c2a5b45a38518b91d8be2c610611623160b9d1c0e91f1ce96d639f8b53e8894625cf20fa45 + languageName: node + linkType: hard + "execa@npm:3.2.0": version: 3.2.0 resolution: "execa@npm:3.2.0" @@ -5608,6 +6363,13 @@ __metadata: languageName: node linkType: hard +"extendable-error@npm:^0.1.5": + version: 0.1.7 + resolution: "extendable-error@npm:0.1.7" + checksum: 80478be7429a1675d2085f701239796bab3230ed6f2fb1b138fbabec24bea6516b7c5ceb6e9c209efcc9c089948d93715703845653535f8e8a49655066a9255e + languageName: node + linkType: hard + "extension-port-stream@npm:^3.0.0": version: 3.0.0 resolution: "extension-port-stream@npm:3.0.0" @@ -5618,6 +6380,17 @@ __metadata: languageName: node linkType: hard +"external-editor@npm:^3.1.0": + version: 3.1.0 + resolution: "external-editor@npm:3.1.0" + dependencies: + chardet: ^0.7.0 + iconv-lite: ^0.4.24 + tmp: ^0.0.33 + checksum: 1c2a616a73f1b3435ce04030261bed0e22d4737e14b090bb48e58865da92529c9f2b05b893de650738d55e692d071819b45e1669259b2b354bc3154d27a698c7 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -5750,6 +6523,15 @@ __metadata: languageName: node linkType: hard +"find-yarn-workspace-root@npm:^2.0.0": + version: 2.0.0 + resolution: "find-yarn-workspace-root@npm:2.0.0" + dependencies: + micromatch: ^4.0.2 + checksum: fa5ca8f9d08fe7a54ce7c0a5931ff9b7e36f9ee7b9475fb13752bcea80ec6b5f180fa5102d60b376d5526ce924ea3fc6b19301262efa0a5d248dd710f3644242 + languageName: node + linkType: hard + "flat-cache@npm:^3.0.4": version: 3.2.0 resolution: "flat-cache@npm:3.2.0" @@ -5805,7 +6587,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:8.1.0": +"fs-extra@npm:8.1.0, fs-extra@npm:^8.1.0": version: 8.1.0 resolution: "fs-extra@npm:8.1.0" dependencies: @@ -5816,6 +6598,29 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^7.0.1": + version: 7.0.1 + resolution: "fs-extra@npm:7.0.1" + dependencies: + graceful-fs: ^4.1.2 + jsonfile: ^4.0.0 + universalify: ^0.1.0 + checksum: 141b9dccb23b66a66cefdd81f4cda959ff89282b1d721b98cea19ba08db3dcbe6f862f28841f3cf24bb299e0b7e6c42303908f65093cb7e201708e86ea5a8dcf + languageName: node + linkType: hard + +"fs-extra@npm:^9.0.0": + version: 9.1.0 + resolution: "fs-extra@npm:9.1.0" + dependencies: + at-least-node: ^1.0.0 + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: ba71ba32e0faa74ab931b7a0031d1523c66a73e225de7426e275e238e312d07313d2da2d33e34a52aa406c8763ade5712eb3ec9ba4d9edce652bcacdc29e6b20 + languageName: node + linkType: hard + "fs-minipass@npm:^1.2.7": version: 1.2.7 resolution: "fs-minipass@npm:1.2.7" @@ -5945,6 +6750,13 @@ __metadata: languageName: node linkType: hard +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b + languageName: node + linkType: hard + "get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": version: 1.2.4 resolution: "get-intrinsic@npm:1.2.4" @@ -6064,7 +6876,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.3": +"glob@npm:^7.1.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -6104,7 +6916,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.1.0": +"globby@npm:^11.0.0, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -6136,7 +6948,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -6221,7 +7033,18 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": +"hash-base@npm:^3.0.0": + version: 3.1.0 + resolution: "hash-base@npm:3.1.0" + dependencies: + inherits: ^2.0.4 + readable-stream: ^3.6.0 + safe-buffer: ^5.2.0 + checksum: 26b7e97ac3de13cb23fc3145e7e3450b0530274a9562144fc2bf5c1e2983afd0e09ed7cc3b20974ba66039fad316db463da80eb452e7373e780cbee9a0d2f2dc + languageName: node + linkType: hard + +"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3, hash.js@npm:^1.1.7": version: 1.1.7 resolution: "hash.js@npm:1.1.7" dependencies: @@ -6325,6 +7148,13 @@ __metadata: languageName: node linkType: hard +"human-id@npm:^1.0.2": + version: 1.0.2 + resolution: "human-id@npm:1.0.2" + checksum: 95ee57ffae849f008e2ef3fe6e437be8c999861b4256f18c3b194c8928670a8a149e0576917105d5fd77e5edbb621c5a4736fade20bb7bf130113c1ebc95cb74 + languageName: node + linkType: hard + "human-signals@npm:^1.1.1": version: 1.1.1 resolution: "human-signals@npm:1.1.1" @@ -6373,7 +7203,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:0.4.24": +"iconv-lite@npm:0.4.24, iconv-lite@npm:^0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" dependencies: @@ -6471,13 +7301,6 @@ __metadata: languageName: node linkType: hard -"interpret@npm:^1.0.0": - version: 1.4.0 - resolution: "interpret@npm:1.4.0" - checksum: 2e5f51268b5941e4a17e4ef0575bc91ed0ab5f8515e3cf77486f7c14d13f3010df9c0959f37063dcc96e78d12dc6b0bb1b9e111cdfe69771f4656d2993d36155 - languageName: node - linkType: hard - "invariant@npm:2.2.4, invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -6577,6 +7400,17 @@ __metadata: languageName: node linkType: hard +"is-ci@npm:^2.0.0": + version: 2.0.0 + resolution: "is-ci@npm:2.0.0" + dependencies: + ci-info: ^2.0.0 + bin: + is-ci: bin.js + checksum: 77b869057510f3efa439bbb36e9be429d53b3f51abd4776eeea79ab3b221337fe1753d1e50058a9e2c650d38246108beffb15ccfd443929d77748d8c0cc90144 + languageName: node + linkType: hard + "is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1": version: 2.15.1 resolution: "is-core-module@npm:2.15.1" @@ -6604,6 +7438,15 @@ __metadata: languageName: node linkType: hard +"is-docker@npm:^2.0.0": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 + languageName: node + linkType: hard + "is-docker@npm:^3.0.0": version: 3.0.0 resolution: "is-docker@npm:3.0.0" @@ -6765,6 +7608,15 @@ __metadata: languageName: node linkType: hard +"is-subdir@npm:^1.1.1": + version: 1.2.0 + resolution: "is-subdir@npm:1.2.0" + dependencies: + better-path-resolve: 1.0.0 + checksum: 31029a383972bff4cc4f1bd1463fd04dde017e0a04ae3a6f6e08124a90c6c4656312d593101b0f38805fa3f3c8f6bc4583524bbf72c50784fa5ca0d3e5a76279 + languageName: node + linkType: hard + "is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": version: 1.0.4 resolution: "is-symbol@npm:1.0.4" @@ -6809,6 +7661,22 @@ __metadata: languageName: node linkType: hard +"is-windows@npm:^1.0.0": + version: 1.0.2 + resolution: "is-windows@npm:1.0.2" + checksum: 438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 + languageName: node + linkType: hard + +"is-wsl@npm:^2.1.1": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: ^2.0.0 + checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 + languageName: node + linkType: hard + "is-wsl@npm:^3.1.0": version: 3.1.0 resolution: "is-wsl@npm:3.1.0" @@ -6967,6 +7835,18 @@ __metadata: languageName: node linkType: hard +"js-yaml@npm:^3.13.1, js-yaml@npm:^3.6.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: ^1.0.7 + esprima: ^4.0.0 + bin: + js-yaml: bin/js-yaml.js + checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c + languageName: node + linkType: hard + "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -7113,7 +7993,7 @@ __metadata: languageName: node linkType: hard -"keccak@npm:^3.0.3": +"keccak@npm:^3.0.0, keccak@npm:^3.0.3": version: 3.0.4 resolution: "keccak@npm:3.0.4" dependencies: @@ -7141,6 +8021,15 @@ __metadata: languageName: node linkType: hard +"klaw-sync@npm:^6.0.0": + version: 6.0.0 + resolution: "klaw-sync@npm:6.0.0" + dependencies: + graceful-fs: ^4.1.11 + checksum: 0da397f8961313c3ef8f79fb63af9002cde5a8fb2aeb1a37351feff0dd6006129c790400c3f5c3b4e757bedcabb13d21ec0a5eaef5a593d59515d4f2c291e475 + languageName: node + linkType: hard + "language-subtag-registry@npm:^0.3.20": version: 0.3.23 resolution: "language-subtag-registry@npm:0.3.23" @@ -7331,6 +8220,13 @@ __metadata: languageName: node linkType: hard +"lodash.startcase@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.startcase@npm:4.4.0" + checksum: c03a4a784aca653845fe09d0ef67c902b6e49288dc45f542a4ab345a9c406a6dc194c774423fa313ee7b06283950301c1221dd2a1d8ecb2dac8dfbb9ed5606b5 + languageName: node + linkType: hard + "lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -7361,6 +8257,15 @@ __metadata: languageName: node linkType: hard +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" + dependencies: + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0, lru-cache@npm:^10.4.3": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" @@ -7368,6 +8273,16 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^4.0.1": + version: 4.1.5 + resolution: "lru-cache@npm:4.1.5" + dependencies: + pseudomap: ^1.0.2 + yallist: ^2.1.2 + checksum: 4bb4b58a36cd7dc4dcec74cbe6a8f766a38b7426f1ff59d4cf7d82a2aa9b9565cd1cb98f6ff60ce5cd174524868d7bc9b7b1c294371851356066ca9ac4cf135a + languageName: node + linkType: hard + "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -7413,6 +8328,17 @@ __metadata: languageName: node linkType: hard +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: ^3.0.0 + inherits: ^2.0.1 + safe-buffer: ^5.1.2 + checksum: 098494d885684bcc4f92294b18ba61b7bd353c23147fbc4688c75b45cb8590f5a95fd4584d742415dcc52487f7a1ef6ea611cfa1543b0dc4492fe026357f3f0c + languageName: node + linkType: hard + "media-query-parser@npm:^2.0.2": version: 2.0.2 resolution: "media-query-parser@npm:2.0.2" @@ -7512,7 +8438,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.1, minimatch@npm:^9.0.4, minimatch@npm:^9.0.5": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -7521,7 +8447,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.7": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -7710,7 +8636,7 @@ __metadata: languageName: node linkType: hard -"mri@npm:1.2.0": +"mri@npm:1.2.0, mri@npm:^1.2.0": version: 1.2.0 resolution: "mri@npm:1.2.0" checksum: 83f515abbcff60150873e424894a2f65d68037e5a7fcde8a9e2b285ee9c13ac581b63cfc1e6826c4732de3aeb84902f7c1e16b7aff46cd3f897a0f757a894e85 @@ -7856,6 +8782,13 @@ __metadata: languageName: node linkType: hard +"nice-try@npm:^1.0.4": + version: 1.0.5 + resolution: "nice-try@npm:1.0.5" + checksum: 0b4af3b5bb5d86c289f7a026303d192a7eb4417231fe47245c460baeabae7277bcd8fd9c728fb6bd62c30b3e15cd6620373e2cf33353b095d8b403d3e8a15aff + languageName: node + linkType: hard + "node-addon-api@npm:^2.0.0": version: 2.0.2 resolution: "node-addon-api@npm:2.0.2" @@ -7865,6 +8798,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^5.0.0": + version: 5.1.0 + resolution: "node-addon-api@npm:5.1.0" + dependencies: + node-gyp: latest + checksum: 2508bd2d2981945406243a7bd31362fc7af8b70b8b4d65f869c61731800058fb818cc2fd36c8eac714ddd0e568cc85becf5e165cebbdf7b5024d5151bbc75ea1 + languageName: node + linkType: hard + "node-addon-api@npm:^7.0.0": version: 7.1.1 resolution: "node-addon-api@npm:7.1.1" @@ -7909,7 +8851,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7": +"node-fetch@npm:^2.5.0, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -7968,6 +8910,13 @@ __metadata: languageName: node linkType: hard +"nofilter@npm:^3.1.0": + version: 3.1.0 + resolution: "nofilter@npm:3.1.0" + checksum: 58aa85a5b4b35cbb6e42de8a8591c5e338061edc9f3e7286f2c335e9e9b9b8fa7c335ae45daa8a1f3433164dc0b9a3d187fa96f9516e04a17a1f9ce722becc4f + languageName: node + linkType: hard + "nopt@npm:^5.0.0": version: 5.0.0 resolution: "nopt@npm:5.0.0" @@ -8198,6 +9147,16 @@ __metadata: languageName: node linkType: hard +"open@npm:^7.4.2": + version: 7.4.2 + resolution: "open@npm:7.4.2" + dependencies: + is-docker: ^2.0.0 + is-wsl: ^2.1.1 + checksum: 3333900ec0e420d64c23b831bc3467e57031461d843c801f569b2204a1acc3cd7b3ec3c7897afc9dde86491dfa289708eb92bba164093d8bd88fb2c231843c91 + languageName: node + linkType: hard + "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -8219,6 +9178,20 @@ __metadata: languageName: node linkType: hard +"os-tmpdir@npm:~1.0.2": + version: 1.0.2 + resolution: "os-tmpdir@npm:1.0.2" + checksum: 5666560f7b9f10182548bf7013883265be33620b1c1b4a4d405c25be2636f970c5488ff3e6c48de75b55d02bde037249fe5dbfbb4c0fb7714953d56aed062e6d + languageName: node + linkType: hard + +"outdent@npm:^0.5.0": + version: 0.5.0 + resolution: "outdent@npm:0.5.0" + checksum: 6e6c63dd09e9890e67ef9a0b4d35df0b0b850b2059ce3f7e19e4cc1a146b26dc5d8c45df238dbf187dfffc8bd82cd07d37c697544015680bcb9f07f29a36c678 + languageName: node + linkType: hard + "outdent@npm:^0.8.0": version: 0.8.0 resolution: "outdent@npm:0.8.0" @@ -8246,6 +9219,15 @@ __metadata: languageName: node linkType: hard +"p-filter@npm:^2.1.0": + version: 2.1.0 + resolution: "p-filter@npm:2.1.0" + dependencies: + p-map: ^2.0.0 + checksum: 76e552ca624ce2233448d68b19eec9de42b695208121998f7e011edce71d1079a83096ee6a2078fb2a59cfa8a5c999f046edf00ebf16a8e780022010b4693234 + languageName: node + linkType: hard + "p-finally@npm:^2.0.0": version: 2.0.1 resolution: "p-finally@npm:2.0.1" @@ -8289,6 +9271,13 @@ __metadata: languageName: node linkType: hard +"p-map@npm:^2.0.0": + version: 2.1.0 + resolution: "p-map@npm:2.1.0" + checksum: 9e3ad3c9f6d75a5b5661bcad78c91f3a63849189737cd75e4f1225bf9ac205194e5c44aac2ef6f09562b1facdb9bd1425584d7ac375bfaa17b3f1a142dab936d + languageName: node + linkType: hard + "p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" @@ -8312,6 +9301,13 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^0.2.0": + version: 0.2.2 + resolution: "package-manager-detector@npm:0.2.2" + checksum: acc0d5a8b6b2a265474c1bac2b3569b6e57fe13db4d764b75cf5fcd11463a44f0ce00bb5dc439a78a1999993780385f431d36ceea51b51a35ce40d512b7388c6 + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -8328,6 +9324,30 @@ __metadata: languageName: node linkType: hard +"patch-package@npm:^6.4.7": + version: 6.5.1 + resolution: "patch-package@npm:6.5.1" + dependencies: + "@yarnpkg/lockfile": ^1.1.0 + chalk: ^4.1.2 + cross-spawn: ^6.0.5 + find-yarn-workspace-root: ^2.0.0 + fs-extra: ^9.0.0 + is-ci: ^2.0.0 + klaw-sync: ^6.0.0 + minimist: ^1.2.6 + open: ^7.4.2 + rimraf: ^2.6.3 + semver: ^5.6.0 + slash: ^2.0.0 + tmp: ^0.0.33 + yaml: ^1.10.2 + bin: + patch-package: index.js + checksum: 8530ffa30f11136b527c6eddf6da48fa12856ee510a47edb1f9cdf8a025636adb82968f5fae778b5e04ce8c87915ebdf5911422b54add59a5a42e372a8f30eb2 + languageName: node + linkType: hard + "path-browserify@npm:^1.0.1": version: 1.0.1 resolution: "path-browserify@npm:1.0.1" @@ -8349,6 +9369,13 @@ __metadata: languageName: node linkType: hard +"path-key@npm:^2.0.1": + version: 2.0.1 + resolution: "path-key@npm:2.0.1" + checksum: f7ab0ad42fe3fb8c7f11d0c4f849871e28fbd8e1add65c370e422512fc5887097b9cf34d09c1747d45c942a8c1e26468d6356e2df3f740bf177ab8ca7301ebfd + languageName: node + linkType: hard + "path-key@npm:^3.0.0, path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -8427,6 +9454,26 @@ __metadata: languageName: node linkType: hard +"pathval@npm:^1.1.1": + version: 1.1.1 + resolution: "pathval@npm:1.1.1" + checksum: 090e3147716647fb7fb5b4b8c8e5b55e5d0a6086d085b6cd23f3d3c01fcf0ff56fd3cc22f2f4a033bd2e46ed55d61ed8379e123b42afe7d531a2a5fc8bb556d6 + languageName: node + linkType: hard + +"pbkdf2@npm:^3.0.17": + version: 3.1.2 + resolution: "pbkdf2@npm:3.1.2" + dependencies: + create-hash: ^1.1.2 + create-hmac: ^1.1.4 + ripemd160: ^2.0.1 + safe-buffer: ^5.0.1 + sha.js: ^2.4.8 + checksum: 2c950a100b1da72123449208e231afc188d980177d021d7121e96a2de7f2abbc96ead2b87d03d8fe5c318face097f203270d7e27908af9f471c165a4e8e69c92 + languageName: node + linkType: hard + "pend@npm:~1.2.0": version: 1.2.0 resolution: "pend@npm:1.2.0" @@ -8478,6 +9525,13 @@ __metadata: languageName: node linkType: hard +"pify@npm:^4.0.1": + version: 4.0.1 + resolution: "pify@npm:4.0.1" + checksum: 9c4e34278cb09987685fa5ef81499c82546c033713518f6441778fbec623fc708777fe8ac633097c72d88470d5963094076c7305cafc7ad340aae27cfacd856b + languageName: node + linkType: hard + "pify@npm:^5.0.0": version: 5.0.0 resolution: "pify@npm:5.0.0" @@ -8677,7 +9731,7 @@ __metadata: languageName: node linkType: hard -"prettier@npm:~2.8.8": +"prettier@npm:^2.7.1": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -8760,6 +9814,17 @@ __metadata: languageName: node linkType: hard +"proper-lockfile@npm:^4.1.1": + version: 4.1.2 + resolution: "proper-lockfile@npm:4.1.2" + dependencies: + graceful-fs: ^4.2.4 + retry: ^0.12.0 + signal-exit: ^3.0.2 + checksum: 00078ee6a61c216a56a6140c7d2a98c6c733b3678503002dc073ab8beca5d50ca271de4c85fca13b9b8ee2ff546c36674d1850509b84a04a5d0363bcb8638939 + languageName: node + linkType: hard + "proxy-compare@npm:2.5.1": version: 2.5.1 resolution: "proxy-compare@npm:2.5.1" @@ -8767,6 +9832,13 @@ __metadata: languageName: node linkType: hard +"pseudomap@npm:^1.0.2": + version: 1.0.2 + resolution: "pseudomap@npm:1.0.2" + checksum: 856c0aae0ff2ad60881168334448e898ad7a0e45fe7386d114b150084254c01e200c957cf378378025df4e052c7890c5bd933939b0e0d2ecfcc1dc2f0b2991f5 + languageName: node + linkType: hard + "pump@npm:^3.0.0": version: 3.0.2 resolution: "pump@npm:3.0.2" @@ -8832,7 +9904,7 @@ __metadata: languageName: node linkType: hard -"qrcode@npm:1.5.4, qrcode@npm:~1.5.3": +"qrcode@npm:1.5.4": version: 1.5.4 resolution: "qrcode@npm:1.5.4" dependencies: @@ -8878,6 +9950,15 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: ^5.1.0 + checksum: d779499376bd4cbb435ef3ab9a957006c8682f343f14089ed5f27764e4645114196e75b7f6abf1cbd84fd247c0cb0651698444df8c9bf30e62120fbbc52269d6 + languageName: node + linkType: hard + "raw-body@npm:2.4.1": version: 2.4.1 resolution: "raw-body@npm:2.4.1" @@ -9035,6 +10116,18 @@ __metadata: languageName: node linkType: hard +"read-yaml-file@npm:^1.1.0": + version: 1.1.0 + resolution: "read-yaml-file@npm:1.1.0" + dependencies: + graceful-fs: ^4.1.5 + js-yaml: ^3.6.1 + pify: ^4.0.1 + strip-bom: ^3.0.0 + checksum: 41ee5f075507ef0403328dd54e225a61c3149f915675ce7fd0fd791ddcce2e6c30a9fe0f76ffa7a465c1c157b9b4ad8ded1dcf47dc3b396103eeb013490bbc2e + languageName: node + linkType: hard + "readable-stream@npm:^2.3.3": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" @@ -9099,15 +10192,6 @@ __metadata: languageName: node linkType: hard -"rechoir@npm:^0.6.2": - version: 0.6.2 - resolution: "rechoir@npm:0.6.2" - dependencies: - resolve: ^1.1.6 - checksum: fe76bf9c21875ac16e235defedd7cbd34f333c02a92546142b7911a0f7c7059d2e16f441fe6fb9ae203f459c05a31b2bcf26202896d89e390eda7514d5d2702b - languageName: node - linkType: hard - "reflect.getprototypeof@npm:^1.0.4": version: 1.0.6 resolution: "reflect.getprototypeof@npm:1.0.6" @@ -9191,7 +10275,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.1.7, resolve@npm:^1.22.4, resolve@npm:^1.22.8": +"resolve@npm:^1.1.7, resolve@npm:^1.22.4, resolve@npm:^1.22.8": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -9217,7 +10301,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@^1.22.8#~builtin": +"resolve@patch:resolve@^1.1.7#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@^1.22.8#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=07638b" dependencies: @@ -9274,6 +10358,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:^2.6.3": + version: 2.7.1 + resolution: "rimraf@npm:2.7.1" + dependencies: + glob: ^7.1.3 + bin: + rimraf: ./bin.js + checksum: cdc7f6eacb17927f2a075117a823e1c5951792c6498ebcce81ca8203454a811d4cf8900314154d3259bb8f0b42ab17f67396a8694a54cae3283326e57ad250cd + languageName: node + linkType: hard + "rimraf@npm:^3.0.2": version: 3.0.2 resolution: "rimraf@npm:3.0.2" @@ -9285,6 +10380,27 @@ __metadata: languageName: node linkType: hard +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": + version: 2.0.2 + resolution: "ripemd160@npm:2.0.2" + dependencies: + hash-base: ^3.0.0 + inherits: ^2.0.1 + checksum: 006accc40578ee2beae382757c4ce2908a826b27e2b079efdcd2959ee544ddf210b7b5d7d5e80467807604244e7388427330f5c6d4cd61e6edaddc5773ccc393 + languageName: node + linkType: hard + +"rlp@npm:^2.2.4": + version: 2.2.7 + resolution: "rlp@npm:2.2.7" + dependencies: + bn.js: ^5.2.0 + bin: + rlp: bin/rlp + checksum: 3db4dfe5c793f40ac7e0be689a1f75d05e6f2ca0c66189aeb62adab8c436b857ab4420a419251ee60370d41d957a55698fc5e23ab1e1b41715f33217bc4bb558 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -9315,7 +10431,7 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 @@ -9363,7 +10479,7 @@ __metadata: languageName: node linkType: hard -"scrypt-js@npm:3.0.1": +"scrypt-js@npm:^3.0.0": version: 3.0.1 resolution: "scrypt-js@npm:3.0.1" checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 @@ -9374,11 +10490,24 @@ __metadata: version: 0.0.0-use.local resolution: "se-2@workspace:." dependencies: + "@chainlink/contracts": ^1.3.0 husky: ~8.0.3 lint-staged: ~13.2.2 languageName: unknown linkType: soft +"secp256k1@npm:^4.0.1": + version: 4.0.4 + resolution: "secp256k1@npm:4.0.4" + dependencies: + elliptic: ^6.5.7 + node-addon-api: ^5.0.0 + node-gyp: latest + node-gyp-build: ^4.2.0 + checksum: 9314ddcd27506c5f8d9b21a2c131c62464762f597b82fe48ba89b50149ec95cd566d6ad2d4a922553dd0a8b4b14c1ccd83283f487229a941b6c7c02361ef5177 + languageName: node + linkType: hard + "semver@npm:6.3.1, semver@npm:^6.0.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" @@ -9399,7 +10528,16 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": +"semver@npm:^5.5.0, semver@npm:^5.6.0": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: fb4ab5e0dd1c22ce0c937ea390b4a822147a9c53dbd2a9a0132f12fe382902beef4fbf12cf51bb955248d8d15874ce8cd89532569756384f994309825f10b686 + languageName: node + linkType: hard + +"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0, semver@npm:^7.6.3": version: 7.6.3 resolution: "semver@npm:7.6.3" bin: @@ -9441,6 +10579,13 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.5": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: c9a6f2c5b51a2dabdc0247db9c46460152ffc62ee139f3157440bd48e7c59425093f42719ac1d7931f054f153e2d26cf37dfeb8da17a794a58198a2705e527fd + languageName: node + linkType: hard + "setprototypeof@npm:1.1.1": version: 1.1.1 resolution: "setprototypeof@npm:1.1.1" @@ -9448,7 +10593,7 @@ __metadata: languageName: node linkType: hard -"sha.js@npm:^2.4.11": +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.11, sha.js@npm:^2.4.8": version: 2.4.11 resolution: "sha.js@npm:2.4.11" dependencies: @@ -9460,6 +10605,15 @@ __metadata: languageName: node linkType: hard +"shebang-command@npm:^1.2.0": + version: 1.2.0 + resolution: "shebang-command@npm:1.2.0" + dependencies: + shebang-regex: ^1.0.0 + checksum: 9eed1750301e622961ba5d588af2212505e96770ec376a37ab678f965795e995ade7ed44910f5d3d3cb5e10165a1847f52d3348c64e146b8be922f7707958908 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -9469,6 +10623,13 @@ __metadata: languageName: node linkType: hard +"shebang-regex@npm:^1.0.0": + version: 1.0.0 + resolution: "shebang-regex@npm:1.0.0" + checksum: 404c5a752cd40f94591dfd9346da40a735a05139dac890ffc229afba610854d8799aaa52f87f7e0c94c5007f2c6af55bdcaeb584b56691926c5eaf41dc8f1372 + languageName: node + linkType: hard + "shebang-regex@npm:^3.0.0": version: 3.0.0 resolution: "shebang-regex@npm:3.0.0" @@ -9476,31 +10637,6 @@ __metadata: languageName: node linkType: hard -"shelljs@npm:^0.8.5": - version: 0.8.5 - resolution: "shelljs@npm:0.8.5" - dependencies: - glob: ^7.0.0 - interpret: ^1.0.0 - rechoir: ^0.6.2 - bin: - shjs: bin/shjs - checksum: 7babc46f732a98f4c054ec1f048b55b9149b98aa2da32f6cf9844c434b43c6251efebd6eec120937bd0999e13811ebd45efe17410edb3ca938f82f9381302748 - languageName: node - linkType: hard - -"shx@npm:~0.3.4": - version: 0.3.4 - resolution: "shx@npm:0.3.4" - dependencies: - minimist: ^1.2.3 - shelljs: ^0.8.5 - bin: - shx: lib/cli.js - checksum: 0aa168bfddc11e3fe8943cce2e0d2d8514a560bd58cf2b835b4351ba03f46068f7d88286c2627f4b85604e81952154c43746369fb3f0d60df0e3b511f465e5b8 - languageName: node - linkType: hard - "side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": version: 1.0.6 resolution: "side-channel@npm:1.0.6" @@ -9534,6 +10670,13 @@ __metadata: languageName: node linkType: hard +"slash@npm:^2.0.0": + version: 2.0.0 + resolution: "slash@npm:2.0.0" + checksum: 512d4350735375bd11647233cb0e2f93beca6f53441015eea241fe784d8068281c3987fbaa93e7ef1c38df68d9c60013045c92837423c69115297d6169aa85e6 + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -9623,6 +10766,13 @@ __metadata: languageName: node linkType: hard +"solidity-ast@npm:^0.4.51": + version: 0.4.59 + resolution: "solidity-ast@npm:0.4.59" + checksum: 348657bb98e027c0969d44c3bbcfb3ac4a3ea32db37ce582e291b544fb5361be5bbebf828c562bd6ddaa1ce89d3e241e3b528dbfbadcce0dbc51a655f5088d26 + languageName: node + linkType: hard + "sonic-boom@npm:^2.2.1": version: 2.8.0 resolution: "sonic-boom@npm:2.8.0" @@ -9646,6 +10796,16 @@ __metadata: languageName: node linkType: hard +"spawndamnit@npm:^2.0.0": + version: 2.0.0 + resolution: "spawndamnit@npm:2.0.0" + dependencies: + cross-spawn: ^5.1.0 + signal-exit: ^3.0.2 + checksum: c74b5e264ee5bc13d55692fd422d74c282e4607eb04ac64d19d06796718d89b14921620fa4237ec5635e7acdff21461670ff19850f210225410a353cad0d7fed + languageName: node + linkType: hard + "split-on-first@npm:^1.0.0": version: 1.1.0 resolution: "split-on-first@npm:1.1.0" @@ -9667,6 +10827,13 @@ __metadata: languageName: node linkType: hard +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.6 resolution: "ssri@npm:10.0.6" @@ -10049,6 +11216,13 @@ __metadata: languageName: node linkType: hard +"term-size@npm:^2.1.0": + version: 2.2.1 + resolution: "term-size@npm:2.2.1" + checksum: 1ed981335483babc1e8206f843e06bd2bf89b85f0bf5a9a9d928033a0fcacdba183c03ba7d91814643015543ba002f1339f7112402a21da8f24b6c56b062a5a9 + languageName: node + linkType: hard + "text-table@npm:^0.2.0": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -10113,6 +11287,15 @@ __metadata: languageName: node linkType: hard +"tmp@npm:^0.0.33": + version: 0.0.33 + resolution: "tmp@npm:0.0.33" + dependencies: + os-tmpdir: ~1.0.2 + checksum: 902d7aceb74453ea02abbf58c203f4a8fc1cead89b60b31e354f74ed5b3fb09ea817f94fb310f884a5d16987dd9fa5a735412a7c2dd088dd3d415aa819ae3a28 + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -10150,13 +11333,6 @@ __metadata: languageName: node linkType: hard -"toml@npm:~3.0.0": - version: 3.0.0 - resolution: "toml@npm:3.0.0" - checksum: 5d7f1d8413ad7780e9bdecce8ea4c3f5130dd53b0a4f2e90b93340979a137739879d7b9ce2ce05c938b8cc828897fe9e95085197342a1377dd8850bf5125f15f - languageName: node - linkType: hard - "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -10290,6 +11466,13 @@ __metadata: languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 3b32f873cd02bc7001b00a61502b7ddc4b49278aabe68d652f732e1b5d768c072de0bc734b427abf59d0520a5f19a2e07309ab921ef02018fa1cb4af155cdb37 + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -10470,6 +11653,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~6.19.8": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: de51f1b447d22571cf155dfe14ff6d12c5bdaec237c765085b439c38ca8518fc360e88c70f99469162bf2e14188a7b0bcb06e1ed2dc031042b984b0bb9544017 + languageName: node + linkType: hard + "undici@npm:5.28.4": version: 5.28.4 resolution: "undici@npm:5.28.4" @@ -11007,6 +12197,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^1.2.9": + version: 1.3.1 + resolution: "which@npm:1.3.1" + dependencies: + isexe: ^2.0.0 + bin: + which: ./bin/which + checksum: f2e185c6242244b8426c9df1510e86629192d93c1a986a7d2a591f2c24869e7ffd03d6dac07ca863b2e4c06f59a4cc9916c585b72ee9fa1aa609d0124df15e04 + languageName: node + linkType: hard + "which@npm:^2.0.1": version: 2.0.2 resolution: "which@npm:2.0.2" @@ -11199,6 +12400,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^2.1.2": + version: 2.1.2 + resolution: "yallist@npm:2.1.2" + checksum: 9ba99409209f485b6fcb970330908a6d41fa1c933f75e08250316cce19383179a6b70a7e0721b89672ebb6199cc377bf3e432f55100da6a7d6e11902b0a642cb + languageName: node + linkType: hard + "yallist@npm:^3.0.0, yallist@npm:^3.1.1": version: 3.1.1 resolution: "yallist@npm:3.1.1" @@ -11213,6 +12421,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^1.10.2": + version: 1.10.2 + resolution: "yaml@npm:1.10.2" + checksum: ce4ada136e8a78a0b08dc10b4b900936912d15de59905b2bf415b4d33c63df1d555d23acb2a41b23cf9fb5da41c256441afca3d6509de7247daa062fd2c5ea5f + languageName: node + linkType: hard + "yaml@npm:^2.2.2, yaml@npm:^2.3.4": version: 2.6.0 resolution: "yaml@npm:2.6.0" From b37418ed70d6c88da5cba56bd97c481470821713 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 19:12:58 +0530 Subject: [PATCH 6/7] Oracle Integration --- .../foundry/lib/chainlink/contracts/README.md | 75 - .../contracts/abi/v0.8/AccessControl.json | 227 - .../abi/v0.8/AccessControllerInterface.json | 26 - .../chainlink/contracts/abi/v0.8/Address.json | 29 - .../abi/v0.8/AggregatorInterface.json | 129 - .../abi/v0.8/AggregatorV2V3Interface.json | 240 - .../abi/v0.8/AggregatorV3Interface.json | 113 - .../v0.8/AggregatorValidatorInterface.json | 36 - .../contracts/abi/v0.8/ArbGasInfo.json | 406 - .../chainlink/contracts/abi/v0.8/ArbSys.json | 355 - .../v0.8/ArbitrumCrossDomainForwarder.json | 199 - .../abi/v0.8/ArbitrumCrossDomainGovernor.json | 217 - .../abi/v0.8/ArbitrumL1BridgeAdapter.json | 272 - .../abi/v0.8/ArbitrumL2BridgeAdapter.json | 155 - .../contracts/abi/v0.8/ArbitrumModule.json | 90 - .../abi/v0.8/ArbitrumSequencerUptimeFeed.json | 621 - .../contracts/abi/v0.8/ArbitrumValidator.json | 565 - .../contracts/abi/v0.8/AuthorizedCallers.json | 164 - .../abi/v0.8/AuthorizedForwarder.json | 286 - .../abi/v0.8/AuthorizedReceiver.json | 66 - .../contracts/abi/v0.8/AutomationBase.json | 7 - .../abi/v0.8/AutomationCompatible.json | 44 - .../v0.8/AutomationCompatibleInterface.json | 39 - .../abi/v0.8/AutomationCompatibleUtils.json | 212 - .../abi/v0.8/AutomationConsumerBenchmark.json | 212 - .../abi/v0.8/AutomationForwarder.json | 69 - .../abi/v0.8/AutomationForwarderLogic.json | 41 - .../abi/v0.8/AutomationRegistrar2_1.json | 761 - .../abi/v0.8/AutomationRegistrar2_3.json | 745 - .../abi/v0.8/AutomationRegistry2_2.json | 1367 -- .../abi/v0.8/AutomationRegistry2_3.json | 1580 -- .../abi/v0.8/AutomationRegistryBase2_2.json | 952 -- .../abi/v0.8/AutomationRegistryBase2_3.json | 1180 -- .../v0.8/AutomationRegistryBaseInterface.json | 403 - ...AutomationRegistryExecutableInterface.json | 447 - .../abi/v0.8/AutomationRegistryInterface.json | 447 - .../abi/v0.8/AutomationRegistryLogicA2_2.json | 1334 -- .../abi/v0.8/AutomationRegistryLogicA2_3.json | 1329 -- .../abi/v0.8/AutomationRegistryLogicB2_2.json | 1998 --- .../abi/v0.8/AutomationRegistryLogicB2_3.json | 1672 -- .../abi/v0.8/AutomationRegistryLogicC2_3.json | 2678 --- .../abi/v0.8/AutomationUtils2_1.json | 302 - .../abi/v0.8/AutomationUtils2_2.json | 302 - .../abi/v0.8/AutomationUtils2_3.json | 47 - .../abi/v0.8/BaseSequencerUptimeFeed.json | 562 - .../contracts/abi/v0.8/BaseValidator.json | 314 - .../contracts/abi/v0.8/BasicConsumer.json | 211 - .../abi/v0.8/BatchBlockhashStore.json | 76 - .../abi/v0.8/BatchVRFCoordinatorV2.json | 156 - .../abi/v0.8/BatchVRFCoordinatorV2Plus.json | 161 - .../contracts/abi/v0.8/BlockhashStore.json | 52 - .../abi/v0.8/BlockhashStoreInterface.json | 21 - .../chainlink/contracts/abi/v0.8/Broken.json | 45 - .../contracts/abi/v0.8/BurnMintERC677.json | 784 - .../contracts/abi/v0.8/ByteUtil.json | 7 - .../contracts/abi/v0.8/CallWithExactGas.json | 17 - .../abi/v0.8/CallWithExactGasHelper.json | 124 - .../contracts/abi/v0.8/Callback.json | 39 - .../abi/v0.8/CapabilitiesRegistry.json | 1324 -- .../v0.8/CapabilityConfigurationContract.json | 74 - .../contracts/abi/v0.8/ChainModuleBase.json | 90 - .../contracts/abi/v0.8/ChainReaderTester.json | 888 - .../abi/v0.8/ChainSpecificUtilHelper.json | 72 - .../contracts/abi/v0.8/Chainable.json | 30 - .../contracts/abi/v0.8/ChainlinkClient.json | 41 - .../abi/v0.8/ChainlinkClientHelper.json | 125 - .../abi/v0.8/ChainlinkClientTestHelper.json | 357 - .../abi/v0.8/ChainlinkRequestInterface.json | 78 - .../abi/v0.8/ChainlinkTestHelper.json | 125 - .../contracts/abi/v0.8/Chainlinked.json | 41 - .../abi/v0.8/ChannelConfigStore.json | 164 - .../contracts/abi/v0.8/Configurator.json | 257 - .../contracts/abi/v0.8/ConfirmedOwner.json | 84 - .../abi/v0.8/ConfirmedOwnerTestHelper.json | 91 - .../abi/v0.8/ConfirmedOwnerWithProposal.json | 89 - .../contracts/abi/v0.8/Consumer.json | 190 - .../chainlink/contracts/abi/v0.8/Counter.json | 54 - .../chainlink/contracts/abi/v0.8/Cron.json | 1218 -- .../abi/v0.8/CronExternalTestHelper.json | 78 - .../abi/v0.8/CronInternalTestHelper.json | 115 - .../contracts/abi/v0.8/CronReceiver.json | 35 - .../contracts/abi/v0.8/CronUpkeep.json | 449 - .../abi/v0.8/CronUpkeepDelegate.json | 31 - .../contracts/abi/v0.8/CronUpkeepFactory.json | 204 - .../abi/v0.8/CronUpkeepTestHelper.json | 517 - .../v0.8/CrossDomainDelegateForwarder.json | 162 - .../abi/v0.8/CrossDomainForwarder.json | 162 - .../abi/v0.8/CrossDomainOwnable.json | 155 - .../contracts/abi/v0.8/Denominations.json | 262 - .../abi/v0.8/DestinationFeeManager.json | 805 - .../abi/v0.8/DestinationFeeManagerProxy.json | 61 - .../abi/v0.8/DestinationRewardManager.json | 554 - .../abi/v0.8/DestinationVerifier.json | 581 - .../abi/v0.8/DestinationVerifierProxy.json | 213 - .../contracts/abi/v0.8/DummyProtocol.json | 214 - .../chainlink/contracts/abi/v0.8/ECDSA.json | 29 - .../chainlink/contracts/abi/v0.8/EIP712.json | 67 - .../contracts/abi/v0.8/ENSInterface.json | 218 - .../contracts/abi/v0.8/ENSResolver.json | 21 - .../chainlink/contracts/abi/v0.8/ERC165.json | 21 - .../chainlink/contracts/abi/v0.8/ERC20.json | 310 - .../abi/v0.8/ERC20BalanceMonitor.json | 505 - .../abi/v0.8/ERC20BalanceMonitorExposed.json | 523 - .../contracts/abi/v0.8/ERC20Burnable.json | 341 - .../contracts/abi/v0.8/ERC20Mock.json | 380 - .../abi/v0.8/ERC20Mock6Decimals.json | 380 - .../contracts/abi/v0.8/ERC20Permit.json | 347 - .../chainlink/contracts/abi/v0.8/ERC677.json | 348 - .../contracts/abi/v0.8/EmptyOracle.json | 213 - .../contracts/abi/v0.8/EntryPoint.json | 1242 -- .../contracts/abi/v0.8/EnumerableMap.json | 13 - .../abi/v0.8/EnumerableMapBytes32.json | 7 - .../contracts/abi/v0.8/ErroredVerifier.json | 340 - .../contracts/abi/v0.8/EthBalanceMonitor.json | 478 - .../abi/v0.8/EthBalanceMonitorExposed.json | 496 - .../abi/v0.8/ExecutionPrevention.json | 7 - .../abi/v0.8/ExposedChannelConfigStore.json | 183 - .../abi/v0.8/ExposedConfigurator.json | 288 - .../abi/v0.8/ExposedVRFCoordinatorV2_5.json | 2155 --- .../ExposedVRFCoordinatorV2_5_Arbitrum.json | 1858 -- .../ExposedVRFCoordinatorV2_5_Optimism.json | 1943 --- .../contracts/abi/v0.8/ExposedVerifier.json | 71 - .../ExtendedVRFCoordinatorV2Interface.json | 309 - .../contracts/abi/v0.8/FeeManager.json | 698 - .../contracts/abi/v0.8/FeeManagerProxy.json | 51 - .../contracts/abi/v0.8/FeedConsumer.json | 214 - .../abi/v0.8/FeedRegistryInterface.json | 803 - .../chainlink/contracts/abi/v0.8/Flags.json | 423 - .../contracts/abi/v0.8/FlagsInterface.json | 92 - .../contracts/abi/v0.8/FlagsTestHelper.json | 64 - .../contracts/abi/v0.8/FunctionsBilling.json | 533 - .../FunctionsBillingRegistryEventsMock.json | 839 - .../contracts/abi/v0.8/FunctionsClient.json | 56 - .../abi/v0.8/FunctionsClientExample.json | 280 - .../abi/v0.8/FunctionsClientHarness.json | 460 - .../abi/v0.8/FunctionsClientTestHelper.json | 375 - .../v0.8/FunctionsClientUpgradeHelper.json | 413 - .../FunctionsClientWithEmptyCallback.json | 161 - .../abi/v0.8/FunctionsCoordinator.json | 1267 -- .../abi/v0.8/FunctionsCoordinatorHarness.json | 1664 -- .../v0.8/FunctionsCoordinatorTestHelper.json | 1318 -- .../abi/v0.8/FunctionsLoadTestClient.json | 421 - .../abi/v0.8/FunctionsOracleEventsMock.json | 586 - .../contracts/abi/v0.8/FunctionsRequest.json | 35 - .../contracts/abi/v0.8/FunctionsRouter.json | 1720 -- .../abi/v0.8/FunctionsRouterHarness.json | 1772 -- .../abi/v0.8/FunctionsSubscriptions.json | 761 - .../v0.8/FunctionsSubscriptionsHarness.json | 887 - .../abi/v0.8/FunctionsTestHelper.json | 93 - .../abi/v0.8/FunctionsV1EventsMock.json | 957 -- .../contracts/abi/v0.8/GasConsumer.json | 16 - .../abi/v0.8/GasGuzzlingConsumer.json | 273 - .../contracts/abi/v0.8/GasPriceOracle.json | 242 - .../contracts/abi/v0.8/GenericReceiver.json | 56 - .../contracts/abi/v0.8/GetterSetter.json | 190 - .../chainlink/contracts/abi/v0.8/Greeter.json | 117 - .../abi/v0.8/HeartbeatRequester.json | 184 - .../v0.8/IAbstractArbitrumTokenGateway.json | 163 - .../contracts/abi/v0.8/IAccessControl.json | 195 - .../contracts/abi/v0.8/IAccessController.json | 26 - .../contracts/abi/v0.8/IAccount.json | 88 - .../contracts/abi/v0.8/IAggregator.json | 229 - .../contracts/abi/v0.8/IAggregatorProxy.json | 15 - .../contracts/abi/v0.8/IArbRollupCore.json | 880 - .../chainlink/contracts/abi/v0.8/IArbSys.json | 21 - .../abi/v0.8/IArbitrumDelayedInbox.json | 407 - .../abi/v0.8/IArbitrumGatewayRouter.json | 232 - .../contracts/abi/v0.8/IArbitrumInbox.json | 326 - .../abi/v0.8/IArbitrumL1GatewayRouter.json | 304 - .../abi/v0.8/IArbitrumTokenGateway.json | 137 - .../abi/v0.8/IAuthorizedReceiver.json | 47 - .../abi/v0.8/IAutomationForwarder.json | 83 - .../abi/v0.8/IAutomationRegistryConsumer.json | 115 - .../abi/v0.8/IAutomationRegistryMaster.json | 2725 --- .../v0.8/IAutomationRegistryMaster2_3.json | 3606 ---- .../abi/v0.8/IAutomationV21PlusCommon.json | 1441 -- .../chainlink/contracts/abi/v0.8/IBridge.json | 227 - .../contracts/abi/v0.8/IBridgeAdapter.json | 131 - .../contracts/abi/v0.8/IBurnMintERC20.json | 252 - .../abi/v0.8/ICapabilityConfiguration.json | 55 - .../contracts/abi/v0.8/IChainModule.json | 90 - .../abi/v0.8/IChannelConfigStore.json | 44 - .../contracts/abi/v0.8/IConfigurator.json | 112 - .../abi/v0.8/ICrossDomainOwnable.json | 73 - .../abi/v0.8/IDelegateForwarder.json | 20 - .../abi/v0.8/IDestinationFeeManager.json | 236 - .../abi/v0.8/IDestinationRewardManager.json | 197 - .../abi/v0.8/IDestinationVerifier.json | 147 - .../v0.8/IDestinationVerifierFeeManager.json | 107 - .../abi/v0.8/IDestinationVerifierProxy.json | 108 - .../IDestinationVerifierProxyVerifier.json | 105 - .../contracts/abi/v0.8/IERC1155Errors.json | 104 - .../chainlink/contracts/abi/v0.8/IERC165.json | 21 - .../chainlink/contracts/abi/v0.8/IERC20.json | 185 - .../contracts/abi/v0.8/IERC20Errors.json | 88 - .../contracts/abi/v0.8/IERC20Metadata.json | 224 - .../contracts/abi/v0.8/IERC20Permit.json | 77 - .../contracts/abi/v0.8/IERC5267.json | 51 - .../chainlink/contracts/abi/v0.8/IERC677.json | 62 - .../contracts/abi/v0.8/IERC677Receiver.json | 25 - .../contracts/abi/v0.8/IERC721Errors.json | 105 - .../contracts/abi/v0.8/IEntryPoint.json | 1065 -- .../contracts/abi/v0.8/IFeeManager.json | 250 - .../chainlink/contracts/abi/v0.8/IFlags.json | 118 - .../contracts/abi/v0.8/IForwarder.json | 20 - .../contracts/abi/v0.8/IFunctionsBilling.json | 150 - .../contracts/abi/v0.8/IFunctionsClient.json | 25 - .../abi/v0.8/IFunctionsCoordinator.json | 187 - .../contracts/abi/v0.8/IFunctionsRouter.json | 338 - .../abi/v0.8/IFunctionsSubscriptions.json | 463 - .../contracts/abi/v0.8/IGasBoundCaller.json | 25 - .../contracts/abi/v0.8/IGasToken.json | 59 - .../chainlink/contracts/abi/v0.8/IInbox.json | 383 - .../abi/v0.8/IKeeperRegistryMaster.json | 2655 --- .../abi/v0.8/IL2ArbitrumGateway.json | 322 - .../abi/v0.8/IL2ArbitrumMessenger.json | 33 - .../contracts/abi/v0.8/IL2GatewayRouter.json | 36 - .../contracts/abi/v0.8/IL2StandardBridge.json | 35 - .../contracts/abi/v0.8/ILinkAvailable.json | 15 - .../abi/v0.8/ILiquidityContainer.json | 66 - .../contracts/abi/v0.8/ILiquidityManager.json | 55 - .../contracts/abi/v0.8/ILogAutomation.json | 86 - .../contracts/abi/v0.8/IMessageProvider.json | 34 - .../contracts/abi/v0.8/INodeInterface.json | 320 - .../abi/v0.8/IOffchainAggregator.json | 15 - .../v0.8/IOptimismCrossDomainMessenger.json | 77 - .../abi/v0.8/IOptimismDisputeGameFactory.json | 71 - .../abi/v0.8/IOptimismL1StandardBridge.json | 25 - .../abi/v0.8/IOptimismL2OutputOracle.json | 57 - .../v0.8/IOptimismL2ToL1MessagePasser.json | 51 - .../abi/v0.8/IOptimismMintableERC20.json | 83 - .../v0.8/IOptimismMintableERC20Minimal.json | 47 - .../contracts/abi/v0.8/IOptimismPortal.json | 142 - .../contracts/abi/v0.8/IOptimismPortal2.json | 28 - .../abi/v0.8/IOptimismStandardBridge.json | 83 - .../chainlink/contracts/abi/v0.8/IOutbox.json | 55 - .../contracts/abi/v0.8/IOwnable.json | 35 - .../abi/v0.8/IOwnableFunctionsRouter.json | 371 - .../contracts/abi/v0.8/IPaymaster.json | 116 - .../contracts/abi/v0.8/IReceiver.json | 20 - .../contracts/abi/v0.8/IRewardManager.json | 184 - .../chainlink/contracts/abi/v0.8/IRouter.json | 239 - .../abi/v0.8/IScrollL1GasPriceOracle.json | 131 - .../contracts/abi/v0.8/IScrollMessenger.json | 145 - .../chainlink/contracts/abi/v0.8/ISemver.json | 15 - .../abi/v0.8/ISequencerUptimeFeed.json | 20 - .../contracts/abi/v0.8/IStakeManager.json | 244 - .../contracts/abi/v0.8/ISystemContext.json | 41 - .../abi/v0.8/ITermsOfServiceAllowList.json | 191 - .../contracts/abi/v0.8/ITypeAndVersion.json | 15 - .../contracts/abi/v0.8/IVRFCoordinatorV2.json | 375 - .../abi/v0.8/IVRFCoordinatorV2Plus.json | 246 - .../v0.8/IVRFCoordinatorV2PlusFulfill.json | 110 - .../v0.8/IVRFCoordinatorV2PlusInternal.json | 490 - .../v0.8/IVRFCoordinatorV2PlusMigration.json | 15 - .../v0.8/IVRFMigratableConsumerV2Plus.json | 28 - .../abi/v0.8/IVRFSubscriptionV2Plus.json | 195 - .../contracts/abi/v0.8/IVRFV2PlusMigrate.json | 20 - .../contracts/abi/v0.8/IVRFV2PlusWrapper.json | 181 - .../contracts/abi/v0.8/IVerifier.json | 300 - .../abi/v0.8/IVerifierFeeManager.json | 97 - .../contracts/abi/v0.8/IVerifierProxy.json | 21 - .../chainlink/contracts/abi/v0.8/IWERC20.json | 22 - .../contracts/abi/v0.8/IWithdrawal.json | 33 - .../contracts/abi/v0.8/IWrappedNative.json | 205 - .../IZKSyncAutomationRegistryMaster2_3.json | 3567 ---- .../abi/v0.8/KeeperCompatibleTestHelper.json | 51 - .../contracts/abi/v0.8/KeeperConsumer.json | 94 - .../abi/v0.8/KeeperConsumerPerformance.json | 289 - .../contracts/abi/v0.8/KeeperRegistrar.json | 594 - .../abi/v0.8/KeeperRegistrar1_2Mock.json | 491 - .../abi/v0.8/KeeperRegistrar2_0.json | 654 - .../contracts/abi/v0.8/KeeperRegistry1_2.json | 1486 -- .../contracts/abi/v0.8/KeeperRegistry1_3.json | 1744 -- .../contracts/abi/v0.8/KeeperRegistry2_0.json | 1951 --- .../contracts/abi/v0.8/KeeperRegistry2_1.json | 1349 -- .../abi/v0.8/KeeperRegistryBase1_3.json | 857 - .../abi/v0.8/KeeperRegistryBase2_0.json | 882 - .../abi/v0.8/KeeperRegistryBase2_1.json | 944 -- ...RegistryCheckUpkeepGasUsageWrapper1_2.json | 131 - ...stryCheckUpkeepGasUsageWrapper1_2Mock.json | 172 - .../abi/v0.8/KeeperRegistryLogic1_3.json | 1208 -- .../abi/v0.8/KeeperRegistryLogic2_0.json | 1290 -- .../abi/v0.8/KeeperRegistryLogicA2_1.json | 1326 -- .../abi/v0.8/KeeperRegistryLogicB2_1.json | 1938 --- .../abi/v0.8/KeepersVRFConsumer.json | 242 - .../abi/v0.8/KeystoneFeedsConsumer.json | 215 - .../v0.8/KeystoneFeedsPermissionHandler.json | 185 - .../contracts/abi/v0.8/KeystoneForwarder.json | 585 - .../chainlink/contracts/abi/v0.8/L1Block.json | 347 - .../abi/v0.8/LinkAvailableBalanceMonitor.json | 946 -- .../contracts/abi/v0.8/LinkToken.json | 763 - .../abi/v0.8/LinkTokenInterface.json | 245 - .../contracts/abi/v0.8/LinkTokenReceiver.json | 38 - .../abi/v0.8/LinkTokenTestHelper.json | 763 - .../contracts/abi/v0.8/LiquidityManager.json | 1147 -- .../abi/v0.8/LiquidityManagerHelper.json | 1165 -- .../contracts/abi/v0.8/LogEmitter.json | 122 - .../abi/v0.8/LogTriggeredStreamsLookup.json | 419 - .../contracts/abi/v0.8/LogUpkeepCounter.json | 321 - .../abi/v0.8/MaliciousChainlinked.json | 41 - .../v0.8/MaliciousConfigurationContract.json | 85 - .../contracts/abi/v0.8/MaliciousConsumer.json | 194 - .../abi/v0.8/MaliciousMultiWordConsumer.json | 194 - .../abi/v0.8/MaliciousReportReceiver.json | 71 - .../abi/v0.8/MaliciousRequester.json | 167 - .../abi/v0.8/MaliciousRevertingReceiver.json | 39 - .../chainlink/contracts/abi/v0.8/Math.json | 7 - .../contracts/abi/v0.8/MercuryRegistry.json | 594 - .../abi/v0.8/MercuryRegistryBatchUpkeep.json | 306 - .../MigratableKeeperRegistryInterface.json | 46 - .../MigratableKeeperRegistryInterfaceV2.json | 46 - .../contracts/abi/v0.8/MockAggregator.json | 67 - .../abi/v0.8/MockAggregatorProxy.json | 39 - .../abi/v0.8/MockAggregatorV2V3.json | 240 - .../abi/v0.8/MockAggregatorValidator.json | 84 - .../contracts/abi/v0.8/MockArbGasInfo.json | 53 - .../contracts/abi/v0.8/MockArbSys.json | 34 - .../contracts/abi/v0.8/MockArbitrumInbox.json | 462 - .../contracts/abi/v0.8/MockBridgehub.json | 795 - .../abi/v0.8/MockETHLINKAggregator.json | 137 - .../abi/v0.8/MockETHUSDAggregator.json | 150 - .../abi/v0.8/MockGasBoundCaller.json | 36 - .../abi/v0.8/MockKeeperRegistry2_1.json | 138 - .../abi/v0.8/MockL1BridgeAdapter.json | 322 - .../abi/v0.8/MockL2BridgeAdapter.json | 131 - .../contracts/abi/v0.8/MockLinkToken.json | 135 - .../abi/v0.8/MockOVMCrossDomainMessenger.json | 101 - .../abi/v0.8/MockOVMGasPriceOracle.json | 40 - .../abi/v0.8/MockOffchainAggregator.json | 41 - .../MockOptimismL1CrossDomainMessenger.json | 238 - .../MockOptimismL2CrossDomainMessenger.json | 146 - .../contracts/abi/v0.8/MockReceiver.json | 35 - .../v0.8/MockScrollCrossDomainMessenger.json | 169 - .../MockScrollL1CrossDomainMessenger.json | 284 - .../abi/v0.8/MockScrollL1MessageQueue.json | 302 - .../MockScrollL2CrossDomainMessenger.json | 195 - .../contracts/abi/v0.8/MockUpkeep.json | 218 - .../contracts/abi/v0.8/MockV3Aggregator.json | 297 - .../abi/v0.8/MockZKSyncSystemContext.json | 41 - .../contracts/abi/v0.8/MultiSend.json | 20 - .../contracts/abi/v0.8/MultiWordConsumer.json | 432 - .../contracts/abi/v0.8/NoOpOCR3.json | 396 - .../contracts/abi/v0.8/OCR2Abstract.json | 212 - .../contracts/abi/v0.8/OCR2Base.json | 318 - .../contracts/abi/v0.8/OCR3Abstract.json | 189 - .../contracts/abi/v0.8/OCR3Base.json | 391 - .../contracts/abi/v0.8/OCR3Capability.json | 299 - .../contracts/abi/v0.8/OCR3Helper.json | 463 - .../abi/v0.8/OVM_GasPriceOracle.json | 298 - .../abi/v0.8/OpStackBurnMintERC677.json | 820 - .../contracts/abi/v0.8/Operator.json | 738 - .../contracts/abi/v0.8/OperatorFactory.json | 176 - .../contracts/abi/v0.8/OperatorInterface.json | 287 - .../v0.8/OptimismCrossDomainForwarder.json | 204 - .../abi/v0.8/OptimismCrossDomainGovernor.json | 222 - .../abi/v0.8/OptimismL1BridgeAdapter.json | 200 - .../v0.8/OptimismL1BridgeAdapterEncoder.json | 168 - .../contracts/abi/v0.8/OptimismL1Fees.json | 158 - .../abi/v0.8/OptimismL2BridgeAdapter.json | 172 - .../contracts/abi/v0.8/OptimismModule.json | 90 - .../contracts/abi/v0.8/OptimismModuleV2.json | 216 - .../abi/v0.8/OptimismSequencerUptimeFeed.json | 583 - .../contracts/abi/v0.8/OptimismValidator.json | 335 - .../contracts/abi/v0.8/OracleInterface.json | 77 - .../contracts/abi/v0.8/OwnerIsCreator.json | 78 - .../contracts/abi/v0.8/Pausable.json | 51 - .../contracts/abi/v0.8/Paymaster.json | 359 - .../abi/v0.8/PerformDataChecker.json | 89 - .../abi/v0.8/PermissionedForwardProxy.json | 183 - .../contracts/abi/v0.8/PoRAddressList.json | 39 - .../contracts/abi/v0.8/PointerInterface.json | 15 - .../chainlink/contracts/abi/v0.8/Proxy.json | 10 - .../contracts/abi/v0.8/ReceiveEmitter.json | 25 - .../abi/v0.8/ReceiveFallbackEmitter.json | 25 - .../contracts/abi/v0.8/ReceiveReverter.json | 6 - .../contracts/abi/v0.8/Receiver.json | 76 - .../contracts/abi/v0.8/ReportEncoder.json | 124 - .../contracts/abi/v0.8/RewardManager.json | 535 - .../contracts/abi/v0.8/Routable.json | 30 - .../lib/chainlink/contracts/abi/v0.8/SCA.json | 235 - .../contracts/abi/v0.8/SafeCast.json | 56 - .../contracts/abi/v0.8/SafeERC20.json | 34 - .../abi/v0.8/ScrollCrossDomainForwarder.json | 204 - .../abi/v0.8/ScrollCrossDomainGovernor.json | 222 - .../contracts/abi/v0.8/ScrollModule.json | 216 - .../abi/v0.8/ScrollSequencerUptimeFeed.json | 588 - .../contracts/abi/v0.8/ScrollValidator.json | 353 - .../contracts/abi/v0.8/SenderCreator.json | 21 - .../contracts/abi/v0.8/ShortStrings.json | 18 - .../abi/v0.8/SimpleLogUpkeepCounter.json | 445 - .../abi/v0.8/SimpleReadAccessController.json | 188 - .../abi/v0.8/SimpleWriteAccessController.json | 193 - .../abi/v0.8/SmartContractAccountFactory.json | 44 - .../abi/v0.8/SmartContractAccountHelper.json | 171 - .../abi/v0.8/SortedSetValidationUtil.json | 34 - .../contracts/abi/v0.8/StakeManager.json | 287 - .../StreamsLookupCompatibleInterface.json | 91 - .../abi/v0.8/StreamsLookupUpkeep.json | 448 - .../chainlink/contracts/abi/v0.8/Strings.json | 18 - .../contracts/abi/v0.8/SubscriptionAPI.json | 843 - .../abi/v0.8/TermsOfServiceAllowList.json | 466 - .../abi/v0.8/TrustedBlockhashStore.json | 235 - .../abi/v0.8/TypeAndVersionInterface.json | 15 - .../contracts/abi/v0.8/UpkeepAutoFunder.json | 261 - .../abi/v0.8/UpkeepBalanceMonitor.json | 524 - .../contracts/abi/v0.8/UpkeepCounter.json | 201 - .../contracts/abi/v0.8/UpkeepCounterNew.json | 427 - .../contracts/abi/v0.8/UpkeepMock.json | 239 - .../v0.8/UpkeepPerformCounterRestrictive.json | 266 - .../contracts/abi/v0.8/UpkeepReverter.json | 44 - .../contracts/abi/v0.8/UpkeepTranscoder.json | 49 - .../abi/v0.8/UpkeepTranscoder3_0.json | 49 - .../abi/v0.8/UpkeepTranscoder4_0.json | 49 - .../abi/v0.8/UpkeepTranscoder5_0.json | 49 - .../abi/v0.8/UpkeepTranscoderInterface.json | 31 - .../abi/v0.8/UpkeepTranscoderInterfaceV2.json | 31 - .../contracts/abi/v0.8/VRFConsumer.json | 86 - .../contracts/abi/v0.8/VRFConsumerBase.json | 20 - .../contracts/abi/v0.8/VRFConsumerBaseV2.json | 36 - .../abi/v0.8/VRFConsumerBaseV2Plus.json | 172 - .../v0.8/VRFConsumerBaseV2Upgradeable.json | 49 - .../contracts/abi/v0.8/VRFConsumerV2.json | 188 - .../contracts/abi/v0.8/VRFConsumerV2Plus.json | 336 - .../VRFConsumerV2PlusUpgradeableExample.json | 229 - .../v0.8/VRFConsumerV2UpgradeableExample.json | 229 - .../abi/v0.8/VRFCoordinatorMock.json | 103 - .../abi/v0.8/VRFCoordinatorTestV2.json | 1463 -- .../abi/v0.8/VRFCoordinatorTestV2_5.json | 1750 -- .../contracts/abi/v0.8/VRFCoordinatorV2.json | 100 - .../abi/v0.8/VRFCoordinatorV2Interface.json | 215 - .../abi/v0.8/VRFCoordinatorV2Mock.json | 765 - .../VRFCoordinatorV2PlusUpgradedVersion.json | 1778 -- .../v0.8/VRFCoordinatorV2Plus_V2Example.json | 329 - .../abi/v0.8/VRFCoordinatorV2TestHelper.json | 78 - .../abi/v0.8/VRFCoordinatorV2_5.json | 1763 -- .../abi/v0.8/VRFCoordinatorV2_5Mock.json | 1180 -- .../abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json | 1763 -- .../abi/v0.8/VRFCoordinatorV2_5_Optimism.json | 1848 -- .../abi/v0.8/VRFExternalSubOwnerExample.json | 130 - .../abi/v0.8/VRFLoadTestExternalSubOwner.json | 190 - .../v0.8/VRFLoadTestOwnerlessConsumer.json | 90 - .../contracts/abi/v0.8/VRFLogEmitter.json | 164 - .../abi/v0.8/VRFMaliciousConsumerV2.json | 155 - .../abi/v0.8/VRFMaliciousConsumerV2Plus.json | 278 - .../abi/v0.8/VRFMockETHLINKAggregator.json | 150 - .../contracts/abi/v0.8/VRFOwner.json | 455 - .../abi/v0.8/VRFOwnerlessConsumerExample.json | 90 - .../abi/v0.8/VRFRequestIDBaseTestHelper.json | 60 - .../abi/v0.8/VRFSingleConsumerExample.json | 208 - .../v0.8/VRFSubscriptionBalanceMonitor.json | 606 - .../VRFSubscriptionBalanceMonitorExposed.json | 624 - .../contracts/abi/v0.8/VRFTestHelper.json | 474 - .../abi/v0.8/VRFV2LoadTestWithMetrics.json | 370 - .../abi/v0.8/VRFV2OwnerTestConsumer.json | 406 - .../contracts/abi/v0.8/VRFV2PlusClient.json | 15 - .../abi/v0.8/VRFV2PlusConsumerExample.json | 392 - .../VRFV2PlusExternalSubOwnerExample.json | 258 - .../v0.8/VRFV2PlusLoadTestWithMetrics.json | 476 - .../abi/v0.8/VRFV2PlusMaliciousMigrator.json | 39 - .../abi/v0.8/VRFV2PlusRevertingExample.json | 324 - .../v0.8/VRFV2PlusSingleConsumerExample.json | 354 - .../contracts/abi/v0.8/VRFV2PlusWrapper.json | 954 -- .../v0.8/VRFV2PlusWrapperConsumerBase.json | 75 - .../v0.8/VRFV2PlusWrapperConsumerExample.json | 366 - .../VRFV2PlusWrapperLoadTestConsumer.json | 513 - .../abi/v0.8/VRFV2PlusWrapper_Arbitrum.json | 954 -- .../abi/v0.8/VRFV2PlusWrapper_Optimism.json | 1050 -- .../contracts/abi/v0.8/VRFV2ProxyAdmin.json | 151 - .../abi/v0.8/VRFV2RevertingExample.json | 188 - .../VRFV2TransparentUpgradeableProxy.json | 76 - .../contracts/abi/v0.8/VRFV2Wrapper.json | 495 - .../abi/v0.8/VRFV2WrapperConsumerBase.json | 20 - .../abi/v0.8/VRFV2WrapperConsumerExample.json | 246 - .../abi/v0.8/VRFV2WrapperInterface.json | 58 - .../v0.8/VRFV2WrapperLoadTestConsumer.json | 387 - .../VRFV2WrapperOutOfGasConsumerExample.json | 136 - .../VRFV2WrapperRevertingConsumerExample.json | 136 - .../VRFV2WrapperUnderFundingConsumer.json | 112 - .../contracts/abi/v0.8/VRFv2Consumer.json | 275 - .../contracts/abi/v0.8/ValidatorProxy.json | 323 - .../abi/v0.8/VerifiableLoadBase.json | 1524 -- .../v0.8/VerifiableLoadLogTriggerUpkeep.json | 1757 -- .../VerifiableLoadStreamsLookupUpkeep.json | 1666 -- .../abi/v0.8/VerifiableLoadUpkeep.json | 1577 -- .../contracts/abi/v0.8/Verifier.json | 714 - .../contracts/abi/v0.8/VerifierProxy.json | 435 - .../contracts/abi/v0.8/WERC20Mock.json | 375 - .../chainlink/contracts/abi/v0.8/WETH9.json | 309 - .../abi/v0.8/ZKSyncAutomationForwarder.json | 80 - .../abi/v0.8/ZKSyncAutomationRegistry2_3.json | 1580 -- .../v0.8/ZKSyncAutomationRegistryBase2_3.json | 1180 -- .../ZKSyncAutomationRegistryLogicA2_3.json | 1329 -- .../ZKSyncAutomationRegistryLogicB2_3.json | 1672 -- .../ZKSyncAutomationRegistryLogicC2_3.json | 2639 --- .../abi/v0.8/ZKSyncSequencerUptimeFeed.json | 578 - .../contracts/abi/v0.8/ZKSyncValidator.json | 402 - .../abi/v0.8/iOVM_CrossDomainMessenger.json | 77 - .../lib/chainlink/contracts/package.json | 84 - .../contracts/src/v0.8/ChainSpecificUtil.sol | 163 - .../src/v0.8/ChainSpecificUtil_v0_8_6.sol | 163 - .../contracts/src/v0.8/Chainlink.sol | 116 - .../contracts/src/v0.8/ChainlinkClient.sol | 318 - .../contracts/src/v0.8/Denominations.sol | 28 - .../chainlink/contracts/src/v0.8/Flags.sol | 124 - .../src/v0.8/PermissionedForwardProxy.sol | 65 - .../contracts/src/v0.8/ValidatorProxy.sol | 230 - .../src/v0.8/automation/AutomationBase.sol | 26 - .../v0.8/automation/AutomationCompatible.sol | 7 - .../automation/AutomationCompatibleUtils.sol | 17 - .../v0.8/automation/AutomationForwarder.sol | 92 - .../automation/AutomationForwarderLogic.sol | 24 - .../src/v0.8/automation/Chainable.sol | 61 - .../v0.8/automation/ExecutionPrevention.sol | 26 - .../v0.8/automation/HeartbeatRequester.sol | 72 - .../src/v0.8/automation/KeeperBase.sol | 7 - .../src/v0.8/automation/KeeperCompatible.sol | 11 - .../contracts/src/v0.8/automation/README.md | 43 - .../src/v0.8/automation/UpkeepFormat.sol | 13 - .../src/v0.8/automation/UpkeepTranscoder.sol | 44 - .../automation/ZKSyncAutomationForwarder.sol | 107 - .../v0.8/automation/chains/ArbitrumModule.sol | 51 - .../automation/chains/ChainModuleBase.sol | 37 - .../v0.8/automation/chains/OptimismModule.sol | 53 - .../automation/chains/OptimismModuleV2.sol | 78 - .../v0.8/automation/chains/ScrollModule.sol | 78 - .../v0.8/automation/dev/MercuryRegistry.sol | 320 - .../dev/MercuryRegistryBatchUpkeep.sol | 88 - .../AutomationCompatibleInterface.sol | 42 - .../interfaces/IAutomationForwarder.sol | 15 - .../IAutomationRegistryConsumer.sol | 24 - .../interfaces/IAutomationV21PlusCommon.sol | 272 - .../automation/interfaces/IChainModule.sol | 42 - .../automation/interfaces/ILogAutomation.sol | 64 - .../interfaces/KeeperCompatibleInterface.sol | 7 - .../MigratableKeeperRegistryInterface.sol | 26 - .../MigratableKeeperRegistryInterfaceV2.sol | 24 - .../StreamsLookupCompatibleInterface.sol | 34 - .../interfaces/UpkeepTranscoderInterface.sol | 13 - .../UpkeepTranscoderInterfaceV2.sol | 11 - .../v1_2/AutomationRegistryInterface1_2.sol | 123 - .../v1_2/KeeperRegistryInterface1_2.sol | 13 - .../v1_3/AutomationRegistryInterface1_3.sol | 156 - .../v2_0/AutomationRegistryInterface2_0.sol | 185 - .../interfaces/v2_1/IKeeperRegistryMaster.sol | 315 - .../v2_2/IAutomationRegistryMaster.sol | 341 - .../v2_3/IAutomationRegistryMaster2_3.sol | 435 - .../interfaces/v2_3/IWrappedNative.sol | 10 - .../interfaces/zksync/IGasBoundCaller.sol | 8 - .../interfaces/zksync/ISystemContext.sol | 10 - .../IZKSyncAutomationRegistryMaster2_3.sol | 441 - .../automation/libraries/external/Cron.sol | 78 - .../automation/libraries/internal/Cron.sol | 544 - .../automation/mocks/ERC20Mock6Decimals.sol | 17 - .../mocks/KeeperRegistrar1_2Mock.sol | 122 - ...istryCheckUpkeepGasUsageWrapper1_2Mock.sol | 32 - .../v0.8/automation/mocks/MockAggregator.sol | 22 - .../automation/mocks/MockAggregatorProxy.sol | 20 - .../mocks/MockKeeperRegistry2_1.sol | 31 - .../src/v0.8/automation/mocks/MockUpkeep.sol | 53 - .../automation/test/AutomationForwarder.t.sol | 74 - .../test/AutomationRegistry2_2.t.sol | 198 - .../src/v0.8/automation/test/BaseTest.t.sol | 14 - .../automation/test/HeartbeatRequester.t.sol | 112 - .../automation/test/MercuryRegistry.t.sol | 336 - .../src/v0.8/automation/test/WETH9.sol | 93 - .../test/v2_3/AutomationRegistrar2_3.t.sol | 409 - .../test/v2_3/AutomationRegistry2_3.t.sol | 2753 --- .../v0.8/automation/test/v2_3/BaseTest.t.sol | 503 - .../test/v2_3_zksync/BaseTest.t.sol | 500 - .../ZKSyncAutomationRegistry2_3.t.sol | 2772 --- .../automation/testhelpers/CronTestHelper.sol | 100 - .../testhelpers/CronUpkeepTestHelper.sol | 41 - .../automation/testhelpers/DummyProtocol.sol | 87 - .../automation/testhelpers/KeeperConsumer.sol | 26 - .../testhelpers/KeeperConsumerPerformance.sol | 88 - .../testhelpers/LogTriggeredStreamsLookup.sol | 155 - .../testhelpers/LogUpkeepCounter.sol | 103 - .../testhelpers/MockETHUSDAggregator.sol | 53 - .../testhelpers/PerformDataChecker.sol | 29 - .../testhelpers/SimpleLogUpkeepCounter.sol | 143 - .../testhelpers/UpkeepAutoFunder.sol | 60 - .../automation/testhelpers/UpkeepCounter.sol | 58 - .../testhelpers/UpkeepCounterNew.sol | 126 - .../automation/testhelpers/UpkeepMock.sol | 81 - .../UpkeepPerformCounterRestrictive.sol | 85 - .../automation/testhelpers/UpkeepReverter.sol | 17 - .../v0.8/automation/upkeeps/CronUpkeep.sol | 263 - .../automation/upkeeps/CronUpkeepDelegate.sol | 71 - .../automation/upkeeps/CronUpkeepFactory.sol | 80 - .../upkeeps/ERC20BalanceMonitor.sol | 279 - .../automation/upkeeps/EthBalanceMonitor.sol | 254 - .../upkeeps/LinkAvailableBalanceMonitor.sol | 480 - .../upkeeps/UpkeepBalanceMonitor.sol | 258 - .../automation/v1_2/KeeperRegistrar1_2.sol | 425 - .../automation/v1_2/KeeperRegistry1_2.sol | 909 - ...rRegistryCheckUpkeepGasUsageWrapper1_2.sol | 48 - .../automation/v1_3/KeeperRegistry1_3.sol | 548 - .../automation/v1_3/KeeperRegistryBase1_3.sol | 304 - .../v1_3/KeeperRegistryLogic1_3.sol | 404 - .../automation/v2_0/KeeperRegistrar2_0.sol | 489 - .../automation/v2_0/KeeperRegistry2_0.sol | 1012 -- .../automation/v2_0/KeeperRegistryBase2_0.sol | 479 - .../v2_0/KeeperRegistryLogic2_0.sol | 474 - .../automation/v2_0/UpkeepTranscoder3_0.sol | 104 - .../v2_1/AutomationRegistrar2_1.sol | 532 - .../automation/v2_1/AutomationUtils2_1.sol | 41 - .../automation/v2_1/KeeperRegistry2_1.sol | 397 - .../automation/v2_1/KeeperRegistryBase2_1.sol | 861 - .../v2_1/KeeperRegistryLogicA2_1.sol | 438 - .../v2_1/KeeperRegistryLogicB2_1.sol | 517 - .../src/v0.8/automation/v2_1/LICENSE | 56 - .../src/v0.8/automation/v2_1/README.md | 40 - .../automation/v2_1/UpkeepTranscoder4_0.sol | 176 - .../automation/v2_2/AutomationRegistry2_2.sol | 416 - .../v2_2/AutomationRegistryBase2_2.sol | 861 - .../v2_2/AutomationRegistryLogicA2_2.sol | 433 - .../v2_2/AutomationRegistryLogicB2_2.sol | 540 - .../automation/v2_2/AutomationUtils2_2.sol | 41 - .../src/v0.8/automation/v2_2/LICENSE | 57 - .../src/v0.8/automation/v2_2/README.md | 40 - .../v2_3/AutomationRegistrar2_3.sol | 442 - .../automation/v2_3/AutomationRegistry2_3.sol | 391 - .../v2_3/AutomationRegistryBase2_3.sol | 1216 -- .../v2_3/AutomationRegistryLogicA2_3.sol | 283 - .../v2_3/AutomationRegistryLogicB2_3.sol | 449 - .../v2_3/AutomationRegistryLogicC2_3.sol | 638 - .../automation/v2_3/AutomationUtils2_3.sol | 17 - .../src/v0.8/automation/v2_3/LICENSE | 57 - .../automation/v2_3/UpkeepTranscoder5_0.sol | 46 - .../ZKSyncAutomationRegistry2_3.sol | 386 - .../ZKSyncAutomationRegistryBase2_3.sol | 1197 -- .../ZKSyncAutomationRegistryLogicA2_3.sol | 283 - .../ZKSyncAutomationRegistryLogicB2_3.sol | 449 - .../ZKSyncAutomationRegistryLogicC2_3.sol | 626 - .../contracts/src/v0.8/ccip/FeeQuoter.sol | 1020 -- .../contracts/src/v0.8/ccip/LICENSE-MIT.md | 21 - .../contracts/src/v0.8/ccip/LICENSE.md | 56 - .../v0.8/ccip/MultiAggregateRateLimiter.sol | 281 - .../contracts/src/v0.8/ccip/NonceManager.sol | 158 - .../contracts/src/v0.8/ccip/Router.sol | 298 - .../ccip/applications/CCIPClientExample.sol | 175 - .../v0.8/ccip/applications/CCIPReceiver.sol | 67 - .../ccip/applications/DefensiveExample.sol | 114 - .../ccip/applications/EtherSenderReceiver.sol | 184 - .../v0.8/ccip/applications/PingPongDemo.sol | 130 - .../src/v0.8/ccip/capability/CCIPHome.sol | 624 - .../interfaces/IAny2EVMMessageReceiver.sol | 17 - .../v0.8/ccip/interfaces/IAny2EVMOffRamp.sol | 11 - .../ccip/interfaces/ICapabilitiesRegistry.sol | 35 - .../src/v0.8/ccip/interfaces/ICommitStore.sol | 17 - .../v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol | 17 - .../ccip/interfaces/IEVM2AnyOnRampClient.sol | 45 - .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 46 - .../v0.8/ccip/interfaces/IGetCCIPAdmin.sol | 8 - .../ccip/interfaces/IMessageInterceptor.sol | 24 - .../v0.8/ccip/interfaces/INonceManager.sol | 23 - .../src/v0.8/ccip/interfaces/IOwner.sol | 8 - .../src/v0.8/ccip/interfaces/IPool.sol | 41 - .../v0.8/ccip/interfaces/IPoolPriorTo1_5.sol | 46 - .../v0.8/ccip/interfaces/IPriceRegistry.sol | 70 - .../src/v0.8/ccip/interfaces/IRMN.sol | 25 - .../src/v0.8/ccip/interfaces/IRMNRemote.sol | 41 - .../src/v0.8/ccip/interfaces/IRouter.sol | 37 - .../v0.8/ccip/interfaces/IRouterClient.sol | 39 - .../ccip/interfaces/ITokenAdminRegistry.sol | 14 - .../v0.8/ccip/interfaces/IWrappedNative.sol | 12 - .../interfaces/automation/ILinkAvailable.sol | 8 - .../encodingutils/ICCIPEncodingUtils.sol | 25 - .../src/v0.8/ccip/libraries/Client.sol | 59 - .../src/v0.8/ccip/libraries/Internal.sol | 275 - .../v0.8/ccip/libraries/MerkleMultiProof.sol | 113 - .../src/v0.8/ccip/libraries/Pool.sol | 57 - .../src/v0.8/ccip/libraries/RateLimiter.sol | 159 - .../ccip/libraries/USDPriceWith18Decimals.sol | 45 - .../src/v0.8/ccip/ocr/MultiOCR3Base.sol | 335 - .../src/v0.8/ccip/offRamp/OffRamp.sol | 1044 -- .../contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 526 - .../v0.8/ccip/pools/BurnFromMintTokenPool.sol | 40 - .../src/v0.8/ccip/pools/BurnMintTokenPool.sol | 32 - .../ccip/pools/BurnMintTokenPoolAbstract.sol | 45 - .../ccip/pools/BurnWithFromMintTokenPool.sol | 42 - .../v0.8/ccip/pools/LockReleaseTokenPool.sol | 139 - .../src/v0.8/ccip/pools/TokenPool.sol | 464 - .../USDC/HybridLockReleaseUSDCTokenPool.sol | 261 - .../ccip/pools/USDC/IMessageTransmitter.sol | 46 - .../v0.8/ccip/pools/USDC/ITokenMessenger.sol | 65 - .../ccip/pools/USDC/USDCBridgeMigrator.sol | 162 - .../v0.8/ccip/pools/USDC/USDCTokenPool.sol | 232 - .../contracts/src/v0.8/ccip/rmn/ARMProxy.sol | 77 - .../contracts/src/v0.8/ccip/rmn/RMNHome.sol | 395 - .../contracts/src/v0.8/ccip/rmn/RMNRemote.sol | 261 - .../src/v0.8/ccip/test/BaseTest.t.sol | 151 - .../src/v0.8/ccip/test/NonceManager.t.sol | 520 - .../contracts/src/v0.8/ccip/test/README.md | 89 - .../src/v0.8/ccip/test/TokenSetup.t.sol | 178 - .../contracts/src/v0.8/ccip/test/WETH9.sol | 84 - .../test/applications/DefensiveExample.t.sol | 97 - .../applications/EtherSenderReceiver.t.sol | 724 - .../test/applications/ImmutableExample.t.sol | 61 - .../ccip/test/applications/PingPongDemo.t.sol | 122 - .../ccip/test/attacks/onRamp/FacadeClient.sol | 56 - .../onRamp/OnRampTokenPoolReentrancy.t.sol | 82 - .../onRamp/ReentrantMaliciousTokenPool.sol | 46 - .../v0.8/ccip/test/capability/CCIPHome.t.sol | 969 -- .../src/v0.8/ccip/test/e2e/End2End.t.sol | 305 - .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 2251 --- .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 442 - .../test/helpers/BurnMintERC677Helper.sol | 20 - .../test/helpers/BurnMintMultiTokenPool.sol | 50 - .../v0.8/ccip/test/helpers/CCIPHomeHelper.sol | 22 - .../ccip/test/helpers/ERC20RebasingHelper.sol | 31 - .../test/helpers/EVM2EVMOffRampHelper.sol | 25 - .../helpers/EtherSenderReceiverHelper.sol | 29 - .../ccip/test/helpers/FeeQuoterHelper.sol | 80 - .../ccip/test/helpers/IgnoreContractSize.sol | 10 - .../MaybeRevertingBurnMintTokenPool.sol | 77 - .../v0.8/ccip/test/helpers/MerkleHelper.sol | 57 - .../v0.8/ccip/test/helpers/MessageHasher.sol | 91 - .../test/helpers/MessageInterceptorHelper.sol | 32 - .../MultiAggregateRateLimiterHelper.sol | 18 - .../ccip/test/helpers/MultiOCR3Helper.sol | 49 - .../v0.8/ccip/test/helpers/MultiTokenPool.sol | 438 - .../v0.8/ccip/test/helpers/OffRampHelper.sol | 114 - .../v0.8/ccip/test/helpers/OnRampHelper.sol | 13 - .../ccip/test/helpers/RateLimiterHelper.sol | 40 - .../v0.8/ccip/test/helpers/ReportCodec.sol | 22 - .../ccip/test/helpers/TokenPoolHelper.sol | 40 - .../ccip/test/helpers/USDCReaderTester.sol | 62 - .../ccip/test/helpers/USDCTokenPoolHelper.sol | 21 - .../helpers/receivers/ConformingReceiver.sol | 17 - .../receivers/MaybeRevertMessageReceiver.sol | 65 - .../MaybeRevertMessageReceiverNo165.sol | 36 - .../helpers/receivers/ReentrancyAbuser.sol | 64 - .../receivers/ReentrancyAbuserMultiRamp.sol | 49 - .../test/libraries/MerkleMultiProof.t.sol | 196 - .../ccip/test/libraries/RateLimiter.t.sol | 297 - .../test/mocks/MockE2EUSDCTokenMessenger.sol | 128 - .../test/mocks/MockE2EUSDCTransmitter.sol | 180 - .../src/v0.8/ccip/test/mocks/MockRMN.sol | 61 - .../src/v0.8/ccip/test/mocks/MockRouter.sol | 169 - .../test/mocks/MockUSDCTokenMessenger.sol | 52 - .../IMessageTransmitterWithRelay.sol | 55 - .../ccip/test/mocks/test/MockRouterTest.t.sol | 68 - .../v0.8/ccip/test/ocr/MultiOCR3Base.t.sol | 1006 -- .../ccip/test/ocr/MultiOCR3BaseSetup.t.sol | 115 - .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 3797 ----- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 497 - .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 1080 -- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 200 - .../test/pools/BurnFromMintTokenPool.t.sol | 103 - .../v0.8/ccip/test/pools/BurnMintSetup.t.sol | 45 - .../ccip/test/pools/BurnMintTokenPool.t.sol | 168 - .../pools/BurnWithFromMintTokenPool.t.sol | 104 - .../HybridLockReleaseUSDCTokenPool.t.sol | 886 - .../test/pools/LockReleaseTokenPool.t.sol | 438 - .../src/v0.8/ccip/test/pools/TokenPool.t.sol | 785 - .../v0.8/ccip/test/pools/USDCTokenPool.t.sol | 702 - .../MultiAggregateRateLimiter.t.sol | 1196 -- .../src/v0.8/ccip/test/rmn/ARMProxy.t.sol | 79 - .../src/v0.8/ccip/test/rmn/RMNHome.t.sol | 377 - .../src/v0.8/ccip/test/rmn/RMNRemote.t.sol | 280 - .../v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol | 148 - .../src/v0.8/ccip/test/router/Router.t.sol | 819 - .../v0.8/ccip/test/router/RouterSetup.t.sol | 50 - .../RegistryModuleOwnerCustom.t.sol | 104 - .../TokenAdminRegistry.t.sol | 395 - .../RegistryModuleOwnerCustom.sol | 60 - .../tokenAdminRegistry/TokenAdminRegistry.sol | 237 - .../src/v0.8/ccip/v1.5-CCIP-License-grants.md | 8 - .../functions/dev/v1_X/FunctionsBilling.sol | 448 - .../functions/dev/v1_X/FunctionsClient.sol | 63 - .../dev/v1_X/FunctionsCoordinator.sol | 227 - .../functions/dev/v1_X/FunctionsRouter.sol | 587 - .../dev/v1_X/FunctionsSubscriptions.sol | 552 - .../src/v0.8/functions/dev/v1_X/Routable.sol | 45 - .../accessControl/TermsOfServiceAllowList.sol | 220 - .../interfaces/ITermsOfServiceAllowList.sol | 84 - .../v1_X/example/FunctionsClientExample.sol | 69 - .../dev/v1_X/interfaces/IFunctionsBilling.sol | 74 - .../dev/v1_X/interfaces/IFunctionsClient.sol | 13 - .../v1_X/interfaces/IFunctionsCoordinator.sol | 37 - .../dev/v1_X/interfaces/IFunctionsRouter.sol | 109 - .../interfaces/IFunctionsSubscriptions.sol | 140 - .../interfaces/IOwnableFunctionsRouter.sol | 8 - .../dev/v1_X/libraries/ChainSpecificUtil.sol | 75 - .../dev/v1_X/libraries/FunctionsRequest.sol | 155 - .../dev/v1_X/libraries/FunctionsResponse.sol | 44 - .../dev/v1_X/mocks/FunctionsV1EventsMock.sol | 183 - .../functions/dev/v1_X/ocr/OCR2Abstract.sol | 103 - .../v0.8/functions/dev/v1_X/ocr/OCR2Base.sol | 353 - .../src/v0.8/functions/interfaces/.gitkeep | 0 .../v0.8/functions/tests/v1_X/BaseTest.t.sol | 25 - .../tests/v1_X/ChainSpecificUtil.t.sol | 271 - .../tests/v1_X/FunctionsBilling.t.sol | 520 - .../tests/v1_X/FunctionsClient.t.sol | 78 - .../tests/v1_X/FunctionsCoordinator.t.sol | 258 - .../tests/v1_X/FunctionsRequest.t.sol | 48 - .../tests/v1_X/FunctionsRouter.t.sol | 1603 -- .../tests/v1_X/FunctionsSubscriptions.t.sol | 1291 -- .../FunctionsTermsOfServiceAllowList.t.sol | 557 - .../src/v0.8/functions/tests/v1_X/Gas.t.sol | 377 - .../src/v0.8/functions/tests/v1_X/OCR2.t.sol | 38 - .../src/v0.8/functions/tests/v1_X/README.md | 25 - .../src/v0.8/functions/tests/v1_X/Setup.t.sol | 721 - .../testhelpers/FunctionsClientHarness.sol | 24 - .../testhelpers/FunctionsClientTestHelper.sol | 128 - .../FunctionsClientUpgradeHelper.sol | 157 - .../FunctionsClientWithEmptyCallback.sol | 31 - .../FunctionsCoordinatorHarness.sol | 127 - .../FunctionsCoordinatorTestHelper.sol | 58 - .../testhelpers/FunctionsLoadTestClient.sol | 152 - .../testhelpers/FunctionsRouterHarness.sol | 30 - .../FunctionsSubscriptionsHarness.sol | 54 - .../v1_X/testhelpers/FunctionsTestHelper.sol | 52 - .../functions/v1_0_0/FunctionsBilling.sol | 372 - .../v0.8/functions/v1_0_0/FunctionsClient.sol | 62 - .../functions/v1_0_0/FunctionsCoordinator.sol | 176 - .../v0.8/functions/v1_0_0/FunctionsRouter.sol | 585 - .../v1_0_0/FunctionsSubscriptions.sol | 552 - .../src/v0.8/functions/v1_0_0/Routable.sol | 45 - .../accessControl/TermsOfServiceAllowList.sol | 142 - .../interfaces/ITermsOfServiceAllowList.sol | 40 - .../v1_0_0/example/FunctionsClientExample.sol | 69 - .../v1_0_0/interfaces/IFunctionsBilling.sol | 44 - .../v1_0_0/interfaces/IFunctionsClient.sol | 13 - .../interfaces/IFunctionsCoordinator.sol | 37 - .../v1_0_0/interfaces/IFunctionsRouter.sol | 109 - .../interfaces/IFunctionsSubscriptions.sol | 140 - .../interfaces/IOwnableFunctionsRouter.sol | 8 - .../v1_0_0/libraries/FunctionsRequest.sol | 155 - .../v1_0_0/libraries/FunctionsResponse.sol | 44 - .../v1_0_0/mocks/FunctionsV1EventsMock.sol | 181 - .../functions/v1_0_0/ocr/OCR2Abstract.sol | 134 - .../v0.8/functions/v1_0_0/ocr/OCR2Base.sol | 357 - .../functions/v1_1_0/FunctionsBilling.sol | 391 - .../functions/v1_1_0/FunctionsCoordinator.sol | 183 - .../v1_1_0/libraries/ChainSpecificUtil.sol | 78 - .../functions/v1_1_0/ocr/OCR2Abstract.sol | 103 - .../v0.8/functions/v1_1_0/ocr/OCR2Base.sol | 348 - .../functions/v1_3_0/FunctionsBilling.sol | 440 - .../v0.8/functions/v1_3_0/FunctionsClient.sol | 62 - .../functions/v1_3_0/FunctionsCoordinator.sol | 228 - .../accessControl/TermsOfServiceAllowList.sol | 205 - .../interfaces/ITermsOfServiceAllowList.sol | 80 - .../v1_3_0/interfaces/IFunctionsBilling.sol | 73 - .../functions/v1_3_0/ocr/OCR2Abstract.sol | 103 - .../v0.8/functions/v1_3_0/ocr/OCR2Base.sol | 353 - .../interfaces/ChainlinkRequestInterface.sol | 23 - .../src/v0.8/interfaces/ENSInterface.sol | 31 - .../v0.8/interfaces/FeedRegistryInterface.sol | 124 - .../src/v0.8/interfaces/FlagsInterface.sol | 17 - .../src/v0.8/interfaces/OperatorInterface.sol | 31 - .../src/v0.8/interfaces/OracleInterface.sol | 18 - .../src/v0.8/interfaces/PoRAddressList.sol | 29 - .../src/v0.8/interfaces/PointerInterface.sol | 7 - .../interfaces/TypeAndVersionInterface.sol | 6 - .../v0.8/keystone/CapabilitiesRegistry.sol | 1055 -- .../v0.8/keystone/KeystoneFeedsConsumer.sol | 107 - .../KeystoneFeedsPermissionHandler.sol | 85 - .../src/v0.8/keystone/KeystoneForwarder.sol | 335 - .../src/v0.8/keystone/OCR3Capability.sol | 168 - .../interfaces/ICapabilityConfiguration.sol | 34 - .../v0.8/keystone/interfaces/IReceiver.sol | 12 - .../src/v0.8/keystone/interfaces/IRouter.sol | 66 - .../lib/KeystoneFeedDefaultMetadataLib.sol | 35 - .../src/v0.8/keystone/ocr/OCR2Abstract.sol | 103 - .../src/v0.8/keystone/test/BaseTest.t.sol | 62 - ...bilitiesRegistry_AddCapabilitiesTest.t.sol | 114 - .../CapabilitiesRegistry_AddDONTest.t.sol | 326 - ...ilitiesRegistry_AddNodeOperatorsTest.t.sol | 51 - .../CapabilitiesRegistry_AddNodesTest.t.sol | 264 - ...esRegistry_DeprecateCapabilitiesTest.t.sol | 80 - ...bilitiesRegistry_GetCapabilitiesTest.t.sol | 48 - .../CapabilitiesRegistry_GetDONsTest.t.sol | 97 - ...esRegistry_GetHashedCapabilityIdTest.t.sol | 28 - ...ilitiesRegistry_GetNodeOperatorsTest.t.sol | 42 - .../CapabilitiesRegistry_GetNodesTest.t.sol | 83 - .../CapabilitiesRegistry_RemoveDONsTest.t.sol | 97 - ...tiesRegistry_RemoveNodeOperatorsTest.t.sol | 46 - ...CapabilitiesRegistry_RemoveNodesTest.t.sol | 243 - ...abilitiesRegistry_TypeAndVersionTest.t.sol | 10 - .../CapabilitiesRegistry_UpdateDONTest.t.sol | 241 - ...tiesRegistry_UpdateNodeOperatorsTest.t.sol | 103 - ...CapabilitiesRegistry_UpdateNodesTest.t.sol | 386 - .../src/v0.8/keystone/test/Constants.t.sol | 38 - .../test/KeystoneForwarderBaseTest.t.sol | 73 - .../test/KeystoneForwarder_ReportTest.t.sol | 326 - .../KeystoneForwarder_SetConfigTest.t.sol | 61 - ...KeystoneForwarder_TypeAndVersionTest.t.sol | 10 - .../test/KeystoneRouter_AccessTest.t.sol | 67 - .../mocks/CapabilityConfigurationContract.sol | 23 - .../mocks/MaliciousConfigurationContract.sol | 49 - .../test/mocks/MaliciousReportReceiver.sol | 23 - .../test/mocks/MaliciousRevertingReceiver.sol | 22 - .../src/v0.8/keystone/test/mocks/Receiver.sol | 24 - .../contracts/src/v0.8/l2ep/README.md | 148 - .../l2ep/dev/CrossDomainDelegateForwarder.sol | 13 - .../v0.8/l2ep/dev/CrossDomainForwarder.sol | 13 - .../src/v0.8/l2ep/dev/CrossDomainOwnable.sol | 81 - .../contracts/src/v0.8/l2ep/dev/Flags.sol | 177 - .../arbitrum/ArbitrumCrossDomainForwarder.sol | 72 - .../arbitrum/ArbitrumCrossDomainGovernor.sol | 63 - .../arbitrum/ArbitrumSequencerUptimeFeed.sol | 313 - .../l2ep/dev/arbitrum/ArbitrumValidator.sol | 355 - .../dev/interfaces/IArbitrumDelayedInbox.sol | 15 - .../dev/interfaces/ICrossDomainOwnable.sol | 15 - .../dev/interfaces/IDelegateForwarder.sol | 10 - .../src/v0.8/l2ep/dev/interfaces/IFlags.sol | 20 - .../v0.8/l2ep/dev/interfaces/IForwarder.sol | 10 - .../dev/interfaces/ISequencerUptimeFeed.sol | 6 - .../optimism/OptimismCrossDomainForwarder.sol | 92 - .../optimism/OptimismCrossDomainGovernor.sol | 74 - .../optimism/OptimismSequencerUptimeFeed.sol | 39 - .../l2ep/dev/optimism/OptimismValidator.sol | 47 - .../dev/scroll/ScrollCrossDomainForwarder.sol | 64 - .../dev/scroll/ScrollCrossDomainGovernor.sol | 91 - .../dev/scroll/ScrollSequencerUptimeFeed.sol | 40 - .../v0.8/l2ep/dev/scroll/ScrollValidator.sol | 55 - .../dev/shared/BaseSequencerUptimeFeed.sol | 231 - .../v0.8/l2ep/dev/shared/BaseValidator.sol | 59 - .../dev/zksync/ZKSyncSequencerUptimeFeed.sol | 25 - .../v0.8/l2ep/dev/zksync/ZKSyncValidator.sol | 104 - .../l2ep/test/mocks/MockAggregatorV2V3.sol | 56 - .../optimism/MockOVMCrossDomainMessenger.sol | 31 - .../scroll/MockScrollCrossDomainMessenger.sol | 36 - .../MockScrollL1CrossDomainMessenger.sol | 60 - .../mocks/scroll/MockScrollL1MessageQueue.sol | 77 - .../MockScrollL2CrossDomainMessenger.sol | 50 - .../test/mocks/zksync/MockZKSyncL1Bridge.sol | 147 - .../src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol | 67 - .../ArbitrumCrossDomainForwarder.t.sol | 159 - .../ArbitrumCrossDomainGovernor.t.sol | 258 - .../ArbitrumSequencerUptimeFeed.t.sol | 248 - .../v1_0_0/arbitrum/ArbitrumValidator.t.sol | 87 - .../OptimismCrossDomainForwarder.t.sol | 187 - .../OptimismCrossDomainGovernor.t.sol | 294 - .../OptimismSequencerUptimeFeed.t.sol | 321 - .../v1_0_0/optimism/OptimismValidator.t.sol | 110 - .../scroll/ScrollCrossDomainForwarder.t.sol | 191 - .../scroll/ScrollCrossDomainGovernor.t.sol | 305 - .../scroll/ScrollSequencerUptimeFeed.t.sol | 325 - .../test/v1_0_0/scroll/ScrollValidator.t.sol | 123 - .../zksync/ZKSyncSequencerUptimeFeed.t.sol | 291 - .../test/v1_0_0/zksync/ZKSyncValidator.t.sol | 149 - .../liquiditymanager/LiquidityManager.sol | 575 - .../ArbitrumL1BridgeAdapter.sol | 175 - .../ArbitrumL2BridgeAdapter.sol | 78 - .../OptimismL1BridgeAdapter.sol | 196 - .../OptimismL2BridgeAdapter.sol | 119 - .../OptimismL1BridgeAdapterEncoder.sol | 21 - .../liquiditymanager/interfaces/IBridge.sol | 49 - .../interfaces/ILiquidityContainer.sol | 16 - .../interfaces/ILiquidityManager.sol | 62 - .../IAbstractArbitrumTokenGateway.sol | 7 - .../interfaces/arbitrum/IArbRollupCore.sol | 7 - .../interfaces/arbitrum/IArbSys.sol | 7 - .../arbitrum/IArbitrumGatewayRouter.sol | 7 - .../interfaces/arbitrum/IArbitrumInbox.sol | 7 - .../arbitrum/IArbitrumL1GatewayRouter.sol | 7 - .../arbitrum/IArbitrumTokenGateway.sol | 7 - .../arbitrum/IL2ArbitrumGateway.sol | 7 - .../arbitrum/IL2ArbitrumMessenger.sol | 7 - .../interfaces/arbitrum/INodeInterface.sol | 7 - .../interfaces/optimism/DisputeTypes.sol | 23 - .../IOptimismCrossDomainMessenger.sol | 31 - .../optimism/IOptimismDisputeGameFactory.sol | 31 - .../optimism/IOptimismL1StandardBridge.sol | 18 - .../optimism/IOptimismL2OutputOracle.sol | 19 - .../optimism/IOptimismL2ToL1MessagePasser.sol | 23 - .../interfaces/optimism/IOptimismPortal.sol | 26 - .../interfaces/optimism/IOptimismPortal2.sol | 12 - .../optimism/IOptimismStandardBridge.sol | 40 - .../interfaces/optimism/Types.sol | 72 - .../liquiditymanager/ocr/OCR3Abstract.sol | 108 - .../v0.8/liquiditymanager/ocr/OCR3Base.sol | 280 - .../test/LiquidityManager.t.sol | 945 -- .../test/LiquidityManagerBaseTest.t.sol | 43 - .../ArbitrumL1BridgeAdapter.t.sol | 98 - .../ArbitrumL2BridgeAdapter.t.sol | 51 - .../OptimismL1BridgeAdapter.t.sol | 129 - .../test/helpers/LiquidityManagerHelper.sol | 22 - .../test/helpers/OCR3Helper.sol | 41 - .../test/helpers/ReportEncoder.sol | 10 - .../test/mocks/MockBridgeAdapter.sol | 191 - .../liquiditymanager/test/mocks/NoOpOCR3.sol | 18 - .../liquiditymanager/test/ocr/OCR3Base.t.sol | 337 - .../liquiditymanager/test/ocr/OCR3Setup.t.sol | 34 - .../llo-feeds/interfaces/IConfigurator.sol | 28 - .../src/v0.8/llo-feeds/libraries/ByteUtil.sol | 86 - .../src/v0.8/llo-feeds/libraries/Common.sol | 89 - .../libraries/test/ByteUtilTest.t.sol | 177 - .../src/v0.8/llo-feeds/v0.3.0/FeeManager.sol | 507 - .../v0.8/llo-feeds/v0.3.0/RewardManager.sol | 321 - .../src/v0.8/llo-feeds/v0.3.0/Verifier.sol | 559 - .../v0.8/llo-feeds/v0.3.0/VerifierProxy.sol | 229 - .../v0.3.0/interfaces/IFeeManager.sol | 78 - .../v0.3.0/interfaces/IRewardManager.sol | 69 - .../llo-feeds/v0.3.0/interfaces/IVerifier.sol | 123 - .../v0.3.0/interfaces/IVerifierFeeManager.sol | 37 - .../v0.3.0/interfaces/IVerifierProxy.sol | 80 - .../test/fee-manager/BaseFeeManager.t.sol | 379 - .../test/fee-manager/FeeManager.general.t.sol | 242 - .../FeeManager.getFeeAndReward.t.sol | 606 - .../fee-manager/FeeManager.processFee.t.sol | 492 - .../FeeManager.processFeeBulk.t.sol | 193 - .../v0.3.0/test/gas/Gas_VerifierTest.t.sol | 230 - .../v0.3.0/test/mocks/ErroredVerifier.sol | 95 - .../v0.3.0/test/mocks/ExposedVerifier.sol | 69 - .../v0.3.0/test/mocks/FeeManagerProxy.sol | 20 - .../reward-manager/BaseRewardManager.t.sol | 262 - .../reward-manager/RewardManager.claim.t.sol | 790 - .../RewardManager.general.t.sol | 69 - .../RewardManager.payRecipients.t.sol | 194 - .../RewardManager.setRecipients.t.sol | 148 - ...RewardManager.updateRewardRecipients.t.sol | 450 - .../test/verifier/BaseVerifierTest.t.sol | 502 - .../verifier/VerifierActivateConfigTest.t.sol | 63 - .../verifier/VerifierDeactivateFeedTest.t.sol | 108 - .../VerifierProxyConstructorTest.t.sol | 24 - .../VerifierProxyInitializeVerifierTest.t.sol | 30 - ...VerifierProxySetAccessControllerTest.t.sol | 34 - .../VerifierProxySetVerifierTest.t.sol | 41 - .../test/verifier/VerifierProxyTest.t.sol | 23 - .../VerifierProxyUnsetVerifierTest.t.sol | 42 - .../VerifierSetConfigFromSourceTest.t.sol | 134 - .../test/verifier/VerifierSetConfigTest.t.sol | 243 - .../v0.3.0/test/verifier/VerifierTest.t.sol | 42 - .../verifier/VerifierTestBillingReport.t.sol | 218 - .../verifier/VerifierUnsetConfigTest.t.sol | 56 - .../test/verifier/VerifierVerifyTest.t.sol | 314 - .../v0.4.0/DestinationFeeManager.sol | 573 - .../v0.4.0/DestinationRewardManager.sol | 328 - .../llo-feeds/v0.4.0/DestinationVerifier.sol | 443 - .../v0.4.0/DestinationVerifierProxy.sol | 70 - .../interfaces/IDestinationFeeManager.sol | 103 - .../interfaces/IDestinationRewardManager.sol | 75 - .../interfaces/IDestinationVerifier.sol | 57 - .../IDestinationVerifierFeeManager.sol | 45 - .../interfaces/IDestinationVerifierProxy.sol | 52 - .../IDestinationVerifierProxyVerifier.sol | 48 - .../BaseDestinationFeeManager.t.sol | 406 - .../DestinationFeeManager.general.t.sol | 299 - ...estinationFeeManager.getFeeAndReward.t.sol | 720 - .../DestinationFeeManager.processFee.t.sol | 492 - ...DestinationFeeManager.processFeeBulk.t.sol | 310 - .../test/mocks/DestinationFeeManagerProxy.sol | 24 - .../BaseDestinationRewardManager.t.sol | 264 - .../DestinationRewardManager.claim.t.sol | 790 - .../DestinationRewardManager.general.t.sol | 99 - ...stinationRewardManager.payRecipients.t.sol | 194 - ...stinationRewardManager.setRecipients.t.sol | 148 - ...RewardManager.updateRewardRecipients.t.sol | 450 - .../BaseDestinationVerifierTest.t.sol | 347 - .../DestinationVerifierInterfacesTest.t.sol | 128 - .../DestinationVerifierProxyTest.t.sol | 38 - ...nationVerifierRemoveLatestConfigTest.t.sol | 126 - ...ationVerifierSetAccessControllerTest.t.sol | 33 - .../DestinationVerifierSetConfigTest.t.sol | 176 - ...DestinationVerifierSetFeeManagerTest.t.sol | 28 - .../verifier/DestinationVerifierTest.t.sol | 34 - ...DestinationVerifierTestBillingReport.t.sol | 189 - .../DestinationVerifierTestRewards.t.sol | 227 - ...erTestRewardsMultiVefifierFeeManager.t.sol | 141 - .../DestinationVerifierVerifyBulkTest.t.sol | 140 - .../DestinationVerifierVerifyTest.t.sol | 714 - .../configuration/ChannelConfigStore.sol | 29 - .../v0.5.0/configuration/Configurator.sol | 188 - .../interfaces/IChannelConfigStore.sol | 8 - .../test/ChannelConfigStore.t.sol | 41 - .../test/mocks/ExposedChannelConfigStore.sol | 15 - .../test/mocks/ExposedConfigurator.sol | 15 - .../FunctionsBillingRegistryEventsMock.sol | 80 - .../v0.8/mocks/FunctionsOracleEventsMock.sol | 63 - .../v0.8/mocks/MockAggregatorValidator.sol | 30 - .../contracts/src/v0.8/mocks/MockArbSys.sol | 17 - .../src/v0.8/mocks/MockLinkToken.sol | 54 - .../src/v0.8/mocks/MockOffchainAggregator.sol | 14 - .../operatorforwarder/AuthorizedForwarder.sol | 91 - .../operatorforwarder/AuthorizedReceiver.sol | 65 - .../operatorforwarder/LinkTokenReceiver.sol | 50 - .../src/v0.8/operatorforwarder/Operator.sol | 497 - .../operatorforwarder/OperatorFactory.sol | 73 - .../interfaces/IAuthorizedReceiver.sol | 10 - .../interfaces/IWithdrawal.sol | 13 - .../v0.8/operatorforwarder/test/Factory.t.sol | 69 - .../operatorforwarder/test/Forwarder.t.sol | 183 - .../operatorforwarder/test/operator.t.sol | 291 - .../test/testhelpers/BasicConsumer.sol | 12 - .../test/testhelpers/Callback.sol | 22 - .../testhelpers/ChainlinkClientHelper.sol | 22 - .../test/testhelpers/Chainlinked.sol | 127 - .../test/testhelpers/Consumer.sol | 60 - .../test/testhelpers/Deployer.t.sol | 33 - .../test/testhelpers/EmptyOracle.sol | 28 - .../test/testhelpers/GasGuzzlingConsumer.sol | 41 - .../test/testhelpers/GetterSetter.sol | 50 - .../test/testhelpers/MaliciousChainlink.sol | 67 - .../test/testhelpers/MaliciousChainlinked.sol | 116 - .../test/testhelpers/MaliciousConsumer.sol | 49 - .../MaliciousMultiWordConsumer.sol | 54 - .../test/testhelpers/MaliciousRequester.sol | 52 - .../test/testhelpers/MockReceiver.sol | 19 - .../test/testhelpers/MultiWordConsumer.sol | 145 - .../v0.8/shared/access/AuthorizedCallers.sol | 82 - .../src/v0.8/shared/access/ConfirmedOwner.sol | 10 - .../access/ConfirmedOwnerWithProposal.sol | 68 - .../src/v0.8/shared/access/OwnerIsCreator.sol | 10 - .../access/SimpleReadAccessController.sol | 22 - .../access/SimpleWriteAccessController.sol | 73 - .../src/v0.8/shared/call/CallWithExactGas.sol | 162 - .../enumerable/EnumerableMapAddresses.sol | 225 - .../enumerable/EnumerableMapBytes32.sol | 136 - .../enumerable/EnumerableSetWithBytes16.sol | 454 - .../interfaces/AccessControllerInterface.sol | 7 - .../shared/interfaces/AggregatorInterface.sol | 19 - .../interfaces/AggregatorV2V3Interface.sol | 8 - .../interfaces/AggregatorV3Interface.sol | 20 - .../AggregatorValidatorInterface.sol | 12 - .../shared/interfaces/IAccessController.sol | 6 - .../shared/interfaces/IERC677Receiver.sol | 6 - .../src/v0.8/shared/interfaces/IOwnable.sol | 10 - .../shared/interfaces/ITypeAndVersion.sol | 6 - .../src/v0.8/shared/interfaces/IWERC20.sol | 8 - .../shared/interfaces/LinkTokenInterface.sol | 29 - .../src/v0.8/shared/mocks/WERC20Mock.sol | 36 - .../src/v0.8/shared/ocr2/OCR2Abstract.sol | 122 - .../src/v0.8/shared/ocr2/OCR2Base.sol | 330 - .../contracts/src/v0.8/shared/ocr2/README.md | 5 - .../src/v0.8/shared/test/BaseTest.t.sol | 29 - .../test/access/AuthorizedCallers.t.sol | 186 - .../shared/test/call/CallWithExactGas.t.sol | 512 - .../test/call/CallWithExactGasHelper.sol | 35 - .../enumerable/EnumerableMapAddresses.t.sol | 249 - .../shared/test/helpers/ChainReaderTester.sol | 202 - .../test/helpers/LinkTokenTestHelper.sol | 12 - .../testhelpers/ConfirmedOwnerTestHelper.sol | 14 - .../shared/test/testhelpers/GasConsumer.sol | 24 - .../test/testhelpers/GenericReceiver.sol | 29 - .../test/token/ERC677/BurnMintERC677.t.sol | 347 - .../token/ERC677/OpStackBurnMintERC677.t.sol | 117 - .../test/util/SortedSetValidationUtil.t.sol | 168 - .../shared/token/ERC20/IBurnMintERC20.sol | 29 - .../token/ERC20/IOptimismMintableERC20.sol | 26 - .../shared/token/ERC677/BurnMintERC677.sol | 217 - .../src/v0.8/shared/token/ERC677/ERC677.sol | 21 - .../src/v0.8/shared/token/ERC677/IERC677.sol | 13 - .../v0.8/shared/token/ERC677/LinkToken.sol | 8 - .../token/ERC677/OpStackBurnMintERC677.sol | 49 - .../shared/util/SortedSetValidationUtil.sol | 60 - .../tests/AutomationConsumerBenchmark.sol | 82 - .../contracts/src/v0.8/tests/Broken.sol | 18 - .../v0.8/tests/ChainlinkClientTestHelper.sol | 83 - .../src/v0.8/tests/ChainlinkTestHelper.sol | 57 - .../contracts/src/v0.8/tests/Counter.sol | 26 - .../contracts/src/v0.8/tests/CronReceiver.sol | 20 - .../v0.8/tests/ERC20BalanceMonitorExposed.sol | 17 - .../v0.8/tests/EthBalanceMonitorExposed.sol | 16 - .../contracts/src/v0.8/tests/FeedConsumer.sol | 62 - .../src/v0.8/tests/FlagsTestHelper.sol | 20 - .../contracts/src/v0.8/tests/Greeter.sol | 18 - .../v0.8/tests/KeeperCompatibleTestHelper.sol | 12 - .../contracts/src/v0.8/tests/LogEmitter.sol | 33 - .../src/v0.8/tests/MockArbGasInfo.sol | 11 - .../src/v0.8/tests/MockArbitrumInbox.sol | 125 - .../src/v0.8/tests/MockETHLINKAggregator.sol | 44 - .../src/v0.8/tests/MockGasBoundCaller.sol | 32 - .../src/v0.8/tests/MockOVMGasPriceOracle.sol | 12 - .../MockOptimismL1CrossDomainMessenger.sol | 41 - .../MockOptimismL2CrossDomainMessenger.sol | 28 - .../src/v0.8/tests/MockV3Aggregator.sol | 78 - .../v0.8/tests/MockZKSyncSystemContext.sol | 16 - .../src/v0.8/tests/ReceiveEmitter.sol | 11 - .../src/v0.8/tests/ReceiveFallbackEmitter.sol | 11 - .../src/v0.8/tests/ReceiveReverter.sol | 9 - .../src/v0.8/tests/StreamsLookupUpkeep.sol | 159 - .../src/v0.8/tests/VRFLogEmitter.sol | 42 - .../src/v0.8/tests/VerifiableLoadBase.sol | 572 - .../tests/VerifiableLoadLogTriggerUpkeep.sol | 127 - .../VerifiableLoadStreamsLookupUpkeep.sol | 85 - .../src/v0.8/tests/VerifiableLoadUpkeep.sol | 52 - .../transmission/dev/ERC-4337/Paymaster.sol | 134 - .../v0.8/transmission/dev/ERC-4337/SCA.sol | 73 - .../transmission/dev/ERC-4337/SCALibrary.sol | 48 - .../ERC-4337/SmartContractAccountFactory.sol | 33 - .../transmission/dev/testhelpers/Greeter.sol | 15 - .../SmartContractAccountHelper.sol | 78 - .../src/v0.8/transmission/test/BaseTest.t.sol | 17 - .../transmission/test/EIP_712_1014_4337.t.sol | 365 - .../src/precompiles/ArbGasInfo.sol | 152 - .../src/precompiles/ArbSys.sol | 153 - .../@ensdomains/buffer/v0.1.0/Buffer.sol | 260 - .../v0.16.2/src/L2/GasPriceOracle.sol | 99 - .../v0.16.2/src/L2/L1Block.sol | 76 - .../v0.16.2/src/libraries/Predeploys.sol | 77 - .../v0.16.2/src/universal/ISemver.sol | 13 - .../v0.17.3/src/L2/GasPriceOracle.sol | 251 - .../v0.17.3/src/L2/L1Block.sol | 169 - .../v0.17.3/src/deps/LibString.sol | 54 - .../v0.17.3/src/deps/LibZip.sol | 108 - .../v0.17.3/src/libraries/Constants.sol | 43 - .../v0.17.3/src/libraries/GasPayingToken.sol | 93 - .../v0.17.3/src/libraries/L1BlockErrors.sol | 23 - .../v0.17.3/src/libraries/Predeploys.sol | 171 - .../v0.17.3/src/libraries/Storage.sol | 94 - .../v0.17.3/src/universal/ISemver.sol | 19 - .../messaging/iOVM_CrossDomainMessenger.sol | 33 - .../L2/predeploys/OVM_GasPriceOracle.sol | 162 - .../L2/predeploys/OVM_GasPriceOracle.sol | 162 - .../L2/predeploys/IScrollL1GasPriceOracle.sol | 55 - .../src/v0.8/vendor/BufferChainlink.sol | 337 - .../src/v0.8/vendor/CBORChainlink.sol | 94 - .../contracts/src/v0.8/vendor/DateTime.sol | 254 - .../contracts/src/v0.8/vendor/ENSResolver.sol | 6 - .../contracts/src/v0.8/vendor/IERC165.sol | 12 - .../vendor/MockOVMCrossDomainMessenger.sol | 74 - .../vendor/MockScrollCrossDomainMessenger.sol | 101 - .../contracts/src/v0.8/vendor/MultiSend.sol | 66 - .../contracts/src/v0.8/vendor/Strings.sol | 842 - .../contracts/bridge/interfaces/IBridge.sol | 60 - .../contracts/bridge/interfaces/IInbox.sol | 92 - .../bridge/interfaces/IMessageProvider.sol | 26 - .../libraries/AddressAliasHelper.sol | 44 - .../vendor/entrypoint/core/EntryPoint.sol | 861 - .../v0.8/vendor/entrypoint/core/Helpers.sol | 68 - .../vendor/entrypoint/core/SenderCreator.sol | 28 - .../vendor/entrypoint/core/StakeManager.sol | 124 - .../vendor/entrypoint/interfaces/IAccount.sol | 34 - .../entrypoint/interfaces/IAggregator.sol | 36 - .../entrypoint/interfaces/IEntryPoint.sol | 197 - .../entrypoint/interfaces/IPaymaster.sol | 51 - .../entrypoint/interfaces/IStakeManager.sol | 104 - .../entrypoint/interfaces/UserOperation.sol | 84 - .../src/v0.8/vendor/entrypoint/utils/Exec.sol | 70 - .../src/v0.8/vendor/forge-std/src/Base.sol | 35 - .../src/v0.8/vendor/forge-std/src/Script.sol | 27 - .../vendor/forge-std/src/StdAssertions.sol | 669 - .../v0.8/vendor/forge-std/src/StdChains.sol | 263 - .../v0.8/vendor/forge-std/src/StdCheats.sol | 817 - .../v0.8/vendor/forge-std/src/StdError.sol | 15 - .../vendor/forge-std/src/StdInvariant.sol | 122 - .../src/v0.8/vendor/forge-std/src/StdJson.sol | 283 - .../src/v0.8/vendor/forge-std/src/StdMath.sol | 43 - .../v0.8/vendor/forge-std/src/StdStorage.sol | 473 - .../v0.8/vendor/forge-std/src/StdStyle.sol | 333 - .../src/v0.8/vendor/forge-std/src/StdToml.sol | 283 - .../v0.8/vendor/forge-std/src/StdUtils.sol | 226 - .../src/v0.8/vendor/forge-std/src/Test.sol | 33 - .../src/v0.8/vendor/forge-std/src/Vm.sol | 1968 --- .../src/v0.8/vendor/forge-std/src/console.sol | 1560 -- .../v0.8/vendor/forge-std/src/console2.sol | 4 - .../forge-std/src/interfaces/IERC1155.sol | 105 - .../forge-std/src/interfaces/IERC165.sol | 12 - .../forge-std/src/interfaces/IERC20.sol | 43 - .../forge-std/src/interfaces/IERC4626.sol | 190 - .../forge-std/src/interfaces/IERC721.sol | 164 - .../forge-std/src/interfaces/IMulticall3.sol | 73 - .../vendor/forge-std/src/mocks/MockERC20.sol | 234 - .../vendor/forge-std/src/mocks/MockERC721.sol | 231 - .../v0.8/vendor/forge-std/src/safeconsole.sol | 13937 ---------------- .../v4.7.3/contracts/proxy/Proxy.sol | 86 - .../v4.7.3/contracts/utils/Address.sol | 244 - .../v4.7.3/contracts/utils/Context.sol | 24 - .../contracts/utils/structs/EnumerableMap.sol | 529 - .../contracts/utils/structs/EnumerableSet.sol | 376 - .../v4.8.3/contracts/access/AccessControl.sol | 247 - .../contracts/access/IAccessControl.sol | 88 - .../v4.8.3/contracts/interfaces/IERC165.sol | 6 - .../v4.8.3/contracts/interfaces/IERC20.sol | 6 - .../interfaces/draft-IERC20Permit.sol | 160 - .../v4.8.3/contracts/mocks/ERC20Mock.sol | 41 - .../v4.8.3/contracts/security/Pausable.sol | 105 - .../v4.8.3/contracts/token/ERC20/ERC20.sol | 365 - .../v4.8.3/contracts/token/ERC20/IERC20.sol | 78 - .../token/ERC20/extensions/ERC20Burnable.sol | 39 - .../token/ERC20/extensions/IERC20Metadata.sol | 28 - .../ERC20/extensions/draft-ERC20Permit.sol | 95 - .../ERC20/extensions/draft-IERC20Permit.sol | 60 - .../contracts/token/ERC20/utils/SafeERC20.sol | 95 - .../v4.8.3/contracts/utils/Address.sol | 236 - .../v4.8.3/contracts/utils/Context.sol | 24 - .../v4.8.3/contracts/utils/Counters.sol | 43 - .../v4.8.3/contracts/utils/StorageSlot.sol | 88 - .../v4.8.3/contracts/utils/Strings.sol | 70 - .../contracts/utils/cryptography/ECDSA.sol | 195 - .../contracts/utils/cryptography/EIP712.sol | 102 - .../contracts/utils/introspection/ERC165.sol | 29 - .../utils/introspection/ERC165Checker.sol | 127 - .../contracts/utils/introspection/IERC165.sol | 25 - .../v4.8.3/contracts/utils/math/Math.sol | 336 - .../v4.8.3/contracts/utils/math/SafeCast.sol | 1136 -- .../contracts/utils/math/SignedMath.sol | 43 - .../contracts/utils/structs/EnumerableMap.sol | 530 - .../contracts/utils/structs/EnumerableSet.sol | 378 - .../v5.0.2/contracts/access/AccessControl.sol | 209 - .../contracts/access/IAccessControl.sol | 98 - .../v5.0.2/contracts/interfaces/IERC165.sol | 6 - .../v5.0.2/contracts/interfaces/IERC20.sol | 6 - .../v5.0.2/contracts/interfaces/IERC5267.sol | 28 - .../contracts/interfaces/draft-IERC6093.sol | 161 - .../v5.0.2/contracts/token/ERC20/ERC20.sol | 316 - .../v5.0.2/contracts/token/ERC20/IERC20.sol | 79 - .../token/ERC20/extensions/ERC20Burnable.sol | 39 - .../token/ERC20/extensions/IERC20Metadata.sol | 26 - .../token/ERC20/extensions/IERC20Permit.sol | 90 - .../contracts/token/ERC20/utils/SafeERC20.sol | 118 - .../v5.0.2/contracts/utils/Address.sol | 159 - .../v5.0.2/contracts/utils/Context.sol | 28 - .../v5.0.2/contracts/utils/Pausable.sol | 119 - .../v5.0.2/contracts/utils/ShortStrings.sol | 123 - .../v5.0.2/contracts/utils/StorageSlot.sol | 135 - .../v5.0.2/contracts/utils/Strings.sol | 94 - .../contracts/utils/cryptography/ECDSA.sol | 174 - .../contracts/utils/cryptography/EIP712.sol | 160 - .../utils/cryptography/MessageHashUtils.sol | 86 - .../contracts/utils/introspection/ERC165.sol | 27 - .../utils/introspection/ERC165Checker.sol | 124 - .../contracts/utils/introspection/IERC165.sol | 25 - .../v5.0.2/contracts/utils/math/Math.sol | 415 - .../v5.0.2/contracts/utils/math/SafeCast.sol | 1153 -- .../contracts/utils/math/SignedMath.sol | 43 - .../contracts/utils/structs/EnumerableMap.sol | 533 - .../contracts/utils/structs/EnumerableSet.sol | 378 - .../vendor/solidity-cborutils/v2.0.0/CBOR.sol | 222 - .../src/v0.8/vrf/AuthorizedReceiver.sol | 86 - .../src/v0.8/vrf/BatchBlockhashStore.sol | 90 - .../src/v0.8/vrf/BatchVRFCoordinatorV2.sol | 68 - .../src/v0.8/vrf/KeepersVRFConsumer.sol | 119 - .../chainlink/contracts/src/v0.8/vrf/VRF.sol | 588 - .../src/v0.8/vrf/VRFConsumerBase.sol | 200 - .../src/v0.8/vrf/VRFConsumerBaseV2.sol | 135 - .../src/v0.8/vrf/VRFCoordinatorV2.sol | 840 - .../contracts/src/v0.8/vrf/VRFOwner.sol | 348 - .../src/v0.8/vrf/VRFRequestIDBase.sol | 42 - .../contracts/src/v0.8/vrf/VRFTypes.sol | 44 - .../contracts/src/v0.8/vrf/VRFV2Wrapper.sol | 450 - .../src/v0.8/vrf/VRFV2WrapperConsumerBase.sol | 86 - .../src/v0.8/vrf/dev/ArbitrumL1Fees.sol | 31 - .../vrf/dev/BatchVRFCoordinatorV2Plus.sol | 71 - .../src/v0.8/vrf/dev/BlockhashStore.sol | 81 - .../src/v0.8/vrf/dev/OptimismL1Fees.sol | 97 - .../src/v0.8/vrf/dev/SubscriptionAPI.sol | 475 - .../v0.8/vrf/dev/TrustedBlockhashStore.sol | 66 - .../v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol | 165 - .../vrf/dev/VRFConsumerBaseV2Upgradeable.sol | 158 - .../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol | 791 - .../vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol | 43 - .../vrf/dev/VRFCoordinatorV2_5_Optimism.sol | 21 - .../vrf/dev/VRFSubscriptionBalanceMonitor.sol | 281 - .../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol | 725 - .../vrf/dev/VRFV2PlusWrapperConsumerBase.sol | 121 - .../vrf/dev/VRFV2PlusWrapper_Arbitrum.sol | 23 - .../vrf/dev/VRFV2PlusWrapper_Optimism.sol | 40 - .../dev/interfaces/IVRFCoordinatorV2Plus.sol | 36 - .../IVRFCoordinatorV2PlusInternal.sol | 67 - .../IVRFCoordinatorV2PlusMigration.sol | 14 - .../IVRFMigratableConsumerV2Plus.sol | 13 - .../dev/interfaces/IVRFSubscriptionV2Plus.sol | 98 - .../vrf/dev/interfaces/IVRFV2PlusMigrate.sol | 15 - .../vrf/dev/interfaces/IVRFV2PlusWrapper.sol | 83 - .../vrf/dev/libraries/VRFV2PlusClient.sol | 24 - .../testhelpers/ExposedVRFCoordinatorV2_5.sol | 78 - .../ExposedVRFCoordinatorV2_5_Arbitrum.sol | 33 - .../ExposedVRFCoordinatorV2_5_Optimism.sol | 33 - .../VRFConsumerV2PlusUpgradeableExample.sol | 75 - .../testhelpers/VRFCoordinatorTestV2_5.sol | 773 - .../VRFCoordinatorV2PlusUpgradedVersion.sol | 809 - .../VRFCoordinatorV2Plus_V2Example.sol | 159 - .../VRFMaliciousConsumerV2Plus.sol | 67 - .../src/v0.8/vrf/dev/testhelpers/VRFOld.sol | 588 - .../testhelpers/VRFV2PlusConsumerExample.sol | 113 - .../VRFV2PlusExternalSubOwnerExample.sol | 48 - .../VRFV2PlusLoadTestWithMetrics.sol | 183 - .../VRFV2PlusMaliciousMigrator.sol | 32 - .../testhelpers/VRFV2PlusRevertingExample.sol | 69 - .../VRFV2PlusSingleConsumerExample.sol | 115 - .../VRFV2PlusWrapperConsumerExample.sol | 87 - .../VRFV2PlusWrapperLoadTestConsumer.sol | 199 - .../interfaces/BlockhashStoreInterface.sol | 7 - .../vrf/interfaces/IAuthorizedReceiver.sol | 10 - .../interfaces/VRFCoordinatorV2Interface.sol | 113 - .../vrf/interfaces/VRFV2WrapperInterface.sol | 33 - .../src/v0.8/vrf/mocks/VRFCoordinatorMock.sol | 36 - .../v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol | 323 - .../v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol | 269 - .../src/v0.8/vrf/test/BaseTest.t.sol | 34 - .../vrf/test/BatchVRFCoordinatorV2Plus.t.sol | 196 - .../src/v0.8/vrf/test/ChainSpecificUtil.t.sol | 196 - .../vrf/test/FixtureVRFCoordinatorV2_5.t.sol | 134 - .../v0.8/vrf/test/TrustedBlockhashStore.t.sol | 89 - .../v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol | 381 - .../test/VRFCoordinatorV2Plus_Migration.t.sol | 352 - .../vrf/test/VRFCoordinatorV2_5Mock.t.sol | 511 - .../test/VRFCoordinatorV2_5_Arbitrum.t.sol | 179 - .../test/VRFCoordinatorV2_5_Optimism.t.sol | 413 - .../src/v0.8/vrf/test/VRFV2Plus.t.sol | 1160 -- .../vrf/test/VRFV2PlusSubscriptionAPI.t.sol | 649 - .../src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol | 488 - .../vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol | 109 - .../vrf/test/VRFV2PlusWrapper_Migration.t.sol | 388 - .../vrf/test/VRFV2PlusWrapper_Optimism.t.sol | 216 - .../testhelpers/ChainSpecificUtilHelper.sol | 23 - .../src/v0.8/vrf/testhelpers/Counter.sol | 26 - .../src/v0.8/vrf/testhelpers/VRFConsumer.sol | 28 - .../v0.8/vrf/testhelpers/VRFConsumerV2.sol | 60 - .../vrf/testhelpers/VRFConsumerV2Plus.sol | 55 - .../VRFConsumerV2UpgradeableExample.sol | 62 - .../vrf/testhelpers/VRFCoordinatorTestV2.sol | 840 - .../VRFCoordinatorV2TestHelper.sol | 88 - .../VRFExternalSubOwnerExample.sol | 46 - .../VRFLoadTestExternalSubOwner.sol | 38 - .../VRFLoadTestOwnerlessConsumer.sol | 42 - .../testhelpers/VRFMaliciousConsumerV2.sol | 50 - .../testhelpers/VRFMockETHLINKAggregator.sol | 53 - .../VRFOwnerlessConsumerExample.sol | 38 - .../VRFRequestIDBaseTestHelper.sol | 19 - .../testhelpers/VRFSingleConsumerExample.sol | 110 - .../VRFSubscriptionBalanceMonitorExposed.sol | 18 - .../v0.8/vrf/testhelpers/VRFTestHelper.sol | 104 - .../testhelpers/VRFV2LoadTestWithMetrics.sol | 163 - .../testhelpers/VRFV2OwnerTestConsumer.sol | 138 - .../v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol | 8 - .../vrf/testhelpers/VRFV2RevertingExample.sol | 61 - .../VRFV2TransparentUpgradeableProxy.sol | 13 - .../VRFV2WrapperConsumerExample.sol | 57 - .../VRFV2WrapperLoadTestConsumer.sol | 137 - .../VRFV2WrapperOutOfGasConsumerExample.sol | 24 - .../VRFV2WrapperRevertingConsumerExample.sol | 24 - .../VRFV2WrapperUnderFundingConsumer.sol | 25 - .../v0.8/vrf/testhelpers/VRFv2Consumer.sol | 64 - 1430 files changed, 369703 deletions(-) delete mode 100644 packages/foundry/lib/chainlink/contracts/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json delete mode 100644 packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json delete mode 100644 packages/foundry/lib/chainlink/contracts/package.json delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol delete mode 100644 packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol diff --git a/packages/foundry/lib/chainlink/contracts/README.md b/packages/foundry/lib/chainlink/contracts/README.md deleted file mode 100644 index 182891c..0000000 --- a/packages/foundry/lib/chainlink/contracts/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# Chainlink Smart Contracts - -## Installation - -```sh -# via pnpm -$ pnpm add @chainlink/contracts -# via npm -$ npm install @chainlink/contracts --save -``` - -### Directory Structure - -```sh -@chainlink/contracts -├── src # Solidity contracts -│ └── v0.8 -└── abi # ABI json output - └── v0.8 -``` - -### Usage - -The solidity smart contracts themselves can be imported via the `src` directory of `@chainlink/contracts`: - -```solidity -import '@chainlink/contracts/src/v0.8/AutomationCompatibleInterface.sol'; -``` - -## Local Development - -Note: Contracts in `dev/` directories are under active development and are likely unaudited. Please refrain from using these in production applications. - -```bash -# Clone Chainlink repository -$ git clone https://github.com/smartcontractkit/chainlink.git -# Continuing via pnpm -$ cd contracts/ -$ pnpm -$ pnpm test -``` - -## Contributing - -Please try to adhere to [Solidity Style Guide](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/STYLE.md). - -Contributions are welcome! Please refer to -[Chainlink's contributing guidelines](https://github.com/smartcontractkit/chainlink/blob/develop/docs/CONTRIBUTING.md) for detailed -contribution information. - -Thank you! - -### Changesets - -We use [changesets](https://github.com/changesets/changesets) to manage versioning the contracts. - -Every PR that modifies any configuration or code, should most likely accompanied by a changeset file. - -To install `changesets`: - 1. Install `pnpm` if it is not already installed - [docs](https://pnpm.io/installation). - 2. Run `pnpm install`. - -Either after or before you create a commit, run the `pnpm changeset` command in the `contracts` directory to create an accompanying changeset entry which will reflect on the CHANGELOG for the next release. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## License -Most of the contracts are licensed under the [MIT](https://choosealicense.com/licenses/mit/) license. -An exception to this is the ccip folder, which defaults to be licensed under the [BUSL-1.1](./src/v0.8/ccip/LICENSE.md) license, however, there are a few exceptions - -- `src/v0.8/ccip/applications/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license -- `src/v0.8/ccip/interfaces/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license -- `src/v0.8/ccip/libraries/{Client.sol, Internal.sol}` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json deleted file mode 100644 index 5756029..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControl.json +++ /dev/null @@ -1,227 +0,0 @@ -[ - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json deleted file mode 100644 index d018c95..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AccessControllerInterface.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json deleted file mode 100644 index e1a1ad8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Address.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "AddressEmptyCode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "AddressInsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "FailedInnerCall", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json deleted file mode 100644 index 7fb29aa..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorInterface.json +++ /dev/null @@ -1,129 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json deleted file mode 100644 index 4667a49..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV2V3Interface.json +++ /dev/null @@ -1,240 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json deleted file mode 100644 index 9fe8722..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorV3Interface.json +++ /dev/null @@ -1,113 +0,0 @@ -[ - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json deleted file mode 100644 index 54a6a92..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AggregatorValidatorInterface.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json deleted file mode 100644 index 375b188..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbGasInfo.json +++ /dev/null @@ -1,406 +0,0 @@ -[ - { - "inputs": [], - "name": "getAmortizedCostCapBips", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentTxL1GasFees", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasAccountingParams", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasBacklog", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasBacklogTolerance", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1BaseFeeEstimate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1BaseFeeEstimateInertia", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1FeesAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1GasPriceEstimate", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1PricingEquilibrationUnits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1PricingFundsDueForRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1PricingSurplus", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1PricingUnitsSinceUpdate", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1RewardRate", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1RewardRecipient", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLastL1PricingSurplus", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLastL1PricingUpdateTime", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinimumGasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerBatchGasCharge", - "outputs": [ - { - "internalType": "int64", - "name": "", - "type": "int64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPricesInArbGas", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "getPricesInArbGasWithAggregator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPricesInWei", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "getPricesInWeiWithAggregator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPricingInertia", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json deleted file mode 100644 index 76bb647..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbSys.json +++ /dev/null @@ -1,355 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "destination", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "uniqueId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "batchNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "indexInBatch", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "arbBlockNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "ethBlockNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "callvalue", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "L2ToL1Transaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "destination", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "hash", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "position", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "arbBlockNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "ethBlockNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "callvalue", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "L2ToL1Tx", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "reserved", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "position", - "type": "uint256" - } - ], - "name": "SendMerkleUpdate", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "arbBlockNum", - "type": "uint256" - } - ], - "name": "arbBlockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "arbBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "arbChainID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "arbOSVersion", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStorageGasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isTopLevelCall", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "unused", - "type": "address" - } - ], - "name": "mapL1SenderContractAddressToL2Alias", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "myCallersAddressWithoutAliasing", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sendMerkleTreeState", - "outputs": [ - { - "internalType": "uint256", - "name": "size", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "partials", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destination", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendTxToL1", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "wasMyCallersAddressAliased", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawEth", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json deleted file mode 100644 index b6f66e0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainForwarder.json +++ /dev/null @@ -1,199 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json deleted file mode 100644 index 6df7093..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumCrossDomainGovernor.json +++ /dev/null @@ -1,217 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forwardDelegate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json deleted file mode 100644 index a25dd05..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL1BridgeAdapter.json +++ /dev/null @@ -1,272 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IL1GatewayRouter", - "name": "l1GatewayRouter", - "type": "address" - }, - { - "internalType": "contract IOutbox", - "name": "l1Outbox", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "NoGatewayForToken", - "type": "error" - }, - { - "inputs": [], - "name": "Unimplemented", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "address", - "name": "l2Sender", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "l2Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l1Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2Timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct ArbitrumL1BridgeAdapter.ArbitrumFinalizationPayload", - "name": "payload", - "type": "tuple" - } - ], - "name": "exposeArbitrumFinalizationPayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - } - ], - "internalType": "struct ArbitrumL1BridgeAdapter.SendERC20Params", - "name": "params", - "type": "tuple" - } - ], - "name": "exposeSendERC20Params", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "arbitrumFinalizationPayload", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "l1Token", - "type": "address" - } - ], - "name": "getL2Token", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json deleted file mode 100644 index 3e51a25..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumL2BridgeAdapter.json +++ /dev/null @@ -1,155 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IL2GatewayRouter", - "name": "l2GatewayRouter", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "depositNativeToL1", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json deleted file mode 100644 index 7a398a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumModule.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json deleted file mode 100644 index c9a61dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumSequencerUptimeFeed.json +++ /dev/null @@ -1,621 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "flagsAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l1SenderAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AlreadyInitialized", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSender", - "type": "error" - }, - { - "inputs": [], - "name": "NoDataPresent", - "type": "error" - }, - { - "inputs": [], - "name": "Uninitialized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1SenderTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "latestStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "latestTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bool", - "name": "incomingStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "incomingTimestamp", - "type": "uint64" - } - ], - "name": "UpdateIgnored", - "type": "event" - }, - { - "inputs": [], - "name": "FLAGS", - "outputs": [ - { - "internalType": "contract IFlags", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FLAG_L2_SEQ_OFFLINE", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aliasedL1MessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Sender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json deleted file mode 100644 index 8faac8f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ArbitrumValidator.json +++ /dev/null @@ -1,565 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "crossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l2ArbitrumSequencerUptimeFeedAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "configACAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - }, - { - "internalType": "address", - "name": "gasPriceL1FeedAddr", - "type": "address" - }, - { - "internalType": "enum ArbitrumValidator.PaymentStrategy", - "name": "_paymentStrategy", - "type": "uint8" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previous", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "current", - "type": "address" - } - ], - "name": "ConfigACSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "gasPriceL1FeedAddr", - "type": "address" - } - ], - "name": "GasConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "refundAddr", - "type": "address" - } - ], - "name": "L2WithdrawalRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "enum ArbitrumValidator.PaymentStrategy", - "name": "paymentStrategy", - "type": "uint8" - } - ], - "name": "PaymentStrategySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "CROSS_DOMAIN_MESSENGER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_ALIAS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_SEQ_STATUS_RECORDER", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "configAC", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "gasConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - }, - { - "internalType": "address", - "name": "gasPriceL1FeedAddr", - "type": "address" - } - ], - "internalType": "struct ArbitrumValidator.GasConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paymentStrategy", - "outputs": [ - { - "internalType": "enum ArbitrumValidator.PaymentStrategy", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessController", - "type": "address" - } - ], - "name": "setConfigAC", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - }, - { - "internalType": "address", - "name": "gasPriceL1FeedAddr", - "type": "address" - } - ], - "name": "setGasConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum ArbitrumValidator.PaymentStrategy", - "name": "_paymentStrategy", - "type": "uint8" - } - ], - "name": "setPaymentStrategy", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "refundAddr", - "type": "address" - } - ], - "name": "withdrawFundsFromL2", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawFundsTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json deleted file mode 100644 index 07c084e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedCallers.json +++ /dev/null @@ -1,164 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address[]", - "name": "authorizedCallers", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "caller", - "type": "address" - } - ], - "name": "UnauthorizedCaller", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "caller", - "type": "address" - } - ], - "name": "AuthorizedCallerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "caller", - "type": "address" - } - ], - "name": "AuthorizedCallerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "addedCallers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "removedCallers", - "type": "address[]" - } - ], - "internalType": "struct AuthorizedCallers.AuthorizedCallerArgs", - "name": "authorizedCallerArgs", - "type": "tuple" - } - ], - "name": "applyAuthorizedCallerUpdates", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAllAuthorizedCallers", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json deleted file mode 100644 index a810c4c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedForwarder.json +++ /dev/null @@ -1,286 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "OwnershipTransferRequestedWithMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAuthorizedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isAuthorizedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "tos", - "type": "address[]" - }, - { - "internalType": "bytes[]", - "name": "datas", - "type": "bytes[]" - } - ], - "name": "multiForward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ownerForward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSenders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "transferOwnershipWithMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json deleted file mode 100644 index 946d5ed..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AuthorizedReceiver.json +++ /dev/null @@ -1,66 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "inputs": [], - "name": "getAuthorizedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isAuthorizedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSenders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json deleted file mode 100644 index b544978..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationBase.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json deleted file mode 100644 index aae2720..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatible.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json deleted file mode 100644 index e934ed8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleInterface.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json deleted file mode 100644 index 1976f74..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationCompatibleUtils.json +++ /dev/null @@ -1,212 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct IAutomationV21PlusCommon.ConditionalTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_conditionalTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "", - "type": "tuple" - } - ], - "name": "_log", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "logBlockHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "logIndex", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct IAutomationV21PlusCommon.LogTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_logTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "filterSelector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "internalType": "struct IAutomationV21PlusCommon.LogTriggerConfig", - "name": "", - "type": "tuple" - } - ], - "name": "_logTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "gasLimits", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "triggers", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "performDatas", - "type": "bytes[]" - } - ], - "internalType": "struct IAutomationV21PlusCommon.Report", - "name": "", - "type": "tuple" - } - ], - "name": "_report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json deleted file mode 100644 index b165a3b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationConsumerBenchmark.json +++ /dev/null @@ -1,212 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialCall", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextEligible", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "range", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "firstEligibleBuffer", - "type": "uint256" - } - ], - "name": "checkEligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "count", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getCountPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "initialCall", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "nextEligible", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json deleted file mode 100644 index b7d64b9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarder.json +++ /dev/null @@ -1,69 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "address", - "name": "registry", - "type": "address" - }, - { - "internalType": "address", - "name": "logic", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasAmount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTarget", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json deleted file mode 100644 index 7b3cdce..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationForwarderLogic.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "inputs": [], - "name": "getRegistry", - "outputs": [ - { - "internalType": "contract IAutomationRegistryConsumer", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newRegistry", - "type": "address" - } - ], - "name": "updateRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json deleted file mode 100644 index be5426f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_1.json +++ /dev/null @@ -1,761 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "LINKAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "enum AutomationRegistrar2_1.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistrar2_1.InitialTriggerConfig[]", - "name": "triggerConfigs", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AmountMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "FunctionNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "HashMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientPayment", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAdminAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "LinkTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyAdminOrOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyLink", - "type": "error" - }, - { - "inputs": [], - "name": "RegistrationRequestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "RequestNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "SenderMismatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "AutoApproveAllowedSenderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "ConfigChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "RegistrationApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "RegistrationRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "RegistrationRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "enum AutomationRegistrar2_1.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "name": "TriggerConfigSet", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "cancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - } - ], - "name": "getAutoApproveAllowedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minLINKJuels", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "getPendingRequest", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - } - ], - "name": "getTriggerRegistrationDetails", - "outputs": [ - { - "components": [ - { - "internalType": "enum AutomationRegistrar2_1.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "approvedCount", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistrar2_1.TriggerRegistrationStorage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "register", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistrar2_1.RegistrationParams", - "name": "requestParams", - "type": "tuple" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "setAutoApproveAllowedSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "enum AutomationRegistrar2_1.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "name": "setTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json deleted file mode 100644 index 77d85ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistrar2_3.json +++ /dev/null @@ -1,745 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "LINKAddress", - "type": "address" - }, - { - "internalType": "contract IAutomationRegistryMaster2_3", - "name": "registry", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "enum AutomationRegistrar2_3.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistrar2_3.InitialTriggerConfig[]", - "name": "triggerConfigs", - "type": "tuple[]" - }, - { - "internalType": "contract IERC20Metadata[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "minRegistrationFees", - "type": "uint256[]" - }, - { - "internalType": "contract IWrappedNative", - "name": "wrappedNativeToken", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "HashMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientPayment", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAdminAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidBillingToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyAdminOrOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyLink", - "type": "error" - }, - { - "inputs": [], - "name": "RequestNotFound", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "TransferFailed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "AutoApproveAllowedSenderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "ConfigChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "RegistrationApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "RegistrationRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "RegistrationRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "enum AutomationRegistrar2_3.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "name": "TriggerConfigSet", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct AutomationRegistrar2_3.RegistrationParams", - "name": "requestParams", - "type": "tuple" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "cancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - } - ], - "name": "getAutoApproveAllowedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getMinimumRegistrationAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "getPendingRequest", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRegistry", - "outputs": [ - { - "internalType": "contract IAutomationRegistryMaster2_3", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - } - ], - "name": "getTriggerRegistrationDetails", - "outputs": [ - { - "components": [ - { - "internalType": "enum AutomationRegistrar2_3.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "approvedCount", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistrar2_3.TriggerRegistrationStorage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_WRAPPED_NATIVE_TOKEN", - "outputs": [ - { - "internalType": "contract IWrappedNative", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct AutomationRegistrar2_3.RegistrationParams", - "name": "requestParams", - "type": "tuple" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "setAutoApproveAllowedSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IAutomationRegistryMaster2_3", - "name": "registry", - "type": "address" - }, - { - "internalType": "contract IERC20Metadata[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "minBalances", - "type": "uint256[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "enum AutomationRegistrar2_3.AutoApproveType", - "name": "autoApproveType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - } - ], - "name": "setTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json deleted file mode 100644 index 15eee02..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_2.json +++ /dev/null @@ -1,1367 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryLogicB2_2", - "name": "logicA", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "internalType": "struct AutomationRegistryBase2_2.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json deleted file mode 100644 index 741f78a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistry2_3.json +++ /dev/null @@ -1,1580 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryLogicA2_3", - "name": "logicA", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "contract IERC20Metadata[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig[]", - "name": "billingConfigs", - "type": "tuple[]" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json deleted file mode 100644 index f954e83..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_2.json +++ /dev/null @@ -1,952 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json deleted file mode 100644 index 65619c1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBase2_3.json +++ /dev/null @@ -1,1180 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json deleted file mode 100644 index fa6a597..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryBaseInterface.json +++ /dev/null @@ -1,403 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getKeeperInfo", - "outputs": [ - { - "internalType": "address", - "name": "payee", - "type": "address" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - } - ], - "internalType": "struct State", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "lastKeeper", - "type": "address" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json deleted file mode 100644 index d90e80e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryExecutableInterface.json +++ /dev/null @@ -1,447 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maxLinkPayment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "adjustedGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkEth", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getKeeperInfo", - "outputs": [ - { - "internalType": "address", - "name": "payee", - "type": "address" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - } - ], - "internalType": "struct State", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "lastKeeper", - "type": "address" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json deleted file mode 100644 index f4401b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryInterface.json +++ /dev/null @@ -1,447 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maxLinkPayment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "gasWei", - "type": "int256" - }, - { - "internalType": "int256", - "name": "linkEth", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getKeeperInfo", - "outputs": [ - { - "internalType": "address", - "name": "payee", - "type": "address" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - } - ], - "internalType": "struct State", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "lastKeeper", - "type": "address" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json deleted file mode 100644 index dc01d9e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_2.json +++ /dev/null @@ -1,1334 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryLogicB2_2", - "name": "logicB", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_2.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "enum AutomationRegistryBase2_2.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json deleted file mode 100644 index b62adce..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicA2_3.json +++ /dev/null @@ -1,1329 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryLogicB2_3", - "name": "logicB", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "enum AutomationRegistryBase2_3.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json deleted file mode 100644 index 17ee845..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_2.json +++ /dev/null @@ -1,1998 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "automationForwarderLogic", - "type": "address" - }, - { - "internalType": "address", - "name": "allowedReadOnlyAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "contract IAutomationForwarder", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum AutomationRegistryBase2_2.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum AutomationRegistryBase2_2.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataFixedBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataPerSignerBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "enum AutomationRegistryBase2_2.Trigger", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum AutomationRegistryBase2_2.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json deleted file mode 100644 index 58d04d2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicB2_3.json +++ /dev/null @@ -1,1672 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryLogicC2_3", - "name": "logicC", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum AutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "removeBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "billingOverrides", - "type": "tuple" - } - ], - "name": "setBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawERC20Fees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json deleted file mode 100644 index 163ac51..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationRegistryLogicC2_3.json +++ /dev/null @@ -1,2678 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkUSDFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "nativeUSDFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "automationForwarderLogic", - "type": "address" - }, - { - "internalType": "address", - "name": "allowedReadOnlyAddress", - "type": "address" - }, - { - "internalType": "enum AutomationRegistryBase2_3.PayoutMode", - "name": "payoutMode", - "type": "uint8" - }, - { - "internalType": "address", - "name": "wrappedNativeTokenAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "disableOffchainPayments", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getAvailableERC20ForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getBillingConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverrides", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverridesEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingToken", - "outputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - } - ], - "name": "getBillingTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBillingTokens", - "outputs": [ - { - "internalType": "contract IERC20Metadata[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackNativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "contract IAutomationForwarder", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getHotVars", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reentrancyGuard", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.HotVars", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "enum AutomationRegistryBase2_3.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNativeUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNumUpkeeps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPayoutMode", - "outputs": [ - { - "internalType": "enum AutomationRegistryBase2_3.PayoutMode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum AutomationRegistryBase2_3.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getReserveAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStorage", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistryBase2_3.Storage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataFixedBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataPerSignerBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmittersWithPayees", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transmitterAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "payeeAddress", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "enum AutomationRegistryBase2_3.Trigger", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNativeTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum AutomationRegistryBase2_3.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "settleNOPsOffchain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - } - ], - "name": "supportsBillingToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json deleted file mode 100644 index a05ca44..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_1.json +++ /dev/null @@ -1,302 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct KeeperRegistryBase2_1.ConditionalTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_conditionalTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "", - "type": "tuple" - } - ], - "name": "_log", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "logBlockHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "logIndex", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct KeeperRegistryBase2_1.LogTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_logTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "filterSelector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "internalType": "struct LogTriggerConfig", - "name": "", - "type": "tuple" - } - ], - "name": "_logTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "", - "type": "tuple" - } - ], - "name": "_onChainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "gasLimits", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "triggers", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "performDatas", - "type": "bytes[]" - } - ], - "internalType": "struct KeeperRegistryBase2_1.Report", - "name": "", - "type": "tuple" - } - ], - "name": "_report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json deleted file mode 100644 index 10f5012..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_2.json +++ /dev/null @@ -1,302 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct AutomationRegistryBase2_2.ConditionalTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_conditionalTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "", - "type": "tuple" - } - ], - "name": "_log", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "logBlockHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "logIndex", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNum", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "internalType": "struct AutomationRegistryBase2_2.LogTrigger", - "name": "", - "type": "tuple" - } - ], - "name": "_logTrigger", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint8", - "name": "filterSelector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "internalType": "struct LogTriggerConfig", - "name": "", - "type": "tuple" - } - ], - "name": "_logTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "", - "type": "tuple" - } - ], - "name": "_onChainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "gasLimits", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "triggers", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "performDatas", - "type": "bytes[]" - } - ], - "internalType": "struct AutomationRegistryBase2_2.Report", - "name": "", - "type": "tuple" - } - ], - "name": "_report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json deleted file mode 100644 index 9f044b0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/AutomationUtils2_3.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint256[]", - "name": "gasLimits", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "triggers", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "performDatas", - "type": "bytes[]" - } - ], - "internalType": "struct AutomationRegistryBase2_3.Report", - "name": "", - "type": "tuple" - } - ], - "name": "_report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json deleted file mode 100644 index dc34fd9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseSequencerUptimeFeed.json +++ /dev/null @@ -1,562 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidSender", - "type": "error" - }, - { - "inputs": [], - "name": "NoDataPresent", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1SenderTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "int256", - "name": "status", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "updatedAt", - "type": "uint64" - } - ], - "name": "RoundUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "latestStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "latestTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bool", - "name": "incomingStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "incomingTimestamp", - "type": "uint64" - } - ], - "name": "UpdateIgnored", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Sender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json deleted file mode 100644 index a91c406..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BaseValidator.json +++ /dev/null @@ -1,314 +0,0 @@ -[ - { - "inputs": [], - "name": "L1CrossDomainMessengerAddressZero", - "type": "error" - }, - { - "inputs": [], - "name": "L2UptimeFeedAddrZero", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "GasLimitUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_UPTIME_FEED_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getGasLimit", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json deleted file mode 100644 index 234365f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BasicConsumer.json +++ /dev/null @@ -1,211 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_specId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "price", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - } - ], - "name": "addExternalRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "_callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "_expiration", - "type": "uint256" - } - ], - "name": "cancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_price", - "type": "bytes32" - } - ], - "name": "fulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPrice", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestEthereumPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_callback", - "type": "address" - } - ], - "name": "requestEthereumPriceByCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json deleted file mode 100644 index 0c7bfe4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchBlockhashStore.json +++ /dev/null @@ -1,76 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStoreAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BHS", - "outputs": [ - { - "internalType": "contract BlockhashStore", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "blockNumbers", - "type": "uint256[]" - } - ], - "name": "getBlockhashes", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "blockNumbers", - "type": "uint256[]" - } - ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "blockNumbers", - "type": "uint256[]" - }, - { - "internalType": "bytes[]", - "name": "headers", - "type": "bytes[]" - } - ], - "name": "storeVerifyHeader", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json deleted file mode 100644 index 9a97cfa..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2.json +++ /dev/null @@ -1,156 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "ErrorReturned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelData", - "type": "bytes" - } - ], - "name": "RawErrorReturned", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof[]", - "name": "proofs", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "internalType": "struct VRFTypes.RequestCommitment[]", - "name": "rcs", - "type": "tuple[]" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json deleted file mode 100644 index 9f5642c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BatchVRFCoordinatorV2Plus.json +++ /dev/null @@ -1,161 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "ErrorReturned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelData", - "type": "bytes" - } - ], - "name": "RawErrorReturned", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2PlusFulfill", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof[]", - "name": "proofs", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus[]", - "name": "rcs", - "type": "tuple[]" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json deleted file mode 100644 index fdf9512..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStore.json +++ /dev/null @@ -1,52 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getBlockhash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "header", - "type": "bytes" - } - ], - "name": "storeVerifyHeader", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json deleted file mode 100644 index 7e9ac19..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BlockhashStoreInterface.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "number", - "type": "uint256" - } - ], - "name": "getBlockhash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json deleted file mode 100644 index 8b54d23..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Broken.json +++ /dev/null @@ -1,45 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "reason", - "type": "string" - }, - { - "internalType": "int256", - "name": "reason2", - "type": "int256" - } - ], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [], - "name": "revertSilently", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "revertWithCustomError", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "revertWithMessage", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json deleted file mode 100644 index 283b77c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/BurnMintERC677.json +++ /dev/null @@ -1,784 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "maxSupply_", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "supplyAfterMint", - "type": "uint256" - } - ], - "name": "MaxSupplyExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotBurner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotMinter", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBurners", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "grantBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burnAndMinter", - "type": "address" - } - ], - "name": "grantMintAndBurnRoles", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "grantMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseApproval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "isBurner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "isMinter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "revokeBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "revokeMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json deleted file mode 100644 index ba347ee..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ByteUtil.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "inputs": [], - "name": "MalformedData", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json deleted file mode 100644 index d5bdb35..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGas.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "inputs": [], - "name": "NoContract", - "type": "error" - }, - { - "inputs": [], - "name": "NoGasForCallExactCheck", - "type": "error" - }, - { - "inputs": [], - "name": "NotEnoughGasForCall", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json deleted file mode 100644 index 67a5c4f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CallWithExactGasHelper.json +++ /dev/null @@ -1,124 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - } - ], - "name": "callWithExactGas", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - } - ], - "name": "callWithExactGasEvenIfTargetIsNoContract", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bool", - "name": "sufficientGas", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "maxReturnBytes", - "type": "uint16" - } - ], - "name": "callWithExactGasSafeReturnData", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "retData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json deleted file mode 100644 index 589b6ad..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Callback.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_operator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "callback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCallbacksReceived", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json deleted file mode 100644 index 14e1f1a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilitiesRegistry.json +++ /dev/null @@ -1,1324 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AccessForbidden", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "CapabilityAlreadyExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "CapabilityDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "CapabilityIsDeprecated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "CapabilityRequiredByDON", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "DONDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - } - ], - "name": "DuplicateDONCapability", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - } - ], - "name": "DuplicateDONNode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedConfigurationContract", - "type": "address" - } - ], - "name": "InvalidCapabilityConfigurationContractInterface", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "nodeCount", - "type": "uint256" - } - ], - "name": "InvalidFaultTolerance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - } - ], - "name": "InvalidNodeCapabilities", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "encryptionPublicKey", - "type": "bytes32" - } - ], - "name": "InvalidNodeEncryptionPublicKey", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidNodeOperatorAdmin", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - } - ], - "name": "InvalidNodeP2PId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidNodeSigner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "lengthOne", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "lengthTwo", - "type": "uint256" - } - ], - "name": "LengthMismatch", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - } - ], - "name": "NodeAlreadyExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - } - ], - "name": "NodeDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - } - ], - "name": "NodeDoesNotSupportCapability", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - } - ], - "name": "NodeOperatorDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - } - ], - "name": "NodePartOfCapabilitiesDON", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "nodeP2PId", - "type": "bytes32" - } - ], - "name": "NodePartOfWorkflowDON", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "CapabilityConfigured", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "CapabilityDeprecated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - } - ], - "name": "NodeAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "NodeOperatorAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - } - ], - "name": "NodeOperatorRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "NodeOperatorUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - } - ], - "name": "NodeRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - } - ], - "name": "NodeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "labelledName", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityType", - "name": "capabilityType", - "type": "uint8" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", - "name": "responseType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "configurationContract", - "type": "address" - } - ], - "internalType": "struct CapabilitiesRegistry.Capability[]", - "name": "capabilities", - "type": "tuple[]" - } - ], - "name": "addCapabilities", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "nodes", - "type": "bytes32[]" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", - "name": "capabilityConfigurations", - "type": "tuple[]" - }, - { - "internalType": "bool", - "name": "isPublic", - "type": "bool" - }, - { - "internalType": "bool", - "name": "acceptsWorkflows", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "name": "addDON", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeOperator[]", - "name": "nodeOperators", - "type": "tuple[]" - } - ], - "name": "addNodeOperators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "encryptionPublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeParams[]", - "name": "nodes", - "type": "tuple[]" - } - ], - "name": "addNodes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - } - ], - "name": "deprecateCapabilities", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCapabilities", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "hashedId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "labelledName", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityType", - "name": "capabilityType", - "type": "uint8" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", - "name": "responseType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "configurationContract", - "type": "address" - }, - { - "internalType": "bool", - "name": "isDeprecated", - "type": "bool" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedId", - "type": "bytes32" - } - ], - "name": "getCapability", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "hashedId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "labelledName", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityType", - "name": "capabilityType", - "type": "uint8" - }, - { - "internalType": "enum CapabilitiesRegistry.CapabilityResponseType", - "name": "responseType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "configurationContract", - "type": "address" - }, - { - "internalType": "bool", - "name": "isDeprecated", - "type": "bool" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - } - ], - "name": "getCapabilityConfigs", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "getDON", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "id", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "isPublic", - "type": "bool" - }, - { - "internalType": "bool", - "name": "acceptsWorkflows", - "type": "bool" - }, - { - "internalType": "bytes32[]", - "name": "nodeP2PIds", - "type": "bytes32[]" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", - "name": "capabilityConfigurations", - "type": "tuple[]" - } - ], - "internalType": "struct CapabilitiesRegistry.DONInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDONs", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "id", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "isPublic", - "type": "bool" - }, - { - "internalType": "bool", - "name": "acceptsWorkflows", - "type": "bool" - }, - { - "internalType": "bytes32[]", - "name": "nodeP2PIds", - "type": "bytes32[]" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", - "name": "capabilityConfigurations", - "type": "tuple[]" - } - ], - "internalType": "struct CapabilitiesRegistry.DONInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "labelledName", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - } - ], - "name": "getHashedCapabilityId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - } - ], - "name": "getNode", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "workflowDONId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "encryptionPublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - }, - { - "internalType": "uint256[]", - "name": "capabilitiesDONIds", - "type": "uint256[]" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeInfo", - "name": "nodeInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - } - ], - "name": "getNodeOperator", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeOperator", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNodeOperators", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeOperator[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNodes", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "workflowDONId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "encryptionPublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - }, - { - "internalType": "uint256[]", - "name": "capabilitiesDONIds", - "type": "uint256[]" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hashedCapabilityId", - "type": "bytes32" - } - ], - "name": "isCapabilityDeprecated", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32[]", - "name": "donIds", - "type": "uint32[]" - } - ], - "name": "removeDONs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32[]", - "name": "nodeOperatorIds", - "type": "uint32[]" - } - ], - "name": "removeNodeOperators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "removedNodeP2PIds", - "type": "bytes32[]" - } - ], - "name": "removeNodes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "nodes", - "type": "bytes32[]" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "capabilityId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "internalType": "struct CapabilitiesRegistry.CapabilityConfiguration[]", - "name": "capabilityConfigurations", - "type": "tuple[]" - }, - { - "internalType": "bool", - "name": "isPublic", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "name": "updateDON", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32[]", - "name": "nodeOperatorIds", - "type": "uint32[]" - }, - { - "components": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeOperator[]", - "name": "nodeOperators", - "type": "tuple[]" - } - ], - "name": "updateNodeOperators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nodeOperatorId", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "signer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "p2pId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "encryptionPublicKey", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "hashedCapabilityIds", - "type": "bytes32[]" - } - ], - "internalType": "struct CapabilitiesRegistry.NodeParams[]", - "name": "nodes", - "type": "tuple[]" - } - ], - "name": "updateNodes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json deleted file mode 100644 index e340a6e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CapabilityConfigurationContract.json +++ /dev/null @@ -1,74 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [], - "name": "CapabilityConfigurationSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "beforeCapabilityConfigSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "getCapabilityConfiguration", - "outputs": [ - { - "internalType": "bytes", - "name": "configuration", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json deleted file mode 100644 index 256eeb1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainModuleBase.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "l1Fee", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "maxL1Fee", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json deleted file mode 100644 index 3612098..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainReaderTester.json +++ /dev/null @@ -1,888 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "StaticBytes", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int32", - "name": "field", - "type": "int32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "oracleId", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "indexed": false, - "internalType": "struct MidLevelDynamicTestStruct", - "name": "nestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "indexed": false, - "internalType": "struct MidLevelStaticTestStruct", - "name": "nestedStaticStruct", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint8[32]", - "name": "oracleIds", - "type": "uint8[32]" - }, - { - "indexed": false, - "internalType": "address", - "name": "Account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "Accounts", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "string", - "name": "differentField", - "type": "string" - }, - { - "indexed": false, - "internalType": "int192", - "name": "bigField", - "type": "int192" - } - ], - "name": "Triggered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "fieldHash", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "field", - "type": "string" - } - ], - "name": "TriggeredEventWithDynamicTopic", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int32", - "name": "field1", - "type": "int32" - }, - { - "indexed": true, - "internalType": "int32", - "name": "field2", - "type": "int32" - }, - { - "indexed": true, - "internalType": "int32", - "name": "field3", - "type": "int32" - } - ], - "name": "TriggeredWithFourTopics", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "string", - "name": "field1", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint8[32]", - "name": "field2", - "type": "uint8[32]" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "field3", - "type": "bytes32" - } - ], - "name": "TriggeredWithFourTopicsWithHashed", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "int32", - "name": "field", - "type": "int32" - }, - { - "internalType": "string", - "name": "differentField", - "type": "string" - }, - { - "internalType": "uint8", - "name": "oracleId", - "type": "uint8" - }, - { - "internalType": "uint8[32]", - "name": "oracleIds", - "type": "uint8[32]" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "int192", - "name": "bigField", - "type": "int192" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelDynamicTestStruct", - "name": "nestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelStaticTestStruct", - "name": "nestedStaticStruct", - "type": "tuple" - } - ], - "name": "addTestStruct", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAlterablePrimitiveValue", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDifferentPrimitiveValue", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "i", - "type": "uint256" - } - ], - "name": "getElementAtIndex", - "outputs": [ - { - "components": [ - { - "internalType": "int32", - "name": "Field", - "type": "int32" - }, - { - "internalType": "string", - "name": "DifferentField", - "type": "string" - }, - { - "internalType": "uint8", - "name": "OracleId", - "type": "uint8" - }, - { - "internalType": "uint8[32]", - "name": "OracleIds", - "type": "uint8[32]" - }, - { - "internalType": "address", - "name": "Account", - "type": "address" - }, - { - "internalType": "address[]", - "name": "Accounts", - "type": "address[]" - }, - { - "internalType": "int192", - "name": "BigField", - "type": "int192" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelDynamicTestStruct", - "name": "NestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelStaticTestStruct", - "name": "NestedStaticStruct", - "type": "tuple" - } - ], - "internalType": "struct TestStruct", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPrimitiveValue", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getSliceValue", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int32", - "name": "field", - "type": "int32" - }, - { - "internalType": "string", - "name": "differentField", - "type": "string" - }, - { - "internalType": "uint8", - "name": "oracleId", - "type": "uint8" - }, - { - "internalType": "uint8[32]", - "name": "oracleIds", - "type": "uint8[32]" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "int192", - "name": "bigField", - "type": "int192" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelDynamicTestStruct", - "name": "nestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelStaticTestStruct", - "name": "nestedStaticStruct", - "type": "tuple" - } - ], - "name": "returnSeen", - "outputs": [ - { - "components": [ - { - "internalType": "int32", - "name": "Field", - "type": "int32" - }, - { - "internalType": "string", - "name": "DifferentField", - "type": "string" - }, - { - "internalType": "uint8", - "name": "OracleId", - "type": "uint8" - }, - { - "internalType": "uint8[32]", - "name": "OracleIds", - "type": "uint8[32]" - }, - { - "internalType": "address", - "name": "Account", - "type": "address" - }, - { - "internalType": "address[]", - "name": "Accounts", - "type": "address[]" - }, - { - "internalType": "int192", - "name": "BigField", - "type": "int192" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelDynamicTestStruct", - "name": "NestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelStaticTestStruct", - "name": "NestedStaticStruct", - "type": "tuple" - } - ], - "internalType": "struct TestStruct", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "value", - "type": "uint64" - } - ], - "name": "setAlterablePrimitiveValue", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int32", - "name": "field", - "type": "int32" - }, - { - "internalType": "uint8", - "name": "oracleId", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "string", - "name": "S", - "type": "string" - } - ], - "internalType": "struct InnerDynamicTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelDynamicTestStruct", - "name": "nestedDynamicStruct", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes2", - "name": "FixedBytes", - "type": "bytes2" - }, - { - "components": [ - { - "internalType": "int64", - "name": "IntVal", - "type": "int64" - }, - { - "internalType": "address", - "name": "A", - "type": "address" - } - ], - "internalType": "struct InnerStaticTestStruct", - "name": "Inner", - "type": "tuple" - } - ], - "internalType": "struct MidLevelStaticTestStruct", - "name": "nestedStaticStruct", - "type": "tuple" - }, - { - "internalType": "uint8[32]", - "name": "oracleIds", - "type": "uint8[32]" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "address[]", - "name": "accounts", - "type": "address[]" - }, - { - "internalType": "string", - "name": "differentField", - "type": "string" - }, - { - "internalType": "int192", - "name": "bigField", - "type": "int192" - } - ], - "name": "triggerEvent", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "field", - "type": "string" - } - ], - "name": "triggerEventWithDynamicTopic", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "val1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "val2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "val3", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "val4", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "val5", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "val6", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "val7", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "raw", - "type": "bytes" - } - ], - "name": "triggerStaticBytes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int32", - "name": "field1", - "type": "int32" - }, - { - "internalType": "int32", - "name": "field2", - "type": "int32" - }, - { - "internalType": "int32", - "name": "field3", - "type": "int32" - } - ], - "name": "triggerWithFourTopics", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "field1", - "type": "string" - }, - { - "internalType": "uint8[32]", - "name": "field2", - "type": "uint8[32]" - }, - { - "internalType": "bytes32", - "name": "field3", - "type": "bytes32" - } - ], - "name": "triggerWithFourTopicsWithHashed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json deleted file mode 100644 index 85ca246..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainSpecificUtilHelper.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "inputs": [], - "name": "getBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockNumber", - "type": "uint64" - } - ], - "name": "getBlockhash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "txCallData", - "type": "string" - } - ], - "name": "getCurrentTxL1GasFees", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "calldataSize", - "type": "uint256" - } - ], - "name": "getL1CalldataGasCost", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json deleted file mode 100644 index 6037a4b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainable.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "fallbackAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json deleted file mode 100644 index 57999bd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClient.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json deleted file mode 100644 index e5c226d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientHelper.json +++ /dev/null @@ -1,125 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "inputs": [], - "name": "FULFILL_SELECTOR", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "cancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "fulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "op", - "type": "address" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json deleted file mode 100644 index 14bfa8f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkClientTestHelper.json +++ /dev/null @@ -1,357 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LinkAmount", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "callbackfunctionSelector", - "type": "bytes4" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Request", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "fulfillRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - } - ], - "name": "publicAddExternalRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "_callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "_expiration", - "type": "uint256" - } - ], - "name": "publicCancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "publicChainlinkToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "publicFulfillChainlinkRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "publicLINK", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_fulfillmentSignature", - "type": "bytes" - } - ], - "name": "publicNewRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "publicOracleAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_fulfillmentSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_wei", - "type": "uint256" - } - ], - "name": "publicRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_fulfillmentSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_wei", - "type": "uint256" - } - ], - "name": "publicRequestOracleData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_fulfillmentSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_wei", - "type": "uint256" - } - ], - "name": "publicRequestOracleDataFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_fulfillmentSignature", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_wei", - "type": "uint256" - } - ], - "name": "publicRequestRunTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json deleted file mode 100644 index 35ea584..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkRequestInterface.json +++ /dev/null @@ -1,78 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "cancelOracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "requestPrice", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "serviceAgreementID", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "oracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json deleted file mode 100644 index 7470682..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChainlinkTestHelper.json +++ /dev/null @@ -1,125 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "RequestData", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_key", - "type": "string" - }, - { - "internalType": "string", - "name": "_value", - "type": "string" - } - ], - "name": "add", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "_value", - "type": "bytes" - } - ], - "name": "addBytes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_key", - "type": "string" - }, - { - "internalType": "int256", - "name": "_value", - "type": "int256" - } - ], - "name": "addInt", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_key", - "type": "string" - }, - { - "internalType": "string[]", - "name": "_values", - "type": "string[]" - } - ], - "name": "addStringArray", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_key", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "addUint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "closeEvent", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "setBuffer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json deleted file mode 100644 index 57999bd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Chainlinked.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json deleted file mode 100644 index 62eaf54..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ChannelConfigStore.json +++ /dev/null @@ -1,164 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "donId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "sha", - "type": "bytes32" - } - ], - "name": "NewChannelDefinition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "bytes32", - "name": "sha", - "type": "bytes32" - } - ], - "name": "setChannelDefinitions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json deleted file mode 100644 index c8ea294..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Configurator.json +++ /dev/null @@ -1,257 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSigners", - "type": "uint256" - } - ], - "name": "ExcessSigners", - "type": "error" - }, - { - "inputs": [], - "name": "FaultToleranceMustBePositive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSigners", - "type": "uint256" - } - ], - "name": "InsufficientSigners", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "isVerifier", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json deleted file mode 100644 index 73d188c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwner.json +++ /dev/null @@ -1,84 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json deleted file mode 100644 index 81f35ae..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerTestHelper.json +++ /dev/null @@ -1,91 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [], - "name": "Here", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "modifierOnlyOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json deleted file mode 100644 index db68d10..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ConfirmedOwnerWithProposal.json +++ /dev/null @@ -1,89 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "pendingOwner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json deleted file mode 100644 index 7b93800..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Consumer.json +++ /dev/null @@ -1,190 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "price", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - } - ], - "name": "addExternalRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "_callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "_expiration", - "type": "uint256" - } - ], - "name": "cancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_price", - "type": "bytes32" - } - ], - "name": "fulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPrice", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestEthereumPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_callback", - "type": "address" - } - ], - "name": "requestEthereumPriceByCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json deleted file mode 100644 index 1d93c6e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Counter.json +++ /dev/null @@ -1,54 +0,0 @@ -[ - { - "inputs": [], - "name": "AlwaysRevert", - "type": "error" - }, - { - "inputs": [], - "name": "alwaysRevert", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "alwaysRevertWithString", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "count", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "increment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json deleted file mode 100644 index 1af3931..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Cron.json +++ /dev/null @@ -1,1218 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "field", - "type": "string" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidField", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidSpec", - "type": "error" - }, - { - "inputs": [], - "name": "ListTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "UnknownFieldType", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "minute", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "hour", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "day", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "month", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "dayOfWeek", - "type": "tuple" - } - ], - "internalType": "struct Spec", - "name": "spec", - "type": "tuple" - } - ], - "name": "lastTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "minute", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "hour", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "day", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "month", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "dayOfWeek", - "type": "tuple" - } - ], - "internalType": "struct Spec", - "name": "spec", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "name": "matches", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "minute", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "hour", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "day", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "month", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "dayOfWeek", - "type": "tuple" - } - ], - "internalType": "struct Spec", - "name": "spec", - "type": "tuple" - } - ], - "name": "nextTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "minute", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "hour", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "day", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "month", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "dayOfWeek", - "type": "tuple" - } - ], - "internalType": "struct Spec", - "name": "spec", - "type": "tuple" - } - ], - "name": "toCronString", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "toEncodedSpec", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "toSpec", - "outputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "minute", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "hour", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "day", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "month", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "enum FieldType", - "name": "fieldType", - "type": "FieldType" - }, - { - "internalType": "uint8", - "name": "singleValue", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "interval", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeStart", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "rangeEnd", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "listLength", - "type": "uint8" - }, - { - "internalType": "uint8[26]", - "name": "list", - "type": "uint8[26]" - } - ], - "internalType": "struct Field", - "name": "dayOfWeek", - "type": "tuple" - } - ], - "internalType": "struct Spec", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json deleted file mode 100644 index 3db6c40..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronExternalTestHelper.json +++ /dev/null @@ -1,78 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "calculateLastTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "calculateNextTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "encodeCronString", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedSpec", - "type": "bytes" - } - ], - "name": "encodedSpecToString", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json deleted file mode 100644 index e7e643b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronInternalTestHelper.json +++ /dev/null @@ -1,115 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "field", - "type": "string" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidField", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidSpec", - "type": "error" - }, - { - "inputs": [], - "name": "ListTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "UnknownFieldType", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "calculateLastTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "calculateNextTick", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "encodeCronString", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedSpec", - "type": "bytes" - } - ], - "name": "encodedSpecToString", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json deleted file mode 100644 index b08bb5d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronReceiver.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [], - "name": "Received1", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Received2", - "type": "event" - }, - { - "inputs": [], - "name": "handler1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "handler2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "revertHandler", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json deleted file mode 100644 index 15f9c31..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeep.json +++ /dev/null @@ -1,449 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "delegate", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxJobs", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "firstJob", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CronJobIDNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "ExceedsMaxJobs", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidHandler", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "TickDoesntMatchSpec", - "type": "error" - }, - { - "inputs": [], - "name": "TickInFuture", - "type": "error" - }, - { - "inputs": [], - "name": "TickTooOld", - "type": "error" - }, - { - "inputs": [], - "name": "UnknownFieldType", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "handler", - "type": "bytes" - } - ], - "name": "CronJobCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CronJobDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "CronJobExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "handler", - "type": "bytes" - } - ], - "name": "CronJobUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "encodedCronSpec", - "type": "bytes" - } - ], - "name": "createCronJobFromEncodedSpec", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "deleteCronJob", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getActiveCronJobIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getCronJob", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "string", - "name": "cronString", - "type": "string" - }, - { - "internalType": "uint256", - "name": "nextTick", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_maxJobs", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newTarget", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newHandler", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "newEncodedCronSpec", - "type": "bytes" - } - ], - "name": "updateCronJob", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json deleted file mode 100644 index 46baaac..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepDelegate.json +++ /dev/null @@ -1,31 +0,0 @@ -[ - { - "inputs": [], - "name": "UnknownFieldType", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json deleted file mode 100644 index 3c413d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepFactory.json +++ /dev/null @@ -1,204 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "upkeep", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "NewCronUpkeepCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "cronDelegateAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "encodeCronJob", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "encodeCronString", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "newCronUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedJob", - "type": "bytes" - } - ], - "name": "newCronUpkeepWithJob", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_maxJobs", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxJobs", - "type": "uint256" - } - ], - "name": "setMaxJobs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json deleted file mode 100644 index b569368..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CronUpkeepTestHelper.json +++ /dev/null @@ -1,517 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "delegate", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxJobs", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "firstJob", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CronJobIDNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "ExceedsMaxJobs", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "field", - "type": "string" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidField", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidHandler", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "InvalidSpec", - "type": "error" - }, - { - "inputs": [], - "name": "ListTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "TickDoesntMatchSpec", - "type": "error" - }, - { - "inputs": [], - "name": "TickInFuture", - "type": "error" - }, - { - "inputs": [], - "name": "TickTooOld", - "type": "error" - }, - { - "inputs": [], - "name": "UnknownFieldType", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "handler", - "type": "bytes" - } - ], - "name": "CronJobCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CronJobDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "CronJobExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "handler", - "type": "bytes" - } - ], - "name": "CronJobUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "encodedCronSpec", - "type": "bytes" - } - ], - "name": "createCronJobFromEncodedSpec", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "string", - "name": "cronString", - "type": "string" - } - ], - "name": "createCronJobFromString", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "deleteCronJob", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getActiveCronJobIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getCronJob", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - }, - { - "internalType": "string", - "name": "cronString", - "type": "string" - }, - { - "internalType": "uint256", - "name": "nextTick", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_maxJobs", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "txCheckUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newTarget", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newHandler", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "newEncodedCronSpec", - "type": "bytes" - } - ], - "name": "updateCronJob", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json deleted file mode 100644 index d64def7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainDelegateForwarder.json +++ /dev/null @@ -1,162 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forwardDelegate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json deleted file mode 100644 index 693d75c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainForwarder.json +++ /dev/null @@ -1,162 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json deleted file mode 100644 index 1e093a2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/CrossDomainOwnable.json +++ /dev/null @@ -1,155 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "newl1Owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json deleted file mode 100644 index 1d16b21..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Denominations.json +++ /dev/null @@ -1,262 +0,0 @@ -[ - { - "inputs": [], - "name": "ARS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "AUD", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BRL", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "BTC", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CAD", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CHF", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "CNY", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ETH", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "EUR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "GBP", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "INR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "JPY", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "KRW", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "NGN", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "NZD", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PHP", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RUB", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SGD", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "USD", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "ZAR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json deleted file mode 100644 index 3fd4237..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManager.json +++ /dev/null @@ -1,805 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_linkAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_nativeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_verifierAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_rewardManagerAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ExpiredReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDeposit", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDiscount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidQuote", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReceivingAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSurcharge", - "type": "error" - }, - { - "inputs": [], - "name": "PoolIdMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroDeficit", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct Common.Asset", - "name": "fee", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct Common.Asset", - "name": "reward", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "appliedDiscount", - "type": "uint256" - } - ], - "name": "DiscountApplied", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "indexed": false, - "internalType": "struct IDestinationRewardManager.FeePayment[]", - "name": "rewards", - "type": "tuple[]" - } - ], - "name": "InsufficientLink", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "linkQuantity", - "type": "uint256" - } - ], - "name": "LinkDeficitCleared", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newSurcharge", - "type": "uint64" - } - ], - "name": "NativeSurchargeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "SubscriberDiscountUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "addVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "address", - "name": "quoteAddress", - "type": "address" - } - ], - "name": "getFeeAndReward", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_nativeAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_rewardManager", - "outputs": [ - { - "internalType": "contract IDestinationRewardManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "payLinkDeficit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "recipient", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - }, - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "removeVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_globalDiscounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_linkDeficit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_nativeSurcharge", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_subscriberDiscounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_verifierAddressList", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setFeeRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "surcharge", - "type": "uint64" - } - ], - "name": "setNativeSurcharge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "rewardManagerAddress", - "type": "address" - } - ], - "name": "setRewardManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberGlobalDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json deleted file mode 100644 index 3974bc2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationFeeManagerProxy.json +++ /dev/null @@ -1,61 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - }, - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeManager", - "type": "address" - } - ], - "name": "setDestinationFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json deleted file mode 100644 index 9aae5b2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationRewardManager.json +++ /dev/null @@ -1,554 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPoolId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPoolLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWeights", - "type": "error" - }, - { - "inputs": [], - "name": "Unauthorized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newFeeManagerAddress", - "type": "address" - } - ], - "name": "FeeManagerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "indexed": false, - "internalType": "struct IDestinationRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "payer", - "type": "address" - } - ], - "name": "FeePaid", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "RewardRecipientsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "RewardsClaimed", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newFeeManagerAddress", - "type": "address" - } - ], - "name": "addFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - } - ], - "name": "claimRewards", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getAvailableRewardPoolIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "internalType": "struct IDestinationRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "payer", - "type": "address" - } - ], - "name": "onFeePaid", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - } - ], - "name": "payRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeManagerAddress", - "type": "address" - } - ], - "name": "removeFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_feeManagerAddressList", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_registeredPoolIds", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_rewardRecipientWeights", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_rewardRecipientWeightsSet", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_totalRewardRecipientFees", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_totalRewardRecipientFeesLastClaimedAmounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "updateRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json deleted file mode 100644 index 16b2372..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifier.json +++ /dev/null @@ -1,581 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "verifierProxy", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessForbidden", - "type": "error" - }, - { - "inputs": [], - "name": "BadActivationTime", - "type": "error" - }, - { - "inputs": [], - "name": "BadVerification", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes24", - "name": "donConfigId", - "type": "bytes24" - } - ], - "name": "DonConfigAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "DonConfigDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSigners", - "type": "uint256" - } - ], - "name": "ExcessSigners", - "type": "error" - }, - { - "inputs": [], - "name": "FaultToleranceMustBePositive", - "type": "error" - }, - { - "inputs": [], - "name": "FeeManagerInvalid", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSigners", - "type": "uint256" - } - ], - "name": "InsufficientSigners", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "rsLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ssLength", - "type": "uint256" - } - ], - "name": "MismatchedSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "NoSigners", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAccessController", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAccessController", - "type": "address" - } - ], - "name": "AccessControllerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes24", - "name": "donConfigId", - "type": "bytes24" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isActive", - "type": "bool" - } - ], - "name": "ConfigActivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes24", - "name": "donConfigId", - "type": "bytes24" - } - ], - "name": "ConfigRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes24", - "name": "donConfigId", - "type": "bytes24" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "donConfigIndex", - "type": "uint16" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldFeeManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newFeeManager", - "type": "address" - } - ], - "name": "FeeManagerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "requester", - "type": "address" - } - ], - "name": "ReportVerified", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "i_verifierProxy", - "outputs": [ - { - "internalType": "contract IDestinationVerifierProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "removeLatestConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_accessController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessController", - "type": "address" - } - ], - "name": "setAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "donConfigIndex", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - } - ], - "name": "setConfigActive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - }, - { - "internalType": "uint32", - "name": "activationTime", - "type": "uint32" - } - ], - "name": "setConfigWithActivationTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeManager", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "signedReport", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "signedReports", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verifyBulk", - "outputs": [ - { - "internalType": "bytes[]", - "name": "", - "type": "bytes[]" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json deleted file mode 100644 index 6a8e0cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DestinationVerifierProxy.json +++ /dev/null @@ -1,213 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "VerifierInvalid", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_accessController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "setVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verifyBulk", - "outputs": [ - { - "internalType": "bytes[]", - "name": "verifiedReports", - "type": "bytes[]" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json deleted file mode 100644 index 010a2c4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/DummyProtocol.json +++ /dev/null @@ -1,214 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "exchange", - "type": "address" - } - ], - "name": "LimitOrderExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "LimitOrderSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "LimitOrderWithdrawn", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "exchange", - "type": "address" - } - ], - "name": "executeLimitOrder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetContract", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "t0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "t1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "t2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "t3", - "type": "bytes32" - } - ], - "name": "getAdvancedLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "t0", - "type": "bytes32" - } - ], - "name": "getBasicLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "sendLimitedOrder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "price", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "withdrawLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json deleted file mode 100644 index 618c81c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ECDSA.json +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json deleted file mode 100644 index 24d1cb5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EIP712.json +++ /dev/null @@ -1,67 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidShortString", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "str", - "type": "string" - } - ], - "name": "StringTooLong", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "EIP712DomainChanged", - "type": "event" - }, - { - "inputs": [], - "name": "eip712Domain", - "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "verifyingContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json deleted file mode 100644 index e622e77..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSInterface.json +++ /dev/null @@ -1,218 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "label", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "NewOwner", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "resolver", - "type": "address" - } - ], - "name": "NewResolver", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "ttl", - "type": "uint64" - } - ], - "name": "NewTTL", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - } - ], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - } - ], - "name": "resolver", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "resolver", - "type": "address" - } - ], - "name": "setResolver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "label", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "setSubnodeOwner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "ttl", - "type": "uint64" - } - ], - "name": "setTTL", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - } - ], - "name": "ttl", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json deleted file mode 100644 index 44ea5ee..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ENSResolver.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "node", - "type": "bytes32" - } - ], - "name": "addr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json deleted file mode 100644 index 53fa000..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC165.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json deleted file mode 100644 index 048513c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20.json +++ /dev/null @@ -1,310 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC20InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC20InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC20InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "ERC20InvalidSpender", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json deleted file mode 100644 index d74eb99..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitor.json +++ /dev/null @@ -1,505 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "erc20TokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "duplicate", - "type": "address" - } - ], - "name": "DuplicateAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "ERC20TokenAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "topUpAddress", - "type": "address" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "oldWatchlist", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "newWatchlist", - "type": "address[]" - } - ], - "name": "WatchlistUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "getAccountInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpLevel", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getERC20TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedAddresses", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "erc20TokenAddress", - "type": "address" - } - ], - "name": "setERC20TokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "addresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "minBalances", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpLevels", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "needsFunding", - "type": "address[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json deleted file mode 100644 index 9f4be22..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20BalanceMonitorExposed.json +++ /dev/null @@ -1,523 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "erc20TokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriod", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "duplicate", - "type": "address" - } - ], - "name": "DuplicateAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "ERC20TokenAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "topUpAddress", - "type": "address" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "oldWatchlist", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "newWatchlist", - "type": "address[]" - } - ], - "name": "WatchlistUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "getAccountInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpLevel", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getERC20TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedAddresses", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "erc20TokenAddress", - "type": "address" - } - ], - "name": "setERC20TokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "name": "setLastTopUpXXXTestOnly", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "addresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "minBalances", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpLevels", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "needsFunding", - "type": "address[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json deleted file mode 100644 index 59f1c94..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Burnable.json +++ /dev/null @@ -1,341 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC20InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC20InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC20InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "ERC20InvalidSpender", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json deleted file mode 100644 index 23105cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock.json +++ /dev/null @@ -1,380 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "address", - "name": "initialAccount", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approveInternal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferInternal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json deleted file mode 100644 index 23105cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Mock6Decimals.json +++ /dev/null @@ -1,380 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "address", - "name": "initialAccount", - "type": "address" - }, - { - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approveInternal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferInternal", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json deleted file mode 100644 index 1e5f78e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC20Permit.json +++ /dev/null @@ -1,347 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json deleted file mode 100644 index 9a10657..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ERC677.json +++ /dev/null @@ -1,348 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json deleted file mode 100644 index dc9fef1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EmptyOracle.json +++ /dev/null @@ -1,213 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "cancelOracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "fulfillOracleRequest", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "getAuthorizationStatus", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "oracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "name": "setFulfillmentPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json deleted file mode 100644 index d37f36b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EntryPoint.json +++ /dev/null @@ -1,1242 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bool", - "name": "targetSuccess", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "targetResult", - "type": "bytes" - } - ], - "name": "ExecutionResult", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "opIndex", - "type": "uint256" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "FailedOp", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderAddressResult", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "SignatureValidationFailed", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prefund", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "sigFailed", - "type": "bool" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bytes", - "name": "paymasterContext", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.ReturnInfo", - "name": "returnInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "senderInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "factoryInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "paymasterInfo", - "type": "tuple" - } - ], - "name": "ValidationResult", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prefund", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "sigFailed", - "type": "bool" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bytes", - "name": "paymasterContext", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.ReturnInfo", - "name": "returnInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "senderInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "factoryInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "paymasterInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "stakeInfo", - "type": "tuple" - } - ], - "internalType": "struct IEntryPoint.AggregatorStakeInfo", - "name": "aggregatorInfo", - "type": "tuple" - } - ], - "name": "ValidationResultWithAggregation", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "factory", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "paymaster", - "type": "address" - } - ], - "name": "AccountDeployed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDeposit", - "type": "uint256" - } - ], - "name": "Deposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "SignatureAggregatorChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalStaked", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "name": "StakeLocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawTime", - "type": "uint256" - } - ], - "name": "StakeUnlocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "paymaster", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "actualGasCost", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "actualGasUsed", - "type": "uint256" - } - ], - "name": "UserOperationEvent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "revertReason", - "type": "bytes" - } - ], - "name": "UserOperationRevertReason", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "inputs": [], - "name": "SIG_VALIDATION_FAILED", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - } - ], - "name": "_validateSenderAndPaymaster", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - } - ], - "name": "addStake", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "depositTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getDepositInfo", - "outputs": [ - { - "components": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "internalType": "struct IStakeManager.DepositInfo", - "name": "info", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "name": "getSenderAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - } - ], - "name": "getUserOpHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "userOps", - "type": "tuple[]" - }, - { - "internalType": "contract IAggregator", - "name": "aggregator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", - "name": "opsPerAggregator", - "type": "tuple[]" - }, - { - "internalType": "address payable", - "name": "beneficiary", - "type": "address" - } - ], - "name": "handleAggregatedOps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "ops", - "type": "tuple[]" - }, - { - "internalType": "address payable", - "name": "beneficiary", - "type": "address" - } - ], - "name": "handleOps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "components": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "address", - "name": "paymaster", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - } - ], - "internalType": "struct EntryPoint.MemoryUserOp", - "name": "mUserOp", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "prefund", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "contextOffset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - } - ], - "internalType": "struct EntryPoint.UserOpInfo", - "name": "opInfo", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - } - ], - "name": "innerHandleOp", - "outputs": [ - { - "internalType": "uint256", - "name": "actualGasCost", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "op", - "type": "tuple" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "targetCallData", - "type": "bytes" - } - ], - "name": "simulateHandleOp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - } - ], - "name": "simulateValidation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unlockStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - } - ], - "name": "withdrawStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "withdrawAmount", - "type": "uint256" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json deleted file mode 100644 index 63ff459..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMap.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "EnumerableMapNonexistentKey", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json deleted file mode 100644 index 162046f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EnumerableMapBytes32.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "inputs": [], - "name": "NonexistentKeyError", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json deleted file mode 100644 index 20ad3fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ErroredVerifier.json +++ /dev/null @@ -1,340 +0,0 @@ -[ - { - "inputs": [], - "name": "FailedToActivateConfig", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToActivateFeed", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToDeactivateConfig", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToDeactivateFeed", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToGetLatestConfigDetails", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToGetLatestConfigDigestAndEpoch", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSetConfig", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToVerify", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "activateConfig", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "activateFeed", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "deactivateConfig", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "deactivateFeed", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "", - "type": "tuple[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "", - "type": "tuple[]" - } - ], - "name": "setConfigFromSource", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json deleted file mode 100644 index 67ccd39..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitor.json +++ /dev/null @@ -1,478 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "duplicate", - "type": "address" - } - ], - "name": "DuplicateAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountAdded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "getAccountInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalanceWei", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpAmountWei", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedAddresses", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "addresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "minBalancesWei", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmountsWei", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "needsFunding", - "type": "address[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json deleted file mode 100644 index d7114e3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/EthBalanceMonitorExposed.json +++ /dev/null @@ -1,496 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriod", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "duplicate", - "type": "address" - } - ], - "name": "DuplicateAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountAdded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "getAccountInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalanceWei", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpAmountWei", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedAddresses", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "name": "setLastTopUpXXXTestOnly", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "addresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "minBalancesWei", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmountsWei", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "needsFunding", - "type": "address[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json deleted file mode 100644 index b544978..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExecutionPrevention.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json deleted file mode 100644 index bbc6671..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedChannelConfigStore.json +++ /dev/null @@ -1,183 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "donId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "version", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "sha", - "type": "bytes32" - } - ], - "name": "NewChannelDefinition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "donId", - "type": "uint256" - } - ], - "name": "exposedReadChannelDefinitionStates", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "bytes32", - "name": "sha", - "type": "bytes32" - } - ], - "name": "setChannelDefinitions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json deleted file mode 100644 index 68a50f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedConfigurator.json +++ /dev/null @@ -1,288 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSigners", - "type": "uint256" - } - ], - "name": "ExcessSigners", - "type": "error" - }, - { - "inputs": [], - "name": "FaultToleranceMustBePositive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSigners", - "type": "uint256" - } - ], - "name": "InsufficientSigners", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "exposedReadConfigurationStates", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - } - ], - "internalType": "struct Configurator.ConfigurationState", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "isVerifier", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json deleted file mode 100644 index 8002cfd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5.json +++ /dev/null @@ -1,2155 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "calculatePaymentAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "nonce", - "type": "uint64" - } - ], - "name": "computeRequestIdExternal", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getActiveSubscriptionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - } - ], - "name": "getRandomnessFromProofExternal", - "outputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "internalType": "struct VRFCoordinatorV2_5.ProvingKey", - "name": "provingKey", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "internalType": "struct VRFCoordinatorV2_5.Output", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscriptionConfig", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "requestedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "internalType": "struct SubscriptionAPI.SubscriptionConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscriptionStruct", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - } - ], - "internalType": "struct SubscriptionAPI.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWithdrawableNativeTestingOnlyXXX", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWithdrawableTokensTestingOnlyXXX", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "isTargetRegisteredExternal", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "newBalance", - "type": "uint96" - } - ], - "name": "setTotalBalanceTestingOnlyXXX", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "newBalance", - "type": "uint96" - } - ], - "name": "setTotalNativeBalanceTestingOnlyXXX", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "newBalance", - "type": "uint96" - } - ], - "name": "setWithdrawableNativeTestingOnlyXXX", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "newBalance", - "type": "uint96" - } - ], - "name": "setWithdrawableTokensTestingOnlyXXX", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json deleted file mode 100644 index 8cf0307..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Arbitrum.json +++ /dev/null @@ -1,1858 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "calculatePaymentAmountLinkExternal", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "calculatePaymentAmountNativeExternal", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockNumberExternal", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockNumber", - "type": "uint64" - } - ], - "name": "getBlockhashExternal", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json deleted file mode 100644 index ac2a223..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVRFCoordinatorV2_5_Optimism.json +++ /dev/null @@ -1,1943 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCalculationMode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCalculationSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "calculatePaymentAmountLinkExternal", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "calculatePaymentAmountNativeExternal", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockNumberExternal", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockNumber", - "type": "uint64" - } - ], - "name": "getBlockhashExternal", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCalculationMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCoefficient", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json deleted file mode 100644 index de868ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExposedVerifier.json +++ /dev/null @@ -1,71 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_feedId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_contractAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "_configCount", - "type": "uint64" - }, - { - "internalType": "address[]", - "name": "_signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "_offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_encodedConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_encodedConfig", - "type": "bytes" - } - ], - "name": "exposedConfigDigestFromConfigData", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json deleted file mode 100644 index 8e08d03..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ExtendedVRFCoordinatorV2Interface.json +++ /dev/null @@ -1,309 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFeeConfig", - "outputs": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRequestConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json deleted file mode 100644 index 4acbde3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManager.json +++ /dev/null @@ -1,698 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_linkAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_nativeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_proxyAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_rewardManagerAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ExpiredReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDeposit", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDiscount", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidQuote", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReceivingAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSurcharge", - "type": "error" - }, - { - "inputs": [], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroDeficit", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct Common.Asset", - "name": "fee", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct Common.Asset", - "name": "reward", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "appliedDiscount", - "type": "uint256" - } - ], - "name": "DiscountApplied", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "indexed": false, - "internalType": "struct IRewardManager.FeePayment[]", - "name": "rewards", - "type": "tuple[]" - } - ], - "name": "InsufficientLink", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "linkQuantity", - "type": "uint256" - } - ], - "name": "LinkDeficitCleared", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newSurcharge", - "type": "uint64" - } - ], - "name": "NativeSurchargeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "SubscriberDiscountUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "Withdraw", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "address", - "name": "quoteAddress", - "type": "address" - } - ], - "name": "getFeeAndReward", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_nativeAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_proxyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_rewardManager", - "outputs": [ - { - "internalType": "contract IRewardManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "payLinkDeficit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_linkDeficit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_nativeSurcharge", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_subscriberDiscounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setFeeRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "surcharge", - "type": "uint64" - } - ], - "name": "setNativeSurcharge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json deleted file mode 100644 index 45384ec..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeeManagerProxy.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IFeeManager", - "name": "feeManager", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json deleted file mode 100644 index 6e3c561..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedConsumer.json +++ /dev/null @@ -1,214 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "feedAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AGGREGATOR", - "outputs": [ - { - "internalType": "contract AggregatorV2V3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "answer", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json deleted file mode 100644 index 5c017df..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FeedRegistryInterface.json +++ /dev/null @@ -1,803 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "denomination", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "latestAggregator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "previousAggregator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "nextPhaseId", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FeedConfirmed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "denomination", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "proposedAggregator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "currentAggregator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FeedProposed", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "confirmFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "answer", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "getCurrentPhaseId", - "outputs": [ - { - "internalType": "uint16", - "name": "currentPhaseId", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "getFeed", - "outputs": [ - { - "internalType": "contract AggregatorV2V3Interface", - "name": "aggregator", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - } - ], - "name": "getNextRoundId", - "outputs": [ - { - "internalType": "uint80", - "name": "nextRoundId", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint16", - "name": "phaseId", - "type": "uint16" - } - ], - "name": "getPhase", - "outputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "phaseId", - "type": "uint16" - }, - { - "internalType": "uint80", - "name": "startingAggregatorRoundId", - "type": "uint80" - }, - { - "internalType": "uint80", - "name": "endingAggregatorRoundId", - "type": "uint80" - } - ], - "internalType": "struct FeedRegistryInterface.Phase", - "name": "phase", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint16", - "name": "phaseId", - "type": "uint16" - } - ], - "name": "getPhaseFeed", - "outputs": [ - { - "internalType": "contract AggregatorV2V3Interface", - "name": "aggregator", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint16", - "name": "phaseId", - "type": "uint16" - } - ], - "name": "getPhaseRange", - "outputs": [ - { - "internalType": "uint80", - "name": "startingRoundId", - "type": "uint80" - }, - { - "internalType": "uint80", - "name": "endingRoundId", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - } - ], - "name": "getPreviousRoundId", - "outputs": [ - { - "internalType": "uint80", - "name": "previousRoundId", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "getProposedFeed", - "outputs": [ - { - "internalType": "contract AggregatorV2V3Interface", - "name": "proposedAggregator", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - } - ], - "name": "getRoundFeed", - "outputs": [ - { - "internalType": "contract AggregatorV2V3Interface", - "name": "aggregator", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "isFeedEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "answer", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "proposeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - }, - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - } - ], - "name": "proposedGetRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "id", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "proposedLatestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "id", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "base", - "type": "address" - }, - { - "internalType": "address", - "name": "quote", - "type": "address" - } - ], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json deleted file mode 100644 index b3129b3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Flags.json +++ /dev/null @@ -1,423 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "racAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "lacAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "FlagLowered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "FlagRaised", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previous", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "current", - "type": "address" - } - ], - "name": "LoweringAccessControllerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previous", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "current", - "type": "address" - } - ], - "name": "RaisingAccessControllerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "getFlag", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "subjects", - "type": "address[]" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bool[]", - "name": "", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "lowerFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "subjects", - "type": "address[]" - } - ], - "name": "lowerFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "loweringAccessController", - "outputs": [ - { - "internalType": "contract AccessControllerInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "raiseFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "subjects", - "type": "address[]" - } - ], - "name": "raiseFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "raisingAccessController", - "outputs": [ - { - "internalType": "contract AccessControllerInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "lacAddress", - "type": "address" - } - ], - "name": "setLoweringAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "racAddress", - "type": "address" - } - ], - "name": "setRaisingAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json deleted file mode 100644 index 0bba7df..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsInterface.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "getFlag", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bool[]", - "name": "", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "lowerFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "raiseFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "raiseFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "setRaisingAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json deleted file mode 100644 index f42ff6d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FlagsTestHelper.json +++ /dev/null @@ -1,64 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "flagsContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "flags", - "outputs": [ - { - "internalType": "contract Flags", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subject", - "type": "address" - } - ], - "name": "getFlag", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "subjects", - "type": "address[]" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bool[]", - "name": "", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json deleted file mode 100644 index e2cf0ce..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBilling.json +++ /dev/null @@ -1,533 +0,0 @@ -[ - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "usdLink", - "type": "int256" - } - ], - "name": "InvalidUsdLinkPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoTransmittersSet", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouter", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouterOwner", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "RouterMustBeSet", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "inputs": [], - "name": "UnsupportedRequestDataVersion", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "CommitmentDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "indexed": false, - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1FeeShareWei", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "callbackCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "donFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "adminFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "operationFeeJuels", - "type": "uint72" - } - ], - "name": "RequestBilled", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "deleteCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - } - ], - "name": "estimateCost", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "getDONFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperationFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUsdPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWeiPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "oracleWithdrawAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json deleted file mode 100644 index 847c66f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsBillingRegistryEventsMock.json +++ /dev/null @@ -1,839 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "signerPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "transmitterPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalCost", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "BillingEnd", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "don", - "type": "address" - }, - { - "internalType": "uint96", - "name": "donFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "registryFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "estimatedCost", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct FunctionsBillingRegistryEventsMock.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "BillingStart", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasAfterPaymentCalculation", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasOverhead", - "type": "uint32" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "emitAuthorizedSendersChanged", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "signerPayment", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "transmitterPayment", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "totalCost", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "emitBillingEnd", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "don", - "type": "address" - }, - { - "internalType": "uint96", - "name": "donFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "registryFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "estimatedCost", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - } - ], - "internalType": "struct FunctionsBillingRegistryEventsMock.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "emitBillingStart", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasAfterPaymentCalculation", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "gasOverhead", - "type": "uint32" - } - ], - "name": "emitConfigSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "emitFundsRecovered", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "emitInitialized", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitPaused", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "emitRequestTimedOut", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "emitSubscriptionCanceled", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "emitSubscriptionConsumerAdded", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "emitSubscriptionConsumerRemoved", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "emitSubscriptionCreated", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "emitSubscriptionFunded", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitSubscriptionOwnerTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitSubscriptionOwnerTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitUnpaused", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json deleted file mode 100644 index 450f733..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClient.json +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json deleted file mode 100644 index 7bef985..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientExample.json +++ /dev/null @@ -1,280 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "UnexpectedRequestID", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "inputs": [], - "name": "MAX_CALLBACK_GAS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastError", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastErrorLength", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastResponse", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastResponseLength", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedSecretsReferences", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "jobId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json deleted file mode 100644 index 4eed938..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientHarness.json +++ /dev/null @@ -1,460 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "result", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "ResponseReceived", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRouter_HARNESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "bytesArgs", - "type": "bytes[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestBytes", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "bytesArgs", - "type": "bytes[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "uint8", - "name": "slotId", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "slotVersion", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestToProposedWithDONHostedSecrets", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "uint8", - "name": "slotId", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "slotVersion", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestWithDONHostedSecrets", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest_HARNESS", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json deleted file mode 100644 index 11784d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientTestHelper.json +++ /dev/null @@ -1,375 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "FulfillRequestInvoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "sourceCode", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "SendRequestInvoked", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "acceptor", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - } - ], - "name": "acceptTermsOfService", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "bytesArgs", - "type": "bytes[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourceCode", - "type": "string" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourceCode", - "type": "string" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendSimpleRequestWithJavaScript", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "on", - "type": "bool" - } - ], - "name": "setDoInvalidOperation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "on", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "setDoInvalidReentrantOperation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "on", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "setDoValidReentrantOperation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "on", - "type": "bool" - } - ], - "name": "setRevertFulfillRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "setRevertFulfillRequestMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json deleted file mode 100644 index 92d6d88..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientUpgradeHelper.json +++ /dev/null @@ -1,413 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "result", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "ResponseReceived", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "bytesArgs", - "type": "bytes[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestBytes", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "bytes[]", - "name": "bytesArgs", - "type": "bytes[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "uint8", - "name": "slotId", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "slotVersion", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestToProposedWithDONHostedSecrets", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "uint8", - "name": "slotId", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "slotVersion", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendRequestWithDONHostedSecrets", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json deleted file mode 100644 index 03a59d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsClientWithEmptyCallback.json +++ /dev/null @@ -1,161 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "FulfillRequestInvoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "sourceCode", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "SendRequestInvoked", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourceCode", - "type": "string" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "sendSimpleRequestWithJavaScript", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json deleted file mode 100644 index ac8cfd2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinator.json +++ /dev/null @@ -1,1267 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address", - "name": "linkToNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "linkToUsdFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyPublicKey", - "type": "error" - }, - { - "inputs": [], - "name": "InconsistentReportData", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "usdLink", - "type": "int256" - } - ], - "name": "InvalidUsdLinkPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoTransmittersSet", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouter", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouterOwner", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "ReportInvalid", - "type": "error" - }, - { - "inputs": [], - "name": "RouterMustBeSet", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedPublicKeyChange", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "inputs": [], - "name": "UnsupportedRequestDataVersion", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "CommitmentDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "indexed": false, - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "callbackGasLimit", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "indexed": false, - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "OracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "OracleResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1FeeShareWei", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "callbackCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "donFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "adminFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "operationFeeJuels", - "type": "uint72" - } - ], - "name": "RequestBilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "deleteCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - } - ], - "name": "estimateCost", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "getDONFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDONPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperationFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getThresholdPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUsdPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWeiPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "oracleWithdrawAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "donPublicKey", - "type": "bytes" - } - ], - "name": "setDONPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "thresholdPublicKey", - "type": "bytes" - } - ], - "name": "setThresholdPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "availableBalance", - "type": "uint96" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - } - ], - "internalType": "struct FunctionsResponse.RequestMeta", - "name": "request", - "type": "tuple" - } - ], - "name": "startRequest", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "transmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json deleted file mode 100644 index 0f719ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorHarness.json +++ /dev/null @@ -1,1664 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address", - "name": "linkToNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "linkToUsdFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyPublicKey", - "type": "error" - }, - { - "inputs": [], - "name": "InconsistentReportData", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "usdLink", - "type": "int256" - } - ], - "name": "InvalidUsdLinkPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoTransmittersSet", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouter", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouterOwner", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "ReportInvalid", - "type": "error" - }, - { - "inputs": [], - "name": "RouterMustBeSet", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedPublicKeyChange", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "inputs": [], - "name": "UnsupportedRequestDataVersion", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "CommitmentDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "indexed": false, - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "callbackGasLimit", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "indexed": false, - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "OracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "OracleResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1FeeShareWei", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "callbackCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "donFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "adminFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "operationFeeJuels", - "type": "uint72" - } - ], - "name": "RequestBilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - } - ], - "name": "beforeSetConfig_HARNESS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "operationFee", - "type": "uint72" - } - ], - "name": "calculateCostEstimate_HARNESS", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "deleteCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "disperseFeePool_HARNESS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - } - ], - "name": "estimateCost", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "onchainMetadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainMetadata", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "reportBatchSize", - "type": "uint8" - } - ], - "name": "fulfillAndBill_HARNESS", - "outputs": [ - { - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "getDONFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDONPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkToNativeFeed_HARNESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkToUsdFeed_HARNESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperationFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRouter_HARNESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getThresholdPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters_HARNESS", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUsdPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWeiPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "node", - "type": "address" - } - ], - "name": "isTransmitter_HARNESS", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onlyOwner_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "oracleWithdrawAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner_HARNESS", - "outputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32[]", - "name": "requestIds", - "type": "bytes32[]" - }, - { - "internalType": "bytes[]", - "name": "results", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "errors", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "onchainMetadata", - "type": "bytes[]" - }, - { - "internalType": "bytes[]", - "name": "offchainMetadata", - "type": "bytes[]" - } - ], - "internalType": "struct OCR2Base.DecodedReport", - "name": "decodedReport", - "type": "tuple" - } - ], - "name": "report_HARNESS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "donPublicKey", - "type": "bytes" - } - ], - "name": "setDONPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "thresholdPublicKey", - "type": "bytes" - } - ], - "name": "setThresholdPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "availableBalance", - "type": "uint96" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - } - ], - "internalType": "struct FunctionsResponse.RequestMeta", - "name": "request", - "type": "tuple" - } - ], - "name": "startBilling_HARNESS", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - }, - { - "internalType": "uint72", - "name": "operationFee", - "type": "uint72" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "availableBalance", - "type": "uint96" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - } - ], - "internalType": "struct FunctionsResponse.RequestMeta", - "name": "request", - "type": "tuple" - } - ], - "name": "startRequest", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "transmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json deleted file mode 100644 index aba6e09..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsCoordinatorTestHelper.json +++ /dev/null @@ -1,1318 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address", - "name": "linkToNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "linkToUsdFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyPublicKey", - "type": "error" - }, - { - "inputs": [], - "name": "InconsistentReportData", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "usdLink", - "type": "int256" - } - ], - "name": "InvalidUsdLinkPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoTransmittersSet", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouter", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouterOwner", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "ReportInvalid", - "type": "error" - }, - { - "inputs": [], - "name": "RouterMustBeSet", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedPublicKeyChange", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "inputs": [], - "name": "UnsupportedRequestDataVersion", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "CommitmentDeleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "indexed": false, - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "callbackGasLimit", - "type": "uint64" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "indexed": false, - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "OracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "OracleResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "l1FeeShareWei", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "callbackCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "donFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "adminFeeJuels", - "type": "uint72" - }, - { - "indexed": false, - "internalType": "uint72", - "name": "operationFeeJuels", - "type": "uint72" - } - ], - "name": "RequestBilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - } - ], - "name": "callReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "address", - "name": "secondSigner", - "type": "address" - } - ], - "name": "callReportMultipleSigners", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "deleteCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - } - ], - "name": "estimateCost", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "getDONFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getDONPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperationFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getThresholdPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUsdPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWeiPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "oracleWithdrawAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "donPublicKey", - "type": "bytes" - } - ], - "name": "setDONPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "thresholdPublicKey", - "type": "bytes" - } - ], - "name": "setThresholdPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "availableBalance", - "type": "uint96" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - } - ], - "internalType": "struct FunctionsResponse.RequestMeta", - "name": "request", - "type": "tuple" - } - ], - "name": "startRequest", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "transmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentGasPriceOverEstimationBP", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "feedStalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadBeforeCallback", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasOverheadAfterCallback", - "type": "uint32" - }, - { - "internalType": "uint40", - "name": "minimumEstimateGasPriceWei", - "type": "uint40" - }, - { - "internalType": "uint16", - "name": "maxSupportedRequestDataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "fallbackUsdPerUnitLink", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "fallbackUsdPerUnitLinkDecimals", - "type": "uint8" - }, - { - "internalType": "uint224", - "name": "fallbackNativePerUnitLink", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "requestTimeoutSeconds", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "donFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "operationFeeCentsUsd", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "transmitTxSizeBytes", - "type": "uint16" - } - ], - "internalType": "struct FunctionsBillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json deleted file mode 100644 index a9f3b78..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsLoadTestClient.json +++ /dev/null @@ -1,421 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyRouterCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "inputs": [], - "name": "MAX_CALLBACK_GAS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getStats", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "lastError", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastResponse", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "resetStats", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "times", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "cborEncodedRequest", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendEncodedRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "times", - "type": "uint32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedSecretsReferences", - "type": "bytes" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "times", - "type": "uint32" - }, - { - "internalType": "string", - "name": "source", - "type": "string" - }, - { - "internalType": "uint8", - "name": "slotId", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "slotVersion", - "type": "uint64" - }, - { - "internalType": "string[]", - "name": "args", - "type": "string[]" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestWithDONHostedSecrets", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalEmptyResponses", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalFailedResponses", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalRequests", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSucceededResponses", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json deleted file mode 100644 index 54abd34..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsOracleEventsMock.json +++ /dev/null @@ -1,586 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "AuthorizedSendersActive", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "AuthorizedSendersDeactive", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "InvalidRequestID", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "OracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "OracleResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "ResponseTransmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "UserCallbackError", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelData", - "type": "bytes" - } - ], - "name": "UserCallbackRawError", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitAuthorizedSendersActive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "emitAuthorizedSendersChanged", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitAuthorizedSendersDeactive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "emitConfigSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "emitInitialized", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "emitInvalidRequestID", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "emitOracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "emitOracleResponse", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "emitResponseTransmitted", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "emitTransmitted", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "emitUserCallbackError", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "lowLevelData", - "type": "bytes" - } - ], - "name": "emitUserCallbackRawError", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json deleted file mode 100644 index 61a5674..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRequest.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "inputs": [], - "name": "REQUEST_DATA_VERSION", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json deleted file mode 100644 index 305caa0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouter.json +++ /dev/null @@ -1,1720 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkToken", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "config", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "CannotRemoveWithPendingRequests", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "DuplicateRequestId", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyRequestData", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "limit", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "IdentifierIsReserved", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "currentBalanceJuels", - "type": "uint96" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "value", - "type": "uint8" - } - ], - "name": "InvalidGasFlagValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidProposal", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeProposedOwner", - "type": "error" - }, - { - "inputs": [], - "name": "MustBeSubscriptionOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RouteNotFound", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderMustAcceptTermsOfService", - "type": "error" - }, - { - "inputs": [], - "name": "TimeoutNotExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maximumConsumers", - "type": "uint16" - } - ], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "indexed": false, - "internalType": "struct FunctionsRouter.Config", - "name": "", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "proposedContractSetId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetFromAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetToAddress", - "type": "address" - } - ], - "name": "ContractProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "ContractUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - } - ], - "name": "RequestNotProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "callbackReturnData", - "type": "bytes" - } - ], - "name": "RequestProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - } - ], - "name": "RequestStart", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "MAX_CALLBACK_RETURN_BYTES", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "createSubscriptionWithConsumer", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "costWithoutCallback", - "type": "uint96" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "fulfill", - "outputs": [ - { - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFee", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowListId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getConsumer", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - } - ], - "internalType": "struct IFunctionsSubscriptions.Consumer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getProposedContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProposedContractSet", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionIdStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subscriptionIdEnd", - "type": "uint64" - } - ], - "name": "getSubscriptionsInRange", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription[]", - "name": "subscriptions", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "isValidCallbackGasLimit", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "ownerWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proposedContractSetIds", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "proposedContractSetAddresses", - "type": "address[]" - } - ], - "name": "proposeContractsUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "proposeSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "allowListId", - "type": "bytes32" - } - ], - "name": "setAllowListId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "name": "setFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment[]", - "name": "requestsToTimeoutByCommitment", - "type": "tuple[]" - } - ], - "name": "timeoutRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "updateContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json deleted file mode 100644 index 1587fb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsRouterHarness.json +++ /dev/null @@ -1,1772 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkToken", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "config", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "CannotRemoveWithPendingRequests", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "DuplicateRequestId", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyRequestData", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "limit", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "IdentifierIsReserved", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "currentBalanceJuels", - "type": "uint96" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "value", - "type": "uint8" - } - ], - "name": "InvalidGasFlagValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidProposal", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeProposedOwner", - "type": "error" - }, - { - "inputs": [], - "name": "MustBeSubscriptionOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "RouteNotFound", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderMustAcceptTermsOfService", - "type": "error" - }, - { - "inputs": [], - "name": "TimeoutNotExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maximumConsumers", - "type": "uint16" - } - ], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "indexed": false, - "internalType": "struct FunctionsRouter.Config", - "name": "", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "proposedContractSetId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetFromAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetToAddress", - "type": "address" - } - ], - "name": "ContractProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "ContractUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - } - ], - "name": "RequestNotProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "callbackReturnData", - "type": "bytes" - } - ], - "name": "RequestProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - } - ], - "name": "RequestStart", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "MAX_CALLBACK_RETURN_BYTES", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "createSubscriptionWithConsumer", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "costWithoutFulfillment", - "type": "uint96" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "fulfill", - "outputs": [ - { - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "resultCode", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFee", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowListId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getConsumer", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - } - ], - "internalType": "struct IFunctionsSubscriptions.Consumer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMaxConsumers_HARNESS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getProposedContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProposedContractSet", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionDepositDetails_HARNESS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionIdStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subscriptionIdEnd", - "type": "uint64" - } - ], - "name": "getSubscriptionsInRange", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription[]", - "name": "subscriptions", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "isValidCallbackGasLimit", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "onlyRouterOwner_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "onlySenderThatAcceptedToS_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "ownerWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proposedContractSetIds", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "proposedContractSetAddresses", - "type": "address[]" - } - ], - "name": "proposeContractsUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "proposeSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "allowListId", - "type": "bytes32" - } - ], - "name": "setAllowListId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "name": "setFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment[]", - "name": "requestsToTimeoutByCommitment", - "type": "tuple[]" - } - ], - "name": "timeoutRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - }, - { - "internalType": "uint16", - "name": "subscriptionDepositMinimumRequests", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "subscriptionDepositJuels", - "type": "uint72" - } - ], - "internalType": "struct FunctionsRouter.Config", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "updateContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "whenNotPaused_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json deleted file mode 100644 index 79d8d54..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptions.json +++ /dev/null @@ -1,761 +0,0 @@ -[ - { - "inputs": [], - "name": "CannotRemoveWithPendingRequests", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "currentBalanceJuels", - "type": "uint96" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeProposedOwner", - "type": "error" - }, - { - "inputs": [], - "name": "MustBeSubscriptionOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "TimeoutNotExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maximumConsumers", - "type": "uint16" - } - ], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "createSubscriptionWithConsumer", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getConsumer", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - } - ], - "internalType": "struct IFunctionsSubscriptions.Consumer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionIdStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subscriptionIdEnd", - "type": "uint64" - } - ], - "name": "getSubscriptionsInRange", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription[]", - "name": "subscriptions", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "ownerWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "proposeSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "name": "setFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment[]", - "name": "requestsToTimeoutByCommitment", - "type": "tuple[]" - } - ], - "name": "timeoutRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json deleted file mode 100644 index 23b9975..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsSubscriptionsHarness.json +++ /dev/null @@ -1,887 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "CannotRemoveWithPendingRequests", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "currentBalanceJuels", - "type": "uint96" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeProposedOwner", - "type": "error" - }, - { - "inputs": [], - "name": "MustBeSubscriptionOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "TimeoutNotExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maximumConsumers", - "type": "uint16" - } - ], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "createSubscriptionWithConsumer", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getConsumer", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - } - ], - "internalType": "struct IFunctionsSubscriptions.Consumer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionIdStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subscriptionIdEnd", - "type": "uint64" - } - ], - "name": "getSubscriptionsInRange", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription[]", - "name": "subscriptions", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "isAllowedConsumer_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "isExistingSubscription_HARNESS", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - } - ], - "name": "markRequestInFlight_HARNESS", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "ownerWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint96", - "name": "adminFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasUsed", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "costWithoutCallbackJuels", - "type": "uint96" - } - ], - "name": "pay_HARNESS", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "callbackGasCostJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "totalCostJuels", - "type": "uint96" - } - ], - "internalType": "struct FunctionsSubscriptions.Receipt", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "proposeSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "name": "setFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment[]", - "name": "requestsToTimeoutByCommitment", - "type": "tuple[]" - } - ], - "name": "timeoutRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json deleted file mode 100644 index 56284be..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsTestHelper.json +++ /dev/null @@ -1,93 +0,0 @@ -[ - { - "inputs": [], - "name": "EmptyArgs", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySecrets", - "type": "error" - }, - { - "inputs": [], - "name": "EmptySource", - "type": "error" - }, - { - "inputs": [], - "name": "NoInlineSecrets", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "RequestData", - "type": "event" - }, - { - "inputs": [], - "name": "addEmptyArgs", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "secrets", - "type": "bytes" - } - ], - "name": "addSecretsReference", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "arg1", - "type": "string" - }, - { - "internalType": "string", - "name": "arg2", - "type": "string" - } - ], - "name": "addTwoArgs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "closeEvent", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "sourceCode", - "type": "string" - } - ], - "name": "initializeRequestForInlineJavaScript", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json deleted file mode 100644 index 587f960..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/FunctionsV1EventsMock.json +++ /dev/null @@ -1,957 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - } - ], - "indexed": false, - "internalType": "struct FunctionsV1EventsMock.Config", - "name": "param1", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "proposedContractSetId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetFromAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "proposedContractSetToAddress", - "type": "address" - } - ], - "name": "ContractProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "ContractUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "resultCode", - "type": "uint8" - } - ], - "name": "RequestNotProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalCostJuels", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "resultCode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "callbackReturnData", - "type": "bytes" - } - ], - "name": "RequestProcessed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - } - ], - "name": "RequestStart", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "RequestTimedOut", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint16", - "name": "maxConsumersPerSubscription", - "type": "uint16" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "bytes4", - "name": "handleOracleFulfillmentSelector", - "type": "bytes4" - }, - { - "internalType": "uint16", - "name": "gasForCallExactCheck", - "type": "uint16" - }, - { - "internalType": "uint32[]", - "name": "maxCallbackGasLimits", - "type": "uint32[]" - } - ], - "internalType": "struct FunctionsV1EventsMock.Config", - "name": "param1", - "type": "tuple" - } - ], - "name": "emitConfigUpdated", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "proposedContractSetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "proposedContractSetFromAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "proposedContractSetToAddress", - "type": "address" - } - ], - "name": "emitContractProposed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitContractUpdated", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "emitFundsRecovered", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitPaused", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "uint8", - "name": "resultCode", - "type": "uint8" - } - ], - "name": "emitRequestNotProcessed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "totalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "uint8", - "name": "resultCode", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callbackReturnData", - "type": "bytes" - } - ], - "name": "emitRequestProcessed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "address", - "name": "requestInitiator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - } - ], - "name": "emitRequestStart", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "emitRequestTimedOut", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "fundsRecipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fundsAmount", - "type": "uint256" - } - ], - "name": "emitSubscriptionCanceled", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "emitSubscriptionConsumerAdded", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "emitSubscriptionConsumerRemoved", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "emitSubscriptionCreated", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "emitSubscriptionFunded", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitSubscriptionOwnerTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitSubscriptionOwnerTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "emitUnpaused", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json deleted file mode 100644 index e7c2127..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasConsumer.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "inputs": [], - "name": "consumeAllGas", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "throwOutOfGasError", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json deleted file mode 100644 index 8b220ab..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasGuzzlingConsumer.json +++ /dev/null @@ -1,273 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_specId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "price", - "type": "bytes32" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - } - ], - "name": "addExternalRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "_callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "_expiration", - "type": "uint256" - } - ], - "name": "cancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_price", - "type": "bytes32" - } - ], - "name": "fulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "gassyFulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "gassyMultiWordFulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "gassyMultiWordRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "gassyRequestEthereumPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPrice", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestEthereumPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_currency", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_callback", - "type": "address" - } - ], - "name": "requestEthereumPriceByCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json deleted file mode 100644 index c5f29ef..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GasPriceOracle.json +++ /dev/null @@ -1,242 +0,0 @@ -[ - { - "inputs": [], - "name": "DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseFeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blobBaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blobBaseFeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "gasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_unsignedTxSize", - "type": "uint256" - } - ], - "name": "getL1FeeUpperBound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1GasUsed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isEcotone", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isFjord", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1BaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "setEcotone", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "setFjord", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json deleted file mode 100644 index 31660a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GenericReceiver.json +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bool", - "name": "toRevert", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "inputs": [], - "name": "s_toRevert", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "setErr", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "toRevert", - "type": "bool" - } - ], - "name": "setRevert", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json deleted file mode 100644 index f849c9d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/GetterSetter.json +++ /dev/null @@ -1,190 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "b32", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "u256", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "b322", - "type": "bytes32" - } - ], - "name": "Output", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "SetBytes", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - } - ], - "name": "SetBytes32", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "SetUint256", - "type": "event" - }, - { - "inputs": [], - "name": "getBytes", - "outputs": [ - { - "internalType": "bytes", - "name": "_value", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_value", - "type": "bytes" - } - ], - "name": "requestedBytes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "name": "requestedBytes32", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "requestedUint256", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_value", - "type": "bytes" - } - ], - "name": "setBytes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "name": "setBytes32", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "setUint256", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json deleted file mode 100644 index edf4dea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Greeter.json +++ /dev/null @@ -1,117 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "greeting", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_greeting", - "type": "string" - } - ], - "name": "setGreeting", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "triggerRevert", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json deleted file mode 100644 index 62b9b47..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/HeartbeatRequester.json +++ /dev/null @@ -1,184 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "HeartbeatNotPermitted", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "permittedCaller", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newProxy", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "oldProxy", - "type": "address" - } - ], - "name": "HeartbeatPermitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "permittedCaller", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "removedProxy", - "type": "address" - } - ], - "name": "HeartbeatRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proxy", - "type": "address" - } - ], - "name": "getAggregatorAndRequestHeartbeat", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "permittedCaller", - "type": "address" - }, - { - "internalType": "contract IAggregatorProxy", - "name": "proxy", - "type": "address" - } - ], - "name": "permitHeartbeat", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "permittedCaller", - "type": "address" - } - ], - "name": "removeHeartbeat", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json deleted file mode 100644 index 45fe1fb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAbstractArbitrumTokenGateway.json +++ /dev/null @@ -1,163 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1ERC20", - "type": "address" - } - ], - "name": "calculateL2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counterpartGateway", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeInboundTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getOutboundCalldata", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "router", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json deleted file mode 100644 index eb8c7b2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessControl.json +++ /dev/null @@ -1,195 +0,0 @@ -[ - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json deleted file mode 100644 index d018c95..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccessController.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json deleted file mode 100644 index 98ebff4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAccount.json +++ /dev/null @@ -1,88 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "missingAccountFunds", - "type": "uint256" - } - ], - "name": "validateUserOp", - "outputs": [ - { - "internalType": "uint256", - "name": "validationData", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json deleted file mode 100644 index 3883c6a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregator.json +++ /dev/null @@ -1,229 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "userOps", - "type": "tuple[]" - } - ], - "name": "aggregateSignatures", - "outputs": [ - { - "internalType": "bytes", - "name": "aggregatedSignature", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "userOps", - "type": "tuple[]" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "validateSignatures", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - } - ], - "name": "validateUserOpSignature", - "outputs": [ - { - "internalType": "bytes", - "name": "sigForUserOp", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json deleted file mode 100644 index 4efa177..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAggregatorProxy.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "aggregator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json deleted file mode 100644 index 5f319cb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbRollupCore.json +++ /dev/null @@ -1,880 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "sendRoot", - "type": "bytes32" - } - ], - "name": "NodeConfirmed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "parentNodeHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "nodeHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "executionHash", - "type": "bytes32" - }, - { - "components": [ - { - "components": [ - { - "components": [ - { - "internalType": "bytes32[2]", - "name": "bytes32Vals", - "type": "bytes32[2]" - }, - { - "internalType": "uint64[2]", - "name": "u64Vals", - "type": "uint64[2]" - } - ], - "internalType": "struct GlobalState", - "name": "globalState", - "type": "tuple" - }, - { - "internalType": "enum MachineStatus", - "name": "machineStatus", - "type": "uint8" - } - ], - "internalType": "struct ExecutionState", - "name": "beforeState", - "type": "tuple" - }, - { - "components": [ - { - "components": [ - { - "internalType": "bytes32[2]", - "name": "bytes32Vals", - "type": "bytes32[2]" - }, - { - "internalType": "uint64[2]", - "name": "u64Vals", - "type": "uint64[2]" - } - ], - "internalType": "struct GlobalState", - "name": "globalState", - "type": "tuple" - }, - { - "internalType": "enum MachineStatus", - "name": "machineStatus", - "type": "uint8" - } - ], - "internalType": "struct ExecutionState", - "name": "afterState", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "numBlocks", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Assertion", - "name": "assertion", - "type": "tuple" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "afterInboxBatchAcc", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "wasmModuleRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "inboxMaxCount", - "type": "uint256" - } - ], - "name": "NodeCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - } - ], - "name": "NodeRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "challengeIndex", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "asserter", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "challenger", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "challengedNode", - "type": "uint64" - } - ], - "name": "RollupChallengeStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "machineHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "name": "RollupInitialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "finalBalance", - "type": "uint256" - } - ], - "name": "UserStakeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "finalBalance", - "type": "uint256" - } - ], - "name": "UserWithdrawableFundsUpdated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "amountStaked", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "baseStake", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "contract IBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "chainId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "challengeManager", - "outputs": [ - { - "internalType": "contract IChallengeManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "confirmPeriodBlocks", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "currentChallenge", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "extraChallengeTimeBlocks", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "firstUnresolvedNode", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - } - ], - "name": "getNode", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "stateHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "challengeHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "confirmData", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "prevNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "deadlineBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "noChildConfirmedBeforeBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "stakerCount", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "childStakerCount", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "firstChildBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestChildNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "createdAtBlock", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "nodeHash", - "type": "bytes32" - } - ], - "internalType": "struct Node", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - } - ], - "name": "getNodeCreationBlockForLogLookup", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "getStaker", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "amountStaked", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "index", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestStakedNode", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "currentChallenge", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "isStaked", - "type": "bool" - } - ], - "internalType": "struct IRollupCore.Staker", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "stakerNum", - "type": "uint64" - } - ], - "name": "getStakerAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "isStaked", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "isValidator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "isZombie", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastStakeBlock", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfirmed", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestNodeCreated", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "latestStakedNode", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "loserStakeEscrow", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minimumAssertionPeriod", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "nodeNum", - "type": "uint64" - }, - { - "internalType": "address", - "name": "staker", - "type": "address" - } - ], - "name": "nodeHasStaker", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "outbox", - "outputs": [ - { - "internalType": "contract IOutbox", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rollupEventInbox", - "outputs": [ - { - "internalType": "contract IRollupEventInbox", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sequencerInbox", - "outputs": [ - { - "internalType": "contract ISequencerInbox", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "stakeToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "stakerCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "validatorWhitelistDisabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "wasmModuleRoot", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "withdrawableFunds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "zombieNum", - "type": "uint256" - } - ], - "name": "zombieAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "zombieCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "zombieNum", - "type": "uint256" - } - ], - "name": "zombieLatestStakedNode", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json deleted file mode 100644 index 3837092..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbSys.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawEth", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json deleted file mode 100644 index 086ef65..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumDelayedInbox.json +++ /dev/null @@ -1,407 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "InboxMessageDelivered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - } - ], - "name": "InboxMessageDeliveredFromOrigin", - "type": "event" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "contract IBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - } - ], - "name": "calculateRetryableSubmissionFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createRetryableTicket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createRetryableTicketNoRefundAliasRewrite", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - } - ], - "name": "depositEth", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGasPrice", - "type": "uint256" - } - ], - "name": "depositEthRetryable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendL1FundedContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendL1FundedUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "messageData", - "type": "bytes" - } - ], - "name": "sendL2Message", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json deleted file mode 100644 index 0e68e95..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumGatewayRouter.json +++ /dev/null @@ -1,232 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newDefaultGateway", - "type": "address" - } - ], - "name": "DefaultGatewayUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "gateway", - "type": "address" - } - ], - "name": "GatewaySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_userFrom", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_userTo", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "gateway", - "type": "address" - } - ], - "name": "TransferRouted", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "l1ERC20", - "type": "address" - } - ], - "name": "calculateL2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "defaultGateway", - "outputs": [ - { - "internalType": "address", - "name": "gateway", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeInboundTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "getGateway", - "outputs": [ - { - "internalType": "address", - "name": "gateway", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getOutboundCalldata", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json deleted file mode 100644 index d71213f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumInbox.json +++ /dev/null @@ -1,326 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "InboxMessageDelivered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - } - ], - "name": "InboxMessageDeliveredFromOrigin", - "type": "event" - }, - { - "inputs": [], - "name": "allowListEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "contract IBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - } - ], - "name": "calculateRetryableSubmissionFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProxyAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IBridge", - "name": "_bridge", - "type": "address" - }, - { - "internalType": "contract ISequencerInbox", - "name": "_sequencerInbox", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "isAllowed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxDataSize", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "messageData", - "type": "bytes" - } - ], - "name": "sendL2Message", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "messageData", - "type": "bytes" - } - ], - "name": "sendL2MessageFromOrigin", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sequencerInbox", - "outputs": [ - { - "internalType": "contract ISequencerInbox", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "user", - "type": "address[]" - }, - { - "internalType": "bool[]", - "name": "val", - "type": "bool[]" - } - ], - "name": "setAllowList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_allowListEnabled", - "type": "bool" - } - ], - "name": "setAllowListEnabled", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json deleted file mode 100644 index 0f841b8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumL1GatewayRouter.json +++ /dev/null @@ -1,304 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1ERC20", - "type": "address" - } - ], - "name": "calculateL2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeInboundTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getOutboundCalldata", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "inbox", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_refundTo", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransferCustomRefund", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_gateway", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_creditBackAddress", - "type": "address" - } - ], - "name": "setGateway", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_gateway", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxSubmissionCost", - "type": "uint256" - } - ], - "name": "setGateway", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json deleted file mode 100644 index 4cc15e0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IArbitrumTokenGateway.json +++ /dev/null @@ -1,137 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1ERC20", - "type": "address" - } - ], - "name": "calculateL2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeInboundTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getOutboundCalldata", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json deleted file mode 100644 index 57336ef..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAuthorizedReceiver.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "inputs": [], - "name": "getAuthorizedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isAuthorizedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSenders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json deleted file mode 100644 index 1cd5abe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationForwarder.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasAmount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRegistry", - "outputs": [ - { - "internalType": "contract IAutomationRegistryConsumer", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTarget", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newRegistry", - "type": "address" - } - ], - "name": "updateRegistry", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json deleted file mode 100644 index 07e8ba9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryConsumer.json +++ /dev/null @@ -1,115 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json deleted file mode 100644 index db2c933..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster.json +++ /dev/null @@ -1,2725 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataFixedBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataPerSignerBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "internalType": "struct AutomationRegistryBase2_2.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "uint8", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json deleted file mode 100644 index c676289..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationRegistryMaster2_3.json +++ /dev/null @@ -1,3606 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct AutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableOffchainPayments", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getAvailableERC20ForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getBillingConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverrides", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverridesEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "getBillingTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBillingTokens", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackNativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getHotVars", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reentrancyGuard", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.HotVars", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNativeUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNumUpkeeps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPayoutMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getReserveAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStorage", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - } - ], - "internalType": "struct AutomationRegistryBase2_3.Storage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataFixedBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitCalldataPerSignerBytesOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmittersWithPayees", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transmitterAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "payeeAddress", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNativeTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "removeBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingOverrides", - "name": "billingOverrides", - "type": "tuple" - } - ], - "name": "setBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct AutomationRegistryBase2_3.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "address[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct AutomationRegistryBase2_3.BillingConfig[]", - "name": "billingConfigs", - "type": "tuple[]" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "uint8", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "settleNOPsOffchain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "supportsBillingToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawERC20Fees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json deleted file mode 100644 index 16f31aa..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IAutomationV21PlusCommon.json +++ /dev/null @@ -1,1441 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json deleted file mode 100644 index 31fc615..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridge.json +++ /dev/null @@ -1,227 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageIndex", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "beforeInboxAcc", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "inbox", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "kind", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "messageDataHash", - "type": "bytes32" - } - ], - "name": "MessageDelivered", - "type": "event" - }, - { - "inputs": [], - "name": "activeOutbox", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "inbox", - "type": "address" - } - ], - "name": "allowedInboxes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "outbox", - "type": "address" - } - ], - "name": "allowedOutboxes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "kind", - "type": "uint8" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "messageDataHash", - "type": "bytes32" - } - ], - "name": "deliverMessageToInbox", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "executeCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "returnData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "inboxAccs", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "messageCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "inbox", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "setInbox", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "inbox", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "setOutbox", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json deleted file mode 100644 index 61ea600..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBridgeAdapter.json +++ /dev/null @@ -1,131 +0,0 @@ -[ - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "remoteSender", - "type": "address" - }, - { - "internalType": "address", - "name": "localReceiver", - "type": "address" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json deleted file mode 100644 index 897cb35..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IBurnMintERC20.json +++ /dev/null @@ -1,252 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json deleted file mode 100644 index 6a14448..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICapabilityConfiguration.json +++ /dev/null @@ -1,55 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [], - "name": "CapabilityConfigurationSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "nodes", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "donCapabilityConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "donCapabilityConfigCount", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "beforeCapabilityConfigSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - } - ], - "name": "getCapabilityConfiguration", - "outputs": [ - { - "internalType": "bytes", - "name": "configuration", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json deleted file mode 100644 index c12d857..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChainModule.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "l1Fee", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "maxL1Fee", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json deleted file mode 100644 index 2a123a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IChannelConfigStore.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "string", - "name": "url", - "type": "string" - }, - { - "internalType": "bytes32", - "name": "sha", - "type": "bytes32" - } - ], - "name": "setChannelDefinitions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json deleted file mode 100644 index 17947ca..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IConfigurator.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "configId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json deleted file mode 100644 index 663cd86..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ICrossDomainOwnable.json +++ /dev/null @@ -1,73 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json deleted file mode 100644 index 10f01bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDelegateForwarder.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forwardDelegate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json deleted file mode 100644 index 1644031..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationFeeManager.json +++ /dev/null @@ -1,236 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "name": "addVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "address", - "name": "quoteAddress", - "type": "address" - } - ], - "name": "getFeeAndReward", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "payLinkDeficit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "name": "removeVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "surcharge", - "type": "uint64" - } - ], - "name": "setNativeSurcharge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "rewardManager", - "type": "address" - } - ], - "name": "setRewardManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberGlobalDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "recipientAddress", - "type": "address" - }, - { - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json deleted file mode 100644 index 46aa2bd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationRewardManager.json +++ /dev/null @@ -1,197 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "newFeeManager", - "type": "address" - } - ], - "name": "addFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - } - ], - "name": "claimRewards", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getAvailableRewardPoolIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "internalType": "struct IDestinationRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "onFeePaid", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - } - ], - "name": "payRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeManager", - "type": "address" - } - ], - "name": "removeFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "updateRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json deleted file mode 100644 index a4a8e97..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifier.json +++ /dev/null @@ -1,147 +0,0 @@ -[ - { - "inputs": [], - "name": "removeLatestConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessController", - "type": "address" - } - ], - "name": "setAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "donConfigId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - } - ], - "name": "setConfigActive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - }, - { - "internalType": "uint32", - "name": "activationTime", - "type": "uint32" - } - ], - "name": "setConfigWithActivationTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "feeManager", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json deleted file mode 100644 index 4962feb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierFeeManager.json +++ /dev/null @@ -1,107 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - }, - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setFeeRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json deleted file mode 100644 index fafe41e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxy.json +++ /dev/null @@ -1,108 +0,0 @@ -[ - { - "inputs": [], - "name": "s_accessController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "setVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "verifierResponse", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verifyBulk", - "outputs": [ - { - "internalType": "bytes[]", - "name": "verifiedReports", - "type": "bytes[]" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json deleted file mode 100644 index 0fea245..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IDestinationVerifierProxyVerifier.json +++ /dev/null @@ -1,105 +0,0 @@ -[ - { - "inputs": [], - "name": "s_accessController", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "signedReport", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "verifierResponse", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "signedReports", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verifyBulk", - "outputs": [ - { - "internalType": "bytes[]", - "name": "verifiedReports", - "type": "bytes[]" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json deleted file mode 100644 index f2d2b1d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC1155Errors.json +++ /dev/null @@ -1,104 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ERC1155InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC1155InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "idsLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "valuesLength", - "type": "uint256" - } - ], - "name": "ERC1155InvalidArrayLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "ERC1155InvalidOperator", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC1155InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC1155InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "ERC1155MissingApprovalForAll", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json deleted file mode 100644 index 0656ec3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC165.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceID", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json deleted file mode 100644 index 018d966..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20.json +++ /dev/null @@ -1,185 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json deleted file mode 100644 index d2e35dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Errors.json +++ /dev/null @@ -1,88 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "allowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "needed", - "type": "uint256" - } - ], - "name": "ERC20InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC20InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC20InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC20InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "ERC20InvalidSpender", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json deleted file mode 100644 index 5b64237..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Metadata.json +++ /dev/null @@ -1,224 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json deleted file mode 100644 index 5e41277..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC20Permit.json +++ /dev/null @@ -1,77 +0,0 @@ -[ - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "nonces", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "permit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json deleted file mode 100644 index ae7ca78..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC5267.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [], - "name": "EIP712DomainChanged", - "type": "event" - }, - { - "inputs": [], - "name": "eip712Domain", - "outputs": [ - { - "internalType": "bytes1", - "name": "fields", - "type": "bytes1" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "version", - "type": "string" - }, - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "verifyingContract", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "salt", - "type": "bytes32" - }, - { - "internalType": "uint256[]", - "name": "extensions", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json deleted file mode 100644 index e3d1461..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677.json +++ /dev/null @@ -1,62 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json deleted file mode 100644 index fd79f59..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC677Receiver.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json deleted file mode 100644 index 719d8f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IERC721Errors.json +++ /dev/null @@ -1,105 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "ERC721IncorrectOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ERC721InsufficientApproval", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "approver", - "type": "address" - } - ], - "name": "ERC721InvalidApprover", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "ERC721InvalidOperator", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "ERC721InvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - } - ], - "name": "ERC721InvalidReceiver", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "ERC721InvalidSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ERC721NonexistentToken", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json deleted file mode 100644 index 53d47e6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IEntryPoint.json +++ /dev/null @@ -1,1065 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bool", - "name": "targetSuccess", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "targetResult", - "type": "bytes" - } - ], - "name": "ExecutionResult", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "opIndex", - "type": "uint256" - }, - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "FailedOp", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderAddressResult", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "SignatureValidationFailed", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prefund", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "sigFailed", - "type": "bool" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bytes", - "name": "paymasterContext", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.ReturnInfo", - "name": "returnInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "senderInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "factoryInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "paymasterInfo", - "type": "tuple" - } - ], - "name": "ValidationResult", - "type": "error" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "preOpGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prefund", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "sigFailed", - "type": "bool" - }, - { - "internalType": "uint48", - "name": "validAfter", - "type": "uint48" - }, - { - "internalType": "uint48", - "name": "validUntil", - "type": "uint48" - }, - { - "internalType": "bytes", - "name": "paymasterContext", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.ReturnInfo", - "name": "returnInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "senderInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "factoryInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "paymasterInfo", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "stake", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "internalType": "struct IStakeManager.StakeInfo", - "name": "stakeInfo", - "type": "tuple" - } - ], - "internalType": "struct IEntryPoint.AggregatorStakeInfo", - "name": "aggregatorInfo", - "type": "tuple" - } - ], - "name": "ValidationResultWithAggregation", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "factory", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "paymaster", - "type": "address" - } - ], - "name": "AccountDeployed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDeposit", - "type": "uint256" - } - ], - "name": "Deposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "SignatureAggregatorChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalStaked", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "name": "StakeLocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawTime", - "type": "uint256" - } - ], - "name": "StakeUnlocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "paymaster", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "actualGasCost", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "actualGasUsed", - "type": "uint256" - } - ], - "name": "UserOperationEvent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "revertReason", - "type": "bytes" - } - ], - "name": "UserOperationRevertReason", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_unstakeDelaySec", - "type": "uint32" - } - ], - "name": "addStake", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "depositTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getDepositInfo", - "outputs": [ - { - "components": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "internalType": "struct IStakeManager.DepositInfo", - "name": "info", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "name": "getSenderAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - } - ], - "name": "getUserOpHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "userOps", - "type": "tuple[]" - }, - { - "internalType": "contract IAggregator", - "name": "aggregator", - "type": "address" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct IEntryPoint.UserOpsPerAggregator[]", - "name": "opsPerAggregator", - "type": "tuple[]" - }, - { - "internalType": "address payable", - "name": "beneficiary", - "type": "address" - } - ], - "name": "handleAggregatedOps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation[]", - "name": "ops", - "type": "tuple[]" - }, - { - "internalType": "address payable", - "name": "beneficiary", - "type": "address" - } - ], - "name": "handleOps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "op", - "type": "tuple" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "targetCallData", - "type": "bytes" - } - ], - "name": "simulateHandleOp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - } - ], - "name": "simulateValidation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unlockStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - } - ], - "name": "withdrawStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "withdrawAmount", - "type": "uint256" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json deleted file mode 100644 index da8ee5a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFeeManager.json +++ /dev/null @@ -1,250 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "address", - "name": "quoteAddress", - "type": "address" - } - ], - "name": "getFeeAndReward", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Common.Asset", - "name": "", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "payLinkDeficit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setFeeRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "surcharge", - "type": "uint64" - } - ], - "name": "setNativeSurcharge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "subscriber", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "discount", - "type": "uint64" - } - ], - "name": "updateSubscriberDiscount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "recipientAddress", - "type": "address" - }, - { - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json deleted file mode 100644 index 843160e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFlags.json +++ /dev/null @@ -1,118 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "getFlag", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bool[]", - "name": "", - "type": "bool[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "lowerFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "lowerFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "raiseFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "name": "raiseFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "setLoweringAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "setRaisingAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json deleted file mode 100644 index 301144c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IForwarder.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json deleted file mode 100644 index 22bd2b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsBilling.json +++ /dev/null @@ -1,150 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "deleteCommitment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "gasPriceWei", - "type": "uint256" - } - ], - "name": "estimateCost", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "requestCBOR", - "type": "bytes" - } - ], - "name": "getDONFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOperationFeeJuels", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUsdPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWeiPerUnitLink", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "oracleWithdrawAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json deleted file mode 100644 index af92e6d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsClient.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - } - ], - "name": "handleOracleFulfillment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json deleted file mode 100644 index c647a60..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsCoordinator.json +++ /dev/null @@ -1,187 +0,0 @@ -[ - { - "inputs": [], - "name": "getDONPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getThresholdPublicKey", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "donPublicKey", - "type": "bytes" - } - ], - "name": "setDONPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "thresholdPublicKey", - "type": "bytes" - } - ], - "name": "setThresholdPublicKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "requestingContract", - "type": "address" - }, - { - "internalType": "uint96", - "name": "availableBalance", - "type": "uint96" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subscriptionOwner", - "type": "address" - } - ], - "internalType": "struct FunctionsResponse.RequestMeta", - "name": "request", - "type": "tuple" - } - ], - "name": "startRequest", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json deleted file mode 100644 index 0dc1ff1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsRouter.json +++ /dev/null @@ -1,338 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "costWithoutFulfillment", - "type": "uint96" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "fulfill", - "outputs": [ - { - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFee", - "outputs": [ - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowListId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getProposedContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProposedContractSet", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "isValidCallbackGasLimit", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proposalSetIds", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "proposalSetAddresses", - "type": "address[]" - } - ], - "name": "proposeContractsUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "allowListId", - "type": "bytes32" - } - ], - "name": "setAllowListId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "updateContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json deleted file mode 100644 index 16ab897..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IFunctionsSubscriptions.json +++ /dev/null @@ -1,463 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "createSubscriptionWithConsumer", - "outputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getConsumer", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "initiatedRequests", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "completedRequests", - "type": "uint64" - } - ], - "internalType": "struct IFunctionsSubscriptions.Consumer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getFlags", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSubscriptionCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionIdStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subscriptionIdEnd", - "type": "uint64" - } - ], - "name": "getSubscriptionsInRange", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "uint96", - "name": "blockedBalance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "internalType": "struct IFunctionsSubscriptions.Subscription[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "proposeSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "flags", - "type": "bytes32" - } - ], - "name": "setFlags", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment[]", - "name": "requestsToTimeoutByCommitment", - "type": "tuple[]" - } - ], - "name": "timeoutRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json deleted file mode 100644 index 6893dd4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasBoundCaller.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_maxTotalGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "gasBoundCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json deleted file mode 100644 index 691cdd3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IGasToken.json +++ /dev/null @@ -1,59 +0,0 @@ -[ - { - "inputs": [], - "name": "gasPayingToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenName", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isCustomGasToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json deleted file mode 100644 index aa899e6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IInbox.json +++ /dev/null @@ -1,383 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "InboxMessageDelivered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - } - ], - "name": "InboxMessageDeliveredFromOrigin", - "type": "event" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "contract IBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createRetryableTicket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createRetryableTicketNoRefundAliasRewrite", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - } - ], - "name": "depositEth", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGasPrice", - "type": "uint256" - } - ], - "name": "depositEthRetryable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendL1FundedContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendL1FundedUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "messageData", - "type": "bytes" - } - ], - "name": "sendL2Message", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "sendUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json deleted file mode 100644 index d5e68ad..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IKeeperRegistryMaster.json +++ /dev/null @@ -1,2655 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "nonpayable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "uint8", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json deleted file mode 100644 index cd3afa0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumGateway.json +++ /dev/null @@ -1,322 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "DepositFinalized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "TxToL1", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_l2ToL1Id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_exitNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "WithdrawalInitiated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "l1ERC20", - "type": "address" - } - ], - "name": "calculateL2TokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counterpartGateway", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "exitNum", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "finalizeInboundTransfer", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getOutboundCalldata", - "outputs": [ - { - "internalType": "bytes", - "name": "outboundCalldata", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "res", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "postUpgradeInit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "router", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json deleted file mode 100644 index ba76cfb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2ArbitrumMessenger.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "TxToL1", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json deleted file mode 100644 index e3d5c12..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2GatewayRouter.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "outboundTransfer", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json deleted file mode 100644 index 87f9d84..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IL2StandardBridge.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_l2Token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json deleted file mode 100644 index 73eb86c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILinkAvailable.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "int256", - "name": "availableBalance", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json deleted file mode 100644 index dfe76ef..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityContainer.json +++ /dev/null @@ -1,66 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityRemoved", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "provideLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json deleted file mode 100644 index 8c184f6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILiquidityManager.json +++ /dev/null @@ -1,55 +0,0 @@ -[ - { - "inputs": [], - "name": "getAllCrossChainRebalancers", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "currentLiquidity", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json deleted file mode 100644 index 0a1d0cb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ILogAutomation.json +++ /dev/null @@ -1,86 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "log", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkLog", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json deleted file mode 100644 index 04cf0ab..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IMessageProvider.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "InboxMessageDelivered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - } - ], - "name": "InboxMessageDeliveredFromOrigin", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json deleted file mode 100644 index ade281c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/INodeInterface.json +++ /dev/null @@ -1,320 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint64", - "name": "l2BlockNum", - "type": "uint64" - } - ], - "name": "blockL1Num", - "outputs": [ - { - "internalType": "uint64", - "name": "l1BlockNum", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "size", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "leaf", - "type": "uint64" - } - ], - "name": "constructOutboxProof", - "outputs": [ - { - "internalType": "bytes32", - "name": "send", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - }, - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deposit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "l2CallValue", - "type": "uint256" - }, - { - "internalType": "address", - "name": "excessFeeRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "callValueRefundAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "estimateRetryableTicket", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - } - ], - "name": "findBatchContainingBlock", - "outputs": [ - { - "internalType": "uint64", - "name": "batch", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bool", - "name": "contractCreation", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "gasEstimateComponents", - "outputs": [ - { - "internalType": "uint64", - "name": "gasEstimate", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "gasEstimateForL1", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l1BaseFeeEstimate", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bool", - "name": "contractCreation", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "gasEstimateL1Component", - "outputs": [ - { - "internalType": "uint64", - "name": "gasEstimateForL1", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l1BaseFeeEstimate", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - } - ], - "name": "getL1Confirmations", - "outputs": [ - { - "internalType": "uint64", - "name": "confirmations", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - } - ], - "name": "l2BlockRangeForL1", - "outputs": [ - { - "internalType": "uint64", - "name": "firstBlock", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastBlock", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "batchNum", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "index", - "type": "uint64" - } - ], - "name": "legacyLookupMessageBatchProof", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "path", - "type": "uint256" - }, - { - "internalType": "address", - "name": "l2Sender", - "type": "address" - }, - { - "internalType": "address", - "name": "l1Dest", - "type": "address" - }, - { - "internalType": "uint256", - "name": "l2Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l1Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "calldataForL1", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "nitroGenesisBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "number", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json deleted file mode 100644 index 1fa1332..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOffchainAggregator.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "requestNewRound", - "outputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json deleted file mode 100644 index acf91b1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismCrossDomainMessenger.json +++ /dev/null @@ -1,77 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minGasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - } - ], - "name": "relayMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json deleted file mode 100644 index 29d5e65..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismDisputeGameFactory.json +++ /dev/null @@ -1,71 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "GameType", - "name": "_gameType", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_n", - "type": "uint256" - } - ], - "name": "findLatestGames", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "GameId", - "name": "metadata", - "type": "bytes32" - }, - { - "internalType": "Timestamp", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "Claim", - "name": "rootClaim", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "internalType": "struct IOptimismDisputeGameFactory.GameSearchResult[]", - "name": "games_", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gameCount", - "outputs": [ - { - "internalType": "uint256", - "name": "gameCount_", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json deleted file mode 100644 index 0100348..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL1StandardBridge.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint32", - "name": "_minGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "depositETHTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json deleted file mode 100644 index 9fe0ee8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2OutputOracle.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - } - ], - "name": "getL2Output", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "outputRoot", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "timestamp", - "type": "uint128" - }, - { - "internalType": "uint128", - "name": "l2BlockNumber", - "type": "uint128" - } - ], - "internalType": "struct Types.OutputProposal", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2BlockNumber", - "type": "uint256" - } - ], - "name": "getL2OutputIndexAfter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json deleted file mode 100644 index bdf64ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismL2ToL1MessagePasser.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "withdrawalHash", - "type": "bytes32" - } - ], - "name": "MessagePassed", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json deleted file mode 100644 index fa9c36b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "remoteToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json deleted file mode 100644 index eadb295..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismMintableERC20Minimal.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "remoteToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json deleted file mode 100644 index 8e562c4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal.json +++ /dev/null @@ -1,142 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - } - ], - "name": "finalizeWithdrawalTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Types.WithdrawalTransaction", - "name": "_tx", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "_l2OutputIndex", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "version", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "messagePasserStorageRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "latestBlockhash", - "type": "bytes32" - } - ], - "internalType": "struct Types.OutputRootProof", - "name": "_outputRootProof", - "type": "tuple" - }, - { - "internalType": "bytes[]", - "name": "_withdrawalProof", - "type": "bytes[]" - } - ], - "name": "proveWithdrawalTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json deleted file mode 100644 index 5c6c934..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismPortal2.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "inputs": [], - "name": "disputeGameFactory", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "respectedGameType", - "outputs": [ - { - "internalType": "GameType", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json deleted file mode 100644 index c173046..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOptimismStandardBridge.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "ERC20BridgeFinalized", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_remoteToken", - "type": "address" - }, - { - "internalType": "address", - "name": "_from", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_extraData", - "type": "bytes" - } - ], - "name": "finalizeBridgeERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json deleted file mode 100644 index a646f82..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOutbox.json +++ /dev/null @@ -1,55 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proof", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "address", - "name": "l2Sender", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "l2Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l1Block", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2Timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "executeTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json deleted file mode 100644 index ee9d817..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnable.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json deleted file mode 100644 index 59332ab..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IOwnableFunctionsRouter.json +++ /dev/null @@ -1,371 +0,0 @@ -[ - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "response", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "err", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "juelsPerGas", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "costWithoutFulfillment", - "type": "uint96" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - }, - { - "internalType": "uint96", - "name": "estimatedTotalCostJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "client", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "donFee", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "gasOverheadBeforeCallback", - "type": "uint40" - }, - { - "internalType": "uint40", - "name": "gasOverheadAfterCallback", - "type": "uint40" - }, - { - "internalType": "uint32", - "name": "timeoutTimestamp", - "type": "uint32" - } - ], - "internalType": "struct FunctionsResponse.Commitment", - "name": "commitment", - "type": "tuple" - } - ], - "name": "fulfill", - "outputs": [ - { - "internalType": "enum FunctionsResponse.FulfillResult", - "name": "", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAdminFee", - "outputs": [ - { - "internalType": "uint72", - "name": "adminFee", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowListId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "getProposedContractById", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getProposedContractSet", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - } - ], - "name": "isValidCallbackGasLimit", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "proposalSetIds", - "type": "bytes32[]" - }, - { - "internalType": "address[]", - "name": "proposalSetAddresses", - "type": "address[]" - } - ], - "name": "proposeContractsUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequest", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint16", - "name": "dataVersion", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "donId", - "type": "bytes32" - } - ], - "name": "sendRequestToProposed", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "allowListId", - "type": "bytes32" - } - ], - "name": "setAllowListId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "updateContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json deleted file mode 100644 index b617778..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IPaymaster.json +++ /dev/null @@ -1,116 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "enum IPaymaster.PostOpMode", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "actualGasCost", - "type": "uint256" - } - ], - "name": "postOp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "maxCost", - "type": "uint256" - } - ], - "name": "validatePaymasterUserOp", - "outputs": [ - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "validationData", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json deleted file mode 100644 index 2b6a061..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IReceiver.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - } - ], - "name": "onReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json deleted file mode 100644 index 5f34d15..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRewardManager.json +++ /dev/null @@ -1,184 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - } - ], - "name": "claimRewards", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getAvailableRewardPoolIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "internalType": "struct IRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "onFeePaid", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - } - ], - "name": "payRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newFeeManager", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "updateRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json deleted file mode 100644 index 2d3c49f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IRouter.json +++ /dev/null @@ -1,239 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - } - ], - "name": "AlreadyAttempted", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - } - ], - "name": "InsufficientGasForRouting", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedForwarder", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "ForwarderAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "ForwarderRemoved", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "addForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmissionId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmissionInfo", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - }, - { - "internalType": "enum IRouter.TransmissionState", - "name": "state", - "type": "uint8" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "bool", - "name": "invalidReceiver", - "type": "bool" - }, - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint80", - "name": "gasLimit", - "type": "uint80" - } - ], - "internalType": "struct IRouter.TransmissionInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmitter", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "removeForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - } - ], - "name": "route", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json deleted file mode 100644 index f568519..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollL1GasPriceOracle.json +++ /dev/null @@ -1,131 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "l1BaseFee", - "type": "uint256" - } - ], - "name": "L1BaseFeeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "overhead", - "type": "uint256" - } - ], - "name": "OverheadUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - } - ], - "name": "ScalarUpdated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "getL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "getL1GasUsed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1BaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l1BaseFee", - "type": "uint256" - } - ], - "name": "setL1BaseFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json deleted file mode 100644 index ec46f23..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IScrollMessenger.json +++ /dev/null @@ -1,145 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "refundAddress", - "type": "address" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json deleted file mode 100644 index c4aed5f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISemver.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json deleted file mode 100644 index a67bc9d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISequencerUptimeFeed.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json deleted file mode 100644 index b8fa2d1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IStakeManager.json +++ /dev/null @@ -1,244 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDeposit", - "type": "uint256" - } - ], - "name": "Deposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalStaked", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "name": "StakeLocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawTime", - "type": "uint256" - } - ], - "name": "StakeUnlocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_unstakeDelaySec", - "type": "uint32" - } - ], - "name": "addStake", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "depositTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getDepositInfo", - "outputs": [ - { - "components": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "internalType": "struct IStakeManager.DepositInfo", - "name": "info", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unlockStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - } - ], - "name": "withdrawStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "withdrawAmount", - "type": "uint256" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json deleted file mode 100644 index a9cb145..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ISystemContext.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "inputs": [], - "name": "gasPerPubdataByte", - "outputs": [ - { - "internalType": "uint256", - "name": "gasPerPubdataByte", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPubdataSpent", - "outputs": [ - { - "internalType": "uint256", - "name": "currentPubdataSpent", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json deleted file mode 100644 index 5c2804d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITermsOfServiceAllowList.json +++ /dev/null @@ -1,191 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "acceptor", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - } - ], - "name": "acceptTermsOfService", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "blockSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAllAllowedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedSendersCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "allowedSenderIdxStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "allowedSenderIdxEnd", - "type": "uint64" - } - ], - "name": "getAllowedSendersInRange", - "outputs": [ - { - "internalType": "address[]", - "name": "allowedSenders", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockedSendersCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockedSenderIdxStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "blockedSenderIdxEnd", - "type": "uint64" - } - ], - "name": "getBlockedSendersInRange", - "outputs": [ - { - "internalType": "address[]", - "name": "blockedSenders", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "acceptor", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getMessage", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isBlockedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "unblockSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json deleted file mode 100644 index 99725a5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ITypeAndVersion.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json deleted file mode 100644 index 14be06d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2.json +++ /dev/null @@ -1,375 +0,0 @@ -[ - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "internalType": "struct VRFTypes.RequestCommitment", - "name": "rc", - "type": "tuple" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFeeConfig", - "outputs": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "internalType": "struct FeeConfig", - "name": "feeConfig", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json deleted file mode 100644 index 01b7fe4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2Plus.json +++ /dev/null @@ -1,246 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json deleted file mode 100644 index 6fb3e61..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusFulfill.json +++ /dev/null @@ -1,110 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json deleted file mode 100644 index b6efb18..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusInternal.json +++ /dev/null @@ -1,490 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct IVRFCoordinatorV2PlusInternal.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct IVRFCoordinatorV2PlusInternal.RequestCommitment", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestID", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json deleted file mode 100644 index 7bf40b8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFCoordinatorV2PlusMigration.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedData", - "type": "bytes" - } - ], - "name": "onMigration", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json deleted file mode 100644 index c08f818..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFMigratableConsumerV2Plus.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json deleted file mode 100644 index 7413236..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFSubscriptionV2Plus.json +++ /dev/null @@ -1,195 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json deleted file mode 100644 index e8dc559..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusMigrate.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json deleted file mode 100644 index 4d25e6a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVRFV2PlusWrapper.json +++ /dev/null @@ -1,181 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "link", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkNativeFeed", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "name": "requestRandomWordsInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json deleted file mode 100644 index 6b5d2dc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifier.json +++ /dev/null @@ -1,300 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "activateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "activateFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "deactivateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "deactivateFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "sourceChainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sourceAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "newConfigCount", - "type": "uint32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfigFromSource", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "signedReport", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "verifierResponse", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json deleted file mode 100644 index 1635137..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierFeeManager.json +++ /dev/null @@ -1,97 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFee", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - }, - { - "internalType": "address", - "name": "subscriber", - "type": "address" - } - ], - "name": "processFeeBulk", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setFeeRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json deleted file mode 100644 index 263abee..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IVerifierProxy.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "signedReport", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "verifierResponse", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json deleted file mode 100644 index 569a62d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWERC20.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "inputs": [], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json deleted file mode 100644 index efdb2d8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWithdrawal.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json deleted file mode 100644 index 8a2916f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IWrappedNative.json +++ /dev/null @@ -1,205 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json deleted file mode 100644 index bd2887e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/IZKSyncAutomationRegistryMaster2_3.json +++ /dev/null @@ -1,3567 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableOffchainPayments", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint8", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getAvailableERC20ForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getBillingConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverrides", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverridesEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "getBillingTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBillingTokens", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackNativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getHotVars", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reentrancyGuard", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.HotVars", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNativeUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNumUpkeeps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPayoutMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "billingToken", - "type": "address" - } - ], - "name": "getReserveAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStorage", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.Storage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmittersWithPayees", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transmitterAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "payeeAddress", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNativeTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "address", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "removeBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "billingOverrides", - "type": "tuple" - } - ], - "name": "setBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "address[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "address", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]", - "name": "billingConfigs", - "type": "tuple[]" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "uint8", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "settleNOPsOffchain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "supportsBillingToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawERC20Fees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json deleted file mode 100644 index df62e86..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperCompatibleTestHelper.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "verifyCannotExecute", - "outputs": [], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json deleted file mode 100644 index 37deb69..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumer.json +++ /dev/null @@ -1,94 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "updateInterval", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "interval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastTimeStamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json deleted file mode 100644 index e4628be..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperConsumerPerformance.json +++ /dev/null @@ -1,289 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_averageEligibilityCadence", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_checkGasToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_performGasToBurn", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "eligible", - "type": "bool" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialCall", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextEligible", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [], - "name": "averageEligibilityCadence", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkEligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "count", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCountPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialCall", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "nextEligible", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setCheckGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_newTestRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_newAverageEligibilityCadence", - "type": "uint256" - } - ], - "name": "setSpread", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json deleted file mode 100644 index 2159111..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar.json +++ /dev/null @@ -1,594 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "LINKAddress", - "type": "address" - }, - { - "internalType": "enum KeeperRegistrar.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "autoApproveMaxAllowed", - "type": "uint16" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AmountMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "FunctionNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "HashMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientPayment", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAdminAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "LinkTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyAdminOrOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyLink", - "type": "error" - }, - { - "inputs": [], - "name": "RegistrationRequestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "RequestNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "SenderMismatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "AutoApproveAllowedSenderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "enum KeeperRegistrar.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "ConfigChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "RegistrationApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "RegistrationRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "source", - "type": "uint8" - } - ], - "name": "RegistrationRequested", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "cancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - } - ], - "name": "getAutoApproveAllowedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "getPendingRequest", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRegistrationConfig", - "outputs": [ - { - "internalType": "enum KeeperRegistrar.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "approvedCount", - "type": "uint32" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minLINKJuels", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "source", - "type": "uint8" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "register", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "setAutoApproveAllowedSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum KeeperRegistrar.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "autoApproveMaxAllowed", - "type": "uint16" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "setRegistrationConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json deleted file mode 100644 index c0a11e7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar1_2Mock.json +++ /dev/null @@ -1,491 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "AutoApproveAllowedSenderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "ConfigChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "RegistrationApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "RegistrationRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "source", - "type": "uint8" - } - ], - "name": "RegistrationRequested", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "emitAutoApproveAllowedSenderSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "emitConfigChanged", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "emitRegistrationApproved", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "emitRegistrationRejected", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "source", - "type": "uint8" - } - ], - "name": "emitRegistrationRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRegistrationConfig", - "outputs": [ - { - "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "approvedCount", - "type": "uint32" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minLINKJuels", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_approvedCount", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_autoApproveConfigType", - "outputs": [ - { - "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_autoApproveMaxAllowed", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_keeperRegistry", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_minLINKJuels", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum KeeperRegistrar1_2Mock.AutoApproveType", - "name": "_autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "_autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_approvedCount", - "type": "uint32" - }, - { - "internalType": "address", - "name": "_keeperRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_minLINKJuels", - "type": "uint256" - } - ], - "name": "setRegistrationConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json deleted file mode 100644 index 2286e96..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistrar2_0.json +++ /dev/null @@ -1,654 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "LINKAddress", - "type": "address" - }, - { - "internalType": "enum KeeperRegistrar2_0.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "autoApproveMaxAllowed", - "type": "uint16" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AmountMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "FunctionNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "HashMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientPayment", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidAdminAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "LinkTransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyAdminOrOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyLink", - "type": "error" - }, - { - "inputs": [], - "name": "RegistrationRequestFailed", - "type": "error" - }, - { - "inputs": [], - "name": "RequestNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "SenderMismatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "AutoApproveAllowedSenderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "enum KeeperRegistrar2_0.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "ConfigChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "displayName", - "type": "string" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "RegistrationApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "RegistrationRejected", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "RegistrationRequested", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "cancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - } - ], - "name": "getAutoApproveAllowedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "hash", - "type": "bytes32" - } - ], - "name": "getPendingRequest", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRegistrationConfig", - "outputs": [ - { - "internalType": "enum KeeperRegistrar2_0.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "autoApproveMaxAllowed", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "approvedCount", - "type": "uint32" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minLINKJuels", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "register", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "bytes", - "name": "encryptedEmail", - "type": "bytes" - }, - { - "internalType": "address", - "name": "upkeepContract", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "adminAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "internalType": "struct KeeperRegistrar2_0.RegistrationParams", - "name": "requestParams", - "type": "tuple" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "allowed", - "type": "bool" - } - ], - "name": "setAutoApproveAllowedSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum KeeperRegistrar2_0.AutoApproveType", - "name": "autoApproveConfigType", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "autoApproveMaxAllowed", - "type": "uint16" - }, - { - "internalType": "address", - "name": "keeperRegistry", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minLINKJuels", - "type": "uint96" - } - ], - "name": "setRegistrationConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json deleted file mode 100644 index 0166311..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_2.json +++ /dev/null @@ -1,1486 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkEthFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "KeepersMustTakeTurns", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveKeepers", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotActive", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "KeepersUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "inputs": [], - "name": "FAST_GAS_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maxLinkPayment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "adjustedGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkEth", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getKeeperInfo", - "outputs": [ - { - "internalType": "address", - "name": "payee", - "type": "address" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum KeeperRegistry1_2.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - } - ], - "internalType": "struct State", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "lastKeeper", - "type": "address" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setKeepers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistry1_2.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json deleted file mode 100644 index 44f3d33..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry1_3.json +++ /dev/null @@ -1,1744 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract KeeperRegistryLogic1_3", - "name": "keeperRegistryLogic", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyAddress", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "KeepersMustTakeTurns", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveKeepers", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "KeepersUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "ARB_NITRO_ORACLE", - "outputs": [ - { - "internalType": "contract ArbGasInfo", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FAST_GAS_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "KEEPER_REGISTRY_LOGIC", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_ORACLE", - "outputs": [ - { - "internalType": "contract OVM_GasPriceOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAYMENT_MODEL", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase1_3.PaymentModel", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REGISTRY_GAS_OVERHEAD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maxLinkPayment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "adjustedGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkEth", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getKeeperInfo", - "outputs": [ - { - "internalType": "address", - "name": "payee", - "type": "address" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - } - ], - "internalType": "struct State", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "lastKeeper", - "type": "address" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setKeepers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json deleted file mode 100644 index edb6ac6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_0.json +++ /dev/null @@ -1,1951 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract KeeperRegistryBase2_0", - "name": "keeperRegistryLogic", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnchainConfigNonEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "checkBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistryLogicAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMode", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_0.Mode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct State", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "internalType": "struct OnchainConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct UpkeepInfo", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json deleted file mode 100644 index e94e2d7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistry2_1.json +++ /dev/null @@ -1,1349 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract KeeperRegistryLogicB2_1", - "name": "logicA", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json deleted file mode 100644 index f02568b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase1_3.json +++ /dev/null @@ -1,857 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyAddress", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "KeepersMustTakeTurns", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveKeepers", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "KeepersUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "ARB_NITRO_ORACLE", - "outputs": [ - { - "internalType": "contract ArbGasInfo", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FAST_GAS_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_ORACLE", - "outputs": [ - { - "internalType": "contract OVM_GasPriceOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAYMENT_MODEL", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase1_3.PaymentModel", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REGISTRY_GAS_OVERHEAD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json deleted file mode 100644 index ef56a9f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_0.json +++ /dev/null @@ -1,882 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnchainConfigNonEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "checkBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMode", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_0.Mode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json deleted file mode 100644 index 0d90ae5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryBase2_1.json +++ /dev/null @@ -1,944 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json deleted file mode 100644 index 910cb03..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.json +++ /dev/null @@ -1,131 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistryExecutableInterface", - "name": "keeperRegistry", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getKeeperRegistry", - "outputs": [ - { - "internalType": "contract AutomationRegistryExecutableInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "measureCheckGas", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json deleted file mode 100644 index cdec278..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.json +++ /dev/null @@ -1,172 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "emitOwnershipTransferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "measureCheckGas", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_mockGas", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_mockPayload", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_mockResult", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "result", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "gas", - "type": "uint256" - } - ], - "name": "setMeasureCheckGasResult", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json deleted file mode 100644 index e81632a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic1_3.json +++ /dev/null @@ -1,1208 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "enum KeeperRegistryBase1_3.PaymentModel", - "name": "paymentModel", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "registryGasOverhead", - "type": "uint256" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkEthFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyAddress", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "KeepersMustTakeTurns", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveKeepers", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "blockCountPerTurn", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address", - "name": "registrar", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct Config", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "KeepersUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "ARB_NITRO_ORACLE", - "outputs": [ - { - "internalType": "contract ArbGasInfo", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "FAST_GAS_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "OPTIMISM_ORACLE", - "outputs": [ - { - "internalType": "contract OVM_GasPriceOracle", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "PAYMENT_MODEL", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase1_3.PaymentModel", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REGISTRY_GAS_OVERHEAD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "maxLinkPayment", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "adjustedGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkEth", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "keepers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setKeepers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase1_3.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeper", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json deleted file mode 100644 index c6ba131..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogic2_0.json +++ /dev/null @@ -1,1290 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "enum KeeperRegistryBase2_0.Mode", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnchainConfigNonEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "checkBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "executeGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMode", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_0.Mode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase2_0.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json deleted file mode 100644 index ba56eaa..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicA2_1.json +++ /dev/null @@ -1,1326 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract KeeperRegistryLogicB2_1", - "name": "logicB", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkNative", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum KeeperRegistryBase2_1.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase2_1.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json deleted file mode 100644 index 12f4abe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeeperRegistryLogicB2_1.json +++ /dev/null @@ -1,1938 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "enum KeeperRegistryBase2_1.Mode", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "automationForwarderLogic", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MaxCheckDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MaxPerformDataSizeCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentGreaterThanAllLINK", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "OwnerFundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "contract IAutomationForwarder", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkNativeFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum KeeperRegistryBase2_1.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMode", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_1.Mode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_1.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerPerformByteGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "enum KeeperRegistryBase2_1.Trigger", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum KeeperRegistryBase2_1.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawOwnerFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json deleted file mode 100644 index aa95d60..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeepersVRFConsumer.json +++ /dev/null @@ -1,242 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "upkeepInterval", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "KEY_HASH", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SUBSCRIPTION_ID", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "UPKEEP_INTERVAL", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastTimeStamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfRequestCounter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfResponseCounter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json deleted file mode 100644 index 8816e0e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsConsumer.json +++ /dev/null @@ -1,215 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes10", - "name": "workflowName", - "type": "bytes10" - } - ], - "name": "UnauthorizedWorkflowName", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "workflowOwner", - "type": "address" - } - ], - "name": "UnauthorizedWorkflowOwner", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint224", - "name": "price", - "type": "uint224" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "timestamp", - "type": "uint32" - } - ], - "name": "FeedReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "getPrice", - "outputs": [ - { - "internalType": "uint224", - "name": "", - "type": "uint224" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - } - ], - "name": "onReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_allowedSendersList", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_allowedWorkflowOwnersList", - "type": "address[]" - }, - { - "internalType": "bytes10[]", - "name": "_allowedWorkflowNamesList", - "type": "bytes10[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json deleted file mode 100644 index 6bbbef4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneFeedsPermissionHandler.json +++ /dev/null @@ -1,185 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - }, - { - "internalType": "address", - "name": "workflowOwner", - "type": "address" - }, - { - "internalType": "bytes10", - "name": "workflowName", - "type": "bytes10" - }, - { - "internalType": "bytes2", - "name": "reportName", - "type": "bytes2" - } - ], - "name": "ReportForwarderUnauthorized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "reportId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - }, - { - "internalType": "bytes10", - "name": "workflowName", - "type": "bytes10" - }, - { - "internalType": "bytes2", - "name": "reportName", - "type": "bytes2" - }, - { - "internalType": "address", - "name": "workflowOwner", - "type": "address" - }, - { - "internalType": "bool", - "name": "isAllowed", - "type": "bool" - } - ], - "indexed": false, - "internalType": "struct KeystoneFeedsPermissionHandler.Permission", - "name": "permission", - "type": "tuple" - } - ], - "name": "ReportPermissionSet", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - }, - { - "internalType": "bytes10", - "name": "workflowName", - "type": "bytes10" - }, - { - "internalType": "bytes2", - "name": "reportName", - "type": "bytes2" - }, - { - "internalType": "address", - "name": "workflowOwner", - "type": "address" - }, - { - "internalType": "bool", - "name": "isAllowed", - "type": "bool" - } - ], - "internalType": "struct KeystoneFeedsPermissionHandler.Permission[]", - "name": "permissions", - "type": "tuple[]" - } - ], - "name": "setReportPermissions", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json deleted file mode 100644 index f62e5b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/KeystoneForwarder.json +++ /dev/null @@ -1,585 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - } - ], - "name": "AlreadyAttempted", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "signer", - "type": "address" - } - ], - "name": "DuplicateSigner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSigners", - "type": "uint256" - } - ], - "name": "ExcessSigners", - "type": "error" - }, - { - "inputs": [], - "name": "FaultToleranceMustBePositive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - } - ], - "name": "InsufficientGasForRouting", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSigners", - "type": "uint256" - } - ], - "name": "InsufficientSigners", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "configId", - "type": "uint64" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "received", - "type": "uint256" - } - ], - "name": "InvalidSignatureCount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "signer", - "type": "address" - } - ], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedForwarder", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "uint32", - "name": "configVersion", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "ForwarderAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "ForwarderRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - }, - { - "indexed": false, - "internalType": "bool", - "name": "result", - "type": "bool" - } - ], - "name": "ReportProcessed", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "addForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configVersion", - "type": "uint32" - } - ], - "name": "clearConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmissionId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmissionInfo", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - }, - { - "internalType": "enum IRouter.TransmissionState", - "name": "state", - "type": "uint8" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "bool", - "name": "invalidReceiver", - "type": "bool" - }, - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint80", - "name": "gasLimit", - "type": "uint80" - } - ], - "internalType": "struct IRouter.TransmissionInfo", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "workflowExecutionId", - "type": "bytes32" - }, - { - "internalType": "bytes2", - "name": "reportId", - "type": "bytes2" - } - ], - "name": "getTransmitter", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "removeForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "reportContext", - "type": "bytes" - }, - { - "internalType": "bytes[]", - "name": "signatures", - "type": "bytes[]" - } - ], - "name": "report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "transmissionId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "validatedReport", - "type": "bytes" - } - ], - "name": "route", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "donId", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "configVersion", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json deleted file mode 100644 index ffd9177..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/L1Block.json +++ /dev/null @@ -1,347 +0,0 @@ -[ - { - "inputs": [], - "name": "NotDepositor", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "name", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "symbol", - "type": "bytes32" - } - ], - "name": "GasPayingTokenSet", - "type": "event" - }, - { - "inputs": [], - "name": "DEPOSITOR_ACCOUNT", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "baseFeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "basefee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "batcherHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blobBaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blobBaseFeeScalar", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingToken", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenName", - "outputs": [ - { - "internalType": "string", - "name": "name_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "symbol_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isCustomGasToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1FeeOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1FeeScalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "number", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_name", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_symbol", - "type": "bytes32" - } - ], - "name": "setGasPayingToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_number", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "_timestamp", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "_basefee", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "_hash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_sequenceNumber", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "_batcherHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_l1FeeOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_l1FeeScalar", - "type": "uint256" - } - ], - "name": "setL1BlockValues", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "setL1BlockValuesEcotone", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timestamp", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json deleted file mode 100644 index 766dff9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkAvailableBalanceMonitor.json +++ /dev/null @@ -1,946 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "contract IERC20", - "name": "linkToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "maxPerform", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "maxCheck", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "upkeepInterval", - "type": "uint8" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "duplicate", - "type": "address" - } - ], - "name": "DuplicateAddress", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidChainSelector", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "lt", - "type": "address" - } - ], - "name": "InvalidLinkTokenAddress", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maxCheck", - "type": "uint16" - } - ], - "name": "InvalidMaxCheck", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "name": "InvalidMinBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "topUpAmount", - "type": "uint96" - } - ], - "name": "InvalidTopUpAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "upkeepInterval", - "type": "uint8" - } - ], - "name": "InvalidUpkeepInterval", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maxPerform", - "type": "uint16" - } - ], - "name": "InvalixMaxPerform", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "BalanceUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMaxCheck", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMaxCheck", - "type": "uint256" - } - ], - "name": "MaxCheckSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMaxPerform", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMaxPerform", - "type": "uint256" - } - ], - "name": "MaxPerformSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "s_minWaitPeriodSeconds", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "name": "MinWaitPeriodSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "topUpAddress", - "type": "address" - } - ], - "name": "TopUpBlocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "topUpAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldTopUpAmount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newTopUpAmount", - "type": "uint256" - } - ], - "name": "TopUpUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldUpkeepInterval", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newUpkeepInterval", - "type": "uint256" - } - ], - "name": "UpkeepIntervalSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "WatchlistUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "dstChainSelector", - "type": "uint64" - } - ], - "name": "addToWatchListOrDecommission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "getAccountInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpAmount", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMaxCheck", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMaxPerform", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "dstChainSelector", - "type": "uint64" - } - ], - "name": "getOnRampAddressAtChainSelector", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUpkeepInterval", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "targetAddress", - "type": "address" - } - ], - "name": "removeFromWatchList", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sampleUnderfundedAddresses", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maxCheck", - "type": "uint16" - } - ], - "name": "setMaxCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "maxPerform", - "type": "uint16" - } - ], - "name": "setMaxPerform", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "name": "setMinBalance", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint96", - "name": "topUpAmount", - "type": "uint96" - } - ], - "name": "setTopUpAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "upkeepInterval", - "type": "uint8" - } - ], - "name": "setUpkeepInterval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "addresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "minBalances", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmounts", - "type": "uint96[]" - }, - { - "internalType": "uint64[]", - "name": "dstChainSelectors", - "type": "uint64[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targetAddresses", - "type": "address[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json deleted file mode 100644 index f1c86bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkToken.json +++ /dev/null @@ -1,763 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "supplyAfterMint", - "type": "uint256" - } - ], - "name": "MaxSupplyExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotBurner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotMinter", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBurners", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "grantBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burnAndMinter", - "type": "address" - } - ], - "name": "grantMintAndBurnRoles", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "grantMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseApproval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "isBurner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "isMinter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "revokeBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "revokeMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json deleted file mode 100644 index dc470f1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenInterface.json +++ /dev/null @@ -1,245 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "remaining", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "decimalPlaces", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "increaseApproval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "tokenName", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "tokenSymbol", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "totalTokensIssued", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json deleted file mode 100644 index 37baafd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenReceiver.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "inputs": [], - "name": "getChainlinkToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json deleted file mode 100644 index f1c86bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LinkTokenTestHelper.json +++ /dev/null @@ -1,763 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "supplyAfterMint", - "type": "uint256" - } - ], - "name": "MaxSupplyExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotBurner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotMinter", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBurners", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "grantBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burnAndMinter", - "type": "address" - } - ], - "name": "grantMintAndBurnRoles", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "grantMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseApproval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "isBurner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "isMinter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "revokeBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "revokeMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json deleted file mode 100644 index 92fc9cb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManager.json +++ /dev/null @@ -1,1147 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IERC20", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "localChainSelector", - "type": "uint64" - }, - { - "internalType": "contract ILiquidityContainer", - "name": "localLiquidityContainer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minimumLiquidity", - "type": "uint256" - }, - { - "internalType": "address", - "name": "finance", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "expected", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "actual", - "type": "bytes32" - } - ], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyReport", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "ForkedChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserve", - "type": "uint256" - } - ], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - } - ], - "name": "InvalidRemoteChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestSequenceNumber", - "type": "uint64" - } - ], - "name": "NonIncreasingSequenceNumber", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceRole", - "type": "error" - }, - { - "inputs": [], - "name": "OracleCannotBeZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "SignaturesOutOfRegistration", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "WrongMessageLength", - "type": "error" - }, - { - "inputs": [], - "name": "WrongNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroChainSelector", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "CrossChainRebalancerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "FinalizationFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - } - ], - "name": "FinalizationStepCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "financeRole", - "type": "address" - } - ], - "name": "FinanceRoleSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityAddedToContainer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "newLiquidityContainer", - "type": "address" - } - ], - "name": "LiquidityContainerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remover", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityRemovedFromContainer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "fromChainSelector", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "toChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeReturnData", - "type": "bytes" - } - ], - "name": "LiquidityTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "MinimumLiquiditySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "depositor", - "type": "address" - } - ], - "name": "NativeDeposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "NativeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "addLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAllCrossChainRebalancers", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - } - ], - "name": "getCrossChainRebalancer", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct LiquidityManager.CrossChainRebalancer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFinanceRole", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "currentLiquidity", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLocalLiquidityContainer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinimumLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSupportedDestChains", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_localToken", - "outputs": [ - { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nativeBridgeFee", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "rebalanceLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "shouldWrapNative", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "receiveLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "removeLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs", - "name": "crossChainLiqManager", - "type": "tuple" - } - ], - "name": "setCrossChainRebalancer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "crossChainRebalancers", - "type": "tuple[]" - } - ], - "name": "setCrossChainRebalancers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "finance", - "type": "address" - } - ], - "name": "setFinanceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ILiquidityContainer", - "name": "localLiquidityContainer", - "type": "address" - } - ], - "name": "setLocalLiquidityContainer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "minimumLiquidity", - "type": "uint256" - } - ], - "name": "setMinimumLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json deleted file mode 100644 index 5418612..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LiquidityManagerHelper.json +++ /dev/null @@ -1,1165 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IERC20", - "name": "token", - "type": "address" - }, - { - "internalType": "uint64", - "name": "localChainSelector", - "type": "uint64" - }, - { - "internalType": "contract ILiquidityContainer", - "name": "localLiquidityContainer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "targetTokens", - "type": "uint256" - }, - { - "internalType": "address", - "name": "finance", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "expected", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "actual", - "type": "bytes32" - } - ], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyReport", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "ForkedChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "reserve", - "type": "uint256" - } - ], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - } - ], - "name": "InvalidRemoteChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestSequenceNumber", - "type": "uint64" - } - ], - "name": "NonIncreasingSequenceNumber", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceRole", - "type": "error" - }, - { - "inputs": [], - "name": "OracleCannotBeZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "SignaturesOutOfRegistration", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "WrongMessageLength", - "type": "error" - }, - { - "inputs": [], - "name": "WrongNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroChainSelector", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "name": "CrossChainRebalancerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "FinalizationFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - } - ], - "name": "FinalizationStepCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "financeRole", - "type": "address" - } - ], - "name": "FinanceRoleSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityAddedToContainer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "newLiquidityContainer", - "type": "address" - } - ], - "name": "LiquidityContainerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "remover", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityRemovedFromContainer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "fromChainSelector", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "toChainSelector", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeSpecificData", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "bridgeReturnData", - "type": "bytes" - } - ], - "name": "LiquidityTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "MinimumLiquiditySet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "depositor", - "type": "address" - } - ], - "name": "NativeDeposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "NativeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "addLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAllCrossChainRebalancers", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - } - ], - "name": "getCrossChainRebalancer", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct LiquidityManager.CrossChainRebalancer", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFinanceRole", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "currentLiquidity", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLocalLiquidityContainer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinimumLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getSupportedDestChains", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_localToken", - "outputs": [ - { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "chainSelector", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nativeBridgeFee", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "rebalanceLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "shouldWrapNative", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "receiveLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "removeLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "rep", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "ocrSeqNum", - "type": "uint64" - } - ], - "name": "report", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs", - "name": "crossChainLiqManager", - "type": "tuple" - } - ], - "name": "setCrossChainRebalancer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "crossChainRebalancers", - "type": "tuple[]" - } - ], - "name": "setCrossChainRebalancers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "finance", - "type": "address" - } - ], - "name": "setFinanceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ILiquidityContainer", - "name": "localLiquidityContainer", - "type": "address" - } - ], - "name": "setLocalLiquidityContainer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "minimumLiquidity", - "type": "uint256" - } - ], - "name": "setMinimumLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawERC20", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "destination", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json deleted file mode 100644 index 83a5b5b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogEmitter.json +++ /dev/null @@ -1,122 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "Log1", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "Log2", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "Log3", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "Log4", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "v", - "type": "uint256[]" - } - ], - "name": "EmitLog1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "v", - "type": "uint256[]" - } - ], - "name": "EmitLog2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "v", - "type": "string[]" - } - ], - "name": "EmitLog3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "w", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - } - ], - "name": "EmitLog4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json deleted file mode 100644 index 877d5fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogTriggeredStreamsLookup.json +++ /dev/null @@ -1,419 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bool", - "name": "_useArbitrumBlockNum", - "type": "bool" - }, - { - "internalType": "bool", - "name": "_verify", - "type": "bool" - }, - { - "internalType": "bool", - "name": "_checkErrReturnBool", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "IgnoringErrorHandlerData", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "exchange", - "type": "address" - } - ], - "name": "LimitOrderExecuted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "orderId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "exchange", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "blob", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "verified", - "type": "bytes" - } - ], - "name": "PerformingLogTriggerUpkeep", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkErrReturnBool", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "log", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkLog", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feedsHex", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParam", - "type": "string" - } - ], - "name": "setFeedParamKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "newFeeds", - "type": "string[]" - } - ], - "name": "setFeedsHex", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "timeParam", - "type": "string" - } - ], - "name": "setTimeParamKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "start", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbitrumBlockNum", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "verify", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json deleted file mode 100644 index c9b1fd9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/LogUpkeepCounter.json +++ /dev/null @@ -1,321 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "lastBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "counter", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Trigger", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "a", - "type": "uint256" - } - ], - "name": "Trigger", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "a", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "b", - "type": "uint256" - } - ], - "name": "Trigger", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "a", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "b", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "c", - "type": "uint256" - } - ], - "name": "Trigger", - "type": "event" - }, - { - "inputs": [], - "name": "autoExecution", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "log", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkLog", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "previousPerformBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_auto", - "type": "bool" - } - ], - "name": "setAuto", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - } - ], - "name": "setSpread", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "start", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json deleted file mode 100644 index 57999bd..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousChainlinked.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json deleted file mode 100644 index 3c6f738..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConfigurationContract.json +++ /dev/null @@ -1,85 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "capabilityWithConfigContractId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [], - "name": "CapabilityConfigurationSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "name": "beforeCapabilityConfigSet", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "name": "getCapabilityConfiguration", - "outputs": [ - { - "internalType": "bytes", - "name": "configuration", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json deleted file mode 100644 index 394fcb4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousConsumer.json +++ /dev/null @@ -1,194 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "assertFail", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "cancelRequestOnFulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "doesNothing", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "remove", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_callbackFunc", - "type": "bytes" - } - ], - "name": "requestData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "stealEthCall", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "stealEthSend", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "stealEthTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json deleted file mode 100644 index 3f3c063..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousMultiWordConsumer.json +++ /dev/null @@ -1,194 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "assertFail", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "cancelRequestOnFulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "doesNothing", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "remove", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_callbackFunc", - "type": "bytes" - } - ], - "name": "requestData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "stealEthCall", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "stealEthSend", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "stealEthTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json deleted file mode 100644 index d66181e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousReportReceiver.json +++ /dev/null @@ -1,71 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "mercuryReports", - "type": "bytes[]" - } - ], - "name": "MessageReceived", - "type": "event" - }, - { - "inputs": [], - "name": "latestReport", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - } - ], - "name": "onReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json deleted file mode 100644 index ef0dd9d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRequester.json +++ /dev/null @@ -1,167 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "doesNothing", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - } - ], - "name": "maliciousPrice", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_callbackFunc", - "type": "bytes" - } - ], - "name": "maliciousRequestCancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - } - ], - "name": "maliciousTargetConsumer", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "maliciousWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_id", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_callbackFunc", - "type": "bytes" - } - ], - "name": "request", - "outputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json deleted file mode 100644 index 624fce5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MaliciousRevertingReceiver.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "onReport", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json deleted file mode 100644 index e75de3c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Math.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - { - "inputs": [], - "name": "MathOverflowedMulDiv", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json deleted file mode 100644 index 831a2be..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistry.json +++ /dev/null @@ -1,594 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string[]", - "name": "feedIds", - "type": "string[]" - }, - { - "internalType": "string[]", - "name": "feedNames", - "type": "string[]" - }, - { - "internalType": "int192[]", - "name": "deviationPercentagePPMs", - "type": "int192[]" - }, - { - "internalType": "uint32[]", - "name": "stalenessSeconds", - "type": "uint32[]" - }, - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedId", - "type": "string" - } - ], - "name": "DuplicateFeed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedId", - "type": "string" - } - ], - "name": "FeedNotActive", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeeds", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedId", - "type": "string" - }, - { - "internalType": "uint32", - "name": "currentTimestamp", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "incomingTimestamp", - "type": "uint32" - } - ], - "name": "StaleReport", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "observationsTimestamp", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int192", - "name": "price", - "type": "int192" - }, - { - "indexed": false, - "internalType": "int192", - "name": "bid", - "type": "int192" - }, - { - "indexed": false, - "internalType": "int192", - "name": "ask", - "type": "int192" - }, - { - "indexed": false, - "internalType": "string", - "name": "feedId", - "type": "string" - } - ], - "name": "FeedUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "feedIds", - "type": "string[]" - }, - { - "internalType": "string[]", - "name": "feedNames", - "type": "string[]" - }, - { - "internalType": "int192[]", - "name": "deviationPercentagePPMs", - "type": "int192[]" - }, - { - "internalType": "uint32[]", - "name": "stalenessSeconds", - "type": "uint32[]" - } - ], - "name": "addFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "lookupData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int192", - "name": "onChain", - "type": "int192" - }, - { - "internalType": "int192", - "name": "offChain", - "type": "int192" - }, - { - "internalType": "int192", - "name": "deviationPercentagePPM", - "type": "int192" - } - ], - "name": "deviationExceedsThreshold", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "feedIds", - "type": "string[]" - } - ], - "name": "getLatestFeedData", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "observationsTimestamp", - "type": "uint32" - }, - { - "internalType": "int192", - "name": "price", - "type": "int192" - }, - { - "internalType": "int192", - "name": "bid", - "type": "int192" - }, - { - "internalType": "int192", - "name": "ask", - "type": "int192" - }, - { - "internalType": "string", - "name": "feedName", - "type": "string" - }, - { - "internalType": "string", - "name": "feedId", - "type": "string" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "int192", - "name": "deviationPercentagePPM", - "type": "int192" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - } - ], - "internalType": "struct MercuryRegistry.Feed[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - } - ], - "name": "revertForFeedLookup", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "name": "s_feedMapping", - "outputs": [ - { - "internalType": "uint32", - "name": "observationsTimestamp", - "type": "uint32" - }, - { - "internalType": "int192", - "name": "price", - "type": "int192" - }, - { - "internalType": "int192", - "name": "bid", - "type": "int192" - }, - { - "internalType": "int192", - "name": "ask", - "type": "int192" - }, - { - "internalType": "string", - "name": "feedName", - "type": "string" - }, - { - "internalType": "string", - "name": "feedId", - "type": "string" - }, - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "int192", - "name": "deviationPercentagePPM", - "type": "int192" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_feeds", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_verifier", - "outputs": [ - { - "internalType": "contract IVerifierProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "feedIds", - "type": "string[]" - }, - { - "internalType": "string[]", - "name": "feedNames", - "type": "string[]" - }, - { - "internalType": "int192[]", - "name": "deviationPercentagePPMs", - "type": "int192[]" - }, - { - "internalType": "uint32[]", - "name": "stalenessSeconds", - "type": "uint32[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "name": "setVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json deleted file mode 100644 index 4d6c39f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MercuryRegistryBatchUpkeep.json +++ /dev/null @@ -1,306 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "mercuryRegistry", - "type": "address" - }, - { - "internalType": "uint256", - "name": "batchStart", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "batchEnd", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "batchsize", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxBatchSize", - "type": "uint256" - } - ], - "name": "BatchSizeTooLarge", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "MAX_BATCH_SIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "lookupData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_registry", - "outputs": [ - { - "internalType": "contract MercuryRegistry", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_batchEnd", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_batchStart", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "batchStart", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "batchEnd", - "type": "uint256" - } - ], - "name": "updateBatchingWindow", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json deleted file mode 100644 index f938ae8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterface.json +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIDs", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTranscoderVersion", - "outputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "version", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json deleted file mode 100644 index 09b1ae3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MigratableKeeperRegistryInterfaceV2.json +++ /dev/null @@ -1,46 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIDs", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json deleted file mode 100644 index da51df1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregator.json +++ /dev/null @@ -1,67 +0,0 @@ -[ - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "newRoundCalled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "requestNewRound", - "outputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_answer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "answer", - "type": "int256" - } - ], - "name": "setLatestAnswer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json deleted file mode 100644 index 3178781..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorProxy.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_aggregator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "aggregator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_aggregator", - "type": "address" - } - ], - "name": "updateAggregator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json deleted file mode 100644 index f105b55..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorV2V3.json +++ /dev/null @@ -1,240 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json deleted file mode 100644 index 130b3bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockAggregatorValidator.json +++ /dev/null @@ -1,84 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint8", - "name": "id_", - "type": "uint8" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "id", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "ValidateCalled", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json deleted file mode 100644 index ba3d9bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbGasInfo.json +++ /dev/null @@ -1,53 +0,0 @@ -[ - { - "inputs": [], - "name": "getCurrentTxL1GasFees", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPricesInWei", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json deleted file mode 100644 index 4170e94..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbSys.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "arbBlockNum", - "type": "uint256" - } - ], - "name": "arbBlockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "arbBlockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json deleted file mode 100644 index 20aa581..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockArbitrumInbox.json +++ /dev/null @@ -1,462 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "InboxMessageDelivered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "messageNum", - "type": "uint256" - } - ], - "name": "InboxMessageDeliveredFromOrigin", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "RetryableTicketNoRefundAliasRewriteCreated", - "type": "event" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "contract IBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "baseFee", - "type": "uint256" - } - ], - "name": "calculateRetryableSubmissionFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "createRetryableTicket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "destAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "arbTxCallValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSubmissionCost", - "type": "uint256" - }, - { - "internalType": "address", - "name": "submissionRefundAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "valueRefundAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasPriceBid", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "createRetryableTicketNoRefundAliasRewrite", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "depositEth", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "depositEthRetryable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendL1FundedContractTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendL1FundedUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendL2Message", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendUnsignedTransaction", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json deleted file mode 100644 index 5761ba0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockBridgehub.json +++ /dev/null @@ -1,795 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "msg", - "type": "string" - } - ], - "name": "NotAuthorized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldAdmin", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "NewAdmin", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "stateTransitionManager", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "chainGovernance", - "type": "address" - } - ], - "name": "NewChain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "oldPendingAdmin", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newPendingAdmin", - "type": "address" - } - ], - "name": "NewPendingAdmin", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [], - "name": "acceptAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stateTransitionManager", - "type": "address" - } - ], - "name": "addStateTransitionManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - } - ], - "name": "addToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - } - ], - "name": "baseToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "name": "baseTokens", - "outputs": [ - { - "internalType": "address", - "name": "baseToken", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_stateTransitionManager", - "type": "address" - }, - { - "internalType": "address", - "name": "_baseToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "createNewChain", - "outputs": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - } - ], - "name": "getHyperchain", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "name": "hyperchains", - "outputs": [ - { - "internalType": "address", - "name": "hyperChain", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "l2TransactionBaseCost", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "pendingAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "enum TxStatus", - "name": "", - "type": "uint8" - } - ], - "name": "proveL1ToL2TransactionStatus", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "l2ShardId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "isService", - "type": "bool" - }, - { - "internalType": "uint16", - "name": "txNumberInBatch", - "type": "uint16" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - } - ], - "internalType": "struct L2Log", - "name": "", - "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "name": "proveL2LogInclusion", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint16", - "name": "txNumberInBatch", - "type": "uint16" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct L2Message", - "name": "", - "type": "tuple" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "name": "proveL2MessageInclusion", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "stateTransitionManager", - "type": "address" - } - ], - "name": "registeredStateTransitionManagers", - "outputs": [ - { - "internalType": "bool", - "name": "stateTransitionManagerIsRegistered", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "baseToken", - "type": "address" - } - ], - "name": "registeredTokens", - "outputs": [ - { - "internalType": "bool", - "name": "tokenIsRegistered", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stateTransitionManager", - "type": "address" - } - ], - "name": "removeStateTransitionManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "mintValue", - "type": "uint256" - }, - { - "internalType": "address", - "name": "l2Contract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "l2Value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "l2Calldata", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "l2GasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2GasPerPubdataByteLimit", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "factoryDeps", - "type": "bytes[]" - }, - { - "internalType": "address", - "name": "refundRecipient", - "type": "address" - } - ], - "internalType": "struct L2TransactionRequestDirect", - "name": "txRequest", - "type": "tuple" - } - ], - "name": "requestL2TransactionDirect", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "mintValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2Value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2GasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "l2GasPerPubdataByteLimit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "refundRecipient", - "type": "address" - }, - { - "internalType": "address", - "name": "secondBridgeAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "secondBridgeValue", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "secondBridgeCalldata", - "type": "bytes" - } - ], - "internalType": "struct L2TransactionRequestTwoBridgesOuter", - "name": "", - "type": "tuple" - } - ], - "name": "requestL2TransactionTwoBridges", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_newPendingAdmin", - "type": "address" - } - ], - "name": "setPendingAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sharedBridgeAddr", - "type": "address" - } - ], - "name": "setSharedBridge", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "sharedBridge", - "outputs": [ - { - "internalType": "contract IL1SharedBridge", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sharedBridgeAddr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_chainId", - "type": "uint256" - } - ], - "name": "stateTransitionManager", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_stateTransitionManager", - "type": "address" - } - ], - "name": "stateTransitionManagerIsRegistered", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "chainId", - "type": "uint256" - } - ], - "name": "stateTransitionManagers", - "outputs": [ - { - "internalType": "address", - "name": "stateTransitionManagerAddress", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_baseToken", - "type": "address" - } - ], - "name": "tokenIsRegistered", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json deleted file mode 100644 index dafee02..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHLINKAggregator.json +++ /dev/null @@ -1,137 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "int256", - "name": "_answer", - "type": "int256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "answer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json deleted file mode 100644 index 760d0fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockETHUSDAggregator.json +++ /dev/null @@ -1,150 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "int256", - "name": "_answer", - "type": "int256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "answer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockTimestampDeduction", - "type": "uint256" - } - ], - "name": "setBlockTimestampDeduction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json deleted file mode 100644 index 65f9a26..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockGasBoundCaller.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "TransactionFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "gasAmount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "gasBoundCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json deleted file mode 100644 index 36750f8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockKeeperRegistry2_1.json +++ /dev/null @@ -1,138 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "updateCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json deleted file mode 100644 index 1b914f1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL1BridgeAdapter.json +++ /dev/null @@ -1,322 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IERC20", - "name": "token", - "type": "address" - }, - { - "internalType": "bool", - "name": "holdNative", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFinalizationAction", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [], - "name": "NativeSendFailed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - } - ], - "name": "NonceAlreadyUsed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - } - ], - "name": "NonceNotProven", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "provider", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "LiquidityRemoved", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct MockL1BridgeAdapter.FinalizePayload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodeFinalizePayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "enum MockL1BridgeAdapter.FinalizationAction", - "name": "action", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct MockL1BridgeAdapter.Payload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodePayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - } - ], - "internalType": "struct MockL1BridgeAdapter.ProvePayload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodeProvePayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "localReceiver", - "type": "address" - }, - { - "internalType": "bytes", - "name": "bridgeSpecificPayload", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "provideLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLiquidity", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json deleted file mode 100644 index 8df42ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockL2BridgeAdapter.json +++ /dev/null @@ -1,131 +0,0 @@ -[ - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json deleted file mode 100644 index 87147a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockLinkToken.json +++ /dev/null @@ -1,135 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "balances", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "setBalance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "totalTokensIssued", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json deleted file mode 100644 index 01ef6d2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMCrossDomainMessenger.json +++ /dev/null @@ -1,101 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "_setMockMessageSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json deleted file mode 100644 index b4532b3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOVMGasPriceOracle.json +++ /dev/null @@ -1,40 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "getL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getL1FeeUpperBound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json deleted file mode 100644 index 3b7e646..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOffchainAggregator.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - } - ], - "name": "RoundIdUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "requestNewRound", - "outputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "roundId", - "outputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json deleted file mode 100644 index f2612dc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL1CrossDomainMessenger.json +++ /dev/null @@ -1,238 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_messageNonce", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "batchIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "batchRoot", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "batchSize", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "prevTotalElements", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "internalType": "struct Lib_OVMCodec.ChainBatchHeader", - "name": "stateRootBatchHeader", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "bytes32[]", - "name": "siblings", - "type": "bytes32[]" - } - ], - "internalType": "struct Lib_OVMCodec.ChainInclusionProof", - "name": "stateRootProof", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "stateTrieWitness", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "storageTrieWitness", - "type": "bytes" - } - ], - "internalType": "struct IL1CrossDomainMessenger.L2MessageInclusionProof", - "name": "_proof", - "type": "tuple" - } - ], - "name": "relayMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_queueIndex", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_oldGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_newGasLimit", - "type": "uint32" - } - ], - "name": "replayMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "_gasLimit", - "type": "uint32" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json deleted file mode 100644 index eaf980a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockOptimismL2CrossDomainMessenger.json +++ /dev/null @@ -1,146 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_messageNonce", - "type": "uint256" - } - ], - "name": "relayMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "_gasLimit", - "type": "uint32" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newSender", - "type": "address" - } - ], - "name": "setSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json deleted file mode 100644 index e8f355d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockReceiver.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "inputs": [], - "name": "getValue", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "receiveData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "revertMessage", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json deleted file mode 100644 index 3a579fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollCrossDomainMessenger.json +++ /dev/null @@ -1,169 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "_setMockMessageSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json deleted file mode 100644 index e220cef..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1CrossDomainMessenger.json +++ /dev/null @@ -1,284 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "maxReplayTimes", - "type": "uint256" - } - ], - "name": "UpdateMaxReplayTimes", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "dropMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "batchIndex", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "merkleProof", - "type": "bytes" - } - ], - "internalType": "struct IL1ScrollMessenger.L2MessageProof", - "name": "proof", - "type": "tuple" - } - ], - "name": "relayMessageWithProof", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "newGasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "refundAddress", - "type": "address" - } - ], - "name": "replayMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json deleted file mode 100644 index bab0cce..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL1MessageQueue.json +++ /dev/null @@ -1,302 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "skippedBitmap", - "type": "uint256" - } - ], - "name": "DequeueTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "DropTransaction", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "queueIndex", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "QueueTransaction", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "appendCrossDomainMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "appendEnforcedTransaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "calculateIntrinsicGasFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "computeTransactionHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "dropCrossDomainMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "estimateCrossDomainMessageFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getCrossDomainMessage", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "nextCrossDomainMessageIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "pendingQueueIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "skippedBitmap", - "type": "uint256" - } - ], - "name": "popCrossDomainMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json deleted file mode 100644 index 4dab44f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockScrollL2CrossDomainMessenger.json +++ /dev/null @@ -1,195 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "messageHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "messageNonce", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "relayMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "_gasLimit", - "type": "uint256" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newSender", - "type": "address" - } - ], - "name": "setSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json deleted file mode 100644 index d3fc208..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockUpkeep.json +++ /dev/null @@ -1,218 +0,0 @@ -[ - { - "inputs": [], - "name": "CheckRevert", - "type": "error" - }, - { - "inputs": [], - "name": "PerformRevert", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "upkeepData", - "type": "bytes" - } - ], - "name": "UpkeepPerformedWith", - "type": "event" - }, - { - "inputs": [], - "name": "checkGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkResult", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "callable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "executedata", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performData", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setCheckGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setCheckResult", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "setPerformData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldCheckRevert", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldPerformRevert", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "shouldCheckRevert", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "shouldPerformRevert", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json deleted file mode 100644 index bd452b6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockV3Aggregator.json +++ /dev/null @@ -1,297 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - }, - { - "internalType": "int256", - "name": "_initialAnswer", - "type": "int256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "_answer", - "type": "int256" - } - ], - "name": "updateAnswer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "_answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "_timestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_startedAt", - "type": "uint256" - } - ], - "name": "updateRoundData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json deleted file mode 100644 index b8a632e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MockZKSyncSystemContext.json +++ /dev/null @@ -1,41 +0,0 @@ -[ - { - "inputs": [], - "name": "gasPerPubdataByte", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "gasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPubdataSpent", - "outputs": [ - { - "internalType": "uint256", - "name": "currentPubdataSpent", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json deleted file mode 100644 index 89d3ba5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiSend.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "transactions", - "type": "bytes" - } - ], - "name": "multiSend", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json deleted file mode 100644 index bf30425..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/MultiWordConsumer.json +++ /dev/null @@ -1,432 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_specId", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkCancelled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "id", - "type": "bytes32" - } - ], - "name": "ChainlinkRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes", - "name": "price", - "type": "bytes" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "usd", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "eur", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "jpy", - "type": "bytes32" - } - ], - "name": "RequestMultipleFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "usd", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "eur", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "jpy", - "type": "uint256" - } - ], - "name": "RequestMultipleFulfilledWithCustomURLs", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - } - ], - "name": "addExternalRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_oracle", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "_callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "_expiration", - "type": "uint256" - } - ], - "name": "cancelRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "eur", - "outputs": [ - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_price", - "type": "bytes" - } - ], - "name": "fulfillBytes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_usd", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_eur", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_jpy", - "type": "bytes32" - } - ], - "name": "fulfillMultipleParameters", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_usd", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_eur", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_jpy", - "type": "uint256" - } - ], - "name": "fulfillMultipleParametersWithCustomURLs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentPrice", - "outputs": [ - { - "internalType": "bytes", - "name": "_value", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "jpy", - "outputs": [ - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "publicGetNextRequestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestEthereumPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestMultipleParameters", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_urlUSD", - "type": "string" - }, - { - "internalType": "string", - "name": "_pathUSD", - "type": "string" - }, - { - "internalType": "string", - "name": "_urlEUR", - "type": "string" - }, - { - "internalType": "string", - "name": "_pathEUR", - "type": "string" - }, - { - "internalType": "string", - "name": "_urlJPY", - "type": "string" - }, - { - "internalType": "string", - "name": "_pathJPY", - "type": "string" - }, - { - "internalType": "uint256", - "name": "_payment", - "type": "uint256" - } - ], - "name": "requestMultipleParametersWithCustomURLs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_specId", - "type": "bytes32" - } - ], - "name": "setSpecID", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usd", - "outputs": [ - { - "internalType": "bytes32", - "name": "_value", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json deleted file mode 100644 index 58bd2e2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/NoOpOCR3.json +++ /dev/null @@ -1,396 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "expected", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "actual", - "type": "bytes32" - } - ], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "ForkedChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestSequenceNumber", - "type": "uint64" - } - ], - "name": "NonIncreasingSequenceNumber", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "OracleCannotBeZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "SignaturesOutOfRegistration", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "WrongMessageLength", - "type": "error" - }, - { - "inputs": [], - "name": "WrongNumberOfSignatures", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json deleted file mode 100644 index ebbdd3d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Abstract.json +++ /dev/null @@ -1,212 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "signers", - "type": "bytes[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "signers", - "type": "bytes[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json deleted file mode 100644 index 8089c1b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR2Base.json +++ /dev/null @@ -1,318 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "ReportInvalid", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "_signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "transmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json deleted file mode 100644 index 25d717e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Abstract.json +++ /dev/null @@ -1,189 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json deleted file mode 100644 index 6ce23e3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Base.json +++ /dev/null @@ -1,391 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "expected", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "actual", - "type": "bytes32" - } - ], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "ForkedChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestSequenceNumber", - "type": "uint64" - } - ], - "name": "NonIncreasingSequenceNumber", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "OracleCannotBeZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "SignaturesOutOfRegistration", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "WrongMessageLength", - "type": "error" - }, - { - "inputs": [], - "name": "WrongNumberOfSignatures", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json deleted file mode 100644 index 3e46109..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Capability.json +++ /dev/null @@ -1,299 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [], - "name": "ReportingUnsupported", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "signers", - "type": "bytes[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "_signers", - "type": "bytes[]" - }, - { - "internalType": "address[]", - "name": "_transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "_f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "_onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "_offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "_offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json deleted file mode 100644 index e2d24b2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OCR3Helper.json +++ /dev/null @@ -1,463 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "expected", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "actual", - "type": "bytes32" - } - ], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "ForkedChain", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "latestSequenceNumber", - "type": "uint64" - } - ], - "name": "NonIncreasingSequenceNumber", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "OracleCannotBeZeroAddress", - "type": "error" - }, - { - "inputs": [], - "name": "SignaturesOutOfRegistration", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "WrongMessageLength", - "type": "error" - }, - { - "inputs": [], - "name": "WrongNumberOfSignatures", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "chainSelector", - "type": "uint256" - }, - { - "internalType": "address", - "name": "contractAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "configDigestFromConfigData", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmitters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestSequenceNumber", - "outputs": [ - { - "internalType": "uint64", - "name": "sequenceNumber", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newSeqNum", - "type": "uint64" - } - ], - "name": "setLatestSeqNum", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setOCR3Config", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "report", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json deleted file mode 100644 index 735c1b6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OVM_GasPriceOracle.json +++ /dev/null @@ -1,298 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "DecimalsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "GasPriceUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "L1BaseFeeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "OverheadUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "ScalarUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "getL1GasUsed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1BaseFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "overhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "scalar", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_decimals", - "type": "uint256" - } - ], - "name": "setDecimals", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_gasPrice", - "type": "uint256" - } - ], - "name": "setGasPrice", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_baseFee", - "type": "uint256" - } - ], - "name": "setL1BaseFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_overhead", - "type": "uint256" - } - ], - "name": "setOverhead", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_scalar", - "type": "uint256" - } - ], - "name": "setScalar", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json deleted file mode 100644 index f995689..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OpStackBurnMintERC677.json +++ /dev/null @@ -1,820 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "string", - "name": "symbol", - "type": "string" - }, - { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "maxSupply_", - "type": "uint256" - }, - { - "internalType": "address", - "name": "l1Token", - "type": "address" - }, - { - "internalType": "address", - "name": "l2Bridge", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "supplyAfterMint", - "type": "uint256" - } - ], - "name": "MaxSupplyExceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotBurner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "SenderNotMinter", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "BurnAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "MintAccessRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burnFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseApproval", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBurners", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getMinters", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "grantBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burnAndMinter", - "type": "address" - } - ], - "name": "grantMintAndBurnRoles", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "grantMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseApproval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "isBurner", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "isMinter", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "maxSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "remoteToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "burner", - "type": "address" - } - ], - "name": "revokeBurnRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "revokeMintRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "transferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json deleted file mode 100644 index fb0892e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Operator.json +++ /dev/null @@ -1,738 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "CancelOracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "specId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "requester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "callbackAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "cancelExpiration", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "OracleRequest", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - } - ], - "name": "OracleResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "acceptedContract", - "type": "address" - } - ], - "name": "OwnableContractAccepted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "TargetsUpdatedAuthorizedSenders", - "type": "event" - }, - { - "inputs": [], - "name": "EXPIRYTIME", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "acceptAuthorizedReceivers", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "ownable", - "type": "address[]" - } - ], - "name": "acceptOwnableContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "callbackFunc", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "cancelOracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "callbackFunc", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "cancelOracleRequestByRequester", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "distributeFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "fulfillOracleRequest", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "fulfillOracleRequest2", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAuthorizedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getChainlinkToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isAuthorizedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "specId", - "type": "bytes32" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "operatorRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "specId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "oracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ownerForward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ownerTransferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSenders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "targets", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSendersOn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "ownable", - "type": "address[]" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnableContracts", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json deleted file mode 100644 index ea31a35..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorFactory.json +++ /dev/null @@ -1,176 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "forwarder", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "AuthorizedForwarderCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "OperatorCreated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "created", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "deployNewForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "deployNewForwarderAndTransferOwnership", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "deployNewOperator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "deployNewOperatorAndForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json deleted file mode 100644 index b5d92c0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OperatorInterface.json +++ /dev/null @@ -1,287 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - } - ], - "name": "cancelOracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable[]", - "name": "receivers", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - } - ], - "name": "distributeFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "fulfillOracleRequest", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "fulfillOracleRequest2", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "specId", - "type": "bytes32" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "operatorRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "requestPrice", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "serviceAgreementID", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "dataVersion", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "oracleRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "ownerTransferAndCall", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json deleted file mode 100644 index ca8ded3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainForwarder.json +++ /dev/null @@ -1,204 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract iOVM_CrossDomainMessenger", - "name": "crossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json deleted file mode 100644 index 5840680..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismCrossDomainGovernor.json +++ /dev/null @@ -1,222 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract iOVM_CrossDomainMessenger", - "name": "crossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forwardDelegate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json deleted file mode 100644 index 599c939..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapter.json +++ /dev/null @@ -1,200 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IL1StandardBridge", - "name": "l1Bridge", - "type": "address" - }, - { - "internalType": "contract IWrappedNative", - "name": "wrappedNative", - "type": "address" - }, - { - "internalType": "contract IOptimismPortal", - "name": "optimismPortal", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFinalizationAction", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getL1Bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getOptimismPortal", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNative", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json deleted file mode 100644 index 4322d1e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1BridgeAdapterEncoder.json +++ /dev/null @@ -1,168 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "enum OptimismL1BridgeAdapter.FinalizationAction", - "name": "action", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodeFinalizeWithdrawalERC20Payload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Types.WithdrawalTransaction", - "name": "withdrawalTransaction", - "type": "tuple" - } - ], - "internalType": "struct OptimismL1BridgeAdapter.OptimismFinalizationPayload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodeOptimismFinalizationPayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Types.WithdrawalTransaction", - "name": "withdrawalTransaction", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "l2OutputIndex", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "version", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "messagePasserStorageRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "latestBlockhash", - "type": "bytes32" - } - ], - "internalType": "struct Types.OutputRootProof", - "name": "outputRootProof", - "type": "tuple" - }, - { - "internalType": "bytes[]", - "name": "withdrawalProof", - "type": "bytes[]" - } - ], - "internalType": "struct OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload", - "name": "payload", - "type": "tuple" - } - ], - "name": "encodeOptimismProveWithdrawalPayload", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json deleted file mode 100644 index 142c04f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL1Fees.json +++ /dev/null @@ -1,158 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCalculationMode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCalculationSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCalculationMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCoefficient", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json deleted file mode 100644 index 9c13a13..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismL2BridgeAdapter.json +++ /dev/null @@ -1,172 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IWrappedNative", - "name": "wrappedNative", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BridgeAddressCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wanted", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "got", - "type": "uint256" - } - ], - "name": "InsufficientEthValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "MsgShouldNotContainValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "msgValue", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MsgValueDoesNotMatchAmount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "finalizeWithdrawERC20", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getBridgeFeeInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getL2Bridge", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNative", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "localToken", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "sendERC20", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json deleted file mode 100644 index a94b46f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModule.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json deleted file mode 100644 index 57b3556..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismModuleV2.json +++ /dev/null @@ -1,216 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCoefficientSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getL1FeeCoefficient", - "outputs": [ - { - "internalType": "uint256", - "name": "coefficient", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json deleted file mode 100644 index 730bea0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismSequencerUptimeFeed.json +++ /dev/null @@ -1,583 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1SenderAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l2CrossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "bool", - "name": "initialStatus", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidSender", - "type": "error" - }, - { - "inputs": [], - "name": "NoDataPresent", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1SenderTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "int256", - "name": "status", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "updatedAt", - "type": "uint64" - } - ], - "name": "RoundUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "latestStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "latestTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bool", - "name": "incomingStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "incomingTimestamp", - "type": "uint64" - } - ], - "name": "UpdateIgnored", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Sender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json deleted file mode 100644 index e6131b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OptimismValidator.json +++ /dev/null @@ -1,335 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1CrossDomainMessengerAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l2UptimeFeedAddr", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "L1CrossDomainMessengerAddressZero", - "type": "error" - }, - { - "inputs": [], - "name": "L2UptimeFeedAddrZero", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "GasLimitUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_UPTIME_FEED_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getGasLimit", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json deleted file mode 100644 index d74508e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OracleInterface.json +++ /dev/null @@ -1,77 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "payment", - "type": "uint256" - }, - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "bytes4", - "name": "callbackFunctionId", - "type": "bytes4" - }, - { - "internalType": "uint256", - "name": "expiration", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "data", - "type": "bytes32" - } - ], - "name": "fulfillOracleRequest", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json deleted file mode 100644 index 890a79d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/OwnerIsCreator.json +++ /dev/null @@ -1,78 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json deleted file mode 100644 index 8b939e6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Pausable.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "inputs": [], - "name": "EnforcedPause", - "type": "error" - }, - { - "inputs": [], - "name": "ExpectedPause", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json deleted file mode 100644 index 71e27ff..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Paymaster.json +++ /dev/null @@ -1,359 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "linkToken", - "type": "address" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "linkEthFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "entryPoint", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "juelsNeeded", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "subscriptionBalance", - "type": "uint256" - } - ], - "name": "InsufficientFunds", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "Unauthorized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - } - ], - "name": "UserOperationAlreadyTried", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "i_entryPoint", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkEthFeed", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "enum IPaymaster.PostOpMode", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "actualGasCost", - "type": "uint256" - } - ], - "name": "postOp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "maxCost", - "type": "uint256" - } - ], - "name": "validatePaymasterUserOp", - "outputs": [ - { - "internalType": "bytes", - "name": "context", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "validationData", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json deleted file mode 100644 index 8c976c3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PerformDataChecker.json +++ /dev/null @@ -1,89 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "expectedData", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_expectedData", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "expectedData", - "type": "bytes" - } - ], - "name": "setExpectedData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json deleted file mode 100644 index 2e61e1e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PermissionedForwardProxy.json +++ /dev/null @@ -1,183 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "PermissionNotSet", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "PermissionRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "PermissionSet", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "handler", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "getPermission", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "removePermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "setPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json deleted file mode 100644 index 5f3bb0b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PoRAddressList.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getPoRAddressList", - "outputs": [ - { - "internalType": "string[]", - "name": "", - "type": "string[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPoRAddressListLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json deleted file mode 100644 index c5ae2c8..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/PointerInterface.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "getAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json deleted file mode 100644 index c1dd512..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Proxy.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json deleted file mode 100644 index 6a75bdb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveEmitter.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "FundsReceived", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json deleted file mode 100644 index 7c7fdcf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveFallbackEmitter.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "FundsReceived", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json deleted file mode 100644 index d48d964..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReceiveReverter.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json deleted file mode 100644 index 3f30efb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Receiver.json +++ /dev/null @@ -1,76 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes[]", - "name": "mercuryReports", - "type": "bytes[]" - } - ], - "name": "MessageReceived", - "type": "event" - }, - { - "inputs": [], - "name": "latestReport", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "metadata", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - } - ], - "name": "onReport", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json deleted file mode 100644 index 3afbe73..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ReportEncoder.json +++ /dev/null @@ -1,124 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nativeBridgeFee", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "bridgeData", - "type": "bytes" - } - ], - "internalType": "struct ILiquidityManager.SendLiquidityParams[]", - "name": "sendLiquidityParams", - "type": "tuple[]" - }, - { - "components": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "shouldWrapNative", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "bridgeData", - "type": "bytes" - } - ], - "internalType": "struct ILiquidityManager.ReceiveLiquidityParams[]", - "name": "receiveLiquidityParams", - "type": "tuple[]" - } - ], - "internalType": "struct ILiquidityManager.LiquidityInstructions", - "name": "instructions", - "type": "tuple" - } - ], - "name": "exposeForEncoding", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getAllCrossChainRebalancers", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "remoteRebalancer", - "type": "address" - }, - { - "internalType": "contract IBridgeAdapter", - "name": "localBridge", - "type": "address" - }, - { - "internalType": "address", - "name": "remoteToken", - "type": "address" - }, - { - "internalType": "uint64", - "name": "remoteChainSelector", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - } - ], - "internalType": "struct ILiquidityManager.CrossChainRebalancerArgs[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLiquidity", - "outputs": [ - { - "internalType": "uint256", - "name": "currentLiquidity", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json deleted file mode 100644 index bbe09c3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/RewardManager.json +++ /dev/null @@ -1,535 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidAddress", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPoolId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPoolLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWeights", - "type": "error" - }, - { - "inputs": [], - "name": "Unauthorized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newFeeManagerAddress", - "type": "address" - } - ], - "name": "FeeManagerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "indexed": false, - "internalType": "struct IRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "payer", - "type": "address" - } - ], - "name": "FeePaid", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "indexed": false, - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "RewardRecipientsUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint192", - "name": "quantity", - "type": "uint192" - } - ], - "name": "RewardsClaimed", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "poolIds", - "type": "bytes32[]" - } - ], - "name": "claimRewards", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "endIndex", - "type": "uint256" - } - ], - "name": "getAvailableRewardPoolIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_linkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "uint192", - "name": "amount", - "type": "uint192" - } - ], - "internalType": "struct IRewardManager.FeePayment[]", - "name": "payments", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "payer", - "type": "address" - } - ], - "name": "onFeePaid", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "recipients", - "type": "address[]" - } - ], - "name": "payRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManagerAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_registeredPoolIds", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_rewardRecipientWeights", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_rewardRecipientWeightsSet", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_totalRewardRecipientFees", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_totalRewardRecipientFeesLastClaimedAmounts", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newFeeManagerAddress", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "rewardRecipientAndWeights", - "type": "tuple[]" - } - ], - "name": "setRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "poolId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "newRewardRecipients", - "type": "tuple[]" - } - ], - "name": "updateRewardRecipients", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json deleted file mode 100644 index 35733b2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Routable.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlyCallableByRouter", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByRouterOwner", - "type": "error" - }, - { - "inputs": [], - "name": "RouterMustBeSet", - "type": "error" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json deleted file mode 100644 index e16ec27..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SCA.json +++ /dev/null @@ -1,235 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "entryPoint", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "BadFormatOrOOG", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentNonce", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "nonceGiven", - "type": "uint256" - } - ], - "name": "IncorrectNonce", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "operationHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "NotAuthorized", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "currentTimestamp", - "type": "uint256" - } - ], - "name": "TransactionExpired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint48", - "name": "deadline", - "type": "uint48" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "executeTransactionFromEntryPoint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "i_entryPoint", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_nonce", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "nonce", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "callData", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "callGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "verificationGasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preVerificationGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxFeePerGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxPriorityFeePerGas", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "paymasterAndData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "signature", - "type": "bytes" - } - ], - "internalType": "struct UserOperation", - "name": "userOp", - "type": "tuple" - }, - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "validateUserOp", - "outputs": [ - { - "internalType": "uint256", - "name": "validationData", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json deleted file mode 100644 index 6627861..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeCast.json +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint8", - "name": "bits", - "type": "uint8" - }, - { - "internalType": "int256", - "name": "value", - "type": "int256" - } - ], - "name": "SafeCastOverflowedIntDowncast", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "value", - "type": "int256" - } - ], - "name": "SafeCastOverflowedIntToUint", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "bits", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "SafeCastOverflowedUintDowncast", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "SafeCastOverflowedUintToInt", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json deleted file mode 100644 index ef89440..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SafeERC20.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "currentAllowance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestedDecrease", - "type": "uint256" - } - ], - "name": "SafeERC20FailedDecreaseAllowance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "SafeERC20FailedOperation", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json deleted file mode 100644 index 8fb5c53..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainForwarder.json +++ /dev/null @@ -1,204 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IScrollMessenger", - "name": "crossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json deleted file mode 100644 index bf50b2b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollCrossDomainGovernor.json +++ /dev/null @@ -1,222 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract IScrollMessenger", - "name": "crossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l1OwnerAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "crossDomainMessenger", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forwardDelegate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "l1Owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Ownership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json deleted file mode 100644 index df53c59..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollModule.json +++ /dev/null @@ -1,216 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCoefficientSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockNumber", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getCurrentL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "chainModuleFixedOverhead", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "chainModulePerByteOverhead", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL1FeeCoefficient", - "outputs": [ - { - "internalType": "uint256", - "name": "coefficient", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "dataSize", - "type": "uint256" - } - ], - "name": "getMaxL1Fee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json deleted file mode 100644 index 0177ef2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollSequencerUptimeFeed.json +++ /dev/null @@ -1,588 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1SenderAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l2CrossDomainMessengerAddr", - "type": "address" - }, - { - "internalType": "bool", - "name": "initialStatus", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidSender", - "type": "error" - }, - { - "inputs": [], - "name": "NoDataPresent", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1SenderTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "int256", - "name": "status", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "updatedAt", - "type": "uint64" - } - ], - "name": "RoundUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "latestStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "latestTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bool", - "name": "incomingStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "incomingTimestamp", - "type": "uint64" - } - ], - "name": "UpdateIgnored", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Sender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json deleted file mode 100644 index bee27a4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ScrollValidator.json +++ /dev/null @@ -1,353 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1CrossDomainMessengerAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l2UptimeFeedAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "l1MessageQueueAddr", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "L1CrossDomainMessengerAddressZero", - "type": "error" - }, - { - "inputs": [], - "name": "L2UptimeFeedAddrZero", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "GasLimitUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L1_MSG_QUEUE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_UPTIME_FEED_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getGasLimit", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json deleted file mode 100644 index 55febb5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SenderCreator.json +++ /dev/null @@ -1,21 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "name": "createSender", - "outputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json deleted file mode 100644 index 24589f2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ShortStrings.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidShortString", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "str", - "type": "string" - } - ], - "name": "StringTooLong", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json deleted file mode 100644 index 803b2a4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleLogUpkeepCounter.json +++ /dev/null @@ -1,445 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bool", - "name": "_isStreamsLookup", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "lastBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "counter", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "timeToPerform", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isRecovered", - "type": "bool" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "checkBurnAmount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "performBurnAmount", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "eventSig", - "type": "bytes32" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - } - ], - "internalType": "struct CheckData", - "name": "", - "type": "tuple" - } - ], - "name": "_checkDataConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "log", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkLog", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "isStreamsLookup", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "previousPerformBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParam", - "type": "string" - } - ], - "name": "setFeedParamKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldRetryOnErrorBool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "timeParam", - "type": "string" - } - ], - "name": "setTimeParamKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "shouldRetryOnError", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "timeToPerform", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json deleted file mode 100644 index e7a38bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleReadAccessController.json +++ /dev/null @@ -1,188 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json deleted file mode 100644 index ecc2ca0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SimpleWriteAccessController.json +++ /dev/null @@ -1,193 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json deleted file mode 100644 index 5297f37..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountFactory.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "inputs": [], - "name": "DeploymentFailed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "scaAddress", - "type": "address" - } - ], - "name": "ContractCreated", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "abiEncodedOwnerAddress", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "name": "deploySmartContractAccount", - "outputs": [ - { - "internalType": "address", - "name": "scaAddress", - "type": "address" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json deleted file mode 100644 index 6f37fb6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SmartContractAccountHelper.json +++ /dev/null @@ -1,171 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "entryPoint", - "type": "address" - }, - { - "internalType": "address", - "name": "factory", - "type": "address" - } - ], - "name": "calculateSmartContractAccountAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "topupThreshold", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "topupAmount", - "type": "uint256" - } - ], - "name": "getAbiEncodedDirectRequestData", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "endContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "getFullEndTxEncoding", - "outputs": [ - { - "internalType": "bytes", - "name": "encoding", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "userOpHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "scaAddress", - "type": "address" - } - ], - "name": "getFullHashForSigning", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "factory", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "entryPoint", - "type": "address" - } - ], - "name": "getInitCode", - "outputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "entryPoint", - "type": "address" - } - ], - "name": "getSCAInitCodeWithConstructor", - "outputs": [ - { - "internalType": "bytes", - "name": "initCode", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json deleted file mode 100644 index aaabb15..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SortedSetValidationUtil.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "inputs": [], - "name": "EmptySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "set", - "type": "bytes32[]" - } - ], - "name": "NotASortedSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32[]", - "name": "subset", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "superset", - "type": "bytes32[]" - } - ], - "name": "NotASubset", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json deleted file mode 100644 index 187fe7f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StakeManager.json +++ /dev/null @@ -1,287 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDeposit", - "type": "uint256" - } - ], - "name": "Deposited", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalStaked", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "unstakeDelaySec", - "type": "uint256" - } - ], - "name": "StakeLocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawTime", - "type": "uint256" - } - ], - "name": "StakeUnlocked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "StakeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - } - ], - "name": "addStake", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "depositTo", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "deposits", - "outputs": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "getDepositInfo", - "outputs": [ - { - "components": [ - { - "internalType": "uint112", - "name": "deposit", - "type": "uint112" - }, - { - "internalType": "bool", - "name": "staked", - "type": "bool" - }, - { - "internalType": "uint112", - "name": "stake", - "type": "uint112" - }, - { - "internalType": "uint32", - "name": "unstakeDelaySec", - "type": "uint32" - }, - { - "internalType": "uint48", - "name": "withdrawTime", - "type": "uint48" - } - ], - "internalType": "struct IStakeManager.DepositInfo", - "name": "info", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "unlockStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - } - ], - "name": "withdrawStake", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "withdrawAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "withdrawAmount", - "type": "uint256" - } - ], - "name": "withdrawTo", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json deleted file mode 100644 index 2605410..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupCompatibleInterface.json +++ /dev/null @@ -1,91 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json deleted file mode 100644 index 20b22ce..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/StreamsLookupUpkeep.json +++ /dev/null @@ -1,448 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "_useArbBlock", - "type": "bool" - }, - { - "internalType": "bool", - "name": "_staging", - "type": "bool" - }, - { - "internalType": "bool", - "name": "_verify", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "v0", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "verifiedV0", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "ed", - "type": "bytes" - } - ], - "name": "MercuryPerformEvent", - "type": "event" - }, - { - "inputs": [], - "name": "callbackReturnBool", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feeds", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "interval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "previousPerformBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setCallbackReturnBool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "_feeds", - "type": "string[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_feedParamKey", - "type": "string" - }, - { - "internalType": "string", - "name": "_timeParamKey", - "type": "string" - } - ], - "name": "setParamKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldRevertCallback", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "shouldRevertCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "staging", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbBlock", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "verify", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json deleted file mode 100644 index 4793f6a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Strings.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "StringsInsufficientHexLength", - "type": "error" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json deleted file mode 100644 index 1c262bc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/SubscriptionAPI.json +++ /dev/null @@ -1,843 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json deleted file mode 100644 index af511ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TermsOfServiceAllowList.json +++ /dev/null @@ -1,466 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "signerPublicKey", - "type": "address" - } - ], - "internalType": "struct TermsOfServiceAllowListConfig", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "initialAllowedSenders", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "initialBlockedSenders", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidUsage", - "type": "error" - }, - { - "inputs": [], - "name": "RecipientIsBlocked", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "BlockedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "signerPublicKey", - "type": "address" - } - ], - "indexed": false, - "internalType": "struct TermsOfServiceAllowListConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "UnblockedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "acceptor", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - } - ], - "name": "acceptTermsOfService", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "blockSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAllAllowedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedSendersCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "allowedSenderIdxStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "allowedSenderIdxEnd", - "type": "uint64" - } - ], - "name": "getAllowedSendersInRange", - "outputs": [ - { - "internalType": "address[]", - "name": "allowedSenders", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBlockedSendersCount", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "blockedSenderIdxStart", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "blockedSenderIdxEnd", - "type": "uint64" - } - ], - "name": "getBlockedSendersInRange", - "outputs": [ - { - "internalType": "address[]", - "name": "blockedSenders", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "signerPublicKey", - "type": "address" - } - ], - "internalType": "struct TermsOfServiceAllowListConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "acceptor", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "getMessage", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isBlockedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "unblockSender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "enabled", - "type": "bool" - }, - { - "internalType": "address", - "name": "signerPublicKey", - "type": "address" - } - ], - "internalType": "struct TermsOfServiceAllowListConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "updateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json deleted file mode 100644 index 04a0302..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TrustedBlockhashStore.json +++ /dev/null @@ -1,235 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address[]", - "name": "whitelist", - "type": "address[]" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidRecentBlockhash", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrustedBlockhashes", - "type": "error" - }, - { - "inputs": [], - "name": "NotInWhitelist", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getBlockhash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_whitelist", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "s_whitelistStatus", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "whitelist", - "type": "address[]" - } - ], - "name": "setWhitelist", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "storeEarliest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "blockNums", - "type": "uint256[]" - }, - { - "internalType": "bytes32[]", - "name": "blockhashes", - "type": "bytes32[]" - }, - { - "internalType": "uint256", - "name": "recentBlockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "recentBlockhash", - "type": "bytes32" - } - ], - "name": "storeTrusted", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "header", - "type": "bytes" - } - ], - "name": "storeVerifyHeader", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json deleted file mode 100644 index 99725a5..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/TypeAndVersionInterface.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json deleted file mode 100644 index a680f22..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepAutoFunder.json +++ /dev/null @@ -1,261 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "registryAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "callable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "executedata", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_autoFundLink", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_isEligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_keeperRegistry", - "outputs": [ - { - "internalType": "contract AutomationRegistryBaseInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_shouldCancel", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_upkeepId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "value", - "type": "uint96" - } - ], - "name": "setAutoFundLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setIsEligible", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldCancel", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setUpkeepId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json deleted file mode 100644 index d636bfb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepBalanceMonitor.json +++ /dev/null @@ -1,524 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "linkToken", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "maxBatchSize", - "type": "uint8" - }, - { - "internalType": "uint24", - "name": "minPercentage", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "targetPercentage", - "type": "uint24" - }, - { - "internalType": "uint96", - "name": "maxTopUpAmount", - "type": "uint96" - } - ], - "internalType": "struct UpkeepBalanceMonitor.Config", - "name": "config", - "type": "tuple" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidConfig", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTopUpData", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyForwarderOrOwner", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "components": [ - { - "internalType": "uint8", - "name": "maxBatchSize", - "type": "uint8" - }, - { - "internalType": "uint24", - "name": "minPercentage", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "targetPercentage", - "type": "uint24" - }, - { - "internalType": "uint96", - "name": "maxTopUpAmount", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct UpkeepBalanceMonitor.Config", - "name": "config", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "forwarderAddress", - "type": "address" - } - ], - "name": "ForwarderSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "registryAddress", - "type": "address" - } - ], - "name": "WatchListSet", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint8", - "name": "maxBatchSize", - "type": "uint8" - }, - { - "internalType": "uint24", - "name": "minPercentage", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "targetPercentage", - "type": "uint24" - }, - { - "internalType": "uint96", - "name": "maxTopUpAmount", - "type": "uint96" - } - ], - "internalType": "struct UpkeepBalanceMonitor.Config", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedUpkeeps", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "", - "type": "uint96[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - }, - { - "internalType": "uint256[][]", - "name": "", - "type": "uint256[][]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint8", - "name": "maxBatchSize", - "type": "uint8" - }, - { - "internalType": "uint24", - "name": "minPercentage", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "targetPercentage", - "type": "uint24" - }, - { - "internalType": "uint96", - "name": "maxTopUpAmount", - "type": "uint96" - } - ], - "internalType": "struct UpkeepBalanceMonitor.Config", - "name": "config", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarderAddress", - "type": "address" - } - ], - "name": "setForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "registryAddress", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "watchlist", - "type": "uint256[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIDs", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "registryAddresses", - "type": "address[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmounts", - "type": "uint96[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json deleted file mode 100644 index 559ad80..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounter.json +++ /dev/null @@ -1,201 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "lastTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "counter", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "interval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "previousPerformBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setSpread", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json deleted file mode 100644 index 9f86cff..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepCounterNew.json +++ /dev/null @@ -1,427 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "InvalidCaller", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "lastTimestamp", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousBlock", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "counter", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [], - "name": "checkGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "dataCopy", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "forwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "interval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "previousPerformBlock", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_checkGasToBurn", - "type": "uint256" - } - ], - "name": "setCheckGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "setData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_forwarder", - "type": "address" - } - ], - "name": "setForwarder", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_performGasToBurn", - "type": "uint256" - } - ], - "name": "setPerformGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setSpread", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_trickSimulation", - "type": "bool" - } - ], - "name": "setTrickSimulation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_useMoreCheckGas", - "type": "bool" - } - ], - "name": "setUseMoreCheckGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_useMorePerformData", - "type": "bool" - } - ], - "name": "setUseMorePerformData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_useMorePerformGas", - "type": "bool" - } - ], - "name": "setUseMorePerformGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "trickSimulation", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useMoreCheckGas", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useMorePerformData", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useMorePerformGas", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json deleted file mode 100644 index 18ad60e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepMock.json +++ /dev/null @@ -1,239 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "upkeepData", - "type": "bytes" - } - ], - "name": "UpkeepPerformedWith", - "type": "event" - }, - { - "inputs": [], - "name": "canCheck", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "canPerform", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkRevertReason", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "callable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "executedata", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "performData", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setCanCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setCanPerform", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setCheckGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "value", - "type": "string" - } - ], - "name": "setCheckRevertReason", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "setPerformData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "value", - "type": "bool" - } - ], - "name": "setShouldRevertCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "shouldRevertCheck", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json deleted file mode 100644 index a6d3e16..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepPerformCounterRestrictive.json +++ /dev/null @@ -1,266 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_testRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_averageEligibilityCadence", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "eligible", - "type": "bool" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "initialCall", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "nextEligible", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - } - ], - "name": "PerformingUpkeep", - "type": "event" - }, - { - "inputs": [], - "name": "averageEligibilityCadence", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkEligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "checkGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCountPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialCall", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "nextEligible", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "performGasToBurn", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setCheckGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformGasToBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_newTestRange", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_newAverageEligibilityCadence", - "type": "uint256" - } - ], - "name": "setSpread", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "testRange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json deleted file mode 100644 index dd3c3e3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepReverter.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "callable", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "executedata", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json deleted file mode 100644 index 977aa03..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidTranscoding", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "enum UpkeepFormat", - "name": "toVersion", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json deleted file mode 100644 index 18259c1..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder3_0.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidTranscoding", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "enum UpkeepFormat", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json deleted file mode 100644 index 7f6f286..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder4_0.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidTranscoding", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json deleted file mode 100644 index 2f7d062..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoder5_0.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "inputs": [], - "name": "InvalidTranscoding", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "toVersion", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json deleted file mode 100644 index 83cadad..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterface.json +++ /dev/null @@ -1,31 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "enum UpkeepFormat", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "enum UpkeepFormat", - "name": "toVersion", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json deleted file mode 100644 index a58a7ca..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/UpkeepTranscoderInterfaceV2.json +++ /dev/null @@ -1,31 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint8", - "name": "fromVersion", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "toVersion", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "transcodeUpkeeps", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json deleted file mode 100644 index 1ad6a94..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumer.json +++ /dev/null @@ -1,86 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "doRequestRandomness", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "randomnessOutput", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "name": "rawFulfillRandomness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "requestId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json deleted file mode 100644 index 2f5c323..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBase.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "name": "rawFulfillRandomness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json deleted file mode 100644 index 413f472..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2.json +++ /dev/null @@ -1,36 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json deleted file mode 100644 index 991702f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Plus.json +++ /dev/null @@ -1,172 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json deleted file mode 100644 index d135614..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerBaseV2Upgradeable.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json deleted file mode 100644 index 797e98d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2.json +++ /dev/null @@ -1,188 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minReqConfs", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json deleted file mode 100644 index 4a35c51..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2Plus.json +++ /dev/null @@ -1,336 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json deleted file mode 100644 index ba7515c..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2PlusUpgradeableExample.json +++ /dev/null @@ -1,229 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "minReqConfs", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json deleted file mode 100644 index 0288525..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFConsumerV2UpgradeableExample.json +++ /dev/null @@ -1,229 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minReqConfs", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json deleted file mode 100644 index 7cde48d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorMock.json +++ /dev/null @@ -1,103 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "RandomnessRequest", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumerContract", - "type": "address" - } - ], - "name": "callBackWithRandomness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fee", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json deleted file mode 100644 index d010a7f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2.json +++ /dev/null @@ -1,1463 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - }, - { - "internalType": "address", - "name": "linkEthFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "want", - "type": "uint256" - } - ], - "name": "InsufficientGasForConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct VRFCoordinatorTestV2.FeeConfig", - "name": "feeConfig", - "type": "tuple" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oracle", - "type": "address" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "oracle", - "type": "address" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "internalType": "struct VRFCoordinatorTestV2.RequestCommitment", - "name": "rc", - "type": "tuple" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "name": "getCommitment", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCurrentSubId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFeeConfig", - "outputs": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - } - ], - "name": "getFeeTier", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRequestConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "oracleWithdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "internalType": "struct VRFCoordinatorTestV2.FeeConfig", - "name": "feeConfig", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json deleted file mode 100644 index a858f4e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorTestV2_5.json +++ /dev/null @@ -1,1750 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFOld.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json deleted file mode 100644 index bc6eb08..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "internalType": "struct VRFTypes.RequestCommitment", - "name": "rc", - "type": "tuple" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json deleted file mode 100644 index 1b16915..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Interface.json +++ /dev/null @@ -1,215 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getRequestConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json deleted file mode 100644 index 74c606b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Mock.json +++ /dev/null @@ -1,765 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint96", - "name": "_baseFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "_gasPriceLink", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRandomWords", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "ConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "ConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "inputs": [], - "name": "BASE_FEE", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "GAS_PRICE_LINK", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "consumerIsAdded", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "_words", - "type": "uint256[]" - } - ], - "name": "fulfillRandomWordsWithOverride", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "uint96", - "name": "_amount", - "type": "uint96" - } - ], - "name": "fundSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getFeeConfig", - "outputs": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getRequestConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "_minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json deleted file mode 100644 index 6bb444b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2PlusUpgradedVersion.json +++ /dev/null @@ -1,1778 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "transferredValue", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "expectedValue", - "type": "uint96" - } - ], - "name": "InvalidNativeBalance", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "requestVersion", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "expectedVersion", - "type": "uint8" - } - ], - "name": "InvalidVersion", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "SubscriptionIDCollisionFound", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRequestConfig", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "", - "type": "uint32" - }, - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "migrationVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedData", - "type": "bytes" - } - ], - "name": "onMigration", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json deleted file mode 100644 index 0c76d73..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2Plus_V2Example.json +++ /dev/null @@ -1,329 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "prevCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "transferredValue", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "expectedValue", - "type": "uint96" - } - ], - "name": "InvalidNativeBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "requestVersion", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "expectedVersion", - "type": "uint8" - } - ], - "name": "InvalidVersion", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "previousCoordinator", - "type": "address" - } - ], - "name": "MustBePreviousCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "SubscriptionIDCollisionFound", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestID", - "type": "uint256" - } - ], - "name": "generateFakeRandomness", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "linkBalance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedData", - "type": "bytes" - } - ], - "name": "onMigration", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_link", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_prevCoordinator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestConsumerMapping", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_subscriptions", - "outputs": [ - { - "internalType": "uint96", - "name": "linkBalance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalLinkBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json deleted file mode 100644 index cc81e63..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2TestHelper.json +++ /dev/null @@ -1,78 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkEthFeed", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasAfterPaymentCalculation", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPM", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "weiPerUnitGas", - "type": "uint256" - } - ], - "name": "calculatePaymentAmountTest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getPaymentAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json deleted file mode 100644 index 60f7254..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5.json +++ /dev/null @@ -1,1763 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json deleted file mode 100644 index a409893..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5Mock.json +++ /dev/null @@ -1,1180 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint96", - "name": "_baseFee", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "_gasPrice", - "type": "uint96" - }, - { - "internalType": "int256", - "name": "_weiPerUnitLink", - "type": "int256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRandomWords", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRequest", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NotImplemented", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "consumerIsAdded", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - }, - { - "internalType": "uint256[]", - "name": "_words", - "type": "uint256[]" - } - ], - "name": "fulfillRandomWordsWithOverride", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "fundSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_base_fee", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_gas_price", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_wei_per_unit_link", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "_req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json deleted file mode 100644 index 60f7254..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Arbitrum.json +++ /dev/null @@ -1,1763 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json deleted file mode 100644 index 30c3d71..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFCoordinatorV2_5_Optimism.json +++ /dev/null @@ -1,1848 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "blockhashStore", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "internalBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "externalBalance", - "type": "uint256" - } - ], - "name": "BalanceInvariantViolated", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "BlockhashNotInStore", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorAlreadyRegistered", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorNotRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToSendNative", - "type": "error" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "GasLimitTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxGas", - "type": "uint256" - } - ], - "name": "GasPriceExceeded", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectCommitment", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidCalldata", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "InvalidConsumer", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidExtraArgsTag", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCalculationMode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "int256", - "name": "linkWei", - "type": "int256" - } - ], - "name": "InvalidLinkWeiPrice", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "have", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "min", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "max", - "type": "uint16" - } - ], - "name": "InvalidRequestConfirmations", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSubscription", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "LinkNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "have", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "max", - "type": "uint32" - } - ], - "name": "MsgDataTooBig", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposedOwner", - "type": "address" - } - ], - "name": "MustBeRequestedOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "MustBeSubOwner", - "type": "error" - }, - { - "inputs": [], - "name": "NoCorrespondingRequest", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "NoSuchProvingKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "have", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "want", - "type": "uint32" - } - ], - "name": "NumWordsTooBig", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [], - "name": "PaymentTooLarge", - "type": "error" - }, - { - "inputs": [], - "name": "PendingRequestExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "ProvingKeyAlreadyRegistered", - "type": "error" - }, - { - "inputs": [], - "name": "Reentrant", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyConsumers", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "CoordinatorRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCalculationSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "fee", - "type": "uint256" - } - ], - "name": "L1GasFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newCoordinator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "MigrationCompleted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeFundsRecovered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyDeregistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "ProvingKeyRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountLink", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amountNative", - "type": "uint256" - } - ], - "name": "SubscriptionCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "SubscriptionConsumerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "SubscriptionCreated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFunded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "oldNativeBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newNativeBalance", - "type": "uint256" - } - ], - "name": "SubscriptionFundedWithNative", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "SubscriptionOwnerTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "BLOCKHASH_STORE", - "outputs": [ - { - "internalType": "contract BlockhashStoreInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_NATIVE_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_CONSUMERS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_NUM_WORDS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "MAX_REQUEST_CONFIRMATIONS", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "acceptSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "addConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "cancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscription", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "deregisterMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFTypes.RequestCommitmentV2Plus", - "name": "rc", - "type": "tuple" - }, - { - "internalType": "bool", - "name": "onlyPremium", - "type": "bool" - } - ], - "name": "fulfillRandomWords", - "outputs": [ - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "fundSubscriptionWithNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveSubscriptionIds", - "outputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "getSubscription", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeBalance", - "type": "uint96" - }, - { - "internalType": "uint64", - "name": "reqCount", - "type": "uint64" - }, - { - "internalType": "address", - "name": "subOwner", - "type": "address" - }, - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicKey", - "type": "uint256[2]" - } - ], - "name": "hashOfKey", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newCoordinator", - "type": "address" - } - ], - "name": "migrate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "pendingRequestExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - } - ], - "name": "recoverNativeFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - } - ], - "name": "registerMigratableCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "removeConsumer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "internalType": "struct VRFV2PlusClient.RandomWordsRequest", - "name": "req", - "type": "tuple" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "requestSubscriptionOwnerTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_config", - "outputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "reentrancyLock", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_currentSubNonce", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fallbackWeiPerUnitLink", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCalculationMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCoefficient", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_provingKeyHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "s_provingKeys", - "outputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "maxGas", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestCommitments", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_totalNativeBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "nativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "linkPremiumPercentage", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkNativeFeed", - "type": "address" - } - ], - "name": "setLINKAndLINKNativeFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json deleted file mode 100644 index eb693d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFExternalSubOwnerExample.json +++ /dev/null @@ -1,130 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json deleted file mode 100644 index 82084df..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestExternalSubOwner.json +++ /dev/null @@ -1,190 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json deleted file mode 100644 index babe0d6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLoadTestOwnerlessConsumer.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_price", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "PRICE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "name": "rawFulfillRandomness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json deleted file mode 100644 index 5efdfc9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFLogEmitter.json +++ /dev/null @@ -1,164 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "RandomWordsFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsRequested", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "outputSeed", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "payment", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "emitRandomWordsFulfilled", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "preSeed", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "emitRandomWordsRequested", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json deleted file mode 100644 index 63f3188..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2.json +++ /dev/null @@ -1,155 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json deleted file mode 100644 index fbd1f4f..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMaliciousConsumerV2Plus.json +++ /dev/null @@ -1,278 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json deleted file mode 100644 index 760d0fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFMockETHLINKAggregator.json +++ /dev/null @@ -1,150 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "int256", - "name": "_answer", - "type": "int256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "answer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "ans", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_blockTimestampDeduction", - "type": "uint256" - } - ], - "name": "setBlockTimestampDeduction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json deleted file mode 100644 index 3ebf34b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwner.json +++ /dev/null @@ -1,455 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "EmptySendersList", - "type": "error" - }, - { - "inputs": [], - "name": "NotAllowedToSetSenders", - "type": "error" - }, - { - "inputs": [], - "name": "UnauthorizedSender", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "senders", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address", - "name": "changedBy", - "type": "address" - } - ], - "name": "AuthorizedSendersChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RandomWordsForced", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "acceptVRFOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "deregisterProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRFTypes.Proof", - "name": "proof", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint64", - "name": "blockNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "internalType": "struct VRFTypes.RequestCommitment", - "name": "rc", - "type": "tuple" - } - ], - "name": "fulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAuthorizedSenders", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getVRFCoordinator", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isAuthorizedSender", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - } - ], - "name": "ownerCancelSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "recoverFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "publicProvingKey", - "type": "uint256[2]" - } - ], - "name": "registerProvingKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "senders", - "type": "address[]" - } - ], - "name": "setAuthorizedSenders", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "minimumRequestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "maxGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "gasAfterPaymentCalculation", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier1", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier2", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier3", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier4", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPMTier5", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "reqsForTier2", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier3", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier4", - "type": "uint24" - }, - { - "internalType": "uint24", - "name": "reqsForTier5", - "type": "uint24" - } - ], - "internalType": "struct FeeConfig", - "name": "feeConfig", - "type": "tuple" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferVRFOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json deleted file mode 100644 index 9254332..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFOwnerlessConsumerExample.json +++ /dev/null @@ -1,90 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "OnlyCallableFromLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "requestId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "randomness", - "type": "uint256" - } - ], - "name": "rawFulfillRandomness", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_randomnessOutput", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json deleted file mode 100644 index 53bb38b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFRequestIDBaseTestHelper.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_vRFInputSeed", - "type": "uint256" - } - ], - "name": "makeRequestId_", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "_userSeed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_requester", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_nonce", - "type": "uint256" - } - ], - "name": "makeVRFInputSeed_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json deleted file mode 100644 index 5a4eb85..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSingleConsumerExample.json +++ /dev/null @@ -1,208 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "fundAndRequestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestConfig", - "outputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "subscribe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "unsubscribe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json deleted file mode 100644 index d39bb01..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitor.json +++ /dev/null @@ -1,606 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkTokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "duplicate", - "type": "uint64" - } - ], - "name": "DuplicateSubcriptionId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountAdded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "LinkTokenAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "lastId", - "type": "uint256" - } - ], - "name": "OutOfGas", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "VRFCoordinatorV2AddressUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscriptionInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalanceJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpAmountJuels", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedSubscriptions", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_keeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_minWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_watchList", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "linkTokenAddress", - "type": "address" - } - ], - "name": "setLinkTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "setVRFCoordinatorV2Address", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64[]", - "name": "subscriptionIds", - "type": "uint64[]" - }, - { - "internalType": "uint96[]", - "name": "minBalancesJuels", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmountsJuels", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64[]", - "name": "needsFunding", - "type": "uint64[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json deleted file mode 100644 index 35a83f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFSubscriptionBalanceMonitorExposed.json +++ /dev/null @@ -1,624 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "linkTokenAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "minWaitPeriodSeconds", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "duplicate", - "type": "uint64" - } - ], - "name": "DuplicateSubcriptionId", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidWatchList", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyKeeperRegistry", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountAdded", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amountWithdrawn", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "KeeperRegistryAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "LinkTokenAddressUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "oldMinWaitPeriod", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMinWaitPeriod", - "type": "uint256" - } - ], - "name": "MinWaitPeriodUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "lastId", - "type": "uint256" - } - ], - "name": "OutOfGas", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "TopUpFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "TopUpSucceeded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAddress", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAddress", - "type": "address" - } - ], - "name": "VRFCoordinatorV2AddressUpdated", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subscriptionId", - "type": "uint64" - } - ], - "name": "getSubscriptionInfo", - "outputs": [ - { - "internalType": "bool", - "name": "isActive", - "type": "bool" - }, - { - "internalType": "uint96", - "name": "minBalanceJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "topUpAmountJuels", - "type": "uint96" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getUnderfundedSubscriptions", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWatchList", - "outputs": [ - { - "internalType": "uint64[]", - "name": "", - "type": "uint64[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_keeperRegistryAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_minWaitPeriodSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_watchList", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "keeperRegistryAddress", - "type": "address" - } - ], - "name": "setKeeperRegistryAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "target", - "type": "uint64" - }, - { - "internalType": "uint56", - "name": "lastTopUpTimestamp", - "type": "uint56" - } - ], - "name": "setLastTopUpXXXTestOnly", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "linkTokenAddress", - "type": "address" - } - ], - "name": "setLinkTokenAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "period", - "type": "uint256" - } - ], - "name": "setMinWaitPeriodSeconds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "coordinatorAddress", - "type": "address" - } - ], - "name": "setVRFCoordinatorV2Address", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64[]", - "name": "subscriptionIds", - "type": "uint64[]" - }, - { - "internalType": "uint96[]", - "name": "minBalancesJuels", - "type": "uint96[]" - }, - { - "internalType": "uint96[]", - "name": "topUpAmountsJuels", - "type": "uint96[]" - } - ], - "name": "setWatchList", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64[]", - "name": "needsFunding", - "type": "uint64[]" - } - ], - "name": "topUp", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address payable", - "name": "payee", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json deleted file mode 100644 index 0c2fe93..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFTestHelper.json +++ /dev/null @@ -1,474 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "p1", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "p2", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "invZ", - "type": "uint256" - } - ], - "name": "affineECAdd_", - "outputs": [ - { - "internalType": "uint256[2]", - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "base", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "exponent", - "type": "uint256" - } - ], - "name": "bigModExp_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "x", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "scalar", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "q", - "type": "uint256[2]" - } - ], - "name": "ecmulVerify_", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "b", - "type": "bytes" - } - ], - "name": "fieldHash_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "x", - "type": "uint256" - } - ], - "name": "hashToCurve_", - "outputs": [ - { - "internalType": "uint256[2]", - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "p", - "type": "uint256[2]" - } - ], - "name": "isOnCurve_", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "p1", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "cp1Witness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "p2", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sp2Witness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "name": "linearCombination_", - "outputs": [ - { - "internalType": "uint256[2]", - "name": "", - "type": "uint256[2]" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "px", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "py", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "qx", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "qy", - "type": "uint256" - } - ], - "name": "projectiveECAdd_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "internalType": "struct VRF.Proof", - "name": "proof", - "type": "tuple" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - } - ], - "name": "randomValueFromVRFProof_", - "outputs": [ - { - "internalType": "uint256", - "name": "output", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "hash", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "v", - "type": "uint256[2]" - } - ], - "name": "scalarFromCurvePoints_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "x", - "type": "uint256" - } - ], - "name": "squareRoot_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256[2]", - "name": "p", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "address", - "name": "lcWitness", - "type": "address" - } - ], - "name": "verifyLinearCombinationWithGenerator_", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[2]", - "name": "pk", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "gamma", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "c", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "s", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "seed", - "type": "uint256" - }, - { - "internalType": "address", - "name": "uWitness", - "type": "address" - }, - { - "internalType": "uint256[2]", - "name": "cGammaWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256[2]", - "name": "sHashWitness", - "type": "uint256[2]" - }, - { - "internalType": "uint256", - "name": "zInv", - "type": "uint256" - } - ], - "name": "verifyVRFProof_", - "outputs": [], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "x", - "type": "uint256" - } - ], - "name": "ySquared_", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json deleted file mode 100644 index 70ec704..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2LoadTestWithMetrics.json +++ /dev/null @@ -1,370 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "SubscriptionCreatedFundedAndConsumerAdded", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "_subTopUpAmount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "name": "requestRandomWordsWithForceFulfill", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageFulfillmentInMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "_subId", - "type": "uint64" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json deleted file mode 100644 index c4b3fa3..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2OwnerTestConsumer.json +++ /dev/null @@ -1,406 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "_link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address", - "name": "consumer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "SubscriptionCreatedFundedAndConsumerAdded", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract VRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINKTOKEN", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "_subTopUpAmount", - "type": "uint256" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageFulfillmentInMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "subId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json deleted file mode 100644 index 34569b2..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusClient.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "inputs": [], - "name": "EXTRA_ARGS_V1_TAG", - "outputs": [ - { - "internalType": "bytes4", - "name": "", - "type": "bytes4" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json deleted file mode 100644 index 250215d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusConsumerExample.json +++ /dev/null @@ -1,392 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "createSubscriptionAndFundNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "idx", - "type": "uint256" - } - ], - "name": "getRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "randomWord", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_recentRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "address", - "name": "requester", - "type": "address" - }, - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinatorApiV1", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - } - ], - "name": "setSubId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "topUpSubscriptionNative", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json deleted file mode 100644 index e923907..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusExternalSubOwnerExample.json +++ /dev/null @@ -1,258 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json deleted file mode 100644 index 6301bab..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusLoadTestWithMetrics.json +++ /dev/null @@ -1,476 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "quantity", - "type": "uint256" - } - ], - "name": "getRequestBlockTimes", - "outputs": [ - { - "internalType": "uint32[]", - "name": "", - "type": "uint32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "_nativePayment", - "type": "bool" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageResponseTimeInBlocksMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageResponseTimeInSecondsMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestResponseTimeInBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestResponseTimeInSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestBlockTimes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestResponseTimeInBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestResponseTimeInSeconds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json deleted file mode 100644 index 87eabea..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusMaliciousMigrator.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json deleted file mode 100644 index a91774a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusRevertingExample.json +++ /dev/null @@ -1,324 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "minReqConfs", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json deleted file mode 100644 index 4051083..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusSingleConsumerExample.json +++ /dev/null @@ -1,354 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "fundAndRequestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "requestRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestConfig", - "outputs": [ - { - "internalType": "uint256", - "name": "subId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "bool", - "name": "nativePayment", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "subscribe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "unsubscribe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json deleted file mode 100644 index f830554..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper.json +++ /dev/null @@ -1,954 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "_coordinator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "expectedMinimumLength", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "actualLength", - "type": "uint16" - } - ], - "name": "IncorrectExtraArgsLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [], - "name": "LINKPaymentInRequestRandomWordsInNative", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "NativePaymentInOnTokenTransfer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "SubscriptionIdMissing", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Enabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "size", - "type": "uint32" - } - ], - "name": "FulfillmentTxSizeSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "WrapperFulfillmentFailed", - "type": "event" - }, - { - "inputs": [], - "name": "SUBSCRIPTION_ID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "isLinkMode", - "type": "bool" - } - ], - "name": "checkPaymentMode", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "disable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "wrapperNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "wrapperLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "link", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkNativeFeed", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "name": "requestRandomWordsInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_callbacks", - "outputs": [ - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "requestGasPrice", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_configured", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_disabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fulfillmentTxSizeBytes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "_coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "_coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "_maxNumWords", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "_stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "_fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_size", - "type": "uint32" - } - ], - "name": "setFulfillmentTxSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json deleted file mode 100644 index f5a54bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerBase.json +++ /dev/null @@ -1,75 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyVRFWrapperCanFulfill", - "type": "error" - }, - { - "inputs": [], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_vrfV2PlusWrapper", - "outputs": [ - { - "internalType": "contract IVRFV2PlusWrapper", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json deleted file mode 100644 index a8782ed..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperConsumerExample.json +++ /dev/null @@ -1,366 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyVRFWrapperCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "Received", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "payment", - "type": "uint256" - } - ], - "name": "WrappedRequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "paid", - "type": "uint256" - } - ], - "name": "WrapperRequestMade", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_vrfV2PlusWrapper", - "outputs": [ - { - "internalType": "contract IVRFV2PlusWrapper", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequest", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequestNative", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "bool", - "name": "native", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json deleted file mode 100644 index 3ba6702..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapperLoadTestConsumer.json +++ /dev/null @@ -1,513 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfV2PlusWrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyVRFWrapperCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "payment", - "type": "uint256" - } - ], - "name": "WrappedRequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "paid", - "type": "uint256" - } - ], - "name": "WrapperRequestMade", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "offset", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "quantity", - "type": "uint256" - } - ], - "name": "getRequestBlockTimes", - "outputs": [ - { - "internalType": "uint32[]", - "name": "", - "type": "uint32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_vrfV2PlusWrapper", - "outputs": [ - { - "internalType": "contract IVRFV2PlusWrapper", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "makeRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "makeRequestsNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageFulfillmentInMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requestBlockTimes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "native", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json deleted file mode 100644 index f830554..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Arbitrum.json +++ /dev/null @@ -1,954 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "_coordinator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "expectedMinimumLength", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "actualLength", - "type": "uint16" - } - ], - "name": "IncorrectExtraArgsLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [], - "name": "LINKPaymentInRequestRandomWordsInNative", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "NativePaymentInOnTokenTransfer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "SubscriptionIdMissing", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Enabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "size", - "type": "uint32" - } - ], - "name": "FulfillmentTxSizeSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "WrapperFulfillmentFailed", - "type": "event" - }, - { - "inputs": [], - "name": "SUBSCRIPTION_ID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "isLinkMode", - "type": "bool" - } - ], - "name": "checkPaymentMode", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "disable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "wrapperNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "wrapperLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "link", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkNativeFeed", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "name": "requestRandomWordsInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_callbacks", - "outputs": [ - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "requestGasPrice", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_configured", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_disabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fulfillmentTxSizeBytes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "_coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "_coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "_maxNumWords", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "_stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "_fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_size", - "type": "uint32" - } - ], - "name": "setFulfillmentTxSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json deleted file mode 100644 index 83a8c30..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2PlusWrapper_Optimism.json +++ /dev/null @@ -1,1050 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_linkNativeFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "_coordinator", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_subId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "FailedToTransferLink", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "expectedMinimumLength", - "type": "uint16" - }, - { - "internalType": "uint16", - "name": "actualLength", - "type": "uint16" - } - ], - "name": "IncorrectExtraArgsLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCalculationMode", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "InvalidL1FeeCoefficient", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "premiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "max", - "type": "uint8" - } - ], - "name": "InvalidPremiumPercentage", - "type": "error" - }, - { - "inputs": [], - "name": "LINKPaymentInRequestRandomWordsInNative", - "type": "error" - }, - { - "inputs": [], - "name": "LinkAlreadySet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "flatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeNativePPM", - "type": "uint32" - } - ], - "name": "LinkDiscountTooHigh", - "type": "error" - }, - { - "inputs": [], - "name": "NativePaymentInOnTokenTransfer", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "coordinator", - "type": "address" - } - ], - "name": "OnlyOwnerOrCoordinator", - "type": "error" - }, - { - "inputs": [], - "name": "SubscriptionIdMissing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - } - ], - "name": "UnsupportedL1FeeCalculationMode", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "name": "CoordinatorSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Disabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "Enabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - } - ], - "name": "FallbackWeiPerUnitLinkUsed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "size", - "type": "uint32" - } - ], - "name": "FulfillmentTxSizeSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "L1FeeCalculationSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "NativeWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Withdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "WrapperFulfillmentFailed", - "type": "event" - }, - { - "inputs": [], - "name": "SUBSCRIPTION_ID", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "calculateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - }, - { - "internalType": "bool", - "name": "isLinkMode", - "type": "bool" - } - ], - "name": "checkPaymentMode", - "outputs": [], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "disable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPriceNative", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "wrapperNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "wrapperLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "link", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkNativeFeed", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "extraArgs", - "type": "bytes" - } - ], - "name": "requestRandomWordsInNative", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_callbacks", - "outputs": [ - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "requestGasPrice", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_configured", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_disabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fulfillmentTxSizeBytes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCalculationMode", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_l1FeeCoefficient", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_vrfCoordinator", - "outputs": [ - { - "internalType": "contract IVRFCoordinatorV2Plus", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadNative", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverheadLink", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_coordinatorGasOverheadPerWord", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "_coordinatorNativePremiumPercentage", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "_coordinatorLinkPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "_maxNumWords", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "_stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "int256", - "name": "_fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeNativePPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_fulfillmentFlatFeeLinkDiscountPPM", - "type": "uint32" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_vrfCoordinator", - "type": "address" - } - ], - "name": "setCoordinator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_size", - "type": "uint32" - } - ], - "name": "setFulfillmentTxSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "mode", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "coefficient", - "type": "uint8" - } - ], - "name": "setL1FeeCalculation", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - } - ], - "name": "withdrawNative", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json deleted file mode 100644 index 7793e0d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2ProxyAdmin.json +++ /dev/null @@ -1,151 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "contract ITransparentUpgradeableProxy", - "name": "proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "changeProxyAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ITransparentUpgradeableProxy", - "name": "proxy", - "type": "address" - } - ], - "name": "getProxyAdmin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ITransparentUpgradeableProxy", - "name": "proxy", - "type": "address" - } - ], - "name": "getProxyImplementation", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ITransparentUpgradeableProxy", - "name": "proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "upgrade", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract ITransparentUpgradeableProxy", - "name": "proxy", - "type": "address" - }, - { - "internalType": "address", - "name": "implementation", - "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "upgradeAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json deleted file mode 100644 index 797e98d..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2RevertingExample.json +++ /dev/null @@ -1,188 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - }, - { - "internalType": "address", - "name": "link", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "createSubscriptionAndFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint16", - "name": "minReqConfs", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "requestRandomness", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_gasAvailable", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_randomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_subId", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "topUpSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "consumers", - "type": "address[]" - } - ], - "name": "updateSubscription", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json deleted file mode 100644 index 27423cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2TransparentUpgradeableProxy.json +++ /dev/null @@ -1,76 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_logic", - "type": "address" - }, - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "beacon", - "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "implementation", - "type": "address" - } - ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json deleted file mode 100644 index 893edb6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2Wrapper.json +++ /dev/null @@ -1,495 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_linkEthFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "_coordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "consumer", - "type": "address" - } - ], - "name": "WrapperFulfillmentFailed", - "type": "event" - }, - { - "inputs": [], - "name": "COORDINATOR", - "outputs": [ - { - "internalType": "contract ExtendedVRFCoordinatorV2Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "LINK_ETH_FEED", - "outputs": [ - { - "internalType": "contract AggregatorV3Interface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "SUBSCRIPTION_ID", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enable", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "internalType": "int256", - "name": "fallbackWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint32", - "name": "stalenessSeconds", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "fulfillmentFlatFeeLinkPPM", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "coordinatorGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "wrapperPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "maxNumWords", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_callbacks", - "outputs": [ - { - "internalType": "address", - "name": "callbackAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "requestGasPrice", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "requestWeiPerUnitLink", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "juelsPaid", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_configured", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_disabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fulfillmentTxSizeBytes", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_wrapperGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_coordinatorGasOverhead", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "_wrapperPremiumPercentage", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_keyHash", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "_maxNumWords", - "type": "uint8" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "size", - "type": "uint32" - } - ], - "name": "setFulfillmentTxSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json deleted file mode 100644 index 797e6f6..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerBase.json +++ /dev/null @@ -1,20 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json deleted file mode 100644 index 1c7a980..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperConsumerExample.json +++ /dev/null @@ -1,246 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "payment", - "type": "uint256" - } - ], - "name": "WrappedRequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "paid", - "type": "uint256" - } - ], - "name": "WrapperRequestMade", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequest", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json deleted file mode 100644 index 6618881..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperInterface.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - } - ], - "name": "calculateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "_requestGasPriceWei", - "type": "uint256" - } - ], - "name": "estimateRequestPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json deleted file mode 100644 index ec71ede..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperLoadTestConsumer.json +++ /dev/null @@ -1,387 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "payment", - "type": "uint256" - } - ], - "name": "WrappedRequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "paid", - "type": "uint256" - } - ], - "name": "WrapperRequestMade", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "i_vrfV2Wrapper", - "outputs": [ - { - "internalType": "contract VRFV2WrapperInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestCount", - "type": "uint16" - } - ], - "name": "makeRequests", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "reset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "s_averageFulfillmentInMillions", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_fastestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_requestCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "uint256", - "name": "paid", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "requestTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentTimestamp", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requestBlockNumber", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fulfilmentBlockNumber", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_responseCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_slowestFulfillment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json deleted file mode 100644 index b4333ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperOutOfGasConsumerExample.json +++ /dev/null @@ -1,136 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequest", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json deleted file mode 100644 index b4333ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperRevertingConsumerExample.json +++ /dev/null @@ -1,136 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequest", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "_randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json deleted file mode 100644 index c2dee64..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFV2WrapperUnderFundingConsumer.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "_link", - "type": "address" - }, - { - "internalType": "address", - "name": "_vrfV2Wrapper", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "_callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "_requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "_numWords", - "type": "uint32" - } - ], - "name": "makeRequest", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json deleted file mode 100644 index 698d6d0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VRFv2Consumer.json +++ /dev/null @@ -1,275 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "vrfCoordinator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "have", - "type": "address" - }, - { - "internalType": "address", - "name": "want", - "type": "address" - } - ], - "name": "OnlyCoordinatorCanFulfill", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "RequestFulfilled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - } - ], - "name": "RequestSent", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_requestId", - "type": "uint256" - } - ], - "name": "getRequestStatus", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "lastRequestId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - }, - { - "internalType": "uint256[]", - "name": "randomWords", - "type": "uint256[]" - } - ], - "name": "rawFulfillRandomWords", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "requestIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "subId", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "callbackGasLimit", - "type": "uint32" - }, - { - "internalType": "uint16", - "name": "requestConfirmations", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "numWords", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "keyHash", - "type": "bytes32" - } - ], - "name": "requestRandomWords", - "outputs": [ - { - "internalType": "uint256", - "name": "requestId", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "s_requests", - "outputs": [ - { - "internalType": "bool", - "name": "fulfilled", - "type": "bool" - }, - { - "internalType": "bool", - "name": "exists", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json deleted file mode 100644 index e570c0e..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ValidatorProxy.json +++ /dev/null @@ -1,323 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "aggregator", - "type": "address" - }, - { - "internalType": "contract AggregatorValidatorInterface", - "name": "validator", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "AggregatorProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previous", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "current", - "type": "address" - } - ], - "name": "AggregatorUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "proposed", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "ProposedAggregatorValidateCall", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract AggregatorValidatorInterface", - "name": "validator", - "type": "address" - } - ], - "name": "ValidatorProposed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract AggregatorValidatorInterface", - "name": "previous", - "type": "address" - }, - { - "indexed": true, - "internalType": "contract AggregatorValidatorInterface", - "name": "current", - "type": "address" - } - ], - "name": "ValidatorUpgraded", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getAggregators", - "outputs": [ - { - "internalType": "address", - "name": "current", - "type": "address" - }, - { - "internalType": "bool", - "name": "hasProposal", - "type": "bool" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getValidators", - "outputs": [ - { - "internalType": "contract AggregatorValidatorInterface", - "name": "current", - "type": "address" - }, - { - "internalType": "bool", - "name": "hasProposal", - "type": "bool" - }, - { - "internalType": "contract AggregatorValidatorInterface", - "name": "proposed", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "proposeNewAggregator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AggregatorValidatorInterface", - "name": "proposed", - "type": "address" - } - ], - "name": "proposeNewValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "upgradeAggregator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upgradeValidator", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "previousRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "previousAnswer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "currentRoundId", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json deleted file mode 100644 index df73015..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadBase.json +++ /dev/null @@ -1,1524 +0,0 @@ -[ - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmittedAgain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "UpkeepTopUp", - "type": "event" - }, - { - "inputs": [], - "name": "BUCKET_SIZE", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "addLinkAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchCancelUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "batchPreparingUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - } - ], - "name": "batchPreparingUpkeepsSimple", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "number", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "checkGasToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "performGasToBurn", - "type": "uint256" - } - ], - "name": "batchRegisterUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "batchSendLogs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint32", - "name": "interval", - "type": "uint32" - } - ], - "name": "batchSetIntervals", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchUpdatePipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchWithdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "bucketedDelays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "buckets", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "burnPerformGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "checkGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "counters", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "delays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedAgainSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feedsHex", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "firstPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gasLimits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDsDeployedByThisContract", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getAllActiveUpkeepIDsOnRegistry", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getBucketedDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getBucketedDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "getLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "p", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getPxDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getSumDelayInBucket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getSumDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "intervals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "lastTopUpBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minBalanceThresholdMultiplier", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performDataSizes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "previousPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registrar", - "outputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "contract IKeeperRegistryMaster", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "sendLog", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "newRegistrar", - "type": "address" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "_feeds", - "type": "string[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setInterval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_feedParamKey", - "type": "string" - }, - { - "internalType": "string", - "name": "_timeParamKey", - "type": "string" - } - ], - "name": "setParamKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformDataSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "topUpFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "updateLogTriggerConfig1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "updateLogTriggerConfig2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "pipelineData", - "type": "bytes" - } - ], - "name": "updateUpkeepPipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTopUpCheckInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbitrumBlockNum", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json deleted file mode 100644 index 9968337..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadLogTriggerUpkeep.json +++ /dev/null @@ -1,1757 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "_registrar", - "type": "address" - }, - { - "internalType": "bool", - "name": "_useArb", - "type": "bool" - }, - { - "internalType": "bool", - "name": "_useMercury", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmittedAgain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "UpkeepTopUp", - "type": "event" - }, - { - "inputs": [], - "name": "BUCKET_SIZE", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "addLinkAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchCancelUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "batchPreparingUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - } - ], - "name": "batchPreparingUpkeepsSimple", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "number", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "checkGasToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "performGasToBurn", - "type": "uint256" - } - ], - "name": "batchRegisterUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "batchSendLogs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint32", - "name": "interval", - "type": "uint32" - } - ], - "name": "batchSetIntervals", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchUpdatePipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchWithdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "bucketedDelays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "buckets", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "burnPerformGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "checkGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "blockNumber", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "blockHash", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "source", - "type": "address" - }, - { - "internalType": "bytes32[]", - "name": "topics", - "type": "bytes32[]" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct Log", - "name": "log", - "type": "tuple" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkLog", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "counters", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "delays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedAgainSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feedsHex", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "firstPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gasLimits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDsDeployedByThisContract", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getAllActiveUpkeepIDsOnRegistry", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getBucketedDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getBucketedDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "getLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "p", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getPxDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getSumDelayInBucket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getSumDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "intervals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "lastTopUpBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "logNum", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minBalanceThresholdMultiplier", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performDataSizes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "previousPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registrar", - "outputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "contract IKeeperRegistryMaster", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "sendLog", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "newRegistrar", - "type": "address" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "_feeds", - "type": "string[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setInterval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "_log", - "type": "uint8" - } - ], - "name": "setLog", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_feedParamKey", - "type": "string" - }, - { - "internalType": "string", - "name": "_timeParamKey", - "type": "string" - } - ], - "name": "setParamKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformDataSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "topUpFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "updateLogTriggerConfig1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "updateLogTriggerConfig2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "pipelineData", - "type": "bytes" - } - ], - "name": "updateUpkeepPipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTopUpCheckInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbitrumBlockNum", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useMercury", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json deleted file mode 100644 index fab8627..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadStreamsLookupUpkeep.json +++ /dev/null @@ -1,1666 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "_registrar", - "type": "address" - }, - { - "internalType": "bool", - "name": "_useArb", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "feedParamKey", - "type": "string" - }, - { - "internalType": "string[]", - "name": "feeds", - "type": "string[]" - }, - { - "internalType": "string", - "name": "timeParamKey", - "type": "string" - }, - { - "internalType": "uint256", - "name": "time", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "StreamsLookup", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmittedAgain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "UpkeepTopUp", - "type": "event" - }, - { - "inputs": [], - "name": "BUCKET_SIZE", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "addLinkAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchCancelUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "batchPreparingUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - } - ], - "name": "batchPreparingUpkeepsSimple", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "number", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "checkGasToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "performGasToBurn", - "type": "uint256" - } - ], - "name": "batchRegisterUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "batchSendLogs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint32", - "name": "interval", - "type": "uint32" - } - ], - "name": "batchSetIntervals", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchUpdatePipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchWithdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "bucketedDelays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "buckets", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "burnPerformGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "errCode", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkErrorHandler", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "checkGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "counters", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "delays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedAgainSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feedsHex", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "firstPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gasLimits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDsDeployedByThisContract", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getAllActiveUpkeepIDsOnRegistry", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getBucketedDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getBucketedDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "getLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "p", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getPxDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getSumDelayInBucket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getSumDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "intervals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "lastTopUpBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minBalanceThresholdMultiplier", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performDataSizes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "previousPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registrar", - "outputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "contract IKeeperRegistryMaster", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "sendLog", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "newRegistrar", - "type": "address" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "_feeds", - "type": "string[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setInterval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_feedParamKey", - "type": "string" - }, - { - "internalType": "string", - "name": "_timeParamKey", - "type": "string" - } - ], - "name": "setParamKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformDataSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "topUpFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "updateLogTriggerConfig1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "updateLogTriggerConfig2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "pipelineData", - "type": "bytes" - } - ], - "name": "updateUpkeepPipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTopUpCheckInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbitrumBlockNum", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json deleted file mode 100644 index e9abeb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifiableLoadUpkeep.json +++ /dev/null @@ -1,1577 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "_registrar", - "type": "address" - }, - { - "internalType": "bool", - "name": "_useArb", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "LogEmittedAgain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "UpkeepTopUp", - "type": "event" - }, - { - "inputs": [], - "name": "BUCKET_SIZE", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "addLinkAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchCancelUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "batchPreparingUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - } - ], - "name": "batchPreparingUpkeepsSimple", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "number", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "checkGasToBurn", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "performGasToBurn", - "type": "uint256" - } - ], - "name": "batchRegisterUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "batchSendLogs", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - }, - { - "internalType": "uint32", - "name": "interval", - "type": "uint32" - } - ], - "name": "batchSetIntervals", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchUpdatePipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "upkeepIds", - "type": "uint256[]" - } - ], - "name": "batchWithdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "bucketedDelays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "buckets", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startGas", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "burnPerformGas", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "checkGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "counters", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "delays", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "dummyMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "eligible", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedAgainSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "emittedSig", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "feedParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "feedsHex", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "firstPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "gasLimits", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDsDeployedByThisContract", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getAllActiveUpkeepIDsOnRegistry", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getBucketedDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getBucketedDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelays", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getDelaysLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "getLogTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "logTrigger", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "p", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getPxDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "bucket", - "type": "uint16" - } - ], - "name": "getSumDelayInBucket", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "n", - "type": "uint256" - } - ], - "name": "getSumDelayLastNPerforms", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepInfo", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "intervals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "lastTopUpBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkToken", - "outputs": [ - { - "internalType": "contract LinkTokenInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "minBalanceThresholdMultiplier", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performDataSizes", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "performGasToBurns", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "performUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "previousPerformBlocks", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registrar", - "outputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "registry", - "outputs": [ - { - "internalType": "contract IKeeperRegistryMaster", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "log", - "type": "uint8" - } - ], - "name": "sendLog", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AutomationRegistrar2_1", - "name": "newRegistrar", - "type": "address" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string[]", - "name": "_feeds", - "type": "string[]" - } - ], - "name": "setFeeds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_interval", - "type": "uint256" - } - ], - "name": "setInterval", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "_feedParamKey", - "type": "string" - }, - { - "internalType": "string", - "name": "_timeParamKey", - "type": "string" - } - ], - "name": "setParamKeys", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "setPerformDataSize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "timeParamKey", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "blockNum", - "type": "uint256" - } - ], - "name": "topUpFund", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint8", - "name": "selector", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "topic0", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic1", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "topic3", - "type": "bytes32" - } - ], - "name": "updateLogTriggerConfig1", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "cfg", - "type": "bytes" - } - ], - "name": "updateLogTriggerConfig2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "pipelineData", - "type": "bytes" - } - ], - "name": "updateUpkeepPipelineData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepTopUpCheckInterval", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "useArbitrumBlockNum", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "withdrawLinks", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json deleted file mode 100644 index 5c6de23..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/Verifier.json +++ /dev/null @@ -1,714 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "verifierProxyAddr", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessForbidden", - "type": "error" - }, - { - "inputs": [], - "name": "BadVerification", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "CannotDeactivateLatestConfig", - "type": "error" - }, - { - "inputs": [], - "name": "DigestEmpty", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "DigestInactive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "DigestNotSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxSigners", - "type": "uint256" - } - ], - "name": "ExcessSigners", - "type": "error" - }, - { - "inputs": [], - "name": "FaultToleranceMustBePositive", - "type": "error" - }, - { - "inputs": [], - "name": "FeedIdEmpty", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "InactiveFeed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "expectedNumSigners", - "type": "uint256" - } - ], - "name": "IncorrectSignatureCount", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "numSigners", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "minSigners", - "type": "uint256" - } - ], - "name": "InsufficientSigners", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "rsLength", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ssLength", - "type": "uint256" - } - ], - "name": "MismatchedSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "NonUniqueSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "ConfigActivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "ConfigDeactivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "FeedActivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "FeedDeactivated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "requester", - "type": "address" - } - ], - "name": "ReportVerified", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "activateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "activateFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "deactivateConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "deactivateFeed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - } - ], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "feedId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "sourceChainId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "sourceAddress", - "type": "address" - }, - { - "internalType": "uint32", - "name": "newConfigCount", - "type": "uint32" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "bytes32[]", - "name": "offchainTransmitters", - "type": "bytes32[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "recipientAddressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setConfigFromSource", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "isVerifier", - "type": "bool" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "signedReport", - "type": "bytes" - }, - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "verifierResponse", - "type": "bytes" - } - ], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json deleted file mode 100644 index 625860a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/VerifierProxy.json +++ /dev/null @@ -1,435 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract AccessControllerInterface", - "name": "accessController", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessForbidden", - "type": "error" - }, - { - "inputs": [], - "name": "BadVerification", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "name": "ConfigDigestAlreadySet", - "type": "error" - }, - { - "inputs": [], - "name": "FeeManagerInvalid", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifier", - "type": "address" - } - ], - "name": "VerifierAlreadyInitialized", - "type": "error" - }, - { - "inputs": [], - "name": "VerifierInvalid", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "VerifierNotFound", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAccessController", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAccessController", - "type": "address" - } - ], - "name": "AccessControllerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldFeeManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newFeeManager", - "type": "address" - } - ], - "name": "FeeManagerSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "VerifierInitialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "oldConfigDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "newConfigDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "VerifierSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "VerifierUnset", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "getVerifier", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "verifierAddress", - "type": "address" - } - ], - "name": "initializeVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_accessController", - "outputs": [ - { - "internalType": "contract AccessControllerInterface", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "s_feeManager", - "outputs": [ - { - "internalType": "contract IVerifierFeeManager", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract AccessControllerInterface", - "name": "accessController", - "type": "address" - } - ], - "name": "setAccessController", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IVerifierFeeManager", - "name": "feeManager", - "type": "address" - } - ], - "name": "setFeeManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "currentConfigDigest", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newConfigDigest", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "weight", - "type": "uint64" - } - ], - "internalType": "struct Common.AddressAndWeight[]", - "name": "addressesAndWeights", - "type": "tuple[]" - } - ], - "name": "setVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "name": "unsetVerifier", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes[]", - "name": "payloads", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "parameterPayload", - "type": "bytes" - } - ], - "name": "verifyBulk", - "outputs": [ - { - "internalType": "bytes[]", - "name": "verifiedReports", - "type": "bytes[]" - } - ], - "stateMutability": "payable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json deleted file mode 100644 index 16b7b02..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WERC20Mock.json +++ /dev/null @@ -1,375 +0,0 @@ -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "subtractedValue", - "type": "uint256" - } - ], - "name": "decreaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "addedValue", - "type": "uint256" - } - ], - "name": "increaseAllowance", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json deleted file mode 100644 index 9cf2ec7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/WETH9.json +++ /dev/null @@ -1,309 +0,0 @@ -[ - { - "inputs": [], - "name": "InsufficientBalance", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "guy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "Withdrawal", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "guy", - "type": "address" - }, - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "deposit", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "src", - "type": "address" - }, - { - "internalType": "address", - "name": "dst", - "type": "address" - }, - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "wad", - "type": "uint256" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json deleted file mode 100644 index a62c6f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationForwarder.json +++ /dev/null @@ -1,80 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "address", - "name": "registry", - "type": "address" - }, - { - "internalType": "address", - "name": "logic", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "InvalidCaller", - "type": "error" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gasAmount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "forward", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getTarget", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json deleted file mode 100644 index fd901fc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistry2_3.json +++ /dev/null @@ -1,1580 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract ZKSyncAutomationRegistryLogicA2_3", - "name": "logicA", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "previousConfigBlockNumber", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "configCount", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "onchainConfig", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "ConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "name": "Transmitted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDetails", - "outputs": [ - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "blockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestConfigDigestAndEpoch", - "outputs": [ - { - "internalType": "bool", - "name": "scanLogs", - "type": "bool" - }, - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "onchainConfigBytes", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "setConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", - "name": "onchainConfig", - "type": "tuple" - }, - { - "internalType": "uint64", - "name": "offchainConfigVersion", - "type": "uint64" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - }, - { - "internalType": "contract IERC20Metadata[]", - "name": "billingTokens", - "type": "address[]" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]", - "name": "billingConfigs", - "type": "tuple[]" - } - ], - "name": "setConfigTypeSafe", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[3]", - "name": "reportContext", - "type": "bytes32[3]" - }, - { - "internalType": "bytes", - "name": "rawReport", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "rs", - "type": "bytes32[]" - }, - { - "internalType": "bytes32[]", - "name": "ss", - "type": "bytes32[]" - }, - { - "internalType": "bytes32", - "name": "rawVs", - "type": "bytes32" - } - ], - "name": "transmit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json deleted file mode 100644 index a94b41b..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryBase2_3.json +++ /dev/null @@ -1,1180 +0,0 @@ -[ - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json deleted file mode 100644 index 2e92ecc..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicA2_3.json +++ /dev/null @@ -1,1329 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract ZKSyncAutomationRegistryLogicB2_3", - "name": "logicB", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "cancelUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256[]", - "name": "ids", - "type": "uint256[]" - }, - { - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "migrateUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "onTokenTransfer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "encodedUpkeeps", - "type": "bytes" - } - ], - "name": "receiveUpkeeps", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "registerUpkeep", - "outputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json deleted file mode 100644 index 0fd9316..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicB2_3.json +++ /dev/null @@ -1,1672 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "contract ZKSyncAutomationRegistryLogicC2_3", - "name": "logicC", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "acceptUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "addFunds", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes[]", - "name": "values", - "type": "bytes[]" - }, - { - "internalType": "bytes", - "name": "extraData", - "type": "bytes" - } - ], - "name": "checkCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerData", - "type": "bytes" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "checkUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "gasLimit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fastGasWei", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "linkUSD", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "executeCallback", - "outputs": [ - { - "internalType": "bool", - "name": "upkeepNeeded", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason", - "name": "upkeepFailureReason", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "fallbackTo", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "pauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "removeBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "billingOverrides", - "type": "tuple" - } - ], - "name": "setBillingOverrides", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "setUpkeepCheckData", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setUpkeepGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "config", - "type": "bytes" - } - ], - "name": "setUpkeepOffchainConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "setUpkeepTriggerConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "performData", - "type": "bytes" - } - ], - "name": "simulatePerformUpkeep", - "outputs": [ - { - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferUpkeepAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "unpauseUpkeep", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawERC20Fees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawFunds", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawLink", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json deleted file mode 100644 index 87ae905..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncAutomationRegistryLogicC2_3.json +++ /dev/null @@ -1,2639 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "link", - "type": "address" - }, - { - "internalType": "address", - "name": "linkUSDFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "nativeUSDFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "fastGasFeed", - "type": "address" - }, - { - "internalType": "address", - "name": "automationForwarderLogic", - "type": "address" - }, - { - "internalType": "address", - "name": "allowedReadOnlyAddress", - "type": "address" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.PayoutMode", - "name": "payoutMode", - "type": "uint8" - }, - { - "internalType": "address", - "name": "wrappedNativeTokenAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ArrayHasNoEntries", - "type": "error" - }, - { - "inputs": [], - "name": "CannotCancel", - "type": "error" - }, - { - "inputs": [], - "name": "CheckDataExceedsLimit", - "type": "error" - }, - { - "inputs": [], - "name": "ConfigDigestMismatch", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateEntry", - "type": "error" - }, - { - "inputs": [], - "name": "DuplicateSigners", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitCanOnlyIncrease", - "type": "error" - }, - { - "inputs": [], - "name": "GasLimitOutsideRange", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfFaultyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSignatures", - "type": "error" - }, - { - "inputs": [], - "name": "IncorrectNumberOfSigners", - "type": "error" - }, - { - "inputs": [], - "name": "IndexOutOfRange", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "available", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "requested", - "type": "uint256" - } - ], - "name": "InsufficientBalance", - "type": "error" - }, - { - "inputs": [], - "name": "InsufficientLinkLiquidity", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidDataLength", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidFeed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidPayee", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidRecipient", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidReport", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidSigner", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidToken", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTransmitter", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTrigger", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidTriggerType", - "type": "error" - }, - { - "inputs": [], - "name": "MigrationNotPermitted", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOffchain", - "type": "error" - }, - { - "inputs": [], - "name": "MustSettleOnchain", - "type": "error" - }, - { - "inputs": [], - "name": "NotAContract", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveSigners", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyActiveTransmitters", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByLINKToken", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByOwnerOrRegistrar", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByProposedPayee", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyCallableByUpkeepPrivilegeManager", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyFinanceAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyPausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "OnlySimulatedBackend", - "type": "error" - }, - { - "inputs": [], - "name": "OnlyUnpausedUpkeep", - "type": "error" - }, - { - "inputs": [], - "name": "ParameterLengthError", - "type": "error" - }, - { - "inputs": [], - "name": "ReentrantCall", - "type": "error" - }, - { - "inputs": [], - "name": "RegistryPaused", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedSigner", - "type": "error" - }, - { - "inputs": [], - "name": "RepeatedTransmitter", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "TargetCheckReverted", - "type": "error" - }, - { - "inputs": [], - "name": "TooManyOracles", - "type": "error" - }, - { - "inputs": [], - "name": "TranscoderNotSet", - "type": "error" - }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepCancelled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotCanceled", - "type": "error" - }, - { - "inputs": [], - "name": "UpkeepNotNeeded", - "type": "error" - }, - { - "inputs": [], - "name": "ValueNotChanged", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "AdminPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "overrides", - "type": "tuple" - } - ], - "name": "BillingConfigOverridden", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "BillingConfigOverrideRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "config", - "type": "tuple" - } - ], - "name": "BillingConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "CancelledUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "newModule", - "type": "address" - } - ], - "name": "ChainSpecificModuleUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "DedupKeyAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetAddress", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "FeesWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "amount", - "type": "uint96" - } - ], - "name": "FundsAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "FundsWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "InsufficientFundsUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256[]", - "name": "payments", - "type": "uint256[]" - } - ], - "name": "NOPsSettledOffchain", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Paused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "PayeesUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "PayeeshipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "name": "PaymentWithdrawn", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "ReorgedUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "StaleUpkeepReport", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "Unpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "UpkeepAdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "atBlockHeight", - "type": "uint64" - } - ], - "name": "UpkeepCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "uint96", - "name": "gasChargeInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInBillingToken", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "gasReimbursementInJuels", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "premiumInJuels", - "type": "uint96" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - }, - { - "internalType": "uint96", - "name": "linkUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "nativeUSD", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "billingUSD", - "type": "uint96" - } - ], - "indexed": false, - "internalType": "struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt", - "name": "receipt", - "type": "tuple" - } - ], - "name": "UpkeepCharged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "newCheckData", - "type": "bytes" - } - ], - "name": "UpkeepCheckDataSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "gasLimit", - "type": "uint96" - } - ], - "name": "UpkeepGasLimitSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "destination", - "type": "address" - } - ], - "name": "UpkeepMigrated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "name": "UpkeepOffchainConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bool", - "name": "success", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "totalPayment", - "type": "uint96" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasUsed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "gasOverhead", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "trigger", - "type": "bytes" - } - ], - "name": "UpkeepPerformed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "privilegeConfig", - "type": "bytes" - } - ], - "name": "UpkeepPrivilegeConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startingBalance", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "importedFrom", - "type": "address" - } - ], - "name": "UpkeepReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "UpkeepRegistered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "triggerConfig", - "type": "bytes" - } - ], - "name": "UpkeepTriggerConfigSet", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "UpkeepUnpaused", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - } - ], - "name": "acceptPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "disableOffchainPayments", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "startIndex", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxCount", - "type": "uint256" - } - ], - "name": "getActiveUpkeepIDs", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - } - ], - "name": "getAdminPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAllowedReadOnlyAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getAutomationForwarderLogic", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getAvailableERC20ForPayment", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getBillingConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverrides", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingOverrides", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingOverridesEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getBillingToken", - "outputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - } - ], - "name": "getBillingTokenConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "gasFeePPB", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "flatFeeMilliCents", - "type": "uint24" - }, - { - "internalType": "contract AggregatorV3Interface", - "name": "priceFeed", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "fallbackPrice", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "minSpend", - "type": "uint96" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.BillingConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getBillingTokens", - "outputs": [ - { - "internalType": "contract IERC20Metadata[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getCancellationDelay", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getChainModule", - "outputs": [ - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getConditionalGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getConfig", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackNativePrice", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.OnchainConfig", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFallbackNativePrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getFastGasFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepID", - "type": "uint256" - } - ], - "name": "getForwarder", - "outputs": [ - { - "internalType": "contract IAutomationForwarder", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getHotVars", - "outputs": [ - { - "components": [ - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reentrancyGuard", - "type": "bool" - }, - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - }, - { - "internalType": "contract IChainModule", - "name": "chainModule", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.HotVars", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLinkUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getLogGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", - "name": "triggerType", - "type": "uint8" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getMaxPaymentForGas", - "outputs": [ - { - "internalType": "uint96", - "name": "maxPayment", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalance", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getMinBalanceForUpkeep", - "outputs": [ - { - "internalType": "uint96", - "name": "minBalance", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNativeUSDFeedAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getNumUpkeeps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPayoutMode", - "outputs": [ - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.PayoutMode", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - } - ], - "name": "getPeerRegistryMigrationPermission", - "outputs": [ - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.MigrationPermission", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getPerSignerGasOverhead", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "getReorgProtectionEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "reorgProtectionEnabled", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "billingToken", - "type": "address" - } - ], - "name": "getReserveAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getSignerInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getState", - "outputs": [ - { - "components": [ - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "ownerLinkBalance", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "expectedLinkBalance", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "totalPremium", - "type": "uint96" - }, - { - "internalType": "uint256", - "name": "numUpkeeps", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "bytes32", - "name": "latestConfigDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "latestEpoch", - "type": "uint32" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - } - ], - "internalType": "struct IAutomationV21PlusCommon.StateLegacy", - "name": "state", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "uint32", - "name": "paymentPremiumPPB", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "flatFeeMicroLink", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint24", - "name": "stalenessSeconds", - "type": "uint24" - }, - { - "internalType": "uint16", - "name": "gasCeilingMultiplier", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "minUpkeepSpend", - "type": "uint96" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - }, - { - "internalType": "uint256", - "name": "fallbackGasPrice", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "fallbackLinkPrice", - "type": "uint256" - }, - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "address[]", - "name": "registrars", - "type": "address[]" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - } - ], - "internalType": "struct IAutomationV21PlusCommon.OnchainConfigLegacy", - "name": "config", - "type": "tuple" - }, - { - "internalType": "address[]", - "name": "signers", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "transmitters", - "type": "address[]" - }, - { - "internalType": "uint8", - "name": "f", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getStorage", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transcoder", - "type": "address" - }, - { - "internalType": "uint32", - "name": "checkGasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxPerformGas", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "nonce", - "type": "uint32" - }, - { - "internalType": "address", - "name": "upkeepPrivilegeManager", - "type": "address" - }, - { - "internalType": "uint32", - "name": "configCount", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "latestConfigBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxCheckDataSize", - "type": "uint32" - }, - { - "internalType": "address", - "name": "financeAdmin", - "type": "address" - }, - { - "internalType": "uint32", - "name": "maxPerformDataSize", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "maxRevertDataSize", - "type": "uint32" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.Storage", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "query", - "type": "address" - } - ], - "name": "getTransmitterInfo", - "outputs": [ - { - "internalType": "bool", - "name": "active", - "type": "bool" - }, - { - "internalType": "uint8", - "name": "index", - "type": "uint8" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "lastCollected", - "type": "uint96" - }, - { - "internalType": "address", - "name": "payee", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTransmittersWithPayees", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "transmitterAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "payeeAddress", - "type": "address" - } - ], - "internalType": "struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getTriggerType", - "outputs": [ - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.Trigger", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - } - ], - "name": "getUpkeep", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "target", - "type": "address" - }, - { - "internalType": "uint32", - "name": "performGas", - "type": "uint32" - }, - { - "internalType": "bytes", - "name": "checkData", - "type": "bytes" - }, - { - "internalType": "uint96", - "name": "balance", - "type": "uint96" - }, - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "uint64", - "name": "maxValidBlocknumber", - "type": "uint64" - }, - { - "internalType": "uint32", - "name": "lastPerformedBlockNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "amountSpent", - "type": "uint96" - }, - { - "internalType": "bool", - "name": "paused", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "offchainConfig", - "type": "bytes" - } - ], - "internalType": "struct IAutomationV21PlusCommon.UpkeepInfoLegacy", - "name": "upkeepInfo", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepPrivilegeConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - } - ], - "name": "getUpkeepTriggerConfig", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getWrappedNativeTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "dedupKey", - "type": "bytes32" - } - ], - "name": "hasDedupKey", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "linkAvailableForPayment", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setAdminPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address[]", - "name": "payees", - "type": "address[]" - } - ], - "name": "setPayees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "peer", - "type": "address" - }, - { - "internalType": "enum ZKSyncAutomationRegistryBase2_3.MigrationPermission", - "name": "permission", - "type": "uint8" - } - ], - "name": "setPeerRegistryMigrationPermission", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "upkeepId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "newPrivilegeConfig", - "type": "bytes" - } - ], - "name": "setUpkeepPrivilegeConfig", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "settleNOPsOffchain", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IERC20Metadata", - "name": "token", - "type": "address" - } - ], - "name": "supportsBillingToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "transmitter", - "type": "address" - }, - { - "internalType": "address", - "name": "proposed", - "type": "address" - } - ], - "name": "transferPayeeship", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "upkeepVersion", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "withdrawPayment", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json deleted file mode 100644 index 44ce54a..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncSequencerUptimeFeed.json +++ /dev/null @@ -1,578 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1SenderAddress", - "type": "address" - }, - { - "internalType": "bool", - "name": "initialStatus", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidSender", - "type": "error" - }, - { - "inputs": [], - "name": "NoDataPresent", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "int256", - "name": "current", - "type": "int256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - } - ], - "name": "AnswerUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "L1SenderTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "startedBy", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - } - ], - "name": "NewRound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "int256", - "name": "status", - "type": "int256" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "updatedAt", - "type": "uint64" - } - ], - "name": "RoundUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bool", - "name": "latestStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "latestTimestamp", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bool", - "name": "incomingStatus", - "type": "bool" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "incomingTimestamp", - "type": "uint64" - } - ], - "name": "UpdateIgnored", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "decimals", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "description", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint80", - "name": "_roundId", - "type": "uint80" - } - ], - "name": "getRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "roundId", - "type": "uint256" - } - ], - "name": "getTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "l1Sender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestAnswer", - "outputs": [ - { - "internalType": "int256", - "name": "", - "type": "int256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestRoundData", - "outputs": [ - { - "internalType": "uint80", - "name": "roundId", - "type": "uint80" - }, - { - "internalType": "int256", - "name": "answer", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "startedAt", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "updatedAt", - "type": "uint256" - }, - { - "internalType": "uint80", - "name": "answeredInRound", - "type": "uint80" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "latestTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferL1Sender", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "status", - "type": "bool" - }, - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - } - ], - "name": "updateStatus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json deleted file mode 100644 index 425d150..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/ZKSyncValidator.json +++ /dev/null @@ -1,402 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "l1CrossDomainMessengerAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "l2UptimeFeedAddr", - "type": "address" - }, - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "chainId", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "l2GasPerPubdataByteLimit", - "type": "uint32" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidChainID", - "type": "error" - }, - { - "inputs": [], - "name": "L1CrossDomainMessengerAddressZero", - "type": "error" - }, - { - "inputs": [], - "name": "L2UptimeFeedAddrZero", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "AddedAccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessDisabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CheckAccessEnabled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "GasLimitUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "l2GasPerPubdataByteLimit", - "type": "uint32" - } - ], - "name": "GasPerPubdataByteLimitUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferRequested", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "user", - "type": "address" - } - ], - "name": "RemovedAccess", - "type": "event" - }, - { - "inputs": [], - "name": "L1_CROSS_DOMAIN_MESSENGER_ADDRESS", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "L2_UPTIME_FEED_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "addAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "checkEnabled", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "disableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "enableAccessCheck", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "getChainId", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getGasLimit", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getL2GasPerPubdataByteLimit", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "hasAccess", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_user", - "type": "address" - } - ], - "name": "removeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "gasLimit", - "type": "uint32" - } - ], - "name": "setGasLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "l2GasPerPubdataByteLimit", - "type": "uint32" - } - ], - "name": "setL2GasPerPubdataByteLimit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "typeAndVersion", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "", - "type": "int256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "int256", - "name": "currentAnswer", - "type": "int256" - } - ], - "name": "validate", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json b/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json deleted file mode 100644 index 7d0e9a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/abi/v0.8/iOVM_CrossDomainMessenger.json +++ /dev/null @@ -1,77 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "FailedRelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - } - ], - "name": "RelayedMessage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "SentMessage", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_target", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_message", - "type": "bytes" - }, - { - "internalType": "uint32", - "name": "_gasLimit", - "type": "uint32" - } - ], - "name": "sendMessage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "xDomainMessageSender", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - } -] diff --git a/packages/foundry/lib/chainlink/contracts/package.json b/packages/foundry/lib/chainlink/contracts/package.json deleted file mode 100644 index c6bb574..0000000 --- a/packages/foundry/lib/chainlink/contracts/package.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "name": "@chainlink/contracts", - "version": "1.3.0", - "description": "Chainlink smart contracts", - "author": "Chainlink devs", - "license": "MIT", - "private": false, - "files": [ - "src/v0.8", - "abi/v0.8" - ], - "engines": { - "node": ">=18", - "pnpm": ">=9" - }, - "devDependencies": { - "@ethereum-waffle/mock-contract": "^3.4.4", - "@ethersproject/abi": "~5.7.0", - "@ethersproject/bignumber": "~5.7.0", - "@ethersproject/contracts": "~5.7.0", - "@ethersproject/providers": "~5.7.2", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", - "@nomicfoundation/hardhat-ethers": "^3.0.8", - "@nomicfoundation/hardhat-network-helpers": "^1.0.12", - "@nomicfoundation/hardhat-verify": "^2.0.11", - "@typechain/ethers-v5": "^7.2.0", - "@typechain/hardhat": "^7.0.0", - "@types/cbor": "~5.0.1", - "@types/chai": "^4.3.20", - "@types/debug": "^4.1.12", - "@types/deep-equal-in-any-order": "^1.0.3", - "@types/mocha": "^10.0.8", - "@types/node": "^20.16.10", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "abi-to-sol": "^0.6.6", - "cbor": "^5.2.0", - "chai": "^4.5.0", - "debug": "^4.3.7", - "deep-equal-in-any-order": "^2.0.6", - "eslint": "^8.57.1", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", - "ethers": "~5.7.2", - "hardhat": "~2.20.1", - "hardhat-abi-exporter": "^2.10.1", - "hardhat-ignore-warnings": "^0.2.6", - "moment": "^2.30.1", - "prettier": "^3.3.3", - "prettier-plugin-solidity": "^1.4.1", - "solhint": "^5.0.3", - "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", - "solhint-plugin-prettier": "^0.1.0", - "ts-node": "^10.9.2", - "typechain": "^8.2.1", - "typescript": "^5.6.2" - }, - "dependencies": { - "@arbitrum/nitro-contracts": "1.1.1", - "@arbitrum/token-bridge-contracts": "1.1.2", - "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "~2.27.8", - "@eth-optimism/contracts": "0.6.0", - "@openzeppelin/contracts": "4.9.3", - "@openzeppelin/contracts-upgradeable": "4.9.3", - "@scroll-tech/contracts": "0.1.0", - "@zksync/contracts": "git+https://github.com/matter-labs/era-contracts.git#446d391d34bdb48255d5f8fef8a8248925fc98b9", - "semver": "^7.6.3" - }, - "scripts": { - "test": "hardhat test --parallel", - "lint": "eslint --ext js,ts .", - "prettier:check": "prettier '**/*' --check --ignore-unknown", - "prettier:write": "prettier '**/*' --write --ignore-unknown", - "size": "hardhat size-contracts", - "clean": "hardhat clean", - "compile:native": "./scripts/native_solc_compile_all", - "compile": "hardhat compile", - "coverage": "hardhat coverage", - "publish-beta": "pnpm publish --tag beta", - "publish-prod": "pnpm publish --tag latest", - "solhint": "solhint --max-warnings 0 \"./src/v0.8/**/*.sol\"" - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol deleted file mode 100644 index c5052cd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil.sol +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_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. -/// @dev For instance, ChainSpecificUtil.getBlockNumber() returns L2 block number in L2 chains -library ChainSpecificUtil { - // ------------ Start Arbitrum Constants ------------ - - /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - - /// @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); - - uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; - uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; - uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; - - // ------------ 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 OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - uint256 private constant OP_MAINNET_CHAIN_ID = 10; - uint256 private constant OP_GOERLI_CHAIN_ID = 420; - uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; - - /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. - uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; - uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; - uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; - - // ------------ End Optimism Constants ------------ - - /** - * @notice Returns the blockhash for the given blockNumber. - * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. - * @notice Otherwise, it uses the blockhash opcode. - * @notice Note that the blockhash opcode will return the L2 blockhash on Optimism. - */ - function _getBlockhash(uint64 blockNumber) internal view returns (bytes32) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - if ((_getBlockNumber() - blockNumber) > 256 || blockNumber >= _getBlockNumber()) { - return ""; - } - return ARBSYS.arbBlockHash(blockNumber); - } - return blockhash(blockNumber); - } - - /** - * @notice Returns the block number of the current block. - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. - * @notice Otherwise, it uses the block.number opcode. - * @notice Note that the block.number opcode will return the L2 block number on Optimism. - */ - function _getBlockNumber() internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - return ARBSYS.arbBlockNumber(); - } - return block.number; - } - - /** - * @notice Returns the L1 fees 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, there's no need to pass the provided calldata - * @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy - * @notice and getL1Fee is called to get the fees. - */ - function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - return ARBGAS.getCurrentTxL1GasFees(); - } else if (_isOptimismChainId(chainid)) { - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); - } - return 0; - } - - /** - * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted - * @notice to L1. - */ - function _getL1CalldataGasCost(uint256 calldataSizeBytes) internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); - // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from - // for the justification behind the 140 number. - return l1PricePerByte * (calldataSizeBytes + 140); - } else if (_isOptimismChainId(chainid)) { - return _calculateOptimismL1DataFee(calldataSizeBytes); - } - return 0; - } - - /** - * @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. - */ - function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == ARB_MAINNET_CHAIN_ID || - chainId == ARB_GOERLI_TESTNET_CHAIN_ID || - chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; - } - - /** - * @notice Return true if and only if the provided chain ID is an Optimism chain ID. - * @notice Note that optimism chain id's are also OP stack chain id's (e.g. Base). - */ - function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == OP_MAINNET_CHAIN_ID || - chainId == OP_GOERLI_CHAIN_ID || - chainId == OP_SEPOLIA_CHAIN_ID || - chainId == BASE_MAINNET_CHAIN_ID || - chainId == BASE_GOERLI_CHAIN_ID || - chainId == BASE_SEPOLIA_CHAIN_ID; - } - - function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { - // from: https://community.optimism.io/docs/developers/build/transaction-fees/#the-l1-data-fee - // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead - // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 - // note we conservatively assume all non-zero bytes. - uint256 l1BaseFeeWei = OVM_GASPRICEORACLE.l1BaseFee(); - uint256 numZeroBytes = 0; - uint256 numNonzeroBytes = calldataSizeBytes - numZeroBytes; - uint256 txDataGas = numZeroBytes * 4 + numNonzeroBytes * 16; - uint256 fixedOverhead = OVM_GASPRICEORACLE.overhead(); - - // The scalar is some value like 0.684, but is represented as - // that times 10 ^ number of scalar decimals. - // e.g scalar = 0.684 * 10^6 - // The divisor is used to divide that and have a net result of the true scalar. - uint256 scalar = OVM_GASPRICEORACLE.scalar(); - uint256 scalarDecimals = OVM_GASPRICEORACLE.decimals(); - uint256 divisor = 10 ** scalarDecimals; - - uint256 l1DataFee = (l1BaseFeeWei * (txDataGas + fixedOverhead) * scalar) / divisor; - return l1DataFee; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol deleted file mode 100644 index 0379dc8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainSpecificUtil_v0_8_6.sol +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "./vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_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. -/// @dev For instance, ChainSpecificUtil.getBlockNumber() returns L2 block number in L2 chains -library ChainSpecificUtil { - // ------------ Start Arbitrum Constants ------------ - - /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - - /// @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); - - uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; - uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; - uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; - - // ------------ 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 OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - uint256 private constant OP_MAINNET_CHAIN_ID = 10; - uint256 private constant OP_GOERLI_CHAIN_ID = 420; - uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; - - /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. - uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; - uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; - uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; - - // ------------ End Optimism Constants ------------ - - /** - * @notice Returns the blockhash for the given blockNumber. - * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. - * @notice Otherwise, it uses the blockhash opcode. - * @notice Note that the blockhash opcode will return the L2 blockhash on Optimism. - */ - function _getBlockhash(uint64 blockNumber) internal view returns (bytes32) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - if ((_getBlockNumber() - blockNumber) > 256 || blockNumber >= _getBlockNumber()) { - return ""; - } - return ARBSYS.arbBlockHash(blockNumber); - } - return blockhash(blockNumber); - } - - /** - * @notice Returns the block number of the current block. - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. - * @notice Otherwise, it uses the block.number opcode. - * @notice Note that the block.number opcode will return the L2 block number on Optimism. - */ - function _getBlockNumber() internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - return ARBSYS.arbBlockNumber(); - } - return block.number; - } - - /** - * @notice Returns the L1 fees 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, there's no need to pass the provided calldata - * @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy - * @notice and getL1Fee is called to get the fees. - */ - function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - return ARBGAS.getCurrentTxL1GasFees(); - } else if (_isOptimismChainId(chainid)) { - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); - } - return 0; - } - - /** - * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted - * @notice to L1. - */ - function _getL1CalldataGasCost(uint256 calldataSizeBytes) internal view returns (uint256) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); - // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from - // for the justification behind the 140 number. - return l1PricePerByte * (calldataSizeBytes + 140); - } else if (_isOptimismChainId(chainid)) { - return _calculateOptimismL1DataFee(calldataSizeBytes); - } - return 0; - } - - /** - * @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. - */ - function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == ARB_MAINNET_CHAIN_ID || - chainId == ARB_GOERLI_TESTNET_CHAIN_ID || - chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; - } - - /** - * @notice Return true if and only if the provided chain ID is an Optimism chain ID. - * @notice Note that optimism chain id's are also OP stack chain id's (e.g. Base). - */ - function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == OP_MAINNET_CHAIN_ID || - chainId == OP_GOERLI_CHAIN_ID || - chainId == OP_SEPOLIA_CHAIN_ID || - chainId == BASE_MAINNET_CHAIN_ID || - chainId == BASE_GOERLI_CHAIN_ID || - chainId == BASE_SEPOLIA_CHAIN_ID; - } - - function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { - // from: https://community.optimism.io/docs/developers/build/transaction-fees/#the-l1-data-fee - // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead - // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 - // note we conservatively assume all non-zero bytes. - uint256 l1BaseFeeWei = OVM_GASPRICEORACLE.l1BaseFee(); - uint256 numZeroBytes = 0; - uint256 numNonzeroBytes = calldataSizeBytes - numZeroBytes; - uint256 txDataGas = numZeroBytes * 4 + numNonzeroBytes * 16; - uint256 fixedOverhead = OVM_GASPRICEORACLE.overhead(); - - // The scalar is some value like 0.684, but is represented as - // that times 10 ^ number of scalar decimals. - // e.g scalar = 0.684 * 10^6 - // The divisor is used to divide that and have a net result of the true scalar. - uint256 scalar = OVM_GASPRICEORACLE.scalar(); - uint256 scalarDecimals = OVM_GASPRICEORACLE.decimals(); - uint256 divisor = 10 ** scalarDecimals; - - uint256 l1DataFee = (l1BaseFeeWei * (txDataGas + fixedOverhead) * scalar) / divisor; - return l1DataFee; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol deleted file mode 100644 index e511cfc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/Chainlink.sol +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {CBORChainlink} from "./vendor/CBORChainlink.sol"; -import {BufferChainlink} from "./vendor/BufferChainlink.sol"; - -/** - * @title Library for common Chainlink functions - * @dev Uses imported CBOR library for encoding to buffer - */ -library Chainlink { - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint256 internal constant defaultBufferSize = 256; - - using CBORChainlink for BufferChainlink.buffer; - - struct Request { - bytes32 id; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - BufferChainlink.buffer buf; - } - - /** - * @notice Initializes a Chainlink request - * @dev Sets the ID, callback address, and callback function signature on the request - * @param self The uninitialized request - * @param jobId The Job Specification ID - * @param callbackAddr The callback address - * @param callbackFunc The callback function signature - * @return The initialized request - */ - function _initialize( - Request memory self, - bytes32 jobId, - address callbackAddr, - bytes4 callbackFunc - ) internal pure returns (Chainlink.Request memory) { - BufferChainlink.init(self.buf, defaultBufferSize); - self.id = jobId; - self.callbackAddress = callbackAddr; - self.callbackFunctionId = callbackFunc; - return self; - } - - /** - * @notice Sets the data for the buffer without encoding CBOR on-chain - * @dev CBOR can be closed with curly-brackets {} or they can be left off - * @param self The initialized request - * @param data The CBOR data - */ - function _setBuffer(Request memory self, bytes memory data) internal pure { - BufferChainlink.init(self.buf, data.length); - BufferChainlink.append(self.buf, data); - } - - /** - * @notice Adds a string value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The string value to add - */ - function _add(Request memory self, string memory key, string memory value) internal pure { - self.buf.encodeString(key); - self.buf.encodeString(value); - } - - /** - * @notice Adds a bytes value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The bytes value to add - */ - function _addBytes(Request memory self, string memory key, bytes memory value) internal pure { - self.buf.encodeString(key); - self.buf.encodeBytes(value); - } - - /** - * @notice Adds a int256 value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The int256 value to add - */ - function _addInt(Request memory self, string memory key, int256 value) internal pure { - self.buf.encodeString(key); - self.buf.encodeInt(value); - } - - /** - * @notice Adds a uint256 value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The uint256 value to add - */ - function _addUint(Request memory self, string memory key, uint256 value) internal pure { - self.buf.encodeString(key); - self.buf.encodeUInt(value); - } - - /** - * @notice Adds an array of strings to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param values The array of string values to add - */ - function _addStringArray(Request memory self, string memory key, string[] memory values) internal pure { - self.buf.encodeString(key); - self.buf.startArray(); - for (uint256 i = 0; i < values.length; i++) { - self.buf.encodeString(values[i]); - } - self.buf.endSequence(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol deleted file mode 100644 index 1d8640a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol +++ /dev/null @@ -1,318 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Chainlink} from "./Chainlink.sol"; -import {ENSInterface} from "./interfaces/ENSInterface.sol"; -import {LinkTokenInterface} from "./shared/interfaces/LinkTokenInterface.sol"; -import {ChainlinkRequestInterface} from "./interfaces/ChainlinkRequestInterface.sol"; -import {OperatorInterface} from "./interfaces/OperatorInterface.sol"; -import {PointerInterface} from "./interfaces/PointerInterface.sol"; -import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; - -/** - * @title The ChainlinkClient contract - * @notice Contract writers can inherit this contract in order to create requests for the - * Chainlink network - */ -// solhint-disable gas-custom-errors -abstract contract ChainlinkClient { - using Chainlink for Chainlink.Request; - - uint256 internal constant LINK_DIVISIBILITY = 10 ** 18; - uint256 private constant AMOUNT_OVERRIDE = 0; - address private constant SENDER_OVERRIDE = address(0); - uint256 private constant ORACLE_ARGS_VERSION = 1; - uint256 private constant OPERATOR_ARGS_VERSION = 2; - bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link"); - bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle"); - address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; - - ENSInterface private s_ens; - bytes32 private s_ensNode; - LinkTokenInterface private s_link; - OperatorInterface private s_oracle; - uint256 private s_requestCount = 1; - mapping(bytes32 => address) private s_pendingRequests; - - event ChainlinkRequested(bytes32 indexed id); - event ChainlinkFulfilled(bytes32 indexed id); - event ChainlinkCancelled(bytes32 indexed id); - - /** - * @notice Creates a request that can hold additional parameters - * @param specId The Job Specification ID that the request will be created for - * @param callbackAddr address to operate the callback on - * @param callbackFunctionSignature function signature to use for the callback - * @return A Chainlink Request struct in memory - */ - function _buildChainlinkRequest( - bytes32 specId, - address callbackAddr, - bytes4 callbackFunctionSignature - ) internal pure returns (Chainlink.Request memory) { - Chainlink.Request memory req; - return req._initialize(specId, callbackAddr, callbackFunctionSignature); - } - - /** - * @notice Creates a request that can hold additional parameters - * @param specId The Job Specification ID that the request will be created for - * @param callbackFunctionSignature function signature to use for the callback - * @return A Chainlink Request struct in memory - */ - function _buildOperatorRequest( - bytes32 specId, - bytes4 callbackFunctionSignature - ) internal view returns (Chainlink.Request memory) { - Chainlink.Request memory req; - return req._initialize(specId, address(this), callbackFunctionSignature); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev Calls `chainlinkRequestTo` with the stored oracle address - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function _sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { - return _sendChainlinkRequestTo(address(s_oracle), req, payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param oracleAddress The address of the oracle for the request - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function _sendChainlinkRequestTo( - address oracleAddress, - Chainlink.Request memory req, - uint256 payment - ) internal returns (bytes32 requestId) { - uint256 nonce = s_requestCount; - s_requestCount = nonce + 1; - bytes memory encodedRequest = abi.encodeWithSelector( - ChainlinkRequestInterface.oracleRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - req.id, - address(this), - req.callbackFunctionId, - nonce, - ORACLE_ARGS_VERSION, - req.buf.buf - ); - return _rawRequest(oracleAddress, nonce, payment, encodedRequest); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev This function supports multi-word response - * @dev Calls `sendOperatorRequestTo` with the stored oracle address - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function _sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { - return _sendOperatorRequestTo(address(s_oracle), req, payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev This function supports multi-word response - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param oracleAddress The address of the oracle for the request - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function _sendOperatorRequestTo( - address oracleAddress, - Chainlink.Request memory req, - uint256 payment - ) internal returns (bytes32 requestId) { - uint256 nonce = s_requestCount; - s_requestCount = nonce + 1; - bytes memory encodedRequest = abi.encodeWithSelector( - OperatorInterface.operatorRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - req.id, - req.callbackFunctionId, - nonce, - OPERATOR_ARGS_VERSION, - req.buf.buf - ); - return _rawRequest(oracleAddress, nonce, payment, encodedRequest); - } - - /** - * @notice Make a request to an oracle - * @param oracleAddress The address of the oracle for the request - * @param nonce used to generate the request ID - * @param payment The amount of LINK to send for the request - * @param encodedRequest data encoded for request type specific format - * @return requestId The request ID - */ - function _rawRequest( - address oracleAddress, - uint256 nonce, - uint256 payment, - bytes memory encodedRequest - ) private returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, nonce)); - s_pendingRequests[requestId] = oracleAddress; - emit ChainlinkRequested(requestId); - require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle"); - return requestId; - } - - /** - * @notice Allows a request to be cancelled if it has not been fulfilled - * @dev Requires keeping track of the expiration value emitted from the oracle contract. - * Deletes the request from the `pendingRequests` mapping. - * Emits ChainlinkCancelled event. - * @param requestId The request ID - * @param payment The amount of LINK sent for the request - * @param callbackFunc The callback function specified for the request - * @param expiration The time of the expiration for the request - */ - function _cancelChainlinkRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) internal { - OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]); - delete s_pendingRequests[requestId]; - emit ChainlinkCancelled(requestId); - requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); - } - - /** - * @notice the next request count to be used in generating a nonce - * @dev starts at 1 in order to ensure consistent gas cost - * @return returns the next request count to be used in a nonce - */ - function _getNextRequestCount() internal view returns (uint256) { - return s_requestCount; - } - - /** - * @notice Sets the stored oracle address - * @param oracleAddress The address of the oracle contract - */ - function _setChainlinkOracle(address oracleAddress) internal { - s_oracle = OperatorInterface(oracleAddress); - } - - /** - * @notice Sets the LINK token address - * @param linkAddress The address of the LINK token contract - */ - function _setChainlinkToken(address linkAddress) internal { - s_link = LinkTokenInterface(linkAddress); - } - - /** - * @notice Sets the Chainlink token address for the public - * network as given by the Pointer contract - */ - function _setPublicChainlinkToken() internal { - _setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); - } - - /** - * @notice Retrieves the stored address of the LINK token - * @return The address of the LINK token - */ - function _chainlinkTokenAddress() internal view returns (address) { - return address(s_link); - } - - /** - * @notice Retrieves the stored address of the oracle contract - * @return The address of the oracle contract - */ - function _chainlinkOracleAddress() internal view returns (address) { - return address(s_oracle); - } - - /** - * @notice Allows for a request which was created on another contract to be fulfilled - * on this contract - * @param oracleAddress The address of the oracle contract that will fulfill the request - * @param requestId The request ID used for the response - */ - function _addChainlinkExternalRequest( - address oracleAddress, - bytes32 requestId - ) internal notPendingRequest(requestId) { - s_pendingRequests[requestId] = oracleAddress; - } - - /** - * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS - * @dev Accounts for subnodes having different resolvers - * @param ensAddress The address of the ENS contract - * @param node The ENS node hash - */ - function _useChainlinkWithENS(address ensAddress, bytes32 node) internal { - s_ens = ENSInterface(ensAddress); - s_ensNode = node; - bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode)); - _setChainlinkToken(resolver.addr(linkSubnode)); - _updateChainlinkOracleWithENS(); - } - - /** - * @notice Sets the stored oracle contract with the address resolved by ENS - * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously - */ - function _updateChainlinkOracleWithENS() internal { - bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode)); - _setChainlinkOracle(resolver.addr(oracleSubnode)); - } - - /** - * @notice Ensures that the fulfillment is valid for this contract - * @dev Use if the contract developer prefers methods instead of modifiers for validation - * @param requestId The request ID for fulfillment - */ - function _validateChainlinkCallback( - bytes32 requestId - ) - internal - recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks - {} - - /** - * @dev Reverts if the sender is not the oracle of the request. - * Emits ChainlinkFulfilled event. - * @param requestId The request ID for fulfillment - */ - modifier recordChainlinkFulfillment(bytes32 requestId) { - require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request"); - delete s_pendingRequests[requestId]; - emit ChainlinkFulfilled(requestId); - _; - } - - /** - * @dev Reverts if the request is already pending - * @param requestId The request ID for fulfillment - */ - modifier notPendingRequest(bytes32 requestId) { - require(s_pendingRequests[requestId] == address(0), "Request is already pending"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol deleted file mode 100644 index 6e9aa77..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/Denominations.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -library Denominations { - address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; - - // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217 - address public constant USD = address(840); - address public constant GBP = address(826); - address public constant EUR = address(978); - address public constant JPY = address(392); - address public constant KRW = address(410); - address public constant CNY = address(156); - address public constant AUD = address(36); - address public constant CAD = address(124); - address public constant CHF = address(756); - address public constant ARS = address(32); - address public constant PHP = address(608); - address public constant NZD = address(554); - address public constant SGD = address(702); - address public constant NGN = address(566); - address public constant ZAR = address(710); - address public constant RUB = address(643); - address public constant INR = address(356); - address public constant BRL = address(986); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol deleted file mode 100644 index de14583..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/Flags.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {SimpleReadAccessController} from "./shared/access/SimpleReadAccessController.sol"; -import {AccessControllerInterface} from "./shared/interfaces/AccessControllerInterface.sol"; -import {FlagsInterface} from "./interfaces/FlagsInterface.sol"; - -/** - * @title The Flags contract - * @notice Allows flags to signal to any reader on the access control list. - * The owner can set flags, or designate other addresses to set flags. The - * owner must turn the flags off, other setters cannot. An expected pattern is - * to allow addresses to raise flags on themselves, so if you are subscribing to - * FlagOn events you should filter for addresses you care about. - */ -// solhint-disable gas-custom-errors -contract Flags is FlagsInterface, SimpleReadAccessController { - AccessControllerInterface public raisingAccessController; - - mapping(address => bool) private s_flags; - - event FlagRaised(address indexed subject); - event FlagLowered(address indexed subject); - event RaisingAccessControllerUpdated(address indexed previous, address indexed current); - - /** - * @param racAddress address for the raising access controller. - */ - constructor(address racAddress) { - setRaisingAccessController(racAddress); - } - - /** - * @notice read the warning flag status of a contract address. - * @param subject The contract address being checked for a flag. - * @return A true value indicates that a flag was raised and a - * false value indicates that no flag was raised. - */ - function getFlag(address subject) external view override checkAccess returns (bool) { - return s_flags[subject]; - } - - /** - * @notice read the warning flag status of a contract address. - * @param subjects An array of addresses being checked for a flag. - * @return An array of bools where a true value for any flag indicates that - * a flag was raised and a false value indicates that no flag was raised. - */ - function getFlags(address[] calldata subjects) external view override checkAccess returns (bool[] memory) { - bool[] memory responses = new bool[](subjects.length); - for (uint256 i = 0; i < subjects.length; i++) { - responses[i] = s_flags[subjects[i]]; - } - return responses; - } - - /** - * @notice enable the warning flag for an address. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subject The contract address whose flag is being raised - */ - function raiseFlag(address subject) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - _tryToRaiseFlag(subject); - } - - /** - * @notice enable the warning flags for multiple addresses. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subjects List of the contract addresses whose flag is being raised - */ - function raiseFlags(address[] calldata subjects) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - for (uint256 i = 0; i < subjects.length; i++) { - _tryToRaiseFlag(subjects[i]); - } - } - - /** - * @notice allows owner to disable the warning flags for multiple addresses. - * @param subjects List of the contract addresses whose flag is being lowered - */ - function lowerFlags(address[] calldata subjects) external override onlyOwner { - for (uint256 i = 0; i < subjects.length; i++) { - address subject = subjects[i]; - - if (s_flags[subject]) { - s_flags[subject] = false; - emit FlagLowered(subject); - } - } - } - - /** - * @notice allows owner to change the access controller for raising flags. - * @param racAddress new address for the raising access controller. - */ - function setRaisingAccessController(address racAddress) public override onlyOwner { - address previous = address(raisingAccessController); - - if (previous != racAddress) { - raisingAccessController = AccessControllerInterface(racAddress); - - emit RaisingAccessControllerUpdated(previous, racAddress); - } - } - - // PRIVATE - - function _allowedToRaiseFlags() private view returns (bool) { - return msg.sender == owner() || raisingAccessController.hasAccess(msg.sender, msg.data); - } - - function _tryToRaiseFlag(address subject) private { - if (!s_flags[subject]) { - s_flags[subject] = true; - emit FlagRaised(subject); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol deleted file mode 100644 index 544f890..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/PermissionedForwardProxy.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; - -/** - * @title PermissionedForwardProxy - * @notice This proxy is used to forward calls from sender to target. It maintains - * a permission list to check which sender is allowed to call which target - */ -contract PermissionedForwardProxy is ConfirmedOwner { - using Address for address; - - error PermissionNotSet(); - - event PermissionSet(address indexed sender, address target); - event PermissionRemoved(address indexed sender); - - mapping(address => address) private s_forwardPermissionList; - - constructor() ConfirmedOwner(msg.sender) {} - - /** - * @notice Verifies if msg.sender has permission to forward to target address and then forwards the handler - * @param target address of the contract to forward the handler to - * @param handler bytes to be passed to target in call data - */ - function forward(address target, bytes calldata handler) external { - if (s_forwardPermissionList[msg.sender] != target) { - revert PermissionNotSet(); - } - target.functionCall(handler); - } - - /** - * @notice Adds permission for sender to forward calls to target via this proxy. - * Note that it allows to overwrite an existing permission - * @param sender The address who will use this proxy to forward calls - * @param target The address where sender will be allowed to forward calls - */ - function setPermission(address sender, address target) external onlyOwner { - s_forwardPermissionList[sender] = target; - - emit PermissionSet(sender, target); - } - - /** - * @notice Removes permission for sender to forward calls via this proxy - * @param sender The address who will use this proxy to forward calls - */ - function removePermission(address sender) external onlyOwner { - delete s_forwardPermissionList[sender]; - - emit PermissionRemoved(sender); - } - - /** - * @notice Returns the target address that the sender can use this proxy for - * @param sender The address to fetch the permissioned target for - */ - function getPermission(address sender) external view returns (address) { - return s_forwardPermissionList[sender]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol deleted file mode 100644 index 58e0e28..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ValidatorProxy.sol +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "./shared/access/ConfirmedOwner.sol"; -import {AggregatorValidatorInterface} from "./shared/interfaces/AggregatorValidatorInterface.sol"; -import {TypeAndVersionInterface} from "./interfaces/TypeAndVersionInterface.sol"; - -// solhint-disable gas-custom-errors -contract ValidatorProxy is AggregatorValidatorInterface, TypeAndVersionInterface, ConfirmedOwner { - /// @notice Uses a single storage slot to store the current address - struct AggregatorConfiguration { - address target; - bool hasNewProposal; - } - - struct ValidatorConfiguration { - AggregatorValidatorInterface target; - bool hasNewProposal; - } - - // Configuration for the current aggregator - AggregatorConfiguration private s_currentAggregator; - // Proposed aggregator address - address private s_proposedAggregator; - - // Configuration for the current validator - ValidatorConfiguration private s_currentValidator; - // Proposed validator address - AggregatorValidatorInterface private s_proposedValidator; - - event AggregatorProposed(address indexed aggregator); - event AggregatorUpgraded(address indexed previous, address indexed current); - event ValidatorProposed(AggregatorValidatorInterface indexed validator); - event ValidatorUpgraded(AggregatorValidatorInterface indexed previous, AggregatorValidatorInterface indexed current); - /// @notice The proposed aggregator called validate, but the call was not passed on to any validators - event ProposedAggregatorValidateCall( - address indexed proposed, - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ); - - /** - * @notice Construct the ValidatorProxy with an aggregator and a validator - * @param aggregator address - * @param validator address - */ - constructor(address aggregator, AggregatorValidatorInterface validator) ConfirmedOwner(msg.sender) { - s_currentAggregator = AggregatorConfiguration({target: aggregator, hasNewProposal: false}); - s_currentValidator = ValidatorConfiguration({target: validator, hasNewProposal: false}); - } - - /** - * @notice Validate a transmission - * @dev Must be called by either the `s_currentAggregator.target`, or the `s_proposedAggregator`. - * If called by the `s_currentAggregator.target` this function passes the call on to the `s_currentValidator.target` - * and the `s_proposedValidator`, if it is set. - * If called by the `s_proposedAggregator` this function emits a `ProposedAggregatorValidateCall` to signal that - * the call was received. - * @dev To guard against external `validate` calls reverting, we use raw calls here. - * We favour `call` over try-catch to ensure that failures are avoided even if the validator address is incorrectly - * set as a non-contract address. - * @dev If the `aggregator` and `validator` are the same contract or collude, this could exhibit reentrancy behavior. - * However, since that contract would have to be explicitly written for reentrancy and that the `owner` would have - * to configure this contract to use that malicious contract, we refrain from using mutex or check here. - * @dev This does not perform any checks on any roundId, so it is possible that a validator receive different reports - * for the same roundId at different points in time. Validator implementations should be aware of this. - * @param previousRoundId uint256 - * @param previousAnswer int256 - * @param currentRoundId uint256 - * @param currentAnswer int256 - * @return bool - */ - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external override returns (bool) { - address currentAggregator = s_currentAggregator.target; - if (msg.sender != currentAggregator) { - address proposedAggregator = s_proposedAggregator; - require(msg.sender == proposedAggregator, "Not a configured aggregator"); - // If the aggregator is still in proposed state, emit an event and don't push to any validator. - // This is to confirm that `validate` is being called prior to upgrade. - emit ProposedAggregatorValidateCall( - proposedAggregator, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ); - return true; - } - - // Send the validate call to the current validator - ValidatorConfiguration memory currentValidator = s_currentValidator; - address currentValidatorAddress = address(currentValidator.target); - require(currentValidatorAddress != address(0), "No validator set"); - // solhint-disable-next-line avoid-low-level-calls - currentValidatorAddress.call( - abi.encodeWithSelector( - AggregatorValidatorInterface.validate.selector, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ) - ); - // If there is a new proposed validator, send the validate call to that validator also - if (currentValidator.hasNewProposal) { - // solhint-disable-next-line avoid-low-level-calls - address(s_proposedValidator).call( - abi.encodeWithSelector( - AggregatorValidatorInterface.validate.selector, - previousRoundId, - previousAnswer, - currentRoundId, - currentAnswer - ) - ); - } - return true; - } - - /** AGGREGATOR CONFIGURATION FUNCTIONS **/ - - /** - * @notice Propose an aggregator - * @dev A zero address can be used to unset the proposed aggregator. Only owner can call. - * @param proposed address - */ - function proposeNewAggregator(address proposed) external onlyOwner { - require(s_proposedAggregator != proposed && s_currentAggregator.target != proposed, "Invalid proposal"); - s_proposedAggregator = proposed; - // If proposed is zero address, hasNewProposal = false - s_currentAggregator.hasNewProposal = (proposed != address(0)); - emit AggregatorProposed(proposed); - } - - /** - * @notice Upgrade the aggregator by setting the current aggregator as the proposed aggregator. - * @dev Must have a proposed aggregator. Only owner can call. - */ - function upgradeAggregator() external onlyOwner { - // Get configuration in memory - AggregatorConfiguration memory current = s_currentAggregator; - address previous = current.target; - address proposed = s_proposedAggregator; - - // Perform the upgrade - require(current.hasNewProposal, "No proposal"); - s_currentAggregator = AggregatorConfiguration({target: proposed, hasNewProposal: false}); - delete s_proposedAggregator; - - emit AggregatorUpgraded(previous, proposed); - } - - /** - * @notice Get aggregator details - * @return current address - * @return hasProposal bool - * @return proposed address - */ - function getAggregators() external view returns (address current, bool hasProposal, address proposed) { - current = s_currentAggregator.target; - hasProposal = s_currentAggregator.hasNewProposal; - proposed = s_proposedAggregator; - return (current, hasProposal, proposed); - } - - /** VALIDATOR CONFIGURATION FUNCTIONS **/ - - /** - * @notice Propose an validator - * @dev A zero address can be used to unset the proposed validator. Only owner can call. - * @param proposed address - */ - function proposeNewValidator(AggregatorValidatorInterface proposed) external onlyOwner { - require(s_proposedValidator != proposed && s_currentValidator.target != proposed, "Invalid proposal"); - s_proposedValidator = proposed; - // If proposed is zero address, hasNewProposal = false - s_currentValidator.hasNewProposal = (address(proposed) != address(0)); - emit ValidatorProposed(proposed); - } - - /** - * @notice Upgrade the validator by setting the current validator as the proposed validator. - * @dev Must have a proposed validator. Only owner can call. - */ - function upgradeValidator() external onlyOwner { - // Get configuration in memory - ValidatorConfiguration memory current = s_currentValidator; - AggregatorValidatorInterface previous = current.target; - AggregatorValidatorInterface proposed = s_proposedValidator; - - // Perform the upgrade - require(current.hasNewProposal, "No proposal"); - s_currentValidator = ValidatorConfiguration({target: proposed, hasNewProposal: false}); - delete s_proposedValidator; - - emit ValidatorUpgraded(previous, proposed); - } - - /** - * @notice Get validator details - * @return current address - * @return hasProposal bool - * @return proposed address - */ - function getValidators() - external - view - returns (AggregatorValidatorInterface current, bool hasProposal, AggregatorValidatorInterface proposed) - { - current = s_currentValidator.target; - hasProposal = s_currentValidator.hasNewProposal; - proposed = s_proposedValidator; - return (current, hasProposal, proposed); - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ValidatorProxy 1.0.0"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol deleted file mode 100644 index 72ee8aa..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationBase.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract AutomationBase { - error OnlySimulatedBackend(); - - /** - * @notice method that allows it to be simulated via eth_call by checking that - * the sender is the zero address. - */ - function _preventExecution() internal view { - // solhint-disable-next-line avoid-tx-origin - if (tx.origin != address(0) && tx.origin != address(0x1111111111111111111111111111111111111111)) { - revert OnlySimulatedBackend(); - } - } - - /** - * @notice modifier that allows it to be simulated via eth_call by checking - * that the sender is the zero address. - */ - modifier cannotExecute() { - _preventExecution(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol deleted file mode 100644 index 6533243..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AutomationBase} from "./AutomationBase.sol"; -import {AutomationCompatibleInterface} from "./interfaces/AutomationCompatibleInterface.sol"; - -abstract contract AutomationCompatible is AutomationBase, AutomationCompatibleInterface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol deleted file mode 100644 index 58d68fc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {Log} from "./interfaces/ILogAutomation.sol"; -import {IAutomationV21PlusCommon} from "./interfaces/IAutomationV21PlusCommon.sol"; - -contract AutomationCompatibleUtils { - function _report(IAutomationV21PlusCommon.Report memory) external {} - - function _logTriggerConfig(IAutomationV21PlusCommon.LogTriggerConfig memory) external {} - - function _logTrigger(IAutomationV21PlusCommon.LogTrigger memory) external {} - - function _conditionalTrigger(IAutomationV21PlusCommon.ConditionalTrigger memory) external {} - - function _log(Log memory) external {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol deleted file mode 100644 index 58707e9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarder.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; - -uint256 constant PERFORM_GAS_CUSHION = 5_000; - -/** - * @title AutomationForwarder is a relayer that sits between the registry and the customer's target contract - * @dev The purpose of the forwarder is to give customers a consistent address to authorize against, - * which stays consistent between migrations. The Forwarder also exposes the registry address, so that users who - * want to programatically interact with the registry (ie top up funds) can do so. - */ -contract AutomationForwarder { - /// @notice the user's target contract address - address private immutable i_target; - - /// @notice the shared logic address - address private immutable i_logic; - - IAutomationRegistryConsumer private s_registry; - - constructor(address target, address registry, address logic) { - s_registry = IAutomationRegistryConsumer(registry); - i_target = target; - i_logic = logic; - } - - /** - * @notice forward is called by the registry and forwards the call to the target - * @param gasAmount is the amount of gas to use in the call - * @param data is the 4 bytes function selector + arbitrary function data - * @return success indicating whether the target call succeeded or failed - */ - function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed) { - if (msg.sender != address(s_registry)) revert(); - address target = i_target; - gasUsed = gasleft(); - assembly { - let g := gas() - // Compute g -= PERFORM_GAS_CUSHION and check for underflow - if lt(g, PERFORM_GAS_CUSHION) { - revert(0, 0) - } - g := sub(g, PERFORM_GAS_CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call with exact gas - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - gasUsed = gasUsed - gasleft(); - return (success, gasUsed); - } - - function getTarget() external view returns (address) { - return i_target; - } - - fallback() external { - // copy to memory for assembly access - address logic = i_logic; - // copied directly from OZ's Proxy contract - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), logic, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol deleted file mode 100644 index d8236f3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/AutomationForwarderLogic.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.16; - -import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; - -contract AutomationForwarderLogic is ITypeAndVersion { - IAutomationRegistryConsumer private s_registry; - - string public constant typeAndVersion = "AutomationForwarder 1.0.0"; - - /** - * @notice updateRegistry is called by the registry during migrations - * @param newRegistry is the registry that this forwarder is being migrated to - */ - function updateRegistry(address newRegistry) external { - if (msg.sender != address(s_registry)) revert(); - s_registry = IAutomationRegistryConsumer(newRegistry); - } - - function getRegistry() external view returns (IAutomationRegistryConsumer) { - return s_registry; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol deleted file mode 100644 index 469ea91..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/Chainable.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -/** - * @title Chainable - the contract size limit nullifier - * @notice Chainable is designed to link together a "chain" of contracts through fallback functions - * and delegatecalls. All code is executed in the context of the head of the chain, the "master" contract. - */ -contract Chainable { - /** - * @dev addresses of the next contract in the chain **have to be immutable/constant** or the system won't work - */ - address private immutable i_FALLBACK_ADDRESS; - - /** - * @param fallbackAddress the address of the next contract in the chain - */ - constructor(address fallbackAddress) { - i_FALLBACK_ADDRESS = fallbackAddress; - } - - /** - * @notice returns the address of the next contract in the chain - */ - function fallbackTo() external view returns (address) { - return i_FALLBACK_ADDRESS; - } - - /** - * @notice the fallback function routes the call to the next contract in the chain - * @dev most of the implementation is copied directly from OZ's Proxy contract - */ - // solhint-disable-next-line no-complex-fallback - fallback() external payable { - // copy to memory for assembly access - address next = i_FALLBACK_ADDRESS; - // copied directly from OZ's Proxy contract - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // Call the next contract. - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), next, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol deleted file mode 100644 index 30a823c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ExecutionPrevention.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -abstract contract ExecutionPrevention { - error OnlySimulatedBackend(); - - /** - * @notice method that allows it to be simulated via eth_call by checking that - * the sender is the zero address. - */ - function _preventExecution() internal view { - // solhint-disable-next-line avoid-tx-origin - if (tx.origin != address(0)) { - revert OnlySimulatedBackend(); - } - } - - /** - * @notice modifier that allows it to be simulated via eth_call by checking - * that the sender is the zero address. - */ - modifier cannotExecute() { - _preventExecution(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol deleted file mode 100644 index 8ef7fa4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/HeartbeatRequester.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity 0.8.6; - -import {TypeAndVersionInterface} from "./../interfaces/TypeAndVersionInterface.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; - -// defines some interfaces for type safety and reduces encoding/decoding -// does not use the full interfaces intentionally because the requester only uses a fraction of them -interface IAggregatorProxy { - function aggregator() external view returns (address); -} - -interface IOffchainAggregator { - function requestNewRound() external returns (uint80); -} - -/** - * @notice The heartbeat requester will maintain a mapping from allowed callers to corresponding proxies. When requested - * by eligible caller, it will call a proxy for an aggregator address and request a new round. The aggregator - * is gated by permissions and this requester address needs to be whitelisted. - */ -contract HeartbeatRequester is TypeAndVersionInterface, ConfirmedOwner { - event HeartbeatPermitted(address indexed permittedCaller, address newProxy, address oldProxy); - event HeartbeatRemoved(address indexed permittedCaller, address removedProxy); - - error HeartbeatNotPermitted(); - - mapping(address => IAggregatorProxy) internal s_heartbeatList; - - /** - * @notice versions: - * - HeartbeatRequester 1.0.0: The requester fetches the latest aggregator address from proxy, and request a new round - * using the aggregator address. - */ - string public constant override typeAndVersion = "HeartbeatRequester 1.0.0"; - - constructor() ConfirmedOwner(msg.sender) {} - - /** - * @notice adds a permitted caller and proxy combination. - * @param permittedCaller the permitted caller - * @param proxy the proxy corresponding to this caller - */ - function permitHeartbeat(address permittedCaller, IAggregatorProxy proxy) external onlyOwner { - address oldProxy = address(s_heartbeatList[permittedCaller]); - s_heartbeatList[permittedCaller] = proxy; - emit HeartbeatPermitted(permittedCaller, address(proxy), oldProxy); - } - - /** - * @notice removes a permitted caller and proxy combination. - * @param permittedCaller the permitted caller - */ - function removeHeartbeat(address permittedCaller) external onlyOwner { - address removedProxy = address(s_heartbeatList[permittedCaller]); - delete s_heartbeatList[permittedCaller]; - emit HeartbeatRemoved(permittedCaller, removedProxy); - } - - /** - * @notice fetches aggregator address from proxy and requests a new round. - * @param proxy the proxy address - */ - function getAggregatorAndRequestHeartbeat(address proxy) external { - IAggregatorProxy proxyInterface = s_heartbeatList[msg.sender]; - if (address(proxyInterface) != proxy) revert HeartbeatNotPermitted(); - - IOffchainAggregator aggregator = IOffchainAggregator(proxyInterface.aggregator()); - aggregator.requestNewRound(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol deleted file mode 100644 index 0e050d4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperBase.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -/** - * @notice This is a deprecated interface. Please use AutomationBase directly. - */ -pragma solidity ^0.8.0; -// solhint-disable-next-line no-unused-import -import {AutomationBase as KeeperBase} from "./AutomationBase.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol deleted file mode 100644 index 6379fe5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/KeeperCompatible.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -/** - * @notice This is a deprecated interface. Please use AutomationCompatible directly. - */ -pragma solidity ^0.8.0; -// solhint-disable-next-line no-unused-import -import {AutomationCompatible as KeeperCompatible} from "./AutomationCompatible.sol"; -// solhint-disable-next-line no-unused-import -import {AutomationBase as KeeperBase} from "./AutomationBase.sol"; -// solhint-disable-next-line no-unused-import -import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./interfaces/AutomationCompatibleInterface.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md deleted file mode 100644 index 717e741..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Automation Contract Structure - -The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. Therefore, we include this explanation of how the pieces fit together and various tradeoffs incurred. - -### Glossary - -**Root Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the on-chain entry-point into the system. The root contract uses `delegatecall` to execute code at various logic contracts. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) - -**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the root contract in order to increase our total capacity for on-chain code. - -### Overview - -We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fallback to the next, always executing the function in the scope of the root contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. - -### Diagram - -```mermaid -graph LR - Root -- delegatecall --> la[Logic A] - la -- delegatecall --> lb[Logic B] - lb -. delegatecall .-> lx[Logic Z] -``` - -### Special Considerations - -- functions on the root contract have the least gas overhead. Therefore, our most price-sensitive functions live there. We have 3 functions that we consider hot paths. Ideally, these would all live on the root contract to minimize gas overhead. - - `transmit()` - this is the most important code path - - `registerUpkeep()` - - `addFunds()` -- functions on the root contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there -- etherscan supports executing logic contract functions that are once removed from the root - therefore we give secondary preference to the first logic contract for user and debugging functions -- functions on logic B through logic Z (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically -- We use Logic A, B, C... to avoid confusion with the version ex `AutomationRegistryLogicA2_1.sol` --> Logic Contract A verion 2.1 -- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break - -### Master Interface - -The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. - -[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 -[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function -[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries -[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol deleted file mode 100644 index e765327..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepFormat.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -/** - * @dev this struct is only maintained for backwards compatibility with MigratableKeeperRegistryInterface - * it should be deprecated in the future in favor of MigratableKeeperRegistryInterfaceV2 - */ -enum UpkeepFormat { - V1, - V2, - V3 -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol deleted file mode 100644 index 03f40d8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/UpkeepTranscoder.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import {UpkeepTranscoderInterface} from "./interfaces/UpkeepTranscoderInterface.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; -import {UpkeepFormat} from "./UpkeepFormat.sol"; - -/** - * @notice Transcoder for converting upkeep data from one keeper - * registry version to another - */ -contract UpkeepTranscoder is UpkeepTranscoderInterface, TypeAndVersionInterface { - error InvalidTranscoding(); - - /** - * @notice versions: - * - UpkeepTranscoder 1.0.0: placeholder to allow new formats in the future - */ - string public constant override typeAndVersion = "UpkeepTranscoder 1.0.0"; - - /** - * @notice transcodeUpkeeps transforms upkeep data from the format expected by - * one registry to the format expected by another. It future-proofs migrations - * by allowing keepers team to customize migration paths and set sensible defaults - * when new fields are added - * @param fromVersion struct version the upkeep is migrating from - * @param toVersion struct version the upkeep is migrating to - * @param encodedUpkeeps encoded upkeep data - * @dev this contract & function are simple now, but should evolve as new registries - * and migration paths are added - */ - function transcodeUpkeeps( - UpkeepFormat fromVersion, - UpkeepFormat toVersion, - bytes calldata encodedUpkeeps - ) external view override returns (bytes memory) { - if (fromVersion != toVersion) { - revert InvalidTranscoding(); - } - - return encodedUpkeeps; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol deleted file mode 100644 index f4616ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/ZKSyncAutomationForwarder.sol +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {IAutomationRegistryConsumer} from "./interfaces/IAutomationRegistryConsumer.sol"; -import {GAS_BOUND_CALLER, IGasBoundCaller} from "./interfaces/zksync/IGasBoundCaller.sol"; - -uint256 constant PERFORM_GAS_CUSHION = 50_000; - -/** - * @title ZKSyncAutomationForwarder is a relayer that sits between the registry and the customer's target contract - * @dev The purpose of the forwarder is to give customers a consistent address to authorize against, - * which stays consistent between migrations. The Forwarder also exposes the registry address, so that users who - * want to programmatically interact with the registry (ie top up funds) can do so. - */ -contract ZKSyncAutomationForwarder { - error InvalidCaller(address); - - /// @notice the user's target contract address - address private immutable i_target; - - /// @notice the shared logic address - address private immutable i_logic; - - IAutomationRegistryConsumer private s_registry; - - constructor(address target, address registry, address logic) { - s_registry = IAutomationRegistryConsumer(registry); - i_target = target; - i_logic = logic; - } - - /** - * @notice forward is called by the registry and forwards the call to the target - * @param gasAmount is the amount of gas to use in the call - * @param data is the 4 bytes function selector + arbitrary function data - * @return success indicating whether the target call succeeded or failed - * @return gasUsed the total gas used from this forwarding call - */ - function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed) { - if (msg.sender != address(s_registry)) revert InvalidCaller(msg.sender); - - uint256 g1 = gasleft(); - address target = i_target; - - assembly { - let g := gas() - // Compute g -= PERFORM_GAS_CUSHION and check for underflow - if lt(g, PERFORM_GAS_CUSHION) { - revert(0, 0) - } - g := sub(g, PERFORM_GAS_CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - } - - bytes memory returnData; - // solhint-disable-next-line avoid-low-level-calls - (success, returnData) = GAS_BOUND_CALLER.delegatecall{gas: gasAmount}( - abi.encodeWithSelector(IGasBoundCaller.gasBoundCall.selector, target, gasAmount, data) - ); - uint256 pubdataGasSpent; - if (success) { - (, pubdataGasSpent) = abi.decode(returnData, (bytes, uint256)); - } - gasUsed = g1 - gasleft() + pubdataGasSpent; - return (success, gasUsed); - } - - function getTarget() external view returns (address) { - return i_target; - } - - // solhint-disable-next-line no-complex-fallback - fallback() external payable { - // copy to memory for assembly access - address logic = i_logic; - // copied directly from OZ's Proxy contract - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), logic, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol deleted file mode 100644 index 2ad6fdd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ArbitrumModule.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {ChainModuleBase} from "./ChainModuleBase.sol"; - -contract ArbitrumModule is ChainModuleBase { - /// @dev ARB_SYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARB_SYS_ADDR = 0x0000000000000000000000000000000000000064; - ArbSys private constant ARB_SYS = ArbSys(ARB_SYS_ADDR); - - /// @dev ARB_GAS_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 ARB_GAS_ADDR = 0x000000000000000000000000000000000000006C; - ArbGasInfo private constant ARB_GAS = ArbGasInfo(ARB_GAS_ADDR); - - uint256 private constant FIXED_GAS_OVERHEAD = 5000; - uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; - - function blockHash(uint256 n) external view override returns (bytes32) { - uint256 blockNum = ARB_SYS.arbBlockNumber(); - if (n >= blockNum || blockNum - n > 256) { - return ""; - } - return ARB_SYS.arbBlockHash(n); - } - - function blockNumber() external view override returns (uint256) { - return ARB_SYS.arbBlockNumber(); - } - - function getCurrentL1Fee(uint256) external view override returns (uint256) { - return ARB_GAS.getCurrentTxL1GasFees(); - } - - function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { - (, uint256 perL1CalldataByte, , , , ) = ARB_GAS.getPricesInWei(); - return perL1CalldataByte * dataSize; - } - - function getGasOverhead() - external - view - override - returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) - { - return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol deleted file mode 100644 index c595dbd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ChainModuleBase.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {IChainModule} from "../interfaces/IChainModule.sol"; - -contract ChainModuleBase is IChainModule { - uint256 private constant FIXED_GAS_OVERHEAD = 300; - uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; - - function blockNumber() external view virtual returns (uint256) { - return block.number; - } - - function blockHash(uint256 n) external view virtual returns (bytes32) { - if (n >= block.number || block.number - n > 256) { - return ""; - } - return blockhash(n); - } - - function getCurrentL1Fee(uint256) external view virtual returns (uint256 l1Fee) { - return 0; - } - - function getMaxL1Fee(uint256) external view virtual returns (uint256 maxL1Fee) { - return 0; - } - - function getGasOverhead() - external - view - virtual - returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) - { - return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol deleted file mode 100644 index 7a46429..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModule.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; -import {ChainModuleBase} from "./ChainModuleBase.sol"; - -/** - * @notice This contract is deprecated. Please use OptimismModuleV2 which utilizes the most recent offerings from OP - * and can estimate L1 fee with much lower cost. - */ -contract OptimismModule is ChainModuleBase { - /// @dev OP_L1_DATA_FEE_PADDING includes 80 bytes for L1 data padding for Optimism and BASE - bytes private constant OP_L1_DATA_FEE_PADDING = - hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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 = 0x420000000000000000000000000000000000000F; - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - uint256 private constant FIXED_GAS_OVERHEAD = 60_000; - uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 270; - - // @dev This will be updated to use the new function introduced by OP team - function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { - return _getL1Fee(dataSize); - } - - function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { - return _getL1Fee(dataSize); - } - - /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size - * @dev this function uses the getL1Fee function in OP gas price oracle. it estimates the exact L1 fee but it costs - * a lot of gas to call. - * @param dataSize the size of calldata - * @return l1Fee the L1 fee - */ - function _getL1Fee(uint256 dataSize) internal view 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); - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, OP_L1_DATA_FEE_PADDING)); - } - - function getGasOverhead() - external - view - override - returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) - { - return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol deleted file mode 100644 index 772b66c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/OptimismModuleV2.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; -import {ChainModuleBase} from "./ChainModuleBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -/** - * @notice OptimismModuleV2 provides a cost-efficient way to get L1 fee on OP stack. - * After EIP-4844 is implemented in OP stack, the new OP upgrade includes a new function getL1FeeUpperBound to estimate - * the upper bound of current transaction's L1 fee. - */ -contract OptimismModuleV2 is ChainModuleBase, ConfirmedOwner { - error InvalidL1FeeCoefficient(uint8 coefficient); - event L1FeeCoefficientSet(uint8 coefficient); - - /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - /// @dev L1 fee coefficient is used to account for the impact of data compression on the l1 fee - /// getL1FeeUpperBound returns the upper bound of l1 fee so this configurable coefficient will help - /// charge a predefined percentage of the upper bound. - uint8 private s_l1FeeCoefficient = 100; - uint256 private constant FIXED_GAS_OVERHEAD = 28_000; - uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; - - constructor() ConfirmedOwner(msg.sender) {} - - function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { - return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; - } - - function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { - return _getL1Fee(dataSize); - } - - /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size - * @dev this function uses the newly provided getL1FeeUpperBound function in OP gas price oracle. this helps - * estimate L1 fee with much lower cost - * @param dataSize the size of calldata - * @return l1Fee the L1 fee - */ - function _getL1Fee(uint256 dataSize) internal view returns (uint256) { - return OVM_GASPRICEORACLE.getL1FeeUpperBound(dataSize); - } - - function getGasOverhead() - external - pure - override - returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) - { - return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); - } - - /* @notice this function sets a new coefficient for L1 fee estimation. - * @dev this function can only be invoked by contract owner - * @param coefficient the new coefficient - */ - function setL1FeeCalculation(uint8 coefficient) external onlyOwner { - if (coefficient > 100) { - revert InvalidL1FeeCoefficient(coefficient); - } - - s_l1FeeCoefficient = coefficient; - - emit L1FeeCoefficientSet(coefficient); - } - - /* @notice this function returns the s_l1FeeCoefficient - * @return coefficient the current s_l1FeeCoefficient in effect - */ - function getL1FeeCoefficient() public view returns (uint256 coefficient) { - return s_l1FeeCoefficient; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol deleted file mode 100644 index 30fdc90..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/chains/ScrollModule.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {IScrollL1GasPriceOracle} from "../../vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol"; -import {ChainModuleBase} from "./ChainModuleBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -contract ScrollModule is ChainModuleBase, ConfirmedOwner { - error InvalidL1FeeCoefficient(uint8 coefficient); - event L1FeeCoefficientSet(uint8 coefficient); - - /// @dev SCROLL_L1_FEE_DATA_PADDING includes 140 bytes for L1 data padding for Scroll - /// @dev according to testing, this padding allows automation registry to properly estimates L1 data fee with 3-5% buffer - /// @dev this MAY NOT work for a different product and this may get out of date if transmit function is changed - bytes private constant SCROLL_L1_FEE_DATA_PADDING = - hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - /// @dev SCROLL_ORACLE_ADDR is the address of the ScrollL1GasPriceOracle precompile on Scroll. - /// @dev reference: https://docs.scroll.io/en/developers/transaction-fees-on-scroll/#estimating-the-l1-data-fee - address private constant SCROLL_ORACLE_ADDR = 0x5300000000000000000000000000000000000002; - IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR); - - /// @dev L1 fee coefficient can be applied to reduce possibly inflated gas cost - uint8 private s_l1FeeCoefficient = 100; - uint256 private constant FIXED_GAS_OVERHEAD = 45_000; - uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 170; - - constructor() ConfirmedOwner(msg.sender) {} - - function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { - return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; - } - - function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { - return _getL1Fee(dataSize); - } - - /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size - * @param dataSize the size of calldata - * @return l1Fee the L1 fee - */ - function _getL1Fee(uint256 dataSize) internal view returns (uint256 l1Fee) { - // 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. - 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) - { - return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); - } - - /* @notice this function sets a new coefficient for L1 fee estimation. - * @dev this function can only be invoked by contract owner - * @param coefficient the new coefficient - */ - function setL1FeeCalculation(uint8 coefficient) external onlyOwner { - if (coefficient > 100) { - revert InvalidL1FeeCoefficient(coefficient); - } - - s_l1FeeCoefficient = coefficient; - - emit L1FeeCoefficientSet(coefficient); - } - - /* @notice this function returns the s_l1FeeCoefficient - * @return coefficient the current s_l1FeeCoefficient in effect - */ - function getL1FeeCoefficient() public view returns (uint256 coefficient) { - return s_l1FeeCoefficient; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol deleted file mode 100644 index 247301a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistry.sol +++ /dev/null @@ -1,320 +0,0 @@ -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; - -/*--------------------------------------------------------------------------------------------------------------------+ -| Mercury + Automation | -| ________________ | -| This implementation allows for an on-chain registry of price feed data to be maintained and updated by Automation | -| nodes. The upkeep provides the following advantages: | -| - Node operator savings. The single committee of automation nodes is able to update all price feed data using | -| off-chain feed data. | -| - Fetch batches of price data. All price feed data is held on the same contract, so a contract that needs | -| multiple sets of feed data can fetch them while paying for only one external call. | -| - Scalability. Feeds can be added or removed from the contract with a single contract call, and the number of | -| feeds that the registry can store is unbounded. | -| | -| Key Contracts: | -| - `MercuryRegistry.sol` - stores price feed data and implements core logic. | -| - `MercuryRegistryBatchUpkeep.sol` - enables batching for the registry. | -| - `MercuryRegistry.t.sol` - contains foundry tests to demonstrate various flows. | -| | -| NOTE: This contract uses Mercury v0.2. Automation will likely upgrade to v0.3 eventually, which may change some | -| components such as the Report struct, verification, and the StreamsLookup revert. | -| | -| TODO: | -| - Optimize gas consumption. | --+---------------------------------------------------------------------------------------------------------------------*/ -contract MercuryRegistry is ConfirmedOwner, AutomationCompatibleInterface, StreamsLookupCompatibleInterface { - error DuplicateFeed(string feedId); - error FeedNotActive(string feedId); - error StaleReport(string feedId, uint32 currentTimestamp, uint32 incomingTimestamp); - error InvalidFeeds(); - - // Feed object used for storing feed data. - // not included but contained in reports: - // - blocknumberUpperBound - // - upperBlockhash - // - blocknumberLowerBound - // - currentBlockTimestamp - struct Feed { - uint32 observationsTimestamp; // the timestamp of the most recent data assigned to this feed - int192 price; // the current price of the feed - int192 bid; // the current bid price of the feed - int192 ask; // the current ask price of the feed - string feedName; // the name of the feed - string feedId; // the id of the feed (hex encoded) - bool active; // true if the feed is being actively updated, otherwise false - int192 deviationPercentagePPM; // acceptable deviation threshold - 1.5% = 15_000, 100% = 1_000_000, etc.. - uint32 stalenessSeconds; // acceptable staleness threshold - 60 = 1 minute, 300 = 5 minutes, etc.. - } - - // Report object obtained from off-chain Mercury server. - struct Report { - bytes32 feedId; // the feed Id of the report - uint32 observationsTimestamp; // the timestamp of when the data was observed - int192 price; // the median value of the OCR round - int192 bid; // the median bid of the OCR round - int192 ask; // the median ask if the OCR round - uint64 blocknumberUpperBound; // the highest block observed at the time the report was generated - bytes32 upperBlockhash; // the blockhash of the highest block observed - uint64 blocknumberLowerBound; // the lowest block observed at the time the report was generated - uint64 currentBlockTimestamp; // the timestamp of the highest block observed - } - - event FeedUpdated(uint32 observationsTimestamp, int192 price, int192 bid, int192 ask, string feedId); - - uint32 private constant MIN_GAS_FOR_PERFORM = 200_000; - - string private constant FEED_PARAM_KEY = "feedIdHex"; // for Mercury v0.2 - format by which feeds are identified - string private constant TIME_PARAM_KEY = "blockNumber"; // for Mercury v0.2 - format by which feeds are filtered to be sufficiently recent - IVerifierProxy public s_verifier; // for Mercury v0.2 - verifies off-chain reports - - int192 private constant SCALE = 1_000_000; // a scalar used for measuring deviation with precision - - string[] public s_feeds; // list of feed Ids - mapping(string => Feed) public s_feedMapping; // mapping of feed Ids to stored feed data - - constructor( - string[] memory feedIds, - string[] memory feedNames, - int192[] memory deviationPercentagePPMs, - uint32[] memory stalenessSeconds, - address verifier - ) ConfirmedOwner(msg.sender) { - s_verifier = IVerifierProxy(verifier); - - // Store desired feeds. - setFeeds(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds); - } - - // Returns a user-defined batch of feed data, based on the on-chain state. - function getLatestFeedData(string[] memory feedIds) external view returns (Feed[] memory) { - Feed[] memory feeds = new Feed[](feedIds.length); - for (uint256 i = 0; i < feedIds.length; i++) { - feeds[i] = s_feedMapping[feedIds[i]]; - } - - return feeds; - } - - // Invoke a feed lookup through the checkUpkeep function. Expected to run on a cron schedule. - function checkUpkeep(bytes calldata /* data */) external view override returns (bool, bytes memory) { - string[] memory feeds = s_feeds; - return revertForFeedLookup(feeds); - } - - // Extracted from `checkUpkeep` for batching purposes. - function revertForFeedLookup(string[] memory feeds) public view returns (bool, bytes memory) { - uint256 blockNumber = ChainSpecificUtil._getBlockNumber(); - revert StreamsLookup(FEED_PARAM_KEY, feeds, TIME_PARAM_KEY, blockNumber, ""); - } - - // Filter for feeds that have deviated sufficiently from their respective on-chain values, or where - // the on-chain values are sufficiently stale. - function checkCallback( - bytes[] memory values, - bytes memory lookupData - ) external view override returns (bool, bytes memory) { - bytes[] memory filteredValues = new bytes[](values.length); - uint256 count = 0; - for (uint256 i = 0; i < values.length; i++) { - Report memory report = _getReport(values[i]); - string memory feedId = _bytes32ToHexString(abi.encodePacked(report.feedId)); - Feed memory feed = s_feedMapping[feedId]; - if ( - (report.observationsTimestamp - feed.observationsTimestamp > feed.stalenessSeconds) || - deviationExceedsThreshold(feed.price, report.price, feed.deviationPercentagePPM) - ) { - filteredValues[count] = values[i]; - count++; - } - } - - // Adjusts the length of the filteredValues array to `count` such that it - // does not have extra empty slots, in case some items were filtered. - assembly { - mstore(filteredValues, count) - } - - bytes memory performData = abi.encode(filteredValues, lookupData); - return (filteredValues.length > 0, performData); - } - - function checkErrorHandler( - uint256 /* errCode */, - bytes memory /* extraData */ - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (false, new bytes(0)); - } - - // Use deviated off-chain values to update on-chain state. - function performUpkeep(bytes calldata performData) external override { - (bytes[] memory values /* bytes memory lookupData */, ) = abi.decode(performData, (bytes[], bytes)); - for (uint256 i = 0; i < values.length; i++) { - // Verify and decode the Mercury report. - Report memory report = abi.decode(s_verifier.verify(values[i]), (Report)); - string memory feedId = _bytes32ToHexString(abi.encodePacked(report.feedId)); - - // Feeds that have been removed between checkUpkeep and performUpkeep should not be updated. - if (!s_feedMapping[feedId].active) { - revert FeedNotActive(feedId); - } - - // Ensure stale reports do not cause a regression in the registry. - if (s_feedMapping[feedId].observationsTimestamp > report.observationsTimestamp) { - revert StaleReport(feedId, s_feedMapping[feedId].observationsTimestamp, report.observationsTimestamp); - } - - // Assign new values to state. - s_feedMapping[feedId].bid = report.bid; - s_feedMapping[feedId].ask = report.ask; - s_feedMapping[feedId].price = report.price; - s_feedMapping[feedId].observationsTimestamp = report.observationsTimestamp; - - // Emit log. - emit FeedUpdated(report.observationsTimestamp, report.price, report.bid, report.ask, feedId); - - // Ensure enough gas remains for the next iteration. Otherwise, stop here. - if (gasleft() < MIN_GAS_FOR_PERFORM) { - return; - } - } - } - - // Decodes a mercury respone into an on-chain object. Thanks @mikestone!! - function _getReport(bytes memory signedReport) internal pure returns (Report memory) { - /* - * bytes32[3] memory reportContext, - * bytes memory reportData, - * bytes32[] memory rs, - * bytes32[] memory ss, - * bytes32 rawVs - **/ - (, bytes memory reportData, , , ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); - - Report memory report = abi.decode(reportData, (Report)); - return report; - } - - // Check if the off-chain value has deviated sufficiently from the on-chain value to justify an update. - // `scale` is used to ensure precision is not lost. - function deviationExceedsThreshold( - int192 onChain, - int192 offChain, - int192 deviationPercentagePPM - ) public pure returns (bool) { - // Compute absolute difference between the on-chain and off-chain values. - int192 scaledDifference = (onChain - offChain) * SCALE; - if (scaledDifference < 0) { - scaledDifference = -scaledDifference; - } - - // Compare to the allowed deviation from the on-chain value. - int192 deviationMax = ((onChain * SCALE) * deviationPercentagePPM) / SCALE; - return scaledDifference > deviationMax; - } - - // Helper function to reconcile a difference in formatting: - // - Automation passes feedId into their off-chain lookup function as a string. - // - Mercury stores feedId in their reports as a bytes32. - function _bytes32ToHexString(bytes memory buffer) internal pure returns (string memory) { - bytes memory converted = new bytes(buffer.length * 2); - bytes memory _base = "0123456789abcdef"; - for (uint256 i = 0; i < buffer.length; i++) { - converted[i * 2] = _base[uint8(buffer[i]) / _base.length]; - converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length]; - } - return string(abi.encodePacked("0x", converted)); - } - - function addFeeds( - string[] memory feedIds, - string[] memory feedNames, - int192[] memory deviationPercentagePPMs, - uint32[] memory stalenessSeconds - ) external onlyOwner feedsAreValid(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds) { - for (uint256 i = 0; i < feedIds.length; i++) { - string memory feedId = feedIds[i]; - if (s_feedMapping[feedId].active) { - revert DuplicateFeed(feedId); - } - _updateFeed(feedId, feedNames[i], deviationPercentagePPMs[i], stalenessSeconds[i]); - s_feedMapping[feedId].active = true; - - s_feeds.push(feedId); - } - } - - function setFeeds( - string[] memory feedIds, - string[] memory feedNames, - int192[] memory deviationPercentagePPMs, - uint32[] memory stalenessSeconds - ) public onlyOwner feedsAreValid(feedIds, feedNames, deviationPercentagePPMs, stalenessSeconds) { - // Clear prior feeds. - for (uint256 i = 0; i < s_feeds.length; i++) { - s_feedMapping[s_feeds[i]].active = false; - } - - // Assign new feeds. - for (uint256 i = 0; i < feedIds.length; i++) { - string memory feedId = feedIds[i]; - if (s_feedMapping[feedId].active) { - revert DuplicateFeed(feedId); - } - _updateFeed(feedId, feedNames[i], deviationPercentagePPMs[i], stalenessSeconds[i]); - s_feedMapping[feedId].active = true; - } - s_feeds = feedIds; - } - - function _updateFeed( - string memory feedId, - string memory feedName, - int192 deviationPercentagePPM, - uint32 stalnessSeconds - ) internal { - s_feedMapping[feedId].feedName = feedName; - s_feedMapping[feedId].deviationPercentagePPM = deviationPercentagePPM; - s_feedMapping[feedId].stalenessSeconds = stalnessSeconds; - s_feedMapping[feedId].feedId = feedId; - } - - function setVerifier(address verifier) external onlyOwner { - s_verifier = IVerifierProxy(verifier); - } - - modifier feedsAreValid( - string[] memory feedIds, - string[] memory feedNames, - int192[] memory deviationPercentagePPMs, - uint32[] memory stalenessSeconds - ) { - if (feedIds.length != feedNames.length) { - revert InvalidFeeds(); - } - if (feedIds.length != deviationPercentagePPMs.length) { - revert InvalidFeeds(); - } - if (feedIds.length != stalenessSeconds.length) { - revert InvalidFeeds(); - } - _; - } -} - -interface IVerifierProxy { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the correct verifier, and bills the user if applicable. - * @param payload The encoded data to be verified, including the signed - * report and any metadata for billing. - * @return verifiedReport The encoded report from the verifier. - */ - function verify(bytes calldata payload) external payable returns (bytes memory verifiedReport); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol deleted file mode 100644 index 2d3daea..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/dev/MercuryRegistryBatchUpkeep.sol +++ /dev/null @@ -1,88 +0,0 @@ -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {MercuryRegistry} from "./MercuryRegistry.sol"; - -contract MercuryRegistryBatchUpkeep is ConfirmedOwner, AutomationCompatibleInterface, StreamsLookupCompatibleInterface { - error BatchSizeTooLarge(uint256 batchsize, uint256 maxBatchSize); - // Use a reasonable maximum batch size. Every Mercury report is ~750 bytes, too many reports - // passed into a single batch could exceed the calldata or transaction size limit for some blockchains. - uint256 public constant MAX_BATCH_SIZE = 50; - - MercuryRegistry public immutable i_registry; // master registry, where feed data is stored - - uint256 public s_batchStart; // starting index of upkeep batch on the MercuryRegistry's s_feeds array, inclusive - uint256 public s_batchEnd; // ending index of upkeep batch on the MercuryRegistry's s_feeds array, exclusive - - constructor(address mercuryRegistry, uint256 batchStart, uint256 batchEnd) ConfirmedOwner(msg.sender) { - i_registry = MercuryRegistry(mercuryRegistry); - - updateBatchingWindow(batchStart, batchEnd); - } - - // Invoke a feed lookup for the feeds this upkeep is responsible for. - function checkUpkeep(bytes calldata /* data */) external view override returns (bool, bytes memory) { - uint256 start = s_batchStart; - uint256 end = s_batchEnd; - string[] memory feeds = new string[](end - start); - uint256 count = 0; - for (uint256 i = start; i < end; i++) { - string memory feedId; - - // If the feed doesn't exist, then the batching window exceeds the underlying registry length. - // So, the batch will be partially empty. - try i_registry.s_feeds(i) returns (string memory f) { - feedId = f; - } catch (bytes memory /* data */) { - break; - } - - // Assign feed. - feeds[i - start] = feedId; - count++; - } - - // Adjusts the length of the batch to `count` such that it does not - // contain any empty feed Ids. - assembly { - mstore(feeds, count) - } - - return i_registry.revertForFeedLookup(feeds); - } - - // Use the master registry to assess deviations. - function checkCallback( - bytes[] memory values, - bytes memory lookupData - ) external view override returns (bool, bytes memory) { - return i_registry.checkCallback(values, lookupData); - } - - function checkErrorHandler( - uint256 /* errCode */, - bytes memory /* extraData */ - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (false, new bytes(0)); - } - - // Use the master registry to update state. - function performUpkeep(bytes calldata performData) external override { - i_registry.performUpkeep(performData); - } - - function updateBatchingWindow(uint256 batchStart, uint256 batchEnd) public onlyOwner { - // Do not allow a batched mercury registry to use an excessive batch size, as to avoid - // calldata size limits. If more feeds need to be updated than allowed by the batch size, - // deploy another `MercuryRegistryBatchUpkeep` contract and register another upkeep job. - if (batchEnd - batchStart > MAX_BATCH_SIZE) { - revert BatchSizeTooLarge(batchEnd - batchStart, MAX_BATCH_SIZE); - } - - s_batchStart = batchStart; - s_batchEnd = batchEnd; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol deleted file mode 100644 index ae92082..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/AutomationCompatibleInterface.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface AutomationCompatibleInterface { - /** - * @notice method that is simulated by the keepers to see if any work actually - * needs to be performed. This method does does not actually need to be - * executable, and since it is only ever simulated it can consume lots of gas. - * @dev To ensure that it is never called, you may want to add the - * cannotExecute modifier from KeeperBase to your implementation of this - * method. - * @param checkData specified in the upkeep registration so it is always the - * same for a registered upkeep. This can easily be broken down into specific - * arguments using `abi.decode`, so multiple upkeeps can be registered on the - * same contract and easily differentiated by the contract. - * @return upkeepNeeded boolean to indicate whether the keeper should call - * performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try - * `abi.encode`. - */ - function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); - - /** - * @notice method that is actually executed by the keepers, via the registry. - * The data returned by the checkUpkeep simulation will be passed into - * this method to actually be executed. - * @dev The input to this method should not be trusted, and the caller of the - * method should not even be restricted to any single registry. Anyone should - * be able call it, and the input should be validated, there is no guarantee - * that the data passed in is the performData returned from checkUpkeep. This - * could happen due to malicious keepers, racing keepers, or simply a state - * change while the performUpkeep transaction is waiting for confirmation. - * Always validate the data passed in. - * @param performData is the data which was passed back from the checkData - * simulation. If it is encoded, it can easily be decoded into other types by - * calling `abi.decode`. This data should not be trusted, and should be - * validated against the contract's current state. - */ - function performUpkeep(bytes calldata performData) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol deleted file mode 100644 index 0a53de6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationForwarder.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IAutomationRegistryConsumer} from "./IAutomationRegistryConsumer.sol"; - -interface IAutomationForwarder is ITypeAndVersion { - function forward(uint256 gasAmount, bytes memory data) external returns (bool success, uint256 gasUsed); - - function updateRegistry(address newRegistry) external; - - function getRegistry() external view returns (IAutomationRegistryConsumer); - - function getTarget() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol deleted file mode 100644 index bea3e95..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationRegistryConsumer.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/** - * @notice IAutomationRegistryConsumer defines the LTS user-facing interface that we intend to maintain for - * across upgrades. As long as users use functions from within this interface, their upkeeps will retain - * backwards compatability across migrations. - * @dev Functions can be added to this interface, but not removed. - */ -interface IAutomationRegistryConsumer { - function getBalance(uint256 id) external view returns (uint96 balance); - - function getMinBalance(uint256 id) external view returns (uint96 minBalance); - - function cancelUpkeep(uint256 id) external; - - function pauseUpkeep(uint256 id) external; - - function unpauseUpkeep(uint256 id) external; - - function addFunds(uint256 id, uint96 amount) external; - - function withdrawFunds(uint256 id, address to) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol deleted file mode 100644 index 6e3d0d7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IAutomationV21PlusCommon.sol +++ /dev/null @@ -1,272 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.4; - -interface IAutomationV21PlusCommon { - // registry events - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - event DedupKeyAdded(bytes32 indexed dedupKey); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event OwnershipTransferred(address indexed from, address indexed to); - event OwnershipTransferRequested(address indexed from, address indexed to); - event Paused(address account); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeesUpdated(address[] transmitters, address[] payees); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event Transmitted(bytes32 configDigest, uint32 epoch); - event Unpaused(address account); - - // upkeep events - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - - /** - * @notice structure of trigger for log triggers - */ - struct LogTriggerConfig { - address contractAddress; - uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply - bytes32 topic0; - bytes32 topic1; - bytes32 topic2; - bytes32 topic3; - } - - /// @dev Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkNative; - uint256[] upkeepIds; - uint256[] gasLimits; - bytes[] triggers; - bytes[] performDatas; - } - - /** - * @notice all information about an upkeep - * @dev only used in return values - * @dev this will likely be deprecated in a future version of the registry - * @member target the contract which needs to be serviced - * @member performGas the gas limit of upkeep execution - * @member checkData the checkData bytes for this upkeep - * @member balance the balance of this upkeep - * @member admin for this upkeep - * @member maxValidBlocknumber until which block this upkeep is valid - * @member lastPerformedBlockNumber the last block number when this upkeep was performed - * @member amountSpent the amount this upkeep has spent - * @member paused if this upkeep has been paused - * @member offchainConfig the off-chain config of this upkeep - */ - struct UpkeepInfoLegacy { - address target; - uint32 performGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformedBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; - } - - /** - * @notice the trigger structure conditional trigger type - */ - struct ConditionalTrigger { - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the trigger structure of log upkeeps - * @dev NOTE that blockNum / blockHash describe the block used for the callback, - * not necessarily the block number that the log was emitted in!!!! - */ - struct LogTrigger { - bytes32 logBlockHash; - bytes32 txHash; - uint32 logIndex; - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice state of the registry - * @dev only used in params and return values - * @dev this will likely be deprecated in a future version of the registry in favor of individual getters - * @member nonce used for ID generation - * @member ownerLinkBalance withdrawable balance of LINK by contract owner - * @member expectedLinkBalance the expected balance of LINK of the registry - * @member totalPremium the total premium collected on registry so far - * @member numUpkeeps total number of upkeeps on the registry - * @member configCount ordinal number of current config, out of all configs applied to this contract so far - * @member latestConfigBlockNumber last block at which this config was set - * @member latestConfigDigest domain-separation tag for current config - * @member latestEpoch for which a report was transmitted - * @member paused freeze on execution scoped to the entire registry - */ - // solhint-disable-next-line gas-struct-packing - struct StateLegacy { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; - } - - /** - * @notice OnchainConfigLegacy of the registry - * @dev only used in params and return values - * @member paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling - * @member maxPerformGas max performGas allowed for an upkeep on this registry - * @member maxCheckDataSize max length of checkData bytes - * @member maxPerformDataSize max length of performData bytes - * @member maxRevertDataSize max length of revertData bytes - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrars addresses of the registrar contracts - * @member upkeepPrivilegeManager address which can set privilege for upkeeps - */ - // solhint-disable-next-line gas-struct-packing - struct OnchainConfigLegacy { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - } - - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function checkUpkeep( - uint256 id - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function simulatePerformUpkeep( - uint256 id, - bytes memory performData - ) external view returns (bool success, uint256 gasUsed); - function executeCallback( - uint256 id, - bytes memory payload - ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function checkCallback( - uint256 id, - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function typeAndVersion() external view returns (string memory); - function addFunds(uint256 id, uint96 amount) external; - function cancelUpkeep(uint256 id) external; - - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); - function hasDedupKey(bytes32 dedupKey) external view returns (bool); - function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); - function getUpkeep(uint256 id) external view returns (UpkeepInfoLegacy memory upkeepInfo); - function getMinBalance(uint256 id) external view returns (uint96); - function getState() - external - view - returns ( - StateLegacy memory state, - OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; - function pauseUpkeep(uint256 id) external; - function unpauseUpkeep(uint256 id) external; - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - function pause() external; - function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; - function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; - function owner() external view returns (address); - function getTriggerType(uint256 upkeepId) external pure returns (uint8); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol deleted file mode 100644 index 15e84f7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/IChainModule.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -interface IChainModule { - /* @notice this function provides the block number of current chain. - * @dev certain chains have its own function to retrieve block number, e.g. Arbitrum - * @return blockNumber the block number of the current chain. - */ - function blockNumber() external view returns (uint256 blockNumber); - - /* @notice this function provides the block hash of a block number. - * @dev this function can usually look back 256 blocks at most, unless otherwise specified - * @param blockNumber the block number - * @return blockHash the block hash of the input block number - */ - function blockHash(uint256 blockNumber) external view returns (bytes32 blockHash); - - /* @notice this function provides the L1 fee of current transaction. - * @dev retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should - * return 0 for L2 chains if they don't have L1 fee component. - * @param dataSize the calldata size of the current transaction - * @return l1Fee the L1 fee in wei incurred by calldata of this data size - */ - function getCurrentL1Fee(uint256 dataSize) external view returns (uint256 l1Fee); - - /* @notice this function provides the max possible L1 fee of current transaction. - * @dev retrieve the max possible L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should - * return 0 for L2 chains if they don't have L1 fee component. - * @param dataSize the calldata size of the current transaction - * @return maxL1Fee the max possible L1 fee in wei incurred by calldata of this data size - */ - function getMaxL1Fee(uint256 dataSize) external view returns (uint256 maxL1Fee); - - /* @notice this function provides the overheads of calling this chain module. - * @return chainModuleFixedOverhead the fixed overhead incurred by calling this chain module - * @return chainModulePerByteOverhead the fixed overhead per byte incurred by calling this chain module with calldata - */ - function getGasOverhead() - external - view - returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol deleted file mode 100644 index 20a41f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/ILogAutomation.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @member index the index of the log in the block. 0 for the first log - * @member timestamp the timestamp of the block containing the log - * @member txHash the hash of the transaction containing the log - * @member blockNumber the number of the block containing the log - * @member blockHash the hash of the block containing the log - * @member source the address of the contract that emitted the log - * @member topics the indexed topics of the log - * @member data the data of the log - */ -struct Log { - uint256 index; - uint256 timestamp; - bytes32 txHash; - uint256 blockNumber; - bytes32 blockHash; - address source; - bytes32[] topics; - bytes data; -} - -interface ILogAutomation { - /** - * @notice method that is simulated by the keepers to see if any work actually - * needs to be performed. This method does does not actually need to be - * executable, and since it is only ever simulated it can consume lots of gas. - * @dev To ensure that it is never called, you may want to add the - * cannotExecute modifier from KeeperBase to your implementation of this - * method. - * @param log the raw log data matching the filter that this contract has - * registered as a trigger - * @param checkData user-specified extra data to provide context to this upkeep - * @return upkeepNeeded boolean to indicate whether the keeper should call - * performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try - * `abi.encode`. - */ - function checkLog( - Log calldata log, - bytes memory checkData - ) external returns (bool upkeepNeeded, bytes memory performData); - - /** - * @notice method that is actually executed by the keepers, via the registry. - * The data returned by the checkUpkeep simulation will be passed into - * this method to actually be executed. - * @dev The input to this method should not be trusted, and the caller of the - * method should not even be restricted to any single registry. Anyone should - * be able call it, and the input should be validated, there is no guarantee - * that the data passed in is the performData returned from checkUpkeep. This - * could happen due to malicious keepers, racing keepers, or simply a state - * change while the performUpkeep transaction is waiting for confirmation. - * Always validate the data passed in. - * @param performData is the data which was passed back from the checkData - * simulation. If it is encoded, it can easily be decoded into other types by - * calling `abi.decode`. This data should not be trusted, and should be - * validated against the contract's current state. - */ - function performUpkeep(bytes calldata performData) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol deleted file mode 100644 index b5ba819..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/KeeperCompatibleInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -/** - * @notice This is a deprecated interface. Please use AutomationCompatibleInterface directly. - */ -pragma solidity ^0.8.0; -// solhint-disable-next-line no-unused-import -import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "./AutomationCompatibleInterface.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol deleted file mode 100644 index d279d93..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterface.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "../UpkeepFormat.sol"; - -interface MigratableKeeperRegistryInterface { - /** - * @notice Migrates upkeeps from one registry to another, including LINK and upkeep params. - * Only callable by the upkeep admin. All upkeeps must have the same admin. Can only migrate active upkeeps. - * @param upkeepIDs ids of upkeeps to migrate - * @param destination the address of the registry to migrate to - */ - function migrateUpkeeps(uint256[] calldata upkeepIDs, address destination) external; - - /** - * @notice Called by other registries when migrating upkeeps. Only callable by other registries. - * @param encodedUpkeeps abi encoding of upkeeps to import - decoded by the transcoder - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external; - - /** - * @notice Specifies the version of upkeep data that this registry requires in order to import - */ - function upkeepTranscoderVersion() external view returns (UpkeepFormat version); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol deleted file mode 100644 index d6dcc03..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/MigratableKeeperRegistryInterfaceV2.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface MigratableKeeperRegistryInterfaceV2 { - /** - * @notice Migrates upkeeps from one registry to another, including LINK and upkeep params. - * Only callable by the upkeep admin. All upkeeps must have the same admin. Can only migrate active upkeeps. - * @param upkeepIDs ids of upkeeps to migrate - * @param destination the address of the registry to migrate to - */ - function migrateUpkeeps(uint256[] calldata upkeepIDs, address destination) external; - - /** - * @notice Called by other registries when migrating upkeeps. Only callable by other registries. - * @param encodedUpkeeps abi encoding of upkeeps to import - decoded by the transcoder - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external; - - /** - * @notice Specifies the version of upkeep data that this registry requires in order to import - */ - function upkeepVersion() external view returns (uint8 version); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol deleted file mode 100644 index ed873a0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/StreamsLookupCompatibleInterface.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface StreamsLookupCompatibleInterface { - error StreamsLookup(string feedParamKey, string[] feeds, string timeParamKey, uint256 time, bytes extraData); - - /** - * @notice any contract which wants to utilize StreamsLookup feature needs to - * implement this interface as well as the automation compatible interface. - * @param values an array of bytes returned from data streams endpoint. - * @param extraData context data from streams lookup process. - * @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try `abi.encode`. - */ - function checkCallback( - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData); - - /** - * @notice this is a new, optional function in streams lookup. It is meant to surface streams lookup errors. - * @param errCode an uint value that represents the streams lookup error code. - * @param extraData context data from streams lookup process. - * @return upkeepNeeded boolean to indicate whether the keeper should call performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try `abi.encode`. - */ - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol deleted file mode 100644 index 59d2bb4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterface.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {UpkeepFormat} from "../UpkeepFormat.sol"; - -// solhint-disable-next-line interface-starts-with-i -interface UpkeepTranscoderInterface { - function transcodeUpkeeps( - UpkeepFormat fromVersion, - UpkeepFormat toVersion, - bytes calldata encodedUpkeeps - ) external view returns (bytes memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol deleted file mode 100644 index 95dc307..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/UpkeepTranscoderInterfaceV2.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface UpkeepTranscoderInterfaceV2 { - function transcodeUpkeeps( - uint8 fromVersion, - uint8 toVersion, - bytes calldata encodedUpkeeps - ) external view returns (bytes memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol deleted file mode 100644 index eb35589..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/AutomationRegistryInterface1_2.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @notice config of the registry - * @dev only used in params and return values - * @member paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @member blockCountPerTurn number of blocks each oracle has during their turn to - * perform upkeep before it will be the next keeper's turn to submit - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling - * @member maxPerformGas max executeGas allowed for an upkeep on this registry - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrar address of the registrar contract - */ -struct Config { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address registrar; -} - -/** - * @notice state of the registry - * @dev only used in params and return values - * @member nonce used for ID generation - * @member ownerLinkBalance withdrawable balance of LINK by contract owner - * @member expectedLinkBalance the expected balance of LINK of the registry - * @member numUpkeeps total number of upkeeps on the registry - */ -struct State { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint256 numUpkeeps; -} - -interface AutomationRegistryBaseInterface { - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external returns (uint256 id); - - function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success); - - function cancelUpkeep(uint256 id) external; - - function addFunds(uint256 id, uint96 amount) external; - - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - - function getUpkeep( - uint256 id - ) - external - view - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber, - uint96 amountSpent - ); - - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - - function getKeeperInfo(address query) external view returns (address payee, bool active, uint96 balance); - - function getState() external view returns (State memory, Config memory, address[] memory); -} - -/** - * @dev The view methods are not actually marked as view in the implementation - * but we want them to be easily queried off-chain. Solidity will not compile - * if we actually inherit from this interface, so we document it here. - */ -interface AutomationRegistryInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId, - address from - ) - external - view - returns (bytes memory performData, uint256 maxLinkPayment, uint256 gasLimit, int256 gasWei, int256 linkEth); -} - -interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId, - address from - ) - external - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol deleted file mode 100644 index 01f70ae..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_2/KeeperRegistryInterface1_2.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -/** - * @notice This is a deprecated interface. Please use AutomationRegistryInterface1_2 directly. - */ -pragma solidity ^0.8.0; -// solhint-disable-next-line no-unused-import -import {Config, State} from "./AutomationRegistryInterface1_2.sol"; -// solhint-disable-next-line no-unused-import -import {AutomationRegistryBaseInterface as KeeperRegistryBaseInterface} from "./AutomationRegistryInterface1_2.sol"; -// solhint-disable-next-line no-unused-import -import {AutomationRegistryInterface as KeeperRegistryInterface} from "./AutomationRegistryInterface1_2.sol"; -// solhint-disable-next-line no-unused-import -import {AutomationRegistryExecutableInterface as KeeperRegistryExecutableInterface} from "./AutomationRegistryInterface1_2.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol deleted file mode 100644 index d41a869..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v1_3/AutomationRegistryInterface1_3.sol +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @notice config of the registry - * @dev only used in params and return values - * @member paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @member blockCountPerTurn number of blocks each oracle has during their turn to - * perform upkeep before it will be the next keeper's turn to submit - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling - * @member maxPerformGas max executeGas allowed for an upkeep on this registry - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrar address of the registrar contract - */ -struct Config { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address registrar; -} - -/** - * @notice state of the registry - * @dev only used in params and return values - * @member nonce used for ID generation - * @member ownerLinkBalance withdrawable balance of LINK by contract owner - * @member expectedLinkBalance the expected balance of LINK of the registry - * @member numUpkeeps total number of upkeeps on the registry - */ -struct State { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint256 numUpkeeps; -} - -/** - * @notice relevant state of an upkeep - * @member balance the balance of this upkeep - * @member lastKeeper the keeper which last performs the upkeep - * @member executeGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member target the contract which needs to be serviced - * @member amountSpent the amount this upkeep has spent - * @member admin the upkeep admin - * @member paused if this upkeep has been paused - */ -struct Upkeep { - uint96 balance; - address lastKeeper; // 1 full evm word - uint96 amountSpent; - address admin; // 2 full evm words - uint32 executeGas; - uint32 maxValidBlocknumber; - address target; - bool paused; // 24 bits to 3 full evm words -} - -interface AutomationRegistryBaseInterface { - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external returns (uint256 id); - - function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success); - - function cancelUpkeep(uint256 id) external; - - function pauseUpkeep(uint256 id) external; - - function unpauseUpkeep(uint256 id) external; - - function transferUpkeepAdmin(uint256 id, address proposed) external; - - function acceptUpkeepAdmin(uint256 id) external; - - function updateCheckData(uint256 id, bytes calldata newCheckData) external; - - function addFunds(uint256 id, uint96 amount) external; - - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - - function getUpkeep( - uint256 id - ) - external - view - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber, - uint96 amountSpent, - bool paused - ); - - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - - function getKeeperInfo(address query) external view returns (address payee, bool active, uint96 balance); - - function getState() external view returns (State memory, Config memory, address[] memory); -} - -/** - * @dev The view methods are not actually marked as view in the implementation - * but we want them to be easily queried off-chain. Solidity will not compile - * if we actually inherit from this interface, so we document it here. - */ -interface AutomationRegistryInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId, - address from - ) - external - view - returns (bytes memory performData, uint256 maxLinkPayment, uint256 gasLimit, int256 gasWei, int256 linkEth); -} - -interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId, - address from - ) - external - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol deleted file mode 100644 index cfc9ab8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_0/AutomationRegistryInterface2_0.sol +++ /dev/null @@ -1,185 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @notice OnchainConfig of the registry - * @dev only used in params and return values - * @member paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling - * @member maxPerformGas max executeGas allowed for an upkeep on this registry - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrar address of the registrar contract - */ -struct OnchainConfig { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address registrar; -} - -/** - * @notice state of the registry - * @dev only used in params and return values - * @member nonce used for ID generation - * @member ownerLinkBalance withdrawable balance of LINK by contract owner - * @member expectedLinkBalance the expected balance of LINK of the registry - * @member totalPremium the total premium collected on registry so far - * @member numUpkeeps total number of upkeeps on the registry - * @member configCount ordinal number of current config, out of all configs applied to this contract so far - * @member latestConfigBlockNumber last block at which this config was set - * @member latestConfigDigest domain-separation tag for current config - * @member latestEpoch for which a report was transmitted - * @member paused freeze on execution scoped to the entire registry - */ -struct State { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; -} - -/** - * @notice all information about an upkeep - * @dev only used in return values - * @member target the contract which needs to be serviced - * @member executeGas the gas limit of upkeep execution - * @member checkData the checkData bytes for this upkeep - * @member balance the balance of this upkeep - * @member admin for this upkeep - * @member maxValidBlocknumber until which block this upkeep is valid - * @member lastPerformBlockNumber the last block number when this upkeep was performed - * @member amountSpent the amount this upkeep has spent - * @member paused if this upkeep has been paused - * @member skipSigVerification skip signature verification in transmit for a low security low cost model - */ -struct UpkeepInfo { - address target; - uint32 executeGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; -} - -enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE -} - -interface AutomationRegistryBaseInterface { - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData, - bytes calldata offchainConfig - ) external returns (uint256 id); - - function cancelUpkeep(uint256 id) external; - - function pauseUpkeep(uint256 id) external; - - function unpauseUpkeep(uint256 id) external; - - function transferUpkeepAdmin(uint256 id, address proposed) external; - - function acceptUpkeepAdmin(uint256 id) external; - - function updateCheckData(uint256 id, bytes calldata newCheckData) external; - - function addFunds(uint256 id, uint96 amount) external; - - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external; - - function getUpkeep(uint256 id) external view returns (UpkeepInfo memory upkeepInfo); - - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); - - function getState() - external - view - returns ( - State memory state, - OnchainConfig memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); -} - -/** - * @dev The view methods are not actually marked as view in the implementation - * but we want them to be easily queried off-chain. Solidity will not compile - * if we actually inherit from this interface, so we document it here. - */ -interface AutomationRegistryInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 fastGasWei, - uint256 linkNative - ); -} - -interface AutomationRegistryExecutableInterface is AutomationRegistryBaseInterface { - function checkUpkeep( - uint256 upkeepId - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 fastGasWei, - uint256 linkNative - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol deleted file mode 100644 index b3f8751..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_1/IKeeperRegistryMaster.sol +++ /dev/null @@ -1,315 +0,0 @@ -// abi-checksum: 0x0ed34e4b36bd7b4a5447152c2d61491e6ba7ed944b11e4dfef4fea184708975e -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! -pragma solidity ^0.8.4; - -interface IKeeperRegistryMaster { - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientFunds(); - error InvalidDataLength(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidTransmitter(); - error InvalidTrigger(); - error InvalidTriggerType(); - error MaxCheckDataSizeCanOnlyIncrease(); - error MaxPerformDataSizeCanOnlyIncrease(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event OwnerFundsWithdrawn(uint96 amount); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event Transmitted(bytes32 configDigest, uint32 epoch); - event Unpaused(address account); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - fallback() external; - function acceptOwnership() external; - function fallbackTo() external view returns (address); - function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; - function owner() external view returns (address); - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function simulatePerformUpkeep( - uint256 id, - bytes memory performData - ) external view returns (bool success, uint256 gasUsed); - function transferOwnership(address to) external; - function transmit( - bytes32[3] memory reportContext, - bytes memory rawReport, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) external; - function typeAndVersion() external view returns (string memory); - - function addFunds(uint256 id, uint96 amount) external; - function cancelUpkeep(uint256 id) external; - function checkCallback( - uint256 id, - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function checkUpkeep( - uint256 id - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function executeCallback( - uint256 id, - bytes memory payload - ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function migrateUpkeeps(uint256[] memory ids, address destination) external; - function receiveUpkeeps(bytes memory encodedUpkeeps) external; - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - uint8 triggerType, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) external returns (uint256 id); - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes memory checkData, - bytes memory offchainConfig - ) external returns (uint256 id); - function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; - - function acceptPayeeship(address transmitter) external; - function acceptUpkeepAdmin(uint256 id) external; - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); - function getAutomationForwarderLogic() external view returns (address); - function getBalance(uint256 id) external view returns (uint96 balance); - function getCancellationDelay() external pure returns (uint256); - function getConditionalGasOverhead() external pure returns (uint256); - function getFastGasFeedAddress() external view returns (address); - function getForwarder(uint256 upkeepID) external view returns (address); - function getLinkAddress() external view returns (address); - function getLinkNativeFeedAddress() external view returns (address); - function getLogGasOverhead() external pure returns (uint256); - function getMaxPaymentForGas(uint8 triggerType, uint32 gasLimit) external view returns (uint96 maxPayment); - function getMinBalance(uint256 id) external view returns (uint96); - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); - function getMode() external view returns (uint8); - function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); - function getPerPerformByteGasOverhead() external pure returns (uint256); - function getPerSignerGasOverhead() external pure returns (uint256); - function getSignerInfo(address query) external view returns (bool active, uint8 index); - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); - function getTriggerType(uint256 upkeepId) external pure returns (uint8); - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); - function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); - function hasDedupKey(bytes32 dedupKey) external view returns (bool); - function pause() external; - function pauseUpkeep(uint256 id) external; - function recoverFunds() external; - function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; - function setPayees(address[] memory payees) external; - function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; - function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; - function transferPayeeship(address transmitter, address proposed) external; - function transferUpkeepAdmin(uint256 id, address proposed) external; - function unpause() external; - function unpauseUpkeep(uint256 id) external; - function upkeepTranscoderVersion() external pure returns (uint8); - function upkeepVersion() external pure returns (uint8); - function withdrawFunds(uint256 id, address to) external; - function withdrawOwnerFunds() external; - function withdrawPayment(address from, address to) external; -} - -interface IAutomationV21PlusCommon { - struct OnchainConfigLegacy { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - } - - struct StateLegacy { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; - } - - struct UpkeepInfoLegacy { - address target; - uint32 performGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformedBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; - } -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: -/* -[{"inputs":[{"internalType":"contract KeeperRegistryLogicB2_1","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MaxCheckDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MaxPerformDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"PaymentGreaterThanAllLINK","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"OwnerFundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract KeeperRegistryLogicB2_1","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum KeeperRegistryBase2_1.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"triggerType","type":"uint8"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum KeeperRegistryBase2_1.Mode","name":"mode","type":"uint8"},{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkNativeFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkNativeFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMode","outputs":[{"internalType":"enum KeeperRegistryBase2_1.Mode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum KeeperRegistryBase2_1.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum KeeperRegistryBase2_1.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum KeeperRegistryBase2_1.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawOwnerFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] -*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol deleted file mode 100644 index edd8443..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_2/IAutomationRegistryMaster.sol +++ /dev/null @@ -1,341 +0,0 @@ -// abi-checksum: 0xfc319f2ddde95d2e0226c913b9e417495effc4c8c847d01fe07e3de68ea8839c -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! -pragma solidity ^0.8.4; - -interface IAutomationRegistryMaster { - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InvalidDataLength(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidTransmitter(); - error InvalidTrigger(); - error InvalidTriggerType(); - error MaxCheckDataSizeCanOnlyIncrease(); - error MaxPerformDataSizeCanOnlyIncrease(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event OwnerFundsWithdrawn(uint96 amount); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event Transmitted(bytes32 configDigest, uint32 epoch); - event Unpaused(address account); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - fallback() external; - function acceptOwnership() external; - function fallbackTo() external view returns (address); - function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; - function owner() external view returns (address); - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - AutomationRegistryBase2_2.OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function simulatePerformUpkeep( - uint256 id, - bytes memory performData - ) external view returns (bool success, uint256 gasUsed); - function transferOwnership(address to) external; - function transmit( - bytes32[3] memory reportContext, - bytes memory rawReport, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) external; - function typeAndVersion() external view returns (string memory); - - function addFunds(uint256 id, uint96 amount) external; - function cancelUpkeep(uint256 id) external; - function checkCallback( - uint256 id, - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function checkUpkeep( - uint256 id - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ); - function executeCallback( - uint256 id, - bytes memory payload - ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function migrateUpkeeps(uint256[] memory ids, address destination) external; - function receiveUpkeeps(bytes memory encodedUpkeeps) external; - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - uint8 triggerType, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) external returns (uint256 id); - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes memory checkData, - bytes memory offchainConfig - ) external returns (uint256 id); - function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; - - function acceptPayeeship(address transmitter) external; - function acceptUpkeepAdmin(uint256 id) external; - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); - function getAllowedReadOnlyAddress() external view returns (address); - function getAutomationForwarderLogic() external view returns (address); - function getBalance(uint256 id) external view returns (uint96 balance); - function getCancellationDelay() external pure returns (uint256); - function getChainModule() external view returns (address chainModule); - function getConditionalGasOverhead() external pure returns (uint256); - function getFastGasFeedAddress() external view returns (address); - function getForwarder(uint256 upkeepID) external view returns (address); - function getLinkAddress() external view returns (address); - function getLinkNativeFeedAddress() external view returns (address); - function getLogGasOverhead() external pure returns (uint256); - function getMaxPaymentForGas(uint8 triggerType, uint32 gasLimit) external view returns (uint96 maxPayment); - function getMinBalance(uint256 id) external view returns (uint96); - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); - function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); - function getPerPerformByteGasOverhead() external pure returns (uint256); - function getPerSignerGasOverhead() external pure returns (uint256); - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); - function getSignerInfo(address query) external view returns (bool active, uint8 index); - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); - function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256); - function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256); - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); - function getTriggerType(uint256 upkeepId) external pure returns (uint8); - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); - function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); - function hasDedupKey(bytes32 dedupKey) external view returns (bool); - function pause() external; - function pauseUpkeep(uint256 id) external; - function recoverFunds() external; - function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; - function setPayees(address[] memory payees) external; - function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; - function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; - function transferPayeeship(address transmitter, address proposed) external; - function transferUpkeepAdmin(uint256 id, address proposed) external; - function unpause() external; - function unpauseUpkeep(uint256 id) external; - function upkeepTranscoderVersion() external pure returns (uint8); - function upkeepVersion() external pure returns (uint8); - function withdrawFunds(uint256 id, address to) external; - function withdrawOwnerFunds() external; - function withdrawPayment(address from, address to) external; -} - -interface AutomationRegistryBase2_2 { - struct OnchainConfig { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - address chainModule; - bool reorgProtectionEnabled; - } -} - -interface IAutomationV21PlusCommon { - struct StateLegacy { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; - } - - struct OnchainConfigLegacy { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - } - - struct UpkeepInfoLegacy { - address target; - uint32 performGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformedBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; - } -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: -/* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_2","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MaxCheckDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MaxPerformDataSizeCanOnlyIncrease","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"PaymentGreaterThanAllLINK","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"OwnerFundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"internalType":"struct AutomationRegistryBase2_2.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_2","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkNative","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_2.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"triggerType","type":"uint8"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkNativeFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkNativeFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_2.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_2.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_2.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawOwnerFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] -*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol deleted file mode 100644 index 7477c02..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ /dev/null @@ -1,435 +0,0 @@ -// abi-checksum: 0xacb9d0daec3e3bed110c8cf95bdbe7280a21ce61519d4cd496f802884bf05524 -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! -pragma solidity ^0.8.4; - -interface IAutomationRegistryMaster2_3 { - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientBalance(uint256 available, uint256 requested); - error InsufficientLinkLiquidity(); - error InvalidDataLength(); - error InvalidFeed(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidToken(); - error InvalidTransmitter(); - error InvalidTrigger(); - error InvalidTriggerType(); - error MigrationNotPermitted(); - error MustSettleOffchain(); - error MustSettleOnchain(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyFinanceAdmin(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error TransferFailed(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - error ZeroAddressNotAllowed(); - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - event BillingConfigSet(address indexed token, AutomationRegistryBase2_3.BillingConfig config); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event Transmitted(bytes32 configDigest, uint32 epoch); - event Unpaused(address account); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCharged(uint256 indexed id, AutomationRegistryBase2_3.PaymentReceipt receipt); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - fallback() external payable; - function acceptOwnership() external; - function fallbackTo() external view returns (address); - function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - function owner() external view returns (address); - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - AutomationRegistryBase2_3.OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - address[] memory billingTokens, - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs - ) external; - function transferOwnership(address to) external; - function transmit( - bytes32[3] memory reportContext, - bytes memory rawReport, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) external; - function typeAndVersion() external view returns (string memory); - - function cancelUpkeep(uint256 id) external; - function migrateUpkeeps(uint256[] memory ids, address destination) external; - function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; - function receiveUpkeeps(bytes memory encodedUpkeeps) external; - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - uint8 triggerType, - address billingToken, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) external returns (uint256 id); - - function acceptUpkeepAdmin(uint256 id) external; - function addFunds(uint256 id, uint96 amount) external payable; - function checkCallback( - uint256 id, - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ); - function checkUpkeep( - uint256 id - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ); - function executeCallback( - uint256 id, - bytes memory payload - ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function pauseUpkeep(uint256 id) external; - function removeBillingOverrides(uint256 id) external; - function setBillingOverrides(uint256 id, AutomationRegistryBase2_3.BillingOverrides memory billingOverrides) external; - function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; - function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; - function simulatePerformUpkeep( - uint256 id, - bytes memory performData - ) external view returns (bool success, uint256 gasUsed); - function transferUpkeepAdmin(uint256 id, address proposed) external; - function unpauseUpkeep(uint256 id) external; - function withdrawERC20Fees(address asset, address to, uint256 amount) external; - function withdrawFunds(uint256 id, address to) external; - function withdrawLink(address to, uint256 amount) external; - - function acceptPayeeship(address transmitter) external; - function disableOffchainPayments() external; - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); - function getAllowedReadOnlyAddress() external view returns (address); - function getAutomationForwarderLogic() external view returns (address); - function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); - function getBalance(uint256 id) external view returns (uint96 balance); - function getBillingConfig( - address billingToken - ) external view returns (AutomationRegistryBase2_3.BillingConfig memory); - function getBillingOverrides( - uint256 upkeepID - ) external view returns (AutomationRegistryBase2_3.BillingOverrides memory); - function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); - function getBillingToken(uint256 upkeepID) external view returns (address); - function getBillingTokenConfig(address token) external view returns (AutomationRegistryBase2_3.BillingConfig memory); - function getBillingTokens() external view returns (address[] memory); - function getCancellationDelay() external pure returns (uint256); - function getChainModule() external view returns (address chainModule); - function getConditionalGasOverhead() external pure returns (uint256); - function getConfig() external view returns (AutomationRegistryBase2_3.OnchainConfig memory); - function getFallbackNativePrice() external view returns (uint256); - function getFastGasFeedAddress() external view returns (address); - function getForwarder(uint256 upkeepID) external view returns (address); - function getHotVars() external view returns (AutomationRegistryBase2_3.HotVars memory); - function getLinkAddress() external view returns (address); - function getLinkUSDFeedAddress() external view returns (address); - function getLogGasOverhead() external pure returns (uint256); - function getMaxPaymentForGas( - uint256 id, - uint8 triggerType, - uint32 gasLimit, - address billingToken - ) external view returns (uint96 maxPayment); - function getMinBalance(uint256 id) external view returns (uint96); - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); - function getNativeUSDFeedAddress() external view returns (address); - function getNumUpkeeps() external view returns (uint256); - function getPayoutMode() external view returns (uint8); - function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); - function getPerPerformByteGasOverhead() external pure returns (uint256); - function getPerSignerGasOverhead() external pure returns (uint256); - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); - function getReserveAmount(address billingToken) external view returns (uint256); - function getSignerInfo(address query) external view returns (bool active, uint8 index); - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); - function getStorage() external view returns (AutomationRegistryBase2_3.Storage memory); - function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256); - function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256); - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); - function getTransmittersWithPayees() external view returns (AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); - function getTriggerType(uint256 upkeepId) external pure returns (uint8); - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); - function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); - function getWrappedNativeTokenAddress() external view returns (address); - function hasDedupKey(bytes32 dedupKey) external view returns (bool); - function linkAvailableForPayment() external view returns (int256); - function pause() external; - function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; - function setPayees(address[] memory payees) external; - function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; - function settleNOPsOffchain() external; - function supportsBillingToken(address token) external view returns (bool); - function transferPayeeship(address transmitter, address proposed) external; - function unpause() external; - function upkeepVersion() external pure returns (uint8); - function withdrawPayment(address from, address to) external; -} - -interface AutomationRegistryBase2_3 { - struct BillingOverrides { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - } - - struct BillingConfig { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - address priceFeed; - uint8 decimals; - uint256 fallbackPrice; - uint96 minSpend; - } - - struct PaymentReceipt { - uint96 gasChargeInBillingToken; - uint96 premiumInBillingToken; - uint96 gasReimbursementInJuels; - uint96 premiumInJuels; - address billingToken; - uint96 linkUSD; - uint96 nativeUSD; - uint96 billingUSD; - } - - struct OnchainConfig { - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - address transcoder; - bool reorgProtectionEnabled; - uint24 stalenessSeconds; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - address upkeepPrivilegeManager; - uint16 gasCeilingMultiplier; - address financeAdmin; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - uint256 fallbackNativePrice; - address[] registrars; - address chainModule; - } - - struct HotVars { - uint96 totalPremium; - uint32 latestEpoch; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint8 f; - bool paused; - bool reentrancyGuard; - bool reorgProtectionEnabled; - address chainModule; - } - - struct Storage { - address transcoder; - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 nonce; - address upkeepPrivilegeManager; - uint32 configCount; - uint32 latestConfigBlockNumber; - uint32 maxCheckDataSize; - address financeAdmin; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - } - - struct TransmitterPayeeInfo { - address transmitterAddress; - address payeeAddress; - } -} - -interface IAutomationV21PlusCommon { - struct StateLegacy { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; - } - - struct OnchainConfigLegacy { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - } - - struct UpkeepInfoLegacy { - address target; - uint32 performGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformedBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; - } -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: -/* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] -*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol deleted file mode 100644 index fdbd7dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/v2_3/IWrappedNative.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - -interface IWrappedNative is IERC20 { - function deposit() external payable; - - function withdraw(uint256 wad) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol deleted file mode 100644 index 9edb541..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IGasBoundCaller.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -address constant GAS_BOUND_CALLER = address(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5); - -interface IGasBoundCaller { - function gasBoundCall(address _to, uint256 _maxTotalGas, bytes calldata _data) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol deleted file mode 100644 index c8f4800..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/ISystemContext.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(address(0x800b)); - -interface ISystemContext { - function gasPrice() external view returns (uint256); - function gasPerPubdataByte() external view returns (uint256 gasPerPubdataByte); - function getCurrentPubdataSpent() external view returns (uint256 currentPubdataSpent); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol deleted file mode 100644 index 8943721..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/interfaces/zksync/IZKSyncAutomationRegistryMaster2_3.sol +++ /dev/null @@ -1,441 +0,0 @@ -// solhint-disable -// abi-checksum: 0x5857a77a981fcb60dbdac0700e68420cbe544249b20d9326d51c5ef8584c5dd7 -// SPDX-License-Identifier: MIT -// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.6.6. SEE SOURCE BELOW. !! -pragma solidity ^0.8.19; - -interface IZKSyncAutomationRegistryMaster2_3 { - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientBalance(uint256 available, uint256 requested); - error InsufficientLinkLiquidity(); - error InvalidDataLength(); - error InvalidFeed(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidToken(); - error InvalidTransmitter(); - error InvalidTrigger(); - error InvalidTriggerType(); - error MigrationNotPermitted(); - error MustSettleOffchain(); - error MustSettleOnchain(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyFinanceAdmin(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error TransferFailed(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - error ZeroAddressNotAllowed(); - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event BillingConfigOverridden(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - event BillingConfigSet(address indexed token, ZKSyncAutomationRegistryBase2_3.BillingConfig config); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event Transmitted(bytes32 configDigest, uint32 epoch); - event Unpaused(address account); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCharged(uint256 indexed id, ZKSyncAutomationRegistryBase2_3.PaymentReceipt receipt); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - fallback() external payable; - function acceptOwnership() external; - function fallbackTo() external view returns (address); - function latestConfigDetails() external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - function latestConfigDigestAndEpoch() external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - function owner() external view returns (address); - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - ZKSyncAutomationRegistryBase2_3.OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - address[] memory billingTokens, - ZKSyncAutomationRegistryBase2_3.BillingConfig[] memory billingConfigs - ) external; - function transferOwnership(address to) external; - function transmit( - bytes32[3] memory reportContext, - bytes memory rawReport, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) external; - function typeAndVersion() external view returns (string memory); - - function cancelUpkeep(uint256 id) external; - function migrateUpkeeps(uint256[] memory ids, address destination) external; - function onTokenTransfer(address sender, uint256 amount, bytes memory data) external; - function receiveUpkeeps(bytes memory encodedUpkeeps) external; - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - uint8 triggerType, - address billingToken, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) external returns (uint256 id); - - function acceptUpkeepAdmin(uint256 id) external; - function addFunds(uint256 id, uint96 amount) external payable; - function checkCallback( - uint256 id, - bytes[] memory values, - bytes memory extraData - ) external view returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ); - function checkUpkeep( - uint256 id - ) - external - view - returns ( - bool upkeepNeeded, - bytes memory performData, - uint8 upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ); - function executeCallback( - uint256 id, - bytes memory payload - ) external returns (bool upkeepNeeded, bytes memory performData, uint8 upkeepFailureReason, uint256 gasUsed); - function pauseUpkeep(uint256 id) external; - function removeBillingOverrides(uint256 id) external; - function setBillingOverrides( - uint256 id, - ZKSyncAutomationRegistryBase2_3.BillingOverrides memory billingOverrides - ) external; - function setUpkeepCheckData(uint256 id, bytes memory newCheckData) external; - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external; - function setUpkeepOffchainConfig(uint256 id, bytes memory config) external; - function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; - function simulatePerformUpkeep( - uint256 id, - bytes memory performData - ) external view returns (bool success, uint256 gasUsed); - function transferUpkeepAdmin(uint256 id, address proposed) external; - function unpauseUpkeep(uint256 id) external; - function withdrawERC20Fees(address asset, address to, uint256 amount) external; - function withdrawFunds(uint256 id, address to) external; - function withdrawLink(address to, uint256 amount) external; - - function acceptPayeeship(address transmitter) external; - function disableOffchainPayments() external; - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory); - function getAllowedReadOnlyAddress() external view returns (address); - function getAutomationForwarderLogic() external view returns (address); - function getAvailableERC20ForPayment(address billingToken) external view returns (uint256); - function getBalance(uint256 id) external view returns (uint96 balance); - function getBillingConfig( - address billingToken - ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); - function getBillingOverrides( - uint256 upkeepID - ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingOverrides memory); - function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool); - function getBillingToken(uint256 upkeepID) external view returns (address); - function getBillingTokenConfig( - address token - ) external view returns (ZKSyncAutomationRegistryBase2_3.BillingConfig memory); - function getBillingTokens() external view returns (address[] memory); - function getCancellationDelay() external pure returns (uint256); - function getChainModule() external view returns (address chainModule); - function getConditionalGasOverhead() external pure returns (uint256); - function getConfig() external view returns (ZKSyncAutomationRegistryBase2_3.OnchainConfig memory); - function getFallbackNativePrice() external view returns (uint256); - function getFastGasFeedAddress() external view returns (address); - function getForwarder(uint256 upkeepID) external view returns (address); - function getHotVars() external view returns (ZKSyncAutomationRegistryBase2_3.HotVars memory); - function getLinkAddress() external view returns (address); - function getLinkUSDFeedAddress() external view returns (address); - function getLogGasOverhead() external pure returns (uint256); - function getMaxPaymentForGas( - uint256 id, - uint8 triggerType, - uint32 gasLimit, - address billingToken - ) external view returns (uint96 maxPayment); - function getMinBalance(uint256 id) external view returns (uint96); - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance); - function getNativeUSDFeedAddress() external view returns (address); - function getNumUpkeeps() external view returns (uint256); - function getPayoutMode() external view returns (uint8); - function getPeerRegistryMigrationPermission(address peer) external view returns (uint8); - function getPerSignerGasOverhead() external pure returns (uint256); - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled); - function getReserveAmount(address billingToken) external view returns (uint256); - function getSignerInfo(address query) external view returns (bool active, uint8 index); - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ); - function getStorage() external view returns (ZKSyncAutomationRegistryBase2_3.Storage memory); - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee); - function getTransmittersWithPayees() - external - view - returns (ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[] memory); - function getTriggerType(uint256 upkeepId) external pure returns (uint8); - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo); - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory); - function getUpkeepTriggerConfig(uint256 upkeepId) external view returns (bytes memory); - function getWrappedNativeTokenAddress() external view returns (address); - function hasDedupKey(bytes32 dedupKey) external view returns (bool); - function linkAvailableForPayment() external view returns (int256); - function pause() external; - function setAdminPrivilegeConfig(address admin, bytes memory newPrivilegeConfig) external; - function setPayees(address[] memory payees) external; - function setPeerRegistryMigrationPermission(address peer, uint8 permission) external; - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory newPrivilegeConfig) external; - function settleNOPsOffchain() external; - function supportsBillingToken(address token) external view returns (bool); - function transferPayeeship(address transmitter, address proposed) external; - function unpause() external; - function upkeepVersion() external pure returns (uint8); - function withdrawPayment(address from, address to) external; -} - -interface ZKSyncAutomationRegistryBase2_3 { - struct BillingOverrides { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - } - - struct BillingConfig { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - address priceFeed; - uint8 decimals; - uint256 fallbackPrice; - uint96 minSpend; - } - - struct PaymentReceipt { - uint96 gasChargeInBillingToken; - uint96 premiumInBillingToken; - uint96 gasReimbursementInJuels; - uint96 premiumInJuels; - address billingToken; - uint96 linkUSD; - uint96 nativeUSD; - uint96 billingUSD; - } - - struct OnchainConfig { - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - address transcoder; - bool reorgProtectionEnabled; - uint24 stalenessSeconds; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - address upkeepPrivilegeManager; - uint16 gasCeilingMultiplier; - address financeAdmin; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - uint256 fallbackNativePrice; - address[] registrars; - address chainModule; - } - - struct HotVars { - uint96 totalPremium; - uint32 latestEpoch; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint8 f; - bool paused; - bool reentrancyGuard; - bool reorgProtectionEnabled; - address chainModule; - } - - struct Storage { - address transcoder; - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 nonce; - address upkeepPrivilegeManager; - uint32 configCount; - uint32 latestConfigBlockNumber; - uint32 maxCheckDataSize; - address financeAdmin; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - } - - struct TransmitterPayeeInfo { - address transmitterAddress; - address payeeAddress; - } -} - -interface IAutomationV21PlusCommon { - struct StateLegacy { - uint32 nonce; - uint96 ownerLinkBalance; - uint256 expectedLinkBalance; - uint96 totalPremium; - uint256 numUpkeeps; - uint32 configCount; - uint32 latestConfigBlockNumber; - bytes32 latestConfigDigest; - uint32 latestEpoch; - bool paused; - } - - struct OnchainConfigLegacy { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - } - - struct UpkeepInfoLegacy { - address target; - uint32 performGas; - bytes checkData; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - uint32 lastPerformedBlockNumber; - uint96 amountSpent; - bool paused; - bytes offchainConfig; - } -} - -// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: -/* -[{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint96","name":"gasChargeInBillingToken","type":"uint96"},{"internalType":"uint96","name":"premiumInBillingToken","type":"uint96"},{"internalType":"uint96","name":"gasReimbursementInJuels","type":"uint96"},{"internalType":"uint96","name":"premiumInJuels","type":"uint96"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"uint96","name":"linkUSD","type":"uint96"},{"internalType":"uint96","name":"nativeUSD","type":"uint96"},{"internalType":"uint96","name":"billingUSD","type":"uint96"}],"indexed":false,"internalType":"struct ZKSyncAutomationRegistryBase2_3.PaymentReceipt","name":"receipt","type":"tuple"}],"name":"UpkeepCharged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ZKSyncAutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getAvailableERC20ForPayment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getBillingConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverrides","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingOverrides","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingOverridesEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmittersWithPayees","outputs":[{"components":[{"internalType":"address","name":"transmitterAddress","type":"address"},{"internalType":"address","name":"payeeAddress","type":"address"}],"internalType":"struct ZKSyncAutomationRegistryBase2_3.TransmitterPayeeInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum ZKSyncAutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum ZKSyncAutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] -*/ diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol deleted file mode 100644 index 0c93c19..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/external/Cron.sol +++ /dev/null @@ -1,78 +0,0 @@ -pragma solidity 0.8.6; - -import {Cron as CronInternal, Spec} from "../internal/Cron.sol"; - -/** - * @title The Cron library - * @notice A utility contract for encoding/decoding cron strings (ex: 0 0 * * *) into an - * abstraction called a Spec. The library also includes a spec function, nextTick(), which - * determines the next time a cron job should fire based on the current block timestamp. - * @dev this is the external version of the library, which relies on the internal library - * by the same name. - */ -library Cron { - using CronInternal for Spec; - using CronInternal for string; - - /** - * @notice nextTick calculates the next datetime that a spec "ticks", starting - * from the current block timestamp. This is gas-intensive and therefore should - * only be called off-chain. - * @param spec the spec to evaluate - * @return the next tick - */ - function nextTick(Spec calldata spec) public view returns (uint256) { - return spec.nextTick(); - } - - /** - * @notice lastTick calculates the previous datetime that a spec "ticks", starting - * from the current block timestamp. This is gas-intensive and therefore should - * only be called off-chain. - * @param spec the spec to evaluate - * @return the next tick - */ - function lastTick(Spec calldata spec) public view returns (uint256) { - return spec.lastTick(); - } - - /** - * @notice matches evaluates whether or not a spec "ticks" at a given timestamp - * @param spec the spec to evaluate - * @param timestamp the timestamp to compare against - * @return true / false if they match - */ - function matches(Spec calldata spec, uint256 timestamp) public view returns (bool) { - return spec.matches(timestamp); - } - - /** - * @notice toSpec converts a cron string to a spec struct. This is gas-intensive - * and therefore should only be called off-chain. - * @param cronString the cron string - * @return the spec struct - */ - function toSpec(string calldata cronString) public pure returns (Spec memory) { - return cronString.toSpec(); - } - - /** - * @notice toEncodedSpec converts a cron string to an abi-encoded spec. This is gas-intensive - * and therefore should only be called off-chain. - * @param cronString the cron string - * @return the abi-encoded spec - */ - function toEncodedSpec(string calldata cronString) public pure returns (bytes memory) { - return cronString.toEncodedSpec(); - } - - /** - * @notice toCronString converts a cron spec to a human-readable cron string. This is gas-intensive - * and therefore should only be called off-chain. - * @param spec the cron spec - * @return the corresponding cron string - */ - function toCronString(Spec calldata spec) public pure returns (string memory) { - return spec.toCronString(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol deleted file mode 100644 index ae4f90d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/libraries/internal/Cron.sol +++ /dev/null @@ -1,544 +0,0 @@ -// SPDX-License-Identifier: MIT - -/* - The Cron contract serves two primary functions: - * parsing cron-formatted strings like "0 0 * * *" into - structs called "Specs" - * computing the "next tick" of a cron spec - - Because manipulating strings is gas-expensive in solidity, - the intended use of this contract is for users to first convert - their cron strings to encoded Spec structs via toEncodedSpec(). - Then, the user stores the Spec on chain. Finally, users use the nextTick(), - function to determine the datetime of the next cron job run. - - Cron jobs are interpreted according to this format: - - ┌───────────── minute (0 - 59) - │ ┌───────────── hour (0 - 23) - │ │ ┌───────────── day of the month (1 - 31) - │ │ │ ┌───────────── month (1 - 12) - │ │ │ │ ┌───────────── day of the week (0 - 6) (Monday to Sunday) - │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - * * * * * - - Special limitations: - * there is no year field - * no special characters: ? L W # - * lists can have a max length of 26 - * no words like JAN / FEB or MON / TUES -*/ - -pragma solidity 0.8.6; - -import "../../../vendor/Strings.sol"; -import "../../../vendor/DateTime.sol"; - -// The fields of a cron spec, by name -string constant MINUTE = "minute"; -string constant HOUR = "hour"; -string constant DAY = "day"; -string constant MONTH = "month"; -string constant DAY_OF_WEEK = "day of week"; - -error UnknownFieldType(); -error InvalidSpec(string reason); -error InvalidField(string field, string reason); -error ListTooLarge(); - -// Set of enums representing a cron field type -enum FieldType { - WILD, - EXACT, - INTERVAL, - RANGE, - LIST -} - -// A spec represents a cron job by decomposing it into 5 fields -struct Spec { - Field minute; - Field hour; - Field day; - Field month; - Field dayOfWeek; -} - -// A field represents a single element in a cron spec. There are 5 types -// of fields (see above). Not all properties of this struct are present at once. -struct Field { - FieldType fieldType; - uint8 singleValue; - uint8 interval; - uint8 rangeStart; - uint8 rangeEnd; - uint8 listLength; - uint8[26] list; -} - -/** - * @title The Cron library - * @notice A utility contract for encoding/decoding cron strings (ex: 0 0 * * *) into an - * abstraction called a Spec. The library also includes a spec function, nextTick(), which - * determines the next time a cron job should fire based on the current block timestamp. - */ -// solhint-disable chainlink-solidity/prefix-internal-functions-with-underscore, no-global-import -library Cron { - using strings for *; - - /** - * @notice nextTick calculates the next datetime that a spec "ticks", starting - * from the current block timestamp. This is gas-intensive and therefore should - * only be called off-chain. - * @param spec the spec to evaluate - * @return the next tick - * @dev this is the internal version of the library. There is also an external version. - */ - function nextTick(Spec memory spec) internal view returns (uint256) { - uint16 year = DateTime.getYear(block.timestamp); - uint8 month = DateTime.getMonth(block.timestamp); - uint8 day = DateTime.getDay(block.timestamp); - uint8 hour = DateTime.getHour(block.timestamp); - uint8 minute = DateTime.getMinute(block.timestamp); - uint8 dayOfWeek; - for (; true; year++) { - for (; month <= 12; month++) { - if (!matches(spec.month, month)) { - day = 1; - hour = 0; - minute = 0; - continue; - } - uint8 maxDay = DateTime.getDaysInMonth(month, year); - for (; day <= maxDay; day++) { - if (!matches(spec.day, day)) { - hour = 0; - minute = 0; - continue; - } - dayOfWeek = DateTime.getWeekday(DateTime.toTimestamp(year, month, day)); - if (!matches(spec.dayOfWeek, dayOfWeek)) { - hour = 0; - minute = 0; - continue; - } - for (; hour < 24; hour++) { - if (!matches(spec.hour, hour)) { - minute = 0; - continue; - } - for (; minute < 60; minute++) { - if (!matches(spec.minute, minute)) { - continue; - } - return DateTime.toTimestamp(year, month, day, hour, minute); - } - minute = 0; - } - hour = 0; - } - day = 1; - } - month = 1; - } - } - - /** - * @notice lastTick calculates the previous datetime that a spec "ticks", starting - * from the current block timestamp. This is gas-intensive and therefore should - * only be called off-chain. - * @param spec the spec to evaluate - * @return the next tick - */ - function lastTick(Spec memory spec) internal view returns (uint256) { - uint16 year = DateTime.getYear(block.timestamp); - uint8 month = DateTime.getMonth(block.timestamp); - uint8 day = DateTime.getDay(block.timestamp); - uint8 hour = DateTime.getHour(block.timestamp); - uint8 minute = DateTime.getMinute(block.timestamp); - uint8 dayOfWeek; - bool resetDay; - for (; true; year--) { - for (; month > 0; month--) { - if (!matches(spec.month, month)) { - resetDay = true; - hour = 23; - minute = 59; - continue; - } - if (resetDay) { - day = DateTime.getDaysInMonth(month, year); - } - for (; day > 0; day--) { - if (!matches(spec.day, day)) { - hour = 23; - minute = 59; - continue; - } - dayOfWeek = DateTime.getWeekday(DateTime.toTimestamp(year, month, day)); - if (!matches(spec.dayOfWeek, dayOfWeek)) { - hour = 23; - minute = 59; - continue; - } - for (; hour >= 0; hour--) { - if (!matches(spec.hour, hour)) { - minute = 59; - if (hour == 0) { - break; - } - continue; - } - for (; minute >= 0; minute--) { - if (!matches(spec.minute, minute)) { - if (minute == 0) { - break; - } - continue; - } - return DateTime.toTimestamp(year, month, day, hour, minute); - } - minute = 59; - if (hour == 0) { - break; - } - } - hour = 23; - } - resetDay = true; - } - month = 12; - } - } - - /** - * @notice matches evaluates whether or not a spec "ticks" at a given timestamp - * @param spec the spec to evaluate - * @param timestamp the timestamp to compare against - * @return true / false if they match - */ - function matches(Spec memory spec, uint256 timestamp) internal view returns (bool) { - DateTime._DateTime memory dt = DateTime.parseTimestamp(timestamp); - return - matches(spec.month, dt.month) && - matches(spec.day, dt.day) && - matches(spec.hour, dt.hour) && - matches(spec.minute, dt.minute); - } - - /** - * @notice toSpec converts a cron string to a spec struct. This is gas-intensive - * and therefore should only be called off-chain. - * @param cronString the cron string - * @return the spec struct - */ - function toSpec(string memory cronString) internal pure returns (Spec memory) { - strings.slice memory space = strings.toSlice(" "); - strings.slice memory cronSlice = strings.toSlice(cronString); - if (cronSlice.count(space) != 4) { - revert InvalidSpec("4 spaces required"); - } - strings.slice memory minuteSlice = cronSlice.split(space); - strings.slice memory hourSlice = cronSlice.split(space); - strings.slice memory daySlice = cronSlice.split(space); - strings.slice memory monthSlice = cronSlice.split(space); - // DEV: dayOfWeekSlice = cronSlice - // The cronSlice now contains the last section of the cron job, - // which corresponds to the day of week - if ( - minuteSlice.len() == 0 || - hourSlice.len() == 0 || - daySlice.len() == 0 || - monthSlice.len() == 0 || - cronSlice.len() == 0 - ) { - revert InvalidSpec("some fields missing"); - } - return - validate( - Spec({ - minute: sliceToField(minuteSlice), - hour: sliceToField(hourSlice), - day: sliceToField(daySlice), - month: sliceToField(monthSlice), - dayOfWeek: sliceToField(cronSlice) - }) - ); - } - - /** - * @notice toEncodedSpec converts a cron string to an abi-encoded spec. This is gas-intensive - * and therefore should only be called off-chain. - * @param cronString the cron string - * @return the abi-encoded spec - */ - function toEncodedSpec(string memory cronString) internal pure returns (bytes memory) { - return abi.encode(toSpec(cronString)); - } - - /** - * @notice toCronString converts a cron spec to a human-readable cron string. This is gas-intensive - * and therefore should only be called off-chain. - * @param spec the cron spec - * @return the corresponding cron string - */ - function toCronString(Spec memory spec) internal pure returns (string memory) { - return - string( - bytes.concat( - fieldToBstring(spec.minute), - " ", - fieldToBstring(spec.hour), - " ", - fieldToBstring(spec.day), - " ", - fieldToBstring(spec.month), - " ", - fieldToBstring(spec.dayOfWeek) - ) - ); - } - - /** - * @notice matches evaluates if a values matches a field. - * ex: 3 matches *, 3 matches 0-5, 3 does not match 0,2,4 - * @param field the field struct to match against - * @param value the value of a field - * @return true / false if they match - */ - function matches(Field memory field, uint8 value) private pure returns (bool) { - if (field.fieldType == FieldType.WILD) { - return true; - } else if (field.fieldType == FieldType.INTERVAL) { - return value % field.interval == 0; - } else if (field.fieldType == FieldType.EXACT) { - return value == field.singleValue; - } else if (field.fieldType == FieldType.RANGE) { - return value >= field.rangeStart && value <= field.rangeEnd; - } else if (field.fieldType == FieldType.LIST) { - for (uint256 idx = 0; idx < field.listLength; idx++) { - if (value == field.list[idx]) { - return true; - } - } - return false; - } - revert UnknownFieldType(); - } - - // VALIDATIONS - - /** - * @notice validate validates a spec, reverting if any errors are found - * @param spec the spec to validate - * @return the original spec - */ - function validate(Spec memory spec) private pure returns (Spec memory) { - validateField(spec.dayOfWeek, DAY_OF_WEEK, 0, 6); - validateField(spec.month, MONTH, 1, 12); - uint8 maxDay = maxDayForMonthField(spec.month); - validateField(spec.day, DAY, 1, maxDay); - validateField(spec.hour, HOUR, 0, 23); - validateField(spec.minute, MINUTE, 0, 59); - return spec; - } - - /** - * @notice validateField validates the value of a field. It reverts if an error is found. - * @param field the field to validate - * @param fieldName the name of the field ex "minute" or "hour" - * @param min the minimum value a field can have (usually 1 or 0) - * @param max the maximum value a field can have (ex minute = 59, hour = 23) - */ - function validateField(Field memory field, string memory fieldName, uint8 min, uint8 max) private pure { - if (field.fieldType == FieldType.WILD) { - return; - } else if (field.fieldType == FieldType.EXACT) { - if (field.singleValue < min || field.singleValue > max) { - string memory reason = string( - bytes.concat("value must be >=,", uintToBString(min), " and <=", uintToBString(max)) - ); - revert InvalidField(fieldName, reason); - } - } else if (field.fieldType == FieldType.INTERVAL) { - if (field.interval < 1 || field.interval > max) { - string memory reason = string( - bytes.concat("inverval must be */(", uintToBString(1), "-", uintToBString(max), ")") - ); - revert InvalidField(fieldName, reason); - } - } else if (field.fieldType == FieldType.RANGE) { - if (field.rangeEnd > max || field.rangeEnd <= field.rangeStart) { - string memory reason = string( - bytes.concat("inverval must be within ", uintToBString(min), "-", uintToBString(max)) - ); - revert InvalidField(fieldName, reason); - } - } else if (field.fieldType == FieldType.LIST) { - if (field.listLength < 2) { - revert InvalidField(fieldName, "lists must have at least 2 items"); - } - string memory reason = string( - bytes.concat("items in list must be within ", uintToBString(min), "-", uintToBString(max)) - ); - uint8 listItem; - for (uint256 idx = 0; idx < field.listLength; idx++) { - listItem = field.list[idx]; - if (listItem < min || listItem > max) { - revert InvalidField(fieldName, reason); - } - } - } else { - revert UnknownFieldType(); - } - } - - /** - * @notice maxDayForMonthField returns the maximum valid day given the month field - * @param month the month field - * @return the max day - */ - function maxDayForMonthField(Field memory month) private pure returns (uint8) { - // DEV: ranges are always safe because any two consecutive months will always - // contain a month with 31 days - if (month.fieldType == FieldType.WILD || month.fieldType == FieldType.RANGE) { - return 31; - } else if (month.fieldType == FieldType.EXACT) { - // DEV: assume leap year in order to get max value - return DateTime.getDaysInMonth(month.singleValue, 4); - } else if (month.fieldType == FieldType.INTERVAL) { - if (month.interval == 9 || month.interval == 11) { - return 30; - } else { - return 31; - } - } else if (month.fieldType == FieldType.LIST) { - uint8 result; - for (uint256 idx = 0; idx < month.listLength; idx++) { - // DEV: assume leap year in order to get max value - uint8 daysInMonth = DateTime.getDaysInMonth(month.list[idx], 4); - if (daysInMonth == 31) { - return daysInMonth; - } - if (daysInMonth > result) { - result = daysInMonth; - } - } - return result; - } else { - revert UnknownFieldType(); - } - } - - /** - * @notice sliceToField converts a strings.slice to a field struct - * @param fieldSlice the slice of a string representing the field of a cron job - * @return the field - */ - function sliceToField(strings.slice memory fieldSlice) private pure returns (Field memory) { - strings.slice memory star = strings.toSlice("*"); - strings.slice memory dash = strings.toSlice("-"); - strings.slice memory slash = strings.toSlice("/"); - strings.slice memory comma = strings.toSlice(","); - Field memory field; - if (fieldSlice.equals(star)) { - field.fieldType = FieldType.WILD; - } else if (fieldSlice.contains(dash)) { - field.fieldType = FieldType.RANGE; - strings.slice memory start = fieldSlice.split(dash); - field.rangeStart = sliceToUint8(start); - field.rangeEnd = sliceToUint8(fieldSlice); - } else if (fieldSlice.contains(slash)) { - field.fieldType = FieldType.INTERVAL; - fieldSlice.split(slash); - field.interval = sliceToUint8(fieldSlice); - } else if (fieldSlice.contains(comma)) { - field.fieldType = FieldType.LIST; - strings.slice memory token; - while (fieldSlice.len() > 0) { - if (field.listLength > 25) { - revert ListTooLarge(); - } - token = fieldSlice.split(comma); - field.list[field.listLength] = sliceToUint8(token); - field.listLength++; - } - } else { - // needs input validation - field.fieldType = FieldType.EXACT; - field.singleValue = sliceToUint8(fieldSlice); - } - return field; - } - - /** - * @notice fieldToBstring converts a field to the bytes representation of that field string - * @param field the field to stringify - * @return bytes representing the string, ex: bytes("*") - */ - function fieldToBstring(Field memory field) private pure returns (bytes memory) { - if (field.fieldType == FieldType.WILD) { - return "*"; - } else if (field.fieldType == FieldType.EXACT) { - return uintToBString(uint256(field.singleValue)); - } else if (field.fieldType == FieldType.RANGE) { - return bytes.concat(uintToBString(field.rangeStart), "-", uintToBString(field.rangeEnd)); - } else if (field.fieldType == FieldType.INTERVAL) { - return bytes.concat("*/", uintToBString(uint256(field.interval))); - } else if (field.fieldType == FieldType.LIST) { - bytes memory result = uintToBString(field.list[0]); - for (uint256 idx = 1; idx < field.listLength; idx++) { - result = bytes.concat(result, ",", uintToBString(field.list[idx])); - } - return result; - } - revert UnknownFieldType(); - } - - /** - * @notice uintToBString converts a uint256 to a bytes representation of that uint as a string - * @param n the number to stringify - * @return bytes representing the string, ex: bytes("1") - */ - function uintToBString(uint256 n) private pure returns (bytes memory) { - if (n == 0) { - return "0"; - } - uint256 j = n; - uint256 len; - while (j != 0) { - len++; - j /= 10; - } - bytes memory bstr = new bytes(len); - uint256 k = len; - while (n != 0) { - k = k - 1; - uint8 temp = (48 + uint8(n - (n / 10) * 10)); - bytes1 b1 = bytes1(temp); - bstr[k] = b1; - n /= 10; - } - return bstr; - } - - /** - * @notice sliceToUint8 converts a strings.slice to uint8 - * @param slice the string slice to convert to a uint8 - * @return the number that the string represents ex: "20" --> 20 - */ - function sliceToUint8(strings.slice memory slice) private pure returns (uint8) { - bytes memory b = bytes(slice.toString()); - uint8 i; - uint8 result = 0; - for (i = 0; i < b.length; i++) { - uint8 c = uint8(b[i]); - if (c >= 48 && c <= 57) { - result = result * 10 + (c - 48); - } - } - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol deleted file mode 100644 index 63a6181..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.8.0; - -import {ERC20Mock} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; - -// mock ERC20 with 6 decimals -contract ERC20Mock6Decimals is ERC20Mock { - constructor( - string memory name, - string memory symbol, - address initialAccount, - uint256 initialBalance - ) payable ERC20Mock(name, symbol, initialAccount, initialBalance) {} - - function decimals() public view virtual override returns (uint8) { - return 6; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol deleted file mode 100644 index b147c98..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistrar1_2Mock.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -contract KeeperRegistrar1_2Mock { - event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); - event ConfigChanged( - uint8 autoApproveConfigType, - uint32 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - event RegistrationRejected(bytes32 indexed hash); - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes checkData, - uint96 amount, - uint8 indexed source - ); - - function emitAutoApproveAllowedSenderSet(address senderAddress, bool allowed) public { - emit AutoApproveAllowedSenderSet(senderAddress, allowed); - } - - function emitConfigChanged( - uint8 autoApproveConfigType, - uint32 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ) public { - emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); - } - - function emitOwnershipTransferRequested(address from, address to) public { - emit OwnershipTransferRequested(from, to); - } - - function emitOwnershipTransferred(address from, address to) public { - emit OwnershipTransferred(from, to); - } - - function emitRegistrationApproved(bytes32 hash, string memory displayName, uint256 upkeepId) public { - emit RegistrationApproved(hash, displayName, upkeepId); - } - - function emitRegistrationRejected(bytes32 hash) public { - emit RegistrationRejected(hash); - } - - function emitRegistrationRequested( - bytes32 hash, - string memory name, - bytes memory encryptedEmail, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes memory checkData, - uint96 amount, - uint8 source - ) public { - emit RegistrationRequested( - hash, - name, - encryptedEmail, - upkeepContract, - gasLimit, - adminAddress, - checkData, - amount, - source - ); - } - - enum AutoApproveType { - DISABLED, - ENABLED_SENDER_ALLOWLIST, - ENABLED_ALL - } - - AutoApproveType public s_autoApproveConfigType; - uint32 public s_autoApproveMaxAllowed; - uint32 public s_approvedCount; - address public s_keeperRegistry; - uint256 public s_minLINKJuels; - - // Function to set mock return data for the getRegistrationConfig function - function setRegistrationConfig( - AutoApproveType _autoApproveConfigType, - uint32 _autoApproveMaxAllowed, - uint32 _approvedCount, - address _keeperRegistry, - uint256 _minLINKJuels - ) external { - s_autoApproveConfigType = _autoApproveConfigType; - s_autoApproveMaxAllowed = _autoApproveMaxAllowed; - s_approvedCount = _approvedCount; - s_keeperRegistry = _keeperRegistry; - s_minLINKJuels = _minLINKJuels; - } - - // Mock getRegistrationConfig function - function getRegistrationConfig() - external - view - returns ( - AutoApproveType autoApproveConfigType, - uint32 autoApproveMaxAllowed, - uint32 approvedCount, - address keeperRegistry, - uint256 minLINKJuels - ) - { - return (s_autoApproveConfigType, s_autoApproveMaxAllowed, s_approvedCount, s_keeperRegistry, s_minLINKJuels); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol deleted file mode 100644 index 87e93c6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.6; - -contract KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock { - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - - function emitOwnershipTransferRequested(address from, address to) public { - emit OwnershipTransferRequested(from, to); - } - - function emitOwnershipTransferred(address from, address to) public { - emit OwnershipTransferred(from, to); - } - - bool public s_mockResult; - bytes public s_mockPayload; - uint256 public s_mockGas; - - // Function to set mock return data for the measureCheckGas function - function setMeasureCheckGasResult(bool result, bytes memory payload, uint256 gas) external { - s_mockResult = result; - s_mockPayload = payload; - s_mockGas = gas; - } - - // Mock measureCheckGas function - function measureCheckGas(uint256 id, address from) external returns (bool, bytes memory, uint256) { - return (s_mockResult, s_mockPayload, s_mockGas); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol deleted file mode 100644 index 8efca03..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregator.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {IOffchainAggregator} from "../HeartbeatRequester.sol"; - -contract MockAggregator is IOffchainAggregator { - int256 public s_answer; - bool public newRoundCalled; - - function setLatestAnswer(int256 answer) public { - s_answer = answer; - } - - function latestAnswer() public view returns (int256) { - return s_answer; - } - - function requestNewRound() external override returns (uint80) { - newRoundCalled = true; - return 1; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol deleted file mode 100644 index c48f028..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockAggregatorProxy.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {IAggregatorProxy} from "../HeartbeatRequester.sol"; - -contract MockAggregatorProxy is IAggregatorProxy { - address internal s_aggregator; - - constructor(address _aggregator) { - s_aggregator = _aggregator; - } - - function updateAggregator(address _aggregator) external { - s_aggregator = _aggregator; - } - - function aggregator() external view override returns (address) { - return s_aggregator; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol deleted file mode 100644 index 2f21780..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockKeeperRegistry2_1.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import "../interfaces/IAutomationRegistryConsumer.sol"; - -contract MockKeeperRegistry2_1 is IAutomationRegistryConsumer { - uint96 balance; - uint96 minBalance; - - constructor() {} - - function getBalance(uint256 id) external view override returns (uint96) { - return balance; - } - - function getMinBalance(uint256 id) external view override returns (uint96) { - return minBalance; - } - - function cancelUpkeep(uint256 id) external override {} - - function pauseUpkeep(uint256 id) external override {} - - function unpauseUpkeep(uint256 id) external override {} - - function updateCheckData(uint256 id, bytes calldata newCheckData) external {} - - function addFunds(uint256 id, uint96 amount) external override {} - - function withdrawFunds(uint256 id, address to) external override {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol deleted file mode 100644 index 17899f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/mocks/MockUpkeep.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract MockUpkeep { - bool public shouldCheckRevert; - bool public shouldPerformRevert; - bool public checkResult = true; - bytes public performData; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - - event UpkeepPerformedWith(bytes upkeepData); - error CheckRevert(); - error PerformRevert(); - - function setShouldCheckRevert(bool value) public { - shouldCheckRevert = value; - } - - function setShouldPerformRevert(bool value) public { - shouldPerformRevert = value; - } - - function setCheckResult(bool value) public { - checkResult = value; - } - - function setPerformData(bytes calldata data) public { - performData = data; - } - - function setCheckGasToBurn(uint256 value) public { - checkGasToBurn = value; - } - - function setPerformGasToBurn(uint256 value) public { - performGasToBurn = value; - } - - function checkUpkeep(bytes calldata) external view returns (bool callable, bytes memory executedata) { - if (shouldCheckRevert) revert CheckRevert(); - uint256 startGas = gasleft(); - while (startGas - gasleft() < checkGasToBurn) {} // burn gas - return (checkResult, performData); - } - - function performUpkeep(bytes calldata data) external { - if (shouldPerformRevert) revert PerformRevert(); - uint256 startGas = gasleft(); - while (startGas - gasleft() < performGasToBurn) {} // burn gas - emit UpkeepPerformedWith(data); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol deleted file mode 100644 index d9a8c3b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationForwarder.t.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {AutomationForwarder} from "../AutomationForwarder.sol"; -import {AutomationForwarderLogic} from "../AutomationForwarderLogic.sol"; -import "forge-std/Test.sol"; - -// in contracts directory, run -// forge test --match-path src/v0.8/automation/test/AutomationForwarder.t.sol - -contract Target { - function handler() external pure {} - - function handlerRevert() external pure { - revert("revert"); - } -} - -contract AutomationForwarderTestSetUp is Test { - address internal constant REGISTRY = 0x3e19ef5Aaa2606655f5A677A97E085cf3811067c; - address internal constant STRANGER = 0x618fae5d04963B2CEf533F247Eb2C46Bf1801D3b; - - IAutomationForwarder internal forwarder; - address internal TARGET; - - function setUp() public { - TARGET = address(new Target()); - AutomationForwarderLogic logicContract = new AutomationForwarderLogic(); - forwarder = IAutomationForwarder(address(new AutomationForwarder(TARGET, REGISTRY, address(logicContract)))); - } -} - -contract AutomationForwarderTest_constructor is AutomationForwarderTestSetUp { - function testInitialValues() external { - assertEq(address(forwarder.getRegistry()), REGISTRY); - assertEq(forwarder.getTarget(), TARGET); - } - - function testTypeAndVersion() external { - assertEq(forwarder.typeAndVersion(), "AutomationForwarder 1.0.0"); - } -} - -contract AutomationForwarderTest_forward is AutomationForwarderTestSetUp { - function testOnlyCallableByTheRegistry() external { - vm.prank(REGISTRY); - forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); - vm.prank(STRANGER); - vm.expectRevert(); - forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); - } - - function testReturnsSuccessValueAndGasUsed() external { - vm.startPrank(REGISTRY); - (bool success, uint256 gasUsed) = forwarder.forward(100000, abi.encodeWithSelector(Target.handler.selector)); - assertTrue(success); - assertGt(gasUsed, 0); - (success, gasUsed) = forwarder.forward(100000, abi.encodeWithSelector(Target.handlerRevert.selector)); - assertFalse(success); - assertGt(gasUsed, 0); - } -} - -contract AutomationForwarderTest_updateRegistry is AutomationForwarderTestSetUp { - function testOnlyCallableByTheActiveRegistry() external { - address newRegistry = address(1); - vm.startPrank(REGISTRY); - forwarder.updateRegistry(newRegistry); - assertEq(address(forwarder.getRegistry()), newRegistry); - vm.expectRevert(); - forwarder.updateRegistry(REGISTRY); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol deleted file mode 100644 index f3eafc0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/AutomationRegistry2_2.t.sol +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationForwarderLogic} from "../AutomationForwarderLogic.sol"; -import {BaseTest} from "./BaseTest.t.sol"; -import {AutomationRegistry2_2} from "../v2_2/AutomationRegistry2_2.sol"; -import {AutomationRegistryBase2_2} from "../v2_2/AutomationRegistryBase2_2.sol"; -import {AutomationRegistryLogicA2_2} from "../v2_2/AutomationRegistryLogicA2_2.sol"; -import {AutomationRegistryLogicB2_2} from "../v2_2/AutomationRegistryLogicB2_2.sol"; -import {IAutomationRegistryMaster} from "../interfaces/v2_2/IAutomationRegistryMaster.sol"; -import {ChainModuleBase} from "../chains/ChainModuleBase.sol"; - -contract AutomationRegistry2_2_SetUp is BaseTest { - address internal constant LINK_ETH_FEED = 0x1111111111111111111111111111111111111110; - address internal constant FAST_GAS_FEED = 0x1111111111111111111111111111111111111112; - address internal constant LINK_TOKEN = 0x1111111111111111111111111111111111111113; - address internal constant ZERO_ADDRESS = address(0); - - // Signer private keys used for these test - uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; - uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; - uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; - - uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 - uint8 internal constant F = 1; - - address[] internal s_valid_signers; - address[] internal s_valid_transmitters; - address[] internal s_registrars; - - IAutomationRegistryMaster internal registryMaster; - - function setUp() public override { - s_valid_transmitters = new address[](4); - for (uint160 i = 0; i < 4; ++i) { - s_valid_transmitters[i] = address(4 + i); - } - - s_valid_signers = new address[](4); - s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 - s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 - s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b - s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 - - s_registrars = new address[](1); - s_registrars[0] = 0x3a0eDE26aa188BFE00b9A0C9A431A1a0CA5f7966; - - AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); - AutomationRegistryLogicB2_2 logicB2_2 = new AutomationRegistryLogicB2_2( - LINK_TOKEN, - LINK_ETH_FEED, - FAST_GAS_FEED, - address(forwarderLogic), - ZERO_ADDRESS - ); - AutomationRegistryLogicA2_2 logicA2_2 = new AutomationRegistryLogicA2_2(logicB2_2); - registryMaster = IAutomationRegistryMaster( - address(new AutomationRegistry2_2(AutomationRegistryLogicB2_2(address(logicA2_2)))) - ); - } -} - -contract AutomationRegistry2_2_LatestConfigDetails is AutomationRegistry2_2_SetUp { - function testGet() public { - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registryMaster.latestConfigDetails(); - assertEq(configCount, 0); - assertEq(blockNumber, 0); - assertEq(configDigest, ""); - } -} - -contract AutomationRegistry2_2_CheckUpkeep is AutomationRegistry2_2_SetUp { - function testPreventExecutionOnCheckUpkeep() public { - uint256 id = 1; - bytes memory triggerData = abi.encodePacked("trigger_data"); - - // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry - // Expecting a revert since the tx.origin is not address(0) - vm.expectRevert(abi.encodeWithSelector(IAutomationRegistryMaster.OnlySimulatedBackend.selector)); - registryMaster.checkUpkeep(id, triggerData); - } -} - -contract AutomationRegistry2_2_SetConfig is AutomationRegistry2_2_SetUp { - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - function testSetConfigSuccess() public { - (uint32 configCount, , ) = registryMaster.latestConfigDetails(); - assertEq(configCount, 0); - ChainModuleBase module = new ChainModuleBase(); - - AutomationRegistryBase2_2.OnchainConfig memory cfg = AutomationRegistryBase2_2.OnchainConfig({ - paymentPremiumPPB: 10_000, - flatFeeMicroLink: 40_000, - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 0, - minUpkeepSpend: 0, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 200_000_000_000, - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: s_registrars, - upkeepPrivilegeManager: 0xD9c855F08A7e460691F41bBDDe6eC310bc0593D8, - chainModule: module, - reorgProtectionEnabled: true - }); - bytes memory onchainConfigBytes = abi.encode(cfg); - - uint256 a = 1234; - address b = address(0); - bytes memory offchainConfigBytes = abi.encode(a, b); - bytes32 configDigest = _configDigestFromConfigData( - block.chainid, - address(registryMaster), - ++configCount, - s_valid_signers, - s_valid_transmitters, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - 0, - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registryMaster.setConfig( - s_valid_signers, - s_valid_transmitters, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registryMaster.getState(); - - assertEq(signers, s_valid_signers); - assertEq(transmitters, s_valid_transmitters); - assertEq(f, F); - } - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol deleted file mode 100644 index ecba652..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/BaseTest.t.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "forge-std/Test.sol"; - -contract BaseTest is Test { - address internal OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - address internal constant STRANGER = address(999); - - function setUp() public virtual { - vm.startPrank(OWNER); - deal(OWNER, 1e20); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol deleted file mode 100644 index caac639..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/HeartbeatRequester.t.sol +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {HeartbeatRequester, IAggregatorProxy} from "../HeartbeatRequester.sol"; -import {MockAggregator} from "../mocks/MockAggregator.sol"; -import {MockAggregatorProxy} from "../mocks/MockAggregatorProxy.sol"; -import {BaseTest} from "./BaseTest.t.sol"; - -// from contracts directory, -// forge test --match-path src/v0.8/automation/test/HeartbeatRequester.t.sol - -contract HeartbeatRequesterSetUp is BaseTest { - HeartbeatRequester internal heartbeatRequester; - MockAggregator internal aggregator; - IAggregatorProxy internal aggregatorProxy; - MockAggregator internal aggregator2; - IAggregatorProxy internal aggregatorProxy2; - - event HeartbeatPermitted(address indexed permittedCaller, address newProxy, address oldProxy); - event HeartbeatRemoved(address indexed permittedCaller, address removedProxy); - error HeartbeatNotPermitted(); - - function setUp() public override { - BaseTest.setUp(); - heartbeatRequester = new HeartbeatRequester(); - aggregator = new MockAggregator(); - aggregatorProxy = IAggregatorProxy(new MockAggregatorProxy(address(aggregator))); - aggregator2 = new MockAggregator(); - aggregatorProxy2 = IAggregatorProxy(new MockAggregatorProxy(address(aggregator2))); - } -} - -contract HeartbeatRequester_permitHeartbeat is HeartbeatRequesterSetUp { - function testBasicSuccess() public { - vm.expectEmit(); - emit HeartbeatPermitted(STRANGER, address(aggregatorProxy), address(0)); - heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); - - vm.expectEmit(); - emit HeartbeatPermitted(STRANGER, address(aggregatorProxy2), address(aggregatorProxy)); - heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy2); - } - - function testBasicDeployerSuccess() public { - vm.expectEmit(); - emit HeartbeatPermitted(OWNER, address(aggregatorProxy), address(0)); - heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy); - - vm.expectEmit(); - emit HeartbeatPermitted(OWNER, address(aggregatorProxy2), address(aggregatorProxy)); - heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy2); - } - - function testOnlyCallableByOwnerReverts() public { - vm.expectRevert(bytes("Only callable by owner")); - changePrank(STRANGER); - heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); - } -} - -contract HeartbeatRequester_removeHeartbeat is HeartbeatRequesterSetUp { - function testBasicSuccess() public { - vm.expectEmit(); - emit HeartbeatPermitted(STRANGER, address(aggregatorProxy), address(0)); - heartbeatRequester.permitHeartbeat(STRANGER, aggregatorProxy); - - vm.expectEmit(); - emit HeartbeatRemoved(STRANGER, address(aggregatorProxy)); - heartbeatRequester.removeHeartbeat(STRANGER); - } - - function testRemoveNoPermitsSuccess() public { - vm.expectEmit(); - emit HeartbeatRemoved(STRANGER, address(0)); - heartbeatRequester.removeHeartbeat(STRANGER); - } - - function testOnlyCallableByOwnerReverts() public { - vm.expectRevert(bytes("Only callable by owner")); - changePrank(STRANGER); - heartbeatRequester.removeHeartbeat(address(this)); - } -} - -contract HeartbeatRequester_getAggregatorRequestHeartbeat is HeartbeatRequesterSetUp { - function testBasicSuccess() public { - vm.expectEmit(); - emit HeartbeatPermitted(OWNER, address(aggregatorProxy), address(0)); - heartbeatRequester.permitHeartbeat(OWNER, aggregatorProxy); - heartbeatRequester.getAggregatorAndRequestHeartbeat(address(aggregatorProxy)); - // getter for newRoundCalled value - bool val = aggregator.newRoundCalled(); - assertEq(val, true); - } - - function testHeartbeatNotPermittedReverts() public { - bytes32 hashedReason = keccak256(abi.encodePacked("HeartbeatNotPermitted()")); - bytes memory revertMessage = bytes32ToBytes(hashedReason); - vm.expectRevert(revertMessage); - heartbeatRequester.getAggregatorAndRequestHeartbeat(address(aggregatorProxy)); - bool val = aggregator.newRoundCalled(); - assertFalse(val); - } - - function bytes32ToBytes(bytes32 _bytes32) public pure returns (bytes memory) { - bytes memory bytesArray = new bytes(4); - for (uint256 i; i < 4; ++i) { - bytesArray[i] = _bytes32[i]; - } - return bytesArray; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol deleted file mode 100644 index 4018c76..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/MercuryRegistry.t.sol +++ /dev/null @@ -1,336 +0,0 @@ -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; -import "../dev/MercuryRegistry.sol"; -import "../dev/MercuryRegistryBatchUpkeep.sol"; -import "../interfaces/StreamsLookupCompatibleInterface.sol"; - -contract MercuryRegistryTest is Test { - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - int192 internal constant DEVIATION_THRESHOLD = 10_000; // 1% - uint32 internal constant STALENESS_SECONDS = 3600; // 1 hour - - address s_verifier = 0x60448B880c9f3B501af3f343DA9284148BD7D77C; - - string[] feedIds; - string s_BTCUSDFeedId = "0x6962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb2"; - string s_ETHUSDFeedId = "0xf753e1201d54ac94dfd9334c542562ff7e42993419a661261d010af0cbfd4e34"; - MercuryRegistry s_testRegistry; - - // Feed: BTC/USD - // Date: Tuesday, August 22, 2023 7:29:28 PM - // Price: $25,857.11126720 - bytes s_august22BTCUSDMercuryReport = - hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad00000000000000000000000000000000000000000000000000000000014cb94e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e50c980000000000000000000000000000000000000000000000000000025a0864a8c00000000000000000000000000000000000000000000000000000025a063481720000000000000000000000000000000000000000000000000000025a0a94d00f000000000000000000000000000000000000000000000000000000000226181f4733a6d98892d1821771c041d5d69298210fdca9d643ad74477423b6a3045647000000000000000000000000000000000000000000000000000000000226181f0000000000000000000000000000000000000000000000000000000064e50c9700000000000000000000000000000000000000000000000000000000000000027f3056b1b71dd516037afd2e636f8afb39853f5cb3ccaa4b02d6f9a2a64622534e94aa1f794f6a72478deb7e0eb2942864b7fac76d6e120bd809530b1b74a32b00000000000000000000000000000000000000000000000000000000000000027bd3b385c0812dfcad2652d225410a014a0b836cd9635a6e7fb404f65f7a912f0b193db57e5c4f38ce71f29170f7eadfa94d972338858bacd59ab224245206db"; - - // Feed: BTC/USD - // Date: Wednesday, August 23, 2023 7:55:02 PM - // Price: $26,720.37346975 - bytes s_august23BTCUSDMercuryReport = - hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad000000000000000000000000000000000000000000000000000000000159a630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e664160000000000000000000000000000000000000000000000000000026e21d63e9f0000000000000000000000000000000000000000000000000000026e2147576a0000000000000000000000000000000000000000000000000000026e226525d30000000000000000000000000000000000000000000000000000000002286ce7c44fa27f67f6dd0a8bb40c12f0f050231845789f022a82aa5f4b3fe5bf2068fb0000000000000000000000000000000000000000000000000000000002286ce70000000000000000000000000000000000000000000000000000000064e664150000000000000000000000000000000000000000000000000000000000000002e9c5857631172082a47a20aa2fd9f580c1c48275d030c17a2dff77da04f88708ce776ef74c04b9ef6ba87c56d8f8c57e80ddd5298b477d60dd49fb8120f1b9ce000000000000000000000000000000000000000000000000000000000000000248624e0e2341cdaf989098f8b3dee2660b792b24e5251d6e48e3abe0a879c0683163a3a199969010e15353a99926d113f6d4cbab9d82ae90a159af9f74f8c157"; - - // Feed: BTC/USD - // Date: Wednesday, August 23, 2023 8:13:28 PM - // Price: $26,559.67100000 - bytes s_august23BTCUSDMercuryReport_2 = - hex"0006a2f7f9b6c10385739c687064aa1e457812927f59446cccddf7740cc025ad000000000000000000000000000000000000000000000000000000000159d009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000280010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001206962e629c3a0f5b7e3e9294b0c283c9b20f94f1c89c8ba8c1ee4650738f20fb20000000000000000000000000000000000000000000000000000000064e668690000000000000000000000000000000000000000000000000000026a63f9bc600000000000000000000000000000000000000000000000000000026a635984c00000000000000000000000000000000000000000000000000000026a67bb929d00000000000000000000000000000000000000000000000000000000022873e999d3ff9b644bba530af933dfaa6c59e31c3e232fcaa1e5f7304e2e79d939da1900000000000000000000000000000000000000000000000000000000022873e80000000000000000000000000000000000000000000000000000000064e66868000000000000000000000000000000000000000000000000000000000000000247c21657a6c2795986e95081876bf8b5f24bf72abd2dc4c601e7c96d654bcf543b5bb730e3d4736a308095e4531e7c03f581ac364f0889922ba3ae24b7cf968000000000000000000000000000000000000000000000000000000000000000020d3037d9f55256a001a2aa79ea746526c7cb36747e1deb4c804311394b4027667e5b711bcecfe60632e86cf8e83c28d1465e2d8d90bc0638dad8347f55488e8e"; - - // Feed: ETH/USD - // Date: Wednesday, August 23, 2023 7:55:01 PM - // Price: $1,690.76482169 - bytes s_august23ETHUSDMercuryReport = - hex"0006c41ec94138ae62cce3f1a2b852e42fe70359502fa7b6bdbf81207970d88e00000000000000000000000000000000000000000000000000000000016d874d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120f753e1201d54ac94dfd9334c542562ff7e42993419a661261d010af0cbfd4e340000000000000000000000000000000000000000000000000000000064e66415000000000000000000000000000000000000000000000000000000275dbe6079000000000000000000000000000000000000000000000000000000275c905eba000000000000000000000000000000000000000000000000000000275e5693080000000000000000000000000000000000000000000000000000000002286ce7c44fa27f67f6dd0a8bb40c12f0f050231845789f022a82aa5f4b3fe5bf2068fb0000000000000000000000000000000000000000000000000000000002286ce70000000000000000000000000000000000000000000000000000000064e664150000000000000000000000000000000000000000000000000000000000000002a2b01f7741563cfe305efaec43e56cd85731e3a8e2396f7c625bd16adca7b39c97805b6170adc84d065f9d68c87104c3509aeefef42c0d1711e028ace633888000000000000000000000000000000000000000000000000000000000000000025d984ad476bda9547cf0f90d32732dc5a0d84b0e2fe9795149b786fb05332d4c092e278b4dddeef45c070b818c6e221db2633b573d616ef923c755a145ea099c"; - - // Feed: USDC/USD - // Date: Wednesday, August 30, 2023 5:05:01 PM - // Price: $1.00035464 - bytes s_august30USDCUSDMercuryReport = - hex"0006970c13551e2a390246f5eccb62b9be26848e72026830f4688f49201b5a050000000000000000000000000000000000000000000000000000000001c89843000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120a5b07943b89e2c278fc8a2754e2854316e03cb959f6d323c2d5da218fb6b0ff80000000000000000000000000000000000000000000000000000000064ef69fa0000000000000000000000000000000000000000000000000000000005f5da000000000000000000000000000000000000000000000000000000000005f5b0f80000000000000000000000000000000000000000000000000000000005f5f8b0000000000000000000000000000000000000000000000000000000000240057307d0a0421d25328cb6dcfc5d0e211ff0580baaaf104e9877fc52cf2e8ec0aa7d00000000000000000000000000000000000000000000000000000000024005730000000000000000000000000000000000000000000000000000000064ef69fa0000000000000000000000000000000000000000000000000000000000000002b9e7fb46f1e9d22a1156024dc2bbf2bc6d337e0a2d78aaa3fb6e43b880217e5897732b516e39074ef4dcda488733bfee80c0a10714b94621cd93df6842373cf5000000000000000000000000000000000000000000000000000000000000000205ca5f8da9d6ae01ec6d85c681e536043323405b3b8a15e4d2a288e02dac32f10b2294593e270a4bbf53b0c4978b725293e85e49685f1d3ce915ff670ab6612f"; - - function setUp() public virtual { - // Set owner, and fork Arbitrum Goerli Testnet (chain ID 421613). - // The fork is only used with the `FORK_TEST` flag enabeld, as to not disrupt CI. For CI, a mock verifier is used instead. - vm.startPrank(OWNER); - try vm.envBool("FORK_TEST") returns (bool /* fork testing enabled */) { - vm.selectFork(vm.createFork("https://goerli-rollup.arbitrum.io/rpc")); - } catch { - s_verifier = address(new MockVerifierProxy()); - } - vm.chainId(31337); // restore chain Id - - // Use a BTC feed and ETH feed. - feedIds = new string[](2); - feedIds[0] = s_BTCUSDFeedId; - feedIds[1] = s_ETHUSDFeedId; - - // Deviation threshold and staleness are the same for all feeds. - int192[] memory thresholds = new int192[](1); - thresholds[0] = DEVIATION_THRESHOLD; - uint32[] memory stalenessSeconds = new uint32[](1); - stalenessSeconds[0] = STALENESS_SECONDS; - - // Initialize with BTC feed. - string[] memory initialFeedIds = new string[](1); - initialFeedIds[0] = feedIds[0]; - string[] memory initialFeedNames = new string[](1); - initialFeedNames[0] = "BTC/USD"; - s_testRegistry = new MercuryRegistry( - initialFeedIds, - initialFeedNames, - thresholds, - stalenessSeconds, - address(0) // verifier unset - ); - s_testRegistry.setVerifier(s_verifier); // set verifier - - // Add ETH feed. - string[] memory addedFeedIds = new string[](1); - addedFeedIds[0] = feedIds[1]; - string[] memory addedFeedNames = new string[](1); - addedFeedNames[0] = "ETH/USD"; - s_testRegistry.addFeeds(addedFeedIds, addedFeedNames, thresholds, stalenessSeconds); - } - - function testMercuryRegistry() public { - // Check upkeep, receive Mercury revert. - uint256 blockNumber = block.number; - vm.expectRevert( - abi.encodeWithSelector( - StreamsLookupCompatibleInterface.StreamsLookup.selector, - "feedIdHex", // feedParamKey - feedIds, // feed Ids - "blockNumber", // timeParamKey - blockNumber, // block number on which request is occuring - "" // extra data - ) - ); - s_testRegistry.checkUpkeep(""); - - // Obtain mercury report off-chain (for August 22 BTC/USD price) - bytes[] memory values = new bytes[](1); - values[0] = s_august22BTCUSDMercuryReport; - - // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. - (bool shouldPerformUpkeep, bytes memory performData) = s_testRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, true); - - // Perform upkeep to update on-chain state. - s_testRegistry.performUpkeep(performData); - - // Check state of BTC/USD feed to ensure update was propagated. - bytes memory oldPerformData; - uint32 oldObservationsTimestamp; - { - // scoped to prevent stack-too-deep error - ( - uint32 observationsTimestamp, - int192 price, - int192 bid, - int192 ask, - string memory feedName, - string memory localFeedId, - bool active, - int192 deviationPercentagePPM, - uint32 stalenessSeconds - ) = s_testRegistry.s_feedMapping(s_BTCUSDFeedId); - assertEq(observationsTimestamp, 1692732568); // Tuesday, August 22, 2023 7:29:28 PM - assertEq(bid, 2585674416498); // $25,856.74416498 - assertEq(price, 2585711126720); // $25,857.11126720 - assertEq(ask, 2585747836943); // $25,857.47836943 - assertEq(feedName, "BTC/USD"); - assertEq(localFeedId, s_BTCUSDFeedId); - assertEq(active, true); - assertEq(deviationPercentagePPM, DEVIATION_THRESHOLD); - assertEq(stalenessSeconds, STALENESS_SECONDS); - - // Save this for later in the test. - oldPerformData = performData; - oldObservationsTimestamp = observationsTimestamp; - } - // Obtain mercury report off-chain (for August 23 BTC/USD price & ETH/USD price) - values = new bytes[](2); - values[0] = s_august23BTCUSDMercuryReport; - values[1] = s_august23ETHUSDMercuryReport; - - // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. - (shouldPerformUpkeep, performData) = s_testRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, true); - - // Perform upkeep to update on-chain state. - s_testRegistry.performUpkeep(performData); - - // Make a batch request for both the BTC/USD feed data and the ETH/USD feed data. - MercuryRegistry.Feed[] memory feeds = s_testRegistry.getLatestFeedData(feedIds); - - // Check state of BTC/USD feed to ensure update was propagated. - assertEq(feeds[0].observationsTimestamp, 1692820502); // Wednesday, August 23, 2023 7:55:02 PM - assertEq(feeds[0].bid, 2672027981674); // $26,720.27981674 - assertEq(feeds[0].price, 2672037346975); // $26,720.37346975 - assertEq(feeds[0].ask, 2672046712275); // $26,720.46712275 - assertEq(feeds[0].feedName, "BTC/USD"); - assertEq(feeds[0].feedId, s_BTCUSDFeedId); - - // Check state of ETH/USD feed to ensure update was propagated. - assertEq(feeds[1].observationsTimestamp, 1692820501); // Wednesday, August 23, 2023 7:55:01 PM - assertEq(feeds[1].bid, 169056689850); // $1,690.56689850 - assertEq(feeds[1].price, 169076482169); // $1,690.76482169 - assertEq(feeds[1].ask, 169086456584); // $16,90.86456584 - assertEq(feeds[1].feedName, "ETH/USD"); - assertEq(feeds[1].feedId, s_ETHUSDFeedId); - assertEq(feeds[1].active, true); - assertEq(feeds[1].deviationPercentagePPM, DEVIATION_THRESHOLD); - assertEq(feeds[1].stalenessSeconds, STALENESS_SECONDS); - - // Obtain mercury report off-chain for August 23 BTC/USD price (second report of the day). - // The price of this incoming report will not deviate enough from the on-chain value to trigger an update, - // nor is the on-chain data stale enough. - values = new bytes[](1); - values[0] = s_august23BTCUSDMercuryReport_2; - - // Pass the obtained mercury report into checkCallback, to assert that an update is not warranted. - (shouldPerformUpkeep, performData) = s_testRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, false); - - // Ensure stale reports cannot be included. - vm.expectRevert( - abi.encodeWithSelector( - MercuryRegistry.StaleReport.selector, - feedIds[0], - feeds[0].observationsTimestamp, - oldObservationsTimestamp - ) - ); - s_testRegistry.performUpkeep(oldPerformData); - - // Ensure reports for inactive feeds cannot be included. - bytes[] memory inactiveFeedReports = new bytes[](1); - inactiveFeedReports[0] = s_august30USDCUSDMercuryReport; - bytes memory lookupData = ""; - vm.expectRevert( - abi.encodeWithSelector( - MercuryRegistry.FeedNotActive.selector, - "0xa5b07943b89e2c278fc8a2754e2854316e03cb959f6d323c2d5da218fb6b0ff8" // USDC/USD feed id - ) - ); - s_testRegistry.performUpkeep(abi.encode(inactiveFeedReports, lookupData)); - } - - // Below are the same tests as `testMercuryRegistry`, except done via a batching Mercury registry that - // consumes the test registry. This is to assert that batching can be accomplished by multiple different - // upkeep jobs, which can populate the same - function testMercuryRegistryBatchUpkeep() public { - MercuryRegistryBatchUpkeep batchedRegistry = new MercuryRegistryBatchUpkeep( - address(s_testRegistry), // use the test registry as master registry - 0, // start batch at index 0. - 50 // end batch beyond length of feed Ids (take responsibility for all feeds) - ); - // Check upkeep, receive Mercury revert. - uint256 blockNumber = block.number; - vm.expectRevert( - abi.encodeWithSelector( - StreamsLookupCompatibleInterface.StreamsLookup.selector, - "feedIdHex", // feedParamKey - feedIds, // feed Ids - "blockNumber", // timeParamKey - blockNumber, // block number on which request is occuring - "" // extra data - ) - ); - batchedRegistry.checkUpkeep(""); - - // Obtain mercury report off-chain (for August 22 BTC/USD price) - bytes[] memory values = new bytes[](1); - values[0] = s_august22BTCUSDMercuryReport; - - // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. - (bool shouldPerformUpkeep, bytes memory performData) = batchedRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, true); - - // Perform upkeep to update on-chain state. - batchedRegistry.performUpkeep(performData); - - // Check state of BTC/USD feed to ensure update was propagated. - ( - uint32 observationsTimestamp, - int192 price, - int192 bid, - int192 ask, - string memory feedName, - string memory localFeedId, - bool active, - int192 deviationPercentagePPM, - uint32 stalenessSeconds - ) = s_testRegistry.s_feedMapping(s_BTCUSDFeedId); - assertEq(observationsTimestamp, 1692732568); // Tuesday, August 22, 2023 7:29:28 PM - assertEq(bid, 2585674416498); // $25,856.74416498 - assertEq(price, 2585711126720); // $25,857.11126720 - assertEq(ask, 2585747836943); // $25,857.47836943 - assertEq(feedName, "BTC/USD"); - assertEq(localFeedId, s_BTCUSDFeedId); - assertEq(active, true); - assertEq(deviationPercentagePPM, DEVIATION_THRESHOLD); - assertEq(stalenessSeconds, STALENESS_SECONDS); - - // Obtain mercury report off-chain (for August 23 BTC/USD price & ETH/USD price) - values = new bytes[](2); - values[0] = s_august23BTCUSDMercuryReport; - values[1] = s_august23ETHUSDMercuryReport; - - // Pass the obtained mercury report into checkCallback, to assert that an update is warranted. - (shouldPerformUpkeep, performData) = batchedRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, true); - - // Perform upkeep to update on-chain state, but with not enough gas to update both feeds. - batchedRegistry.performUpkeep{gas: 250_000}(performData); - - // Make a batch request for both the BTC/USD feed data and the ETH/USD feed data. - MercuryRegistry.Feed[] memory feeds = s_testRegistry.getLatestFeedData(feedIds); - - // Check state of BTC/USD feed to ensure update was propagated. - assertEq(feeds[0].observationsTimestamp, 1692820502); // Wednesday, August 23, 2023 7:55:02 PM - assertEq(feeds[0].bid, 2672027981674); // $26,720.27981674 - assertEq(feeds[0].price, 2672037346975); // $26,720.37346975 - assertEq(feeds[0].ask, 2672046712275); // $26,720.46712275 - assertEq(feeds[0].feedName, "BTC/USD"); - assertEq(feeds[0].feedId, s_BTCUSDFeedId); - - // Check state of ETH/USD feed to observe that the update was not propagated. - assertEq(feeds[1].observationsTimestamp, 0); - assertEq(feeds[1].bid, 0); - assertEq(feeds[1].price, 0); - assertEq(feeds[1].ask, 0); - assertEq(feeds[1].feedName, "ETH/USD"); - assertEq(feeds[1].feedId, s_ETHUSDFeedId); - assertEq(feeds[1].active, true); - assertEq(feeds[1].deviationPercentagePPM, DEVIATION_THRESHOLD); - assertEq(feeds[1].stalenessSeconds, STALENESS_SECONDS); - - // Try again, with sufficient gas to update both feeds. - batchedRegistry.performUpkeep{gas: 2_500_000}(performData); - feeds = s_testRegistry.getLatestFeedData(feedIds); - - // Check state of ETH/USD feed to ensure update was propagated. - assertEq(feeds[1].observationsTimestamp, 1692820501); // Wednesday, August 23, 2023 7:55:01 PM - assertEq(feeds[1].bid, 169056689850); // $1,690.56689850 - assertEq(feeds[1].price, 169076482169); // $1,690.76482169 - assertEq(feeds[1].ask, 169086456584); // $16,90.86456584 - assertEq(feeds[1].feedName, "ETH/USD"); - assertEq(feeds[1].feedId, s_ETHUSDFeedId); - - // Obtain mercury report off-chain for August 23 BTC/USD price (second report of the day). - // The price of this incoming report will not deviate enough from the on-chain value to trigger an update. - values = new bytes[](1); - values[0] = s_august23BTCUSDMercuryReport_2; - - // Pass the obtained mercury report into checkCallback, to assert that an update is not warranted. - (shouldPerformUpkeep, performData) = batchedRegistry.checkCallback(values, bytes("")); - assertEq(shouldPerformUpkeep, false); - } -} - -contract MockVerifierProxy is IVerifierProxy { - function verify(bytes calldata payload) external payable override returns (bytes memory) { - (, bytes memory reportData, , , ) = abi.decode(payload, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); - return reportData; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol deleted file mode 100644 index 1225e6e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/WETH9.sol +++ /dev/null @@ -1,93 +0,0 @@ -// Submitted for verification at Etherscan.io on 2017-12-12 - -// Copyright (C) 2015, 2016, 2017 Dapphub - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -pragma solidity 0.8.19; - -contract WETH9 { - string public name = "Wrapped Ether"; - string public symbol = "WETH"; - uint8 public decimals = 18; - - event Approval(address indexed src, address indexed guy, uint256 wad); - event Transfer(address indexed src, address indexed dst, uint256 wad); - event Deposit(address indexed dst, uint256 wad); - event Withdrawal(address indexed src, uint256 wad); - - error InsufficientBalance(); - - mapping(address => uint256) public balanceOf; - mapping(address => mapping(address => uint256)) public allowance; - - receive() external payable { - _deposit(); - } - - function _deposit() internal { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - - function deposit() external payable { - _deposit(); - } - - function mint(address account, uint256 amount) public { - balanceOf[account] += amount; - } - - function withdraw(uint256 wad) external { - if (balanceOf[msg.sender] < wad) { - revert InsufficientBalance(); - } - balanceOf[msg.sender] -= wad; - payable(msg.sender).call{value: wad}(""); - emit Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint256) { - return address(this).balance; - } - - function approve(address guy, uint256 wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - function transfer(address dst, uint256 wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint256 wad) public returns (bool) { - if (balanceOf[src] < wad) { - revert InsufficientBalance(); - } - - if (src != msg.sender && allowance[src][msg.sender] != type(uint128).max) { - if (allowance[src][msg.sender] < wad) { - revert InsufficientBalance(); - } - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol deleted file mode 100644 index 171e4e3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol +++ /dev/null @@ -1,409 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {IAutomationRegistryMaster2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; -import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; - -// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistrar2_3.t.sol - -contract SetUp is BaseTest { - IAutomationRegistryMaster2_3 internal registry; - AutomationRegistrar2_3 internal registrar; - - function setUp() public override { - super.setUp(); - vm.startPrank(OWNER); - (registry, registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - vm.stopPrank(); // reset identity at the start of each test - } -} - -contract CancelUpkeep is SetUp { - function testUSDToken_happy() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); - usdToken18.approve(address(registrar), amount); - - AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: usdToken18, - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - // default is auto approve off - registrar.registerUpkeep(registrationParams); - - assertEq(usdToken18.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - - uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); - uint256 startUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); - - // cancel the upkeep - vm.startPrank(OWNER); - bytes32 hash = keccak256(abi.encode(registrationParams)); - registrar.cancel(hash); - - uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); - uint256 endUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN); - - assertEq(startRegistrarBalance - amount, endRegistrarBalance); - assertEq(startUpkeepAdminBalance + amount, endUpkeepAdminBalance); - } -} - -contract ApproveUpkeep is SetUp { - function testUSDToken_happy() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); - usdToken18.approve(address(registrar), amount); - - AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: usdToken18, - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - // default is auto approve off - registrar.registerUpkeep(registrationParams); - - assertEq(usdToken18.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - - uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar)); - uint256 startRegistryBalance = usdToken18.balanceOf(address(registry)); - - // approve the upkeep - vm.startPrank(OWNER); - registrar.approve(registrationParams); - - uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar)); - uint256 endRegistryBalance = usdToken18.balanceOf(address(registry)); - - assertEq(startRegistrarBalance - amount, endRegistrarBalance); - assertEq(startRegistryBalance + amount, endRegistryBalance); - } -} - -contract RegisterUpkeep is SetUp { - function testLink_autoApproveOff_happy() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); - linkToken.approve(address(registrar), amount); - - registrar.registerUpkeep( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(linkToken)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(linkToken.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - } - - function testUSDToken_autoApproveOff_happy() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); - usdToken18.approve(address(registrar), amount); - - registrar.registerUpkeep( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: usdToken18, - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(usdToken18.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - } - - function testLink_autoApproveOn_happy() external { - vm.startPrank(OWNER); - registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); - - vm.startPrank(UPKEEP_ADMIN); - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); - linkToken.approve(address(registrar), amount); - - registrar.registerUpkeep( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(linkToken)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(linkToken.balanceOf(address(registrar)), 0); - assertEq(linkToken.balanceOf(address(registry)), amount); - assertEq(registry.getNumUpkeeps(), 1); - } - - function testUSDToken_autoApproveOn_happy() external { - vm.startPrank(OWNER); - registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); - - vm.startPrank(UPKEEP_ADMIN); - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); - usdToken18.approve(address(registrar), amount); - - registrar.registerUpkeep( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: usdToken18, - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(usdToken18.balanceOf(address(registrar)), 0); - assertEq(usdToken18.balanceOf(address(registry)), amount); - assertEq(registry.getNumUpkeeps(), 1); - } - - function testNative_autoApproveOn_happy() external { - vm.startPrank(OWNER); - registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); - - vm.startPrank(UPKEEP_ADMIN); - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); - IWrappedNative(address(weth)).approve(address(registrar), amount); - - registrar.registerUpkeep{value: amount}( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: 0, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(weth)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(weth.balanceOf(address(registrar)), 0); - assertEq(weth.balanceOf(address(registry)), amount); - assertEq(registry.getNumUpkeeps(), 1); - } - - // when msg.value is 0, it uses the ERC20 payment path - function testNative_autoApproveOff_msgValue0() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); - IWrappedNative(address(weth)).approve(address(registrar), amount); - - registrar.registerUpkeep( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(weth)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(weth.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - } - - // when msg.value is not 0, it uses the native payment path - function testNative_autoApproveOff_msgValueNot0() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(weth)))); - IWrappedNative(address(weth)).approve(address(registrar), amount); - - registrar.registerUpkeep{value: amount}( - AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: 0, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(weth)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }) - ); - - assertEq(weth.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - } - - function testLink_autoApproveOff_revertOnDuplicateEntry() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); - linkToken.approve(address(registrar), amount * 2); - - AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(linkToken)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - registrar.registerUpkeep(params); - - assertEq(linkToken.balanceOf(address(registrar)), amount); - assertEq(registry.getNumUpkeeps(), 0); - - // attempt to register the same upkeep again - vm.expectRevert(AutomationRegistrar2_3.DuplicateEntry.selector); - registrar.registerUpkeep(params); - } - - function test_revertOnInsufficientPayment() external { - vm.startPrank(UPKEEP_ADMIN); - - // slightly less than the minimum amount - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))) - 1); - linkToken.approve(address(registrar), amount); - - AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(linkToken)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - // attempt to register but revert bc of insufficient payment - vm.expectRevert(AutomationRegistrar2_3.InsufficientPayment.selector); - registrar.registerUpkeep(params); - } - - function test_revertOnInvalidAdminAddress() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken)))); - linkToken.approve(address(registrar), amount); - - AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: ZERO_ADDRESS, // zero address is invalid - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(linkToken)), - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - // attempt to register but revert bc of invalid admin address - vm.expectRevert(AutomationRegistrar2_3.InvalidAdminAddress.selector); - registrar.registerUpkeep(params); - } - - function test_revertOnInvalidBillingToken() external { - vm.startPrank(UPKEEP_ADMIN); - - uint96 amount = 1; - usdToken18_2.approve(address(registrar), amount); - - AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({ - upkeepContract: address(TARGET1), - amount: amount, - adminAddress: UPKEEP_ADMIN, - gasLimit: 10_000, - triggerType: 0, - billingToken: IERC20(address(usdToken18_2)), // unsupported billing token - name: "foobar", - encryptedEmail: "", - checkData: bytes("check data"), - triggerConfig: "", - offchainConfig: "" - }); - - // attempt to register but revert bc of invalid admin address - vm.expectRevert(AutomationRegistrar2_3.InvalidBillingToken.selector); - registrar.registerUpkeep(params); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol deleted file mode 100644 index 41aabf1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol +++ /dev/null @@ -1,2753 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {Vm} from "forge-std/Test.sol"; -import {BaseTest} from "./BaseTest.t.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; -import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; - -// forge test --match-path src/v0.8/automation/test/v2_3/AutomationRegistry2_3.t.sol - -enum Trigger { - CONDITION, - LOG -} - -contract SetUp is BaseTest { - Registry internal registry; - AutomationRegistryBase2_3.OnchainConfig internal config; - bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); - - uint256 internal linkUpkeepID; - uint256 internal linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario - uint256 internal usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals - uint256 internal usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals - uint256 internal nativeUpkeepID; - - function setUp() public virtual override { - super.setUp(); - (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - config = registry.getConfig(); - - vm.startPrank(OWNER); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.startPrank(UPKEEP_ADMIN); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.startPrank(STRANGER); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.stopPrank(); - - linkUpkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - - linkUpkeepID2 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - - usdUpkeepID18 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(usdToken18), - "", - "", - "" - ); - - usdUpkeepID6 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(usdToken6), - "", - "", - "" - ); - - nativeUpkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(weth), - "", - "", - "" - ); - - vm.startPrank(OWNER); - registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); - registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); - registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); - registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); - registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); - vm.stopPrank(); - } -} - -contract LatestConfigDetails is SetUp { - function testGet() public { - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails(); - assertEq(configCount, 1); - assertTrue(blockNumber > 0); - assertNotEq(configDigest, ""); - } -} - -contract CheckUpkeep is SetUp { - function testPreventExecutionOnCheckUpkeep() public { - uint256 id = 1; - bytes memory triggerData = abi.encodePacked("trigger_data"); - - // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry - // Expecting a revert since the tx.origin is not address(0) - vm.expectRevert(abi.encodeWithSelector(Registry.OnlySimulatedBackend.selector)); - registry.checkUpkeep(id, triggerData); - } -} - -contract WithdrawFunds is SetUp { - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - - function test_RevertsWhen_CalledByNonAdmin() external { - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - vm.prank(STRANGER); - registry.withdrawFunds(linkUpkeepID, STRANGER); - } - - function test_RevertsWhen_InvalidRecipient() external { - vm.expectRevert(Registry.InvalidRecipient.selector); - vm.prank(UPKEEP_ADMIN); - registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); - } - - function test_RevertsWhen_UpkeepNotCanceled() external { - vm.expectRevert(Registry.UpkeepNotCanceled.selector); - vm.prank(UPKEEP_ADMIN); - registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); - } - - function test_Happy_Link() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - vm.roll(100 + block.number); - - uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); - uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); - - uint256 upkeepBalance = registry.getBalance(linkUpkeepID); - vm.expectEmit(); - emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); - registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); - - assertEq(registry.getBalance(linkUpkeepID), 0); - assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); - assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); - } - - function test_Happy_USDToken() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(usdUpkeepID6); - vm.roll(100 + block.number); - - uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); - uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); - - uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); - vm.expectEmit(); - emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); - registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); - - assertEq(registry.getBalance(usdUpkeepID6), 0); - assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); - assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); - } -} - -contract AddFunds is SetUp { - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - - // when msg.value is 0, it uses the ERC20 payment path - function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { - vm.startPrank(OWNER); - uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); - uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); - registry.addFunds(nativeUpkeepID, 1); - assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); - assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); - assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); - } - - // when msg.value is not 0, it uses the native payment path - function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { - uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); - uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); - registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored - assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); - assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); - assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); - } - - // it fails when the billing token is not native, but trying to pay with native - function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.addFunds{value: 1}(linkUpkeepID, 0); - } - - function test_RevertsWhen_UpkeepDoesNotExist() public { - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.addFunds(randomNumber(), 1); - } - - function test_RevertsWhen_UpkeepIsCanceled() public { - registry.cancelUpkeep(linkUpkeepID); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.addFunds(linkUpkeepID, 1); - } - - function test_anyoneCanAddFunds() public { - uint256 startAmount = registry.getBalance(linkUpkeepID); - vm.prank(UPKEEP_ADMIN); - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); - vm.prank(STRANGER); - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); - } - - function test_movesFundFromCorrectToken() public { - vm.startPrank(UPKEEP_ADMIN); - - uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); - uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); - uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); - uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); - - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); - assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); - - registry.addFunds(usdUpkeepID18, 2); - assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); - assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); - } - - function test_emitsAnEvent() public { - vm.startPrank(UPKEEP_ADMIN); - vm.expectEmit(); - emit FundsAdded(linkUpkeepID, address(UPKEEP_ADMIN), 100); - registry.addFunds(linkUpkeepID, 100); - } -} - -contract Withdraw is SetUp { - address internal aMockAddress = randomAddress(); - - function testLinkAvailableForPaymentReturnsLinkBalance() public { - uint256 startBalance = linkToken.balanceOf(address(registry)); - int256 startLinkAvailable = registry.linkAvailableForPayment(); - - //simulate a deposit of link to the liquidity pool - _mintLink(address(registry), 1e10); - - //check there's a balance - assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); - - //check the link available has increased by the same amount - assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); - } - - function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { - vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); - registry.withdrawLink(aMockAddress, 1); - } - - function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is 0 balance - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawLink(aMockAddress, 1); - - vm.stopPrank(); - } - - function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is 0 balance - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); - registry.withdrawLink(ZERO_ADDRESS, 1); - - vm.stopPrank(); - } - - function testWithdrawLinkSuccess() public { - //simulate a deposit of link to the liquidity pool - _mintLink(address(registry), 1e10); - uint256 startBalance = linkToken.balanceOf(address(registry)); - - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is a ton of link available - registry.withdrawLink(aMockAddress, 1); - - vm.stopPrank(); - - assertEq(linkToken.balanceOf(address(aMockAddress)), 1); - assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); - } - - function test_WithdrawERC20Fees_RespectsReserveAmount() public { - assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); - } - - function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { - _mintLink(address(registry), 1e10); - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(Registry.InvalidToken.selector); - registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert - registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds - } - - // default is ON_CHAIN mode - function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { - _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance - require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); - require( - registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, - "ERC20AvailableForPayment should be positive" - ); - vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert - _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw - } - - function test_WithdrawERC20Fees_InOffChainMode_Happy() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry); - require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw - - // recipient should get the funds - assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); - } - - function testWithdrawERC20FeeSuccess() public { - // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) - uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); - uint256 startAmount = usdToken18.balanceOf(address(registry)); - _mintERC20_18Decimals(address(registry), 1e10); - - // depositing shouldn't change reserve amount - assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); - - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 USDToken - registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); - - vm.stopPrank(); - - assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); - assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); - assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); - } -} - -contract SetConfig is SetUp { - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - address module = address(new ChainModuleBase()); - - AutomationRegistryBase2_3.OnchainConfig cfg = - AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 0, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: _getRegistrars(), - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: module, - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - function testSetConfigSuccess() public { - (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress = address(usdToken18); - address[] memory billingTokens = new address[](1); - billingTokens[0] = billingTokenAddress; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - bytes memory onchainConfigBytes = abi.encode(cfg); - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - bytes32 configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); - assertEq(config.gasFeePPB, 5_000); - assertEq(config.flatFeeMilliCents, 20_000); - assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config.minSpend, 100_000); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 1); - } - - function testSetConfigMultipleBillingConfigsSuccess() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress1 = address(linkToken); - address billingTokenAddress2 = address(usdToken18); - address[] memory billingTokens = new address[](2); - billingTokens[0] = billingTokenAddress1; - billingTokens[1] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); - assertEq(config1.gasFeePPB, 5_001); - assertEq(config1.flatFeeMilliCents, 20_001); - assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config1.fallbackPrice, 100); - assertEq(config1.minSpend, 100); - - AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); - assertEq(config2.gasFeePPB, 5_002); - assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config2.fallbackPrice, 200); - assertEq(config2.minSpend, 200); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 2); - } - - function testSetConfigTwiceAndLastSetOverwrites() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - // BillingConfig1 - address billingTokenAddress1 = address(usdToken18); - address[] memory billingTokens1 = new address[](1); - billingTokens1[0] = billingTokenAddress1; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs1 = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - - // the first time uses the default onchain config with 2 registrars - bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); - - // set config once - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling1, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig1, , , ) = registry.getState(); - assertEq(onchainConfig1.registrars.length, 2); - - // BillingConfig2 - address billingTokenAddress2 = address(usdToken18); - address[] memory billingTokens2 = new address[](1); - billingTokens2[0] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs2 = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - address[] memory newRegistrars = new address[](3); - newRegistrars[0] = address(uint160(uint256(keccak256("newRegistrar1")))); - newRegistrars[1] = address(uint160(uint256(keccak256("newRegistrar2")))); - newRegistrars[2] = address(uint160(uint256(keccak256("newRegistrar3")))); - - // new onchain config with 3 new registrars, all other fields stay the same as the default - AutomationRegistryBase2_3.OnchainConfig memory cfg2 = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 0, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: newRegistrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: module, - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - // the second time uses the new onchain config with 3 new registrars and also new billing tokens/configs - bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg2, billingTokens2, billingConfigs2); - - // set config twice - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling2, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - ( - , - IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig2, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) = registry.getState(); - - assertEq(onchainConfig2.registrars.length, 3); - for (uint256 i = 0; i < newRegistrars.length; i++) { - assertEq(newRegistrars[i], onchainConfig2.registrars[i]); - } - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); - assertEq(config2.gasFeePPB, 5_002); - assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config2.fallbackPrice, 200); - assertEq(config2.minSpend, 200); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 1); - } - - function testSetConfigDuplicateBillingConfigFailure() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress1 = address(linkToken); - address billingTokenAddress2 = address(linkToken); - address[] memory billingTokens = new address[](2); - billingTokens[0] = billingTokenAddress1; - billingTokens[1] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - // expect revert because of duplicate tokens - vm.expectRevert(abi.encodeWithSelector(Registry.DuplicateEntry.selector)); - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - } - - function testSetConfigRevertDueToInvalidToken() public { - address[] memory billingTokens = new address[](1); - billingTokens[0] = address(linkToken); - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - // deploy registry with OFF_CHAIN payout mode - registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); - - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - } - - function testSetConfigRevertDueToInvalidDecimals() public { - address[] memory billingTokens = new address[](1); - billingTokens[0] = address(linkToken); - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 6 // link token should have 18 decimals - }); - - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - } - - function testSetConfigOnTransmittersAndPayees() public { - registry.setPayees(PAYEES); - AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry - .getTransmittersWithPayees(); - assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); - - for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { - address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; - address payeeAddress = transmitterPayeeInfos[i].payeeAddress; - - address expectedTransmitter = TRANSMITTERS[i]; - address expectedPayee = PAYEES[i]; - - assertEq(transmitterAddress, expectedTransmitter); - assertEq(payeeAddress, expectedPayee); - } - } - - function testSetConfigWithNewTransmittersSuccess() public { - registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); - - (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); - assertEq(configCount, 0); - - address billingTokenAddress = address(usdToken18); - address[] memory billingTokens = new address[](1); - billingTokens[0] = billingTokenAddress; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - bytes memory onchainConfigBytes = abi.encode(cfg); - - bytes32 configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - - (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - - (configCount, blockNumber, ) = registry.latestConfigDetails(); - configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - NEW_TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - NEW_TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfigTypeSafe( - SIGNERS, - NEW_TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - - (, , signers, transmitters, ) = registry.getState(); - assertEq(signers, SIGNERS); - assertEq(transmitters, NEW_TRANSMITTERS); - } - - function _getRegistrars() private pure returns (address[] memory) { - address[] memory registrars = new address[](2); - registrars[0] = address(uint160(uint256(keccak256("registrar1")))); - registrars[1] = address(uint160(uint256(keccak256("registrar2")))); - return registrars; - } - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } -} - -contract NOPsSettlement is SetUp { - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - - function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); - registry.settleNOPsOffchain(); - } - - function testSettleNOPsOffchainRevertDueToOffchainSettlementDisabled() public { - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - vm.prank(FINANCE_ADMIN); - vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOnchain.selector)); - registry.settleNOPsOffchain(); - } - - function testSettleNOPsOffchainSuccess() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - uint256[] memory payments = new uint256[](TRANSMITTERS.length); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - payments[i] = 0; - } - - vm.startPrank(FINANCE_ADMIN); - vm.expectEmit(); - emit NOPsSettledOffchain(PAYEES, payments); - registry.settleNOPsOffchain(); - } - - // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same - function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry); - - // verify transmitters have positive balances - uint256[] memory payments = new uint256[](TRANSMITTERS.length); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertTrue(balance > 0); - assertEq(0, lastCollected); - - payments[i] = balance; - } - - // verify offchain settlement will emit NOPs' balances - vm.startPrank(FINANCE_ADMIN); - vm.expectEmit(); - emit NOPsSettledOffchain(PAYEES, payments); - registry.settleNOPsOffchain(); - - // verify that transmitters balance has been zeroed out - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertEq(0, balance); - } - - // after the offchain settlement, the total reserve amount of LINK should be 0 - assertEq(registry.getReserveAmount(address(linkToken)), 0); - // should have some ERC20s in registry after transmit - uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); - - vm.startPrank(UPKEEP_ADMIN); - vm.roll(100 + block.number); - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry); - - uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); - - // finance admin comes to withdraw all available ERC20s - vm.startPrank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); - - uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); - - uint256 reservedLink = registry.getReserveAmount(address(linkToken)); - require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); - - // owner comes to disable offchain mode - vm.startPrank(registry.owner()); - registry.disableOffchainPayments(); - - // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity - vm.startPrank(FINANCE_ADMIN); - uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); - - // reserved link amount to NOPs should stay the same after switching to onchain mode - assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); - // available ERC20 for payment should be 0 since finance admin withdrew all already - assertEq(erc20ForPayment4, 0); - } - - function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, Registrar registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so TRANSMITTERS earn some rewards - _transmit(id, registry); - - // TRANSMITTERS have positive balance now - // configure the registry to use NEW_TRANSMITTERS - _configureWithNewTransmitters(registry, registrar); - - _transmit(id, registry); - - // verify all transmitters have positive balances - address[] memory expectedPayees = new address[](6); - uint256[] memory expectedPayments = new uint256[](6); - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( - NEW_TRANSMITTERS[i] - ); - assertTrue(active); - assertEq(i, index); - assertTrue(lastCollected > 0); - expectedPayments[i] = balance; - expectedPayees[i] = payee; - } - for (uint256 i = 2; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( - TRANSMITTERS[i] - ); - assertFalse(active); - assertEq(i, index); - assertTrue(balance > 0); - assertTrue(lastCollected > 0); - expectedPayments[2 + i] = balance; - expectedPayees[2 + i] = payee; - } - - // verify offchain settlement will emit NOPs' balances - vm.startPrank(FINANCE_ADMIN); - - // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these - // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. - vm.recordLogs(); - registry.settleNOPsOffchain(); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 1); - Vm.Log memory l = entries[0]; - assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); - (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); - assertEq(actualPayees.length, 6); - assertEq(actualPayments.length, 6); - - // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - assertEq(actualPayees[i], expectedPayees[i]); - assertEq(actualPayments[i], expectedPayments[i]); - } - - // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered - assertTrue( - (actualPayments[5] == expectedPayments[5] && - actualPayees[5] == expectedPayees[5] && - actualPayments[4] == expectedPayments[4] && - actualPayees[4] == expectedPayees[4]) || - (actualPayments[5] == expectedPayments[4] && - actualPayees[5] == expectedPayees[4] && - actualPayments[4] == expectedPayments[5] && - actualPayees[4] == expectedPayees[5]) - ); - - // verify that new transmitters balance has been zeroed out - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertEq(0, balance); - } - // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out - for (uint256 i = 2; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertFalse(active); - assertEq(i, index); - assertEq(0, balance); - } - - // after the offchain settlement, the total reserve amount of LINK should be 0 - assertEq(registry.getReserveAmount(address(linkToken)), 0); - } - - function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(bytes("Only callable by owner")); - registry.disableOffchainPayments(); - } - - function testDisableOffchainPaymentsSuccess() public { - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.startPrank(registry.owner()); - registry.disableOffchainPayments(); - - assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); - } - - function testSinglePerformAndNodesCanWithdrawOnchain() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry); - - // disable offchain payments - _mintLink(address(registry), 1e19); - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - // payees should be able to withdraw onchain - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - vm.prank(payee); - vm.expectEmit(); - emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); - registry.withdrawPayment(TRANSMITTERS[i], payee); - } - - // allow upkeep admin to withdraw funds - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(id); - vm.roll(100 + block.number); - vm.expectEmit(); - // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value - emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); - registry.withdrawFunds(id, UPKEEP_ADMIN); - } - - function testMultiplePerformsAndNodesCanWithdrawOnchain() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually call transmit so transmitters earn some rewards - for (uint256 i = 0; i < 50; i++) { - vm.roll(100 + block.number); - _transmit(id, registry); - } - - // disable offchain payments - _mintLink(address(registry), 1e19); - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - // manually call transmit after offchain payment is disabled - for (uint256 i = 0; i < 50; i++) { - vm.roll(100 + block.number); - _transmit(id, registry); - } - - // payees should be able to withdraw onchain - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - vm.prank(payee); - vm.expectEmit(); - emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); - registry.withdrawPayment(TRANSMITTERS[i], payee); - } - - // allow upkeep admin to withdraw funds - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(id); - vm.roll(100 + block.number); - uint256 balance = registry.getBalance(id); - vm.expectEmit(); - emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); - registry.withdrawFunds(id, UPKEEP_ADMIN); - } - - function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { - IERC20[] memory billingTokens = new IERC20[](1); - billingTokens[0] = IERC20(address(usdToken18)); - - uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100e18; // 100 USD - - address[] memory billingTokenAddresses = new address[](billingTokens.length); - for (uint256 i = 0; i < billingTokens.length; i++) { - billingTokenAddresses[i] = address(billingTokens[i]); - } - - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 10_000_000, // 15% - flatFeeMilliCents: 2_000, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 1e8, // $1 - minSpend: 1e18, // 1 USD - decimals: 18 - }); - - address[] memory registrars = new address[](1); - registrars[0] = address(registrar); - - AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 2, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: registrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: address(new ChainModuleBase()), - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - registry.setConfigTypeSafe( - SIGNERS, - NEW_TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokenAddresses, - billingTokenConfigs - ); - - registry.setPayees(NEW_PAYEES); - } -} - -contract WithdrawPayment is SetUp { - function testWithdrawPaymentRevertDueToOffchainPayoutMode() public { - registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); - vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOffchain.selector)); - vm.prank(TRANSMITTERS[0]); - registry.withdrawPayment(TRANSMITTERS[0], TRANSMITTERS[0]); - } -} - -contract RegisterUpkeep is SetUp { - function test_RevertsWhen_Paused() public { - registry.pause(); - vm.expectRevert(Registry.RegistryPaused.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_TargetIsNotAContract() public { - vm.expectRevert(Registry.NotAContract.selector); - registry.registerUpkeep( - randomAddress(), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_CalledByNonOwner() public { - vm.prank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByOwnerOrRegistrar.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_ExecuteGasIsTooLow() public { - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.registerUpkeep( - address(TARGET1), - 2299, // 1 less than min - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_ExecuteGasIsTooHigh() public { - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas + 1, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { - vm.expectRevert(Registry.InvalidToken.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - randomAddress(), - "", - "", - "" - ); - } - - function test_RevertsWhen_CheckDataIsTooLarge() public { - vm.expectRevert(Registry.CheckDataExceedsLimit.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - randomBytes(config.maxCheckDataSize + 1), - "", - "" - ); - } - - function test_Happy() public { - bytes memory checkData = randomBytes(config.maxCheckDataSize); - bytes memory trigggerConfig = randomBytes(100); - bytes memory offchainConfig = randomBytes(100); - - uint256 upkeepCount = registry.getNumUpkeeps(); - - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.LOG), - address(linkToken), - checkData, - trigggerConfig, - offchainConfig - ); - - assertEq(registry.getNumUpkeeps(), upkeepCount + 1); - assertEq(registry.getUpkeep(upkeepID).target, address(TARGET1)); - assertEq(registry.getUpkeep(upkeepID).performGas, config.maxPerformGas); - assertEq(registry.getUpkeep(upkeepID).checkData, checkData); - assertEq(registry.getUpkeep(upkeepID).balance, 0); - assertEq(registry.getUpkeep(upkeepID).admin, UPKEEP_ADMIN); - assertEq(registry.getUpkeep(upkeepID).offchainConfig, offchainConfig); - assertEq(registry.getUpkeepTriggerConfig(upkeepID), trigggerConfig); - assertEq(uint8(registry.getTriggerType(upkeepID)), uint8(Trigger.LOG)); - } -} - -contract OnTokenTransfer is SetUp { - function test_RevertsWhen_NotCalledByTheLinkToken() public { - vm.expectRevert(Registry.OnlyCallableByLINKToken.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); - } - - function test_RevertsWhen_NotCalledWithExactly32Bytes() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.InvalidDataLength.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(31)); - vm.expectRevert(Registry.InvalidDataLength.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(33)); - } - - function test_RevertsWhen_TheUpkeepIsCancelledOrDNE() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(randomNumber())); - } - - function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.InvalidToken.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); - } - - function test_Happy() public { - vm.startPrank(address(linkToken)); - uint256 beforeBalance = registry.getBalance(linkUpkeepID); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); - assertEq(registry.getBalance(linkUpkeepID), beforeBalance + 100); - } -} - -contract GetMinBalanceForUpkeep is SetUp { - function test_accountsForFlatFee_with18Decimals() public { - // set fee to 0 - AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); - usdTokenConfig.flatFeeMilliCents = 0; - _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - - uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); - - // set fee to non-zero - usdTokenConfig.flatFeeMilliCents = 100; - _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - - uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); - assertEq( - minBalanceAfter, - minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) - ); - } - - function test_accountsForFlatFee_with6Decimals() public { - // set fee to 0 - AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); - usdTokenConfig.flatFeeMilliCents = 0; - _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); - - uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); - - // set fee to non-zero - usdTokenConfig.flatFeeMilliCents = 100; - _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); - - uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); - assertEq( - minBalanceAfter, - minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) - ); - } -} - -contract BillingOverrides is SetUp { - event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - - function test_RevertsWhen_NotPrivilegeManager() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_RevertsWhen_UpkeepCancelled() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(PRIVILEGE_MANAGER); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_Happy_SetBillingOverrides() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - vm.startPrank(PRIVILEGE_MANAGER); - - vm.expectEmit(); - emit BillingConfigOverridden(linkUpkeepID, billingOverrides); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_Happy_RemoveBillingOverrides() public { - vm.startPrank(PRIVILEGE_MANAGER); - - vm.expectEmit(); - emit BillingConfigOverrideRemoved(linkUpkeepID); - registry.removeBillingOverrides(linkUpkeepID); - } - - function test_Happy_MaxGasPayment_WithBillingOverrides() public { - uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); - - // Double the two billing values - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 - }); - - vm.startPrank(PRIVILEGE_MANAGER); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - - // maxPayment2 should be greater than maxPayment1 after the overrides - // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium - // We do not apply the exact equation since we couldn't get the receipt.premium value - uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); - assertGt(maxPayment2, maxPayment1); - } -} - -contract Transmit is SetUp { - function test_transmitRevertWithExtraBytes() external { - bytes32[3] memory exampleReportContext = [ - bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef), - bytes32(0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890), - bytes32(0x7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456) - ]; - - bytes memory exampleRawReport = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; - - bytes32[] memory exampleRs = new bytes32[](3); - exampleRs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleRs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleRs[2] = bytes32(0x7890789078907890789078907890789078907890789078907890789078907890); - - bytes32[] memory exampleSs = new bytes32[](3); - exampleSs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleSs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleSs[2] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - - bytes32 exampleRawVs = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - - bytes memory transmitData = abi.encodeWithSelector( - registry.transmit.selector, - exampleReportContext, - exampleRawReport, - exampleRs, - exampleSs, - exampleRawVs - ); - bytes memory badTransmitData = bytes.concat(transmitData, bytes1(0x00)); // add extra data - vm.startPrank(TRANSMITTERS[0]); - (bool success, bytes memory returnData) = address(registry).call(badTransmitData); // send the bogus transmit - assertFalse(success, "Call did not revert as expected"); - assertEq(returnData, abi.encodePacked(Registry.InvalidDataLength.selector)); - vm.stopPrank(); - } - - function test_handlesMixedBatchOfBillingTokens() external { - uint256[] memory prevUpkeepBalances = new uint256[](3); - prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); - prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); - prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); - uint256[] memory prevTokenBalances = new uint256[](3); - prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); - prevTokenBalances[2] = weth.balanceOf(address(registry)); - uint256[] memory prevReserveBalances = new uint256[](3); - prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); - prevReserveBalances[2] = registry.getReserveAmount(address(weth)); - uint256[] memory upkeepIDs = new uint256[](3); - upkeepIDs[0] = linkUpkeepID; - upkeepIDs[1] = usdUpkeepID18; - upkeepIDs[2] = nativeUpkeepID; - - // withdraw-able by finance team should be 0 - require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); - require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); - - // do the thing - _transmit(upkeepIDs, registry); - - // withdraw-able by the finance team should be positive - require( - registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, - "ERC20AvailableForPayment should be positive" - ); - require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); - - // assert upkeep balances have decreased - require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); - require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); - require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); - // assert token balances have not changed - assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); - assertEq(prevTokenBalances[1], usdToken18.balanceOf(address(registry))); - assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); - // assert reserve amounts have adjusted accordingly - require( - prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), - "usd reserve amount should have increased" - ); // link reserve amount increases in value equal to the decrease of the other reserve amounts - require( - prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), - "usd reserve amount should have decreased" - ); - require( - prevReserveBalances[2] > registry.getReserveAmount(address(weth)), - "native reserve amount should have decreased" - ); - } - - function test_handlesInsufficientBalanceWithUSDToken18() external { - // deploy and configure a registry with ON_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - // register an upkeep and add funds - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - 1000000, - UPKEEP_ADMIN, - 0, - address(usdToken18), - "", - "", - "" - ); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(upkeepID, 1); // smaller than gasCharge - uint256 balance = registry.getBalance(upkeepID); - - // manually create a transmit - vm.recordLogs(); - _transmit(upkeepID, registry); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 3); - Vm.Log memory l1 = entries[1]; - assertEq( - l1.topics[0], - keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") - ); - ( - uint96 gasChargeInBillingToken, - uint96 premiumInBillingToken, - uint96 gasReimbursementInJuels, - uint96 premiumInJuels, - address billingToken, - uint96 linkUSD, - uint96 nativeUSD, - uint96 billingUSD - ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); - - assertEq(gasChargeInBillingToken, balance); - assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD); - assertEq(premiumInJuels, 0); - assertEq(premiumInBillingToken, 0); - } - - function test_handlesInsufficientBalanceWithUSDToken6() external { - // deploy and configure a registry with ON_CHAIN payout - (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - // register an upkeep and add funds - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - 1000000, - UPKEEP_ADMIN, - 0, - address(usdToken6), - "", - "", - "" - ); - vm.prank(OWNER); - usdToken6.mint(UPKEEP_ADMIN, 1e20); - - vm.startPrank(UPKEEP_ADMIN); - usdToken6.approve(address(registry), 1e20); - registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium) - uint256 balance = registry.getBalance(upkeepID); - - // manually create a transmit - vm.recordLogs(); - _transmit(upkeepID, registry); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 3); - Vm.Log memory l1 = entries[1]; - assertEq( - l1.topics[0], - keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") - ); - ( - uint96 gasChargeInBillingToken, - uint96 premiumInBillingToken, - uint96 gasReimbursementInJuels, - uint96 premiumInJuels, - address billingToken, - uint96 linkUSD, - uint96 nativeUSD, - uint96 billingUSD - ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); - - assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals - assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12)); - } -} - -contract MigrateReceive is SetUp { - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - - Registry newRegistry; - uint256[] idsToMigrate; - - function setUp() public override { - super.setUp(); - (newRegistry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - idsToMigrate.push(linkUpkeepID); - idsToMigrate.push(linkUpkeepID2); - idsToMigrate.push(usdUpkeepID18); - idsToMigrate.push(nativeUpkeepID); - registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); - } - - function test_RevertsWhen_PermissionsNotSet() external { - // no permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // only outgoing permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // only incoming permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // permissions opposite direction - registry.setPeerRegistryMigrationPermission(address(newRegistry), 2); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 1); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - } - - function test_RevertsWhen_ReceivingRegistryDoesNotSupportToken() external { - _removeBillingTokenConfig(newRegistry, address(weth)); - vm.expectRevert(Registry.InvalidToken.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - idsToMigrate.pop(); // remove native upkeep id - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); // should succeed now - } - - function test_RevertsWhen_CalledByNonAdmin() external { - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - vm.prank(STRANGER); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - } - - function test_Success() external { - vm.startPrank(UPKEEP_ADMIN); - - // add some changes in upkeep data to the mix - registry.pauseUpkeep(usdUpkeepID18); - registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); - registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); - - // record previous state - uint256[] memory prevUpkeepBalances = new uint256[](4); - prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); - prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); - prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); - prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); - uint256[] memory prevReserveBalances = new uint256[](3); - prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); - prevReserveBalances[2] = registry.getReserveAmount(address(weth)); - uint256[] memory prevTokenBalances = new uint256[](3); - prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); - prevTokenBalances[2] = weth.balanceOf(address(registry)); - bytes[] memory prevUpkeepData = new bytes[](4); - prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); - prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); - prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); - prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); - bytes[] memory prevUpkeepTriggerData = new bytes[](4); - prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); - prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); - prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); - prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); - - // event expectations - vm.expectEmit(address(registry)); - emit UpkeepMigrated(linkUpkeepID, prevUpkeepBalances[0], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(linkUpkeepID, prevUpkeepBalances[0], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); - - // do the thing - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // assert upkeep balances have been migrated - assertEq(registry.getBalance(linkUpkeepID), 0); - assertEq(registry.getBalance(linkUpkeepID2), 0); - assertEq(registry.getBalance(usdUpkeepID18), 0); - assertEq(registry.getBalance(nativeUpkeepID), 0); - assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); - assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); - assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); - assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); - - // assert reserve balances have been adjusted - assertEq( - newRegistry.getReserveAmount(address(linkToken)), - newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) - ); - assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); - assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); - assertEq( - newRegistry.getReserveAmount(address(linkToken)), - prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) - ); - assertEq( - newRegistry.getReserveAmount(address(usdToken18)), - prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) - ); - assertEq( - newRegistry.getReserveAmount(address(weth)), - prevReserveBalances[2] - registry.getReserveAmount(address(weth)) - ); - - // assert token have been transferred - assertEq( - linkToken.balanceOf(address(newRegistry)), - newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) - ); - assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); - assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); - assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); - assertEq( - usdToken18.balanceOf(address(registry)), - prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) - ); - assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); - - // assert upkeep data matches - assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); - assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); - assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); - assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); - assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); - assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); - assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); - assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); - - vm.stopPrank(); - } -} - -contract Pause is SetUp { - function test_RevertsWhen_CalledByNonOwner() external { - vm.expectRevert(bytes("Only callable by owner")); - vm.prank(STRANGER); - registry.pause(); - } - - function test_CalledByOwner_success() external { - vm.startPrank(registry.owner()); - registry.pause(); - - (IAutomationV21PlusCommon.StateLegacy memory state, , , , ) = registry.getState(); - assertTrue(state.paused); - } - - function test_revertsWhen_transmitInPausedRegistry() external { - vm.startPrank(registry.owner()); - registry.pause(); - - _transmitAndExpectRevert(usdUpkeepID18, registry, Registry.RegistryPaused.selector); - } -} - -contract Unpause is SetUp { - function test_RevertsWhen_CalledByNonOwner() external { - vm.startPrank(registry.owner()); - registry.pause(); - - vm.expectRevert(bytes("Only callable by owner")); - vm.startPrank(STRANGER); - registry.unpause(); - } - - function test_CalledByOwner_success() external { - vm.startPrank(registry.owner()); - registry.pause(); - (IAutomationV21PlusCommon.StateLegacy memory state1, , , , ) = registry.getState(); - assertTrue(state1.paused); - - registry.unpause(); - (IAutomationV21PlusCommon.StateLegacy memory state2, , , , ) = registry.getState(); - assertFalse(state2.paused); - } -} - -contract CancelUpkeep is SetUp { - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - - function test_RevertsWhen_IdIsInvalid_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - vm.expectRevert(Registry.CannotCancel.selector); - registry.cancelUpkeep(1111111); - } - - function test_RevertsWhen_IdIsInvalid_CalledByOwner() external { - vm.startPrank(registry.owner()); - vm.expectRevert(Registry.CannotCancel.selector); - registry.cancelUpkeep(1111111); - } - - function test_RevertsWhen_NotCalledByOwnerOrAdmin() external { - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByOwnerOrAdmin.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(registry.owner()); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(UPKEEP_ADMIN); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); - - // 50 is the cancellation delay - assertEq(bn + 50, maxValidBlocknumber); - } - - function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); - - // cancellation by registry owner is immediate and no cancellation delay is applied - assertEq(bn, maxValidBlocknumber); - } - - function test_CancelUpkeep_EmitEvent_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepCanceled(linkUpkeepID, uint64(bn + 50)); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_CancelUpkeep_EmitEvent_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - - vm.expectEmit(); - emit UpkeepCanceled(linkUpkeepID, uint64(bn)); - registry.cancelUpkeep(linkUpkeepID); - } -} - -contract SetPeerRegistryMigrationPermission is SetUp { - function test_SetPeerRegistryMigrationPermission_CalledByOwner() external { - address peer = randomAddress(); - vm.startPrank(registry.owner()); - - uint8 permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(0, permission); - - registry.setPeerRegistryMigrationPermission(peer, 1); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(1, permission); - - registry.setPeerRegistryMigrationPermission(peer, 2); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(2, permission); - - registry.setPeerRegistryMigrationPermission(peer, 0); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(0, permission); - } - - function test_RevertsWhen_InvalidPermission_CalledByOwner() external { - address peer = randomAddress(); - vm.startPrank(registry.owner()); - - vm.expectRevert(); - registry.setPeerRegistryMigrationPermission(peer, 100); - } - - function test_RevertsWhen_CalledByNonOwner() external { - address peer = randomAddress(); - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - registry.setPeerRegistryMigrationPermission(peer, 1); - } -} - -contract SetUpkeepPrivilegeConfig is SetUp { - function test_RevertsWhen_CalledByNonManager() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); - } - - function test_UpkeepHasEmptyConfig() external { - bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); - assertEq(cfg, bytes("")); - } - - function test_SetUpkeepPrivilegeConfig_CalledByManager() external { - vm.startPrank(PRIVILEGE_MANAGER); - - registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); - - bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); - assertEq(cfg, hex"1233"); - } -} - -contract SetAdminPrivilegeConfig is SetUp { - function test_RevertsWhen_CalledByNonManager() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setAdminPrivilegeConfig(randomAddress(), hex"1233"); - } - - function test_UpkeepHasEmptyConfig() external { - bytes memory cfg = registry.getAdminPrivilegeConfig(randomAddress()); - assertEq(cfg, bytes("")); - } - - function test_SetAdminPrivilegeConfig_CalledByManager() external { - vm.startPrank(PRIVILEGE_MANAGER); - address admin = randomAddress(); - - registry.setAdminPrivilegeConfig(admin, hex"1233"); - - bytes memory cfg = registry.getAdminPrivilegeConfig(admin); - assertEq(cfg, hex"1233"); - } -} - -contract TransferUpkeepAdmin is SetUp { - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - } - - function test_RevertsWhen_TransferToSelf() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.ValueNotChanged.selector); - registry.transferUpkeepAdmin(linkUpkeepID, UPKEEP_ADMIN); - } - - function test_RevertsWhen_UpkeepCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - } - - function test_DoesNotChangeUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - - assertEq(registry.getUpkeep(linkUpkeepID).admin, UPKEEP_ADMIN); - } - - function test_EmitEvent_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - // transferring to the same propose admin won't yield another event - vm.recordLogs(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(0, entries.length); - } - - function test_CancelTransfer_ByTransferToEmptyAddress() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, address(0)); - registry.transferUpkeepAdmin(linkUpkeepID, address(0)); - } -} - -contract AcceptUpkeepAdmin is SetUp { - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByProposedAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByProposedAdmin.selector); - registry.acceptUpkeepAdmin(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(newAdmin); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.acceptUpkeepAdmin(linkUpkeepID); - } - - function test_UpkeepAdminChanged() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.startPrank(newAdmin); - vm.expectEmit(); - emit UpkeepAdminTransferred(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.acceptUpkeepAdmin(linkUpkeepID); - - assertEq(newAdmin, registry.getUpkeep(linkUpkeepID).admin); - } -} - -contract PauseUpkeep is SetUp { - event UpkeepPaused(uint256 indexed id); - - function test_RevertsWhen_NotCalledByUpkeepAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.pauseUpkeep(linkUpkeepID + 1); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyPaused() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.OnlyUnpausedUpkeep.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_EmitEvent_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepPaused(linkUpkeepID); - registry.pauseUpkeep(linkUpkeepID); - } -} - -contract UnpauseUpkeep is SetUp { - event UpkeepUnpaused(uint256 indexed id); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.unpauseUpkeep(linkUpkeepID + 1); - } - - function test_RevertsWhen_UpkeepIsNotPaused() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyPausedUpkeep.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_NotCalledByUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_UnpauseUpkeep_CalledByUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - uint256[] memory ids1 = registry.getActiveUpkeepIDs(0, 0); - - vm.expectEmit(); - emit UpkeepUnpaused(linkUpkeepID); - registry.unpauseUpkeep(linkUpkeepID); - - uint256[] memory ids2 = registry.getActiveUpkeepIDs(0, 0); - assertEq(ids1.length + 1, ids2.length); - } -} - -contract SetUpkeepCheckData is SetUp { - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepCheckData(linkUpkeepID + 1, hex"1234"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NewCheckDataTooLarge() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.CheckDataExceedsLimit.selector); - registry.setUpkeepCheckData(linkUpkeepID, new bytes(10_000)); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - } - - function test_UpdateOffchainConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); - } - - function test_UpdateOffchainConfigOnPausedUpkeep_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - registry.pauseUpkeep(linkUpkeepID); - - vm.expectEmit(); - emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - - assertTrue(registry.getUpkeep(linkUpkeepID).paused); - assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); - } -} - -contract SetUpkeepGasLimit is SetUp { - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepGasLimit(linkUpkeepID + 1, 1230000); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - } - - function test_RevertsWhen_NewGasLimitOutOfRange() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 300); - - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 3000000000); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - } - - function test_UpdateGasLimit_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepGasLimitSet(linkUpkeepID, 1230000); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - - assertEq(registry.getUpkeep(linkUpkeepID).performGas, 1230000); - } -} - -contract SetUpkeepOffchainConfig is SetUp { - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID + 1, hex"1233"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - } - - function test_UpdateOffchainConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepOffchainConfigSet(linkUpkeepID, hex"1234"); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeep(linkUpkeepID).offchainConfig, hex"1234"); - } -} - -contract SetUpkeepTriggerConfig is SetUp { - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID + 1, hex"1233"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - } - - function test_UpdateTriggerConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepTriggerConfigSet(linkUpkeepID, hex"1234"); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeepTriggerConfig(linkUpkeepID), hex"1234"); - } -} - -contract TransferPayeeship is SetUp { - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByPayee() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByPayee.selector); - registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); - } - - function test_RevertsWhen_TransferToSelf() external { - registry.setPayees(PAYEES); - vm.startPrank(PAYEES[0]); - - vm.expectRevert(Registry.ValueNotChanged.selector); - registry.transferPayeeship(TRANSMITTERS[0], PAYEES[0]); - } - - function test_Transfer_DoesNotChangePayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - - registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); - - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertEq(PAYEES[0], payee); - } - - function test_EmitEvent_CalledByPayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - - vm.expectEmit(); - emit PayeeshipTransferRequested(TRANSMITTERS[0], PAYEES[0], newPayee); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - // transferring to the same propose payee won't yield another event - vm.recordLogs(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(0, entries.length); - } -} - -contract AcceptPayeeship is SetUp { - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByProposedPayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByProposedPayee.selector); - registry.acceptPayeeship(TRANSMITTERS[0]); - } - - function test_PayeeChanged() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - vm.startPrank(newPayee); - vm.expectEmit(); - emit PayeeshipTransferred(TRANSMITTERS[0], PAYEES[0], newPayee); - registry.acceptPayeeship(TRANSMITTERS[0]); - - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertEq(newPayee, payee); - } -} - -contract SetPayees is SetUp { - event PayeesUpdated(address[] transmitters, address[] payees); - - function test_RevertsWhen_NotCalledByOwner() external { - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - registry.setPayees(NEW_PAYEES); - } - - function test_RevertsWhen_PayeesLengthError() external { - vm.startPrank(registry.owner()); - - address[] memory payees = new address[](5); - vm.expectRevert(Registry.ParameterLengthError.selector); - registry.setPayees(payees); - } - - function test_RevertsWhen_InvalidPayee() external { - vm.startPrank(registry.owner()); - - NEW_PAYEES[0] = address(0); - vm.expectRevert(Registry.InvalidPayee.selector); - registry.setPayees(NEW_PAYEES); - } - - function test_SetPayees_WhenExistingPayeesAreEmpty() external { - (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertEq(address(0), payee); - } - - vm.startPrank(registry.owner()); - - vm.expectEmit(); - emit PayeesUpdated(TRANSMITTERS, PAYEES); - registry.setPayees(PAYEES); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(PAYEES[i], payee); - } - } - - function test_DotNotSetPayeesToIgnoredAddress() external { - address IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - PAYEES[0] = IGNORE_ADDRESS; - - registry.setPayees(PAYEES); - (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertTrue(active); - assertEq(address(0), payee); - - (active, , , , payee) = registry.getTransmitterInfo(TRANSMITTERS[1]); - assertTrue(active); - assertEq(PAYEES[1], payee); - } -} - -contract GetActiveUpkeepIDs is SetUp { - function test_RevertsWhen_IndexOutOfRange() external { - vm.expectRevert(Registry.IndexOutOfRange.selector); - registry.getActiveUpkeepIDs(5, 0); - - vm.expectRevert(Registry.IndexOutOfRange.selector); - registry.getActiveUpkeepIDs(6, 0); - } - - function test_ReturnsAllUpkeeps_WhenMaxCountIsZero() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(0, 0); - assertEq(5, uids.length); - - uids = registry.getActiveUpkeepIDs(2, 0); - assertEq(3, uids.length); - } - - function test_ReturnsAllRemainingUpkeeps_WhenMaxCountIsTooLarge() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(2, 20); - assertEq(3, uids.length); - } - - function test_ReturnsUpkeeps_BoundByMaxCount() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(1, 2); - assertEq(2, uids.length); - assertEq(uids[0], linkUpkeepID2); - assertEq(uids[1], usdUpkeepID18); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol deleted file mode 100644 index e0d15da..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3/BaseTest.t.sol +++ /dev/null @@ -1,503 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import "forge-std/Test.sol"; - -import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; -import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; -import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; -import {AutomationRegistry2_3} from "../../v2_3/AutomationRegistry2_3.sol"; -import {AutomationRegistryBase2_3 as AutoBase} from "../../v2_3/AutomationRegistryBase2_3.sol"; -import {AutomationRegistryLogicA2_3} from "../../v2_3/AutomationRegistryLogicA2_3.sol"; -import {AutomationRegistryLogicB2_3} from "../../v2_3/AutomationRegistryLogicB2_3.sol"; -import {AutomationRegistryLogicC2_3} from "../../v2_3/AutomationRegistryLogicC2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; -import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; -import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; -import {WETH9} from "../WETH9.sol"; - -/** - * @title BaseTest provides basic test setup procedures and dependencies for use by other - * unit tests - */ -contract BaseTest is Test { - // test state (not exposed to derived tests) - uint256 private nonce; - - // constants - address internal constant ZERO_ADDRESS = address(0); - uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; - uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; - - // config - uint8 internal constant F = 1; // number of faulty nodes - uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 - - // contracts - LinkToken internal linkToken; - ERC20Mock6Decimals internal usdToken6; - ERC20Mock internal usdToken18; - ERC20Mock internal usdToken18_2; - WETH9 internal weth; - MockV3Aggregator internal LINK_USD_FEED; - MockV3Aggregator internal NATIVE_USD_FEED; - MockV3Aggregator internal USDTOKEN_USD_FEED; - MockV3Aggregator internal FAST_GAS_FEED; - MockUpkeep internal TARGET1; - MockUpkeep internal TARGET2; - Transcoder internal TRANSCODER; - - // roles - address internal constant OWNER = address(uint160(uint256(keccak256("OWNER")))); - address internal constant UPKEEP_ADMIN = address(uint160(uint256(keccak256("UPKEEP_ADMIN")))); - address internal constant FINANCE_ADMIN = address(uint160(uint256(keccak256("FINANCE_ADMIN")))); - address internal constant STRANGER = address(uint160(uint256(keccak256("STRANGER")))); - address internal constant BROKE_USER = address(uint160(uint256(keccak256("BROKE_USER")))); // do not mint to this address - address internal constant PRIVILEGE_MANAGER = address(uint160(uint256(keccak256("PRIVILEGE_MANAGER")))); - - // nodes - uint256 internal constant SIGNING_KEY0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - uint256 internal constant SIGNING_KEY1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; - uint256 internal constant SIGNING_KEY2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; - uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; - address[] internal SIGNERS = new address[](4); - address[] internal TRANSMITTERS = new address[](4); - address[] internal NEW_TRANSMITTERS = new address[](4); - address[] internal PAYEES = new address[](4); - address[] internal NEW_PAYEES = new address[](4); - - function setUp() public virtual { - vm.startPrank(OWNER); - linkToken = new LinkToken(); - linkToken.grantMintRole(OWNER); - usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); - usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); - usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); - weth = new WETH9(); - - LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 - NATIVE_USD_FEED = new MockV3Aggregator(8, 400_000_000_000); // $4,000 - USDTOKEN_USD_FEED = new MockV3Aggregator(8, 100_000_000); // $1 - FAST_GAS_FEED = new MockV3Aggregator(0, 1_000_000_000); // 1 gwei - - TARGET1 = new MockUpkeep(); - TARGET2 = new MockUpkeep(); - - TRANSCODER = new Transcoder(); - - SIGNERS[0] = vm.addr(SIGNING_KEY0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 - SIGNERS[1] = vm.addr(SIGNING_KEY1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 - SIGNERS[2] = vm.addr(SIGNING_KEY2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b - SIGNERS[3] = vm.addr(SIGNING_KEY3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 - - TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); - TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); - TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); - TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); - NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); - NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); - NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); - NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); - - PAYEES[0] = address(100); - PAYEES[1] = address(101); - PAYEES[2] = address(102); - PAYEES[3] = address(103); - NEW_PAYEES[0] = address(100); - NEW_PAYEES[1] = address(101); - NEW_PAYEES[2] = address(106); - NEW_PAYEES[3] = address(107); - - // mint funds - vm.deal(OWNER, 100 ether); - vm.deal(UPKEEP_ADMIN, 100 ether); - vm.deal(FINANCE_ADMIN, 100 ether); - vm.deal(STRANGER, 100 ether); - - linkToken.mint(OWNER, 1000e18); - linkToken.mint(UPKEEP_ADMIN, 1000e18); - linkToken.mint(FINANCE_ADMIN, 1000e18); - linkToken.mint(STRANGER, 1000e18); - - usdToken18.mint(OWNER, 1000e18); - usdToken18.mint(UPKEEP_ADMIN, 1000e18); - usdToken18.mint(FINANCE_ADMIN, 1000e18); - usdToken18.mint(STRANGER, 1000e18); - - usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); - - usdToken6.mint(OWNER, 1000e6); - usdToken6.mint(UPKEEP_ADMIN, 1000e6); - usdToken6.mint(FINANCE_ADMIN, 1000e6); - usdToken6.mint(STRANGER, 1000e6); - - weth.mint(OWNER, 1000e18); - weth.mint(UPKEEP_ADMIN, 1000e18); - weth.mint(FINANCE_ADMIN, 1000e18); - weth.mint(STRANGER, 1000e18); - - vm.stopPrank(); - } - - /// @notice deploys the component parts of a registry, but nothing more - function deployRegistry(AutoBase.PayoutMode payoutMode) internal returns (Registry) { - AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); - AutomationRegistryLogicC2_3 logicC2_3 = new AutomationRegistryLogicC2_3( - address(linkToken), - address(LINK_USD_FEED), - address(NATIVE_USD_FEED), - address(FAST_GAS_FEED), - address(forwarderLogic), - ZERO_ADDRESS, - payoutMode, - address(weth) - ); - AutomationRegistryLogicB2_3 logicB2_3 = new AutomationRegistryLogicB2_3(logicC2_3); - AutomationRegistryLogicA2_3 logicA2_3 = new AutomationRegistryLogicA2_3(logicB2_3); - return Registry(payable(address(new AutomationRegistry2_3(logicA2_3)))); - } - - /// @notice deploys and configures a registry, registrar, and everything needed for most tests - function deployAndConfigureRegistryAndRegistrar( - AutoBase.PayoutMode payoutMode - ) internal returns (Registry, AutomationRegistrar2_3) { - Registry registry = deployRegistry(payoutMode); - - IERC20[] memory billingTokens = new IERC20[](4); - billingTokens[0] = IERC20(address(usdToken18)); - billingTokens[1] = IERC20(address(weth)); - billingTokens[2] = IERC20(address(linkToken)); - billingTokens[3] = IERC20(address(usdToken6)); - uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100e18; // 100 USD - minRegistrationFees[1] = 5e18; // 5 Native - minRegistrationFees[2] = 5e18; // 5 LINK - minRegistrationFees[3] = 100e6; // 100 USD - address[] memory billingTokenAddresses = new address[](billingTokens.length); - for (uint256 i = 0; i < billingTokens.length; i++) { - billingTokenAddresses[i] = address(billingTokens[i]); - } - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100_000_000, // $1 - minSpend: 1e18, // 1 USD - decimals: 18 - }); - billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(NATIVE_USD_FEED), - fallbackPrice: 100_000_000, // $1 - minSpend: 5e18, // 5 Native - decimals: 18 - }); - billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(LINK_USD_FEED), - fallbackPrice: 1_000_000_000, // $10 - minSpend: 1e18, // 1 LINK - decimals: 18 - }); - billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 1e8, // $1 - minSpend: 1e6, // 1 USD - decimals: 6 - }); - - if (payoutMode == AutoBase.PayoutMode.OFF_CHAIN) { - // remove LINK as a payment method if we are settling offchain - assembly { - mstore(billingTokens, 2) - mstore(minRegistrationFees, 2) - mstore(billingTokenAddresses, 2) - mstore(billingTokenConfigs, 2) - } - } - - // deploy registrar - AutomationRegistrar2_3.InitialTriggerConfig[] - memory triggerConfigs = new AutomationRegistrar2_3.InitialTriggerConfig[](2); - triggerConfigs[0] = AutomationRegistrar2_3.InitialTriggerConfig({ - triggerType: 0, // condition - autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, - autoApproveMaxAllowed: 0 - }); - triggerConfigs[1] = AutomationRegistrar2_3.InitialTriggerConfig({ - triggerType: 1, // log - autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, - autoApproveMaxAllowed: 0 - }); - AutomationRegistrar2_3 registrar = new AutomationRegistrar2_3( - address(linkToken), - registry, - triggerConfigs, - billingTokens, - minRegistrationFees, - IWrappedNative(address(weth)) - ); - - address[] memory registrars; - registrars = new address[](1); - registrars[0] = address(registrar); - - AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 2, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: address(TRANSCODER), - registrars: registrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: address(new ChainModuleBase()), - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokenAddresses, - billingTokenConfigs - ); - return (registry, registrar); - } - - /// @notice this function updates the billing config for the provided token on the provided registry, - /// and throws an error if the token is not found - function _updateBillingTokenConfig( - Registry registry, - address billingToken, - AutomationRegistryBase2_3.BillingConfig memory newConfig - ) internal { - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); - address[] memory billingTokens = registry.getBillingTokens(); - - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - - bool found = false; - for (uint256 i = 0; i < billingTokens.length; i++) { - if (billingTokens[i] == billingToken) { - found = true; - billingTokenConfigs[i] = newConfig; - } else { - billingTokenConfigs[i] = registry.getBillingTokenConfig(billingTokens[i]); - } - } - require(found, "could not find billing token provided on registry"); - - registry.setConfigTypeSafe( - signers, - transmitters, - f, - config, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokens, - billingTokenConfigs - ); - } - - /// @notice this function removes a billing token from the registry - function _removeBillingTokenConfig(Registry registry, address billingToken) internal { - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); - address[] memory billingTokens = registry.getBillingTokens(); - - address[] memory newBillingTokens = new address[](billingTokens.length - 1); - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length - 1); - - uint256 j = 0; - for (uint256 i = 0; i < billingTokens.length; i++) { - if (billingTokens[i] != billingToken) { - if (j == newBillingTokens.length) revert("could not find billing token provided on registry"); - newBillingTokens[j] = billingTokens[i]; - billingTokenConfigs[j] = registry.getBillingTokenConfig(billingTokens[i]); - j++; - } - } - - registry.setConfigTypeSafe( - signers, - transmitters, - f, - config, - OFFCHAIN_CONFIG_VERSION, - "", - newBillingTokens, - billingTokenConfigs - ); - } - - // tests single upkeep, expects success - function _transmit(uint256 id, Registry registry) internal { - uint256[] memory ids = new uint256[](1); - ids[0] = id; - _handleTransmit(ids, registry, bytes4(0)); - } - - // tests multiple upkeeps, expects success - function _transmit(uint256[] memory ids, Registry registry) internal { - _handleTransmit(ids, registry, bytes4(0)); - } - - // tests single upkeep, expects revert - function _transmitAndExpectRevert(uint256 id, Registry registry, bytes4 selector) internal { - uint256[] memory ids = new uint256[](1); - ids[0] = id; - _handleTransmit(ids, registry, selector); - } - - // private function not exposed to actual testing contract - function _handleTransmit(uint256[] memory ids, Registry registry, bytes4 selector) private { - bytes memory reportBytes; - { - uint256[] memory upkeepIds = new uint256[](ids.length); - uint256[] memory gasLimits = new uint256[](ids.length); - bytes[] memory performDatas = new bytes[](ids.length); - bytes[] memory triggers = new bytes[](ids.length); - for (uint256 i = 0; i < ids.length; i++) { - upkeepIds[i] = ids[i]; - gasLimits[i] = registry.getUpkeep(ids[i]).performGas; - performDatas[i] = new bytes(0); - uint8 triggerType = registry.getTriggerType(ids[i]); - if (triggerType == 0) { - triggers[i] = _encodeConditionalTrigger( - AutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) - ); - } else { - revert("not implemented"); - } - } - - AutoBase.Report memory report = AutoBase.Report( - uint256(1000000000), - uint256(2000000000), - upkeepIds, - gasLimits, - triggers, - performDatas - ); - - reportBytes = _encodeReport(report); - } - (, , bytes32 configDigest) = registry.latestConfigDetails(); - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - uint256[] memory signerPKs = new uint256[](2); - signerPKs[0] = SIGNING_KEY0; - signerPKs[1] = SIGNING_KEY1; - (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); - - vm.startPrank(TRANSMITTERS[0]); - if (selector != bytes4(0)) { - vm.expectRevert(selector); - } - registry.transmit(reportContext, reportBytes, rs, ss, vs); - vm.stopPrank(); - } - - /// @notice Gather signatures on report data - /// @param report - Report bytes generated from `_buildReport` - /// @param reportContext - Report context bytes32 generated from `_buildReport` - /// @param signerPrivateKeys - One or more addresses that will sign the report data - /// @return rawRs - Signature rs - /// @return rawSs - Signature ss - /// @return rawVs - Signature vs - function _signReport( - bytes memory report, - bytes32[3] memory reportContext, - uint256[] memory signerPrivateKeys - ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { - bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); - bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); - bytes memory vs = new bytes(signerPrivateKeys.length); - - bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - for (uint256 i = 0; i < signerPrivateKeys.length; i++) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); - rs[i] = r; - ss[i] = s; - vs[i] = bytes1(v - 27); - } - - return (rs, ss, bytes32(vs)); - } - - function _encodeReport(AutoBase.Report memory report) internal pure returns (bytes memory reportBytes) { - return abi.encode(report); - } - - function _encodeConditionalTrigger( - AutoBase.ConditionalTrigger memory trigger - ) internal pure returns (bytes memory triggerBytes) { - return abi.encode(trigger.blockNum, trigger.blockHash); - } - - /// @dev mints LINK to the recipient - function _mintLink(address recipient, uint256 amount) internal { - vm.prank(OWNER); - linkToken.mint(recipient, amount); - } - - /// @dev mints USDToken with 18 decimals to the recipient - function _mintERC20_18Decimals(address recipient, uint256 amount) internal { - vm.prank(OWNER); - usdToken18.mint(recipient, amount); - } - - /// @dev returns a pseudo-random 32 bytes - function _random() private returns (bytes32) { - nonce++; - return keccak256(abi.encode(block.timestamp, nonce)); - } - - /// @dev returns a pseudo-random number - function randomNumber() internal returns (uint256) { - return uint256(_random()); - } - - /// @dev returns a pseudo-random address - function randomAddress() internal returns (address) { - return address(uint160(randomNumber())); - } - - /// @dev returns a pseudo-random byte array - function randomBytes(uint256 length) internal returns (bytes memory) { - bytes memory result = new bytes(length); - bytes32 entropy; - for (uint256 i = 0; i < length; i++) { - if (i % 32 == 0) { - entropy = _random(); - } - result[i] = entropy[i % 32]; - } - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol deleted file mode 100644 index cde05ab..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/BaseTest.t.sol +++ /dev/null @@ -1,500 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import "forge-std/Test.sol"; - -import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; -import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; -import {UpkeepTranscoder5_0 as Transcoder} from "../../v2_3/UpkeepTranscoder5_0.sol"; -import {ZKSyncAutomationRegistry2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistry2_3.sol"; -import {ZKSyncAutomationRegistryLogicA2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol"; -import {ZKSyncAutomationRegistryLogicB2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol"; -import {ZKSyncAutomationRegistryLogicC2_3} from "../../v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol"; -import {ZKSyncAutomationRegistryBase2_3 as ZKSyncAutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {AutomationRegistrar2_3} from "../../v2_3/AutomationRegistrar2_3.sol"; -import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; -import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; -import {WETH9} from "../WETH9.sol"; -import {MockGasBoundCaller} from "../../../tests/MockGasBoundCaller.sol"; -import {MockZKSyncSystemContext} from "../../../tests/MockZKSyncSystemContext.sol"; - -/** - * @title BaseTest provides basic test setup procedures and dependencies for use by other - * unit tests - */ -contract BaseTest is Test { - // test state (not exposed to derived tests) - uint256 private nonce; - - // constants - address internal constant ZERO_ADDRESS = address(0); - uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; - uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; - - // config - uint8 internal constant F = 1; // number of faulty nodes - uint64 internal constant OFFCHAIN_CONFIG_VERSION = 30; // 2 for OCR2 - - // contracts - LinkToken internal linkToken; - ERC20Mock6Decimals internal usdToken6; - ERC20Mock internal usdToken18; - ERC20Mock internal usdToken18_2; - WETH9 internal weth; - MockV3Aggregator internal LINK_USD_FEED; - MockV3Aggregator internal NATIVE_USD_FEED; - MockV3Aggregator internal USDTOKEN_USD_FEED; - MockV3Aggregator internal FAST_GAS_FEED; - MockUpkeep internal TARGET1; - MockUpkeep internal TARGET2; - Transcoder internal TRANSCODER; - MockGasBoundCaller internal GAS_BOUND_CALLER; - MockZKSyncSystemContext internal SYSTEM_CONTEXT; - - // roles - address internal constant OWNER = address(uint160(uint256(keccak256("OWNER")))); - address internal constant UPKEEP_ADMIN = address(uint160(uint256(keccak256("UPKEEP_ADMIN")))); - address internal constant FINANCE_ADMIN = address(uint160(uint256(keccak256("FINANCE_ADMIN")))); - address internal constant STRANGER = address(uint160(uint256(keccak256("STRANGER")))); - address internal constant BROKE_USER = address(uint160(uint256(keccak256("BROKE_USER")))); // do not mint to this address - address internal constant PRIVILEGE_MANAGER = address(uint160(uint256(keccak256("PRIVILEGE_MANAGER")))); - - // nodes - uint256 internal constant SIGNING_KEY0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - uint256 internal constant SIGNING_KEY1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; - uint256 internal constant SIGNING_KEY2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; - uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; - address[] internal SIGNERS = new address[](4); - address[] internal TRANSMITTERS = new address[](4); - address[] internal NEW_TRANSMITTERS = new address[](4); - address[] internal PAYEES = new address[](4); - address[] internal NEW_PAYEES = new address[](4); - - function setUp() public virtual { - vm.startPrank(OWNER); - linkToken = new LinkToken(); - linkToken.grantMintRole(OWNER); - usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); - usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0); - usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); - weth = new WETH9(); - - LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 - NATIVE_USD_FEED = new MockV3Aggregator(8, 400_000_000_000); // $4,000 - USDTOKEN_USD_FEED = new MockV3Aggregator(8, 100_000_000); // $1 - FAST_GAS_FEED = new MockV3Aggregator(0, 1_000_000_000); // 1 gwei - - TARGET1 = new MockUpkeep(); - TARGET2 = new MockUpkeep(); - - TRANSCODER = new Transcoder(); - GAS_BOUND_CALLER = new MockGasBoundCaller(); - SYSTEM_CONTEXT = new MockZKSyncSystemContext(); - - bytes memory callerCode = address(GAS_BOUND_CALLER).code; - vm.etch(0xc706EC7dfA5D4Dc87f29f859094165E8290530f5, callerCode); - - bytes memory contextCode = address(SYSTEM_CONTEXT).code; - vm.etch(0x000000000000000000000000000000000000800B, contextCode); - - SIGNERS[0] = vm.addr(SIGNING_KEY0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 - SIGNERS[1] = vm.addr(SIGNING_KEY1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 - SIGNERS[2] = vm.addr(SIGNING_KEY2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b - SIGNERS[3] = vm.addr(SIGNING_KEY3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 - - TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); - TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); - TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); - TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); - NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); - NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); - NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); - NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); - - PAYEES[0] = address(100); - PAYEES[1] = address(101); - PAYEES[2] = address(102); - PAYEES[3] = address(103); - NEW_PAYEES[0] = address(100); - NEW_PAYEES[1] = address(101); - NEW_PAYEES[2] = address(106); - NEW_PAYEES[3] = address(107); - - // mint funds - vm.deal(OWNER, 100 ether); - vm.deal(UPKEEP_ADMIN, 100 ether); - vm.deal(FINANCE_ADMIN, 100 ether); - vm.deal(STRANGER, 100 ether); - - linkToken.mint(OWNER, 1000e18); - linkToken.mint(UPKEEP_ADMIN, 1000e18); - linkToken.mint(FINANCE_ADMIN, 1000e18); - linkToken.mint(STRANGER, 1000e18); - - usdToken18.mint(OWNER, 1000e18); - usdToken18.mint(UPKEEP_ADMIN, 1000e18); - usdToken18.mint(FINANCE_ADMIN, 1000e18); - usdToken18.mint(STRANGER, 1000e18); - - usdToken18_2.mint(UPKEEP_ADMIN, 1000e18); - - usdToken6.mint(OWNER, 1000e6); - usdToken6.mint(UPKEEP_ADMIN, 1000e6); - usdToken6.mint(FINANCE_ADMIN, 1000e6); - usdToken6.mint(STRANGER, 1000e6); - - weth.mint(OWNER, 1000e18); - weth.mint(UPKEEP_ADMIN, 1000e18); - weth.mint(FINANCE_ADMIN, 1000e18); - weth.mint(STRANGER, 1000e18); - - vm.stopPrank(); - } - - /// @notice deploys the component parts of a registry, but nothing more - function deployZKSyncRegistry(ZKSyncAutoBase.PayoutMode payoutMode) internal returns (Registry) { - AutomationForwarderLogic forwarderLogic = new AutomationForwarderLogic(); - ZKSyncAutomationRegistryLogicC2_3 logicC2_3 = new ZKSyncAutomationRegistryLogicC2_3( - address(linkToken), - address(LINK_USD_FEED), - address(NATIVE_USD_FEED), - address(FAST_GAS_FEED), - address(forwarderLogic), - ZERO_ADDRESS, - payoutMode, - address(weth) - ); - ZKSyncAutomationRegistryLogicB2_3 logicB2_3 = new ZKSyncAutomationRegistryLogicB2_3(logicC2_3); - ZKSyncAutomationRegistryLogicA2_3 logicA2_3 = new ZKSyncAutomationRegistryLogicA2_3(logicB2_3); - return Registry(payable(address(new ZKSyncAutomationRegistry2_3(logicA2_3)))); - } - - /// @notice deploys and configures a registry, registrar, and everything needed for most tests - function deployAndConfigureZKSyncRegistryAndRegistrar( - ZKSyncAutoBase.PayoutMode payoutMode - ) internal returns (Registry, AutomationRegistrar2_3) { - Registry registry = deployZKSyncRegistry(payoutMode); - - IERC20[] memory billingTokens = new IERC20[](4); - billingTokens[0] = IERC20(address(usdToken18)); - billingTokens[1] = IERC20(address(weth)); - billingTokens[2] = IERC20(address(linkToken)); - billingTokens[3] = IERC20(address(usdToken6)); - uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100e18; // 100 USD - minRegistrationFees[1] = 5e18; // 5 Native - minRegistrationFees[2] = 5e18; // 5 LINK - minRegistrationFees[3] = 100e6; // 100 USD - address[] memory billingTokenAddresses = new address[](billingTokens.length); - for (uint256 i = 0; i < billingTokens.length; i++) { - billingTokenAddresses[i] = address(billingTokens[i]); - } - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100_000_000, // $1 - minSpend: 1e18, // 1 USD - decimals: 18 - }); - billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(NATIVE_USD_FEED), - fallbackPrice: 100_000_000, // $1 - minSpend: 5e18, // 5 Native - decimals: 18 - }); - billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(LINK_USD_FEED), - fallbackPrice: 1_000_000_000, // $10 - minSpend: 1e18, // 1 LINK - decimals: 18 - }); - billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 1e8, // $1 - minSpend: 1e6, // 1 USD - decimals: 6 - }); - - if (payoutMode == ZKSyncAutoBase.PayoutMode.OFF_CHAIN) { - // remove LINK as a payment method if we are settling offchain - assembly { - mstore(billingTokens, 2) - mstore(minRegistrationFees, 2) - mstore(billingTokenAddresses, 2) - mstore(billingTokenConfigs, 2) - } - } - - // deploy registrar - AutomationRegistrar2_3.InitialTriggerConfig[] - memory triggerConfigs = new AutomationRegistrar2_3.InitialTriggerConfig[](2); - triggerConfigs[0] = AutomationRegistrar2_3.InitialTriggerConfig({ - triggerType: 0, // condition - autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, - autoApproveMaxAllowed: 0 - }); - triggerConfigs[1] = AutomationRegistrar2_3.InitialTriggerConfig({ - triggerType: 1, // log - autoApproveType: AutomationRegistrar2_3.AutoApproveType.DISABLED, - autoApproveMaxAllowed: 0 - }); - AutomationRegistrar2_3 registrar = new AutomationRegistrar2_3( - address(linkToken), - registry, - triggerConfigs, - billingTokens, - minRegistrationFees, - IWrappedNative(address(weth)) - ); - - address[] memory registrars; - registrars = new address[](1); - registrars[0] = address(registrar); - - AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 2, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: address(TRANSCODER), - registrars: registrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: address(new ChainModuleBase()), - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokenAddresses, - billingTokenConfigs - ); - return (registry, registrar); - } - - /// @notice this function updates the billing config for the provided token on the provided registry, - /// and throws an error if the token is not found - function _updateBillingTokenConfig( - Registry registry, - address billingToken, - AutomationRegistryBase2_3.BillingConfig memory newConfig - ) internal { - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); - address[] memory billingTokens = registry.getBillingTokens(); - - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - - bool found = false; - for (uint256 i = 0; i < billingTokens.length; i++) { - if (billingTokens[i] == billingToken) { - found = true; - billingTokenConfigs[i] = newConfig; - } else { - billingTokenConfigs[i] = registry.getBillingTokenConfig(billingTokens[i]); - } - } - require(found, "could not find billing token provided on registry"); - - registry.setConfigTypeSafe( - signers, - transmitters, - f, - config, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokens, - billingTokenConfigs - ); - } - - /// @notice this function removes a billing token from the registry - function _removeBillingTokenConfig(Registry registry, address billingToken) internal { - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - AutomationRegistryBase2_3.OnchainConfig memory config = registry.getConfig(); - address[] memory billingTokens = registry.getBillingTokens(); - - address[] memory newBillingTokens = new address[](billingTokens.length - 1); - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length - 1); - - uint256 j = 0; - for (uint256 i = 0; i < billingTokens.length; i++) { - if (billingTokens[i] != billingToken) { - if (j == newBillingTokens.length) revert("could not find billing token provided on registry"); - newBillingTokens[j] = billingTokens[i]; - billingTokenConfigs[j] = registry.getBillingTokenConfig(billingTokens[i]); - j++; - } - } - - registry.setConfigTypeSafe( - signers, - transmitters, - f, - config, - OFFCHAIN_CONFIG_VERSION, - "", - newBillingTokens, - billingTokenConfigs - ); - } - - function _transmit(uint256 id, Registry registry, bytes4 selector) internal { - uint256[] memory ids = new uint256[](1); - ids[0] = id; - _transmit(ids, registry, selector); - } - - function _transmit(uint256[] memory ids, Registry registry, bytes4 selector) internal { - bytes memory reportBytes; - { - uint256[] memory upkeepIds = new uint256[](ids.length); - uint256[] memory gasLimits = new uint256[](ids.length); - bytes[] memory performDatas = new bytes[](ids.length); - bytes[] memory triggers = new bytes[](ids.length); - for (uint256 i = 0; i < ids.length; i++) { - upkeepIds[i] = ids[i]; - gasLimits[i] = registry.getUpkeep(ids[i]).performGas; - performDatas[i] = new bytes(0); - uint8 triggerType = registry.getTriggerType(ids[i]); - if (triggerType == 0) { - triggers[i] = _encodeConditionalTrigger( - ZKSyncAutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) - ); - } else { - revert("not implemented"); - } - } - ZKSyncAutoBase.Report memory report = ZKSyncAutoBase.Report( - uint256(1000000000), - uint256(2000000000), - upkeepIds, - gasLimits, - triggers, - performDatas - ); - - reportBytes = _encodeReport(report); - } - (, , bytes32 configDigest) = registry.latestConfigDetails(); - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - uint256[] memory signerPKs = new uint256[](2); - signerPKs[0] = SIGNING_KEY0; - signerPKs[1] = SIGNING_KEY1; - (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); - - vm.startPrank(TRANSMITTERS[0]); - if (selector != bytes4(0)) { - vm.expectRevert(selector); - } - registry.transmit(reportContext, reportBytes, rs, ss, vs); - vm.stopPrank(); - } - - /// @notice Gather signatures on report data - /// @param report - Report bytes generated from `_buildReport` - /// @param reportContext - Report context bytes32 generated from `_buildReport` - /// @param signerPrivateKeys - One or more addresses that will sign the report data - /// @return rawRs - Signature rs - /// @return rawSs - Signature ss - /// @return rawVs - Signature vs - function _signReport( - bytes memory report, - bytes32[3] memory reportContext, - uint256[] memory signerPrivateKeys - ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { - bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); - bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); - bytes memory vs = new bytes(signerPrivateKeys.length); - - bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - for (uint256 i = 0; i < signerPrivateKeys.length; i++) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); - rs[i] = r; - ss[i] = s; - vs[i] = bytes1(v - 27); - } - - return (rs, ss, bytes32(vs)); - } - - function _encodeReport(ZKSyncAutoBase.Report memory report) internal pure returns (bytes memory reportBytes) { - return abi.encode(report); - } - - function _encodeConditionalTrigger( - ZKSyncAutoBase.ConditionalTrigger memory trigger - ) internal pure returns (bytes memory triggerBytes) { - return abi.encode(trigger.blockNum, trigger.blockHash); - } - - /// @dev mints LINK to the recipient - function _mintLink(address recipient, uint256 amount) internal { - vm.prank(OWNER); - linkToken.mint(recipient, amount); - } - - /// @dev mints USDToken with 18 decimals to the recipient - function _mintERC20_18Decimals(address recipient, uint256 amount) internal { - vm.prank(OWNER); - usdToken18.mint(recipient, amount); - } - - /// @dev returns a pseudo-random 32 bytes - function _random() private returns (bytes32) { - nonce++; - return keccak256(abi.encode(block.timestamp, nonce)); - } - - /// @dev returns a pseudo-random number - function randomNumber() internal returns (uint256) { - return uint256(_random()); - } - - /// @dev returns a pseudo-random address - function randomAddress() internal returns (address) { - return address(uint160(randomNumber())); - } - - /// @dev returns a pseudo-random byte array - function randomBytes(uint256 length) internal returns (bytes memory) { - bytes memory result = new bytes(length); - bytes32 entropy; - for (uint256 i = 0; i < length; i++) { - if (i % 32 == 0) { - entropy = _random(); - } - result[i] = entropy[i % 32]; - } - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol deleted file mode 100644 index 7098d9f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol +++ /dev/null @@ -1,2772 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {Vm} from "forge-std/Test.sol"; -import {BaseTest} from "./BaseTest.t.sol"; -import {ZKSyncAutomationRegistryBase2_3 as AutoBase} from "../../v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol"; -import {AutomationRegistrar2_3 as Registrar} from "../../v2_3/AutomationRegistrar2_3.sol"; -import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3, IAutomationV21PlusCommon} from "../../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IWrappedNative} from "../../interfaces/v2_3/IWrappedNative.sol"; - -// forge test --match-path src/v0.8/automation/test/v2_3_zksync/ZKSyncAutomationRegistry2_3.t.sol --match-test - -enum Trigger { - CONDITION, - LOG -} - -contract SetUp is BaseTest { - Registry internal registry; - AutomationRegistryBase2_3.OnchainConfig internal config; - bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); - - uint256 linkUpkeepID; - uint256 linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario - uint256 usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals - uint256 usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals - uint256 nativeUpkeepID; - - function setUp() public virtual override { - super.setUp(); - (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - config = registry.getConfig(); - - vm.startPrank(OWNER); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.startPrank(UPKEEP_ADMIN); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.startPrank(STRANGER); - linkToken.approve(address(registry), type(uint256).max); - usdToken6.approve(address(registry), type(uint256).max); - usdToken18.approve(address(registry), type(uint256).max); - weth.approve(address(registry), type(uint256).max); - vm.stopPrank(); - - linkUpkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - - linkUpkeepID2 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - - usdUpkeepID18 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(usdToken18), - "", - "", - "" - ); - - usdUpkeepID6 = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(usdToken6), - "", - "", - "" - ); - - nativeUpkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(weth), - "", - "", - "" - ); - - vm.startPrank(OWNER); - registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); - registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); - registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); - registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); - registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); - vm.stopPrank(); - } -} - -contract LatestConfigDetails is SetUp { - function testGet() public { - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = registry.latestConfigDetails(); - assertEq(configCount, 1); - assertTrue(blockNumber > 0); - assertNotEq(configDigest, ""); - } -} - -contract CheckUpkeep is SetUp { - function testPreventExecutionOnCheckUpkeep() public { - uint256 id = 1; - bytes memory triggerData = abi.encodePacked("trigger_data"); - - // The tx.origin is the DEFAULT_SENDER (0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38) of foundry - // Expecting a revert since the tx.origin is not address(0) - vm.expectRevert(abi.encodeWithSelector(Registry.OnlySimulatedBackend.selector)); - registry.checkUpkeep(id, triggerData); - } -} - -contract WithdrawFunds is SetUp { - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - - function test_RevertsWhen_CalledByNonAdmin() external { - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - vm.prank(STRANGER); - registry.withdrawFunds(linkUpkeepID, STRANGER); - } - - function test_RevertsWhen_InvalidRecipient() external { - vm.expectRevert(Registry.InvalidRecipient.selector); - vm.prank(UPKEEP_ADMIN); - registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS); - } - - function test_RevertsWhen_UpkeepNotCanceled() external { - vm.expectRevert(Registry.UpkeepNotCanceled.selector); - vm.prank(UPKEEP_ADMIN); - registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); - } - - function test_Happy_Link() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - vm.roll(100 + block.number); - - uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN); - uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken)); - - uint256 upkeepBalance = registry.getBalance(linkUpkeepID); - vm.expectEmit(); - emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN)); - registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN); - - assertEq(registry.getBalance(linkUpkeepID), 0); - assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); - assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance); - } - - function test_Happy_USDToken() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(usdUpkeepID6); - vm.roll(100 + block.number); - - uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN); - uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6)); - - uint256 upkeepBalance = registry.getBalance(usdUpkeepID6); - vm.expectEmit(); - emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN)); - registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN); - - assertEq(registry.getBalance(usdUpkeepID6), 0); - assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance); - assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance); - } -} - -contract AddFunds is SetUp { - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - - // when msg.value is 0, it uses the ERC20 payment path - function test_HappyWhen_NativeUpkeep_WithMsgValue0() external { - vm.startPrank(OWNER); - uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); - uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); - registry.addFunds(nativeUpkeepID, 1); - assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); - assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); - assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); - } - - // when msg.value is not 0, it uses the native payment path - function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external { - uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID); - uint256 startTokenBalance = registry.getBalance(nativeUpkeepID); - registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored - assertEq(registry.getBalance(nativeUpkeepID), startRegistryBalance + 1); - assertEq(weth.balanceOf(address(registry)), startTokenBalance + 1); - assertEq(registry.getAvailableERC20ForPayment(address(weth)), 0); - } - - // it fails when the billing token is not native, but trying to pay with native - function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.addFunds{value: 1}(linkUpkeepID, 0); - } - - function test_RevertsWhen_UpkeepDoesNotExist() public { - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.addFunds(randomNumber(), 1); - } - - function test_RevertsWhen_UpkeepIsCanceled() public { - registry.cancelUpkeep(linkUpkeepID); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.addFunds(linkUpkeepID, 1); - } - - function test_anyoneCanAddFunds() public { - uint256 startAmount = registry.getBalance(linkUpkeepID); - vm.prank(UPKEEP_ADMIN); - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); - vm.prank(STRANGER); - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); - } - - function test_movesFundFromCorrectToken() public { - vm.startPrank(UPKEEP_ADMIN); - - uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); - uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); - uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); - uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); - - registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); - assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); - - registry.addFunds(usdUpkeepID18, 2); - assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); - assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); - } - - function test_emitsAnEvent() public { - vm.startPrank(UPKEEP_ADMIN); - vm.expectEmit(); - emit FundsAdded(linkUpkeepID, address(UPKEEP_ADMIN), 100); - registry.addFunds(linkUpkeepID, 100); - } -} - -contract Withdraw is SetUp { - address internal aMockAddress = randomAddress(); - - function testLinkAvailableForPaymentReturnsLinkBalance() public { - uint256 startBalance = linkToken.balanceOf(address(registry)); - int256 startLinkAvailable = registry.linkAvailableForPayment(); - - //simulate a deposit of link to the liquidity pool - _mintLink(address(registry), 1e10); - - //check there's a balance - assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); - - //check the link available has increased by the same amount - assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); - } - - function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { - vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); - registry.withdrawLink(aMockAddress, 1); - } - - function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is 0 balance - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawLink(aMockAddress, 1); - - vm.stopPrank(); - } - - function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is 0 balance - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); - registry.withdrawLink(ZERO_ADDRESS, 1); - - vm.stopPrank(); - } - - function testWithdrawLinkSuccess() public { - //simulate a deposit of link to the liquidity pool - _mintLink(address(registry), 1e10); - uint256 startBalance = linkToken.balanceOf(address(registry)); - - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 link while there is a ton of link available - registry.withdrawLink(aMockAddress, 1); - - vm.stopPrank(); - - assertEq(linkToken.balanceOf(address(aMockAddress)), 1); - assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); - } - - function test_WithdrawERC20Fees_RespectsReserveAmount() public { - assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); - } - - function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { - _mintLink(address(registry), 1e10); - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(Registry.InvalidToken.selector); - registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert - registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds - } - - // default is ON_CHAIN mode - function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { - _transmit(usdUpkeepID18, registry, bytes4(0)); // adds USD token to finance withdrawable, and gives NOPs a LINK balance - require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); - require( - registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, - "ERC20AvailableForPayment should be positive" - ); - vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert - _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw - } - - function test_WithdrawERC20Fees_InOffChainMode_Happy() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry, bytes4(0)); - require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); - vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); // finance can withdraw - - // recipient should get the funds - assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); - } - - function testWithdrawERC20FeeSuccess() public { - // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) - uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); - uint256 startAmount = usdToken18.balanceOf(address(registry)); - _mintERC20_18Decimals(address(registry), 1e10); - - // depositing shouldn't change reserve amount - assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); - - vm.startPrank(FINANCE_ADMIN); - - // try to withdraw 1 USDToken - registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); - - vm.stopPrank(); - - assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); - assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); - assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); - } -} - -contract SetConfig is SetUp { - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - address module = address(new ChainModuleBase()); - - AutomationRegistryBase2_3.OnchainConfig cfg = - AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 0, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: _getRegistrars(), - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: module, - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - function testSetConfigSuccess() public { - (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress = address(usdToken18); - address[] memory billingTokens = new address[](1); - billingTokens[0] = billingTokenAddress; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - bytes memory onchainConfigBytes = abi.encode(cfg); - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - bytes32 configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); - assertEq(config.gasFeePPB, 5_000); - assertEq(config.flatFeeMilliCents, 20_000); - assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config.minSpend, 100_000); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 1); - } - - function testSetConfigMultipleBillingConfigsSuccess() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress1 = address(linkToken); - address billingTokenAddress2 = address(usdToken18); - address[] memory billingTokens = new address[](2); - billingTokens[0] = billingTokenAddress1; - billingTokens[1] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, , address[] memory signers, address[] memory transmitters, uint8 f) = registry.getState(); - - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); - assertEq(config1.gasFeePPB, 5_001); - assertEq(config1.flatFeeMilliCents, 20_001); - assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config1.fallbackPrice, 100); - assertEq(config1.minSpend, 100); - - AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); - assertEq(config2.gasFeePPB, 5_002); - assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config2.fallbackPrice, 200); - assertEq(config2.minSpend, 200); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 2); - } - - function testSetConfigTwiceAndLastSetOverwrites() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - // BillingConfig1 - address billingTokenAddress1 = address(usdToken18); - address[] memory billingTokens1 = new address[](1); - billingTokens1[0] = billingTokenAddress1; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs1 = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - - // the first time uses the default onchain config with 2 registrars - bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); - - // set config once - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling1, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - (, IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig1, , , ) = registry.getState(); - assertEq(onchainConfig1.registrars.length, 2); - - // BillingConfig2 - address billingTokenAddress2 = address(usdToken18); - address[] memory billingTokens2 = new address[](1); - billingTokens2[0] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs2 = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - address[] memory newRegistrars = new address[](3); - newRegistrars[0] = address(uint160(uint256(keccak256("newRegistrar1")))); - newRegistrars[1] = address(uint160(uint256(keccak256("newRegistrar2")))); - newRegistrars[2] = address(uint160(uint256(keccak256("newRegistrar3")))); - - // new onchain config with 3 new registrars, all other fields stay the same as the default - AutomationRegistryBase2_3.OnchainConfig memory cfg2 = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 0, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: newRegistrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: module, - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - // the second time uses the new onchain config with 3 new registrars and also new billing tokens/configs - bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg2, billingTokens2, billingConfigs2); - - // set config twice - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling2, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - ( - , - IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig2, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) = registry.getState(); - - assertEq(onchainConfig2.registrars.length, 3); - for (uint256 i = 0; i < newRegistrars.length; i++) { - assertEq(newRegistrars[i], onchainConfig2.registrars[i]); - } - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - assertEq(f, F); - - AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); - assertEq(config2.gasFeePPB, 5_002); - assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); - assertEq(config2.fallbackPrice, 200); - assertEq(config2.minSpend, 200); - - address[] memory tokens = registry.getBillingTokens(); - assertEq(tokens.length, 1); - } - - function testSetConfigDuplicateBillingConfigFailure() public { - (uint32 configCount, , ) = registry.latestConfigDetails(); - assertEq(configCount, 1); - - address billingTokenAddress1 = address(linkToken); - address billingTokenAddress2 = address(linkToken); - address[] memory billingTokens = new address[](2); - billingTokens[0] = billingTokenAddress1; - billingTokens[1] = billingTokenAddress2; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](2); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_001, - flatFeeMilliCents: 20_001, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100, - minSpend: 100, - decimals: 18 - }); - billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_002, - flatFeeMilliCents: 20_002, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 200, - minSpend: 200, - decimals: 18 - }); - - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); - - // expect revert because of duplicate tokens - vm.expectRevert(abi.encodeWithSelector(Registry.DuplicateEntry.selector)); - registry.setConfig( - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytesWithBilling, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - } - - function testSetConfigRevertDueToInvalidToken() public { - address[] memory billingTokens = new address[](1); - billingTokens[0] = address(linkToken); - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - // deploy registry with OFF_CHAIN payout mode - registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); - - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - } - - function testSetConfigRevertDueToInvalidDecimals() public { - address[] memory billingTokens = new address[](1); - billingTokens[0] = address(linkToken); - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 6 // link token should have 18 decimals - }); - - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - } - - function testSetConfigOnTransmittersAndPayees() public { - registry.setPayees(PAYEES); - AutomationRegistryBase2_3.TransmitterPayeeInfo[] memory transmitterPayeeInfos = registry - .getTransmittersWithPayees(); - assertEq(transmitterPayeeInfos.length, TRANSMITTERS.length); - - for (uint256 i = 0; i < transmitterPayeeInfos.length; i++) { - address transmitterAddress = transmitterPayeeInfos[i].transmitterAddress; - address payeeAddress = transmitterPayeeInfos[i].payeeAddress; - - address expectedTransmitter = TRANSMITTERS[i]; - address expectedPayee = PAYEES[i]; - - assertEq(transmitterAddress, expectedTransmitter); - assertEq(payeeAddress, expectedPayee); - } - } - - function testSetConfigWithNewTransmittersSuccess() public { - registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); - - (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); - assertEq(configCount, 0); - - address billingTokenAddress = address(usdToken18); - address[] memory billingTokens = new address[](1); - billingTokens[0] = billingTokenAddress; - - AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); - billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000, - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000, - decimals: 18 - }); - - bytes memory onchainConfigBytes = abi.encode(cfg); - - bytes32 configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfigTypeSafe( - SIGNERS, - TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - - (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); - assertEq(signers, SIGNERS); - assertEq(transmitters, TRANSMITTERS); - - (configCount, blockNumber, ) = registry.latestConfigDetails(); - configDigest = _configDigestFromConfigData( - block.chainid, - address(registry), - ++configCount, - SIGNERS, - NEW_TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - vm.expectEmit(); - emit ConfigSet( - blockNumber, - configDigest, - configCount, - SIGNERS, - NEW_TRANSMITTERS, - F, - onchainConfigBytes, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes - ); - - registry.setConfigTypeSafe( - SIGNERS, - NEW_TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - offchainConfigBytes, - billingTokens, - billingConfigs - ); - - (, , signers, transmitters, ) = registry.getState(); - assertEq(signers, SIGNERS); - assertEq(transmitters, NEW_TRANSMITTERS); - } - - function _getRegistrars() private pure returns (address[] memory) { - address[] memory registrars = new address[](2); - registrars[0] = address(uint160(uint256(keccak256("registrar1")))); - registrars[1] = address(uint160(uint256(keccak256("registrar2")))); - return registrars; - } - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } -} - -contract NOPsSettlement is SetUp { - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - - function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); - registry.settleNOPsOffchain(); - } - - function testSettleNOPsOffchainRevertDueToOffchainSettlementDisabled() public { - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - vm.prank(FINANCE_ADMIN); - vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOnchain.selector)); - registry.settleNOPsOffchain(); - } - - function testSettleNOPsOffchainSuccess() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - uint256[] memory payments = new uint256[](TRANSMITTERS.length); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - payments[i] = 0; - } - - vm.startPrank(FINANCE_ADMIN); - vm.expectEmit(); - emit NOPsSettledOffchain(PAYEES, payments); - registry.settleNOPsOffchain(); - } - - // 1. transmitter balance zeroed after settlement, 2. admin can withdraw ERC20, 3. switch to onchain mode, 4. link amount owed to NOPs stays the same - function testSettleNOPsOffchainSuccessWithERC20MultiSteps() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry, bytes4(0)); - - // verify transmitters have positive balances - uint256[] memory payments = new uint256[](TRANSMITTERS.length); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertTrue(balance > 0); - assertEq(0, lastCollected); - - payments[i] = balance; - } - - // verify offchain settlement will emit NOPs' balances - vm.startPrank(FINANCE_ADMIN); - vm.expectEmit(); - emit NOPsSettledOffchain(PAYEES, payments); - registry.settleNOPsOffchain(); - - // verify that transmitters balance has been zeroed out - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertEq(0, balance); - } - - // after the offchain settlement, the total reserve amount of LINK should be 0 - assertEq(registry.getReserveAmount(address(linkToken)), 0); - // should have some ERC20s in registry after transmit - uint256 erc20ForPayment1 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment1 > 0, "ERC20AvailableForPayment should be positive"); - - vm.startPrank(UPKEEP_ADMIN); - vm.roll(100 + block.number); - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry, bytes4(0)); - - uint256 erc20ForPayment2 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment2 > erc20ForPayment1, "ERC20AvailableForPayment should be greater after another transmit"); - - // finance admin comes to withdraw all available ERC20s - vm.startPrank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment2); - - uint256 erc20ForPayment3 = registry.getAvailableERC20ForPayment(address(usdToken18)); - require(erc20ForPayment3 == 0, "ERC20AvailableForPayment should be 0 now after withdrawal"); - - uint256 reservedLink = registry.getReserveAmount(address(linkToken)); - require(reservedLink > 0, "Reserve amount of LINK should be positive since there was another transmit"); - - // owner comes to disable offchain mode - vm.startPrank(registry.owner()); - registry.disableOffchainPayments(); - - // finance admin comes to withdraw all available ERC20s, should revert bc of insufficient link liquidity - vm.startPrank(FINANCE_ADMIN); - uint256 erc20ForPayment4 = registry.getAvailableERC20ForPayment(address(usdToken18)); - vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientLinkLiquidity.selector)); - registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, erc20ForPayment4); - - // reserved link amount to NOPs should stay the same after switching to onchain mode - assertEq(registry.getReserveAmount(address(linkToken)), reservedLink); - // available ERC20 for payment should be 0 since finance admin withdrew all already - assertEq(erc20ForPayment4, 0); - } - - function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, Registrar registrar) = deployAndConfigureZKSyncRegistryAndRegistrar( - AutoBase.PayoutMode.OFF_CHAIN - ); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so TRANSMITTERS earn some rewards - _transmit(id, registry, bytes4(0)); - - // TRANSMITTERS have positive balance now - // configure the registry to use NEW_TRANSMITTERS - _configureWithNewTransmitters(registry, registrar); - - _transmit(id, registry, bytes4(0)); - - // verify all transmitters have positive balances - address[] memory expectedPayees = new address[](6); - uint256[] memory expectedPayments = new uint256[](6); - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( - NEW_TRANSMITTERS[i] - ); - assertTrue(active); - assertEq(i, index); - assertTrue(lastCollected > 0); - expectedPayments[i] = balance; - expectedPayees[i] = payee; - } - for (uint256 i = 2; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( - TRANSMITTERS[i] - ); - assertFalse(active); - assertEq(i, index); - assertTrue(balance > 0); - assertTrue(lastCollected > 0); - expectedPayments[2 + i] = balance; - expectedPayees[2 + i] = payee; - } - - // verify offchain settlement will emit NOPs' balances - vm.startPrank(FINANCE_ADMIN); - - // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these - // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. - vm.recordLogs(); - registry.settleNOPsOffchain(); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 1); - Vm.Log memory l = entries[0]; - assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); - (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); - assertEq(actualPayees.length, 6); - assertEq(actualPayments.length, 6); - - // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - assertEq(actualPayees[i], expectedPayees[i]); - assertEq(actualPayments[i], expectedPayments[i]); - } - - // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered - assertTrue( - (actualPayments[5] == expectedPayments[5] && - actualPayees[5] == expectedPayees[5] && - actualPayments[4] == expectedPayments[4] && - actualPayees[4] == expectedPayees[4]) || - (actualPayments[5] == expectedPayments[4] && - actualPayees[5] == expectedPayees[4] && - actualPayments[4] == expectedPayments[5] && - actualPayees[4] == expectedPayees[5]) - ); - - // verify that new transmitters balance has been zeroed out - for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); - assertTrue(active); - assertEq(i, index); - assertEq(0, balance); - } - // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out - for (uint256 i = 2; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertFalse(active); - assertEq(i, index); - assertEq(0, balance); - } - - // after the offchain settlement, the total reserve amount of LINK should be 0 - assertEq(registry.getReserveAmount(address(linkToken)), 0); - } - - function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.startPrank(FINANCE_ADMIN); - vm.expectRevert(bytes("Only callable by owner")); - registry.disableOffchainPayments(); - } - - function testDisableOffchainPaymentsSuccess() public { - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - - vm.startPrank(registry.owner()); - registry.disableOffchainPayments(); - - assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); - } - - function testSinglePerformAndNodesCanWithdrawOnchain() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually create a transmit so transmitters earn some rewards - _transmit(id, registry, bytes4(0)); - - // disable offchain payments - _mintLink(address(registry), 1e19); - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - // payees should be able to withdraw onchain - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - vm.prank(payee); - vm.expectEmit(); - emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); - registry.withdrawPayment(TRANSMITTERS[i], payee); - } - - // allow upkeep admin to withdraw funds - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(id); - vm.roll(100 + block.number); - vm.expectEmit(); - // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value - emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); - registry.withdrawFunds(id, UPKEEP_ADMIN); - } - - function testMultiplePerformsAndNodesCanWithdrawOnchain() public { - // deploy and configure a registry with OFF_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); - registry.setPayees(PAYEES); - - // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(id, 1e20); - - // manually call transmit so transmitters earn some rewards - for (uint256 i = 0; i < 50; i++) { - vm.roll(100 + block.number); - _transmit(id, registry, bytes4(0)); - } - - // disable offchain payments - _mintLink(address(registry), 1e19); - vm.prank(registry.owner()); - registry.disableOffchainPayments(); - - // manually call transmit after offchain payment is disabled - for (uint256 i = 0; i < 50; i++) { - vm.roll(100 + block.number); - _transmit(id, registry, bytes4(0)); - } - - // payees should be able to withdraw onchain - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - vm.prank(payee); - vm.expectEmit(); - emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); - registry.withdrawPayment(TRANSMITTERS[i], payee); - } - - // allow upkeep admin to withdraw funds - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(id); - vm.roll(100 + block.number); - uint256 balance = registry.getBalance(id); - vm.expectEmit(); - emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); - registry.withdrawFunds(id, UPKEEP_ADMIN); - } - - function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { - IERC20[] memory billingTokens = new IERC20[](1); - billingTokens[0] = IERC20(address(usdToken18)); - - uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100e18; // 100 USD - - address[] memory billingTokenAddresses = new address[](billingTokens.length); - for (uint256 i = 0; i < billingTokens.length; i++) { - billingTokenAddresses[i] = address(billingTokens[i]); - } - - AutomationRegistryBase2_3.BillingConfig[] - memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); - billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 10_000_000, // 15% - flatFeeMilliCents: 2_000, // 2 cents - priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 1e8, // $1 - minSpend: 1e18, // 1 USD - decimals: 18 - }); - - address[] memory registrars = new address[](1); - registrars[0] = address(registrar); - - AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ - checkGasLimit: 5_000_000, - stalenessSeconds: 90_000, - gasCeilingMultiplier: 2, - maxPerformGas: 10_000_000, - maxCheckDataSize: 5_000, - maxPerformDataSize: 5_000, - maxRevertDataSize: 5_000, - fallbackGasPrice: 20_000_000_000, - fallbackLinkPrice: 2_000_000_000, // $20 - fallbackNativePrice: 400_000_000_000, // $4,000 - transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, - registrars: registrars, - upkeepPrivilegeManager: PRIVILEGE_MANAGER, - chainModule: address(new ChainModuleBase()), - reorgProtectionEnabled: true, - financeAdmin: FINANCE_ADMIN - }); - - registry.setConfigTypeSafe( - SIGNERS, - NEW_TRANSMITTERS, - F, - cfg, - OFFCHAIN_CONFIG_VERSION, - "", - billingTokenAddresses, - billingTokenConfigs - ); - - registry.setPayees(NEW_PAYEES); - } -} - -contract WithdrawPayment is SetUp { - function testWithdrawPaymentRevertDueToOffchainPayoutMode() public { - registry = deployZKSyncRegistry(AutoBase.PayoutMode.OFF_CHAIN); - vm.expectRevert(abi.encodeWithSelector(Registry.MustSettleOffchain.selector)); - vm.prank(TRANSMITTERS[0]); - registry.withdrawPayment(TRANSMITTERS[0], TRANSMITTERS[0]); - } -} - -contract RegisterUpkeep is SetUp { - function test_RevertsWhen_Paused() public { - registry.pause(); - vm.expectRevert(Registry.RegistryPaused.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_TargetIsNotAContract() public { - vm.expectRevert(Registry.NotAContract.selector); - registry.registerUpkeep( - randomAddress(), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_CalledByNonOwner() public { - vm.prank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByOwnerOrRegistrar.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_ExecuteGasIsTooLow() public { - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.registerUpkeep( - address(TARGET1), - 2299, // 1 less than min - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_ExecuteGasIsTooHigh() public { - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas + 1, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { - vm.expectRevert(Registry.InvalidToken.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - randomAddress(), - "", - "", - "" - ); - } - - function test_RevertsWhen_CheckDataIsTooLarge() public { - vm.expectRevert(Registry.CheckDataExceedsLimit.selector); - registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - randomBytes(config.maxCheckDataSize + 1), - "", - "" - ); - } - - function test_Happy() public { - bytes memory checkData = randomBytes(config.maxCheckDataSize); - bytes memory trigggerConfig = randomBytes(100); - bytes memory offchainConfig = randomBytes(100); - - uint256 upkeepCount = registry.getNumUpkeeps(); - - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.LOG), - address(linkToken), - checkData, - trigggerConfig, - offchainConfig - ); - - assertEq(registry.getNumUpkeeps(), upkeepCount + 1); - assertEq(registry.getUpkeep(upkeepID).target, address(TARGET1)); - assertEq(registry.getUpkeep(upkeepID).performGas, config.maxPerformGas); - assertEq(registry.getUpkeep(upkeepID).checkData, checkData); - assertEq(registry.getUpkeep(upkeepID).balance, 0); - assertEq(registry.getUpkeep(upkeepID).admin, UPKEEP_ADMIN); - assertEq(registry.getUpkeep(upkeepID).offchainConfig, offchainConfig); - assertEq(registry.getUpkeepTriggerConfig(upkeepID), trigggerConfig); - assertEq(uint8(registry.getTriggerType(upkeepID)), uint8(Trigger.LOG)); - } -} - -contract OnTokenTransfer is SetUp { - function test_RevertsWhen_NotCalledByTheLinkToken() public { - vm.expectRevert(Registry.OnlyCallableByLINKToken.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); - } - - function test_RevertsWhen_NotCalledWithExactly32Bytes() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.InvalidDataLength.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(31)); - vm.expectRevert(Registry.InvalidDataLength.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, randomBytes(33)); - } - - function test_RevertsWhen_TheUpkeepIsCancelledOrDNE() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(randomNumber())); - } - - function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { - vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.InvalidToken.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); - } - - function test_Happy() public { - vm.startPrank(address(linkToken)); - uint256 beforeBalance = registry.getBalance(linkUpkeepID); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(linkUpkeepID)); - assertEq(registry.getBalance(linkUpkeepID), beforeBalance + 100); - } -} - -contract GetMinBalanceForUpkeep is SetUp { - function test_accountsForFlatFee_with18Decimals() public { - // set fee to 0 - AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); - usdTokenConfig.flatFeeMilliCents = 0; - _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - - uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); - - // set fee to non-zero - usdTokenConfig.flatFeeMilliCents = 100; - _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - - uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); - assertEq( - minBalanceAfter, - minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) - ); - } - - function test_accountsForFlatFee_with6Decimals() public { - // set fee to 0 - AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); - usdTokenConfig.flatFeeMilliCents = 0; - _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); - - uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); - - // set fee to non-zero - usdTokenConfig.flatFeeMilliCents = 100; - _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); - - uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); - assertEq( - minBalanceAfter, - minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) - ); - } -} - -contract BillingOverrides is SetUp { - event BillingConfigOverridden(uint256 indexed id, AutomationRegistryBase2_3.BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - - function test_RevertsWhen_NotPrivilegeManager() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_RevertsWhen_UpkeepCancelled() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(PRIVILEGE_MANAGER); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_Happy_SetBillingOverrides() public { - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: 5_000, - flatFeeMilliCents: 20_000 - }); - - vm.startPrank(PRIVILEGE_MANAGER); - - vm.expectEmit(); - emit BillingConfigOverridden(linkUpkeepID, billingOverrides); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - } - - function test_Happy_RemoveBillingOverrides() public { - vm.startPrank(PRIVILEGE_MANAGER); - - vm.expectEmit(); - emit BillingConfigOverrideRemoved(linkUpkeepID); - registry.removeBillingOverrides(linkUpkeepID); - } - - function test_Happy_MaxGasPayment_WithBillingOverrides() public { - uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); - - // Double the two billing values - AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ - gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, - flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 - }); - - vm.startPrank(PRIVILEGE_MANAGER); - registry.setBillingOverrides(linkUpkeepID, billingOverrides); - - // maxPayment2 should be greater than maxPayment1 after the overrides - // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium - // We do not apply the exact equation since we couldn't get the receipt.premium value - uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); - assertGt(maxPayment2, maxPayment1); - } -} - -contract Transmit is SetUp { - function test_transmitRevertWithExtraBytes() external { - bytes32[3] memory exampleReportContext = [ - bytes32(0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef), - bytes32(0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890), - bytes32(0x7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456) - ]; - - bytes memory exampleRawReport = hex"deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; - - bytes32[] memory exampleRs = new bytes32[](3); - exampleRs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleRs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleRs[2] = bytes32(0x7890789078907890789078907890789078907890789078907890789078907890); - - bytes32[] memory exampleSs = new bytes32[](3); - exampleSs[0] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleSs[1] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - exampleSs[2] = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - - bytes32 exampleRawVs = bytes32(0x1234561234561234561234561234561234561234561234561234561234561234); - - bytes memory transmitData = abi.encodeWithSelector( - registry.transmit.selector, - exampleReportContext, - exampleRawReport, - exampleRs, - exampleSs, - exampleRawVs - ); - bytes memory badTransmitData = bytes.concat(transmitData, bytes1(0x00)); // add extra data - vm.startPrank(TRANSMITTERS[0]); - (bool success, bytes memory returnData) = address(registry).call(badTransmitData); // send the bogus transmit - assertFalse(success, "Call did not revert as expected"); - assertEq(returnData, abi.encodePacked(Registry.InvalidDataLength.selector)); - vm.stopPrank(); - } - - function test_handlesMixedBatchOfBillingTokens() external { - uint256[] memory prevUpkeepBalances = new uint256[](3); - prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); - prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); - prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); - uint256[] memory prevTokenBalances = new uint256[](3); - prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); - prevTokenBalances[2] = weth.balanceOf(address(registry)); - uint256[] memory prevReserveBalances = new uint256[](3); - prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); - prevReserveBalances[2] = registry.getReserveAmount(address(weth)); - uint256[] memory upkeepIDs = new uint256[](3); - upkeepIDs[0] = linkUpkeepID; - upkeepIDs[1] = usdUpkeepID18; - upkeepIDs[2] = nativeUpkeepID; - - // withdraw-able by finance team should be 0 - require(registry.getAvailableERC20ForPayment(address(usdToken18)) == 0, "ERC20AvailableForPayment should be 0"); - require(registry.getAvailableERC20ForPayment(address(weth)) == 0, "ERC20AvailableForPayment should be 0"); - - // do the thing - _transmit(upkeepIDs, registry, bytes4(0)); - - // withdraw-able by the finance team should be positive - require( - registry.getAvailableERC20ForPayment(address(usdToken18)) > 0, - "ERC20AvailableForPayment should be positive" - ); - require(registry.getAvailableERC20ForPayment(address(weth)) > 0, "ERC20AvailableForPayment should be positive"); - - // assert upkeep balances have decreased - require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); - require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); - require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); - // assert token balances have not changed - assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); - assertEq(prevTokenBalances[1], usdToken18.balanceOf(address(registry))); - assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); - // assert reserve amounts have adjusted accordingly - require( - prevReserveBalances[0] < registry.getReserveAmount(address(linkToken)), - "usd reserve amount should have increased" - ); // link reserve amount increases in value equal to the decrease of the other reserve amounts - require( - prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), - "usd reserve amount should have decreased" - ); - require( - prevReserveBalances[2] > registry.getReserveAmount(address(weth)), - "native reserve amount should have decreased" - ); - } - - function test_handlesInsufficientBalanceWithUSDToken18() external { - // deploy and configure a registry with ON_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - // register an upkeep and add funds - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - 1000000, - UPKEEP_ADMIN, - 0, - address(usdToken18), - "", - "", - "" - ); - _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); - vm.startPrank(UPKEEP_ADMIN); - usdToken18.approve(address(registry), 1e20); - registry.addFunds(upkeepID, 1); // smaller than gasCharge - uint256 balance = registry.getBalance(upkeepID); - - // manually create a transmit - vm.recordLogs(); - _transmit(upkeepID, registry, bytes4(0)); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 3); - Vm.Log memory l1 = entries[1]; - assertEq( - l1.topics[0], - keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") - ); - ( - uint96 gasChargeInBillingToken, - uint96 premiumInBillingToken, - uint96 gasReimbursementInJuels, - uint96 premiumInJuels, - address billingToken, - uint96 linkUSD, - uint96 nativeUSD, - uint96 billingUSD - ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); - - assertEq(gasChargeInBillingToken, balance); - assertEq(gasReimbursementInJuels, (balance * billingUSD) / linkUSD); - assertEq(premiumInJuels, 0); - assertEq(premiumInBillingToken, 0); - } - - function test_handlesInsufficientBalanceWithUSDToken6() external { - // deploy and configure a registry with ON_CHAIN payout - (Registry registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - // register an upkeep and add funds - uint256 upkeepID = registry.registerUpkeep( - address(TARGET1), - 1000000, - UPKEEP_ADMIN, - 0, - address(usdToken6), - "", - "", - "" - ); - vm.prank(OWNER); - usdToken6.mint(UPKEEP_ADMIN, 1e20); - - vm.startPrank(UPKEEP_ADMIN); - usdToken6.approve(address(registry), 1e20); - registry.addFunds(upkeepID, 100); // this is greater than gasCharge but less than (gasCharge + premium) - uint256 balance = registry.getBalance(upkeepID); - - // manually create a transmit - vm.recordLogs(); - _transmit(upkeepID, registry, bytes4(0)); - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 3); - Vm.Log memory l1 = entries[1]; - assertEq( - l1.topics[0], - keccak256("UpkeepCharged(uint256,(uint96,uint96,uint96,uint96,address,uint96,uint96,uint96))") - ); - ( - uint96 gasChargeInBillingToken, - uint96 premiumInBillingToken, - uint96 gasReimbursementInJuels, - uint96 premiumInJuels, - address billingToken, - uint96 linkUSD, - uint96 nativeUSD, - uint96 billingUSD - ) = abi.decode(l1.data, (uint96, uint96, uint96, uint96, address, uint96, uint96, uint96)); - - assertEq(premiumInJuels, (balance * billingUSD * 1e12) / linkUSD - gasReimbursementInJuels); // scale to 18 decimals - assertEq(premiumInBillingToken, (premiumInJuels * linkUSD + (billingUSD * 1e12 - 1)) / (billingUSD * 1e12)); - } -} - -contract MigrateReceive is SetUp { - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - - Registry newRegistry; - uint256[] idsToMigrate; - - function setUp() public override { - super.setUp(); - (newRegistry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - idsToMigrate.push(linkUpkeepID); - idsToMigrate.push(linkUpkeepID2); - idsToMigrate.push(usdUpkeepID18); - idsToMigrate.push(nativeUpkeepID); - registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); - } - - function test_RevertsWhen_PermissionsNotSet() external { - // no permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // only outgoing permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 0); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // only incoming permissions - registry.setPeerRegistryMigrationPermission(address(newRegistry), 0); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // permissions opposite direction - registry.setPeerRegistryMigrationPermission(address(newRegistry), 2); - newRegistry.setPeerRegistryMigrationPermission(address(registry), 1); - vm.expectRevert(Registry.MigrationNotPermitted.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - } - - function test_RevertsWhen_ReceivingRegistryDoesNotSupportToken() external { - _removeBillingTokenConfig(newRegistry, address(weth)); - vm.expectRevert(Registry.InvalidToken.selector); - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - idsToMigrate.pop(); // remove native upkeep id - vm.prank(UPKEEP_ADMIN); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); // should succeed now - } - - function test_RevertsWhen_CalledByNonAdmin() external { - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - vm.prank(STRANGER); - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - } - - function test_Success() external { - vm.startPrank(UPKEEP_ADMIN); - - // add some changes in upkeep data to the mix - registry.pauseUpkeep(usdUpkeepID18); - registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); - registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); - - // record previous state - uint256[] memory prevUpkeepBalances = new uint256[](4); - prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); - prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); - prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); - prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); - uint256[] memory prevReserveBalances = new uint256[](3); - prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); - prevReserveBalances[2] = registry.getReserveAmount(address(weth)); - uint256[] memory prevTokenBalances = new uint256[](3); - prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); - prevTokenBalances[2] = weth.balanceOf(address(registry)); - bytes[] memory prevUpkeepData = new bytes[](4); - prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); - prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); - prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); - prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); - bytes[] memory prevUpkeepTriggerData = new bytes[](4); - prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); - prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); - prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); - prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); - - // event expectations - vm.expectEmit(address(registry)); - emit UpkeepMigrated(linkUpkeepID, prevUpkeepBalances[0], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); - vm.expectEmit(address(registry)); - emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(linkUpkeepID, prevUpkeepBalances[0], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); - vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); - - // do the thing - registry.migrateUpkeeps(idsToMigrate, address(newRegistry)); - - // assert upkeep balances have been migrated - assertEq(registry.getBalance(linkUpkeepID), 0); - assertEq(registry.getBalance(linkUpkeepID2), 0); - assertEq(registry.getBalance(usdUpkeepID18), 0); - assertEq(registry.getBalance(nativeUpkeepID), 0); - assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); - assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); - assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); - assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); - - // assert reserve balances have been adjusted - assertEq( - newRegistry.getReserveAmount(address(linkToken)), - newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) - ); - assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); - assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); - assertEq( - newRegistry.getReserveAmount(address(linkToken)), - prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) - ); - assertEq( - newRegistry.getReserveAmount(address(usdToken18)), - prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) - ); - assertEq( - newRegistry.getReserveAmount(address(weth)), - prevReserveBalances[2] - registry.getReserveAmount(address(weth)) - ); - - // assert token have been transferred - assertEq( - linkToken.balanceOf(address(newRegistry)), - newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) - ); - assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); - assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); - assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); - assertEq( - usdToken18.balanceOf(address(registry)), - prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) - ); - assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); - - // assert upkeep data matches - assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); - assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); - assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); - assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); - assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); - assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); - assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); - assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); - - vm.stopPrank(); - } -} - -contract Pause is SetUp { - function test_RevertsWhen_CalledByNonOwner() external { - vm.expectRevert(bytes("Only callable by owner")); - vm.prank(STRANGER); - registry.pause(); - } - - function test_CalledByOwner_success() external { - vm.startPrank(registry.owner()); - registry.pause(); - - (IAutomationV21PlusCommon.StateLegacy memory state, , , , ) = registry.getState(); - assertTrue(state.paused); - } - - function test_revertsWhen_registerUpkeepInPausedRegistry() external { - vm.startPrank(registry.owner()); - registry.pause(); - - vm.expectRevert(Registry.RegistryPaused.selector); - uint256 id = registry.registerUpkeep( - address(TARGET1), - config.maxPerformGas, - UPKEEP_ADMIN, - uint8(Trigger.CONDITION), - address(linkToken), - "", - "", - "" - ); - } - - function test_revertsWhen_transmitInPausedRegistry() external { - vm.startPrank(registry.owner()); - registry.pause(); - - _transmit(usdUpkeepID18, registry, Registry.RegistryPaused.selector); - } -} - -contract Unpause is SetUp { - function test_RevertsWhen_CalledByNonOwner() external { - vm.startPrank(registry.owner()); - registry.pause(); - - vm.expectRevert(bytes("Only callable by owner")); - vm.startPrank(STRANGER); - registry.unpause(); - } - - function test_CalledByOwner_success() external { - vm.startPrank(registry.owner()); - registry.pause(); - (IAutomationV21PlusCommon.StateLegacy memory state1, , , , ) = registry.getState(); - assertTrue(state1.paused); - - registry.unpause(); - (IAutomationV21PlusCommon.StateLegacy memory state2, , , , ) = registry.getState(); - assertFalse(state2.paused); - } -} - -contract CancelUpkeep is SetUp { - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - - function test_RevertsWhen_IdIsInvalid_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - vm.expectRevert(Registry.CannotCancel.selector); - registry.cancelUpkeep(1111111); - } - - function test_RevertsWhen_IdIsInvalid_CalledByOwner() external { - vm.startPrank(registry.owner()); - vm.expectRevert(Registry.CannotCancel.selector); - registry.cancelUpkeep(1111111); - } - - function test_RevertsWhen_NotCalledByOwnerOrAdmin() external { - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByOwnerOrAdmin.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(registry.owner()); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(UPKEEP_ADMIN); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByAdmin_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceledByOwner_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); - - // 50 is the cancellation delay - assertEq(bn + 50, maxValidBlocknumber); - } - - function test_CancelUpkeep_SetMaxValidBlockNumber_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - registry.cancelUpkeep(linkUpkeepID); - - uint256 maxValidBlocknumber = uint256(registry.getUpkeep(linkUpkeepID).maxValidBlocknumber); - - // cancellation by registry owner is immediate and no cancellation delay is applied - assertEq(bn, maxValidBlocknumber); - } - - function test_CancelUpkeep_EmitEvent_CalledByAdmin() external { - uint256 bn = block.number; - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepCanceled(linkUpkeepID, uint64(bn + 50)); - registry.cancelUpkeep(linkUpkeepID); - } - - function test_CancelUpkeep_EmitEvent_CalledByOwner() external { - uint256 bn = block.number; - vm.startPrank(registry.owner()); - - vm.expectEmit(); - emit UpkeepCanceled(linkUpkeepID, uint64(bn)); - registry.cancelUpkeep(linkUpkeepID); - } -} - -contract SetPeerRegistryMigrationPermission is SetUp { - function test_SetPeerRegistryMigrationPermission_CalledByOwner() external { - address peer = randomAddress(); - vm.startPrank(registry.owner()); - - uint8 permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(0, permission); - - registry.setPeerRegistryMigrationPermission(peer, 1); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(1, permission); - - registry.setPeerRegistryMigrationPermission(peer, 2); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(2, permission); - - registry.setPeerRegistryMigrationPermission(peer, 0); - permission = registry.getPeerRegistryMigrationPermission(peer); - assertEq(0, permission); - } - - function test_RevertsWhen_InvalidPermission_CalledByOwner() external { - address peer = randomAddress(); - vm.startPrank(registry.owner()); - - vm.expectRevert(); - registry.setPeerRegistryMigrationPermission(peer, 100); - } - - function test_RevertsWhen_CalledByNonOwner() external { - address peer = randomAddress(); - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - registry.setPeerRegistryMigrationPermission(peer, 1); - } -} - -contract SetUpkeepPrivilegeConfig is SetUp { - function test_RevertsWhen_CalledByNonManager() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); - } - - function test_UpkeepHasEmptyConfig() external { - bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); - assertEq(cfg, bytes("")); - } - - function test_SetUpkeepPrivilegeConfig_CalledByManager() external { - vm.startPrank(PRIVILEGE_MANAGER); - - registry.setUpkeepPrivilegeConfig(linkUpkeepID, hex"1233"); - - bytes memory cfg = registry.getUpkeepPrivilegeConfig(linkUpkeepID); - assertEq(cfg, hex"1233"); - } -} - -contract SetAdminPrivilegeConfig is SetUp { - function test_RevertsWhen_CalledByNonManager() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByUpkeepPrivilegeManager.selector); - registry.setAdminPrivilegeConfig(randomAddress(), hex"1233"); - } - - function test_UpkeepHasEmptyConfig() external { - bytes memory cfg = registry.getAdminPrivilegeConfig(randomAddress()); - assertEq(cfg, bytes("")); - } - - function test_SetAdminPrivilegeConfig_CalledByManager() external { - vm.startPrank(PRIVILEGE_MANAGER); - address admin = randomAddress(); - - registry.setAdminPrivilegeConfig(admin, hex"1233"); - - bytes memory cfg = registry.getAdminPrivilegeConfig(admin); - assertEq(cfg, hex"1233"); - } -} - -contract TransferUpkeepAdmin is SetUp { - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - } - - function test_RevertsWhen_TransferToSelf() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.ValueNotChanged.selector); - registry.transferUpkeepAdmin(linkUpkeepID, UPKEEP_ADMIN); - } - - function test_RevertsWhen_UpkeepCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - } - - function test_DoesNotChangeUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.transferUpkeepAdmin(linkUpkeepID, randomAddress()); - - assertEq(registry.getUpkeep(linkUpkeepID).admin, UPKEEP_ADMIN); - } - - function test_EmitEvent_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - // transferring to the same propose admin won't yield another event - vm.recordLogs(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(0, entries.length); - } - - function test_CancelTransfer_ByTransferToEmptyAddress() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.expectEmit(); - emit UpkeepAdminTransferRequested(linkUpkeepID, UPKEEP_ADMIN, address(0)); - registry.transferUpkeepAdmin(linkUpkeepID, address(0)); - } -} - -contract AcceptUpkeepAdmin is SetUp { - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByProposedAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByProposedAdmin.selector); - registry.acceptUpkeepAdmin(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - registry.cancelUpkeep(linkUpkeepID); - - vm.startPrank(newAdmin); - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.acceptUpkeepAdmin(linkUpkeepID); - } - - function test_UpkeepAdminChanged() external { - vm.startPrank(UPKEEP_ADMIN); - address newAdmin = randomAddress(); - registry.transferUpkeepAdmin(linkUpkeepID, newAdmin); - - vm.startPrank(newAdmin); - vm.expectEmit(); - emit UpkeepAdminTransferred(linkUpkeepID, UPKEEP_ADMIN, newAdmin); - registry.acceptUpkeepAdmin(linkUpkeepID); - - assertEq(newAdmin, registry.getUpkeep(linkUpkeepID).admin); - } -} - -contract PauseUpkeep is SetUp { - event UpkeepPaused(uint256 indexed id); - - function test_RevertsWhen_NotCalledByUpkeepAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.pauseUpkeep(linkUpkeepID + 1); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyPaused() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.OnlyUnpausedUpkeep.selector); - registry.pauseUpkeep(linkUpkeepID); - } - - function test_EmitEvent_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepPaused(linkUpkeepID); - registry.pauseUpkeep(linkUpkeepID); - } -} - -contract UnpauseUpkeep is SetUp { - event UpkeepUnpaused(uint256 indexed id); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.unpauseUpkeep(linkUpkeepID + 1); - } - - function test_RevertsWhen_UpkeepIsNotPaused() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyPausedUpkeep.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_RevertsWhen_NotCalledByUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.unpauseUpkeep(linkUpkeepID); - } - - function test_UnpauseUpkeep_CalledByUpkeepAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - registry.pauseUpkeep(linkUpkeepID); - - uint256[] memory ids1 = registry.getActiveUpkeepIDs(0, 0); - - vm.expectEmit(); - emit UpkeepUnpaused(linkUpkeepID); - registry.unpauseUpkeep(linkUpkeepID); - - uint256[] memory ids2 = registry.getActiveUpkeepIDs(0, 0); - assertEq(ids1.length + 1, ids2.length); - } -} - -contract SetUpkeepCheckData is SetUp { - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepCheckData(linkUpkeepID + 1, hex"1234"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NewCheckDataTooLarge() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.CheckDataExceedsLimit.selector); - registry.setUpkeepCheckData(linkUpkeepID, new bytes(10_000)); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - } - - function test_UpdateOffchainConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); - } - - function test_UpdateOffchainConfigOnPausedUpkeep_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - registry.pauseUpkeep(linkUpkeepID); - - vm.expectEmit(); - emit UpkeepCheckDataSet(linkUpkeepID, hex"1234"); - registry.setUpkeepCheckData(linkUpkeepID, hex"1234"); - - assertTrue(registry.getUpkeep(linkUpkeepID).paused); - assertEq(registry.getUpkeep(linkUpkeepID).checkData, hex"1234"); - } -} - -contract SetUpkeepGasLimit is SetUp { - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepGasLimit(linkUpkeepID + 1, 1230000); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - } - - function test_RevertsWhen_NewGasLimitOutOfRange() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 300); - - vm.expectRevert(Registry.GasLimitOutsideRange.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 3000000000); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - } - - function test_UpdateGasLimit_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepGasLimitSet(linkUpkeepID, 1230000); - registry.setUpkeepGasLimit(linkUpkeepID, 1230000); - - assertEq(registry.getUpkeep(linkUpkeepID).performGas, 1230000); - } -} - -contract SetUpkeepOffchainConfig is SetUp { - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID + 1, hex"1233"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - } - - function test_UpdateOffchainConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepOffchainConfigSet(linkUpkeepID, hex"1234"); - registry.setUpkeepOffchainConfig(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeep(linkUpkeepID).offchainConfig, hex"1234"); - } -} - -contract SetUpkeepTriggerConfig is SetUp { - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - - function test_RevertsWhen_InvalidUpkeepId() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID + 1, hex"1233"); - } - - function test_RevertsWhen_UpkeepAlreadyCanceled() external { - vm.startPrank(UPKEEP_ADMIN); - registry.cancelUpkeep(linkUpkeepID); - - vm.expectRevert(Registry.UpkeepCancelled.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - } - - function test_RevertsWhen_NotCalledByAdmin() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByAdmin.selector); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - } - - function test_UpdateTriggerConfig_CalledByAdmin() external { - vm.startPrank(UPKEEP_ADMIN); - - vm.expectEmit(); - emit UpkeepTriggerConfigSet(linkUpkeepID, hex"1234"); - registry.setUpkeepTriggerConfig(linkUpkeepID, hex"1234"); - - assertEq(registry.getUpkeepTriggerConfig(linkUpkeepID), hex"1234"); - } -} - -contract TransferPayeeship is SetUp { - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByPayee() external { - vm.startPrank(STRANGER); - - vm.expectRevert(Registry.OnlyCallableByPayee.selector); - registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); - } - - function test_RevertsWhen_TransferToSelf() external { - registry.setPayees(PAYEES); - vm.startPrank(PAYEES[0]); - - vm.expectRevert(Registry.ValueNotChanged.selector); - registry.transferPayeeship(TRANSMITTERS[0], PAYEES[0]); - } - - function test_Transfer_DoesNotChangePayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - - registry.transferPayeeship(TRANSMITTERS[0], randomAddress()); - - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertEq(PAYEES[0], payee); - } - - function test_EmitEvent_CalledByPayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - - vm.expectEmit(); - emit PayeeshipTransferRequested(TRANSMITTERS[0], PAYEES[0], newPayee); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - // transferring to the same propose payee won't yield another event - vm.recordLogs(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(0, entries.length); - } -} - -contract AcceptPayeeship is SetUp { - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - - function test_RevertsWhen_NotCalledByProposedPayee() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - vm.startPrank(STRANGER); - vm.expectRevert(Registry.OnlyCallableByProposedPayee.selector); - registry.acceptPayeeship(TRANSMITTERS[0]); - } - - function test_PayeeChanged() external { - registry.setPayees(PAYEES); - - vm.startPrank(PAYEES[0]); - address newPayee = randomAddress(); - registry.transferPayeeship(TRANSMITTERS[0], newPayee); - - vm.startPrank(newPayee); - vm.expectEmit(); - emit PayeeshipTransferred(TRANSMITTERS[0], PAYEES[0], newPayee); - registry.acceptPayeeship(TRANSMITTERS[0]); - - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertEq(newPayee, payee); - } -} - -contract SetPayees is SetUp { - event PayeesUpdated(address[] transmitters, address[] payees); - - function test_RevertsWhen_NotCalledByOwner() external { - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - registry.setPayees(NEW_PAYEES); - } - - function test_RevertsWhen_PayeesLengthError() external { - vm.startPrank(registry.owner()); - - address[] memory payees = new address[](5); - vm.expectRevert(Registry.ParameterLengthError.selector); - registry.setPayees(payees); - } - - function test_RevertsWhen_InvalidPayee() external { - vm.startPrank(registry.owner()); - - NEW_PAYEES[0] = address(0); - vm.expectRevert(Registry.InvalidPayee.selector); - registry.setPayees(NEW_PAYEES); - } - - function test_SetPayees_WhenExistingPayeesAreEmpty() external { - (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertEq(address(0), payee); - } - - vm.startPrank(registry.owner()); - - vm.expectEmit(); - emit PayeesUpdated(TRANSMITTERS, PAYEES); - registry.setPayees(PAYEES); - for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); - assertTrue(active); - assertEq(PAYEES[i], payee); - } - } - - function test_DotNotSetPayeesToIgnoredAddress() external { - address IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - (registry, ) = deployAndConfigureZKSyncRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); - PAYEES[0] = IGNORE_ADDRESS; - - registry.setPayees(PAYEES); - (bool active, , , , address payee) = registry.getTransmitterInfo(TRANSMITTERS[0]); - assertTrue(active); - assertEq(address(0), payee); - - (active, , , , payee) = registry.getTransmitterInfo(TRANSMITTERS[1]); - assertTrue(active); - assertEq(PAYEES[1], payee); - } -} - -contract GetActiveUpkeepIDs is SetUp { - function test_RevertsWhen_IndexOutOfRange() external { - vm.expectRevert(Registry.IndexOutOfRange.selector); - registry.getActiveUpkeepIDs(5, 0); - - vm.expectRevert(Registry.IndexOutOfRange.selector); - registry.getActiveUpkeepIDs(6, 0); - } - - function test_ReturnsAllUpkeeps_WhenMaxCountIsZero() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(0, 0); - assertEq(5, uids.length); - - uids = registry.getActiveUpkeepIDs(2, 0); - assertEq(3, uids.length); - } - - function test_ReturnsAllRemainingUpkeeps_WhenMaxCountIsTooLarge() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(2, 20); - assertEq(3, uids.length); - } - - function test_ReturnsUpkeeps_BoundByMaxCount() external { - uint256[] memory uids = registry.getActiveUpkeepIDs(1, 2); - assertEq(2, uids.length); - assertEq(uids[0], linkUpkeepID2); - assertEq(uids[1], usdUpkeepID18); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol deleted file mode 100644 index f500547..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronTestHelper.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {Cron as CronInternal, Spec} from "../libraries/internal/Cron.sol"; -import {Cron as CronExternal} from "../libraries/external/Cron.sol"; - -/** - * @title The CronInternalTestHelper contract - * @notice This contract exposes core functionality of the internal/Cron library. - * It is only intended for use in tests. - */ -contract CronInternalTestHelper { - /** - * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to convert and encode - * @return the abi encoding of the Spec struct representing the cron string - */ - function encodeCronString(string memory cronString) external pure returns (bytes memory) { - return CronInternal.toEncodedSpec(cronString); - } - - /** - * @notice encodedSpecToString is a helper function for turning an - * encoded spec back into a string. There is limited or no use for this outside - * of tests. - */ - function encodedSpecToString(bytes memory encodedSpec) public pure returns (string memory) { - Spec memory spec = abi.decode(encodedSpec, (Spec)); - return CronInternal.toCronString(spec); - } - - /** - * @notice calculateNextTick calculates the next time a cron job should "tick". - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to consider - * @return the timestamp in UTC of the next "tick" - */ - function calculateNextTick(string memory cronString) external view returns (uint256) { - return CronInternal.nextTick(CronInternal.toSpec(cronString)); - } - - /** - * @notice calculateLastTick calculates the last time a cron job "ticked". - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to consider - * @return the timestamp in UTC of the last "tick" - */ - function calculateLastTick(string memory cronString) external view returns (uint256) { - return CronInternal.lastTick(CronInternal.toSpec(cronString)); - } -} - -/** - * @title The CronExternalTestHelper contract - * @notice This contract exposes core functionality of the external/Cron library. - * It is only intended for use in tests. - */ -contract CronExternalTestHelper { - /** - * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to convert and encode - * @return the abi encoding of the Spec struct representing the cron string - */ - function encodeCronString(string memory cronString) external pure returns (bytes memory) { - return CronExternal.toEncodedSpec(cronString); - } - - /** - * @notice encodedSpecToString is a helper function for turning an - * encoded spec back into a string. There is limited or no use for this outside - * of tests. - */ - function encodedSpecToString(bytes memory encodedSpec) public pure returns (string memory) { - Spec memory spec = abi.decode(encodedSpec, (Spec)); - return CronExternal.toCronString(spec); - } - - /** - * @notice calculateNextTick calculates the next time a cron job should "tick". - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to consider - * @return the timestamp in UTC of the next "tick" - */ - function calculateNextTick(string memory cronString) external view returns (uint256) { - return CronExternal.nextTick(CronExternal.toSpec(cronString)); - } - - /** - * @notice calculateLastTick calculates the last time a cron job "ticked". - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to consider - * @return the timestamp in UTC of the last "tick" - */ - function calculateLastTick(string memory cronString) external view returns (uint256) { - return CronExternal.lastTick(CronExternal.toSpec(cronString)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol deleted file mode 100644 index 8ede4ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/CronUpkeepTestHelper.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import "../upkeeps/CronUpkeep.sol"; -import {Cron, Spec} from "../libraries/internal/Cron.sol"; - -/** - * @title The CronUpkeepTestHelper contract - * @notice This contract exposes core functionality of the CronUpkeep contract. - * It is only intended for use in tests. - */ -contract CronUpkeepTestHelper is CronUpkeep { - using Cron for Spec; - using Cron for string; - - constructor( - address owner, - address delegate, - uint256 maxJobs, - bytes memory firstJob - ) CronUpkeep(owner, delegate, maxJobs, firstJob) {} - - /** - * @notice createCronJobFromString is a helper function for creating cron jobs - * directly from strings. This is gas-intensive and shouldn't be done outside - * of testing environments. - */ - function createCronJobFromString(address target, bytes memory handler, string memory cronString) external { - Spec memory spec = cronString.toSpec(); - createCronJobFromSpec(target, handler, spec); - } - - /** - * @notice txCheckUpkeep is a helper function for sending real txs to the - * checkUpkeep function. This allows us to do gas analysis on it. - */ - function txCheckUpkeep(bytes calldata checkData) external { - address(this).call(abi.encodeWithSelector(bytes4(keccak256("checkUpkeep(bytes)")), checkData)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol deleted file mode 100644 index 4e86ec2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/DummyProtocol.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -// this struct is the same as LogTriggerConfig defined in KeeperRegistryLogicA2_1 contract -struct LogTriggerConfig { - address contractAddress; - uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply - bytes32 topic0; - bytes32 topic1; - bytes32 topic2; - bytes32 topic3; -} - -contract DummyProtocol { - event LimitOrderSent(uint256 indexed amount, uint256 indexed price, address indexed to); // keccak256(LimitOrderSent(uint256,uint256,address)) => 0x3e9c37b3143f2eb7e9a2a0f8091b6de097b62efcfe48e1f68847a832e521750a - event LimitOrderWithdrawn(uint256 indexed amount, uint256 indexed price, address indexed from); // keccak256(LimitOrderWithdrawn(uint256,uint256,address)) => 0x0a71b8ed921ff64d49e4d39449f8a21094f38a0aeae489c3051aedd63f2c229f - event LimitOrderExecuted(uint256 indexed orderId, uint256 indexed amount, address indexed exchange); // keccak(LimitOrderExecuted(uint256,uint256,address)) => 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd - - function sendLimitedOrder(uint256 amount, uint256 price, address to) public { - // send an order to an exchange - emit LimitOrderSent(amount, price, to); - } - - function withdrawLimit(uint256 amount, uint256 price, address from) public { - // withdraw an order from an exchange - emit LimitOrderSent(amount, price, from); - } - - function executeLimitOrder(uint256 orderId, uint256 amount, address exchange) public { - // execute a limit order - emit LimitOrderExecuted(orderId, amount, exchange); - } - - /** - * @notice this function generates bytes for a basic log trigger config with no filter selector. - * @param targetContract the address of contract where events will be emitted from - * @param t0 the signature of the event to listen to - */ - function getBasicLogTriggerConfig( - address targetContract, - bytes32 t0 - ) external view returns (bytes memory logTrigger) { - LogTriggerConfig memory cfg = LogTriggerConfig({ - contractAddress: targetContract, - filterSelector: 0, - topic0: t0, - topic1: 0x000000000000000000000000000000000000000000000000000000000000000, - topic2: 0x000000000000000000000000000000000000000000000000000000000000000, - topic3: 0x000000000000000000000000000000000000000000000000000000000000000 - }); - return abi.encode(cfg); - } - - /** - * @notice this function generates bytes for a customizable log trigger config. - * @param targetContract the address of contract where events will be emitted from - * @param selector the filter selector. this denotes which topics apply to filter ex 000, 101, 111....only last 3 bits apply - * if 0, it won't filter based on topic 1, 2, 3. - * if 1, it will filter based on topic 1, - * if 2, it will filter based on topic 2, - * if 3, it will filter based on topic 1 and topic 2, - * if 4, it will filter based on topic 3, - * if 5, it will filter based on topic 1 and topic 3.... - * @param t0 the signature of the event to listen to. - * @param t1 the topic 1 of the event. - * @param t2 the topic 2 of the event. - * @param t3 the topic 2 of the event. - */ - function getAdvancedLogTriggerConfig( - address targetContract, - uint8 selector, - bytes32 t0, - bytes32 t1, - bytes32 t2, - bytes32 t3 - ) external view returns (bytes memory logTrigger) { - LogTriggerConfig memory cfg = LogTriggerConfig({ - contractAddress: targetContract, - filterSelector: selector, - topic0: t0, - topic1: t1, - topic2: t2, - topic3: t3 - }); - return abi.encode(cfg); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol deleted file mode 100644 index fb492f3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumer.sol +++ /dev/null @@ -1,26 +0,0 @@ -pragma solidity 0.8.16; - -import "../interfaces/KeeperCompatibleInterface.sol"; -import "../KeeperBase.sol"; - -contract KeeperConsumer is KeeperCompatibleInterface, KeeperBase { - uint public counter; - uint public immutable interval; - uint public lastTimeStamp; - - constructor(uint updateInterval) public { - interval = updateInterval; - lastTimeStamp = block.timestamp; - counter = 0; - } - - function checkUpkeep( - bytes calldata checkData - ) external view override cannotExecute returns (bool upkeepNeeded, bytes memory performData) { - return (true, checkData); - } - - function performUpkeep(bytes calldata performData) external override { - counter = counter + 1; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol deleted file mode 100644 index 5b7f57e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/KeeperConsumerPerformance.sol +++ /dev/null @@ -1,88 +0,0 @@ -pragma solidity 0.8.16; - -contract KeeperConsumerPerformance { - event PerformingUpkeep(bool eligible, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); - - uint256 public initialCall = 0; - uint256 public nextEligible = 0; - uint256 public testRange; - uint256 public averageEligibilityCadence; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - - uint256 public count = 0; - - constructor( - uint256 _testRange, - uint256 _averageEligibilityCadence, - uint256 _checkGasToBurn, - uint256 _performGasToBurn - ) { - testRange = _testRange; - averageEligibilityCadence = _averageEligibilityCadence; - checkGasToBurn = _checkGasToBurn; - performGasToBurn = _performGasToBurn; - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - uint256 startGas = gasleft(); - bool dummy; - // burn gas - while (startGas - gasleft() < checkGasToBurn) { - dummy = dummy && dummyMap[blockhash(block.number)]; // arbitrary state reads - } - return (eligible(), abi.encode(dummy)); - } - - function performUpkeep(bytes calldata data) external { - uint256 startGas = gasleft(); - bool eligible = eligible(); - uint256 blockNum = block.number; - emit PerformingUpkeep(eligible, tx.origin, initialCall, nextEligible, blockNum); - require(eligible); - if (initialCall == 0) { - initialCall = blockNum; - } - nextEligible = (blockNum + (rand() % (averageEligibilityCadence * 2))) + 1; - count++; - // burn gas - while (startGas - gasleft() < performGasToBurn) { - dummyMap[blockhash(block.number)] = false; - } - } - - function setCheckGasToBurn(uint256 value) public { - checkGasToBurn = value; - } - - function setPerformGasToBurn(uint256 value) public { - performGasToBurn = value; - } - - function getCountPerforms() public view returns (uint256) { - return count; - } - - function eligible() internal view returns (bool) { - return initialCall == 0 || (block.number - initialCall < testRange && block.number > nextEligible); - } - - function checkEligible() public view returns (bool) { - return eligible(); - } - - function reset() external { - initialCall = 0; - count = 0; - } - - function setSpread(uint256 _newTestRange, uint256 _newAverageEligibilityCadence) external { - testRange = _newTestRange; - averageEligibilityCadence = _newAverageEligibilityCadence; - } - - function rand() private view returns (uint256) { - return uint256(keccak256(abi.encode(blockhash(block.number - 1), address(this)))); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol deleted file mode 100644 index d0b89b3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogTriggeredStreamsLookup.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; - -interface IVerifierProxy { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the correct verifier. - * @param signedReport The encoded data to be verified. - * @return verifierResponse The encoded response from the verifier. - */ - function verify(bytes memory signedReport) external returns (bytes memory verifierResponse); -} - -contract LogTriggeredStreamsLookup is ILogAutomation, StreamsLookupCompatibleInterface { - event PerformingLogTriggerUpkeep( - address indexed from, - uint256 orderId, - uint256 amount, - address exchange, - uint256 blockNumber, - bytes blob, - bytes verified - ); - event LimitOrderExecuted(uint256 indexed orderId, uint256 indexed amount, address indexed exchange); // keccak(LimitOrderExecuted(uint256,uint256,address)) => 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd - event IgnoringErrorHandlerData(); - - ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); - IVerifierProxy internal constant VERIFIER = IVerifierProxy(0x09DFf56A4fF44e0f4436260A04F5CFa65636A481); - - // for log trigger - bytes32 constant sentSig = 0x3e9c37b3143f2eb7e9a2a0f8091b6de097b62efcfe48e1f68847a832e521750a; - bytes32 constant withdrawnSig = 0x0a71b8ed921ff64d49e4d39449f8a21094f38a0aeae489c3051aedd63f2c229f; - bytes32 constant executedSig = 0xd1ffe9e45581c11d7d9f2ed5f75217cd4be9f8b7eee6af0f6d03f46de53956cd; - - // for mercury config - bool public useArbitrumBlockNum; - bool public verify; - string[] public feedsHex = ["0x4554482d5553442d415242495452554d2d544553544e45540000000000000000"]; - string public feedParamKey = "feedIdHex"; - string public timeParamKey = "blockNumber"; - uint256 public counter; - bool public checkErrReturnBool; - - constructor(bool _useArbitrumBlockNum, bool _verify, bool _checkErrReturnBool) { - useArbitrumBlockNum = _useArbitrumBlockNum; - verify = _verify; - checkErrReturnBool = _checkErrReturnBool; - counter = 0; - } - - function start() public { - // need an initial event to begin the cycle - emit LimitOrderExecuted(1, 100, address(0x0)); - } - - function setTimeParamKey(string memory timeParam) external { - timeParamKey = timeParam; - } - - function setFeedParamKey(string memory feedParam) external { - feedParamKey = feedParam; - } - - function setFeedsHex(string[] memory newFeeds) external { - feedsHex = newFeeds; - } - - function checkLog( - Log calldata log, - bytes memory - ) external override returns (bool upkeepNeeded, bytes memory performData) { - uint256 blockNum = getBlockNumber(); - - // filter by event signature - if (log.topics[0] == executedSig) { - // filter by indexed parameters - bytes memory t1 = abi.encodePacked(log.topics[1]); // bytes32 to bytes - uint256 orderId = abi.decode(t1, (uint256)); - bytes memory t2 = abi.encodePacked(log.topics[2]); - uint256 amount = abi.decode(t2, (uint256)); - bytes memory t3 = abi.encodePacked(log.topics[3]); - address exchange = abi.decode(t3, (address)); - - revert StreamsLookup( - feedParamKey, - feedsHex, - timeParamKey, - blockNum, - abi.encode(orderId, amount, exchange, executedSig) - ); - } - revert("could not find matching event sig"); - } - - function performUpkeep(bytes calldata performData) external override { - if (performData.length == 0) { - emit IgnoringErrorHandlerData(); - return; - } - (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); - (uint256 orderId, uint256 amount, address exchange, bytes32 logTopic0) = abi.decode( - extraData, - (uint256, uint256, address, bytes32) - ); - - bytes memory verifiedResponse = ""; - if (verify) { - verifiedResponse = VERIFIER.verify(values[0]); - } - - counter = counter + 1; - if (logTopic0 == executedSig) { - emit LimitOrderExecuted(1, 100, address(0x0)); - } - - emit PerformingLogTriggerUpkeep( - tx.origin, - orderId, - amount, - exchange, - getBlockNumber(), - values[0], - verifiedResponse - ); - } - - function checkCallback( - bytes[] memory values, - bytes memory extraData - ) external view override returns (bool, bytes memory) { - // do sth about the chainlinkBlob data in values and extraData - bytes memory performData = abi.encode(values, extraData); - return (true, performData); - } - - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (checkErrReturnBool, new bytes(0)); - } - - function getBlockNumber() internal view returns (uint256) { - if (useArbitrumBlockNum) { - return ARB_SYS.arbBlockNumber(); - } else { - return block.number; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol deleted file mode 100644 index 8f7fa46..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/LogUpkeepCounter.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; - -contract LogUpkeepCounter is ILogAutomation { - bytes32 sig1 = 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d; - bytes32 sig2 = 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da; - bytes32 sig3 = 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8; - bytes32 sig4 = 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71; - - event PerformingUpkeep( - address indexed from, - uint256 initialBlock, - uint256 lastBlock, - uint256 previousBlock, - uint256 counter - ); - - /** - * @dev we include multiple event types for testing various filters, signatures, etc - */ - event Trigger(); // 0x3d53a39550e04688065827f3bb86584cb007ab9ebca7ebd528e7301c9c31eb5d - event Trigger(uint256 a); // 0x57b1de35764b0939dde00771c7069cdf8d6a65d6a175623f19aa18784fd4c6da - event Trigger(uint256 a, uint256 b); // 0x1da9f70fe932e73fba9374396c5c0b02dbd170f951874b7b4afabe4dd029a9c8 - event Trigger(uint256 a, uint256 b, uint256 c); // 0x5121119bad45ca7e58e0bdadf39045f5111e93ba4304a0f6457a3e7bc9791e71 - - uint256 public testRange; - uint256 public lastBlock; - uint256 public previousPerformBlock; - uint256 public initialBlock; - uint256 public counter; - bool public autoExecution; - - constructor(uint256 _testRange) { - testRange = _testRange; - previousPerformBlock = 0; - lastBlock = block.number; - initialBlock = 0; - counter = 0; - autoExecution = true; - } - - function start() public { - // need an initial event to begin the cycle - emit Trigger(); - emit Trigger(1); - emit Trigger(1, 2); - emit Trigger(1, 2, 3); - } - - function checkLog(Log calldata log, bytes memory) external view override returns (bool, bytes memory) { - require(eligible(), "not eligible"); - if (log.topics[0] == sig1 || log.topics[0] == sig2 || log.topics[0] == sig3 || log.topics[0] == sig4) { - return (true, abi.encode(log)); - } else { - revert("could not find matching event sig"); - } - } - - function performUpkeep(bytes calldata performData) external override { - if (initialBlock == 0) { - initialBlock = block.number; - } - lastBlock = block.number; - counter = counter + 1; - previousPerformBlock = lastBlock; - Log memory log = abi.decode(performData, (Log)); - if (autoExecution) { - if (log.topics[0] == sig1) { - emit Trigger(); - } else if (log.topics[0] == sig2) { - emit Trigger(1); - } else if (log.topics[0] == sig3) { - emit Trigger(1, 2); - } else if (log.topics[0] == sig4) { - emit Trigger(1, 2, 3); - } else { - revert("could not find matching sig"); - } - } - emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter); - } - - function eligible() public view returns (bool) { - if (initialBlock == 0) { - return true; - } - - return (block.number - initialBlock) < testRange; - } - - function setSpread(uint256 _testRange) external { - testRange = _testRange; - initialBlock = 0; - counter = 0; - } - - function setAuto(bool _auto) external { - autoExecution = _auto; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol deleted file mode 100644 index 10f6732..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import "../../shared/interfaces/AggregatorV3Interface.sol"; - -contract MockETHUSDAggregator is AggregatorV3Interface { - int256 public answer; - uint256 private blockTimestampDeduction = 0; - - constructor(int256 _answer) { - answer = _answer; - } - - function decimals() external pure override returns (uint8) { - return 8; - } - - function description() external pure override returns (string memory) { - return "MockETHUSDAggregator"; - } - - function version() external pure override returns (uint256) { - return 1; - } - - function getRoundData( - uint80 /*_roundId*/ - ) - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); - } - - function latestRoundData() - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); - } - - function getDeductedBlockTimestamp() internal view returns (uint256) { - return block.timestamp - blockTimestampDeduction; - } - - function setBlockTimestampDeduction(uint256 _blockTimestampDeduction) external { - blockTimestampDeduction = _blockTimestampDeduction; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol deleted file mode 100644 index 268942f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/PerformDataChecker.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import "../interfaces/KeeperCompatibleInterface.sol"; - -contract PerformDataChecker is KeeperCompatibleInterface { - uint256 public counter; - bytes public s_expectedData; - - constructor(bytes memory expectedData) { - s_expectedData = expectedData; - } - - function setExpectedData(bytes calldata expectedData) external { - s_expectedData = expectedData; - } - - function checkUpkeep( - bytes calldata checkData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - return (keccak256(checkData) == keccak256(s_expectedData), checkData); - } - - function performUpkeep(bytes calldata performData) external override { - if (keccak256(performData) == keccak256(s_expectedData)) { - counter++; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol deleted file mode 100644 index c4d5771..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import "../interfaces/StreamsLookupCompatibleInterface.sol"; - -struct CheckData { - uint256 checkBurnAmount; - uint256 performBurnAmount; - bytes32 eventSig; - string[] feeds; -} - -contract SimpleLogUpkeepCounter is ILogAutomation, StreamsLookupCompatibleInterface { - event PerformingUpkeep( - address indexed from, - uint256 initialBlock, - uint256 lastBlock, - uint256 previousBlock, - uint256 counter, - uint256 timeToPerform, - bool isRecovered - ); - - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - uint256 public lastBlock; - uint256 public previousPerformBlock; - uint256 public initialBlock; - uint256 public counter; - uint256 public timeToPerform; - bool internal isRecovered; - bool public isStreamsLookup; - bool public shouldRetryOnError; - string public feedParamKey = "feedIDs"; - string public timeParamKey = "timestamp"; - - constructor(bool _isStreamsLookup) { - previousPerformBlock = 0; - lastBlock = block.number; - initialBlock = 0; - counter = 0; - isStreamsLookup = _isStreamsLookup; - } - - function _checkDataConfig(CheckData memory) external {} - - function setTimeParamKey(string memory timeParam) external { - timeParamKey = timeParam; - } - - function setFeedParamKey(string memory feedParam) external { - feedParamKey = feedParam; - } - - function setShouldRetryOnErrorBool(bool value) public { - shouldRetryOnError = value; - } - - function checkLog(Log calldata log, bytes calldata checkData) external view override returns (bool, bytes memory) { - CheckData memory _checkData = abi.decode(checkData, (CheckData)); - uint256 startGas = gasleft(); - bytes32 dummyIndex = blockhash(block.number - 1); - bool dummy; - // burn gas - if (_checkData.checkBurnAmount > 0) { - while (startGas - gasleft() < _checkData.checkBurnAmount) { - dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads - dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); - } - } - bytes[] memory values = new bytes[](2); - values[0] = abi.encode(0x00); - values[1] = abi.encode(0x00); - bytes memory extraData = abi.encode(log, block.number, checkData); - if (log.topics[2] == _checkData.eventSig) { - if (isStreamsLookup) { - revert StreamsLookup(feedParamKey, _checkData.feeds, timeParamKey, block.timestamp, extraData); - } - return (true, abi.encode(values, extraData)); - } - return (false, abi.encode(values, extraData)); - } - - function checkCallback( - bytes[] memory values, - bytes memory extraData - ) external view override returns (bool, bytes memory) { - // do sth about the chainlinkBlob data in values and extraData - bytes memory performData = abi.encode(values, extraData); - return (true, performData); - } - - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - bytes[] memory values = new bytes[](2); - values[0] = abi.encode(errCode); - values[1] = abi.encode(extraData); - bytes memory returnData = abi.encode(values, extraData); - return (shouldRetryOnError, returnData); - } - - function performUpkeep(bytes calldata performData) external override { - if (initialBlock == 0) { - initialBlock = block.number; - } - lastBlock = block.number; - counter = counter + 1; - previousPerformBlock = lastBlock; - (, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); - (Log memory log, uint256 checkBlock, bytes memory checkData) = abi.decode(extraData, (Log, uint256, bytes)); - timeToPerform = block.timestamp - log.timestamp; - isRecovered = false; - if (checkBlock != log.blockNumber) { - isRecovered = true; - } - CheckData memory _checkData = abi.decode(checkData, (CheckData)); - uint256 startGas = gasleft(); - bytes32 dummyIndex = blockhash(block.number - 1); - bool dummy; - if (log.topics[2] != _checkData.eventSig) { - revert("Invalid event signature"); - } - // burn gas - if (_checkData.performBurnAmount > 0) { - while (startGas - gasleft() < _checkData.performBurnAmount) { - dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads - dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); - } - } - emit PerformingUpkeep( - tx.origin, - initialBlock, - lastBlock, - previousPerformBlock, - counter, - timeToPerform, - isRecovered - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol deleted file mode 100644 index 263aad5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AutomationCompatible} from "../AutomationCompatible.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AutomationRegistryBaseInterface} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; - -contract UpkeepAutoFunder is AutomationCompatible, ConfirmedOwner { - bool public s_isEligible; - bool public s_shouldCancel; - uint256 public s_upkeepId; - uint96 public s_autoFundLink; - LinkTokenInterface public immutable LINK; - AutomationRegistryBaseInterface public immutable s_keeperRegistry; - - constructor(address linkAddress, address registryAddress) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(linkAddress); - s_keeperRegistry = AutomationRegistryBaseInterface(registryAddress); - - s_isEligible = false; - s_shouldCancel = false; - s_upkeepId = 0; - s_autoFundLink = 0; - } - - function setShouldCancel(bool value) external onlyOwner { - s_shouldCancel = value; - } - - function setIsEligible(bool value) external onlyOwner { - s_isEligible = value; - } - - function setAutoFundLink(uint96 value) external onlyOwner { - s_autoFundLink = value; - } - - function setUpkeepId(uint256 value) external onlyOwner { - s_upkeepId = value; - } - - function checkUpkeep( - bytes calldata data - ) external override cannotExecute returns (bool callable, bytes calldata executedata) { - return (s_isEligible, data); - } - - function performUpkeep(bytes calldata data) external override { - require(s_isEligible, "Upkeep should be eligible"); - s_isEligible = false; // Allow upkeep only once until it is set again - - // Topup upkeep so it can be called again - LINK.transferAndCall(address(s_keeperRegistry), s_autoFundLink, abi.encode(s_upkeepId)); - - if (s_shouldCancel) { - s_keeperRegistry.cancelUpkeep(s_upkeepId); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol deleted file mode 100644 index 24a8b1f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounter.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -contract UpkeepCounter { - event PerformingUpkeep( - address indexed from, - uint256 initialTimestamp, - uint256 lastTimestamp, - uint256 previousBlock, - uint256 counter - ); - - uint256 public testRange; - uint256 public interval; - uint256 public lastTimestamp; - uint256 public previousPerformBlock; - uint256 public initialTimestamp; - uint256 public counter; - - constructor(uint256 _testRange, uint256 _interval) { - testRange = _testRange; - interval = _interval; - previousPerformBlock = 0; - lastTimestamp = block.timestamp; - initialTimestamp = 0; - counter = 0; - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - return (eligible(), data); - } - - function performUpkeep(bytes calldata performData) external { - if (initialTimestamp == 0) { - initialTimestamp = block.timestamp; - } - lastTimestamp = block.timestamp; - counter = counter + 1; - performData; - emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); - previousPerformBlock = lastTimestamp; - } - - function eligible() public view returns (bool) { - if (initialTimestamp == 0) { - return true; - } - - return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; - } - - function setSpread(uint256 _testRange, uint256 _interval) external { - testRange = _testRange; - interval = _interval; - initialTimestamp = 0; - counter = 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol deleted file mode 100644 index 76b3877..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepCounterNew.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -contract UpkeepCounterNew { - event PerformingUpkeep( - address indexed from, - uint256 initialTimestamp, - uint256 lastTimestamp, - uint256 previousBlock, - uint256 counter - ); - error InvalidCaller(address caller, address forwarder); - - uint256 public testRange; - uint256 public interval; - uint256 public lastTimestamp; - uint256 public previousPerformBlock; - uint256 public initialTimestamp; - uint256 public counter; - bool public useMoreCheckGas; - bool public useMorePerformGas; - bool public useMorePerformData; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - bytes public data; - bytes public dataCopy; - bool public trickSimulation = false; - address public forwarder; - - constructor() { - testRange = 1000000; - interval = 40; - previousPerformBlock = 0; - lastTimestamp = block.timestamp; - initialTimestamp = 0; - counter = 0; - useMoreCheckGas = false; - useMorePerformData = false; - useMorePerformGas = false; - checkGasToBurn = 9700000; - performGasToBurn = 7700000; - } - - function setPerformGasToBurn(uint256 _performGasToBurn) external { - performGasToBurn = _performGasToBurn; - } - - function setCheckGasToBurn(uint256 _checkGasToBurn) external { - checkGasToBurn = _checkGasToBurn; - } - - function setUseMoreCheckGas(bool _useMoreCheckGas) external { - useMoreCheckGas = _useMoreCheckGas; - } - - function setUseMorePerformGas(bool _useMorePerformGas) external { - useMorePerformGas = _useMorePerformGas; - } - - function setUseMorePerformData(bool _useMorePerformData) external { - useMorePerformData = _useMorePerformData; - } - - function setData(bytes calldata _data) external { - data = _data; - } - - function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { - if (useMoreCheckGas) { - uint256 startGas = gasleft(); - while (startGas - gasleft() < checkGasToBurn) {} // burn gas - } - - if (useMorePerformData) { - return (eligible(), data); - } - return (eligible(), ""); - } - - function setTrickSimulation(bool _trickSimulation) external { - trickSimulation = _trickSimulation; - } - - function performUpkeep(bytes calldata performData) external { - if (trickSimulation && tx.origin == address(0)) { - return; - } - - if (msg.sender != forwarder) { - revert InvalidCaller(msg.sender, forwarder); - } - - if (useMorePerformGas) { - uint256 startGas = gasleft(); - while (startGas - gasleft() < performGasToBurn) {} // burn gas - } - - if (initialTimestamp == 0) { - initialTimestamp = block.timestamp; - } - lastTimestamp = block.timestamp; - counter = counter + 1; - dataCopy = performData; - emit PerformingUpkeep(tx.origin, initialTimestamp, lastTimestamp, previousPerformBlock, counter); - previousPerformBlock = lastTimestamp; - } - - function eligible() public view returns (bool) { - if (initialTimestamp == 0) { - return true; - } - - return (block.timestamp - initialTimestamp) < testRange && (block.timestamp - lastTimestamp) >= interval; - } - - function setSpread(uint256 _testRange, uint256 _interval) external { - testRange = _testRange; - interval = _interval; - initialTimestamp = 0; - counter = 0; - } - - function setForwarder(address _forwarder) external { - forwarder = _forwarder; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol deleted file mode 100644 index 392700e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AutomationCompatible} from "../AutomationCompatible.sol"; - -contract UpkeepMock is AutomationCompatible { - bool public shouldRevertCheck; - bool public canCheck; - bool public canPerform; - bytes public performData; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - string public checkRevertReason; - - uint256 constant checkGasBuffer = 6000; // use all but this amount in gas burn loops - uint256 constant performGasBuffer = 1000; // use all but this amount in gas burn loops - - event UpkeepPerformedWith(bytes upkeepData); - - function setShouldRevertCheck(bool value) public { - shouldRevertCheck = value; - } - - function setPerformData(bytes calldata data) public { - performData = data; - } - - function setCanCheck(bool value) public { - canCheck = value; - } - - function setCanPerform(bool value) public { - canPerform = value; - } - - function setCheckRevertReason(string calldata value) public { - checkRevertReason = value; - } - - function setCheckGasToBurn(uint256 value) public { - require(value > checkGasBuffer || value == 0, "checkGasToBurn must be 0 (disabled) or greater than buffer"); - if (value > 0) { - checkGasToBurn = value - checkGasBuffer; - } else { - checkGasToBurn = 0; - } - } - - function setPerformGasToBurn(uint256 value) public { - require(value > performGasBuffer || value == 0, "performGasToBurn must be 0 (disabled) or greater than buffer"); - if (value > 0) { - performGasToBurn = value - performGasBuffer; - } else { - performGasToBurn = 0; - } - } - - function checkUpkeep( - bytes calldata - ) external override cannotExecute returns (bool callable, bytes memory executedata) { - require(!shouldRevertCheck, checkRevertReason); - uint256 startGas = gasleft(); - bool couldCheck = canCheck; - - setCanCheck(false); // test that state modifications don't stick - - while (startGas - gasleft() < checkGasToBurn) {} // burn gas - - return (couldCheck, performData); - } - - function performUpkeep(bytes calldata data) external override { - uint256 startGas = gasleft(); - - require(canPerform, "Cannot perform"); - - emit UpkeepPerformedWith(data); - - while (startGas - gasleft() < performGasToBurn) {} // burn gas - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol deleted file mode 100644 index 3aa345a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepPerformCounterRestrictive.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity 0.8.16; - -contract UpkeepPerformCounterRestrictive { - event PerformingUpkeep(bool eligible, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); - - uint256 public initialCall = 0; - uint256 public nextEligible = 0; - uint256 public testRange; - uint256 public averageEligibilityCadence; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - - uint256 private count = 0; - - constructor(uint256 _testRange, uint256 _averageEligibilityCadence) { - testRange = _testRange; - averageEligibilityCadence = _averageEligibilityCadence; - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - uint256 startGas = gasleft(); - uint256 blockNum = block.number - 1; - bool dummy; - // burn gas - while (startGas - gasleft() < checkGasToBurn) { - dummy = dummy && dummyMap[blockhash(blockNum)]; // arbitrary storage reads - blockNum--; - } - return (eligible(), abi.encode(dummy)); - } - - function performUpkeep(bytes calldata) external { - uint256 startGas = gasleft(); - bool eligible = eligible(); - uint256 blockNum = block.number; - emit PerformingUpkeep(eligible, tx.origin, initialCall, nextEligible, blockNum); - require(eligible); - if (initialCall == 0) { - initialCall = blockNum; - } - nextEligible = (blockNum + (rand() % (averageEligibilityCadence * 2))) + 1; - count++; - // burn gas - blockNum--; - while (startGas - gasleft() < performGasToBurn) { - dummyMap[blockhash(blockNum)] = false; // arbitrary storage writes - blockNum--; - } - } - - function setCheckGasToBurn(uint256 value) public { - checkGasToBurn = value; - } - - function setPerformGasToBurn(uint256 value) public { - performGasToBurn = value; - } - - function getCountPerforms() public view returns (uint256) { - return count; - } - - function eligible() internal view returns (bool) { - return initialCall == 0 || (block.number - initialCall < testRange && block.number > nextEligible); - } - - function checkEligible() public view returns (bool) { - return eligible(); - } - - function reset() external { - initialCall = 0; - count = 0; - } - - function setSpread(uint256 _newTestRange, uint256 _newAverageEligibilityCadence) external { - testRange = _newTestRange; - averageEligibilityCadence = _newAverageEligibilityCadence; - } - - function rand() private view returns (uint256) { - return uint256(keccak256(abi.encode(blockhash(block.number - 1), address(this)))); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol deleted file mode 100644 index 1d140cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AutomationCompatible} from "../AutomationCompatible.sol"; - -contract UpkeepReverter is AutomationCompatible { - function checkUpkeep( - bytes calldata data - ) public view override cannotExecute returns (bool callable, bytes calldata executedata) { - require(false, "!working"); - return (true, data); - } - - function performUpkeep(bytes calldata) external pure override { - require(false, "!working"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol deleted file mode 100644 index b9eda1f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeep.sol +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: MIT - -/** - The Cron contract is a chainlink keepers-powered cron job runner for smart contracts. - The contract enables developers to trigger actions on various targets using cron - strings to specify the cadence. For example, a user may have 3 tasks that require - regular service in their dapp ecosystem: - 1) 0xAB..CD, update(1), "0 0 * * *" --> runs update(1) on 0xAB..CD daily at midnight - 2) 0xAB..CD, update(2), "30 12 * * 0-4" --> runs update(2) on 0xAB..CD weekdays at 12:30 - 3) 0x12..34, trigger(), "0 * * * *" --> runs trigger() on 0x12..34 hourly - - To use this contract, a user first deploys this contract and registers it on the chainlink - keeper registry. Then the user adds cron jobs by following these steps: - 1) Convert a cron string to an encoded cron spec by calling encodeCronString() - 2) Take the encoding, target, and handler, and create a job by sending a tx to createCronJob() - 3) Cron job is running :) -*/ - -pragma solidity 0.8.6; - -import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; -import {Proxy} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {KeeperBase as KeeperBase} from "../KeeperBase.sol"; -import {KeeperCompatibleInterface as KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; -import {Cron as CronInternal, Spec} from "../libraries/internal/Cron.sol"; -import {Cron as CronExternal} from "../libraries/external/Cron.sol"; - -/** - * @title The CronUpkeep contract - * @notice A keeper-compatible contract that runs various tasks on cron schedules. - * Users must use the encodeCronString() function to encode their cron jobs before - * setting them. This keeps all the string manipulation off chain and reduces gas costs. - */ -contract CronUpkeep is KeeperCompatibleInterface, KeeperBase, ConfirmedOwner, Pausable, Proxy { - using EnumerableSet for EnumerableSet.UintSet; - - event CronJobExecuted(uint256 indexed id, bool success); - event CronJobCreated(uint256 indexed id, address target, bytes handler); - event CronJobUpdated(uint256 indexed id, address target, bytes handler); - event CronJobDeleted(uint256 indexed id); - - error CronJobIDNotFound(uint256 id); - error ExceedsMaxJobs(); - error InvalidHandler(); - error TickInFuture(); - error TickTooOld(); - error TickDoesntMatchSpec(); - - address immutable s_delegate; - uint256 public immutable s_maxJobs; - uint256 private s_nextCronJobID = 1; - EnumerableSet.UintSet private s_activeCronJobIDs; - - mapping(uint256 => uint256) private s_lastRuns; - mapping(uint256 => Spec) private s_specs; - mapping(uint256 => address) private s_targets; - mapping(uint256 => bytes) private s_handlers; - mapping(uint256 => bytes32) private s_handlerSignatures; - - /** - * @param owner the initial owner of the contract - * @param delegate the contract to delegate checkUpkeep calls to - * @param maxJobs the max number of cron jobs this contract will support - * @param firstJob an optional encoding of the first cron job - */ - constructor(address owner, address delegate, uint256 maxJobs, bytes memory firstJob) ConfirmedOwner(owner) { - s_delegate = delegate; - s_maxJobs = maxJobs; - if (firstJob.length > 0) { - (address target, bytes memory handler, Spec memory spec) = abi.decode(firstJob, (address, bytes, Spec)); - createCronJobFromSpec(target, handler, spec); - } - } - - /** - * @notice Executes the cron job with id encoded in performData - * @param performData abi encoding of cron job ID and the cron job's next run-at datetime - */ - function performUpkeep(bytes calldata performData) external override whenNotPaused { - (uint256 id, uint256 tickTime, address target, bytes memory handler) = abi.decode( - performData, - (uint256, uint256, address, bytes) - ); - validate(id, tickTime, target, handler); - s_lastRuns[id] = block.timestamp; - (bool success, ) = target.call(handler); - emit CronJobExecuted(id, success); - } - - /** - * @notice Creates a cron job from the given encoded spec - * @param target the destination contract of a cron job - * @param handler the function signature on the target contract to call - * @param encodedCronSpec abi encoding of a cron spec - */ - function createCronJobFromEncodedSpec( - address target, - bytes memory handler, - bytes memory encodedCronSpec - ) external onlyOwner { - if (s_activeCronJobIDs.length() >= s_maxJobs) { - revert ExceedsMaxJobs(); - } - Spec memory spec = abi.decode(encodedCronSpec, (Spec)); - createCronJobFromSpec(target, handler, spec); - } - - /** - * @notice Updates a cron job from the given encoded spec - * @param id the id of the cron job to update - * @param newTarget the destination contract of a cron job - * @param newHandler the function signature on the target contract to call - * @param newEncodedCronSpec abi encoding of a cron spec - */ - function updateCronJob( - uint256 id, - address newTarget, - bytes memory newHandler, - bytes memory newEncodedCronSpec - ) external onlyOwner onlyValidCronID(id) { - Spec memory newSpec = abi.decode(newEncodedCronSpec, (Spec)); - s_targets[id] = newTarget; - s_handlers[id] = newHandler; - s_specs[id] = newSpec; - s_handlerSignatures[id] = handlerSig(newTarget, newHandler); - emit CronJobUpdated(id, newTarget, newHandler); - } - - /** - * @notice Deletes the cron job matching the provided id. Reverts if - * the id is not found. - * @param id the id of the cron job to delete - */ - function deleteCronJob(uint256 id) external onlyOwner onlyValidCronID(id) { - delete s_lastRuns[id]; - delete s_specs[id]; - delete s_targets[id]; - delete s_handlers[id]; - delete s_handlerSignatures[id]; - s_activeCronJobIDs.remove(id); - emit CronJobDeleted(id); - } - - /** - * @notice Pauses the contract, which prevents executing performUpkeep - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice Unpauses the contract - */ - function unpause() external onlyOwner { - _unpause(); - } - - /** - * @notice Get the id of an eligible cron job - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding - * of the id and "next tick" of the elligible cron job - */ - function checkUpkeep(bytes calldata) external override whenNotPaused cannotExecute returns (bool, bytes memory) { - _delegate(s_delegate); - } - - /** - * @notice gets a list of active cron job IDs - * @return list of active cron job IDs - */ - function getActiveCronJobIDs() external view returns (uint256[] memory) { - uint256 length = s_activeCronJobIDs.length(); - uint256[] memory jobIDs = new uint256[](length); - for (uint256 idx = 0; idx < length; idx++) { - jobIDs[idx] = s_activeCronJobIDs.at(idx); - } - return jobIDs; - } - - /** - * @notice gets a cron job - * @param id the cron job ID - * @return target - the address a cron job forwards the eth tx to - handler - the encoded function sig to execute when forwarding a tx - cronString - the string representing the cron job - nextTick - the timestamp of the next time the cron job will run - */ - function getCronJob( - uint256 id - ) - external - view - onlyValidCronID(id) - returns (address target, bytes memory handler, string memory cronString, uint256 nextTick) - { - Spec memory spec = s_specs[id]; - return (s_targets[id], s_handlers[id], CronExternal.toCronString(spec), CronExternal.nextTick(spec)); - } - - /** - * @notice Adds a cron spec to storage and the ID to the list of jobs - * @param target the destination contract of a cron job - * @param handler the function signature on the target contract to call - * @param spec the cron spec to create - */ - function createCronJobFromSpec(address target, bytes memory handler, Spec memory spec) internal { - uint256 newID = s_nextCronJobID; - s_activeCronJobIDs.add(newID); - s_targets[newID] = target; - s_handlers[newID] = handler; - s_specs[newID] = spec; - s_lastRuns[newID] = block.timestamp; - s_handlerSignatures[newID] = handlerSig(target, handler); - s_nextCronJobID++; - emit CronJobCreated(newID, target, handler); - } - - function _implementation() internal view override returns (address) { - return s_delegate; - } - - /** - * @notice validates the input to performUpkeep - * @param id the id of the cron job - * @param tickTime the observed tick time - * @param target the contract to forward the tx to - * @param handler the handler of the contract receiving the forwarded tx - */ - function validate(uint256 id, uint256 tickTime, address target, bytes memory handler) private { - tickTime = tickTime - (tickTime % 60); // remove seconds from tick time - if (block.timestamp < tickTime) { - revert TickInFuture(); - } - if (tickTime <= s_lastRuns[id]) { - revert TickTooOld(); - } - if (!CronInternal.matches(s_specs[id], tickTime)) { - revert TickDoesntMatchSpec(); - } - if (handlerSig(target, handler) != s_handlerSignatures[id]) { - revert InvalidHandler(); - } - } - - /** - * @notice returns a unique identifier for target/handler pairs - * @param target the contract to forward the tx to - * @param handler the handler of the contract receiving the forwarded tx - * @return a hash of the inputs - */ - function handlerSig(address target, bytes memory handler) private pure returns (bytes32) { - return keccak256(abi.encodePacked(target, handler)); - } - - modifier onlyValidCronID(uint256 id) { - if (!s_activeCronJobIDs.contains(id)) { - revert CronJobIDNotFound(id); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol deleted file mode 100644 index ed8d031..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepDelegate.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Cron, Spec} from "../libraries/internal/Cron.sol"; - -/** - * @title The CronUpkeepDelegate contract - * @notice This contract serves as a delegate for all instances of CronUpkeep. Those contracts - * delegate their checkUpkeep calls onto this contract. Utilizing this pattern reduces the size - * of the CronUpkeep contracts. - */ -contract CronUpkeepDelegate { - using EnumerableSet for EnumerableSet.UintSet; - using Cron for Spec; - - address private s_owner; // from ConfirmedOwner - address private s_delegate; - uint256 private s_nextCronJobID; - EnumerableSet.UintSet private s_activeCronJobIDs; - mapping(uint256 => uint256) private s_lastRuns; - mapping(uint256 => Spec) private s_specs; - mapping(uint256 => address) private s_targets; - mapping(uint256 => bytes) private s_handlers; - - /** - * @notice Get the id of an eligible cron job - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding - * of the id and "next tick" of the eligible cron job - */ - function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) { - // DEV: start at a random spot in the list so that checks are - // spread evenly among cron jobs - uint256 numCrons = s_activeCronJobIDs.length(); - if (numCrons == 0) { - return (false, bytes("")); - } - uint256 startIdx = block.number % numCrons; - bool result; - bytes memory payload; - (result, payload) = checkInRange(startIdx, numCrons); - if (result) { - return (result, payload); - } - (result, payload) = checkInRange(0, startIdx); - if (result) { - return (result, payload); - } - return (false, bytes("")); - } - - /** - * @notice checks the cron jobs in a given range - * @param start the starting id to check (inclusive) - * @param end the ending id to check (exclusive) - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoding - * of the id and "next tick" of the eligible cron job - */ - function checkInRange(uint256 start, uint256 end) private view returns (bool, bytes memory) { - uint256 id; - uint256 lastTick; - for (uint256 idx = start; idx < end; idx++) { - id = s_activeCronJobIDs.at(idx); - lastTick = s_specs[id].lastTick(); - if (lastTick > s_lastRuns[id]) { - return (true, abi.encode(id, lastTick, s_targets[id], s_handlers[id])); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol deleted file mode 100644 index 2b6e97e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/CronUpkeepFactory.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {CronUpkeep} from "./CronUpkeep.sol"; -import {CronUpkeepDelegate} from "./CronUpkeepDelegate.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {Spec, Cron as CronExternal} from "../libraries/external/Cron.sol"; - -/** - * @title The CronUpkeepFactory contract - * @notice This contract serves as a delegate for all instances of CronUpkeep. Those contracts - * delegate their checkUpkeep calls onto this contract. Utilizing this pattern reduces the size - * of the CronUpkeep contracts. - */ -contract CronUpkeepFactory is ConfirmedOwner { - event NewCronUpkeepCreated(address upkeep, address owner); - - address private immutable s_cronDelegate; - uint256 public s_maxJobs = 5; - - constructor() ConfirmedOwner(msg.sender) { - s_cronDelegate = address(new CronUpkeepDelegate()); - } - - /** - * @notice Creates a new CronUpkeep contract, with msg.sender as the owner - */ - function newCronUpkeep() external { - newCronUpkeepWithJob(bytes("")); - } - - /** - * @notice Creates a new CronUpkeep contract, with msg.sender as the owner, and registers a cron job - */ - function newCronUpkeepWithJob(bytes memory encodedJob) public { - emit NewCronUpkeepCreated(address(new CronUpkeep(msg.sender, s_cronDelegate, s_maxJobs, encodedJob)), msg.sender); - } - - /** - * @notice Sets the max job limit on new cron upkeeps - */ - function setMaxJobs(uint256 maxJobs) external onlyOwner { - s_maxJobs = maxJobs; - } - - /** - * @notice Gets the address of the delegate contract - * @return the address of the delegate contract - */ - function cronDelegateAddress() external view returns (address) { - return s_cronDelegate; - } - - /** - * @notice Converts a cron string to a Spec, validates the spec, and encodes the spec. - * This should only be called off-chain, as it is gas expensive! - * @param cronString the cron string to convert and encode - * @return the abi encoding of the Spec struct representing the cron string - */ - function encodeCronString(string memory cronString) external pure returns (bytes memory) { - return CronExternal.toEncodedSpec(cronString); - } - - /** - * @notice Converts, validates, and encodes a full cron spec. This payload is then passed to newCronUpkeepWithJob. - * @param target the destination contract of a cron job - * @param handler the function signature on the target contract to call - * @param cronString the cron string to convert and encode - * @return the abi encoding of the entire cron job - */ - function encodeCronJob( - address target, - bytes memory handler, - string memory cronString - ) external pure returns (bytes memory) { - Spec memory spec = CronExternal.toSpec(cronString); - return abi.encode(target, handler, spec); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol deleted file mode 100644 index d2a7adc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/ERC20BalanceMonitor.sol +++ /dev/null @@ -1,279 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.4; - -import "../../shared/access/ConfirmedOwner.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; -import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; -import "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/** - * @title The ERC20BalanceMonitor contract. - * @notice A keeper-compatible contract that monitors and funds ERC20 tokens. - */ -contract ERC20BalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { - uint16 private constant MAX_WATCHLIST_SIZE = 300; - uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; - - event FundsWithdrawn(uint256 amountWithdrawn, address payee); - event TopUpSucceeded(address indexed topUpAddress); - event WatchlistUpdated(address[] oldWatchlist, address[] newWatchlist); - event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); - event ERC20TokenAddressUpdated(address oldAddress, address newAddress); - event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); - - error InvalidWatchList(); - error OnlyKeeperRegistry(); - error DuplicateAddress(address duplicate); - - struct Target { - bool isActive; - uint96 minBalance; - uint96 topUpLevel; - uint56 lastTopUpTimestamp; - } - - IERC20 private s_erc20Token; - address private s_keeperRegistryAddress; - uint256 private s_minWaitPeriodSeconds; - address[] private s_watchList; - mapping(address => Target) internal s_targets; - - /** - * @param erc20TokenAddress the ERC20 token address - * @param keeperRegistryAddress the address of the keeper registry contract - * @param minWaitPeriodSeconds the minimum wait period for addresses between funding - */ - constructor( - address erc20TokenAddress, - address keeperRegistryAddress, - uint256 minWaitPeriodSeconds - ) ConfirmedOwner(msg.sender) { - setERC20TokenAddress(erc20TokenAddress); - setKeeperRegistryAddress(keeperRegistryAddress); - setMinWaitPeriodSeconds(minWaitPeriodSeconds); - } - - /** - * @notice Sets the list of subscriptions to watch and their funding parameters. - * @param addresses the list of subscription ids to watch - * @param minBalances the minimum balances for each subscription - * @param topUpLevels the amount to top up to for each subscription - */ - function setWatchList( - address[] calldata addresses, - uint96[] calldata minBalances, - uint96[] calldata topUpLevels - ) external onlyOwner { - if ( - addresses.length != minBalances.length || - addresses.length != topUpLevels.length || - addresses.length > MAX_WATCHLIST_SIZE - ) { - revert InvalidWatchList(); - } - address[] memory oldWatchList = s_watchList; - for (uint256 idx = 0; idx < oldWatchList.length; idx++) { - s_targets[oldWatchList[idx]].isActive = false; - } - for (uint256 idx = 0; idx < addresses.length; idx++) { - if (s_targets[addresses[idx]].isActive) { - revert DuplicateAddress(addresses[idx]); - } - if (addresses[idx] == address(0)) { - revert InvalidWatchList(); - } - if (topUpLevels[idx] <= minBalances[idx]) { - revert InvalidWatchList(); - } - s_targets[addresses[idx]] = Target({ - isActive: true, - minBalance: minBalances[idx], - topUpLevel: topUpLevels[idx], - lastTopUpTimestamp: 0 - }); - } - s_watchList = addresses; - emit WatchlistUpdated(oldWatchList, addresses); - } - - /** - * @notice Gets a list of subscriptions that are underfunded. - * @return list of subscriptions that are underfunded - */ - function getUnderfundedAddresses() public view returns (address[] memory) { - address[] memory watchList = s_watchList; - address[] memory needsFunding = new address[](watchList.length); - uint256 count = 0; - uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; - uint256 contractBalance = s_erc20Token.balanceOf(address(this)); - Target memory target; - for (uint256 idx = 0; idx < watchList.length; idx++) { - target = s_targets[watchList[idx]]; - uint256 targetTokenBalance = s_erc20Token.balanceOf(watchList[idx]); - if ( - target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && - targetTokenBalance < target.minBalance && - contractBalance >= (target.topUpLevel - targetTokenBalance) - ) { - uint256 topUpAmount = target.topUpLevel - targetTokenBalance; - needsFunding[count] = watchList[idx]; - count++; - contractBalance -= topUpAmount; - } - } - if (count != watchList.length) { - assembly { - mstore(needsFunding, count) // resize array to number of valid targets - } - } - return needsFunding; - } - - /** - * @notice Send funds to the subscriptions provided. - * @param needsFunding the list of subscriptions to fund - */ - function topUp(address[] memory needsFunding) public whenNotPaused { - uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; - Target memory target; - uint256 contractBalance = s_erc20Token.balanceOf(address(this)); - for (uint256 idx = 0; idx < needsFunding.length; idx++) { - target = s_targets[needsFunding[idx]]; - uint256 targetTokenBalance = s_erc20Token.balanceOf(needsFunding[idx]); - if ( - target.isActive && - target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && - targetTokenBalance < target.minBalance && - contractBalance >= (target.topUpLevel - targetTokenBalance) - ) { - uint256 topUpAmount = target.topUpLevel - targetTokenBalance; - s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); - contractBalance -= topUpAmount; - SafeERC20.safeTransfer(s_erc20Token, needsFunding[idx], topUpAmount); - emit TopUpSucceeded(needsFunding[idx]); - } - if (gasleft() < MIN_GAS_FOR_TRANSFER) { - return; - } - } - } - - /** - * @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds - */ - function checkUpkeep( - bytes calldata - ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { - address[] memory needsFunding = getUnderfundedAddresses(); - upkeepNeeded = needsFunding.length > 0; - performData = abi.encode(needsFunding); - return (upkeepNeeded, performData); - } - - /** - * @notice Called by the keeper to send funds to underfunded addresses. - * @param performData the abi encoded list of addresses to fund - */ - function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { - address[] memory needsFunding = abi.decode(performData, (address[])); - topUp(needsFunding); - } - - /** - * @notice Withdraws the contract balance in the ERC20 token. - * @param amount the amount of the ERC20 to withdraw - * @param payee the address to pay - */ - function withdraw(uint256 amount, address payable payee) external onlyOwner { - require(payee != address(0)); - SafeERC20.safeTransfer(s_erc20Token, payee, amount); - emit FundsWithdrawn(amount, payee); - } - - /** - * @notice Sets the ERC20 token address. - */ - function setERC20TokenAddress(address erc20TokenAddress) public onlyOwner { - require(erc20TokenAddress != address(0)); - emit ERC20TokenAddressUpdated(address(s_erc20Token), erc20TokenAddress); - s_erc20Token = IERC20(erc20TokenAddress); - } - - /** - * @notice Sets the keeper registry address. - */ - function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { - require(keeperRegistryAddress != address(0)); - emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); - s_keeperRegistryAddress = keeperRegistryAddress; - } - - /** - * @notice Sets the minimum wait period (in seconds) for subscription ids between funding. - */ - function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { - emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); - s_minWaitPeriodSeconds = period; - } - - /** - * @notice Gets the ERC20 token address. - */ - function getERC20TokenAddress() external view returns (address) { - return address(s_erc20Token); - } - - /** - * @notice Gets the keeper registry address. - */ - function getKeeperRegistryAddress() external view returns (address) { - return s_keeperRegistryAddress; - } - - /** - * @notice Gets the minimum wait period. - */ - function getMinWaitPeriodSeconds() external view returns (uint256) { - return s_minWaitPeriodSeconds; - } - - /** - * @notice Gets the list of subscription ids being watched. - */ - function getWatchList() external view returns (address[] memory) { - return s_watchList; - } - - /** - * @notice Gets configuration information for an address on the watchlist - */ - function getAccountInfo( - address targetAddress - ) external view returns (bool isActive, uint96 minBalance, uint96 topUpLevel, uint56 lastTopUpTimestamp) { - Target memory target = s_targets[targetAddress]; - return (target.isActive, target.minBalance, target.topUpLevel, target.lastTopUpTimestamp); - } - - /** - * @notice Pause the contract, which prevents executing performUpkeep. - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice Unpause the contract. - */ - function unpause() external onlyOwner { - _unpause(); - } - - modifier onlyKeeperRegistry() { - if (msg.sender != s_keeperRegistryAddress) { - revert OnlyKeeperRegistry(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol deleted file mode 100644 index c7d8a30..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/EthBalanceMonitor.sol +++ /dev/null @@ -1,254 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import "../../shared/access/ConfirmedOwner.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; - -/** - * @title The EthBalanceMonitor contract - * @notice A keeper-compatible contract that monitors and funds eth addresses - */ -contract EthBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { - // observed limit of 45K + 10k buffer - uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; - - event FundsAdded(uint256 amountAdded, uint256 newBalance, address sender); - event FundsWithdrawn(uint256 amountWithdrawn, address payee); - event TopUpSucceeded(address indexed recipient); - event TopUpFailed(address indexed recipient); - event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); - event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); - - error InvalidWatchList(); - error OnlyKeeperRegistry(); - error DuplicateAddress(address duplicate); - - struct Target { - bool isActive; - uint96 minBalanceWei; - uint96 topUpAmountWei; - uint56 lastTopUpTimestamp; // enough space for 2 trillion years - } - - address private s_keeperRegistryAddress; - uint256 private s_minWaitPeriodSeconds; - address[] private s_watchList; - mapping(address => Target) internal s_targets; - - /** - * @param keeperRegistryAddress The address of the keeper registry contract - * @param minWaitPeriodSeconds The minimum wait period for addresses between funding - */ - constructor(address keeperRegistryAddress, uint256 minWaitPeriodSeconds) ConfirmedOwner(msg.sender) { - setKeeperRegistryAddress(keeperRegistryAddress); - setMinWaitPeriodSeconds(minWaitPeriodSeconds); - } - - /** - * @notice Sets the list of addresses to watch and their funding parameters - * @param addresses the list of addresses to watch - * @param minBalancesWei the minimum balances for each address - * @param topUpAmountsWei the amount to top up each address - */ - function setWatchList( - address[] calldata addresses, - uint96[] calldata minBalancesWei, - uint96[] calldata topUpAmountsWei - ) external onlyOwner { - if (addresses.length != minBalancesWei.length || addresses.length != topUpAmountsWei.length) { - revert InvalidWatchList(); - } - address[] memory oldWatchList = s_watchList; - for (uint256 idx = 0; idx < oldWatchList.length; idx++) { - s_targets[oldWatchList[idx]].isActive = false; - } - for (uint256 idx = 0; idx < addresses.length; idx++) { - if (s_targets[addresses[idx]].isActive) { - revert DuplicateAddress(addresses[idx]); - } - if (addresses[idx] == address(0)) { - revert InvalidWatchList(); - } - if (topUpAmountsWei[idx] == 0) { - revert InvalidWatchList(); - } - s_targets[addresses[idx]] = Target({ - isActive: true, - minBalanceWei: minBalancesWei[idx], - topUpAmountWei: topUpAmountsWei[idx], - lastTopUpTimestamp: 0 - }); - } - s_watchList = addresses; - } - - /** - * @notice Gets a list of addresses that are under funded - * @return list of addresses that are underfunded - */ - function getUnderfundedAddresses() public view returns (address[] memory) { - address[] memory watchList = s_watchList; - address[] memory needsFunding = new address[](watchList.length); - uint256 count = 0; - uint256 minWaitPeriod = s_minWaitPeriodSeconds; - uint256 balance = address(this).balance; - Target memory target; - for (uint256 idx = 0; idx < watchList.length; idx++) { - target = s_targets[watchList[idx]]; - if ( - target.lastTopUpTimestamp + minWaitPeriod <= block.timestamp && - balance >= target.topUpAmountWei && - watchList[idx].balance < target.minBalanceWei - ) { - needsFunding[count] = watchList[idx]; - count++; - balance -= target.topUpAmountWei; - } - } - if (count != watchList.length) { - assembly { - mstore(needsFunding, count) - } - } - return needsFunding; - } - - /** - * @notice Send funds to the addresses provided - * @param needsFunding the list of addresses to fund (addresses must be pre-approved) - */ - function topUp(address[] memory needsFunding) public whenNotPaused { - uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; - Target memory target; - for (uint256 idx = 0; idx < needsFunding.length; idx++) { - target = s_targets[needsFunding[idx]]; - if ( - target.isActive && - target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && - needsFunding[idx].balance < target.minBalanceWei - ) { - bool success = payable(needsFunding[idx]).send(target.topUpAmountWei); - if (success) { - s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); - emit TopUpSucceeded(needsFunding[idx]); - } else { - emit TopUpFailed(needsFunding[idx]); - } - } - if (gasleft() < MIN_GAS_FOR_TRANSFER) { - return; - } - } - } - - /** - * @notice Get list of addresses that are underfunded and return keeper-compatible payload - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of addresses that need funds - */ - function checkUpkeep( - bytes calldata - ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { - address[] memory needsFunding = getUnderfundedAddresses(); - upkeepNeeded = needsFunding.length > 0; - performData = abi.encode(needsFunding); - return (upkeepNeeded, performData); - } - - /** - * @notice Called by keeper to send funds to underfunded addresses - * @param performData The abi encoded list of addresses to fund - */ - function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { - address[] memory needsFunding = abi.decode(performData, (address[])); - topUp(needsFunding); - } - - /** - * @notice Withdraws the contract balance - * @param amount The amount of eth (in wei) to withdraw - * @param payee The address to pay - */ - function withdraw(uint256 amount, address payable payee) external onlyOwner { - require(payee != address(0)); - emit FundsWithdrawn(amount, payee); - payee.transfer(amount); - } - - /** - * @notice Receive funds - */ - receive() external payable { - emit FundsAdded(msg.value, address(this).balance, msg.sender); - } - - /** - * @notice Sets the keeper registry address - */ - function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { - require(keeperRegistryAddress != address(0)); - emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); - s_keeperRegistryAddress = keeperRegistryAddress; - } - - /** - * @notice Sets the minimum wait period (in seconds) for addresses between funding - */ - function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { - emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); - s_minWaitPeriodSeconds = period; - } - - /** - * @notice Gets the keeper registry address - */ - function getKeeperRegistryAddress() external view returns (address keeperRegistryAddress) { - return s_keeperRegistryAddress; - } - - /** - * @notice Gets the minimum wait period - */ - function getMinWaitPeriodSeconds() external view returns (uint256) { - return s_minWaitPeriodSeconds; - } - - /** - * @notice Gets the list of addresses being watched - */ - function getWatchList() external view returns (address[] memory) { - return s_watchList; - } - - /** - * @notice Gets configuration information for an address on the watchlist - */ - function getAccountInfo( - address targetAddress - ) external view returns (bool isActive, uint96 minBalanceWei, uint96 topUpAmountWei, uint56 lastTopUpTimestamp) { - Target memory target = s_targets[targetAddress]; - return (target.isActive, target.minBalanceWei, target.topUpAmountWei, target.lastTopUpTimestamp); - } - - /** - * @notice Pauses the contract, which prevents executing performUpkeep - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice Unpauses the contract - */ - function unpause() external onlyOwner { - _unpause(); - } - - modifier onlyKeeperRegistry() { - if (msg.sender != s_keeperRegistryAddress) { - revert OnlyKeeperRegistry(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol deleted file mode 100644 index 9bf68fc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/LinkAvailableBalanceMonitor.sol +++ /dev/null @@ -1,480 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.19; - -import {AutomationCompatibleInterface} from "../interfaces/AutomationCompatibleInterface.sol"; -import {AccessControl} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol"; -import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; - -interface IAggregatorProxy { - function aggregator() external view returns (address); -} - -interface ILinkAvailable { - function linkAvailableForPayment() external view returns (int256 availableBalance); -} - -/// @title The LinkAvailableBalanceMonitor contract. -/// @notice A keeper-compatible contract that monitors target contracts for balance from a custom -/// function linkAvailableForPayment() and funds them with LINK if it falls below a defined -/// threshold. Also supports aggregator proxy contracts monitoring which require fetching the actual -/// target contract through a predefined interface. -/// @dev with 30 addresses as the s_maxPerform, the measured max gas usage of performUpkeep is around 2M -/// therefore, we recommend an upkeep gas limit of 3M (this has a 33% margin of safety). Although, nothing -/// prevents us from using 5M gas and increasing s_maxPerform, 30 seems like a reasonable batch size that -/// is probably plenty for most needs. -/// @dev with 130 addresses as the s_maxCheck, the measured max gas usage of checkUpkeep is around 3.5M, -/// which is 30% below the 5M limit. -/// Note that testing conditions DO NOT match live chain gas usage, hence the margins. Change -/// at your own risk!!! -/// @dev some areas for improvement / acknowledgement of limitations: -/// validate that all addresses conform to interface when adding them to the watchlist -/// this is a "trustless" upkeep, meaning it does not trust the caller of performUpkeep; -/// we could save a fair amount of gas and re-write this upkeep for use with Automation v2.0+, -/// which has significantly different trust assumptions -contract LinkAvailableBalanceMonitor is AccessControl, AutomationCompatibleInterface, Pausable { - using EnumerableMap for EnumerableMap.UintToAddressMap; - using EnumerableSet for EnumerableSet.AddressSet; - - event BalanceUpdated(address indexed addr, uint256 oldBalance, uint256 newBalance); - event FundsWithdrawn(uint256 amountWithdrawn, address payee); - event UpkeepIntervalSet(uint256 oldUpkeepInterval, uint256 newUpkeepInterval); - event MaxCheckSet(uint256 oldMaxCheck, uint256 newMaxCheck); - event MaxPerformSet(uint256 oldMaxPerform, uint256 newMaxPerform); - event MinWaitPeriodSet(uint256 s_minWaitPeriodSeconds, uint256 minWaitPeriodSeconds); - event TopUpBlocked(address indexed topUpAddress); - event TopUpFailed(address indexed recipient); - event TopUpSucceeded(address indexed topUpAddress, uint256 amount); - event TopUpUpdated(address indexed addr, uint256 oldTopUpAmount, uint256 newTopUpAmount); - event WatchlistUpdated(); - - error InvalidAddress(address target); - error InvalidMaxCheck(uint16 maxCheck); - error InvalixMaxPerform(uint16 maxPerform); - error InvalidMinBalance(uint96 minBalance); - error InvalidTopUpAmount(uint96 topUpAmount); - error InvalidUpkeepInterval(uint8 upkeepInterval); - error InvalidLinkTokenAddress(address lt); - error InvalidWatchList(); - error InvalidChainSelector(); - error DuplicateAddress(address duplicate); - error ReentrantCall(); - - struct MonitoredAddress { - uint96 minBalance; - uint96 topUpAmount; - uint56 lastTopUpTimestamp; - bool isActive; - } - - bytes32 private constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - bytes32 private constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); - uint96 private constant DEFAULT_TOP_UP_AMOUNT_JUELS = 3000000000000000000; - uint96 private constant DEFAULT_MIN_BALANCE_JUELS = 1000000000000000000; - IERC20 private immutable i_linkToken; - - uint256 private s_minWaitPeriodSeconds; - uint16 private s_maxPerform; - uint16 private s_maxCheck; - uint8 private s_upkeepInterval; - - /// @notice s_watchList contains all the addresses watched by this monitor - /// @dev It mainly provides the length() function - EnumerableSet.AddressSet private s_watchList; - - /// @notice s_targets contains all the addresses watched by this monitor - /// Each key points to a MonitoredAddress with all the needed metadata - mapping(address targetAddress => MonitoredAddress targetProperties) private s_targets; - - /// @notice s_onRampAddresses represents a list of CCIP onRamp addresses watched on this contract - /// There has to be only one onRamp per dstChainSelector. - /// dstChainSelector is needed as we have to track the live onRamp, and delete the onRamp - /// whenever a new one is deployed with the same dstChainSelector. - EnumerableMap.UintToAddressMap private s_onRampAddresses; - - bool private reentrancyGuard; - - /// @param admin is the administrator address of this contract - /// @param linkToken the LINK token address - /// @param minWaitPeriodSeconds represents the amount of time that has to wait a contract to be funded - /// @param maxPerform maximum amount of contracts to fund - /// @param maxCheck maximum amount of contracts to check - /// @param upkeepInterval randomizes the check for underfunded contracts - constructor( - address admin, - IERC20 linkToken, - uint256 minWaitPeriodSeconds, - uint16 maxPerform, - uint16 maxCheck, - uint8 upkeepInterval - ) { - _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); - _setRoleAdmin(EXECUTOR_ROLE, ADMIN_ROLE); - _grantRole(ADMIN_ROLE, admin); - i_linkToken = linkToken; - setMinWaitPeriodSeconds(minWaitPeriodSeconds); - setMaxPerform(maxPerform); - setMaxCheck(maxCheck); - setUpkeepInterval(upkeepInterval); - reentrancyGuard = false; - } - - /// @notice Sets the list of subscriptions to watch and their funding parameters - /// @param addresses the list of target addresses to watch (could be direct target or IAggregatorProxy) - /// @param minBalances the list of corresponding minBalance for the target address - /// @param topUpAmounts the list of corresponding minTopUp for the target address - function setWatchList( - address[] calldata addresses, - uint96[] calldata minBalances, - uint96[] calldata topUpAmounts, - uint64[] calldata dstChainSelectors - ) external onlyAdminOrExecutor { - if ( - addresses.length != minBalances.length || - addresses.length != topUpAmounts.length || - addresses.length != dstChainSelectors.length - ) { - revert InvalidWatchList(); - } - for (uint256 idx = s_watchList.length(); idx > 0; idx--) { - address member = s_watchList.at(idx - 1); - s_watchList.remove(member); - delete s_targets[member]; - } - // s_onRampAddresses is not the same length as s_watchList, so it has - // to be clean in a separate loop - for (uint256 idx = s_onRampAddresses.length(); idx > 0; idx--) { - (uint256 key, ) = s_onRampAddresses.at(idx - 1); - s_onRampAddresses.remove(key); - } - for (uint256 idx = 0; idx < addresses.length; idx++) { - address targetAddress = addresses[idx]; - if (s_targets[targetAddress].isActive) revert DuplicateAddress(targetAddress); - if (targetAddress == address(0)) revert InvalidWatchList(); - if (minBalances[idx] == 0) revert InvalidWatchList(); - if (topUpAmounts[idx] == 0) revert InvalidWatchList(); - s_targets[targetAddress] = MonitoredAddress({ - isActive: true, - minBalance: minBalances[idx], - topUpAmount: topUpAmounts[idx], - lastTopUpTimestamp: 0 - }); - if (dstChainSelectors[idx] > 0) { - s_onRampAddresses.set(dstChainSelectors[idx], targetAddress); - } - s_watchList.add(targetAddress); - } - emit WatchlistUpdated(); - } - - /// @notice Adds a new address to the watchlist - /// @param targetAddress the address to be added to the watchlist - /// @param dstChainSelector carries a non-zero value in case the targetAddress is an onRamp, otherwise it carries a 0 - /// @dev this function has to be compatible with the event onRampSet(address, dstChainSelector) emitted by - /// the CCIP router. Important detail to know is this event is also emitted when an onRamp is decommissioned, - /// in which case it will carry the proper dstChainSelector along with the 0x0 address - function addToWatchListOrDecommission(address targetAddress, uint64 dstChainSelector) public onlyAdminOrExecutor { - if (s_targets[targetAddress].isActive) revert DuplicateAddress(targetAddress); - if (targetAddress == address(0) && dstChainSelector == 0) revert InvalidAddress(targetAddress); - bool onRampExists = s_onRampAddresses.contains(dstChainSelector); - // if targetAddress is an existing onRamp, there's a need of cleaning the previous onRamp associated to this dstChainSelector - // there's no need to remove any other address that's not an onRamp - if (dstChainSelector > 0 && onRampExists) { - address oldAddress = s_onRampAddresses.get(dstChainSelector); - removeFromWatchList(oldAddress); - } - // only add the new address if it's not 0x0 - if (targetAddress != address(0)) { - s_targets[targetAddress] = MonitoredAddress({ - isActive: true, - minBalance: DEFAULT_MIN_BALANCE_JUELS, - topUpAmount: DEFAULT_TOP_UP_AMOUNT_JUELS, - lastTopUpTimestamp: 0 - }); - s_watchList.add(targetAddress); - // add the contract to onRampAddresses if it carries a valid dstChainSelector - if (dstChainSelector > 0) { - s_onRampAddresses.set(dstChainSelector, targetAddress); - } - // else if is redundant as this is the only corner case left, maintaining it for legibility - } else if (targetAddress == address(0) && dstChainSelector > 0) { - s_onRampAddresses.remove(dstChainSelector); - } - } - - /// @notice Delete an address from the watchlist and sets the target to inactive - /// @param targetAddress the address to be deleted - function removeFromWatchList(address targetAddress) public onlyAdminOrExecutor returns (bool) { - if (s_watchList.remove(targetAddress)) { - delete s_targets[targetAddress]; - return true; - } - return false; - } - - /// @notice Gets a list of proxies that are underfunded, up to the s_maxPerform size - /// @dev the function starts at a random index in the list to avoid biasing the first - /// addresses in the list over latter ones. - /// @dev the function will check at most s_maxCheck proxies in a single call - /// @dev the function returns a list with a max length of s_maxPerform - /// @return list of target addresses which are underfunded - function sampleUnderfundedAddresses() public view returns (address[] memory) { - uint16 maxPerform = s_maxPerform; - uint16 maxCheck = s_maxCheck; - uint256 numTargets = s_watchList.length(); - uint256 idx = uint256(blockhash(block.number - (block.number % s_upkeepInterval) - 1)) % numTargets; - uint256 numToCheck = numTargets < maxCheck ? numTargets : maxCheck; - uint256 numFound = 0; - uint256 minWaitPeriod = s_minWaitPeriodSeconds; - address[] memory targetsToFund = new address[](maxPerform); - MonitoredAddress memory contractToFund; - address targetAddress; - for ( - uint256 numChecked = 0; - numChecked < numToCheck; - (idx, numChecked) = ((idx + 1) % numTargets, numChecked + 1) - ) { - targetAddress = s_watchList.at(idx); - contractToFund = s_targets[targetAddress]; - (bool fundingNeeded, ) = _needsFunding( - targetAddress, - contractToFund.lastTopUpTimestamp + minWaitPeriod, - contractToFund.minBalance, - contractToFund.isActive - ); - if (fundingNeeded) { - targetsToFund[numFound] = targetAddress; - numFound++; - if (numFound == maxPerform) { - break; // max number of addresses in batch reached - } - } - } - if (numFound != maxPerform) { - assembly { - mstore(targetsToFund, numFound) // resize array to number of valid targets - } - } - return targetsToFund; - } - - /// @notice tries to fund an array of target addresses, checking if they're underfunded in the process - /// @param targetAddresses is an array of contract addresses to be funded in case they're underfunded - function topUp(address[] memory targetAddresses) public whenNotPaused nonReentrant { - MonitoredAddress memory contractToFund; - uint256 minWaitPeriod = s_minWaitPeriodSeconds; - uint256 localBalance = i_linkToken.balanceOf(address(this)); - for (uint256 idx = 0; idx < targetAddresses.length; idx++) { - address targetAddress = targetAddresses[idx]; - contractToFund = s_targets[targetAddress]; - - (bool fundingNeeded, address target) = _needsFunding( - targetAddress, - contractToFund.lastTopUpTimestamp + minWaitPeriod, - contractToFund.minBalance, - contractToFund.isActive - ); - if (localBalance >= contractToFund.topUpAmount && fundingNeeded) { - bool success = i_linkToken.transfer(target, contractToFund.topUpAmount); - if (success) { - localBalance -= contractToFund.topUpAmount; - s_targets[targetAddress].lastTopUpTimestamp = uint56(block.timestamp); - emit TopUpSucceeded(target, contractToFund.topUpAmount); - } else { - emit TopUpFailed(targetAddress); - } - } else { - emit TopUpBlocked(targetAddress); - } - } - } - - /// @notice checks the target (could be direct target or IAggregatorProxy), and determines - /// if it is eligible for funding - /// @param targetAddress the target to check - /// @param minBalance minimum balance required for the target - /// @param minWaitPeriodPassed the minimum wait period (target lastTopUpTimestamp + minWaitPeriod) - /// @return bool whether the target needs funding or not - /// @return address the address to fund. for DF, this is the aggregator address behind the proxy address. - /// for other products, it's the original target address - function _needsFunding( - address targetAddress, - uint256 minWaitPeriodPassed, - uint256 minBalance, - bool contractIsActive - ) private view returns (bool, address) { - // Explicitly check if the targetAddress is the zero address - // or if it's not a contract. In both cases return with false, - // to prevent target.linkAvailableForPayment from running, - // which would revert the operation. - if (targetAddress == address(0) || targetAddress.code.length == 0) { - return (false, address(0)); - } - ILinkAvailable target; - IAggregatorProxy proxy = IAggregatorProxy(targetAddress); - try proxy.aggregator() returns (address aggregatorAddress) { - // proxy.aggregator() can return a 0 address if the address is not an aggregator - if (aggregatorAddress == address(0)) return (false, address(0)); - target = ILinkAvailable(aggregatorAddress); - } catch { - target = ILinkAvailable(targetAddress); - } - try target.linkAvailableForPayment() returns (int256 balance) { - if (balance < int256(minBalance) && minWaitPeriodPassed <= block.timestamp && contractIsActive) { - return (true, address(target)); - } - } catch {} - return (false, address(0)); - } - - /// @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. - /// @return upkeepNeeded signals if upkeep is needed - /// @return performData is an abi encoded list of subscription ids that need funds - function checkUpkeep( - bytes calldata - ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { - address[] memory needsFunding = sampleUnderfundedAddresses(); - if (needsFunding.length == 0) { - return (false, ""); - } - uint96 total_batch_balance; - for (uint256 idx = 0; idx < needsFunding.length; idx++) { - address targetAddress = needsFunding[idx]; - total_batch_balance = total_batch_balance + s_targets[targetAddress].topUpAmount; - } - if (i_linkToken.balanceOf(address(this)) >= total_batch_balance) { - return (true, abi.encode(needsFunding)); - } - return (false, ""); - } - - /// @notice Called by the keeper to send funds to underfunded addresses. - /// @param performData the abi encoded list of addresses to fund - function performUpkeep(bytes calldata performData) external override { - address[] memory needsFunding = abi.decode(performData, (address[])); - topUp(needsFunding); - } - - /// @notice Withdraws the contract balance in the LINK token. - /// @param amount the amount of the LINK to withdraw - /// @param payee the address to pay - function withdraw(uint256 amount, address payable payee) external onlyAdminOrExecutor { - if (payee == address(0)) revert InvalidAddress(payee); - i_linkToken.transfer(payee, amount); - emit FundsWithdrawn(amount, payee); - } - - /// @notice Sets the minimum balance for the given target address - function setMinBalance(address target, uint96 minBalance) external onlyRole(ADMIN_ROLE) { - if (target == address(0)) revert InvalidAddress(target); - if (minBalance == 0) revert InvalidMinBalance(minBalance); - if (!s_targets[target].isActive) revert InvalidWatchList(); - uint256 oldBalance = s_targets[target].minBalance; - s_targets[target].minBalance = minBalance; - emit BalanceUpdated(target, oldBalance, minBalance); - } - - /// @notice Sets the minimum balance for the given target address - function setTopUpAmount(address target, uint96 topUpAmount) external onlyRole(ADMIN_ROLE) { - if (target == address(0)) revert InvalidAddress(target); - if (topUpAmount == 0) revert InvalidTopUpAmount(topUpAmount); - if (!s_targets[target].isActive) revert InvalidWatchList(); - uint256 oldTopUpAmount = s_targets[target].topUpAmount; - s_targets[target].topUpAmount = topUpAmount; - emit BalanceUpdated(target, oldTopUpAmount, topUpAmount); - } - - /// @notice Update s_maxPerform - function setMaxPerform(uint16 maxPerform) public onlyRole(ADMIN_ROLE) { - emit MaxPerformSet(s_maxPerform, maxPerform); - s_maxPerform = maxPerform; - } - - /// @notice Update s_maxCheck - function setMaxCheck(uint16 maxCheck) public onlyRole(ADMIN_ROLE) { - emit MaxCheckSet(s_maxCheck, maxCheck); - s_maxCheck = maxCheck; - } - - /// @notice Sets the minimum wait period (in seconds) for addresses between funding - function setMinWaitPeriodSeconds(uint256 minWaitPeriodSeconds) public onlyRole(ADMIN_ROLE) { - emit MinWaitPeriodSet(s_minWaitPeriodSeconds, minWaitPeriodSeconds); - s_minWaitPeriodSeconds = minWaitPeriodSeconds; - } - - /// @notice Update s_upkeepInterval - function setUpkeepInterval(uint8 upkeepInterval) public onlyRole(ADMIN_ROLE) { - if (upkeepInterval > 255) revert InvalidUpkeepInterval(upkeepInterval); - emit UpkeepIntervalSet(s_upkeepInterval, upkeepInterval); - s_upkeepInterval = upkeepInterval; - } - - /// @notice Gets maxPerform - function getMaxPerform() external view returns (uint16) { - return s_maxPerform; - } - - /// @notice Gets maxCheck - function getMaxCheck() external view returns (uint16) { - return s_maxCheck; - } - - /// @notice Gets the minimum wait period - function getMinWaitPeriodSeconds() external view returns (uint256) { - return s_minWaitPeriodSeconds; - } - - /// @notice Gets upkeepInterval - function getUpkeepInterval() external view returns (uint8) { - return s_upkeepInterval; - } - - /// @notice Gets the list of subscription ids being watched - function getWatchList() external view returns (address[] memory) { - return s_watchList.values(); - } - - /// @notice Gets the onRamp address with the specified dstChainSelector - function getOnRampAddressAtChainSelector(uint64 dstChainSelector) external view returns (address) { - if (dstChainSelector == 0) revert InvalidChainSelector(); - return s_onRampAddresses.get(dstChainSelector); - } - - /// @notice Gets configuration information for an address on the watchlist - function getAccountInfo( - address targetAddress - ) external view returns (bool isActive, uint96 minBalance, uint96 topUpAmount, uint56 lastTopUpTimestamp) { - MonitoredAddress memory target = s_targets[targetAddress]; - return (target.isActive, target.minBalance, target.topUpAmount, target.lastTopUpTimestamp); - } - - /// @dev Modifier to make a function callable only by executor role or the - /// admin role. - modifier onlyAdminOrExecutor() { - address sender = _msgSender(); - if (!hasRole(ADMIN_ROLE, sender)) { - _checkRole(EXECUTOR_ROLE, sender); - } - _; - } - - modifier nonReentrant() { - if (reentrancyGuard) revert ReentrantCall(); - reentrancyGuard = true; - _; - reentrancyGuard = false; - } - - /// @notice Pause the contract, which prevents executing performUpkeep - function pause() external onlyRole(ADMIN_ROLE) { - _pause(); - } - - /// @notice Unpause the contract - function unpause() external onlyRole(ADMIN_ROLE) { - _unpause(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol deleted file mode 100644 index dae17da..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/upkeeps/UpkeepBalanceMonitor.sol +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IAutomationRegistryConsumer} from "../interfaces/IAutomationRegistryConsumer.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; -import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; - -/// @title The UpkeepBalanceMonitor contract -/// @notice A keeper-compatible contract that monitors and funds Chainlink Automation upkeeps. -contract UpkeepBalanceMonitor is ConfirmedOwner, Pausable { - using EnumerableSet for EnumerableSet.AddressSet; - - event ConfigSet(Config config); - event ForwarderSet(address forwarderAddress); - event FundsWithdrawn(uint256 amountWithdrawn, address payee); - event TopUpFailed(uint256 indexed upkeepId); - event TopUpSucceeded(uint256 indexed upkeepId, uint96 amount); - event WatchListSet(address registryAddress); - - error InvalidConfig(); - error InvalidTopUpData(); - error OnlyForwarderOrOwner(); - - /// @member maxBatchSize is the maximum number of upkeeps to fund in a single transaction - /// @member minPercentage is the percentage of the upkeep's minBalance at which top-up occurs - /// @member targetPercentage is the percentage of the upkeep's minBalance to top-up to - /// @member maxTopUpAmount is the maximum amount of LINK to top-up an upkeep with - struct Config { - uint8 maxBatchSize; - uint24 minPercentage; - uint24 targetPercentage; - uint96 maxTopUpAmount; - } - - // ================================================================ - // | STORAGE | - // ================================================================ - - LinkTokenInterface private immutable LINK_TOKEN; - - mapping(address => uint256[]) s_registryWatchLists; - EnumerableSet.AddressSet s_registries; - Config private s_config; - address private s_forwarderAddress; - - // ================================================================ - // | CONSTRUCTOR | - // ================================================================ - - /// @param linkToken the Link token address - /// @param config the initial config for the contract - constructor(LinkTokenInterface linkToken, Config memory config) ConfirmedOwner(msg.sender) { - require(address(linkToken) != address(0)); - LINK_TOKEN = linkToken; - setConfig(config); - } - - // ================================================================ - // | CORE FUNCTIONALITY | - // ================================================================ - - /// @notice Gets a list of upkeeps that are underfunded - /// @return needsFunding list of underfunded upkeepIDs - /// @return registryAddresses list of registries that the upkeepIDs belong to - /// @return topUpAmounts amount to top up each upkeep - function getUnderfundedUpkeeps() public view returns (uint256[] memory, address[] memory, uint96[] memory) { - Config memory config = s_config; - uint256[] memory needsFunding = new uint256[](config.maxBatchSize); - address[] memory registryAddresses = new address[](config.maxBatchSize); - uint96[] memory topUpAmounts = new uint96[](config.maxBatchSize); - uint256 availableFunds = LINK_TOKEN.balanceOf(address(this)); - uint256 count; - for (uint256 i = 0; i < s_registries.length(); i++) { - IAutomationRegistryConsumer registry = IAutomationRegistryConsumer(s_registries.at(i)); - for (uint256 j = 0; j < s_registryWatchLists[address(registry)].length; j++) { - uint256 upkeepID = s_registryWatchLists[address(registry)][j]; - uint96 upkeepBalance = registry.getBalance(upkeepID); - uint96 minBalance = registry.getMinBalance(upkeepID); - uint96 topUpThreshold = (minBalance * config.minPercentage) / 100; - uint96 topUpAmount = ((minBalance * config.targetPercentage) / 100) - upkeepBalance; - if (topUpAmount > config.maxTopUpAmount) { - topUpAmount = config.maxTopUpAmount; - } - if (upkeepBalance <= topUpThreshold && availableFunds >= topUpAmount) { - needsFunding[count] = upkeepID; - topUpAmounts[count] = topUpAmount; - registryAddresses[count] = address(registry); - count++; - availableFunds -= topUpAmount; - } - if (count == config.maxBatchSize) { - break; - } - } - if (count == config.maxBatchSize) { - break; - } - } - if (count < config.maxBatchSize) { - assembly { - mstore(needsFunding, count) - mstore(registryAddresses, count) - mstore(topUpAmounts, count) - } - } - return (needsFunding, registryAddresses, topUpAmounts); - } - - /// @notice Called by the keeper/owner to send funds to underfunded upkeeps - /// @param upkeepIDs the list of upkeep ids to fund - /// @param registryAddresses the list of registries that the upkeepIDs belong to - /// @param topUpAmounts the list of amounts to fund each upkeep with - /// @dev We explicitly choose not to verify that input upkeepIDs are included in the watchlist. We also - /// explicity permit any amount to be sent via topUpAmounts; it does not have to meet the criteria - /// specified in getUnderfundedUpkeeps(). Here, we are relying on the security of automation's OCR to - /// secure the output of getUnderfundedUpkeeps() as the input to topUp(), and we are treating the owner - /// as a privileged user that can perform arbitrary top-ups to any upkeepID. - function topUp( - uint256[] memory upkeepIDs, - address[] memory registryAddresses, - uint96[] memory topUpAmounts - ) public whenNotPaused { - if (msg.sender != address(s_forwarderAddress) && msg.sender != owner()) revert OnlyForwarderOrOwner(); - if (upkeepIDs.length != registryAddresses.length || upkeepIDs.length != topUpAmounts.length) - revert InvalidTopUpData(); - for (uint256 i = 0; i < upkeepIDs.length; i++) { - try LINK_TOKEN.transferAndCall(registryAddresses[i], topUpAmounts[i], abi.encode(upkeepIDs[i])) returns ( - bool success - ) { - if (success) { - emit TopUpSucceeded(upkeepIDs[i], topUpAmounts[i]); - continue; - } - } catch {} - emit TopUpFailed(upkeepIDs[i]); - } - } - - // ================================================================ - // | AUTOMATION COMPATIBLE | - // ================================================================ - - /// @notice Gets list of upkeeps ids that are underfunded and returns a keeper-compatible payload. - /// @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds - function checkUpkeep(bytes calldata) external view returns (bool upkeepNeeded, bytes memory performData) { - ( - uint256[] memory needsFunding, - address[] memory registryAddresses, - uint96[] memory topUpAmounts - ) = getUnderfundedUpkeeps(); - upkeepNeeded = needsFunding.length > 0; - if (upkeepNeeded) { - performData = abi.encode(needsFunding, registryAddresses, topUpAmounts); - } - return (upkeepNeeded, performData); - } - - /// @notice Called by the keeper to send funds to underfunded addresses. - /// @param performData the abi encoded list of addresses to fund - function performUpkeep(bytes calldata performData) external { - (uint256[] memory upkeepIDs, address[] memory registryAddresses, uint96[] memory topUpAmounts) = abi.decode( - performData, - (uint256[], address[], uint96[]) - ); - topUp(upkeepIDs, registryAddresses, topUpAmounts); - } - - // ================================================================ - // | ADMIN | - // ================================================================ - - /// @notice Withdraws the contract balance in LINK. - /// @param amount the amount of LINK (in juels) to withdraw - /// @param payee the address to pay - function withdraw(uint256 amount, address payee) external onlyOwner { - require(payee != address(0)); - LINK_TOKEN.transfer(payee, amount); - emit FundsWithdrawn(amount, payee); - } - - /// @notice Pause the contract, which prevents executing performUpkeep. - function pause() external onlyOwner { - _pause(); - } - - /// @notice Unpause the contract. - function unpause() external onlyOwner { - _unpause(); - } - - // ================================================================ - // | SETTERS | - // ================================================================ - - /// @notice Sets the list of upkeeps to watch - /// @param registryAddress the registry that this watchlist applies to - /// @param watchlist the list of UpkeepIDs to watch - function setWatchList(address registryAddress, uint256[] calldata watchlist) external onlyOwner { - if (watchlist.length == 0) { - s_registries.remove(registryAddress); - delete s_registryWatchLists[registryAddress]; - } else { - s_registries.add(registryAddress); - s_registryWatchLists[registryAddress] = watchlist; - } - emit WatchListSet(registryAddress); - } - - /// @notice Sets the contract config - /// @param config the new config - function setConfig(Config memory config) public onlyOwner { - if ( - config.maxBatchSize == 0 || - config.minPercentage < 100 || - config.targetPercentage <= config.minPercentage || - config.maxTopUpAmount == 0 - ) { - revert InvalidConfig(); - } - s_config = config; - emit ConfigSet(config); - } - - /// @notice Sets the upkeep's forwarder contract - /// @param forwarderAddress the new forwarder - /// @dev this should only need to be called once, after registering the contract with the registry - function setForwarder(address forwarderAddress) external onlyOwner { - s_forwarderAddress = forwarderAddress; - emit ForwarderSet(forwarderAddress); - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - /// @notice Gets the list of upkeeps ids being monitored - function getWatchList() external view returns (address[] memory, uint256[][] memory) { - address[] memory registryAddresses = s_registries.values(); - uint256[][] memory upkeepIDs = new uint256[][](registryAddresses.length); - for (uint256 i = 0; i < registryAddresses.length; i++) { - upkeepIDs[i] = s_registryWatchLists[registryAddresses[i]]; - } - return (registryAddresses, upkeepIDs); - } - - /// @notice Gets the contract config - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice Gets the upkeep's forwarder contract - function getForwarder() external view returns (address) { - return s_forwarderAddress; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol deleted file mode 100644 index f455d56..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistrar1_2.sol +++ /dev/null @@ -1,425 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; -import "../../shared/interfaces/LinkTokenInterface.sol"; -import "../../shared/access/ConfirmedOwner.sol"; -import "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Contract to accept requests for upkeep registrations - * @dev There are 2 registration workflows in this contract - * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually - * calls `approve` to register upkeep and emit events to inform UI and others interested. - * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on - * keeper registry and then emits approved event to finish the flow automatically without manual intervention. - * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. - * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. - */ -contract KeeperRegistrar is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { - /** - * DISABLED: No auto approvals, all new upkeeps should be approved manually. - * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. - * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. - */ - enum AutoApproveType { - DISABLED, - ENABLED_SENDER_ALLOWLIST, - ENABLED_ALL - } - - bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; - - mapping(bytes32 => PendingRequest) private s_pendingRequests; - - LinkTokenInterface public immutable LINK; - - /** - * @notice versions: - * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve - * : Remove rate limit and add max allowed for auto approve - * - KeeperRegistrar 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistrar 1.1.0"; - - struct Config { - AutoApproveType autoApproveConfigType; - uint32 autoApproveMaxAllowed; - uint32 approvedCount; - KeeperRegistryBaseInterface keeperRegistry; - uint96 minLINKJuels; - } - - struct PendingRequest { - address admin; - uint96 balance; - } - - Config private s_config; - // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST - mapping(address => bool) private s_autoApproveAllowedSenders; - - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes checkData, - uint96 amount, - uint8 indexed source - ); - - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - - event RegistrationRejected(bytes32 indexed hash); - - event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); - - event ConfigChanged( - AutoApproveType autoApproveConfigType, - uint32 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ); - - error InvalidAdminAddress(); - error RequestNotFound(); - error HashMismatch(); - error OnlyAdminOrOwner(); - error InsufficientPayment(); - error RegistrationRequestFailed(); - error OnlyLink(); - error AmountMismatch(); - error SenderMismatch(); - error FunctionNotPermitted(); - error LinkTransferFailed(address to); - error InvalidDataLength(); - - /* - * @param LINKAddress Address of Link token - * @param autoApproveConfigType setting for auto-approve registrations - * @param autoApproveMaxAllowed max number of registrations that can be auto approved - * @param keeperRegistry keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - */ - constructor( - address LINKAddress, - AutoApproveType autoApproveConfigType, - uint16 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(LINKAddress); - setRegistrationConfig(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); - } - - //EXTERNAL - - /** - * @notice register can only be called through transferAndCall on LINK contract - * @param name string of the upkeep to be registered - * @param encryptedEmail email address of upkeep contact - * @param upkeepContract address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when performing upkeep - * @param adminAddress address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - * @param amount quantity of LINK upkeep is funded with (specified in Juels) - * @param source application sending this request - * @param sender address of the sender making the request - */ - function register( - string memory name, - bytes calldata encryptedEmail, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - uint96 amount, - uint8 source, - address sender - ) external onlyLINK { - if (adminAddress == address(0)) { - revert InvalidAdminAddress(); - } - bytes32 hash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); - - emit RegistrationRequested( - hash, - name, - encryptedEmail, - upkeepContract, - gasLimit, - adminAddress, - checkData, - amount, - source - ); - - Config memory config = s_config; - if (_shouldAutoApprove(config, sender)) { - s_config.approvedCount = config.approvedCount + 1; - - _approve(name, upkeepContract, gasLimit, adminAddress, checkData, amount, hash); - } else { - uint96 newBalance = s_pendingRequests[hash].balance + amount; - s_pendingRequests[hash] = PendingRequest({admin: adminAddress, balance: newBalance}); - } - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - bytes32 hash - ) external onlyOwner { - PendingRequest memory request = s_pendingRequests[hash]; - if (request.admin == address(0)) { - revert RequestNotFound(); - } - bytes32 expectedHash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); - if (hash != expectedHash) { - revert HashMismatch(); - } - delete s_pendingRequests[hash]; - _approve(name, upkeepContract, gasLimit, adminAddress, checkData, request.balance, hash); - } - - /** - * @notice cancel will remove a registration request and return the refunds to the msg.sender - * @param hash the request hash - */ - function cancel(bytes32 hash) external { - PendingRequest memory request = s_pendingRequests[hash]; - if (!(msg.sender == request.admin || msg.sender == owner())) { - revert OnlyAdminOrOwner(); - } - if (request.admin == address(0)) { - revert RequestNotFound(); - } - delete s_pendingRequests[hash]; - bool success = LINK.transfer(msg.sender, request.balance); - if (!success) { - revert LinkTransferFailed(msg.sender); - } - emit RegistrationRejected(hash); - } - - /** - * @notice owner calls this function to set if registration requests should be sent directly to the Keeper Registry - * @param autoApproveConfigType setting for auto-approve registrations - * note: autoApproveAllowedSenders list persists across config changes irrespective of type - * @param autoApproveMaxAllowed max number of registrations that can be auto approved - * @param keeperRegistry new keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - */ - function setRegistrationConfig( - AutoApproveType autoApproveConfigType, - uint16 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ) public onlyOwner { - uint32 approvedCount = s_config.approvedCount; - s_config = Config({ - autoApproveConfigType: autoApproveConfigType, - autoApproveMaxAllowed: autoApproveMaxAllowed, - approvedCount: approvedCount, - minLINKJuels: minLINKJuels, - keeperRegistry: KeeperRegistryBaseInterface(keeperRegistry) - }); - - emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); - } - - /** - * @notice owner calls this function to set allowlist status for senderAddress - * @param senderAddress senderAddress to set the allowlist status for - * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed - */ - function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { - s_autoApproveAllowedSenders[senderAddress] = allowed; - - emit AutoApproveAllowedSenderSet(senderAddress, allowed); - } - - /** - * @notice read the allowlist status of senderAddress - * @param senderAddress address to read the allowlist status for - */ - function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { - return s_autoApproveAllowedSenders[senderAddress]; - } - - /** - * @notice read the current registration configuration - */ - function getRegistrationConfig() - external - view - returns ( - AutoApproveType autoApproveConfigType, - uint32 autoApproveMaxAllowed, - uint32 approvedCount, - address keeperRegistry, - uint256 minLINKJuels - ) - { - Config memory config = s_config; - return ( - config.autoApproveConfigType, - config.autoApproveMaxAllowed, - config.approvedCount, - address(config.keeperRegistry), - config.minLINKJuels - ); - } - - /** - * @notice gets the admin address and the current balance of a registration request - */ - function getPendingRequest(bytes32 hash) external view returns (address, uint96) { - PendingRequest memory request = s_pendingRequests[hash]; - return (request.admin, request.balance); - } - - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @param sender Address of the sender transfering LINK - * @param amount Amount of LINK sent (specified in Juels) - * @param data Payload of the transaction - */ - function onTokenTransfer( - address sender, - uint256 amount, - bytes calldata data - ) - external - override - onlyLINK - permittedFunctionsForLINK(data) - isActualAmount(amount, data) - isActualSender(sender, data) - { - if (data.length < 292) revert InvalidDataLength(); - if (amount < s_config.minLINKJuels) { - revert InsufficientPayment(); - } - (bool success, ) = address(this).delegatecall(data); - // calls register - if (!success) { - revert RegistrationRequestFailed(); - } - } - - //PRIVATE - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function _approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - uint96 amount, - bytes32 hash - ) private { - KeeperRegistryBaseInterface keeperRegistry = s_config.keeperRegistry; - - // register upkeep - uint256 upkeepId = keeperRegistry.registerUpkeep(upkeepContract, gasLimit, adminAddress, checkData); - // fund upkeep - bool success = LINK.transferAndCall(address(keeperRegistry), amount, abi.encode(upkeepId)); - if (!success) { - revert LinkTransferFailed(address(keeperRegistry)); - } - - emit RegistrationApproved(hash, name, upkeepId); - } - - /** - * @dev verify sender allowlist if needed and check max limit - */ - function _shouldAutoApprove(Config memory config, address sender) private returns (bool) { - if (config.autoApproveConfigType == AutoApproveType.DISABLED) { - return false; - } - if ( - config.autoApproveConfigType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender]) - ) { - return false; - } - if (config.approvedCount < config.autoApproveMaxAllowed) { - return true; - } - return false; - } - - //MODIFIERS - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - if (msg.sender != address(LINK)) { - revert OnlyLink(); - } - _; - } - - /** - * @dev Reverts if the given data does not begin with the `register` function selector - * @param _data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory _data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data - } - if (funcSelector != REGISTER_REQUEST_SELECTOR) { - revert FunctionNotPermitted(); - } - _; - } - - /** - * @dev Reverts if the actual amount passed does not match the expected amount - * @param expected amount that should match the actual amount - * @param data bytes - */ - modifier isActualAmount(uint256 expected, bytes memory data) { - uint256 actual; - assembly { - actual := mload(add(data, 228)) - } - if (expected != actual) { - revert AmountMismatch(); - } - _; - } - - /** - * @dev Reverts if the actual sender address does not match the expected sender address - * @param expected address that should match the actual sender address - * @param data bytes - */ - modifier isActualSender(address expected, bytes memory data) { - address actual; - assembly { - actual := mload(add(data, 292)) - } - if (expected != actual) { - revert SenderMismatch(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol deleted file mode 100644 index 2fa1ee6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistry1_2.sol +++ /dev/null @@ -1,909 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/security/Pausable.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "../KeeperBase.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; -import "../../shared/interfaces/AggregatorV3Interface.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; -import "../interfaces/v1_2/KeeperRegistryInterface1_2.sol"; -import "../interfaces/MigratableKeeperRegistryInterface.sol"; -import "../interfaces/UpkeepTranscoderInterface.sol"; -import "../../shared/interfaces/IERC677Receiver.sol"; -import "../../shared/interfaces/LinkTokenInterface.sol"; -import "../../shared/access/ConfirmedOwner.sol"; - -struct Upkeep { - uint96 balance; - address lastKeeper; // 1 storage slot full - uint32 executeGas; - uint64 maxValidBlocknumber; - address target; // 2 storage slots full - uint96 amountSpent; - address admin; // 3 storage slots full -} - -/** - * @notice Registry for adding work for Chainlink Keepers to perform on client - * contracts. Clients must support the Upkeep interface. - */ -contract KeeperRegistry1_2 is - TypeAndVersionInterface, - ConfirmedOwner, - KeeperBase, - ReentrancyGuard, - Pausable, - KeeperRegistryExecutableInterface, - MigratableKeeperRegistryInterface, - IERC677Receiver -{ - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - - address private constant ZERO_ADDRESS = address(0); - address private constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 private constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 private constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - uint256 private constant PERFORM_GAS_MIN = 2_300; - uint256 private constant CANCELATION_DELAY = 50; - uint256 private constant PERFORM_GAS_CUSHION = 5_000; - uint256 private constant REGISTRY_GAS_OVERHEAD = 80_000; - uint256 private constant PPB_BASE = 1_000_000_000; - uint64 private constant UINT64_MAX = 2 ** 64 - 1; - uint96 private constant LINK_TOTAL_SUPPLY = 1e27; - - address[] private s_keeperList; - EnumerableSet.UintSet private s_upkeepIDs; - mapping(uint256 => Upkeep) private s_upkeep; - mapping(address => KeeperInfo) private s_keeperInfo; - mapping(address => address) private s_proposedPayee; - mapping(uint256 => bytes) private s_checkData; - mapping(address => MigrationPermission) private s_peerRegistryMigrationPermission; - Storage private s_storage; - uint256 private s_fallbackGasPrice; // not in config object for gas savings - uint256 private s_fallbackLinkPrice; // not in config object for gas savings - uint96 private s_ownerLinkBalance; - uint256 private s_expectedLinkBalance; - address private s_transcoder; - address private s_registrar; - - LinkTokenInterface public immutable LINK; - AggregatorV3Interface public immutable LINK_ETH_FEED; - AggregatorV3Interface public immutable FAST_GAS_FEED; - - /** - * @notice versions: - * - KeeperRegistry 1.2.0: allow funding within performUpkeep - * : allow configurable registry maxPerformGas - * : add function to let admin change upkeep gas limit - * : add minUpkeepSpend requirement - : upgrade to solidity v0.8 - * - KeeperRegistry 1.1.0: added flatFeeMicroLink - * - KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistry 1.2.0"; - - error CannotCancel(); - error UpkeepNotActive(); - error MigrationNotPermitted(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error NotAContract(); - error PaymentGreaterThanAllLINK(); - error OnlyActiveKeepers(); - error InsufficientFunds(); - error KeepersMustTakeTurns(); - error ParameterLengthError(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByLINKToken(); - error InvalidPayee(); - error DuplicateEntry(); - error ValueNotChanged(); - error IndexOutOfRange(); - error TranscoderNotSet(); - error ArrayHasNoEntries(); - error GasLimitOutsideRange(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedPayee(); - error GasLimitCanOnlyIncrease(); - error OnlyCallableByAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error InvalidRecipient(); - error InvalidDataLength(); - error TargetCheckReverted(bytes reason); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - /** - * @notice storage of the registry, contains a mix of config and state data - */ - struct Storage { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; // 1 evm word - uint32 maxPerformGas; - uint32 nonce; // 2 evm words - } - - struct KeeperInfo { - address payee; - uint96 balance; - bool active; - } - - struct PerformParams { - address from; - uint256 id; - bytes performData; - uint256 maxLinkPayment; - uint256 gasLimit; - uint256 adjustedGasWei; - uint256 linkEth; - } - - event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - address indexed from, - uint96 payment, - bytes performData - ); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event OwnerFundsWithdrawn(uint96 amount); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event ConfigSet(Config config); - event KeepersUpdated(address[] keepers, address[] payees); - event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); - event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - - /** - * @param link address of the LINK Token - * @param linkEthFeed address of the LINK/ETH price feed - * @param fastGasFeed address of the Fast Gas price feed - * @param config registry config settings - */ - constructor(address link, address linkEthFeed, address fastGasFeed, Config memory config) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(link); - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - FAST_GAS_FEED = AggregatorV3Interface(fastGasFeed); - setConfig(config); - } - - // ACTIONS - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external override onlyOwnerOrRegistrar returns (uint256 id) { - id = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), s_storage.nonce))); - _createUpkeep(id, target, gasLimit, admin, 0, checkData); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - return id; - } - - /** - * @notice simulated by keepers via eth_call to see if the upkeep needs to be - * performed. If upkeep is needed, the call then simulates performUpkeep - * to make sure it succeeds. Finally, it returns the success status along with - * payment information and the perform data payload. - * @param id identifier of the upkeep to check - * @param from the address to simulate performing the upkeep from - */ - function checkUpkeep( - uint256 id, - address from - ) - external - override - cannotExecute - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) - { - Upkeep memory upkeep = s_upkeep[id]; - - bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); - (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); - - if (!success) revert TargetCheckReverted(result); - - (success, performData) = abi.decode(result, (bool, bytes)); - if (!success) revert UpkeepNotNeeded(); - - PerformParams memory params = _generatePerformParams(from, id, performData, false); - _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - return (performData, params.maxLinkPayment, params.gasLimit, params.adjustedGasWei, params.linkEth); - } - - /** - * @notice executes the upkeep with the perform data returned from - * checkUpkeep, validates the keeper's permissions, and pays the keeper. - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - */ - function performUpkeep( - uint256 id, - bytes calldata performData - ) external override whenNotPaused returns (bool success) { - return _performUpkeepWithParams(_generatePerformParams(msg.sender, id, performData, true)); - } - - /** - * @notice prevent an upkeep from being performed in the future - * @param id upkeep to be canceled - */ - function cancelUpkeep(uint256 id) external override { - uint64 maxValid = s_upkeep[id].maxValidBlocknumber; - bool canceled = maxValid != UINT64_MAX; - bool isOwner = msg.sender == owner(); - - if (canceled && !(isOwner && maxValid > block.number)) revert CannotCancel(); - if (!isOwner && msg.sender != s_upkeep[id].admin) revert OnlyCallableByOwnerOrAdmin(); - - uint256 height = block.number; - if (!isOwner) { - height = height + CANCELATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint64(height); - s_upkeepIDs.remove(id); - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice adds LINK funding for an upkeep by transferring from the sender's - * LINK balance - * @param id upkeep to fund - * @param amount number of LINK to transfer - */ - function addFunds(uint256 id, uint96 amount) external override onlyActiveUpkeep(id) { - s_upkeep[id].balance = s_upkeep[id].balance + amount; - s_expectedLinkBalance = s_expectedLinkBalance + amount; - LINK.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(LINK)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); - - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_expectedLinkBalance = s_expectedLinkBalance + amount; - - emit FundsAdded(id, sender, uint96(amount)); - } - - /** - * @notice removes funding from a canceled upkeep - * @param id upkeep to withdraw funds from - * @param to destination address for sending remaining funds - */ - function withdrawFunds(uint256 id, address to) external validRecipient(to) onlyUpkeepAdmin(id) { - if (s_upkeep[id].maxValidBlocknumber > block.number) revert UpkeepNotCanceled(); - - uint96 minUpkeepSpend = s_storage.minUpkeepSpend; - uint96 amountLeft = s_upkeep[id].balance; - uint96 amountSpent = s_upkeep[id].amountSpent; - - uint96 cancellationFee = 0; - // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) - if (amountSpent < minUpkeepSpend) { - cancellationFee = minUpkeepSpend - amountSpent; - if (cancellationFee > amountLeft) { - cancellationFee = amountLeft; - } - } - uint96 amountToWithdraw = amountLeft - cancellationFee; - - s_upkeep[id].balance = 0; - s_ownerLinkBalance = s_ownerLinkBalance + cancellationFee; - - s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; - emit FundsWithdrawn(id, amountToWithdraw, to); - - LINK.transfer(to, amountToWithdraw); - } - - /** - * @notice withdraws LINK funds collected through cancellation fees - */ - function withdrawOwnerFunds() external onlyOwner { - uint96 amount = s_ownerLinkBalance; - - s_expectedLinkBalance = s_expectedLinkBalance - amount; - s_ownerLinkBalance = 0; - - emit OwnerFundsWithdrawn(amount); - LINK.transfer(msg.sender, amount); - } - - /** - * @notice allows the admin of an upkeep to modify gas limit - * @param id upkeep to be change the gas limit for - * @param gasLimit new gas limit for the upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override onlyActiveUpkeep(id) onlyUpkeepAdmin(id) { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - - s_upkeep[id].executeGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @notice recovers LINK funds improperly transferred to the registry - * @dev In principle this function’s execution cost could exceed block - * gas limit. However, in our anticipated deployment, the number of upkeeps and - * keepers will be low enough to avoid this problem. - */ - function recoverFunds() external onlyOwner { - uint256 total = LINK.balanceOf(address(this)); - LINK.transfer(msg.sender, total - s_expectedLinkBalance); - } - - /** - * @notice withdraws a keeper's payment, callable only by the keeper's payee - * @param from keeper address - * @param to address to send the payment to - */ - function withdrawPayment(address from, address to) external validRecipient(to) { - KeeperInfo memory keeper = s_keeperInfo[from]; - if (keeper.payee != msg.sender) revert OnlyCallableByPayee(); - - s_keeperInfo[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance - keeper.balance; - emit PaymentWithdrawn(from, keeper.balance, to, msg.sender); - - LINK.transfer(to, keeper.balance); - } - - /** - * @notice proposes the safe transfer of a keeper's payee to another address - * @param keeper address of the keeper to transfer payee role - * @param proposed address to nominate for next payeeship - */ - function transferPayeeship(address keeper, address proposed) external { - if (s_keeperInfo[keeper].payee != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[keeper] != proposed) { - s_proposedPayee[keeper] = proposed; - emit PayeeshipTransferRequested(keeper, msg.sender, proposed); - } - } - - /** - * @notice accepts the safe transfer of payee role for a keeper - * @param keeper address to accept the payee role for - */ - function acceptPayeeship(address keeper) external { - if (s_proposedPayee[keeper] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_keeperInfo[keeper].payee; - s_keeperInfo[keeper].payee = msg.sender; - s_proposedPayee[keeper] = ZERO_ADDRESS; - - emit PayeeshipTransferred(keeper, past, msg.sender); - } - - /** - * @notice signals to keepers that they should not perform upkeeps until the - * contract has been unpaused - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice signals to keepers that they can perform upkeeps once again after - * having been paused - */ - function unpause() external onlyOwner { - _unpause(); - } - - // SETTERS - - /** - * @notice updates the configuration of the registry - * @param config registry config fields - */ - function setConfig(Config memory config) public onlyOwner { - if (config.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); - s_storage = Storage({ - paymentPremiumPPB: config.paymentPremiumPPB, - flatFeeMicroLink: config.flatFeeMicroLink, - blockCountPerTurn: config.blockCountPerTurn, - checkGasLimit: config.checkGasLimit, - stalenessSeconds: config.stalenessSeconds, - gasCeilingMultiplier: config.gasCeilingMultiplier, - minUpkeepSpend: config.minUpkeepSpend, - maxPerformGas: config.maxPerformGas, - nonce: s_storage.nonce - }); - s_fallbackGasPrice = config.fallbackGasPrice; - s_fallbackLinkPrice = config.fallbackLinkPrice; - s_transcoder = config.transcoder; - s_registrar = config.registrar; - emit ConfigSet(config); - } - - /** - * @notice update the list of keepers allowed to perform upkeep - * @param keepers list of addresses allowed to perform upkeep - * @param payees addresses corresponding to keepers who are allowed to - * move payments which have been accrued - */ - function setKeepers(address[] calldata keepers, address[] calldata payees) external onlyOwner { - if (keepers.length != payees.length || keepers.length < 2) revert ParameterLengthError(); - for (uint256 i = 0; i < s_keeperList.length; i++) { - address keeper = s_keeperList[i]; - s_keeperInfo[keeper].active = false; - } - for (uint256 i = 0; i < keepers.length; i++) { - address keeper = keepers[i]; - KeeperInfo storage s_keeper = s_keeperInfo[keeper]; - address oldPayee = s_keeper.payee; - address newPayee = payees[i]; - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) revert InvalidPayee(); - if (s_keeper.active) revert DuplicateEntry(); - s_keeper.active = true; - if (newPayee != IGNORE_ADDRESS) { - s_keeper.payee = newPayee; - } - } - s_keeperList = keepers; - emit KeepersUpdated(keepers, payees); - } - - // GETTERS - - /** - * @notice read all of the details about an upkeep - */ - function getUpkeep( - uint256 id - ) - external - view - override - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber, - uint96 amountSpent - ) - { - Upkeep memory reg = s_upkeep[id]; - return ( - reg.target, - reg.executeGas, - s_checkData[id], - reg.balance, - reg.lastKeeper, - reg.admin, - reg.maxValidBlocknumber, - reg.amountSpent - ); - } - - /** - * @notice retrieve active upkeep IDs - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a wholistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { - uint256 maxIdx = s_upkeepIDs.length(); - if (startIndex >= maxIdx) revert IndexOutOfRange(); - if (maxCount == 0) { - maxCount = maxIdx - startIndex; - } - uint256[] memory ids = new uint256[](maxCount); - for (uint256 idx = 0; idx < maxCount; idx++) { - ids[idx] = s_upkeepIDs.at(startIndex + idx); - } - return ids; - } - - /** - * @notice read the current info about any keeper address - */ - function getKeeperInfo(address query) external view override returns (address payee, bool active, uint96 balance) { - KeeperInfo memory keeper = s_keeperInfo[query]; - return (keeper.payee, keeper.active, keeper.balance); - } - - /** - * @notice read the current state of the registry - */ - function getState() - external - view - override - returns (State memory state, Config memory config, address[] memory keepers) - { - Storage memory store = s_storage; - state.nonce = store.nonce; - state.ownerLinkBalance = s_ownerLinkBalance; - state.expectedLinkBalance = s_expectedLinkBalance; - state.numUpkeeps = s_upkeepIDs.length(); - config.paymentPremiumPPB = store.paymentPremiumPPB; - config.flatFeeMicroLink = store.flatFeeMicroLink; - config.blockCountPerTurn = store.blockCountPerTurn; - config.checkGasLimit = store.checkGasLimit; - config.stalenessSeconds = store.stalenessSeconds; - config.gasCeilingMultiplier = store.gasCeilingMultiplier; - config.minUpkeepSpend = store.minUpkeepSpend; - config.maxPerformGas = store.maxPerformGas; - config.fallbackGasPrice = s_fallbackGasPrice; - config.fallbackLinkPrice = s_fallbackLinkPrice; - config.transcoder = s_transcoder; - config.registrar = s_registrar; - return (state, config, s_keeperList); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { - return getMaxPaymentForGas(s_upkeep[id].executeGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas(uint256 gasLimit) public view returns (uint96 maxPayment) { - (uint256 gasWei, uint256 linkEth) = _getFeedData(); - uint256 adjustedGasWei = _adjustGasPrice(gasWei, false); - return _calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice sets the peer registry migration permission - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external override { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - uint256 id; - Upkeep memory upkeep; - uint256 totalBalanceRemaining; - bytes[] memory checkDatas = new bytes[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); - upkeeps[idx] = upkeep; - checkDatas[idx] = s_checkData[id]; - totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; - delete s_upkeep[id]; - delete s_checkData[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; - bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas); - MigratableKeeperRegistryInterface(destination).receiveUpkeeps( - UpkeepTranscoderInterface(s_transcoder).transcodeUpkeeps( - UpkeepFormat.V1, - MigratableKeeperRegistryInterface(destination).upkeepTranscoderVersion(), - encodedUpkeeps - ) - ); - LINK.transfer(destination, totalBalanceRemaining); - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - UpkeepFormat public constant override upkeepTranscoderVersion = UpkeepFormat.V1; - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external override { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], Upkeep[], bytes[]) - ); - for (uint256 idx = 0; idx < ids.length; idx++) { - _createUpkeep( - ids[idx], - upkeeps[idx].target, - upkeeps[idx].executeGas, - upkeeps[idx].admin, - upkeeps[idx].balance, - checkDatas[idx] - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } - - /** - * @notice creates a new upkeep with the given fields - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - */ - function _createUpkeep( - uint256 id, - address target, - uint32 gasLimit, - address admin, - uint96 balance, - bytes memory checkData - ) internal whenNotPaused { - if (!target.isContract()) revert NotAContract(); - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - s_upkeep[id] = Upkeep({ - target: target, - executeGas: gasLimit, - balance: balance, - admin: admin, - maxValidBlocknumber: UINT64_MAX, - lastKeeper: ZERO_ADDRESS, - amountSpent: 0 - }); - s_expectedLinkBalance = s_expectedLinkBalance + balance; - s_checkData[id] = checkData; - s_upkeepIDs.add(id); - } - - /** - * @dev retrieves feed data for fast gas/eth and link/eth prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData() private view returns (uint256 gasWei, uint256 linkEth) { - uint32 stalenessSeconds = s_storage.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = FAST_GAS_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - linkEth = s_fallbackLinkPrice; - } else { - linkEth = uint256(feedValue); - } - return (gasWei, linkEth); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - */ - function _calculatePaymentAmount( - uint256 gasLimit, - uint256 gasWei, - uint256 linkEth - ) private view returns (uint96 payment) { - uint256 weiForGas = gasWei * (gasLimit + REGISTRY_GAS_OVERHEAD); - uint256 premium = PPB_BASE + s_storage.paymentPremiumPPB; - uint256 total = ((weiForGas * (1e9) * (premium)) / (linkEth)) + (uint256(s_storage.flatFeeMicroLink) * (1e12)); - if (total > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); - return uint96(total); // LINK_TOTAL_SUPPLY < UINT96_MAX - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= PERFORM_GAS_CUSHION and check for underflow - if lt(g, PERFORM_GAS_CUSHION) { - revert(0, 0) - } - g := sub(g, PERFORM_GAS_CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * keeper and the exact gas required by the Upkeep - */ - function _performUpkeepWithParams( - PerformParams memory params - ) private nonReentrant validUpkeep(params.id) returns (bool success) { - Upkeep memory upkeep = s_upkeep[params.id]; - _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - uint256 gasUsed = gasleft(); - bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, params.performData); - success = _callWithExactGas(params.gasLimit, upkeep.target, callData); - gasUsed = gasUsed - gasleft(); - - uint96 payment = _calculatePaymentAmount(gasUsed, params.adjustedGasWei, params.linkEth); - - s_upkeep[params.id].balance = s_upkeep[params.id].balance - payment; - s_upkeep[params.id].amountSpent = s_upkeep[params.id].amountSpent + payment; - s_upkeep[params.id].lastKeeper = params.from; - s_keeperInfo[params.from].balance = s_keeperInfo[params.from].balance + payment; - - emit UpkeepPerformed(params.id, success, params.from, payment, params.performData); - return success; - } - - /** - * @dev ensures all required checks are passed before an upkeep is performed - */ - function _prePerformUpkeep(Upkeep memory upkeep, address from, uint256 maxLinkPayment) private view { - if (!s_keeperInfo[from].active) revert OnlyActiveKeepers(); - if (upkeep.balance < maxLinkPayment) revert InsufficientFunds(); - if (upkeep.lastKeeper == from) revert KeepersMustTakeTurns(); - } - - /** - * @dev adjusts the gas price to min(ceiling, tx.gasprice) or just uses the ceiling if tx.gasprice is disabled - */ - function _adjustGasPrice(uint256 gasWei, bool useTxGasPrice) private view returns (uint256 adjustedPrice) { - adjustedPrice = gasWei * s_storage.gasCeilingMultiplier; - if (useTxGasPrice && tx.gasprice < adjustedPrice) { - adjustedPrice = tx.gasprice; - } - } - - /** - * @dev generates a PerformParams struct for use in _performUpkeepWithParams() - */ - function _generatePerformParams( - address from, - uint256 id, - bytes memory performData, - bool useTxGasPrice - ) private view returns (PerformParams memory) { - uint256 gasLimit = s_upkeep[id].executeGas; - (uint256 gasWei, uint256 linkEth) = _getFeedData(); - uint256 adjustedGasWei = _adjustGasPrice(gasWei, useTxGasPrice); - uint96 maxLinkPayment = _calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); - - return - PerformParams({ - from: from, - id: id, - performData: performData, - maxLinkPayment: maxLinkPayment, - gasLimit: gasLimit, - adjustedGasWei: adjustedGasWei, - linkEth: linkEth - }); - } - - // MODIFIERS - - /** - * @dev ensures a upkeep is valid - */ - modifier validUpkeep(uint256 id) { - if (s_upkeep[id].maxValidBlocknumber <= block.number) revert UpkeepNotActive(); - _; - } - - /** - * @dev Reverts if called by anyone other than the admin of upkeep #id - */ - modifier onlyUpkeepAdmin(uint256 id) { - if (msg.sender != s_upkeep[id].admin) revert OnlyCallableByAdmin(); - _; - } - - /** - * @dev Reverts if called on a cancelled upkeep - */ - modifier onlyActiveUpkeep(uint256 id) { - if (s_upkeep[id].maxValidBlocknumber != UINT64_MAX) revert UpkeepNotActive(); - _; - } - - /** - * @dev ensures that burns don't accidentally happen by sending to the zero - * address - */ - modifier validRecipient(address to) { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - _; - } - - /** - * @dev Reverts if called by anyone other than the contract owner or registrar. - */ - modifier onlyOwnerOrRegistrar() { - if (msg.sender != owner() && msg.sender != s_registrar) revert OnlyCallableByOwnerOrRegistrar(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol deleted file mode 100644 index 253a421..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import {AutomationRegistryExecutableInterface} from "../interfaces/v1_2/AutomationRegistryInterface1_2.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -/** - * @notice This contract serves as a wrapper around a keeper registry's checkUpkeep function. - */ -contract KeeperRegistryCheckUpkeepGasUsageWrapper1_2 is ConfirmedOwner { - AutomationRegistryExecutableInterface private immutable i_keeperRegistry; - - /** - * @param keeperRegistry address of a keeper registry - */ - constructor(AutomationRegistryExecutableInterface keeperRegistry) ConfirmedOwner(msg.sender) { - i_keeperRegistry = keeperRegistry; - } - - /** - * @return the keeper registry - */ - function getKeeperRegistry() external view returns (AutomationRegistryExecutableInterface) { - return i_keeperRegistry; - } - - /** - * @notice This function is called by monitoring service to estimate how much gas checkUpkeep functions will consume. - * @param id identifier of the upkeep to check - * @param from the address to simulate performing the upkeep from - */ - function measureCheckGas(uint256 id, address from) external returns (bool, bytes memory, uint256) { - uint256 startGas = gasleft(); - try i_keeperRegistry.checkUpkeep(id, from) returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) { - uint256 gasUsed = startGas - gasleft(); - return (true, performData, gasUsed); - } catch { - uint256 gasUsed = startGas - gasleft(); - return (false, "", gasUsed); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol deleted file mode 100644 index dbef8d7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistry1_3.sol +++ /dev/null @@ -1,548 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "@openzeppelin/contracts/proxy/Proxy.sol"; -import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; -import "./KeeperRegistryBase1_3.sol"; -import "./KeeperRegistryLogic1_3.sol"; -import {AutomationRegistryExecutableInterface, State} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol"; -import "../interfaces/MigratableKeeperRegistryInterface.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; -import "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Registry for adding work for Chainlink Keepers to perform on client - * contracts. Clients must support the Upkeep interface. - */ -contract KeeperRegistry1_3 is - KeeperRegistryBase1_3, - Proxy, - TypeAndVersionInterface, - AutomationRegistryExecutableInterface, - MigratableKeeperRegistryInterface, - IERC677Receiver -{ - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - - address public immutable KEEPER_REGISTRY_LOGIC; - - /** - * @notice versions: - * - KeeperRegistry 1.3.0: split contract into Proxy and Logic - * : account for Arbitrum and Optimism L1 gas fee - * : allow users to configure upkeeps - * - KeeperRegistry 1.2.0: allow funding within performUpkeep - * : allow configurable registry maxPerformGas - * : add function to let admin change upkeep gas limit - * : add minUpkeepSpend requirement - : upgrade to solidity v0.8 - * - KeeperRegistry 1.1.0: added flatFeeMicroLink - * - KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistry 1.3.0"; - - /** - * @param keeperRegistryLogic the address of keeper registry logic - * @param config registry config settings - */ - constructor( - KeeperRegistryLogic1_3 keeperRegistryLogic, - Config memory config - ) - KeeperRegistryBase1_3( - keeperRegistryLogic.PAYMENT_MODEL(), - keeperRegistryLogic.REGISTRY_GAS_OVERHEAD(), - address(keeperRegistryLogic.LINK()), - address(keeperRegistryLogic.LINK_ETH_FEED()), - address(keeperRegistryLogic.FAST_GAS_FEED()) - ) - { - KEEPER_REGISTRY_LOGIC = address(keeperRegistryLogic); - setConfig(config); - } - - // ACTIONS - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external override returns (uint256 id) { - // Executed through logic contract - _fallback(); - } - - /** - * @notice simulated by keepers via eth_call to see if the upkeep needs to be - * performed. If upkeep is needed, the call then simulates performUpkeep - * to make sure it succeeds. Finally, it returns the success status along with - * payment information and the perform data payload. - * @param id identifier of the upkeep to check - * @param from the address to simulate performing the upkeep from - */ - function checkUpkeep( - uint256 id, - address from - ) - external - override - cannotExecute - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) - { - // Executed through logic contract - _fallback(); - } - - /** - * @notice executes the upkeep with the perform data returned from - * checkUpkeep, validates the keeper's permissions, and pays the keeper. - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - */ - function performUpkeep( - uint256 id, - bytes calldata performData - ) external override whenNotPaused returns (bool success) { - return _performUpkeepWithParams(_generatePerformParams(msg.sender, id, performData, true)); - } - - /** - * @notice prevent an upkeep from being performed in the future - * @param id upkeep to be canceled - */ - function cancelUpkeep(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice pause an upkeep - * @param id upkeep to be paused - */ - function pauseUpkeep(uint256 id) external override { - Upkeep memory upkeep = s_upkeep[id]; - requireAdminAndNotCancelled(upkeep); - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @notice unpause an upkeep - * @param id upkeep to be resumed - */ - function unpauseUpkeep(uint256 id) external override { - Upkeep memory upkeep = s_upkeep[id]; - requireAdminAndNotCancelled(upkeep); - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @notice update the check data of an upkeep - * @param id the id of the upkeep whose check data needs to be updated - * @param newCheckData the new check data - */ - function updateCheckData(uint256 id, bytes calldata newCheckData) external override { - Upkeep memory upkeep = s_upkeep[id]; - requireAdminAndNotCancelled(upkeep); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataUpdated(id, newCheckData); - } - - /** - * @notice adds LINK funding for an upkeep by transferring from the sender's - * LINK balance - * @param id upkeep to fund - * @param amount number of LINK to transfer - */ - function addFunds(uint256 id, uint96 amount) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(LINK)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_expectedLinkBalance = s_expectedLinkBalance + amount; - - emit FundsAdded(id, sender, uint96(amount)); - } - - /** - * @notice removes funding from a canceled upkeep - * @param id upkeep to withdraw funds from - * @param to destination address for sending remaining funds - */ - function withdrawFunds(uint256 id, address to) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice withdraws LINK funds collected through cancellation fees - */ - function withdrawOwnerFunds() external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice allows the admin of an upkeep to modify gas limit - * @param id upkeep to be change the gas limit for - * @param gasLimit new gas limit for the upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice recovers LINK funds improperly transferred to the registry - * @dev In principle this function’s execution cost could exceed block - * gas limit. However, in our anticipated deployment, the number of upkeeps and - * keepers will be low enough to avoid this problem. - */ - function recoverFunds() external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice withdraws a keeper's payment, callable only by the keeper's payee - * @param from keeper address - * @param to address to send the payment to - */ - function withdrawPayment(address from, address to) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice proposes the safe transfer of a keeper's payee to another address - * @param keeper address of the keeper to transfer payee role - * @param proposed address to nominate for next payeeship - */ - function transferPayeeship(address keeper, address proposed) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice accepts the safe transfer of payee role for a keeper - * @param keeper address to accept the payee role for - */ - function acceptPayeeship(address keeper) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice proposes the safe transfer of an upkeep's admin role to another address - * @param id the upkeep id to transfer admin - * @param proposed address to nominate for the new upkeep admin - */ - function transferUpkeepAdmin(uint256 id, address proposed) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice accepts the safe transfer of admin role for an upkeep - * @param id the upkeep id - */ - function acceptUpkeepAdmin(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice signals to keepers that they should not perform upkeeps until the - * contract has been unpaused - */ - function pause() external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice signals to keepers that they can perform upkeeps once again after - * having been paused - */ - function unpause() external { - // Executed through logic contract - _fallback(); - } - - // SETTERS - - /** - * @notice updates the configuration of the registry - * @param config registry config fields - */ - function setConfig(Config memory config) public onlyOwner { - if (config.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); - s_storage = Storage({ - paymentPremiumPPB: config.paymentPremiumPPB, - flatFeeMicroLink: config.flatFeeMicroLink, - blockCountPerTurn: config.blockCountPerTurn, - checkGasLimit: config.checkGasLimit, - stalenessSeconds: config.stalenessSeconds, - gasCeilingMultiplier: config.gasCeilingMultiplier, - minUpkeepSpend: config.minUpkeepSpend, - maxPerformGas: config.maxPerformGas, - nonce: s_storage.nonce - }); - s_fallbackGasPrice = config.fallbackGasPrice; - s_fallbackLinkPrice = config.fallbackLinkPrice; - s_transcoder = config.transcoder; - s_registrar = config.registrar; - emit ConfigSet(config); - } - - /** - * @notice update the list of keepers allowed to perform upkeep - * @param keepers list of addresses allowed to perform upkeep - * @param payees addresses corresponding to keepers who are allowed to - * move payments which have been accrued - */ - function setKeepers(address[] calldata keepers, address[] calldata payees) external { - // Executed through logic contract - _fallback(); - } - - // GETTERS - - /** - * @notice read all of the details about an upkeep - */ - function getUpkeep( - uint256 id - ) - external - view - override - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber, - uint96 amountSpent, - bool paused - ) - { - Upkeep memory reg = s_upkeep[id]; - return ( - reg.target, - reg.executeGas, - s_checkData[id], - reg.balance, - reg.lastKeeper, - reg.admin, - reg.maxValidBlocknumber, - reg.amountSpent, - reg.paused - ); - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { - uint256 maxIdx = s_upkeepIDs.length(); - if (startIndex >= maxIdx) revert IndexOutOfRange(); - if (maxCount == 0) { - maxCount = maxIdx - startIndex; - } - uint256[] memory ids = new uint256[](maxCount); - for (uint256 idx = 0; idx < maxCount; idx++) { - ids[idx] = s_upkeepIDs.at(startIndex + idx); - } - return ids; - } - - /** - * @notice read the current info about any keeper address - */ - function getKeeperInfo(address query) external view override returns (address payee, bool active, uint96 balance) { - KeeperInfo memory keeper = s_keeperInfo[query]; - return (keeper.payee, keeper.active, keeper.balance); - } - - /** - * @notice read the current state of the registry - */ - function getState() - external - view - override - returns (State memory state, Config memory config, address[] memory keepers) - { - Storage memory store = s_storage; - state.nonce = store.nonce; - state.ownerLinkBalance = s_ownerLinkBalance; - state.expectedLinkBalance = s_expectedLinkBalance; - state.numUpkeeps = s_upkeepIDs.length(); - config.paymentPremiumPPB = store.paymentPremiumPPB; - config.flatFeeMicroLink = store.flatFeeMicroLink; - config.blockCountPerTurn = store.blockCountPerTurn; - config.checkGasLimit = store.checkGasLimit; - config.stalenessSeconds = store.stalenessSeconds; - config.gasCeilingMultiplier = store.gasCeilingMultiplier; - config.minUpkeepSpend = store.minUpkeepSpend; - config.maxPerformGas = store.maxPerformGas; - config.fallbackGasPrice = s_fallbackGasPrice; - config.fallbackLinkPrice = s_fallbackLinkPrice; - config.transcoder = s_transcoder; - config.registrar = s_registrar; - return (state, config, s_keeperList); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { - return getMaxPaymentForGas(s_upkeep[id].executeGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas(uint256 gasLimit) public view returns (uint96 maxPayment) { - (uint256 fastGasWei, uint256 linkEth) = _getFeedData(); - return _calculatePaymentAmount(gasLimit, fastGasWei, linkEth, false); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice sets the peer registry migration permission - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external { - // Executed through logic contract - _fallback(); - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - UpkeepFormat public constant override upkeepTranscoderVersion = UPKEEP_TRANSCODER_VERSION_BASE; - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @dev This is the address to which proxy functions are delegated to - */ - function _implementation() internal view override returns (address) { - return KEEPER_REGISTRY_LOGIC; - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= PERFORM_GAS_CUSHION and check for underflow - if lt(g, PERFORM_GAS_CUSHION) { - revert(0, 0) - } - g := sub(g, PERFORM_GAS_CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * keeper and the exact gas required by the Upkeep - */ - function _performUpkeepWithParams(PerformParams memory params) private nonReentrant returns (bool success) { - Upkeep memory upkeep = s_upkeep[params.id]; - if (upkeep.maxValidBlocknumber <= block.number) revert UpkeepCancelled(); - _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - uint256 gasUsed = gasleft(); - bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, params.performData); - success = _callWithExactGas(params.gasLimit, upkeep.target, callData); - gasUsed = gasUsed - gasleft(); - uint96 payment = _calculatePaymentAmount(gasUsed, params.fastGasWei, params.linkEth, true); - - s_upkeep[params.id].balance = s_upkeep[params.id].balance - payment; - s_upkeep[params.id].amountSpent = s_upkeep[params.id].amountSpent + payment; - s_upkeep[params.id].lastKeeper = params.from; - s_keeperInfo[params.from].balance = s_keeperInfo[params.from].balance + payment; - - emit UpkeepPerformed(params.id, success, params.from, payment, params.performData); - return success; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol deleted file mode 100644 index c21f3a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryBase1_3.sol +++ /dev/null @@ -1,304 +0,0 @@ -pragma solidity 0.8.6; - -import "@openzeppelin/contracts/security/Pausable.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; -import "../ExecutionPrevention.sol"; -import {Config, Upkeep} from "../interfaces/v1_3/AutomationRegistryInterface1_3.sol"; -import "../../shared/access/ConfirmedOwner.sol"; -import "../../shared/interfaces/AggregatorV3Interface.sol"; -import "../../shared/interfaces/LinkTokenInterface.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; -import "../interfaces/UpkeepTranscoderInterface.sol"; - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * KeeperRegistry and KeeperRegistryLogic - */ -abstract contract KeeperRegistryBase1_3 is ConfirmedOwner, ExecutionPrevention, ReentrancyGuard, Pausable { - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; - uint32 internal constant UINT32_MAX = type(uint32).max; - uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; - UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V2; - // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism - bytes internal constant L1_FEE_DATA_PADDING = - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - // MAX_INPUT_DATA represents the estimated max size of the sum of L1 data padding and msg.data in performUpkeep - // function, which includes 4 bytes for function selector, 32 bytes for upkeep id, 35 bytes for data padding, and - // 64 bytes for estimated perform data - bytes internal constant MAX_INPUT_DATA = - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - - address[] internal s_keeperList; - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; - mapping(address => KeeperInfo) internal s_keeperInfo; - mapping(address => address) internal s_proposedPayee; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; - Storage internal s_storage; - uint256 internal s_fallbackGasPrice; // not in config object for gas savings - uint256 internal s_fallbackLinkPrice; // not in config object for gas savings - uint96 internal s_ownerLinkBalance; - uint256 internal s_expectedLinkBalance; - address internal s_transcoder; - address internal s_registrar; - - LinkTokenInterface public immutable LINK; - AggregatorV3Interface public immutable LINK_ETH_FEED; - AggregatorV3Interface public immutable FAST_GAS_FEED; - OVM_GasPriceOracle public immutable OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); - ArbGasInfo public immutable ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); - PaymentModel public immutable PAYMENT_MODEL; - uint256 public immutable REGISTRY_GAS_OVERHEAD; - - error ArrayHasNoEntries(); - error CannotCancel(); - error DuplicateEntry(); - error EmptyAddress(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IndexOutOfRange(); - error InsufficientFunds(); - error InvalidDataLength(); - error InvalidPayee(); - error InvalidRecipient(); - error KeepersMustTakeTurns(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveKeepers(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyPausedUpkeep(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error TargetCheckReverted(bytes reason); - error TranscoderNotSet(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum PaymentModel { - DEFAULT, - ARBITRUM, - OPTIMISM - } - - /** - * @notice storage of the registry, contains a mix of config and state data - */ - struct Storage { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; // 1 full evm word - uint32 maxPerformGas; - uint32 nonce; - } - - struct KeeperInfo { - address payee; - uint96 balance; - bool active; - } - - struct PerformParams { - address from; - uint256 id; - bytes performData; - uint256 maxLinkPayment; - uint256 gasLimit; - uint256 fastGasWei; - uint256 linkEth; - } - - event ConfigSet(Config config); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event KeepersUpdated(address[] keepers, address[] payees); - event OwnerFundsWithdrawn(uint96 amount); - event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataUpdated(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - address indexed from, - uint96 payment, - bytes performData - ); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepUnpaused(uint256 indexed id); - event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); - - /** - * @param paymentModel the payment model of default, Arbitrum, or Optimism - * @param registryGasOverhead the gas overhead used by registry in performUpkeep - * @param link address of the LINK Token - * @param linkEthFeed address of the LINK/ETH price feed - * @param fastGasFeed address of the Fast Gas price feed - */ - constructor( - PaymentModel paymentModel, - uint256 registryGasOverhead, - address link, - address linkEthFeed, - address fastGasFeed - ) ConfirmedOwner(msg.sender) { - PAYMENT_MODEL = paymentModel; - REGISTRY_GAS_OVERHEAD = registryGasOverhead; - if (ZERO_ADDRESS == link || ZERO_ADDRESS == linkEthFeed || ZERO_ADDRESS == fastGasFeed) { - revert EmptyAddress(); - } - LINK = LinkTokenInterface(link); - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - FAST_GAS_FEED = AggregatorV3Interface(fastGasFeed); - } - - /** - * @dev retrieves feed data for fast gas/eth and link/eth prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData() internal view returns (uint256 gasWei, uint256 linkEth) { - uint32 stalenessSeconds = s_storage.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = FAST_GAS_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - linkEth = s_fallbackLinkPrice; - } else { - linkEth = uint256(feedValue); - } - return (gasWei, linkEth); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @param gasLimit the amount of gas used - * @param fastGasWei the fast gas price - * @param linkEth the exchange ratio between LINK and ETH - * @param isExecution if this is triggered by a perform upkeep function - */ - function _calculatePaymentAmount( - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkEth, - bool isExecution - ) internal view returns (uint96 payment) { - Storage memory store = s_storage; - uint256 gasWei = fastGasWei * store.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (isExecution && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - - uint256 weiForGas = gasWei * (gasLimit + REGISTRY_GAS_OVERHEAD); - uint256 premium = PPB_BASE + store.paymentPremiumPPB; - uint256 l1CostWei = 0; - if (PAYMENT_MODEL == PaymentModel.OPTIMISM) { - bytes memory txCallData = new bytes(0); - if (isExecution) { - txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); - } else { - txCallData = MAX_INPUT_DATA; - } - l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); - } else if (PAYMENT_MODEL == PaymentModel.ARBITRUM) { - l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); - } - // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound - if (!isExecution) { - l1CostWei = store.gasCeilingMultiplier * l1CostWei; - } - - uint256 total = ((weiForGas + l1CostWei) * 1e9 * premium) / linkEth + uint256(store.flatFeeMicroLink) * 1e12; - if (total > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); - return uint96(total); // LINK_TOTAL_SUPPLY < UINT96_MAX - } - - /** - * @dev ensures all required checks are passed before an upkeep is performed - */ - function _prePerformUpkeep(Upkeep memory upkeep, address from, uint256 maxLinkPayment) internal view { - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - if (!s_keeperInfo[from].active) revert OnlyActiveKeepers(); - if (upkeep.balance < maxLinkPayment) revert InsufficientFunds(); - if (upkeep.lastKeeper == from) revert KeepersMustTakeTurns(); - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function requireAdminAndNotCancelled(Upkeep memory upkeep) internal view { - if (msg.sender != upkeep.admin) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } - - /** - * @dev generates a PerformParams struct for use in _performUpkeepWithParams() - */ - function _generatePerformParams( - address from, - uint256 id, - bytes memory performData, - bool isExecution - ) internal view returns (PerformParams memory) { - uint256 gasLimit = s_upkeep[id].executeGas; - (uint256 fastGasWei, uint256 linkEth) = _getFeedData(); - uint96 maxLinkPayment = _calculatePaymentAmount(gasLimit, fastGasWei, linkEth, isExecution); - - return - PerformParams({ - from: from, - id: id, - performData: performData, - maxLinkPayment: maxLinkPayment, - gasLimit: gasLimit, - fastGasWei: fastGasWei, - linkEth: linkEth - }); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol deleted file mode 100644 index fd7c3af..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v1_3/KeeperRegistryLogic1_3.sol +++ /dev/null @@ -1,404 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; -import "./KeeperRegistryBase1_3.sol"; -import "../interfaces/MigratableKeeperRegistryInterface.sol"; -import "../interfaces/UpkeepTranscoderInterface.sol"; - -/** - * @notice Logic contract, works in tandem with KeeperRegistry as a proxy - */ -contract KeeperRegistryLogic1_3 is KeeperRegistryBase1_3 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - - /** - * @param paymentModel one of Default, Arbitrum, Optimism - * @param registryGasOverhead the gas overhead used by registry in performUpkeep - * @param link address of the LINK Token - * @param linkEthFeed address of the LINK/ETH price feed - * @param fastGasFeed address of the Fast Gas price feed - */ - constructor( - PaymentModel paymentModel, - uint256 registryGasOverhead, - address link, - address linkEthFeed, - address fastGasFeed - ) KeeperRegistryBase1_3(paymentModel, registryGasOverhead, link, linkEthFeed, fastGasFeed) {} - - function checkUpkeep( - uint256 id, - address from - ) - external - cannotExecute - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) - { - Upkeep memory upkeep = s_upkeep[id]; - - bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); - (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); - - if (!success) revert TargetCheckReverted(result); - - (success, performData) = abi.decode(result, (bool, bytes)); - if (!success) revert UpkeepNotNeeded(); - - PerformParams memory params = _generatePerformParams(from, id, performData, false); - _prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - return ( - performData, - params.maxLinkPayment, - params.gasLimit, - // adjustedGasWei equals fastGasWei multiplies gasCeilingMultiplier in non-execution cases - params.fastGasWei * s_storage.gasCeilingMultiplier, - params.linkEth - ); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawOwnerFunds() external onlyOwner { - uint96 amount = s_ownerLinkBalance; - - s_expectedLinkBalance = s_expectedLinkBalance - amount; - s_ownerLinkBalance = 0; - - emit OwnerFundsWithdrawn(amount); - LINK.transfer(msg.sender, amount); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function recoverFunds() external onlyOwner { - uint256 total = LINK.balanceOf(address(this)); - LINK.transfer(msg.sender, total - s_expectedLinkBalance); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setKeepers(address[] calldata keepers, address[] calldata payees) external onlyOwner { - if (keepers.length != payees.length || keepers.length < 2) revert ParameterLengthError(); - for (uint256 i = 0; i < s_keeperList.length; i++) { - address keeper = s_keeperList[i]; - s_keeperInfo[keeper].active = false; - } - for (uint256 i = 0; i < keepers.length; i++) { - address keeper = keepers[i]; - KeeperInfo storage s_keeper = s_keeperInfo[keeper]; - address oldPayee = s_keeper.payee; - address newPayee = payees[i]; - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) revert InvalidPayee(); - if (s_keeper.active) revert DuplicateEntry(); - s_keeper.active = true; - if (newPayee != IGNORE_ADDRESS) { - s_keeper.payee = newPayee; - } - } - s_keeperList = keepers; - emit KeepersUpdated(keepers, payees); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function unpause() external onlyOwner { - _unpause(); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external returns (uint256 id) { - if (msg.sender != owner() && msg.sender != s_registrar) revert OnlyCallableByOwnerOrRegistrar(); - - id = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), address(this), s_storage.nonce))); - _createUpkeep(id, target, gasLimit, admin, 0, checkData, false); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - return id; - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; - bool isOwner = msg.sender == owner(); - - if (canceled && !(isOwner && upkeep.maxValidBlocknumber > block.number)) revert CannotCancel(); - if (!isOwner && msg.sender != upkeep.admin) revert OnlyCallableByOwnerOrAdmin(); - - uint256 height = block.number; - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minUpkeepSpend is not met - uint96 minUpkeepSpend = s_storage.minUpkeepSpend; - uint96 cancellationFee = 0; - // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) - if (upkeep.amountSpent < minUpkeepSpend) { - cancellationFee = minUpkeepSpend - upkeep.amountSpent; - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_ownerLinkBalance = s_ownerLinkBalance + cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function addFunds(uint256 id, uint96 amount) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].balance = upkeep.balance + amount; - s_expectedLinkBalance = s_expectedLinkBalance + amount; - LINK.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawFunds(uint256 id, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > block.number) revert UpkeepNotCanceled(); - - uint96 amountToWithdraw = s_upkeep[id].balance; - s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; - s_upkeep[id].balance = 0; - emit FundsWithdrawn(id, amountToWithdraw, to); - - LINK.transfer(to, amountToWithdraw); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (upkeep.admin != msg.sender) revert OnlyCallableByAdmin(); - - s_upkeep[id].executeGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - KeeperInfo memory keeper = s_keeperInfo[from]; - if (keeper.payee != msg.sender) revert OnlyCallableByPayee(); - - s_keeperInfo[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance - keeper.balance; - emit PaymentWithdrawn(from, keeper.balance, to, msg.sender); - - LINK.transfer(to, keeper.balance); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function transferPayeeship(address keeper, address proposed) external { - if (s_keeperInfo[keeper].payee != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[keeper] != proposed) { - s_proposedPayee[keeper] = proposed; - emit PayeeshipTransferRequested(keeper, msg.sender, proposed); - } - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function acceptPayeeship(address keeper) external { - if (s_proposedPayee[keeper] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_keeperInfo[keeper].payee; - s_keeperInfo[keeper].payee = msg.sender; - s_proposedPayee[keeper] = ZERO_ADDRESS; - - emit PayeeshipTransferred(keeper, past, msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - Upkeep memory upkeep = s_upkeep[id]; - requireAdminAndNotCancelled(upkeep); - if (proposed == msg.sender) revert ValueNotChanged(); - if (proposed == ZERO_ADDRESS) revert InvalidRecipient(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = upkeep.admin; - s_upkeep[id].admin = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - uint256 id; - Upkeep memory upkeep; - uint256 totalBalanceRemaining; - bytes[] memory checkDatas = new bytes[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - requireAdminAndNotCancelled(upkeep); - upkeeps[idx] = upkeep; - checkDatas[idx] = s_checkData[id]; - totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; - delete s_upkeep[id]; - delete s_checkData[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; - bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas); - MigratableKeeperRegistryInterface(destination).receiveUpkeeps( - UpkeepTranscoderInterface(s_transcoder).transcodeUpkeeps( - UPKEEP_TRANSCODER_VERSION_BASE, - MigratableKeeperRegistryInterface(destination).upkeepTranscoderVersion(), - encodedUpkeeps - ) - ); - LINK.transfer(destination, totalBalanceRemaining); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], Upkeep[], bytes[]) - ); - for (uint256 idx = 0; idx < ids.length; idx++) { - _createUpkeep( - ids[idx], - upkeeps[idx].target, - upkeeps[idx].executeGas, - upkeeps[idx].admin, - upkeeps[idx].balance, - checkDatas[idx], - upkeeps[idx].paused - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } - - /** - * @notice creates a new upkeep with the given fields - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - * @param paused if this upkeep is paused - */ - function _createUpkeep( - uint256 id, - address target, - uint32 gasLimit, - address admin, - uint96 balance, - bytes memory checkData, - bool paused - ) internal whenNotPaused { - if (!target.isContract()) revert NotAContract(); - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - s_upkeep[id] = Upkeep({ - target: target, - executeGas: gasLimit, - balance: balance, - admin: admin, - maxValidBlocknumber: UINT32_MAX, - lastKeeper: ZERO_ADDRESS, - amountSpent: 0, - paused: paused - }); - s_expectedLinkBalance = s_expectedLinkBalance + balance; - s_checkData[id] = checkData; - s_upkeepIDs.add(id); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol deleted file mode 100644 index c1b7e45..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistrar2_0.sol +++ /dev/null @@ -1,489 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "../../shared/interfaces/LinkTokenInterface.sol"; -import "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; -import "../../shared/access/ConfirmedOwner.sol"; -import "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Contract to accept requests for upkeep registrations - * @dev There are 2 registration workflows in this contract - * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually - * calls `approve` to register upkeep and emit events to inform UI and others interested. - * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on - * keeper registry and then emits approved event to finish the flow automatically without manual intervention. - * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. - * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. - */ -contract KeeperRegistrar2_0 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { - /** - * DISABLED: No auto approvals, all new upkeeps should be approved manually. - * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. - * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. - */ - enum AutoApproveType { - DISABLED, - ENABLED_SENDER_ALLOWLIST, - ENABLED_ALL - } - - bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; - - mapping(bytes32 => PendingRequest) private s_pendingRequests; - - LinkTokenInterface public immutable LINK; - - /** - * @notice versions: - * - KeeperRegistrar 2.0.0: Remove source from register - * Breaks our example of "Register an Upkeep using your own deployed contract" - * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve - * : Remove rate limit and add max allowed for auto approve - * - KeeperRegistrar 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistrar 2.0.0"; - - struct RegistrarConfig { - AutoApproveType autoApproveConfigType; - uint32 autoApproveMaxAllowed; - uint32 approvedCount; - AutomationRegistryBaseInterface keeperRegistry; - uint96 minLINKJuels; - } - - struct PendingRequest { - address admin; - uint96 balance; - } - - struct RegistrationParams { - string name; - bytes encryptedEmail; - address upkeepContract; - uint32 gasLimit; - address adminAddress; - bytes checkData; - bytes offchainConfig; - uint96 amount; - } - - RegistrarConfig private s_config; - // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST - mapping(address => bool) private s_autoApproveAllowedSenders; - - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes checkData, - uint96 amount - ); - - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - - event RegistrationRejected(bytes32 indexed hash); - - event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); - - event ConfigChanged( - AutoApproveType autoApproveConfigType, - uint32 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ); - - error InvalidAdminAddress(); - error RequestNotFound(); - error HashMismatch(); - error OnlyAdminOrOwner(); - error InsufficientPayment(); - error RegistrationRequestFailed(); - error OnlyLink(); - error AmountMismatch(); - error SenderMismatch(); - error FunctionNotPermitted(); - error LinkTransferFailed(address to); - error InvalidDataLength(); - - /* - * @param LINKAddress Address of Link token - * @param autoApproveConfigType setting for auto-approve registrations - * @param autoApproveMaxAllowed max number of registrations that can be auto approved - * @param keeperRegistry keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - */ - constructor( - address LINKAddress, - AutoApproveType autoApproveConfigType, - uint16 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(LINKAddress); - setRegistrationConfig(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); - } - - //EXTERNAL - - /** - * @notice register can only be called through transferAndCall on LINK contract - * @param name string of the upkeep to be registered - * @param encryptedEmail email address of upkeep contact - * @param upkeepContract address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when performing upkeep - * @param adminAddress address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - * @param amount quantity of LINK upkeep is funded with (specified in Juels) - * @param offchainConfig offchainConfig for upkeep in bytes - * @param sender address of the sender making the request - */ - function register( - string memory name, - bytes calldata encryptedEmail, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - bytes calldata offchainConfig, - uint96 amount, - address sender - ) external onlyLINK { - _register( - RegistrationParams({ - name: name, - encryptedEmail: encryptedEmail, - upkeepContract: upkeepContract, - gasLimit: gasLimit, - adminAddress: adminAddress, - checkData: checkData, - offchainConfig: offchainConfig, - amount: amount - }), - sender - ); - } - - /** - * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract - * @param requestParams struct of all possible registration parameters - */ - function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256) { - if (requestParams.amount < s_config.minLINKJuels) { - revert InsufficientPayment(); - } - - LINK.transferFrom(msg.sender, address(this), requestParams.amount); - - return _register(requestParams, msg.sender); - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - bytes calldata offchainConfig, - bytes32 hash - ) external onlyOwner { - PendingRequest memory request = s_pendingRequests[hash]; - if (request.admin == address(0)) { - revert RequestNotFound(); - } - bytes32 expectedHash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData, offchainConfig)); - if (hash != expectedHash) { - revert HashMismatch(); - } - delete s_pendingRequests[hash]; - _approve( - RegistrationParams({ - name: name, - encryptedEmail: "", - upkeepContract: upkeepContract, - gasLimit: gasLimit, - adminAddress: adminAddress, - checkData: checkData, - offchainConfig: offchainConfig, - amount: request.balance - }), - expectedHash - ); - } - - /** - * @notice cancel will remove a registration request and return the refunds to the request.admin - * @param hash the request hash - */ - function cancel(bytes32 hash) external { - PendingRequest memory request = s_pendingRequests[hash]; - if (!(msg.sender == request.admin || msg.sender == owner())) { - revert OnlyAdminOrOwner(); - } - if (request.admin == address(0)) { - revert RequestNotFound(); - } - delete s_pendingRequests[hash]; - bool success = LINK.transfer(request.admin, request.balance); - if (!success) { - revert LinkTransferFailed(request.admin); - } - emit RegistrationRejected(hash); - } - - /** - * @notice owner calls this function to set if registration requests should be sent directly to the Keeper Registry - * @param autoApproveConfigType setting for auto-approve registrations - * note: autoApproveAllowedSenders list persists across config changes irrespective of type - * @param autoApproveMaxAllowed max number of registrations that can be auto approved - * @param keeperRegistry new keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - */ - function setRegistrationConfig( - AutoApproveType autoApproveConfigType, - uint16 autoApproveMaxAllowed, - address keeperRegistry, - uint96 minLINKJuels - ) public onlyOwner { - uint32 approvedCount = s_config.approvedCount; - s_config = RegistrarConfig({ - autoApproveConfigType: autoApproveConfigType, - autoApproveMaxAllowed: autoApproveMaxAllowed, - approvedCount: approvedCount, - minLINKJuels: minLINKJuels, - keeperRegistry: AutomationRegistryBaseInterface(keeperRegistry) - }); - - emit ConfigChanged(autoApproveConfigType, autoApproveMaxAllowed, keeperRegistry, minLINKJuels); - } - - /** - * @notice owner calls this function to set allowlist status for senderAddress - * @param senderAddress senderAddress to set the allowlist status for - * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed - */ - function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { - s_autoApproveAllowedSenders[senderAddress] = allowed; - - emit AutoApproveAllowedSenderSet(senderAddress, allowed); - } - - /** - * @notice read the allowlist status of senderAddress - * @param senderAddress address to read the allowlist status for - */ - function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { - return s_autoApproveAllowedSenders[senderAddress]; - } - - /** - * @notice read the current registration configuration - */ - function getRegistrationConfig() - external - view - returns ( - AutoApproveType autoApproveConfigType, - uint32 autoApproveMaxAllowed, - uint32 approvedCount, - address keeperRegistry, - uint256 minLINKJuels - ) - { - RegistrarConfig memory config = s_config; - return ( - config.autoApproveConfigType, - config.autoApproveMaxAllowed, - config.approvedCount, - address(config.keeperRegistry), - config.minLINKJuels - ); - } - - /** - * @notice gets the admin address and the current balance of a registration request - */ - function getPendingRequest(bytes32 hash) external view returns (address, uint96) { - PendingRequest memory request = s_pendingRequests[hash]; - return (request.admin, request.balance); - } - - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @param sender Address of the sender transfering LINK - * @param amount Amount of LINK sent (specified in Juels) - * @param data Payload of the transaction - */ - function onTokenTransfer( - address sender, - uint256 amount, - bytes calldata data - ) - external - override - onlyLINK - permittedFunctionsForLINK(data) - isActualAmount(amount, data) - isActualSender(sender, data) - { - if (data.length < 292) revert InvalidDataLength(); - if (amount < s_config.minLINKJuels) { - revert InsufficientPayment(); - } - (bool success, ) = address(this).delegatecall(data); - // calls register - if (!success) { - revert RegistrationRequestFailed(); - } - } - - //PRIVATE - - /** - * @dev verify registration request and emit RegistrationRequested event - */ - function _register(RegistrationParams memory params, address sender) private returns (uint256) { - if (params.adminAddress == address(0)) { - revert InvalidAdminAddress(); - } - bytes32 hash = keccak256( - abi.encode(params.upkeepContract, params.gasLimit, params.adminAddress, params.checkData, params.offchainConfig) - ); - - emit RegistrationRequested( - hash, - params.name, - params.encryptedEmail, - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.checkData, - params.amount - ); - - uint256 upkeepId; - RegistrarConfig memory config = s_config; - if (_shouldAutoApprove(config, sender)) { - s_config.approvedCount = config.approvedCount + 1; - - upkeepId = _approve(params, hash); - } else { - uint96 newBalance = s_pendingRequests[hash].balance + params.amount; - s_pendingRequests[hash] = PendingRequest({admin: params.adminAddress, balance: newBalance}); - } - - return upkeepId; - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { - AutomationRegistryBaseInterface keeperRegistry = s_config.keeperRegistry; - - // register upkeep - uint256 upkeepId = keeperRegistry.registerUpkeep( - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.checkData, - params.offchainConfig - ); - // fund upkeep - bool success = LINK.transferAndCall(address(keeperRegistry), params.amount, abi.encode(upkeepId)); - if (!success) { - revert LinkTransferFailed(address(keeperRegistry)); - } - - emit RegistrationApproved(hash, params.name, upkeepId); - - return upkeepId; - } - - /** - * @dev verify sender allowlist if needed and check max limit - */ - function _shouldAutoApprove(RegistrarConfig memory config, address sender) private view returns (bool) { - if (config.autoApproveConfigType == AutoApproveType.DISABLED) { - return false; - } - if ( - config.autoApproveConfigType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender]) - ) { - return false; - } - if (config.approvedCount < config.autoApproveMaxAllowed) { - return true; - } - return false; - } - - //MODIFIERS - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - if (msg.sender != address(LINK)) { - revert OnlyLink(); - } - _; - } - - /** - * @dev Reverts if the given data does not begin with the `register` function selector - * @param _data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory _data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data - } - if (funcSelector != REGISTER_REQUEST_SELECTOR) { - revert FunctionNotPermitted(); - } - _; - } - - /** - * @dev Reverts if the actual amount passed does not match the expected amount - * @param expected amount that should match the actual amount - * @param data bytes - */ - modifier isActualAmount(uint256 expected, bytes calldata data) { - // decode register function arguments to get actual amount - (, , , , , , , uint96 amount, ) = abi.decode( - data[4:], - (string, bytes, address, uint32, address, bytes, bytes, uint96, address) - ); - if (expected != amount) { - revert AmountMismatch(); - } - _; - } - - /** - * @dev Reverts if the actual sender address does not match the expected sender address - * @param expected address that should match the actual sender address - * @param data bytes - */ - modifier isActualSender(address expected, bytes calldata data) { - // decode register function arguments to get actual sender - (, , , , , , , , address sender) = abi.decode( - data[4:], - (string, bytes, address, uint32, address, bytes, bytes, uint96, address) - ); - if (expected != sender) { - revert SenderMismatch(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol deleted file mode 100644 index bd3c78e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistry2_0.sol +++ /dev/null @@ -1,1012 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol"; -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import "./KeeperRegistryBase2_0.sol"; -import {AutomationRegistryExecutableInterface, UpkeepInfo, State, OnchainConfig, UpkeepFailureReason} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; -import "../interfaces/MigratableKeeperRegistryInterface.sol"; -import "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import "../../shared/interfaces/IERC677Receiver.sol"; -import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; - -/** - _. _|_ _ ._ _ _._|_o _ ._ o _ _ ._ _| _ __|_o._ -(_||_||_(_)| | |(_| |_|(_)| | |_> (_)|_|| (_|(/__> |_|| |\/ - / - */ -/** - * @notice Registry for adding work for Chainlink Keepers to perform on client - * contracts. Clients must support the Upkeep interface. - */ -contract KeeperRegistry2_0 is - KeeperRegistryBase2_0, - Proxy, - OCR2Abstract, - AutomationRegistryExecutableInterface, - MigratableKeeperRegistryInterface, - MigratableKeeperRegistryInterfaceV2, - IERC677Receiver -{ - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - - // Immutable address of logic contract where some functionality is delegated to - address private immutable i_keeperRegistryLogic; - - /** - * @notice versions: - * - KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts - * : fixes issue with arbitrum block number - * : does an early return in case of stale report instead of revert - * - KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X - * - KeeperRegistry 2.0.0: implement OCR interface - * - KeeperRegistry 1.3.0: split contract into Proxy and Logic - * : account for Arbitrum and Optimism L1 gas fee - * : allow users to configure upkeeps - * - KeeperRegistry 1.2.0: allow funding within performUpkeep - * : allow configurable registry maxPerformGas - * : add function to let admin change upkeep gas limit - * : add minUpkeepSpend requirement - * : upgrade to solidity v0.8 - * - KeeperRegistry 1.1.0: added flatFeeMicroLink - * - KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistry 2.0.2"; - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - - UpkeepFormat public constant override upkeepTranscoderVersion = UPKEEP_TRANSCODER_VERSION_BASE; - - /** - * @inheritdoc MigratableKeeperRegistryInterfaceV2 - */ - uint8 public constant override upkeepVersion = UPKEEP_VERSION_BASE; - - /** - * @param keeperRegistryLogic address of the logic contract - */ - constructor( - KeeperRegistryBase2_0 keeperRegistryLogic - ) - KeeperRegistryBase2_0( - keeperRegistryLogic.getMode(), - keeperRegistryLogic.getLinkAddress(), - keeperRegistryLogic.getLinkNativeFeedAddress(), - keeperRegistryLogic.getFastGasFeedAddress() - ) - { - i_keeperRegistryLogic = address(keeperRegistryLogic); - } - - //////// - // ACTIONS - //////// - - /** - * @dev This struct is used to maintain run time information about an upkeep in transmit function - * @member upkeep the upkeep struct - * @member earlyChecksPassed whether the upkeep passed early checks before perform - * @member paymentParams the paymentParams for this upkeep - * @member performSuccess whether the perform was successful - * @member gasUsed gasUsed by this upkeep in perform - */ - struct UpkeepTransmitInfo { - Upkeep upkeep; - bool earlyChecksPassed; - uint96 maxLinkPayment; - bool performSuccess; - uint256 gasUsed; - uint256 gasOverhead; - } - - /** - * @inheritdoc OCR2Abstract - */ - function transmit( - bytes32[3] calldata reportContext, - bytes calldata rawReport, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external override { - uint256 gasOverhead = gasleft(); - HotVars memory hotVars = s_hotVars; - - if (hotVars.paused) revert RegistryPaused(); - if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); - - Report memory report = _decodeReport(rawReport); - UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); - uint16 numUpkeepsPassedChecks; - - for (uint256 i = 0; i < report.upkeepIds.length; i++) { - upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]]; - - upkeepTransmitInfo[i].maxLinkPayment = _getMaxLinkPayment( - hotVars, - upkeepTransmitInfo[i].upkeep.executeGas, - uint32(report.wrappedPerformDatas[i].performData.length), - report.fastGasWei, - report.linkNative, - true - ); - upkeepTransmitInfo[i].earlyChecksPassed = _prePerformChecks( - report.upkeepIds[i], - report.wrappedPerformDatas[i], - upkeepTransmitInfo[i].upkeep, - upkeepTransmitInfo[i].maxLinkPayment - ); - - if (upkeepTransmitInfo[i].earlyChecksPassed) { - numUpkeepsPassedChecks += 1; - } - } - // No upkeeps to be performed in this report - if (numUpkeepsPassedChecks == 0) { - return; - } - - // Verify signatures - if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); - if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); - _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); - - // Actually perform upkeeps - for (uint256 i = 0; i < report.upkeepIds.length; i++) { - if (upkeepTransmitInfo[i].earlyChecksPassed) { - // Check if this upkeep was already performed in this report - if (s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber == uint32(_blockNum())) { - revert InvalidReport(); - } - - // Actually perform the target upkeep - (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( - upkeepTransmitInfo[i].upkeep, - report.wrappedPerformDatas[i].performData - ); - - // Deduct that gasUsed by upkeep from our running counter - gasOverhead -= upkeepTransmitInfo[i].gasUsed; - - // Store last perform block number for upkeep - s_upkeep[report.upkeepIds[i]].lastPerformBlockNumber = uint32(_blockNum()); - } - } - - // 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 - gasOverhead = - (gasOverhead - gasleft() + 16 * rawReport.length) + - ACCOUNTING_FIXED_GAS_OVERHEAD + - (ACCOUNTING_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); - gasOverhead = gasOverhead / 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, - uint32(report.wrappedPerformDatas[i].performData.length), - hotVars.f - ); - - (reimbursement, premium) = _postPerformPayment( - hotVars, - report.upkeepIds[i], - upkeepTransmitInfo[i], - report.fastGasWei, - report.linkNative, - numUpkeepsPassedChecks - ); - totalPremium += premium; - totalReimbursement += reimbursement; - - emit UpkeepPerformed( - report.upkeepIds[i], - upkeepTransmitInfo[i].performSuccess, - report.wrappedPerformDatas[i].checkBlockNumber, - upkeepTransmitInfo[i].gasUsed, - upkeepTransmitInfo[i].gasOverhead, - reimbursement + premium - ); - } - } - } - // record payments - s_transmitters[msg.sender].balance += totalReimbursement; - s_hotVars.totalPremium += totalPremium; - - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - if (epoch > hotVars.latestEpoch) { - s_hotVars.latestEpoch = epoch; - } - } - - /** - * @notice simulates the upkeep with the perform data returned from - * checkUpkeep - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - */ - function simulatePerformUpkeep( - uint256 id, - bytes calldata performData - ) external cannotExecute returns (bool success, uint256 gasUsed) { - if (s_hotVars.paused) revert RegistryPaused(); - - Upkeep memory upkeep = s_upkeep[id]; - return _performUpkeep(upkeep, performData); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_expectedLinkBalance = s_expectedLinkBalance + amount; - - emit FundsAdded(id, sender, uint96(amount)); - } - - //////// - // SETTERS - //////// - - /** - * @inheritdoc OCR2Abstract - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override onlyOwner { - if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); - if (f == 0) revert IncorrectNumberOfFaultyOracles(); - if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); - - // move all pooled payments out of the pool to each transmitter's balance - uint96 totalPremium = s_hotVars.totalPremium; - uint96 oldLength = uint96(s_transmittersList.length); - for (uint256 i = 0; i < oldLength; i++) { - _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); - } - - // remove any old signer/transmitter addresses - address signerAddress; - address transmitterAddress; - for (uint256 i = 0; i < oldLength; i++) { - signerAddress = s_signersList[i]; - transmitterAddress = s_transmittersList[i]; - delete s_signers[signerAddress]; - // Do not delete the whole transmitter struct as it has balance information stored - s_transmitters[transmitterAddress].active = false; - } - delete s_signersList; - delete s_transmittersList; - - // add new signer/transmitter addresses - { - Transmitter memory transmitter; - address temp; - for (uint256 i = 0; i < signers.length; i++) { - if (s_signers[signers[i]].active) revert RepeatedSigner(); - s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); - - temp = transmitters[i]; - transmitter = s_transmitters[temp]; - if (transmitter.active) revert RepeatedTransmitter(); - transmitter.active = true; - transmitter.index = uint8(i); - transmitter.lastCollected = totalPremium; - s_transmitters[temp] = transmitter; - } - } - s_signersList = signers; - s_transmittersList = transmitters; - - // Set the onchain config - OnchainConfig memory onchainConfigStruct = abi.decode(onchainConfig, (OnchainConfig)); - if (onchainConfigStruct.maxPerformGas < s_storage.maxPerformGas) revert GasLimitCanOnlyIncrease(); - if (onchainConfigStruct.maxCheckDataSize < s_storage.maxCheckDataSize) revert MaxCheckDataSizeCanOnlyIncrease(); - if (onchainConfigStruct.maxPerformDataSize < s_storage.maxPerformDataSize) - revert MaxPerformDataSizeCanOnlyIncrease(); - - s_hotVars = HotVars({ - f: f, - paymentPremiumPPB: onchainConfigStruct.paymentPremiumPPB, - flatFeeMicroLink: onchainConfigStruct.flatFeeMicroLink, - stalenessSeconds: onchainConfigStruct.stalenessSeconds, - gasCeilingMultiplier: onchainConfigStruct.gasCeilingMultiplier, - paused: false, - reentrancyGuard: false, - totalPremium: totalPremium, - latestEpoch: 0 - }); - - s_storage = Storage({ - checkGasLimit: onchainConfigStruct.checkGasLimit, - minUpkeepSpend: onchainConfigStruct.minUpkeepSpend, - maxPerformGas: onchainConfigStruct.maxPerformGas, - transcoder: onchainConfigStruct.transcoder, - registrar: onchainConfigStruct.registrar, - maxCheckDataSize: onchainConfigStruct.maxCheckDataSize, - maxPerformDataSize: onchainConfigStruct.maxPerformDataSize, - nonce: s_storage.nonce, - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - ownerLinkBalance: s_storage.ownerLinkBalance - }); - s_fallbackGasPrice = onchainConfigStruct.fallbackGasPrice; - s_fallbackLinkPrice = onchainConfigStruct.fallbackLinkPrice; - - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - s_storage.latestConfigBlockNumber = uint32(_blockNum()); - s_storage.configCount += 1; - - s_latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_storage.configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - emit ConfigSet( - previousConfigBlockNumber, - s_latestConfigDigest, - s_storage.configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - //////// - // GETTERS - //////// - - /** - * @notice read all of the details about an upkeep - */ - function getUpkeep(uint256 id) external view override returns (UpkeepInfo memory upkeepInfo) { - Upkeep memory reg = s_upkeep[id]; - upkeepInfo = UpkeepInfo({ - target: reg.target, - executeGas: reg.executeGas, - checkData: s_checkData[id], - balance: reg.balance, - admin: s_upkeepAdmin[id], - maxValidBlocknumber: reg.maxValidBlocknumber, - lastPerformBlockNumber: reg.lastPerformBlockNumber, - amountSpent: reg.amountSpent, - paused: reg.paused, - offchainConfig: s_upkeepOffchainConfig[id] - }); - return upkeepInfo; - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view override returns (uint256[] memory) { - uint256 maxIdx = s_upkeepIDs.length(); - if (startIndex >= maxIdx) revert IndexOutOfRange(); - if (maxCount == 0) { - maxCount = maxIdx - startIndex; - } - uint256[] memory ids = new uint256[](maxCount); - for (uint256 idx = 0; idx < maxCount; idx++) { - ids[idx] = s_upkeepIDs.at(startIndex + idx); - } - return ids; - } - - /** - * @notice read the current info about any transmitter address - */ - function getTransmitterInfo( - address query - ) external view override returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { - Transmitter memory transmitter = s_transmitters[query]; - uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; - uint96 pooledShare = totalDifference / uint96(s_transmittersList.length); - - return ( - transmitter.active, - transmitter.index, - (transmitter.balance + pooledShare), - transmitter.lastCollected, - s_transmitterPayees[query] - ); - } - - /** - * @notice read the current info about any signer address - */ - function getSignerInfo(address query) external view returns (bool active, uint8 index) { - Signer memory signer = s_signers[query]; - return (signer.active, signer.index); - } - - /** - * @notice read the current state of the registry - */ - function getState() - external - view - override - returns ( - State memory state, - OnchainConfig memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) - { - state = State({ - nonce: s_storage.nonce, - ownerLinkBalance: s_storage.ownerLinkBalance, - expectedLinkBalance: s_expectedLinkBalance, - totalPremium: s_hotVars.totalPremium, - numUpkeeps: s_upkeepIDs.length(), - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - latestConfigDigest: s_latestConfigDigest, - latestEpoch: s_hotVars.latestEpoch, - paused: s_hotVars.paused - }); - - config = OnchainConfig({ - paymentPremiumPPB: s_hotVars.paymentPremiumPPB, - flatFeeMicroLink: s_hotVars.flatFeeMicroLink, - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - minUpkeepSpend: s_storage.minUpkeepSpend, - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - transcoder: s_storage.transcoder, - registrar: s_storage.registrar - }); - - return (state, config, s_signersList, s_transmittersList, s_hotVars.f); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { - return getMaxPaymentForGas(s_upkeep[id].executeGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas(uint32 gasLimit) public view returns (uint96 maxPayment) { - HotVars memory hotVars = s_hotVars; - (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); - return _getMaxLinkPayment(hotVars, gasLimit, s_storage.maxPerformDataSize, fastGasWei, linkNative, false); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice retrieves the address of the logic address - */ - function getKeeperRegistryLogicAddress() external view returns (address) { - return i_keeperRegistryLogic; - } - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); - } - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_latestConfigDigest, s_hotVars.latestEpoch); - } - - //////// - // INTERNAL FUNCTIONS - //////// - - /** - * @dev This is the address to which proxy functions are delegated to - */ - function _implementation() internal view override returns (address) { - return i_keeperRegistryLogic; - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= PERFORM_GAS_CUSHION and check for underflow - if lt(g, PERFORM_GAS_CUSHION) { - revert(0, 0) - } - g := sub(g, PERFORM_GAS_CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - /** - * @dev _decodeReport decodes a serialized report into a Report struct - */ - function _decodeReport(bytes memory rawReport) internal pure returns (Report memory) { - ( - uint256 fastGasWei, - uint256 linkNative, - uint256[] memory upkeepIds, - PerformDataWrapper[] memory wrappedPerformDatas - ) = abi.decode(rawReport, (uint256, uint256, uint256[], PerformDataWrapper[])); - if (upkeepIds.length != wrappedPerformDatas.length) revert InvalidReport(); - - return - Report({ - fastGasWei: fastGasWei, - linkNative: linkNative, - upkeepIds: upkeepIds, - wrappedPerformDatas: wrappedPerformDatas - }); - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - */ - function _prePerformChecks( - uint256 upkeepId, - PerformDataWrapper memory wrappedPerformData, - Upkeep memory upkeep, - uint96 maxLinkPayment - ) internal returns (bool) { - if (wrappedPerformData.checkBlockNumber < upkeep.lastPerformBlockNumber) { - // Can happen when another report performed this upkeep after this report was generated - emit StaleUpkeepReport(upkeepId); - return false; - } - - if (_blockHash(wrappedPerformData.checkBlockNumber) != wrappedPerformData.checkBlockhash) { - // Can happen when the block on which report was generated got reorged - // We will also revert if checkBlockNumber is older than 256 blocks. In this case we rely on a new transmission - // with the latest checkBlockNumber - emit ReorgedUpkeepReport(upkeepId); - return false; - } - - if (upkeep.maxValidBlocknumber <= _blockNum()) { - // Can happen when an upkeep got cancelled after report was generated. - // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice - emit CancelledUpkeepReport(upkeepId); - return false; - } - - if (upkeep.balance < maxLinkPayment) { - // Can happen due to flucutations in gas / link prices - emit InsufficientFundsUpkeepReport(upkeepId); - return false; - } - - return true; - } - - /** - * @dev Verify signatures attached to report - */ - function _verifyReportSignature( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) internal view { - bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount = 0; - - Signer memory signer; - address signerAddress; - for (uint256 i = 0; i < rs.length; i++) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - signer = s_signers[signerAddress]; - if (!signer.active) revert OnlyActiveSigners(); - unchecked { - signedCount += 1 << (8 * signer.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * transmitter and the exact gas required by the Upkeep - */ - function _performUpkeep( - Upkeep memory upkeep, - bytes memory performData - ) private nonReentrant returns (bool success, uint256 gasUsed) { - gasUsed = gasleft(); - bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); - success = _callWithExactGas(upkeep.executeGas, upkeep.target, callData); - gasUsed = gasUsed - gasleft(); - - return (success, gasUsed); - } - - /** - * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases - * amount spent. - */ - function _postPerformPayment( - HotVars memory hotVars, - uint256 upkeepId, - UpkeepTransmitInfo memory upkeepTransmitInfo, - uint256 fastGasWei, - uint256 linkNative, - uint16 numBatchedUpkeeps - ) internal returns (uint96 gasReimbursement, uint96 premium) { - (gasReimbursement, premium) = _calculatePaymentAmount( - hotVars, - upkeepTransmitInfo.gasUsed, - upkeepTransmitInfo.gasOverhead, - fastGasWei, - linkNative, - numBatchedUpkeeps, - true - ); - - uint96 payment = gasReimbursement + premium; - s_upkeep[upkeepId].balance -= payment; - s_upkeep[upkeepId].amountSpent += payment; - - return (gasReimbursement, premium); - } - - /** - * @dev Caps the gas overhead by the constant overhead used within initial payment checks in order to - * prevent a revert in payment processing. - */ - function _getCappedGasOverhead( - uint256 calculatedGasOverhead, - uint32 performDataLength, - uint8 f - ) private pure returns (uint256 cappedGasOverhead) { - cappedGasOverhead = _getMaxGasOverhead(performDataLength, f); - if (calculatedGasOverhead < cappedGasOverhead) { - return calculatedGasOverhead; - } - return cappedGasOverhead; - } - - //////// - // PROXY FUNCTIONS - EXECUTED THROUGH FALLBACK - //////// - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData, - bytes calldata offchainConfig - ) external override returns (uint256 id) { - // Executed through logic contract - _fallback(); - } - - /** - * @notice simulated by keepers via eth_call to see if the upkeep needs to be - * performed. It returns the success status / failure reason along with the perform data payload. - * @param id identifier of the upkeep to check - */ - function checkUpkeep( - uint256 id - ) - external - override - cannotExecute - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 fastGasWei, - uint256 linkNative - ) - { - // Executed through logic contract - _fallback(); - } - - /** - * @notice prevent an upkeep from being performed in the future - * @param id upkeep to be canceled - */ - function cancelUpkeep(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice pause an upkeep - * @param id upkeep to be paused - */ - function pauseUpkeep(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice unpause an upkeep - * @param id upkeep to be resumed - */ - function unpauseUpkeep(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice update the check data of an upkeep - * @param id the id of the upkeep whose check data needs to be updated - * @param newCheckData the new check data - */ - function updateCheckData(uint256 id, bytes calldata newCheckData) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice adds LINK funding for an upkeep by transferring from the sender's - * LINK balance - * @param id upkeep to fund - * @param amount number of LINK to transfer - */ - function addFunds(uint256 id, uint96 amount) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice removes funding from a canceled upkeep - * @param id upkeep to withdraw funds from - * @param to destination address for sending remaining funds - */ - function withdrawFunds(uint256 id, address to) external { - // Executed through logic contract - // Restricted to nonRentrant in logic contract as this is not callable from a user's performUpkeep - _fallback(); - } - - /** - * @notice allows the admin of an upkeep to modify gas limit - * @param id upkeep to be change the gas limit for - * @param gasLimit new gas limit for the upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice allows the admin of an upkeep to modify the offchain config - * @param id upkeep to be change the gas limit for - * @param config instructs oracles of offchain config preferences - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice withdraws a transmitter's payment, callable only by the transmitter's payee - * @param from transmitter address - * @param to address to send the payment to - */ - function withdrawPayment(address from, address to) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice proposes the safe transfer of a transmitter's payee to another address - * @param transmitter address of the transmitter to transfer payee role - * @param proposed address to nominate for next payeeship - */ - function transferPayeeship(address transmitter, address proposed) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice accepts the safe transfer of payee role for a transmitter - * @param transmitter address to accept the payee role for - */ - function acceptPayeeship(address transmitter) external { - // Executed through logic contract - _fallback(); - } - - /** - * @notice proposes the safe transfer of an upkeep's admin role to another address - * @param id the upkeep id to transfer admin - * @param proposed address to nominate for the new upkeep admin - */ - function transferUpkeepAdmin(uint256 id, address proposed) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @notice accepts the safe transfer of admin role for an upkeep - * @param id the upkeep id - */ - function acceptUpkeepAdmin(uint256 id) external override { - // Executed through logic contract - _fallback(); - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function migrateUpkeeps( - uint256[] calldata ids, - address destination - ) external override(MigratableKeeperRegistryInterface, MigratableKeeperRegistryInterfaceV2) { - // Executed through logic contract - _fallback(); - } - - /** - * @inheritdoc MigratableKeeperRegistryInterface - */ - function receiveUpkeeps( - bytes calldata encodedUpkeeps - ) external override(MigratableKeeperRegistryInterface, MigratableKeeperRegistryInterfaceV2) { - // Executed through logic contract - _fallback(); - } - - //////// - // OWNER RESTRICTED FUNCTIONS - //////// - - /** - * @notice recovers LINK funds improperly transferred to the registry - * @dev In principle this function’s execution cost could exceed block - * gas limit. However, in our anticipated deployment, the number of upkeeps and - * transmitters will be low enough to avoid this problem. - */ - function recoverFunds() external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } - - /** - * @notice withdraws LINK funds collected through cancellation fees - */ - function withdrawOwnerFunds() external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } - - /** - * @notice update the list of payees corresponding to the transmitters - * @param payees addresses corresponding to transmitters who are allowed to - * move payments which have been accrued - */ - function setPayees(address[] calldata payees) external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } - - /** - * @notice signals to transmitters that they should not perform upkeeps until the - * contract has been unpaused - */ - function pause() external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } - - /** - * @notice signals to transmitters that they can perform upkeeps once again after - * having been paused - */ - function unpause() external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } - - /** - * @notice sets the peer registry migration permission - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external { - // Executed through logic contract - // Restricted to onlyOwner in logic contract - _fallback(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol deleted file mode 100644 index 9b78e58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryBase2_0.sol +++ /dev/null @@ -1,479 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import "../ExecutionPrevention.sol"; -import "../../shared/access/ConfirmedOwner.sol"; -import "../../shared/interfaces/AggregatorV3Interface.sol"; -import "../../shared/interfaces/LinkTokenInterface.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; -import "../interfaces/UpkeepTranscoderInterface.sol"; - -/** - * @notice relevant state of an upkeep which is used in transmit function - * @member executeGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member paused if this upkeep has been paused - * @member target the contract which needs to be serviced - * @member amountSpent the amount this upkeep has spent - * @member balance the balance of this upkeep - * @member lastPerformBlockNumber the last block number when this upkeep was performed - */ -struct Upkeep { - uint32 executeGas; - uint32 maxValidBlocknumber; - bool paused; - address target; - // 3 bytes left in 1st EVM word - not written to in transmit - uint96 amountSpent; - uint96 balance; - uint32 lastPerformBlockNumber; - // 4 bytes left in 2nd EVM word - written in transmit path -} - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * KeeperRegistry and KeeperRegistryLogic - */ -abstract contract KeeperRegistryBase2_0 is ConfirmedOwner, ExecutionPrevention { - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; - uint32 internal constant UINT32_MAX = type(uint32).max; - uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - /** - * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with - * MigratableKeeperRegistryInterfaceV1 - it should be removed in future versions in favor of - * UPKEEP_VERSION_BASE and MigratableKeeperRegistryInterfaceV2 - */ - UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; - uint8 internal constant UPKEEP_VERSION_BASE = uint8(UpkeepFormat.V3); - // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism - bytes internal constant L1_FEE_DATA_PADDING = - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - - uint256 internal constant REGISTRY_GAS_OVERHEAD = 70_000; // Used only in maxPayment estimation, not in actual payment - uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 20; // Used only in maxPayment estimation, not in actual payment. Value scales with performData length. - uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 7_500; // Used only in maxPayment estimation, not in actual payment. Value scales with f. - - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 26_900; // Used in actual payment. Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_SIGNER_GAS_OVERHEAD = 1_100; // Used in actual payment. overhead per signer - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 5_800; // Used in actual payment. overhead per upkeep performed - - OVM_GasPriceOracle internal constant OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); - ArbGasInfo internal constant ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); - ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); - - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_linkNativeFeed; - AggregatorV3Interface internal immutable i_fastGasFeed; - Mode internal immutable i_mode; - - // @dev - The storage is gas optimised for one and only function - transmit. All the storage accessed in transmit - // is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path - // Upkeep storage - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit - mapping(uint256 => address) internal s_upkeepAdmin; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - // Registry config and state - mapping(address => Transmitter) internal s_transmitters; - mapping(address => Signer) internal s_signers; - address[] internal s_signersList; // s_signersList contains the signing address of each oracle - address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle - mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. - mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter - bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification - HotVars internal s_hotVars; // Mixture of config and state, used in transmit - Storage internal s_storage; // Mixture of config and state, not used in transmit - uint256 internal s_fallbackGasPrice; - uint256 internal s_fallbackLinkPrice; - uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro - mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general configuration preferences - - error ArrayHasNoEntries(); - error CannotCancel(); - error DuplicateEntry(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IndexOutOfRange(); - error InsufficientFunds(); - error InvalidDataLength(); - error InvalidPayee(); - error InvalidRecipient(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyPausedUpkeep(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error TargetCheckReverted(bytes reason); - error TranscoderNotSet(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - error ConfigDigestMismatch(); - error IncorrectNumberOfSignatures(); - error OnlyActiveSigners(); - error DuplicateSigners(); - error TooManyOracles(); - error IncorrectNumberOfSigners(); - error IncorrectNumberOfFaultyOracles(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error OnchainConfigNonEmpty(); - error CheckDataExceedsLimit(); - error MaxCheckDataSizeCanOnlyIncrease(); - error MaxPerformDataSizeCanOnlyIncrease(); - error InvalidReport(); - error RegistryPaused(); - error ReentrantCall(); - error UpkeepAlreadyExists(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum Mode { - DEFAULT, - ARBITRUM, - OPTIMISM - } - - // Config + State storage struct which is on hot transmit path - struct HotVars { - uint8 f; // maximum number of faulty oracles - uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost - uint32 flatFeeMicroLink; // flat fee charged to user for every perform - uint24 stalenessSeconds; // Staleness tolerance for feeds - uint16 gasCeilingMultiplier; // multiplier on top of fast gas feed for upper bound - bool paused; // pause switch for all upkeeps in the registry - bool reentrancyGuard; // guard against reentrancy - uint96 totalPremium; // total historical payment to oracles for premium - uint32 latestEpoch; // latest epoch for which a report was transmitted - // 1 EVM word full - } - - // Config + State storage struct which is not on hot transmit path - struct Storage { - uint96 minUpkeepSpend; // Minimum amount an upkeep must spend - address transcoder; // Address of transcoder contract used in migrations - // 1 EVM word full - uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent - address registrar; // Address of registrar used to register upkeeps - // 2 EVM word full - uint32 checkGasLimit; // Gas limit allowed in checkUpkeep - uint32 maxPerformGas; // Max gas an upkeep can use on this registry - uint32 nonce; // Nonce for each upkeep created - uint32 configCount; // incremented each time a new config is posted, The count - // is incorporated into the config digest to prevent replay attacks. - uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs - uint32 maxCheckDataSize; // max length of checkData bytes - uint32 maxPerformDataSize; // max length of performData bytes - // 4 bytes to 3rd EVM word - } - - struct Transmitter { - bool active; - uint8 index; // Index of oracle in s_signersList/s_transmittersList - uint96 balance; - uint96 lastCollected; - } - - struct Signer { - bool active; - // Index of oracle in s_signersList/s_transmittersList - uint8 index; - } - - // This struct is used to pack information about the user's check function - struct PerformDataWrapper { - uint32 checkBlockNumber; // Block number-1 on which check was simulated - bytes32 checkBlockhash; // blockhash of checkBlockNumber. Used for reorg protection - bytes performData; // actual performData that user's check returned - } - - // Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkNative; - uint256[] upkeepIds; // Ids of upkeeps - PerformDataWrapper[] wrappedPerformDatas; // Contains checkInfo and performData for the corresponding upkeeps - } - - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event OwnerFundsWithdrawn(uint96 amount); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataUpdated(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint32 checkBlockNumber, - uint256 gasUsed, - uint256 gasOverhead, - uint96 totalPayment - ); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepUnpaused(uint256 indexed id); - event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); - event StaleUpkeepReport(uint256 indexed id); - event ReorgedUpkeepReport(uint256 indexed id); - event InsufficientFundsUpkeepReport(uint256 indexed id); - event CancelledUpkeepReport(uint256 indexed id); - event Paused(address account); - event Unpaused(address account); - - /** - * @param mode the contract mode of default, Arbitrum, or Optimism - * @param link address of the LINK Token - * @param linkNativeFeed address of the LINK/Native price feed - * @param fastGasFeed address of the Fast Gas price feed - */ - constructor(Mode mode, address link, address linkNativeFeed, address fastGasFeed) ConfirmedOwner(msg.sender) { - i_mode = mode; - i_link = LinkTokenInterface(link); - i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); - i_fastGasFeed = AggregatorV3Interface(fastGasFeed); - } - - //////// - // GETTERS - //////// - - function getMode() external view returns (Mode) { - return i_mode; - } - - function getLinkAddress() external view returns (address) { - return address(i_link); - } - - function getLinkNativeFeedAddress() external view returns (address) { - return address(i_linkNativeFeed); - } - - function getFastGasFeedAddress() external view returns (address) { - return address(i_fastGasFeed); - } - - //////// - // INTERNAL - //////// - - /** - * @dev retrieves feed data for fast gas/native and link/native prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { - uint32 stalenessSeconds = hotVars.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - linkNative = s_fallbackLinkPrice; - } else { - linkNative = uint256(feedValue); - } - return (gasWei, linkNative); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @param gasLimit the amount of gas used - * @param gasOverhead the amount of gas overhead - * @param fastGasWei the fast gas price - * @param linkNative the exchange ratio between LINK and Native token - * @param numBatchedUpkeeps the number of upkeeps in this batch. Used to divide the L1 cost - * @param isExecution if this is triggered by a perform upkeep function - */ - function _calculatePaymentAmount( - HotVars memory hotVars, - uint256 gasLimit, - uint256 gasOverhead, - uint256 fastGasWei, - uint256 linkNative, - uint16 numBatchedUpkeeps, - bool isExecution - ) internal view returns (uint96, uint96) { - uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (isExecution && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - - uint256 l1CostWei = 0; - if (i_mode == Mode.OPTIMISM) { - bytes memory txCallData = new bytes(0); - if (isExecution) { - txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); - } else { - // @dev fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have - // s_storage.maxPerformDataSize non zero-bytes. Instead of setting bytes to non-zero - // we initialize 'new bytes' of length 4*maxPerformDataSize to cover for zero bytes. - txCallData = new bytes(4 * s_storage.maxPerformDataSize); - } - l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); - } else if (i_mode == Mode.ARBITRUM) { - l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); - } - // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound - if (!isExecution) { - l1CostWei = hotVars.gasCeilingMultiplier * l1CostWei; - } - // Divide l1CostWei among all batched upkeeps. Spare change from division is not charged - l1CostWei = l1CostWei / numBatchedUpkeeps; - - uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; - uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / - linkNative + - uint256(hotVars.flatFeeMicroLink) * - 1e12; - // LINK_TOTAL_SUPPLY < UINT96_MAX - if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); - return (uint96(gasPayment), uint96(premium)); - } - - /** - * @dev generates the max link payment for an upkeep - */ - function _getMaxLinkPayment( - HotVars memory hotVars, - uint32 executeGas, - uint32 performDataLength, - uint256 fastGasWei, - uint256 linkNative, - bool isExecution // Whether this is an actual perform execution or just a simulation - ) internal view returns (uint96) { - uint256 gasOverhead = _getMaxGasOverhead(performDataLength, hotVars.f); - (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( - hotVars, - executeGas, - gasOverhead, - fastGasWei, - linkNative, - 1, // Consider only 1 upkeep in batch to get maxPayment - isExecution - ); - - return reimbursement + premium; - } - - /** - * @dev returns the max gas overhead that can be charged for an upkeep - */ - function _getMaxGasOverhead(uint32 performDataLength, uint8 f) internal pure returns (uint256) { - // performData causes additional overhead in report length and memory operations - return - REGISTRY_GAS_OVERHEAD + - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (f + 1)) + - (REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD * performDataLength); - } - - /** - * @dev move a transmitter's balance from total pool to withdrawable balance - */ - function _updateTransmitterBalanceFromPool( - address transmitterAddress, - uint96 totalPremium, - uint96 payeeCount - ) internal returns (uint96) { - Transmitter memory transmitter = s_transmitters[transmitterAddress]; - - uint96 uncollected = totalPremium - transmitter.lastCollected; - uint96 due = uncollected / payeeCount; - transmitter.balance += due; - transmitter.lastCollected = totalPremium; - - // Transfer spare change to owner - s_storage.ownerLinkBalance += (uncollected - due * payeeCount); - s_transmitters[transmitterAddress] = transmitter; - - return transmitter.balance; - } - - /** - * @notice returns the current block number in a chain agnostic manner - */ - function _blockNum() internal view returns (uint256) { - if (i_mode == Mode.ARBITRUM) { - return ARB_SYS.arbBlockNumber(); - } else { - return block.number; - } - } - - /** - * @notice returns the blockhash of the provided block number in a chain agnostic manner - * @param n the blocknumber to retrieve the blockhash for - * @return blockhash the blockhash of block number n, or 0 if n is out queryable of range - */ - function _blockHash(uint256 n) internal view returns (bytes32) { - if (i_mode == Mode.ARBITRUM) { - uint256 blockNum = ARB_SYS.arbBlockNumber(); - if (n >= blockNum || blockNum - n > 256) { - return ""; - } - return ARB_SYS.arbBlockHash(n); - } else { - return blockhash(n); - } - } - - /** - * @notice replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_hotVars.reentrancyGuard) revert ReentrantCall(); - s_hotVars.reentrancyGuard = true; - _; - s_hotVars.reentrancyGuard = false; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol deleted file mode 100644 index 7eacc3c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/KeeperRegistryLogic2_0.sol +++ /dev/null @@ -1,474 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import "./KeeperRegistryBase2_0.sol"; -import {UpkeepFailureReason} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; -import "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import "../interfaces/UpkeepTranscoderInterfaceV2.sol"; - -/** - * @notice Logic contract, works in tandem with KeeperRegistry as a proxy - */ -contract KeeperRegistryLogic2_0 is KeeperRegistryBase2_0 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - - /** - * @param mode one of Default, Arbitrum, Optimism - * @param link address of the LINK Token - * @param linkNativeFeed address of the LINK/Native price feed - * @param fastGasFeed address of the Fast Gas price feed - */ - constructor( - Mode mode, - address link, - address linkNativeFeed, - address fastGasFeed - ) KeeperRegistryBase2_0(mode, link, linkNativeFeed, fastGasFeed) {} - - function checkUpkeep( - uint256 id - ) - external - cannotExecute - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 fastGasWei, - uint256 linkNative - ) - { - HotVars memory hotVars = s_hotVars; - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, gasUsed, 0, 0); - if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, gasUsed, 0, 0); - - (fastGasWei, linkNative) = _getFeedData(hotVars); - uint96 maxLinkPayment = _getMaxLinkPayment( - hotVars, - upkeep.executeGas, - s_storage.maxPerformDataSize, - fastGasWei, - linkNative, - false - ); - if (upkeep.balance < maxLinkPayment) - return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, gasUsed, fastGasWei, linkNative); - - gasUsed = gasleft(); - bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); - (bool success, bytes memory result) = upkeep.target.call{gas: s_storage.checkGasLimit}(callData); - gasUsed = gasUsed - gasleft(); - - if (!success) { - upkeepFailureReason = UpkeepFailureReason.TARGET_CHECK_REVERTED; - } else { - (upkeepNeeded, result) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, fastGasWei, linkNative); - if (result.length > s_storage.maxPerformDataSize) - return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed, fastGasWei, linkNative); - } - - performData = abi.encode( - PerformDataWrapper({ - checkBlockNumber: uint32(_blockNum() - 1), - checkBlockhash: _blockHash(_blockNum() - 1), - performData: result - }) - ); - - return (success, performData, upkeepFailureReason, gasUsed, fastGasWei, linkNative); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawOwnerFunds() external onlyOwner { - uint96 amount = s_storage.ownerLinkBalance; - - s_expectedLinkBalance = s_expectedLinkBalance - amount; - s_storage.ownerLinkBalance = 0; - - emit OwnerFundsWithdrawn(amount); - i_link.transfer(msg.sender, amount); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function recoverFunds() external onlyOwner { - uint256 total = i_link.balanceOf(address(this)); - i_link.transfer(msg.sender, total - s_expectedLinkBalance); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setPayees(address[] calldata payees) external onlyOwner { - if (s_transmittersList.length != payees.length) revert ParameterLengthError(); - for (uint256 i = 0; i < s_transmittersList.length; i++) { - address transmitter = s_transmittersList[i]; - address oldPayee = s_transmitterPayees[transmitter]; - address newPayee = payees[i]; - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) revert InvalidPayee(); - if (newPayee != IGNORE_ADDRESS) { - s_transmitterPayees[transmitter] = newPayee; - } - } - emit PayeesUpdated(s_transmittersList, payees); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function pause() external onlyOwner { - s_hotVars.paused = true; - - emit Paused(msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function unpause() external onlyOwner { - s_hotVars.paused = false; - - emit Unpaused(msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData, - bytes calldata offchainConfig - ) external returns (uint256 id) { - if (msg.sender != owner() && msg.sender != s_storage.registrar) revert OnlyCallableByOwnerOrRegistrar(); - - id = uint256(keccak256(abi.encode(_blockHash(_blockNum() - 1), address(this), s_storage.nonce))); - _createUpkeep(id, target, gasLimit, admin, 0, checkData, false); - s_storage.nonce++; - s_upkeepOffchainConfig[id] = offchainConfig; - emit UpkeepRegistered(id, gasLimit, admin); - return id; - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; - bool isOwner = msg.sender == owner(); - - if (canceled && !(isOwner && upkeep.maxValidBlocknumber > _blockNum())) revert CannotCancel(); - if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); - - uint256 height = _blockNum(); - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minUpkeepSpend is not met - uint96 minUpkeepSpend = s_storage.minUpkeepSpend; - uint96 cancellationFee = 0; - // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) - if (upkeep.amountSpent < minUpkeepSpend) { - cancellationFee = minUpkeepSpend - upkeep.amountSpent; - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function addFunds(uint256 id, uint96 amount) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].balance = upkeep.balance + amount; - s_expectedLinkBalance = s_expectedLinkBalance + amount; - i_link.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawFunds(uint256 id, address to) external nonReentrant { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > _blockNum()) revert UpkeepNotCanceled(); - - uint96 amountToWithdraw = s_upkeep[id].balance; - s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; - s_upkeep[id].balance = 0; - i_link.transfer(to, amountToWithdraw); - emit FundsWithdrawn(id, amountToWithdraw, to); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - _requireAdminAndNotCancelled(id); - s_upkeep[id].executeGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { - _requireAdminAndNotCancelled(id); - - s_upkeepOffchainConfig[id] = config; - - emit UpkeepOffchainConfigSet(id, config); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); - - uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); - s_transmitters[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance - balance; - - i_link.transfer(to, balance); - - emit PaymentWithdrawn(from, balance, to, msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function transferPayeeship(address transmitter, address proposed) external { - if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[transmitter] != proposed) { - s_proposedPayee[transmitter] = proposed; - emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); - } - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function acceptPayeeship(address transmitter) external { - if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_transmitterPayees[transmitter]; - s_transmitterPayees[transmitter] = msg.sender; - s_proposedPayee[transmitter] = ZERO_ADDRESS; - - emit PayeeshipTransferred(transmitter, past, msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - _requireAdminAndNotCancelled(id); - if (proposed == msg.sender) revert ValueNotChanged(); - if (proposed == ZERO_ADDRESS) revert InvalidRecipient(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = s_upkeepAdmin[id]; - s_upkeepAdmin[id] = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function pauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function unpauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function updateCheckData(uint256 id, bytes calldata newCheckData) external { - _requireAdminAndNotCancelled(id); - if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataUpdated(id, newCheckData); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - uint256 id; - Upkeep memory upkeep; - uint256 totalBalanceRemaining; - bytes[] memory checkDatas = new bytes[](ids.length); - address[] memory admins = new address[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - _requireAdminAndNotCancelled(id); - upkeeps[idx] = upkeep; - checkDatas[idx] = s_checkData[id]; - admins[idx] = s_upkeepAdmin[id]; - totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; - delete s_upkeep[id]; - delete s_checkData[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; - bytes memory encodedUpkeeps = abi.encode(ids, upkeeps, checkDatas, admins); - MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( - UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( - UPKEEP_VERSION_BASE, - MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), - encodedUpkeeps - ) - ); - i_link.transfer(destination, totalBalanceRemaining); - } - - /** - * @dev Called through KeeperRegistry main contract - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - (uint256[] memory ids, Upkeep[] memory upkeeps, bytes[] memory checkDatas, address[] memory upkeepAdmins) = abi - .decode(encodedUpkeeps, (uint256[], Upkeep[], bytes[], address[])); - for (uint256 idx = 0; idx < ids.length; idx++) { - _createUpkeep( - ids[idx], - upkeeps[idx].target, - upkeeps[idx].executeGas, - upkeepAdmins[idx], - upkeeps[idx].balance, - checkDatas[idx], - upkeeps[idx].paused - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } - - /** - * @notice creates a new upkeep with the given fields - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - * @param paused if this upkeep is paused - */ - function _createUpkeep( - uint256 id, - address target, - uint32 gasLimit, - address admin, - uint96 balance, - bytes memory checkData, - bool paused - ) internal { - if (s_hotVars.paused) revert RegistryPaused(); - if (!target.isContract()) revert NotAContract(); - if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - if (s_upkeep[id].target != address(0)) revert UpkeepAlreadyExists(); - s_upkeep[id] = Upkeep({ - target: target, - executeGas: gasLimit, - balance: balance, - maxValidBlocknumber: UINT32_MAX, - lastPerformBlockNumber: 0, - amountSpent: 0, - paused: paused - }); - s_upkeepAdmin[id] = admin; - s_expectedLinkBalance = s_expectedLinkBalance + balance; - s_checkData[id] = checkData; - s_upkeepIDs.add(id); - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { - if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); - if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol deleted file mode 100644 index 0a56f20..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_0/UpkeepTranscoder3_0.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import "../../automation/interfaces/UpkeepTranscoderInterface.sol"; -import "../../interfaces/TypeAndVersionInterface.sol"; -import {Upkeep as UpkeepV1} from "../../automation/v1_2/KeeperRegistry1_2.sol"; -import {Upkeep as UpkeepV2} from "../../automation/v1_3/KeeperRegistryBase1_3.sol"; -import {Upkeep as UpkeepV3} from "../../automation/v2_0/KeeperRegistryBase2_0.sol"; -import "../../automation/UpkeepFormat.sol"; - -/** - * @notice UpkeepTranscoder 3_0 allows converting upkeep data from previous keeper registry versions 1.2 and 1.3 to - * registry 2.0 - */ -contract UpkeepTranscoder3_0 is UpkeepTranscoderInterface, TypeAndVersionInterface { - error InvalidTranscoding(); - - /** - * @notice versions: - * - UpkeepTranscoder 3.0.0: version 3.0.0 works with registry 2.0; adds temporary workaround for UpkeepFormat enum bug - */ - string public constant override typeAndVersion = "UpkeepTranscoder 3.0.0"; - uint32 internal constant UINT32_MAX = type(uint32).max; - - /** - * @notice transcodeUpkeeps transforms upkeep data from the format expected by - * one registry to the format expected by another. It future-proofs migrations - * by allowing keepers team to customize migration paths and set sensible defaults - * when new fields are added - * @param fromVersion struct version the upkeep is migrating from - * @param encodedUpkeeps encoded upkeep data - * @dev this transcoder should ONLY be use for V1/V2 --> V3 migrations - * @dev this transcoder **ignores** the toVersion param, as it assumes all migrations are - * for the V3 version. Therefore, it is the responsibility of the deployer of this contract - * to ensure it is not used in any other migration paths. - */ - function transcodeUpkeeps( - UpkeepFormat fromVersion, - UpkeepFormat, - bytes calldata encodedUpkeeps - ) external view override returns (bytes memory) { - // this transcoder only handles upkeep V1/V2 to V3, all other formats are invalid. - if (fromVersion == UpkeepFormat.V1) { - (uint256[] memory ids, UpkeepV1[] memory upkeepsV1, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], UpkeepV1[], bytes[]) - ); - - if (ids.length != upkeepsV1.length || ids.length != checkDatas.length) { - revert InvalidTranscoding(); - } - - address[] memory admins = new address[](ids.length); - UpkeepV3[] memory newUpkeeps = new UpkeepV3[](ids.length); - UpkeepV1 memory upkeepV1; - for (uint256 idx = 0; idx < ids.length; idx++) { - upkeepV1 = upkeepsV1[idx]; - newUpkeeps[idx] = UpkeepV3({ - executeGas: upkeepV1.executeGas, - maxValidBlocknumber: UINT32_MAX, // maxValidBlocknumber is uint64 in V1, hence a new default value is provided - paused: false, // migrated upkeeps are not paused by default - target: upkeepV1.target, - amountSpent: upkeepV1.amountSpent, - balance: upkeepV1.balance, - lastPerformBlockNumber: 0 - }); - admins[idx] = upkeepV1.admin; - } - return abi.encode(ids, newUpkeeps, checkDatas, admins); - } - - if (fromVersion == UpkeepFormat.V2) { - (uint256[] memory ids, UpkeepV2[] memory upkeepsV2, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], UpkeepV2[], bytes[]) - ); - - if (ids.length != upkeepsV2.length || ids.length != checkDatas.length) { - revert InvalidTranscoding(); - } - - address[] memory admins = new address[](ids.length); - UpkeepV3[] memory newUpkeeps = new UpkeepV3[](ids.length); - UpkeepV2 memory upkeepV2; - for (uint256 idx = 0; idx < ids.length; idx++) { - upkeepV2 = upkeepsV2[idx]; - newUpkeeps[idx] = UpkeepV3({ - executeGas: upkeepV2.executeGas, - maxValidBlocknumber: upkeepV2.maxValidBlocknumber, - paused: upkeepV2.paused, - target: upkeepV2.target, - amountSpent: upkeepV2.amountSpent, - balance: upkeepV2.balance, - lastPerformBlockNumber: 0 - }); - admins[idx] = upkeepV2.admin; - } - return abi.encode(ids, newUpkeeps, checkDatas, admins); - } - - revert InvalidTranscoding(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol deleted file mode 100644 index 407dda2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationRegistrar2_1.sol +++ /dev/null @@ -1,532 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {IKeeperRegistryMaster} from "../interfaces/v2_1/IKeeperRegistryMaster.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Contract to accept requests for upkeep registrations - * @dev There are 2 registration workflows in this contract - * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually - * calls `approve` to register upkeep and emit events to inform UI and others interested. - * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on - * keeper registry and then emits approved event to finish the flow automatically without manual intervention. - * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. - * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. - */ -contract AutomationRegistrar2_1 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { - /** - * DISABLED: No auto approvals, all new upkeeps should be approved manually. - * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. - * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. - */ - enum AutoApproveType { - DISABLED, - ENABLED_SENDER_ALLOWLIST, - ENABLED_ALL - } - - bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; - - mapping(bytes32 => PendingRequest) private s_pendingRequests; - mapping(uint8 => TriggerRegistrationStorage) private s_triggerRegistrations; - - LinkTokenInterface public immutable LINK; - - /** - * @notice versions: - * - KeeperRegistrar 2.1.0: Update for compatability with registry 2.1.0 - * Add auto approval levels by type - * - KeeperRegistrar 2.0.0: Remove source from register - * Breaks our example of "Register an Upkeep using your own deployed contract" - * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve - * : Remove rate limit and add max allowed for auto approve - * - KeeperRegistrar 1.0.0: initial release - */ - string public constant override typeAndVersion = "AutomationRegistrar 2.1.0"; - - /** - * @notice TriggerRegistrationStorage stores the auto-approval levels for upkeeps by type - * @member autoApproveType the auto approval setting (see enum) - * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - * @member approvedCount the count of upkeeps auto approved of this type - */ - struct TriggerRegistrationStorage { - AutoApproveType autoApproveType; - uint32 autoApproveMaxAllowed; - uint32 approvedCount; - } - - /** - * @notice InitialTriggerConfig configures the auto-approval levels for upkeeps by trigger type - * @dev this struct is only used in the constructor to set the initial values for various trigger configs - * @member triggerType the upkeep type to configure - * @member autoApproveType the auto approval setting (see enum) - * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - */ - struct InitialTriggerConfig { - uint8 triggerType; - AutoApproveType autoApproveType; - uint32 autoApproveMaxAllowed; - } - - struct RegistrarConfig { - IKeeperRegistryMaster keeperRegistry; - uint96 minLINKJuels; - } - - struct PendingRequest { - address admin; - uint96 balance; - } - - struct RegistrationParams { - string name; - bytes encryptedEmail; - address upkeepContract; - uint32 gasLimit; - address adminAddress; - uint8 triggerType; - bytes checkData; - bytes triggerConfig; - bytes offchainConfig; - uint96 amount; - } - - RegistrarConfig private s_config; - // Only applicable if s_config.configType is ENABLED_SENDER_ALLOWLIST - mapping(address => bool) private s_autoApproveAllowedSenders; - - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - uint8 triggerType, - bytes triggerConfig, - bytes offchainConfig, - bytes checkData, - uint96 amount - ); - - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - - event RegistrationRejected(bytes32 indexed hash); - - event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); - - event ConfigChanged(address keeperRegistry, uint96 minLINKJuels); - - event TriggerConfigSet(uint8 triggerType, AutoApproveType autoApproveType, uint32 autoApproveMaxAllowed); - - error InvalidAdminAddress(); - error RequestNotFound(); - error HashMismatch(); - error OnlyAdminOrOwner(); - error InsufficientPayment(); - error RegistrationRequestFailed(); - error OnlyLink(); - error AmountMismatch(); - error SenderMismatch(); - error FunctionNotPermitted(); - error LinkTransferFailed(address to); - error InvalidDataLength(); - - /** - * @param LINKAddress Address of Link token - * @param keeperRegistry keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - * @param triggerConfigs the initial config for individual triggers - */ - constructor( - address LINKAddress, - address keeperRegistry, - uint96 minLINKJuels, - InitialTriggerConfig[] memory triggerConfigs - ) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(LINKAddress); - setConfig(keeperRegistry, minLINKJuels); - for (uint256 idx = 0; idx < triggerConfigs.length; idx++) { - setTriggerConfig( - triggerConfigs[idx].triggerType, - triggerConfigs[idx].autoApproveType, - triggerConfigs[idx].autoApproveMaxAllowed - ); - } - } - - //EXTERNAL - - /** - * @notice register can only be called through transferAndCall on LINK contract - * @param name string of the upkeep to be registered - * @param encryptedEmail email address of upkeep contact - * @param upkeepContract address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when performing upkeep - * @param adminAddress address to cancel upkeep and withdraw remaining funds - * @param triggerType the type of trigger for the upkeep - * @param checkData data passed to the contract when checking for upkeep - * @param triggerConfig the config for the trigger - * @param offchainConfig offchainConfig for upkeep in bytes - * @param amount quantity of LINK upkeep is funded with (specified in Juels) - * @param sender address of the sender making the request - */ - function register( - string memory name, - bytes calldata encryptedEmail, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - uint8 triggerType, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig, - uint96 amount, - address sender - ) external onlyLINK { - _register( - RegistrationParams({ - name: name, - encryptedEmail: encryptedEmail, - upkeepContract: upkeepContract, - gasLimit: gasLimit, - adminAddress: adminAddress, - triggerType: triggerType, - checkData: checkData, - triggerConfig: triggerConfig, - offchainConfig: offchainConfig, - amount: amount - }), - sender - ); - } - - /** - * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract - * @param requestParams struct of all possible registration parameters - */ - function registerUpkeep(RegistrationParams calldata requestParams) external returns (uint256) { - if (requestParams.amount < s_config.minLINKJuels) { - revert InsufficientPayment(); - } - - LINK.transferFrom(msg.sender, address(this), requestParams.amount); - - return _register(requestParams, msg.sender); - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - uint8 triggerType, - bytes calldata checkData, - bytes memory triggerConfig, - bytes calldata offchainConfig, - bytes32 hash - ) external onlyOwner { - PendingRequest memory request = s_pendingRequests[hash]; - if (request.admin == address(0)) { - revert RequestNotFound(); - } - bytes32 expectedHash = keccak256( - abi.encode(upkeepContract, gasLimit, adminAddress, triggerType, checkData, triggerConfig, offchainConfig) - ); - if (hash != expectedHash) { - revert HashMismatch(); - } - delete s_pendingRequests[hash]; - _approve( - RegistrationParams({ - name: name, - encryptedEmail: "", - upkeepContract: upkeepContract, - gasLimit: gasLimit, - adminAddress: adminAddress, - triggerType: triggerType, - checkData: checkData, - triggerConfig: triggerConfig, - offchainConfig: offchainConfig, - amount: request.balance - }), - expectedHash - ); - } - - /** - * @notice cancel will remove a registration request and return the refunds to the request.admin - * @param hash the request hash - */ - function cancel(bytes32 hash) external { - PendingRequest memory request = s_pendingRequests[hash]; - if (!(msg.sender == request.admin || msg.sender == owner())) { - revert OnlyAdminOrOwner(); - } - if (request.admin == address(0)) { - revert RequestNotFound(); - } - delete s_pendingRequests[hash]; - bool success = LINK.transfer(request.admin, request.balance); - if (!success) { - revert LinkTransferFailed(request.admin); - } - emit RegistrationRejected(hash); - } - - /** - * @notice owner calls this function to set contract config - * @param keeperRegistry new keeper registry address - * @param minLINKJuels minimum LINK that new registrations should fund their upkeep with - */ - function setConfig(address keeperRegistry, uint96 minLINKJuels) public onlyOwner { - s_config = RegistrarConfig({minLINKJuels: minLINKJuels, keeperRegistry: IKeeperRegistryMaster(keeperRegistry)}); - emit ConfigChanged(keeperRegistry, minLINKJuels); - } - - /** - * @notice owner calls to set the config for this upkeep type - * @param triggerType the upkeep type to configure - * @param autoApproveType the auto approval setting (see enum) - * @param autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - */ - function setTriggerConfig( - uint8 triggerType, - AutoApproveType autoApproveType, - uint32 autoApproveMaxAllowed - ) public onlyOwner { - s_triggerRegistrations[triggerType].autoApproveType = autoApproveType; - s_triggerRegistrations[triggerType].autoApproveMaxAllowed = autoApproveMaxAllowed; - emit TriggerConfigSet(triggerType, autoApproveType, autoApproveMaxAllowed); - } - - /** - * @notice owner calls this function to set allowlist status for senderAddress - * @param senderAddress senderAddress to set the allowlist status for - * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed - */ - function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { - s_autoApproveAllowedSenders[senderAddress] = allowed; - - emit AutoApproveAllowedSenderSet(senderAddress, allowed); - } - - /** - * @notice read the allowlist status of senderAddress - * @param senderAddress address to read the allowlist status for - */ - function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { - return s_autoApproveAllowedSenders[senderAddress]; - } - - /** - * @notice read the current registration configuration - */ - function getConfig() external view returns (address keeperRegistry, uint256 minLINKJuels) { - RegistrarConfig memory config = s_config; - return (address(config.keeperRegistry), config.minLINKJuels); - } - - /** - * @notice read the config for this upkeep type - * @param triggerType upkeep type to read config for - */ - function getTriggerRegistrationDetails(uint8 triggerType) external view returns (TriggerRegistrationStorage memory) { - return s_triggerRegistrations[triggerType]; - } - - /** - * @notice gets the admin address and the current balance of a registration request - */ - function getPendingRequest(bytes32 hash) external view returns (address, uint96) { - PendingRequest memory request = s_pendingRequests[hash]; - return (request.admin, request.balance); - } - - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @param sender Address of the sender transfering LINK - * @param amount Amount of LINK sent (specified in Juels) - * @param data Payload of the transaction - */ - function onTokenTransfer( - address sender, - uint256 amount, - bytes calldata data - ) - external - override - onlyLINK - permittedFunctionsForLINK(data) - isActualAmount(amount, data) - isActualSender(sender, data) - { - if (amount < s_config.minLINKJuels) { - revert InsufficientPayment(); - } - (bool success, ) = address(this).delegatecall(data); - // calls register - if (!success) { - revert RegistrationRequestFailed(); - } - } - - // ================================================================ - // | PRIVATE | - // ================================================================ - - /** - * @dev verify registration request and emit RegistrationRequested event - */ - function _register(RegistrationParams memory params, address sender) private returns (uint256) { - if (params.adminAddress == address(0)) { - revert InvalidAdminAddress(); - } - bytes32 hash = keccak256( - abi.encode( - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.triggerType, - params.checkData, - params.triggerConfig, - params.offchainConfig - ) - ); - - emit RegistrationRequested( - hash, - params.name, - params.encryptedEmail, - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.triggerType, - params.triggerConfig, - params.offchainConfig, - params.checkData, - params.amount - ); - - uint256 upkeepId; - if (_shouldAutoApprove(s_triggerRegistrations[params.triggerType], sender)) { - s_triggerRegistrations[params.triggerType].approvedCount++; - upkeepId = _approve(params, hash); - } else { - uint96 newBalance = s_pendingRequests[hash].balance + params.amount; - s_pendingRequests[hash] = PendingRequest({admin: params.adminAddress, balance: newBalance}); - } - - return upkeepId; - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { - IKeeperRegistryMaster keeperRegistry = s_config.keeperRegistry; - uint256 upkeepId = keeperRegistry.registerUpkeep( - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.triggerType, - params.checkData, - params.triggerConfig, - params.offchainConfig - ); - bool success = LINK.transferAndCall(address(keeperRegistry), params.amount, abi.encode(upkeepId)); - if (!success) { - revert LinkTransferFailed(address(keeperRegistry)); - } - emit RegistrationApproved(hash, params.name, upkeepId); - return upkeepId; - } - - /** - * @dev verify sender allowlist if needed and check max limit - */ - function _shouldAutoApprove(TriggerRegistrationStorage memory config, address sender) private view returns (bool) { - if (config.autoApproveType == AutoApproveType.DISABLED) { - return false; - } - if (config.autoApproveType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender])) { - return false; - } - if (config.approvedCount < config.autoApproveMaxAllowed) { - return true; - } - return false; - } - - // ================================================================ - // | MODIFIERS | - // ================================================================ - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - if (msg.sender != address(LINK)) { - revert OnlyLink(); - } - _; - } - - /** - * @dev Reverts if the given data does not begin with the `register` function selector - * @param _data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory _data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(_data, 32)) // First 32 bytes contain length of data - } - if (funcSelector != REGISTER_REQUEST_SELECTOR) { - revert FunctionNotPermitted(); - } - _; - } - - /** - * @dev Reverts if the actual amount passed does not match the expected amount - * @param expected amount that should match the actual amount - * @param data bytes - */ - modifier isActualAmount(uint256 expected, bytes calldata data) { - // decode register function arguments to get actual amount - (, , , , , , , , , uint96 amount, ) = abi.decode( - data[4:], - (string, bytes, address, uint32, address, uint8, bytes, bytes, bytes, uint96, address) - ); - if (expected != amount) { - revert AmountMismatch(); - } - _; - } - - /** - * @dev Reverts if the actual sender address does not match the expected sender address - * @param expected address that should match the actual sender address - * @param data bytes - */ - modifier isActualSender(address expected, bytes calldata data) { - // decode register function arguments to get actual sender - (, , , , , , , , , , address sender) = abi.decode( - data[4:], - (string, bytes, address, uint32, address, uint8, bytes, bytes, bytes, uint96, address) - ); - if (expected != sender) { - revert SenderMismatch(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol deleted file mode 100644 index 76483c8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/AutomationUtils2_1.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; -import {Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -/** - * @notice this file exposes structs that are otherwise internal to the automation registry - * doing this allows those structs to be encoded and decoded with type safety in offchain code - * and tests because generated wrappers are made available - */ - -/** - * @notice structure of trigger for log triggers - */ -struct LogTriggerConfig { - address contractAddress; - uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply - bytes32 topic0; - bytes32 topic1; - bytes32 topic2; - bytes32 topic3; -} - -contract AutomationUtils2_1 { - /** - * @dev this can be removed as OnchainConfig is now exposed directly from the registry - */ - function _onChainConfig(IAutomationV21PlusCommon.OnchainConfigLegacy memory) external {} // 0x2ff92a81 - - function _report(KeeperRegistryBase2_1.Report memory) external {} // 0xe65d6546 - - function _logTriggerConfig(LogTriggerConfig memory) external {} // 0x21f373d7 - - function _logTrigger(KeeperRegistryBase2_1.LogTrigger memory) external {} // 0x1c8d8260 - - function _conditionalTrigger(KeeperRegistryBase2_1.ConditionalTrigger memory) external {} // 0x4b6df294 - - function _log(Log memory) external {} // 0xe9720a49 -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol deleted file mode 100644 index 25028e6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistry2_1.sol +++ /dev/null @@ -1,397 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; -import {KeeperRegistryLogicB2_1} from "./KeeperRegistryLogicB2_1.sol"; -import {Chainable} from "../Chainable.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -/** - * @notice Registry for adding work for Chainlink Keepers to perform on client - * contracts. Clients must support the Upkeep interface. - */ -contract KeeperRegistry2_1 is KeeperRegistryBase2_1, OCR2Abstract, Chainable, IERC677Receiver { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @notice versions: - * - KeeperRegistry 2.1.0: introduces support for log, cron, and ready triggers - : removes the need for "wrapped perform data" - * - KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts - * : fixes issue with arbitrum block number - * : does an early return in case of stale report instead of revert - * - KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X - * - KeeperRegistry 2.0.0: implement OCR interface - * - KeeperRegistry 1.3.0: split contract into Proxy and Logic - * : account for Arbitrum and Optimism L1 gas fee - * : allow users to configure upkeeps - * - KeeperRegistry 1.2.0: allow funding within performUpkeep - * : allow configurable registry maxPerformGas - * : add function to let admin change upkeep gas limit - * : add minUpkeepSpend requirement - * : upgrade to solidity v0.8 - * - KeeperRegistry 1.1.0: added flatFeeMicroLink - * - KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistry 2.1.0"; - - /** - * @param logicA the address of the first logic contract, but cast as logicB in order to call logicB functions - */ - constructor( - KeeperRegistryLogicB2_1 logicA - ) - KeeperRegistryBase2_1( - logicA.getMode(), - logicA.getLinkAddress(), - logicA.getLinkNativeFeedAddress(), - logicA.getFastGasFeedAddress(), - logicA.getAutomationForwarderLogic() - ) - Chainable(address(logicA)) - {} - - // ================================================================ - // | ACTIONS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function transmit( - bytes32[3] calldata reportContext, - bytes calldata rawReport, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external override { - uint256 gasOverhead = gasleft(); - HotVars memory hotVars = s_hotVars; - - if (hotVars.paused) revert RegistryPaused(); - if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); - - // Verify signatures - if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); - if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); - _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); - - Report memory report = _decodeReport(rawReport); - UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); - uint16 numUpkeepsPassedChecks; - - 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], - report.triggers[i], - upkeepTransmitInfo[i] - ); - - if (upkeepTransmitInfo[i].earlyChecksPassed) { - numUpkeepsPassedChecks += 1; - } else { - continue; - } - - // Actually perform the target upkeep - (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( - upkeepTransmitInfo[i].upkeep.forwarder, - report.gasLimits[i], - report.performDatas[i] - ); - - // 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], upkeepTransmitInfo[i]); - } - // No upkeeps to be performed in this report - if (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 - gasOverhead = - (gasOverhead - gasleft() + 16 * rawReport.length) + - ACCOUNTING_FIXED_GAS_OVERHEAD + - (ACCOUNTING_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); - gasOverhead = gasOverhead / 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], - report.fastGasWei, - report.linkNative, - numUpkeepsPassedChecks - ); - totalPremium += premium; - totalReimbursement += reimbursement; - - emit UpkeepPerformed( - report.upkeepIds[i], - upkeepTransmitInfo[i].performSuccess, - reimbursement + premium, - upkeepTransmitInfo[i].gasUsed, - upkeepTransmitInfo[i].gasOverhead, - report.triggers[i] - ); - } - } - } - // record payments - s_transmitters[msg.sender].balance += totalReimbursement; - s_hotVars.totalPremium += totalPremium; - - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - if (epoch > hotVars.latestEpoch) { - s_hotVars.latestEpoch = epoch; - } - } - - /** - * @notice simulates the upkeep with the perform data returned from checkUpkeep - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - * @return success whether the call reverted or not - * @return gasUsed the amount of gas the target contract consumed - */ - function simulatePerformUpkeep( - uint256 id, - bytes calldata performData - ) external cannotExecute returns (bool success, uint256 gasUsed) { - if (s_hotVars.paused) revert RegistryPaused(); - Upkeep memory upkeep = s_upkeep[id]; - (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); - return (success, gasUsed); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_expectedLinkBalance = s_expectedLinkBalance + amount; - emit FundsAdded(id, sender, uint96(amount)); - } - - // ================================================================ - // | SETTERS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - * @dev prefer the type-safe version of setConfig (below) whenever possible - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override { - setConfigTypeSafe( - signers, - transmitters, - f, - abi.decode(onchainConfigBytes, (IAutomationV21PlusCommon.OnchainConfigLegacy)), - offchainConfigVersion, - offchainConfig - ); - } - - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - IAutomationV21PlusCommon.OnchainConfigLegacy memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) public onlyOwner { - if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); - if (f == 0) revert IncorrectNumberOfFaultyOracles(); - if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); - - // move all pooled payments out of the pool to each transmitter's balance - uint96 totalPremium = s_hotVars.totalPremium; - uint96 oldLength = uint96(s_transmittersList.length); - for (uint256 i = 0; i < oldLength; i++) { - _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); - } - - // remove any old signer/transmitter addresses - address signerAddress; - address transmitterAddress; - for (uint256 i = 0; i < oldLength; i++) { - signerAddress = s_signersList[i]; - transmitterAddress = s_transmittersList[i]; - delete s_signers[signerAddress]; - // Do not delete the whole transmitter struct as it has balance information stored - s_transmitters[transmitterAddress].active = false; - } - delete s_signersList; - delete s_transmittersList; - - // add new signer/transmitter addresses - { - Transmitter memory transmitter; - address temp; - for (uint256 i = 0; i < signers.length; i++) { - if (s_signers[signers[i]].active) revert RepeatedSigner(); - if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); - s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); - - temp = transmitters[i]; - if (temp == ZERO_ADDRESS) revert InvalidTransmitter(); - transmitter = s_transmitters[temp]; - if (transmitter.active) revert RepeatedTransmitter(); - transmitter.active = true; - transmitter.index = uint8(i); - // new transmitters start afresh from current totalPremium - // some spare change of premium from previous pool will be forfeited - transmitter.lastCollected = totalPremium; - s_transmitters[temp] = transmitter; - } - } - s_signersList = signers; - s_transmittersList = transmitters; - - s_hotVars = HotVars({ - f: f, - paymentPremiumPPB: onchainConfig.paymentPremiumPPB, - flatFeeMicroLink: onchainConfig.flatFeeMicroLink, - stalenessSeconds: onchainConfig.stalenessSeconds, - gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, - paused: s_hotVars.paused, - reentrancyGuard: s_hotVars.reentrancyGuard, - totalPremium: totalPremium, - latestEpoch: 0 // DON restarts epoch - }); - - s_storage = Storage({ - checkGasLimit: onchainConfig.checkGasLimit, - minUpkeepSpend: onchainConfig.minUpkeepSpend, - maxPerformGas: onchainConfig.maxPerformGas, - transcoder: onchainConfig.transcoder, - maxCheckDataSize: onchainConfig.maxCheckDataSize, - maxPerformDataSize: onchainConfig.maxPerformDataSize, - maxRevertDataSize: onchainConfig.maxRevertDataSize, - upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, - nonce: s_storage.nonce, - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - ownerLinkBalance: s_storage.ownerLinkBalance - }); - s_fallbackGasPrice = onchainConfig.fallbackGasPrice; - s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; - - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - s_storage.latestConfigBlockNumber = uint32(_blockNum()); - s_storage.configCount += 1; - - bytes memory onchainConfigBytes = abi.encode(onchainConfig); - - s_latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - - for (uint256 idx = 0; idx < s_registrars.length(); idx++) { - s_registrars.remove(s_registrars.at(idx)); - } - - for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { - s_registrars.add(onchainConfig.registrars[idx]); - } - - emit ConfigSet( - previousConfigBlockNumber, - s_latestConfigDigest, - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); - } - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_latestConfigDigest, s_hotVars.latestEpoch); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol deleted file mode 100644 index fe73894..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryBase2_1.sol +++ /dev/null @@ -1,861 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; -import {ExecutionPrevention} from "../ExecutionPrevention.sol"; -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; -import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * KeeperRegistry and KeeperRegistryLogic - * @dev all errors, events, and internal functions should live here - */ -abstract contract KeeperRegistryBase2_1 is ConfirmedOwner, ExecutionPrevention { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; - bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; - uint32 internal constant UINT32_MAX = type(uint32).max; - uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - /** - * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with - * MigratableKeeperRegistryInterfaceV1 - it should be removed in future versions in favor of - * UPKEEP_VERSION_BASE and MigratableKeeperRegistryInterfaceV2 - */ - UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; - uint8 internal constant UPKEEP_VERSION_BASE = 3; - // L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism - bytes internal constant L1_FEE_DATA_PADDING = - "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - - uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 90_000; // Used in maxPayment estimation, and in capping overheads during actual payment - uint256 internal constant REGISTRY_LOG_OVERHEAD = 110_000; // Used only in maxPayment estimation, and in capping overheads during actual payment. - uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 20; // Used only in maxPayment estimation, and in capping overheads during actual payment. Value scales with performData length. - uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 7_500; // Used only in maxPayment estimation, and in capping overheads during actual payment. Value scales with f. - - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 27_500; // Used in actual payment. Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_SIGNER_GAS_OVERHEAD = 1_100; // Used in actual payment. overhead per signer - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 7_000; // Used in actual payment. overhead per upkeep performed - - OVM_GasPriceOracle internal constant OPTIMISM_ORACLE = OVM_GasPriceOracle(0x420000000000000000000000000000000000000F); - ArbGasInfo internal constant ARB_NITRO_ORACLE = ArbGasInfo(0x000000000000000000000000000000000000006C); - ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); - - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_linkNativeFeed; - AggregatorV3Interface internal immutable i_fastGasFeed; - Mode internal immutable i_mode; - address internal immutable i_automationForwarderLogic; - - /** - * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit - * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path - */ - - // Upkeep storage - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit - mapping(uint256 => address) internal s_upkeepAdmin; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - mapping(bytes32 => bool) internal s_dedupKeys; - // Registry config and state - EnumerableSet.AddressSet internal s_registrars; - mapping(address => Transmitter) internal s_transmitters; - mapping(address => Signer) internal s_signers; - address[] internal s_signersList; // s_signersList contains the signing address of each oracle - address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle - mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. - mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter - bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification - HotVars internal s_hotVars; // Mixture of config and state, used in transmit - Storage internal s_storage; // Mixture of config and state, not used in transmit - uint256 internal s_fallbackGasPrice; - uint256 internal s_fallbackLinkPrice; - uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro - mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers - mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep - mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep - mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin - - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientFunds(); - error InvalidDataLength(); - error InvalidTrigger(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidTransmitter(); - error InvalidTriggerType(); - error MaxCheckDataSizeCanOnlyIncrease(); - error MaxPerformDataSizeCanOnlyIncrease(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyPausedUpkeep(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum Mode { - DEFAULT, - ARBITRUM, - OPTIMISM - } - - enum Trigger { - CONDITION, - LOG - } - - enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, - CALLBACK_REVERTED, - REVERT_DATA_EXCEEDS_LIMIT, - REGISTRY_PAUSED - } - - /** - * @notice relevant state of an upkeep which is used in transmit function - * @member paused if this upkeep has been paused - * @member performGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member forwarder the forwarder contract to use for this upkeep - * @member amountSpent the amount this upkeep has spent - * @member balance the balance of this upkeep - * @member lastPerformedBlockNumber the last block number when this upkeep was performed - */ - struct Upkeep { - bool paused; - uint32 performGas; - uint32 maxValidBlocknumber; - IAutomationForwarder forwarder; - // 0 bytes left in 1st EVM word - not written to in transmit - uint96 amountSpent; - uint96 balance; - uint32 lastPerformedBlockNumber; - // 2 bytes left in 2nd EVM word - written in transmit path - } - - /// @dev Config + State storage struct which is on hot transmit path - struct HotVars { - uint8 f; // maximum number of faulty oracles - uint32 paymentPremiumPPB; // premium percentage charged to user over tx cost - uint32 flatFeeMicroLink; // flat fee charged to user for every perform - uint24 stalenessSeconds; // Staleness tolerance for feeds - uint16 gasCeilingMultiplier; // multiplier on top of fast gas feed for upper bound - bool paused; // pause switch for all upkeeps in the registry - bool reentrancyGuard; // guard against reentrancy - uint96 totalPremium; // total historical payment to oracles for premium - uint32 latestEpoch; // latest epoch for which a report was transmitted - // 1 EVM word full - } - - /// @dev Config + State storage struct which is not on hot transmit path - struct Storage { - uint96 minUpkeepSpend; // Minimum amount an upkeep must spend - address transcoder; // Address of transcoder contract used in migrations - // 1 EVM word full - uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent - uint32 checkGasLimit; // Gas limit allowed in checkUpkeep - uint32 maxPerformGas; // Max gas an upkeep can use on this registry - uint32 nonce; // Nonce for each upkeep created - uint32 configCount; // incremented each time a new config is posted, The count - // is incorporated into the config digest to prevent replay attacks. - uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs - // 2 EVM word full - uint32 maxCheckDataSize; // max length of checkData bytes - uint32 maxPerformDataSize; // max length of performData bytes - uint32 maxRevertDataSize; // max length of revertData bytes - address upkeepPrivilegeManager; // address which can set privilege for upkeeps - // 3 EVM word full - } - - /// @dev Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkNative; - uint256[] upkeepIds; - uint256[] gasLimits; - bytes[] triggers; - bytes[] performDatas; - } - - /** - * @dev This struct is used to maintain run time information about an upkeep in transmit function - * @member upkeep the upkeep struct - * @member earlyChecksPassed whether the upkeep passed early checks before perform - * @member maxLinkPayment the max amount this upkeep could pay for work - * @member performSuccess whether the perform was successful - * @member triggerType the type of trigger - * @member gasUsed gasUsed by this upkeep in perform - * @member gasOverhead gasOverhead for this upkeep - * @member dedupID unique ID used to dedup an upkeep/trigger combo - */ - struct UpkeepTransmitInfo { - Upkeep upkeep; - bool earlyChecksPassed; - uint96 maxLinkPayment; - bool performSuccess; - Trigger triggerType; - uint256 gasUsed; - uint256 gasOverhead; - bytes32 dedupID; - } - - struct Transmitter { - bool active; - uint8 index; // Index of oracle in s_signersList/s_transmittersList - uint96 balance; - uint96 lastCollected; - } - - struct Signer { - bool active; - // Index of oracle in s_signersList/s_transmittersList - uint8 index; - } - - /** - * @notice the trigger structure conditional trigger type - */ - struct ConditionalTrigger { - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the trigger structure of log upkeeps - * @dev NOTE that blockNum / blockHash describe the block used for the callback, - * not necessarily the block number that the log was emitted in!!!! - */ - struct LogTrigger { - bytes32 logBlockHash; - bytes32 txHash; - uint32 logIndex; - uint32 blockNum; - bytes32 blockHash; - } - - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event OwnerFundsWithdrawn(uint96 amount); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - event Unpaused(address account); - - /** - * @param mode the contract mode of default, Arbitrum, or Optimism - * @param link address of the LINK Token - * @param linkNativeFeed address of the LINK/Native price feed - * @param fastGasFeed address of the Fast Gas price feed - */ - constructor( - Mode mode, - address link, - address linkNativeFeed, - address fastGasFeed, - address automationForwarderLogic - ) ConfirmedOwner(msg.sender) { - i_mode = mode; - i_link = LinkTokenInterface(link); - i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); - i_fastGasFeed = AggregatorV3Interface(fastGasFeed); - i_automationForwarderLogic = automationForwarderLogic; - } - - // ================================================================ - // | INTERNAL FUNCTIONS ONLY | - // ================================================================ - - /** - * @dev creates a new upkeep with the given fields - * @param id the id of the upkeep - * @param upkeep the upkeep to create - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data which is passed to user's checkUpkeep - * @param triggerConfig the trigger config for this upkeep - * @param offchainConfig the off-chain config of this upkeep - */ - function _createUpkeep( - uint256 id, - Upkeep memory upkeep, - address admin, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) internal { - if (s_hotVars.paused) revert RegistryPaused(); - if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) - revert GasLimitOutsideRange(); - if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); - s_upkeep[id] = upkeep; - s_upkeepAdmin[id] = admin; - s_checkData[id] = checkData; - s_expectedLinkBalance = s_expectedLinkBalance + upkeep.balance; - s_upkeepTriggerConfig[id] = triggerConfig; - s_upkeepOffchainConfig[id] = offchainConfig; - s_upkeepIDs.add(id); - } - - /** - * @dev creates an ID for the upkeep based on the upkeep's type - * @dev the format of the ID looks like this: - * ****00000000000X**************** - * 4 bytes of entropy - * 11 bytes of zeros - * 1 identifying byte for the trigger type - * 16 bytes of entropy - * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique - * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only - * see the first 4 and last 4 hex values ex 0x1234...ABCD - */ - function _createID(Trigger triggerType) internal view returns (uint256) { - bytes1 empty; - bytes memory idBytes = abi.encodePacked( - keccak256(abi.encode(_blockHash(_blockNum() - 1), address(this), s_storage.nonce)) - ); - for (uint256 idx = 4; idx < 15; idx++) { - idBytes[idx] = empty; - } - idBytes[15] = bytes1(uint8(triggerType)); - return uint256(bytes32(idBytes)); - } - - /** - * @dev retrieves feed data for fast gas/native and link/native prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { - uint32 stalenessSeconds = hotVars.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - linkNative = s_fallbackLinkPrice; - } else { - linkNative = uint256(feedValue); - } - return (gasWei, linkNative); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @param gasLimit the amount of gas used - * @param gasOverhead the amount of gas overhead - * @param fastGasWei the fast gas price - * @param linkNative the exchange ratio between LINK and Native token - * @param numBatchedUpkeeps the number of upkeeps in this batch. Used to divide the L1 cost - * @param isExecution if this is triggered by a perform upkeep function - */ - function _calculatePaymentAmount( - HotVars memory hotVars, - uint256 gasLimit, - uint256 gasOverhead, - uint256 fastGasWei, - uint256 linkNative, - uint16 numBatchedUpkeeps, - bool isExecution - ) internal view returns (uint96, uint96) { - uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (isExecution && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - - uint256 l1CostWei = 0; - if (i_mode == Mode.OPTIMISM) { - bytes memory txCallData = new bytes(0); - if (isExecution) { - txCallData = bytes.concat(msg.data, L1_FEE_DATA_PADDING); - } else { - // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have - // s_storage.maxPerformDataSize non zero-bytes. Instead of setting bytes to non-zero - // we initialize 'new bytes' of length 4*maxPerformDataSize to cover for zero bytes. - txCallData = new bytes(4 * s_storage.maxPerformDataSize); - } - l1CostWei = OPTIMISM_ORACLE.getL1Fee(txCallData); - } else if (i_mode == Mode.ARBITRUM) { - if (isExecution) { - l1CostWei = ARB_NITRO_ORACLE.getCurrentTxL1GasFees(); - } else { - // fee is 4 per 0 byte, 16 per non-zero byte - we assume all non-zero and - // max data size to calculate max payment - (, uint256 perL1CalldataUnit, , , , ) = ARB_NITRO_ORACLE.getPricesInWei(); - l1CostWei = perL1CalldataUnit * s_storage.maxPerformDataSize * 16; - } - } - // if it's not performing upkeeps, use gas ceiling multiplier to estimate the upper bound - if (!isExecution) { - l1CostWei = hotVars.gasCeilingMultiplier * l1CostWei; - } - // Divide l1CostWei among all batched upkeeps. Spare change from division is not charged - l1CostWei = l1CostWei / numBatchedUpkeeps; - - uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; - uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / - linkNative + - uint256(hotVars.flatFeeMicroLink) * - 1e12; - // LINK_TOTAL_SUPPLY < UINT96_MAX - if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); - return (uint96(gasPayment), uint96(premium)); - } - - /** - * @dev calculates the max LINK payment for an upkeep - */ - function _getMaxLinkPayment( - HotVars memory hotVars, - Trigger triggerType, - uint32 performGas, - uint32 performDataLength, - uint256 fastGasWei, - uint256 linkNative, - bool isExecution // Whether this is an actual perform execution or just a simulation - ) internal view returns (uint96) { - uint256 gasOverhead = _getMaxGasOverhead(triggerType, performDataLength, hotVars.f); - (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( - hotVars, - performGas, - gasOverhead, - fastGasWei, - linkNative, - 1, // Consider only 1 upkeep in batch to get maxPayment - isExecution - ); - - return reimbursement + premium; - } - - /** - * @dev returns the max gas overhead that can be charged for an upkeep - */ - function _getMaxGasOverhead(Trigger triggerType, uint32 performDataLength, uint8 f) internal pure returns (uint256) { - // performData causes additional overhead in report length and memory operations - uint256 baseOverhead; - if (triggerType == Trigger.CONDITION) { - baseOverhead = REGISTRY_CONDITIONAL_OVERHEAD; - } else if (triggerType == Trigger.LOG) { - baseOverhead = REGISTRY_LOG_OVERHEAD; - } else { - revert InvalidTriggerType(); - } - return - baseOverhead + - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (f + 1)) + - (REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD * performDataLength); - } - - /** - * @dev move a transmitter's balance from total pool to withdrawable balance - */ - function _updateTransmitterBalanceFromPool( - address transmitterAddress, - uint96 totalPremium, - uint96 payeeCount - ) internal returns (uint96) { - Transmitter memory transmitter = s_transmitters[transmitterAddress]; - - if (transmitter.active) { - uint96 uncollected = totalPremium - transmitter.lastCollected; - uint96 due = uncollected / payeeCount; - transmitter.balance += due; - transmitter.lastCollected += due * payeeCount; - s_transmitters[transmitterAddress] = transmitter; - } - - return transmitter.balance; - } - - /** - * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) - */ - function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { - bytes32 rawID = bytes32(upkeepId); - bytes1 empty = bytes1(0); - for (uint256 idx = 4; idx < 15; idx++) { - if (rawID[idx] != empty) { - // old IDs that were created before this standard and migrated to this registry - return Trigger.CONDITION; - } - } - return Trigger(uint8(rawID[15])); - } - - function _checkPayload( - uint256 upkeepId, - Trigger triggerType, - bytes memory triggerData - ) internal view returns (bytes memory) { - if (triggerType == Trigger.CONDITION) { - return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); - } else if (triggerType == Trigger.LOG) { - Log memory log = abi.decode(triggerData, (Log)); - return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); - } - revert InvalidTriggerType(); - } - - /** - * @dev _decodeReport decodes a serialized report into a Report struct - */ - function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { - Report memory report = abi.decode(rawReport, (Report)); - uint256 expectedLength = report.upkeepIds.length; - if ( - report.gasLimits.length != expectedLength || - report.triggers.length != expectedLength || - report.performDatas.length != expectedLength - ) { - revert InvalidReport(); - } - return report; - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - * @return bool whether the upkeep should be performed - * @return bytes32 dedupID for preventing duplicate performances of this trigger - */ - function _prePerformChecks( - uint256 upkeepId, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo - ) internal returns (bool, bytes32) { - bytes32 dedupID; - if (transmitInfo.triggerType == Trigger.CONDITION) { - if (!_validateConditionalTrigger(upkeepId, rawTrigger, transmitInfo)) return (false, dedupID); - } else if (transmitInfo.triggerType == Trigger.LOG) { - bool valid; - (valid, dedupID) = _validateLogTrigger(upkeepId, rawTrigger, transmitInfo); - if (!valid) return (false, dedupID); - } else { - revert InvalidTriggerType(); - } - if (transmitInfo.upkeep.maxValidBlocknumber <= _blockNum()) { - // Can happen when an upkeep got cancelled after report was generated. - // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice - emit CancelledUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - if (transmitInfo.upkeep.balance < transmitInfo.maxLinkPayment) { - // Can happen due to fluctuations in gas / link prices - emit InsufficientFundsUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - */ - function _validateConditionalTrigger( - uint256 upkeepId, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo - ) internal returns (bool) { - ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); - if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { - // Can happen when another report performed this upkeep after this report was generated - emit StaleUpkeepReport(upkeepId, rawTrigger); - return false; - } - if ( - (trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) || - trigger.blockNum >= _blockNum() - ) { - // There are two cases of reorged report - // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain - // which is always protected against - // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is - // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain - // when it is sent - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return false; - } - return true; - } - - function _validateLogTrigger( - uint256 upkeepId, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo - ) internal returns (bool, bytes32) { - LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); - bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); - if ( - (trigger.blockHash != bytes32("") && _blockHash(trigger.blockNum) != trigger.blockHash) || - trigger.blockNum >= _blockNum() - ) { - // Reorg protection is same as conditional trigger upkeeps - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - if (s_dedupKeys[dedupID]) { - emit StaleUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Verify signatures attached to report - */ - function _verifyReportSignature( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) internal view { - bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount = 0; - - Signer memory signer; - address signerAddress; - for (uint256 i = 0; i < rs.length; i++) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - signer = s_signers[signerAddress]; - if (!signer.active) revert OnlyActiveSigners(); - unchecked { - signedCount += 1 << (8 * signer.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); - } - - /** - * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances - * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID - */ - function _updateTriggerMarker(uint256 upkeepID, UpkeepTransmitInfo memory upkeepTransmitInfo) internal { - if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { - s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(_blockNum()); - } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { - s_dedupKeys[upkeepTransmitInfo.dedupID] = true; - emit DedupKeyAdded(upkeepTransmitInfo.dedupID); - } - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * transmitter and the exact gas required by the Upkeep - */ - function _performUpkeep( - IAutomationForwarder forwarder, - uint256 performGas, - bytes memory performData - ) internal nonReentrant returns (bool success, uint256 gasUsed) { - performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); - return forwarder.forward(performGas, performData); - } - - /** - * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases - * amount spent. - */ - function _postPerformPayment( - HotVars memory hotVars, - uint256 upkeepId, - UpkeepTransmitInfo memory upkeepTransmitInfo, - uint256 fastGasWei, - uint256 linkNative, - uint16 numBatchedUpkeeps - ) internal returns (uint96 gasReimbursement, uint96 premium) { - (gasReimbursement, premium) = _calculatePaymentAmount( - hotVars, - upkeepTransmitInfo.gasUsed, - upkeepTransmitInfo.gasOverhead, - fastGasWei, - linkNative, - numBatchedUpkeeps, - true - ); - - uint96 payment = gasReimbursement + premium; - s_upkeep[upkeepId].balance -= payment; - s_upkeep[upkeepId].amountSpent += payment; - - return (gasReimbursement, premium); - } - - /** - * @dev Caps the gas overhead by the constant overhead used within initial payment checks in order to - * prevent a revert in payment processing. - */ - function _getCappedGasOverhead( - uint256 calculatedGasOverhead, - Trigger triggerType, - uint32 performDataLength, - uint8 f - ) internal pure returns (uint256 cappedGasOverhead) { - cappedGasOverhead = _getMaxGasOverhead(triggerType, performDataLength, f); - if (calculatedGasOverhead < cappedGasOverhead) { - return calculatedGasOverhead; - } - return cappedGasOverhead; - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { - if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); - if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } - - /** - * @dev returns the current block number in a chain agnostic manner - */ - function _blockNum() internal view returns (uint256) { - if (i_mode == Mode.ARBITRUM) { - return ARB_SYS.arbBlockNumber(); - } else { - return block.number; - } - } - - /** - * @dev returns the blockhash of the provided block number in a chain agnostic manner - * @param n the blocknumber to retrieve the blockhash for - * @return blockhash the blockhash of block number n, or 0 if n is out queryable of range - */ - function _blockHash(uint256 n) internal view returns (bytes32) { - if (i_mode == Mode.ARBITRUM) { - uint256 blockNum = ARB_SYS.arbBlockNumber(); - if (n >= blockNum || blockNum - n > 256) { - return ""; - } - return ARB_SYS.arbBlockHash(n); - } else { - return blockhash(n); - } - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_hotVars.reentrancyGuard) revert ReentrantCall(); - s_hotVars.reentrancyGuard = true; - _; - s_hotVars.reentrancyGuard = false; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol deleted file mode 100644 index 517d14d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicA2_1.sol +++ /dev/null @@ -1,438 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; -import {KeeperRegistryLogicB2_1} from "./KeeperRegistryLogicB2_1.sol"; -import {Chainable} from "../Chainable.sol"; -import {AutomationForwarder} from "../AutomationForwarder.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; - -/** - * @notice Logic contract, works in tandem with KeeperRegistry as a proxy - */ -contract KeeperRegistryLogicA2_1 is KeeperRegistryBase2_1, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @param logicB the address of the second logic contract - */ - constructor( - KeeperRegistryLogicB2_1 logicB - ) - KeeperRegistryBase2_1( - logicB.getMode(), - logicB.getLinkAddress(), - logicB.getLinkNativeFeedAddress(), - logicB.getFastGasFeedAddress(), - logicB.getAutomationForwarderLogic() - ) - Chainable(address(logicB)) - {} - - /** - * @notice called by the automation DON to check if work is needed - * @param id the upkeep ID to check for work needed - * @param triggerData extra contextual data about the trigger (not used in all code paths) - * @dev this one of the core functions called in the hot path - * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility - * @dev there is an incongruency on what gets returned during failure modes - * ex sometimes we include price data, sometimes we omit it depending on the failure - */ - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - public - cannotExecute - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ) - { - Trigger triggerType = _getTriggerType(id); - HotVars memory hotVars = s_hotVars; - Upkeep memory upkeep = s_upkeep[id]; - - if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); - if (upkeep.maxValidBlocknumber != UINT32_MAX) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); - if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); - - (fastGasWei, linkNative) = _getFeedData(hotVars); - uint96 maxLinkPayment = _getMaxLinkPayment( - hotVars, - triggerType, - upkeep.performGas, - s_storage.maxPerformDataSize, - fastGasWei, - linkNative, - false - ); - if (upkeep.balance < maxLinkPayment) { - return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); - } - - bytes memory callData = _checkPayload(id, triggerType, triggerData); - - gasUsed = gasleft(); - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); - gasUsed = gasUsed - gasleft(); - - if (!success) { - // User's target check reverted. We capture the revert data here and pass it within performData - if (result.length > s_storage.maxRevertDataSize) { - return ( - false, - bytes(""), - UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - } - return ( - upkeepNeeded, - result, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - } - - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) - return ( - false, - bytes(""), - UpkeepFailureReason.UPKEEP_NOT_NEEDED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - - if (performData.length > s_storage.maxPerformDataSize) - return ( - false, - bytes(""), - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkNative); - } - - /** - * @notice see other checkUpkeep function for description - * @dev this function may be deprecated in a future version of chainlink automation - */ - function checkUpkeep( - uint256 id - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ) - { - return checkUpkeep(id, bytes("")); - } - - /** - * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) - * @param id the upkeepID to execute a callback for - * @param values the values returned from the data streams lookup - * @param extraData the user-provided extra context data - */ - function checkCallback( - uint256 id, - bytes[] memory values, - bytes calldata extraData - ) - external - cannotExecute - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); - return executeCallback(id, payload); - } - - /** - * @notice this is a generic callback executor that forwards a call to a user's contract with the configured - * gas limit - * @param id the upkeepID to execute a callback for - * @param payload the data (including function selector) to call on the upkeep target contract - */ - function executeCallback( - uint256 id, - bytes memory payload - ) - public - cannotExecute - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - Upkeep memory upkeep = s_upkeep[id]; - gasUsed = gasleft(); - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); - gasUsed = gasUsed - gasleft(); - if (!success) { - return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); - } - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) { - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); - } - if (performData.length > s_storage.maxPerformDataSize) { - return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); - } - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); - } - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param triggerType the trigger for the upkeep - * @param checkData data passed to the contract when checking for upkeep - * @param triggerConfig the config for the trigger - * @param offchainConfig arbitrary offchain config for the upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - Trigger triggerType, - bytes calldata checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) public returns (uint256 id) { - if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); - if (!target.isContract()) revert NotAContract(); - id = _createID(triggerType); - IAutomationForwarder forwarder = IAutomationForwarder( - address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) - ); - _createUpkeep( - id, - Upkeep({ - performGas: gasLimit, - balance: 0, - maxValidBlocknumber: UINT32_MAX, - lastPerformedBlockNumber: 0, - amountSpent: 0, - paused: false, - forwarder: forwarder - }), - admin, - checkData, - triggerConfig, - offchainConfig - ); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - emit UpkeepCheckDataSet(id, checkData); - emit UpkeepTriggerConfigSet(id, triggerConfig); - emit UpkeepOffchainConfigSet(id, offchainConfig); - return (id); - } - - /** - * @notice this function registers a conditional upkeep, using a backwards compatible function signature - * @dev this function is backwards compatible with versions <=2.0, but may be removed in a future version - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData, - bytes calldata offchainConfig - ) external returns (uint256 id) { - return registerUpkeep(target, gasLimit, admin, Trigger.CONDITION, checkData, bytes(""), offchainConfig); - } - - /** - * @notice cancels an upkeep - * @param id the upkeepID to cancel - * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to - * allow any pending performUpkeep txs time to get confirmed - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool canceled = upkeep.maxValidBlocknumber != UINT32_MAX; - bool isOwner = msg.sender == owner(); - - if (canceled && !(isOwner && upkeep.maxValidBlocknumber > _blockNum())) revert CannotCancel(); - if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); - - uint256 height = _blockNum(); - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minUpkeepSpend is not met - uint96 minUpkeepSpend = s_storage.minUpkeepSpend; - uint96 cancellationFee = 0; - // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) - if (upkeep.amountSpent < minUpkeepSpend) { - cancellationFee = minUpkeepSpend - upkeep.amountSpent; - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice adds fund to an upkeep - * @param id the upkeepID - * @param amount the amount of LINK to fund, in jules (jules = "wei" of LINK) - */ - function addFunds(uint256 id, uint96 amount) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - s_upkeep[id].balance = upkeep.balance + amount; - s_expectedLinkBalance = s_expectedLinkBalance + amount; - i_link.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice migrates upkeeps from one registry to another - * @param ids the upkeepIDs to migrate - * @param destination the destination registry address - * @dev a transcoder must be set in order to enable migration - * @dev migration permissions must be set on *both* sending and receiving registries - * @dev only an upkeep admin can migrate their upkeeps - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - uint256 id; - Upkeep memory upkeep; - uint256 totalBalanceRemaining; - address[] memory admins = new address[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - bytes[] memory checkDatas = new bytes[](ids.length); - bytes[] memory triggerConfigs = new bytes[](ids.length); - bytes[] memory offchainConfigs = new bytes[](ids.length); - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - _requireAdminAndNotCancelled(id); - upkeep.forwarder.updateRegistry(destination); - upkeeps[idx] = upkeep; - admins[idx] = s_upkeepAdmin[id]; - checkDatas[idx] = s_checkData[id]; - triggerConfigs[idx] = s_upkeepTriggerConfig[id]; - offchainConfigs[idx] = s_upkeepOffchainConfig[id]; - totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; - delete s_upkeep[id]; - delete s_checkData[id]; - delete s_upkeepTriggerConfig[id]; - delete s_upkeepOffchainConfig[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; - bytes memory encodedUpkeeps = abi.encode( - ids, - upkeeps, - new address[](ids.length), - admins, - checkDatas, - triggerConfigs, - offchainConfigs - ); - MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( - UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( - UPKEEP_VERSION_BASE, - MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), - encodedUpkeeps - ) - ); - i_link.transfer(destination, totalBalanceRemaining); - } - - /** - * @notice received upkeeps migrated from another registry - * @param encodedUpkeeps the raw upkeep data to import - * @dev this function is never called directly, it is only called by another registry's migrate function - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - ( - uint256[] memory ids, - Upkeep[] memory upkeeps, - address[] memory targets, - address[] memory upkeepAdmins, - bytes[] memory checkDatas, - bytes[] memory triggerConfigs, - bytes[] memory offchainConfigs - ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); - for (uint256 idx = 0; idx < ids.length; idx++) { - if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { - upkeeps[idx].forwarder = IAutomationForwarder( - address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) - ); - } - _createUpkeep( - ids[idx], - upkeeps[idx], - upkeepAdmins[idx], - checkDatas[idx], - triggerConfigs[idx], - offchainConfigs[idx] - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } - - /** - * @notice sets the upkeep trigger config - * @param id the upkeepID to change the trigger for - * @param triggerConfig the new trigger config - */ - function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { - _requireAdminAndNotCancelled(id); - s_upkeepTriggerConfig[id] = triggerConfig; - emit UpkeepTriggerConfigSet(id, triggerConfig); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol deleted file mode 100644 index 243d0ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/KeeperRegistryLogicB2_1.sol +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.16; - -import {KeeperRegistryBase2_1} from "./KeeperRegistryBase2_1.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -contract KeeperRegistryLogicB2_1 is KeeperRegistryBase2_1 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @dev see KeeperRegistry master contract for constructor description - */ - constructor( - Mode mode, - address link, - address linkNativeFeed, - address fastGasFeed, - address automationForwarderLogic - ) KeeperRegistryBase2_1(mode, link, linkNativeFeed, fastGasFeed, automationForwarderLogic) {} - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice transfers the address of an admin for an upkeep - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - _requireAdminAndNotCancelled(id); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of an upkeep admin - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = s_upkeepAdmin[id]; - s_upkeepAdmin[id] = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused - */ - function pauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @notice unpauses an upkeep - */ - function unpauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @notice updates the checkData for an upkeep - */ - function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { - _requireAdminAndNotCancelled(id); - if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataSet(id, newCheckData); - } - - /** - * @notice updates the gas limit for an upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - _requireAdminAndNotCancelled(id); - s_upkeep[id].performGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @notice updates the offchain config for an upkeep - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { - _requireAdminAndNotCancelled(id); - s_upkeepOffchainConfig[id] = config; - emit UpkeepOffchainConfigSet(id, config); - } - - /** - * @notice withdraws LINK funds from an upkeep - * @dev note that an upkeep must be cancelled first!! - */ - function withdrawFunds(uint256 id, address to) external nonReentrant { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > _blockNum()) revert UpkeepNotCanceled(); - uint96 amountToWithdraw = s_upkeep[id].balance; - s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; - s_upkeep[id].balance = 0; - i_link.transfer(to, amountToWithdraw); - emit FundsWithdrawn(id, amountToWithdraw, to); - } - - // ================================================================ - // | NODE MANAGEMENT | - // ================================================================ - - /** - * @notice transfers the address of payee for a transmitter - */ - function transferPayeeship(address transmitter, address proposed) external { - if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[transmitter] != proposed) { - s_proposedPayee[transmitter] = proposed; - emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of the payee - */ - function acceptPayeeship(address transmitter) external { - if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_transmitterPayees[transmitter]; - s_transmitterPayees[transmitter] = msg.sender; - s_proposedPayee[transmitter] = ZERO_ADDRESS; - - emit PayeeshipTransferred(transmitter, past, msg.sender); - } - - /** - * @notice withdraws LINK received as payment for work performed - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); - uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); - s_transmitters[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance - balance; - i_link.transfer(to, balance); - emit PaymentWithdrawn(from, balance, to, msg.sender); - } - - // ================================================================ - // | OWNER / MANAGER ACTIONS | - // ================================================================ - - /** - * @notice sets the privilege config for an upkeep - */ - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; - emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); - } - - /** - * @notice withdraws the owner's LINK balance - */ - function withdrawOwnerFunds() external onlyOwner { - uint96 amount = s_storage.ownerLinkBalance; - s_expectedLinkBalance = s_expectedLinkBalance - amount; - s_storage.ownerLinkBalance = 0; - emit OwnerFundsWithdrawn(amount); - i_link.transfer(msg.sender, amount); - } - - /** - * @notice allows the owner to withdraw any LINK accidentally sent to the contract - */ - function recoverFunds() external onlyOwner { - uint256 total = i_link.balanceOf(address(this)); - i_link.transfer(msg.sender, total - s_expectedLinkBalance); - } - - /** - * @notice sets the payees for the transmitters - */ - function setPayees(address[] calldata payees) external onlyOwner { - if (s_transmittersList.length != payees.length) revert ParameterLengthError(); - for (uint256 i = 0; i < s_transmittersList.length; i++) { - address transmitter = s_transmittersList[i]; - address oldPayee = s_transmitterPayees[transmitter]; - address newPayee = payees[i]; - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) revert InvalidPayee(); - if (newPayee != IGNORE_ADDRESS) { - s_transmitterPayees[transmitter] = newPayee; - } - } - emit PayeesUpdated(s_transmittersList, payees); - } - - /** - * @notice sets the migration permission for a peer registry - * @dev this must be done before upkeeps can be migrated to/from another registry - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @notice pauses the entire registry - */ - function pause() external onlyOwner { - s_hotVars.paused = true; - emit Paused(msg.sender); - } - - /** - * @notice unpauses the entire registry - */ - function unpause() external onlyOwner { - s_hotVars.paused = false; - emit Unpaused(msg.sender); - } - - /** - * @notice sets a generic bytes field used to indicate the privilege that this admin address had - * @param admin the address to set privilege for - * @param newPrivilegeConfig the privileges that this admin has - */ - function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - s_adminPrivilegeConfig[admin] = newPrivilegeConfig; - emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - function getConditionalGasOverhead() external pure returns (uint256) { - return REGISTRY_CONDITIONAL_OVERHEAD; - } - - function getLogGasOverhead() external pure returns (uint256) { - return REGISTRY_LOG_OVERHEAD; - } - - function getPerPerformByteGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; - } - - function getPerSignerGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_SIGNER_GAS_OVERHEAD; - } - - function getCancellationDelay() external pure returns (uint256) { - return CANCELLATION_DELAY; - } - - function getMode() external view returns (Mode) { - return i_mode; - } - - function getLinkAddress() external view returns (address) { - return address(i_link); - } - - function getLinkNativeFeedAddress() external view returns (address) { - return address(i_linkNativeFeed); - } - - function getFastGasFeedAddress() external view returns (address) { - return address(i_fastGasFeed); - } - - function getAutomationForwarderLogic() external view returns (address) { - return i_automationForwarderLogic; - } - - function upkeepTranscoderVersion() public pure returns (UpkeepFormat) { - return UPKEEP_TRANSCODER_VERSION_BASE; - } - - function upkeepVersion() public pure returns (uint8) { - return UPKEEP_VERSION_BASE; - } - - /** - * @notice read all of the details about an upkeep - * @dev this function may be deprecated in a future version of automation in favor of individual - * getters for each field - */ - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { - Upkeep memory reg = s_upkeep[id]; - address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); - upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ - target: target, - performGas: reg.performGas, - checkData: s_checkData[id], - balance: reg.balance, - admin: s_upkeepAdmin[id], - maxValidBlocknumber: reg.maxValidBlocknumber, - lastPerformedBlockNumber: reg.lastPerformedBlockNumber, - amountSpent: reg.amountSpent, - paused: reg.paused, - offchainConfig: s_upkeepOffchainConfig[id] - }); - return upkeepInfo; - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { - uint256 numUpkeeps = s_upkeepIDs.length(); - if (startIndex >= numUpkeeps) revert IndexOutOfRange(); - uint256 endIndex = startIndex + maxCount; - endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; - uint256[] memory ids = new uint256[](endIndex - startIndex); - for (uint256 idx = 0; idx < ids.length; idx++) { - ids[idx] = s_upkeepIDs.at(idx + startIndex); - } - return ids; - } - - /** - * @notice returns the upkeep's trigger type - */ - function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { - return _getTriggerType(upkeepId); - } - - /** - * @notice returns the trigger config for an upkeeep - */ - function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { - return s_upkeepTriggerConfig[upkeepId]; - } - - /** - * @notice read the current info about any transmitter address - */ - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { - Transmitter memory transmitter = s_transmitters[query]; - - uint96 pooledShare = 0; - if (transmitter.active) { - uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; - pooledShare = totalDifference / uint96(s_transmittersList.length); - } - - return ( - transmitter.active, - transmitter.index, - (transmitter.balance + pooledShare), - transmitter.lastCollected, - s_transmitterPayees[query] - ); - } - - /** - * @notice read the current info about any signer address - */ - function getSignerInfo(address query) external view returns (bool active, uint8 index) { - Signer memory signer = s_signers[query]; - return (signer.active, signer.index); - } - - /** - * @notice read the current state of the registry - */ - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) - { - state = IAutomationV21PlusCommon.StateLegacy({ - nonce: s_storage.nonce, - ownerLinkBalance: s_storage.ownerLinkBalance, - expectedLinkBalance: s_expectedLinkBalance, - totalPremium: s_hotVars.totalPremium, - numUpkeeps: s_upkeepIDs.length(), - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - latestConfigDigest: s_latestConfigDigest, - latestEpoch: s_hotVars.latestEpoch, - paused: s_hotVars.paused - }); - - config = IAutomationV21PlusCommon.OnchainConfigLegacy({ - paymentPremiumPPB: s_hotVars.paymentPremiumPPB, - flatFeeMicroLink: s_hotVars.flatFeeMicroLink, - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - minUpkeepSpend: s_storage.minUpkeepSpend, - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager - }); - - return (state, config, s_signersList, s_transmittersList, s_hotVars.f); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getBalance(uint256 id) external view returns (uint96 balance) { - return s_upkeep[id].balance; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalance(uint256 id) external view returns (uint96) { - return getMinBalanceForUpkeep(id); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - * @dev this will be deprecated in a future version in favor of getMinBalance - */ - function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { - return getMaxPaymentForGas(_getTriggerType(id), s_upkeep[id].performGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas(Trigger triggerType, uint32 gasLimit) public view returns (uint96 maxPayment) { - HotVars memory hotVars = s_hotVars; - (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); - return - _getMaxLinkPayment(hotVars, triggerType, gasLimit, s_storage.maxPerformDataSize, fastGasWei, linkNative, false); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { - return s_upkeepPrivilegeConfig[upkeepId]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { - return s_adminPrivilegeConfig[admin]; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { - return s_upkeep[upkeepID].forwarder; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function hasDedupKey(bytes32 dedupKey) external view returns (bool) { - return s_dedupKeys[dedupKey]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE deleted file mode 100644 index f60ab65..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/LICENSE +++ /dev/null @@ -1,56 +0,0 @@ -Business Source License 1.1 - -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ---- - -Parameters - -Licensor: SmartContract Chainlink Limited SEZC - -Licensed Work: Automation v2.1 -The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC - -Additional Use Grant: Any uses listed and defined at https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md - - -Change Date: September 12, 2027 - -Change License: MIT - ---- - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. - -If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. - -MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. - ---- - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. - -2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md deleted file mode 100644 index 43c71da..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Automation Contract Structure - -The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. It is also too large to fit into 2 contracts, a solution that works for most large projects. Therefore, we included this explanation of how the pieces fit together and various tradeoffs incurred. - -### Glossary - -**Master Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the entry-point into the chain of delegatecalls. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) - -**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the master contract in order to increase our total capacity for on-chain code. - -### Overview - -We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fall back to the next, always executing the function in the scope of the master contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. - -### Diagram - -```mermaid -graph LR - Master -- delegatecall --> la[Logic A] - la -- delegatecall --> lb[Logic B] - lb -. delegatecall .-> lx[Logic X] -``` - -### Special Considerations - -- functions on the master contract have the least gas overhead, therefore, our most price-sensitive functions live there -- functions on the master contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there -- etherscan supports executing logic contract functions that are once removed from the master - therefore we give secondary preference to the first logic contract for user and debugging functions -- functions on logic A through logic X (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically -- We use Logic A, B, C... to avoid confusion with the version ex `KeeperRegistryLogicA2_1.sol` --> Logic Contract A verion 2.1 -- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break - -### Master Interface - -The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. This process is not a hardened one. Users of this script should take great care to ensure it's efficacy. - -[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 -[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function -[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries -[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol deleted file mode 100644 index 53b681d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_1/UpkeepTranscoder4_0.sol +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 - -pragma solidity 0.8.16; - -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {KeeperRegistryBase2_1 as R21} from "./KeeperRegistryBase2_1.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; - -enum RegistryVersion { - V12, - V13, - V20, - V21 -} - -/** - * @dev structs copied directly from source (can't import without changing the contract version) - */ -struct UpkeepV12 { - uint96 balance; - address lastKeeper; - uint32 executeGas; - uint64 maxValidBlocknumber; - address target; - uint96 amountSpent; - address admin; -} - -struct UpkeepV13 { - uint96 balance; - address lastKeeper; - uint96 amountSpent; - address admin; - uint32 executeGas; - uint32 maxValidBlocknumber; - address target; - bool paused; -} - -struct UpkeepV20 { - uint32 executeGas; - uint32 maxValidBlocknumber; - bool paused; - address target; - uint96 amountSpent; - uint96 balance; - uint32 lastPerformedBlockNumber; -} - -/** - * @notice UpkeepTranscoder allows converting upkeep data from previous keeper registry versions 1.2, 1.3, and - * 2.0 to registry 2.1 - */ -contract UpkeepTranscoder4_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { - error InvalidTranscoding(); - - /** - * @notice versions: - * - UpkeepTranscoder 4.0.0: adds support for registry 2.1; adds support for offchainConfigs - * - UpkeepTranscoder 3.0.0: works with registry 2.0; adds temporary workaround for UpkeepFormat enum bug - */ - string public constant override typeAndVersion = "UpkeepTranscoder 4.0.0"; - uint32 internal constant UINT32_MAX = type(uint32).max; - IAutomationForwarder internal constant ZERO_FORWARDER = IAutomationForwarder(address(0)); - - /** - * @notice transcodeUpkeeps transforms upkeep data from the format expected by - * one registry to the format expected by another. It future-proofs migrations - * by allowing keepers team to customize migration paths and set sensible defaults - * when new fields are added - * @param fromVersion struct version the upkeep is migrating from - * @param encodedUpkeeps encoded upkeep data - * @dev this transcoder should ONLY be use for V1/V2 --> V3 migrations - * @dev this transcoder **ignores** the toVersion param, as it assumes all migrations are - * for the V3 version. Therefore, it is the responsibility of the deployer of this contract - * to ensure it is not used in any other migration paths. - */ - function transcodeUpkeeps( - uint8 fromVersion, - uint8, - bytes calldata encodedUpkeeps - ) external view override returns (bytes memory) { - // v1.2 => v2.1 - if (fromVersion == uint8(RegistryVersion.V12)) { - (uint256[] memory ids, UpkeepV12[] memory upkeepsV12, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], UpkeepV12[], bytes[]) - ); - if (ids.length != upkeepsV12.length || ids.length != checkDatas.length) { - revert InvalidTranscoding(); - } - address[] memory targets = new address[](ids.length); - address[] memory admins = new address[](ids.length); - R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); - UpkeepV12 memory upkeepV12; - for (uint256 idx = 0; idx < ids.length; idx++) { - upkeepV12 = upkeepsV12[idx]; - newUpkeeps[idx] = R21.Upkeep({ - performGas: upkeepV12.executeGas, - maxValidBlocknumber: UINT32_MAX, // maxValidBlocknumber is uint64 in V1, hence a new default value is provided - paused: false, // migrated upkeeps are not paused by default - forwarder: ZERO_FORWARDER, - amountSpent: upkeepV12.amountSpent, - balance: upkeepV12.balance, - lastPerformedBlockNumber: 0 - }); - targets[idx] = upkeepV12.target; - admins[idx] = upkeepV12.admin; - } - return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, new bytes[](ids.length), new bytes[](ids.length)); - } - // v1.3 => v2.1 - if (fromVersion == uint8(RegistryVersion.V13)) { - (uint256[] memory ids, UpkeepV13[] memory upkeepsV13, bytes[] memory checkDatas) = abi.decode( - encodedUpkeeps, - (uint256[], UpkeepV13[], bytes[]) - ); - if (ids.length != upkeepsV13.length || ids.length != checkDatas.length) { - revert InvalidTranscoding(); - } - address[] memory targets = new address[](ids.length); - address[] memory admins = new address[](ids.length); - R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); - UpkeepV13 memory upkeepV13; - for (uint256 idx = 0; idx < ids.length; idx++) { - upkeepV13 = upkeepsV13[idx]; - newUpkeeps[idx] = R21.Upkeep({ - performGas: upkeepV13.executeGas, - maxValidBlocknumber: upkeepV13.maxValidBlocknumber, - paused: upkeepV13.paused, - forwarder: ZERO_FORWARDER, - amountSpent: upkeepV13.amountSpent, - balance: upkeepV13.balance, - lastPerformedBlockNumber: 0 - }); - targets[idx] = upkeepV13.target; - admins[idx] = upkeepV13.admin; - } - return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, new bytes[](ids.length), new bytes[](ids.length)); - } - // v2.0 => v2.1 - if (fromVersion == uint8(RegistryVersion.V20)) { - (uint256[] memory ids, UpkeepV20[] memory upkeepsV20, bytes[] memory checkDatas, address[] memory admins) = abi - .decode(encodedUpkeeps, (uint256[], UpkeepV20[], bytes[], address[])); - if (ids.length != upkeepsV20.length || ids.length != checkDatas.length) { - revert InvalidTranscoding(); - } - // bit of a hack - transcodeUpkeeps should be a pure function - R21.Upkeep[] memory newUpkeeps = new R21.Upkeep[](ids.length); - bytes[] memory emptyBytes = new bytes[](ids.length); - address[] memory targets = new address[](ids.length); - UpkeepV20 memory upkeepV20; - for (uint256 idx = 0; idx < ids.length; idx++) { - upkeepV20 = upkeepsV20[idx]; - newUpkeeps[idx] = R21.Upkeep({ - performGas: upkeepV20.executeGas, - maxValidBlocknumber: upkeepV20.maxValidBlocknumber, - paused: upkeepV20.paused, - forwarder: ZERO_FORWARDER, - amountSpent: upkeepV20.amountSpent, - balance: upkeepV20.balance, - lastPerformedBlockNumber: 0 - }); - targets[idx] = upkeepV20.target; - } - return abi.encode(ids, newUpkeeps, targets, admins, checkDatas, emptyBytes, emptyBytes); - } - // v2.1 => v2.1 - if (fromVersion == uint8(RegistryVersion.V21)) { - return encodedUpkeeps; - } - - revert InvalidTranscoding(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol deleted file mode 100644 index 464e874..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistry2_2.sol +++ /dev/null @@ -1,416 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; -import {AutomationRegistryLogicB2_2} from "./AutomationRegistryLogicB2_2.sol"; -import {Chainable} from "../Chainable.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; - -/** - * @notice Registry for adding work for Chainlink nodes to perform on client - * contracts. Clients must support the AutomationCompatibleInterface interface. - */ -contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chainable, IERC677Receiver { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @notice versions: - * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module - * KeeperRegistry 2.1.0: introduces support for log triggers - * removes the need for "wrapped perform data" - * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts - * fixes issue with arbitrum block number - * does an early return in case of stale report instead of revert - * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X - * KeeperRegistry 2.0.0: implement OCR interface - * KeeperRegistry 1.3.0: split contract into Proxy and Logic - * account for Arbitrum and Optimism L1 gas fee - * allow users to configure upkeeps - * KeeperRegistry 1.2.0: allow funding within performUpkeep - * allow configurable registry maxPerformGas - * add function to let admin change upkeep gas limit - * add minUpkeepSpend requirement - * upgrade to solidity v0.8 - * KeeperRegistry 1.1.0: added flatFeeMicroLink - * KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "AutomationRegistry 2.2.0"; - - /** - * @param logicA the address of the first logic contract, but cast as logicB in order to call logicB functions - */ - constructor( - AutomationRegistryLogicB2_2 logicA - ) - AutomationRegistryBase2_2( - logicA.getLinkAddress(), - logicA.getLinkNativeFeedAddress(), - logicA.getFastGasFeedAddress(), - logicA.getAutomationForwarderLogic(), - logicA.getAllowedReadOnlyAddress() - ) - Chainable(address(logicA)) - {} - - /** - * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors - */ - // solhint-disable-next-line gas-struct-packing - struct TransmitVars { - uint16 numUpkeepsPassedChecks; - uint256 totalCalldataWeight; - uint96 totalReimbursement; - uint96 totalPremium; - } - - // ================================================================ - // | ACTIONS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function transmit( - bytes32[3] calldata reportContext, - bytes calldata rawReport, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external override { - uint256 gasOverhead = gasleft(); - HotVars memory hotVars = s_hotVars; - - if (hotVars.paused) revert RegistryPaused(); - if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); - - // Verify signatures - if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); - if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); - _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); - - Report memory report = _decodeReport(rawReport); - - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - - _handleReport(hotVars, report, gasOverhead); - - if (epoch > hotVars.latestEpoch) { - s_hotVars.latestEpoch = epoch; - } - } - - function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private { - UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); - TransmitVars memory transmitVars = TransmitVars({ - numUpkeepsPassedChecks: 0, - totalCalldataWeight: 0, - totalReimbursement: 0, - totalPremium: 0 - }); - - uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); - - 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( - report.upkeepIds[i], - blocknumber, - report.triggers[i], - upkeepTransmitInfo[i], - hotVars - ); - - if (upkeepTransmitInfo[i].earlyChecksPassed) { - transmitVars.numUpkeepsPassedChecks += 1; - } else { - continue; - } - - // Actually perform the target upkeep - (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( - upkeepTransmitInfo[i].upkeep.forwarder, - report.gasLimits[i], - 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 (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 - gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD; - gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; - - { - uint96 reimbursement; - uint96 premium; - for (uint256 i = 0; i < report.upkeepIds.length; i++) { - if (upkeepTransmitInfo[i].earlyChecksPassed) { - (reimbursement, premium) = _postPerformPayment( - hotVars, - report.upkeepIds[i], - upkeepTransmitInfo[i].gasUsed, - report.fastGasWei, - report.linkNative, - gasOverhead, - (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight - ); - transmitVars.totalPremium += premium; - transmitVars.totalReimbursement += reimbursement; - - emit UpkeepPerformed( - report.upkeepIds[i], - upkeepTransmitInfo[i].performSuccess, - reimbursement + premium, - upkeepTransmitInfo[i].gasUsed, - gasOverhead, - report.triggers[i] - ); - } - } - } - // record payments - s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; - s_hotVars.totalPremium += transmitVars.totalPremium; - } - - /** - * @notice simulates the upkeep with the perform data returned from checkUpkeep - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - * @return success whether the call reverted or not - * @return gasUsed the amount of gas the target contract consumed - */ - function simulatePerformUpkeep( - uint256 id, - bytes calldata performData - ) external returns (bool success, uint256 gasUsed) { - _preventExecution(); - - if (s_hotVars.paused) revert RegistryPaused(); - Upkeep memory upkeep = s_upkeep[id]; - (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); - return (success, gasUsed); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_expectedLinkBalance = s_expectedLinkBalance + amount; - emit FundsAdded(id, sender, uint96(amount)); - } - - // ================================================================ - // | SETTERS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override { - setConfigTypeSafe( - signers, - transmitters, - f, - abi.decode(onchainConfigBytes, (OnchainConfig)), - offchainConfigVersion, - offchainConfig - ); - } - - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) public onlyOwner { - if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); - if (f == 0) revert IncorrectNumberOfFaultyOracles(); - if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); - - // move all pooled payments out of the pool to each transmitter's balance - uint96 totalPremium = s_hotVars.totalPremium; - uint96 oldLength = uint96(s_transmittersList.length); - for (uint256 i = 0; i < oldLength; i++) { - _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, oldLength); - } - - // remove any old signer/transmitter addresses - address signerAddress; - address transmitterAddress; - for (uint256 i = 0; i < oldLength; i++) { - signerAddress = s_signersList[i]; - transmitterAddress = s_transmittersList[i]; - delete s_signers[signerAddress]; - // Do not delete the whole transmitter struct as it has balance information stored - s_transmitters[transmitterAddress].active = false; - } - delete s_signersList; - delete s_transmittersList; - - // add new signer/transmitter addresses - { - Transmitter memory transmitter; - address temp; - for (uint256 i = 0; i < signers.length; i++) { - if (s_signers[signers[i]].active) revert RepeatedSigner(); - if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); - s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); - - temp = transmitters[i]; - if (temp == ZERO_ADDRESS) revert InvalidTransmitter(); - transmitter = s_transmitters[temp]; - if (transmitter.active) revert RepeatedTransmitter(); - transmitter.active = true; - transmitter.index = uint8(i); - // new transmitters start afresh from current totalPremium - // some spare change of premium from previous pool will be forfeited - transmitter.lastCollected = totalPremium; - s_transmitters[temp] = transmitter; - } - } - s_signersList = signers; - s_transmittersList = transmitters; - - s_hotVars = HotVars({ - f: f, - paymentPremiumPPB: onchainConfig.paymentPremiumPPB, - flatFeeMicroLink: onchainConfig.flatFeeMicroLink, - stalenessSeconds: onchainConfig.stalenessSeconds, - gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, - paused: s_hotVars.paused, - reentrancyGuard: s_hotVars.reentrancyGuard, - totalPremium: totalPremium, - latestEpoch: 0, // DON restarts epoch - reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, - chainModule: onchainConfig.chainModule - }); - - s_storage = Storage({ - checkGasLimit: onchainConfig.checkGasLimit, - minUpkeepSpend: onchainConfig.minUpkeepSpend, - maxPerformGas: onchainConfig.maxPerformGas, - transcoder: onchainConfig.transcoder, - maxCheckDataSize: onchainConfig.maxCheckDataSize, - maxPerformDataSize: onchainConfig.maxPerformDataSize, - maxRevertDataSize: onchainConfig.maxRevertDataSize, - upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, - nonce: s_storage.nonce, - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - ownerLinkBalance: s_storage.ownerLinkBalance - }); - s_fallbackGasPrice = onchainConfig.fallbackGasPrice; - s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; - - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - s_storage.latestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); - s_storage.configCount += 1; - - bytes memory onchainConfigBytes = abi.encode(onchainConfig); - - s_latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - - for (uint256 idx = 0; idx < s_registrars.length(); idx++) { - s_registrars.remove(s_registrars.at(idx)); - } - - for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { - s_registrars.add(onchainConfig.registrars[idx]); - } - - emit ConfigSet( - previousConfigBlockNumber, - s_latestConfigDigest, - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); - } - - /** - * @inheritdoc OCR2Abstract - */ - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_latestConfigDigest, s_hotVars.latestEpoch); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol deleted file mode 100644 index 6903f55..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryBase2_2.sol +++ /dev/null @@ -1,861 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; -import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * AutomationRegistry and AutomationRegistryLogic - * @dev all errors, events, and internal functions should live here - */ -// solhint-disable-next-line max-states-count -abstract contract AutomationRegistryBase2_2 is ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; - bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; - uint32 internal constant UINT32_MAX = type(uint32).max; - uint96 internal constant LINK_TOTAL_SUPPLY = 1e27; - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - /** - * @dev UPKEEP_TRANSCODER_VERSION_BASE is temporary necessity for backwards compatibility with - * MigratableAutomationRegistryInterfaceV1 - it should be removed in future versions in favor of - * UPKEEP_VERSION_BASE and MigratableAutomationRegistryInterfaceV2 - */ - UpkeepFormat internal constant UPKEEP_TRANSCODER_VERSION_BASE = UpkeepFormat.V1; - uint8 internal constant UPKEEP_VERSION_BASE = 3; - - // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation - // These values are calibrated using hardhat tests which simulates various cases and verifies that - // the variables result in accurate estimation - uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 60_000; // Fixed gas overhead for conditional upkeeps - uint256 internal constant REGISTRY_LOG_OVERHEAD = 85_000; // Fixed gas overhead for log upkeeps - uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f - uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead - - // The overhead (in bytes) in addition to perform data for upkeep sent in calldata - // This includes overhead for all struct encoding as well as report signatures - // There is a fixed component and a per signer component. This is calculated exactly by doing abi encoding - uint256 internal constant TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD = 932; - uint256 internal constant TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD = 64; - - // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the - // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants - // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that - // the variables result in accurate estimation - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 22_000; // Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 7_000; // Overhead per upkeep performed in batch - - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_linkNativeFeed; - AggregatorV3Interface internal immutable i_fastGasFeed; - address internal immutable i_automationForwarderLogic; - address internal immutable i_allowedReadOnlyAddress; - - /** - * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit - * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path - */ - - // Upkeep storage - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit - mapping(uint256 => address) internal s_upkeepAdmin; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - mapping(bytes32 => bool) internal s_dedupKeys; - // Registry config and state - EnumerableSet.AddressSet internal s_registrars; - mapping(address => Transmitter) internal s_transmitters; - mapping(address => Signer) internal s_signers; - address[] internal s_signersList; // s_signersList contains the signing address of each oracle - address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle - mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. - mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter - bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification - HotVars internal s_hotVars; // Mixture of config and state, used in transmit - Storage internal s_storage; // Mixture of config and state, not used in transmit - uint256 internal s_fallbackGasPrice; - uint256 internal s_fallbackLinkPrice; - uint256 internal s_expectedLinkBalance; // Used in case of erroneous LINK transfers to contract - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro - mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers - mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep - mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep - mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin - - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InvalidDataLength(); - error InvalidTrigger(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidTransmitter(); - error InvalidTriggerType(); - error MaxCheckDataSizeCanOnlyIncrease(); - error MaxPerformDataSizeCanOnlyIncrease(); - error MigrationNotPermitted(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error PaymentGreaterThanAllLINK(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum Trigger { - CONDITION, - LOG - } - - enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, - CALLBACK_REVERTED, - REVERT_DATA_EXCEEDS_LIMIT, - REGISTRY_PAUSED - } - - /** - * @notice OnchainConfig of the registry - * @dev used only in setConfig() - * @member paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @member flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member minUpkeepSpend minimum LINK that an upkeep must spend before cancelling - * @member maxPerformGas max performGas allowed for an upkeep on this registry - * @member maxCheckDataSize max length of checkData bytes - * @member maxPerformDataSize max length of performData bytes - * @member maxRevertDataSize max length of revertData bytes - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrars addresses of the registrar contracts - * @member upkeepPrivilegeManager address which can set privilege for upkeeps - * @member reorgProtectionEnabled if this registry enables re-org protection checks - * @member chainModule the chain specific module - */ - // solhint-disable-next-line gas-struct-packing - struct OnchainConfig { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - uint96 minUpkeepSpend; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - address transcoder; - address[] registrars; - address upkeepPrivilegeManager; - IChainModule chainModule; - bool reorgProtectionEnabled; - } - - /** - * @notice relevant state of an upkeep which is used in transmit function - * @member paused if this upkeep has been paused - * @member performGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member forwarder the forwarder contract to use for this upkeep - * @member amountSpent the amount this upkeep has spent - * @member balance the balance of this upkeep - * @member lastPerformedBlockNumber the last block number when this upkeep was performed - */ - struct Upkeep { - bool paused; - uint32 performGas; - uint32 maxValidBlocknumber; - IAutomationForwarder forwarder; - // 0 bytes left in 1st EVM word - not written to in transmit - uint96 amountSpent; - uint96 balance; - uint32 lastPerformedBlockNumber; - // 2 bytes left in 2nd EVM word - written in transmit path - } - - /// @dev Config + State storage struct which is on hot transmit path - struct HotVars { - uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium - uint32 paymentPremiumPPB; // │ premium percentage charged to user over tx cost - uint32 flatFeeMicroLink; // │ flat fee charged to user for every perform - uint32 latestEpoch; // │ latest epoch for which a report was transmitted - uint24 stalenessSeconds; // │ Staleness tolerance for feeds - uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound - uint8 f; // │ maximum number of faulty oracles - bool paused; // │ pause switch for all upkeeps in the registry - bool reentrancyGuard; // ────────╯ guard against reentrancy - bool reorgProtectionEnabled; // if this registry should enable re-org protection mechanism - IChainModule chainModule; // the interface of chain specific module - } - - /// @dev Config + State storage struct which is not on hot transmit path - struct Storage { - uint96 minUpkeepSpend; // Minimum amount an upkeep must spend - address transcoder; // Address of transcoder contract used in migrations - // 1 EVM word full - uint96 ownerLinkBalance; // Balance of owner, accumulates minUpkeepSpend in case it is not spent - uint32 checkGasLimit; // Gas limit allowed in checkUpkeep - uint32 maxPerformGas; // Max gas an upkeep can use on this registry - uint32 nonce; // Nonce for each upkeep created - uint32 configCount; // incremented each time a new config is posted, The count - // is incorporated into the config digest to prevent replay attacks. - uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs - // 2 EVM word full - uint32 maxCheckDataSize; // max length of checkData bytes - uint32 maxPerformDataSize; // max length of performData bytes - uint32 maxRevertDataSize; // max length of revertData bytes - address upkeepPrivilegeManager; // address which can set privilege for upkeeps - // 3 EVM word full - } - - /// @dev Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkNative; - uint256[] upkeepIds; - uint256[] gasLimits; - bytes[] triggers; - bytes[] performDatas; - } - - /** - * @dev This struct is used to maintain run time information about an upkeep in transmit function - * @member upkeep the upkeep struct - * @member earlyChecksPassed whether the upkeep passed early checks before perform - * @member performSuccess whether the perform was successful - * @member triggerType the type of trigger - * @member gasUsed gasUsed by this upkeep in perform - * @member calldataWeight weight assigned to this upkeep for its contribution to calldata. It is used to split L1 fee - * @member dedupID unique ID used to dedup an upkeep/trigger combo - */ - struct UpkeepTransmitInfo { - Upkeep upkeep; - bool earlyChecksPassed; - bool performSuccess; - Trigger triggerType; - uint256 gasUsed; - uint256 calldataWeight; - bytes32 dedupID; - } - - struct Transmitter { - bool active; - uint8 index; // Index of oracle in s_signersList/s_transmittersList - uint96 balance; - uint96 lastCollected; - } - - struct Signer { - bool active; - // Index of oracle in s_signersList/s_transmittersList - uint8 index; - } - - /** - * @notice the trigger structure conditional trigger type - */ - struct ConditionalTrigger { - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the trigger structure of log upkeeps - * @dev NOTE that blockNum / blockHash describe the block used for the callback, - * not necessarily the block number that the log was emitted in!!!! - */ - struct LogTrigger { - bytes32 logBlockHash; - bytes32 txHash; - uint32 logIndex; - uint32 blockNum; - bytes32 blockHash; - } - - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event OwnerFundsWithdrawn(uint96 amount); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - event Unpaused(address account); - - /** - * @param link address of the LINK Token - * @param linkNativeFeed address of the LINK/Native price feed - * @param fastGasFeed address of the Fast Gas price feed - * @param automationForwarderLogic the address of automation forwarder logic - * @param allowedReadOnlyAddress the address of the allowed read only address - */ - constructor( - address link, - address linkNativeFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress - ) ConfirmedOwner(msg.sender) { - i_link = LinkTokenInterface(link); - i_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); - i_fastGasFeed = AggregatorV3Interface(fastGasFeed); - i_automationForwarderLogic = automationForwarderLogic; - i_allowedReadOnlyAddress = allowedReadOnlyAddress; - } - - // ================================================================ - // | INTERNAL FUNCTIONS ONLY | - // ================================================================ - - /** - * @dev creates a new upkeep with the given fields - * @param id the id of the upkeep - * @param upkeep the upkeep to create - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data which is passed to user's checkUpkeep - * @param triggerConfig the trigger config for this upkeep - * @param offchainConfig the off-chain config of this upkeep - */ - function _createUpkeep( - uint256 id, - Upkeep memory upkeep, - address admin, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) internal { - if (s_hotVars.paused) revert RegistryPaused(); - if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) - revert GasLimitOutsideRange(); - if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); - s_upkeep[id] = upkeep; - s_upkeepAdmin[id] = admin; - s_checkData[id] = checkData; - s_expectedLinkBalance = s_expectedLinkBalance + upkeep.balance; - s_upkeepTriggerConfig[id] = triggerConfig; - s_upkeepOffchainConfig[id] = offchainConfig; - s_upkeepIDs.add(id); - } - - /** - * @dev creates an ID for the upkeep based on the upkeep's type - * @dev the format of the ID looks like this: - * ****00000000000X**************** - * 4 bytes of entropy - * 11 bytes of zeros - * 1 identifying byte for the trigger type - * 16 bytes of entropy - * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique - * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only - * see the first 4 and last 4 hex values ex 0x1234...ABCD - */ - function _createID(Trigger triggerType) internal view returns (uint256) { - bytes1 empty; - IChainModule chainModule = s_hotVars.chainModule; - bytes memory idBytes = abi.encodePacked( - keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) - ); - for (uint256 idx = 4; idx < 15; idx++) { - idBytes[idx] = empty; - } - idBytes[15] = bytes1(uint8(triggerType)); - return uint256(bytes32(idBytes)); - } - - /** - * @dev retrieves feed data for fast gas/native and link/native prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData(HotVars memory hotVars) internal view returns (uint256 gasWei, uint256 linkNative) { - uint32 stalenessSeconds = hotVars.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = i_linkNativeFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - linkNative = s_fallbackLinkPrice; - } else { - linkNative = uint256(feedValue); - } - return (gasWei, linkNative); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @param gasLimit the amount of gas used - * @param gasOverhead the amount of gas overhead - * @param l1CostWei the amount to be charged for L1 fee in wei - * @param fastGasWei the fast gas price - * @param linkNative the exchange ratio between LINK and Native token - * @param isExecution if this is triggered by a perform upkeep function - */ - function _calculatePaymentAmount( - HotVars memory hotVars, - uint256 gasLimit, - uint256 gasOverhead, - uint256 l1CostWei, - uint256 fastGasWei, - uint256 linkNative, - bool isExecution - ) internal view returns (uint96, uint96) { - uint256 gasWei = fastGasWei * hotVars.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (isExecution && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - uint256 gasPayment = ((gasWei * (gasLimit + gasOverhead) + l1CostWei) * 1e18) / linkNative; - uint256 premium = (((gasWei * gasLimit) + l1CostWei) * 1e9 * hotVars.paymentPremiumPPB) / - linkNative + - uint256(hotVars.flatFeeMicroLink) * - 1e12; - // LINK_TOTAL_SUPPLY < UINT96_MAX - if (gasPayment + premium > LINK_TOTAL_SUPPLY) revert PaymentGreaterThanAllLINK(); - return (uint96(gasPayment), uint96(premium)); - } - - /** - * @dev calculates the max LINK payment for an upkeep. Called during checkUpkeep simulation and assumes - * maximum gas overhead, L1 fee - */ - function _getMaxLinkPayment( - HotVars memory hotVars, - Trigger triggerType, - uint32 performGas, - uint256 fastGasWei, - uint256 linkNative - ) internal view returns (uint96) { - uint256 maxGasOverhead; - if (triggerType == Trigger.CONDITION) { - maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; - } else if (triggerType == Trigger.LOG) { - maxGasOverhead = REGISTRY_LOG_OVERHEAD; - } else { - revert InvalidTriggerType(); - } - uint256 maxCalldataSize = s_storage.maxPerformDataSize + - TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + - (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); - (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) = s_hotVars.chainModule.getGasOverhead(); - maxGasOverhead += - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + - ((REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD + chainModulePerByteOverhead) * maxCalldataSize) + - chainModuleFixedOverhead; - - uint256 maxL1Fee = hotVars.gasCeilingMultiplier * hotVars.chainModule.getMaxL1Fee(maxCalldataSize); - - (uint96 reimbursement, uint96 premium) = _calculatePaymentAmount( - hotVars, - performGas, - maxGasOverhead, - maxL1Fee, - fastGasWei, - linkNative, - false //isExecution - ); - - return reimbursement + premium; - } - - /** - * @dev move a transmitter's balance from total pool to withdrawable balance - */ - function _updateTransmitterBalanceFromPool( - address transmitterAddress, - uint96 totalPremium, - uint96 payeeCount - ) internal returns (uint96) { - Transmitter memory transmitter = s_transmitters[transmitterAddress]; - - if (transmitter.active) { - uint96 uncollected = totalPremium - transmitter.lastCollected; - uint96 due = uncollected / payeeCount; - transmitter.balance += due; - transmitter.lastCollected += due * payeeCount; - s_transmitters[transmitterAddress] = transmitter; - } - - return transmitter.balance; - } - - /** - * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) - */ - function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { - bytes32 rawID = bytes32(upkeepId); - bytes1 empty = bytes1(0); - for (uint256 idx = 4; idx < 15; idx++) { - if (rawID[idx] != empty) { - // old IDs that were created before this standard and migrated to this registry - return Trigger.CONDITION; - } - } - return Trigger(uint8(rawID[15])); - } - - function _checkPayload( - uint256 upkeepId, - Trigger triggerType, - bytes memory triggerData - ) internal view returns (bytes memory) { - if (triggerType == Trigger.CONDITION) { - return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); - } else if (triggerType == Trigger.LOG) { - Log memory log = abi.decode(triggerData, (Log)); - return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); - } - revert InvalidTriggerType(); - } - - /** - * @dev _decodeReport decodes a serialized report into a Report struct - */ - function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { - Report memory report = abi.decode(rawReport, (Report)); - uint256 expectedLength = report.upkeepIds.length; - if ( - report.gasLimits.length != expectedLength || - report.triggers.length != expectedLength || - report.performDatas.length != expectedLength - ) { - revert InvalidReport(); - } - return report; - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - * @return bool whether the upkeep should be performed - * @return bytes32 dedupID for preventing duplicate performances of this trigger - */ - function _prePerformChecks( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - bytes32 dedupID; - if (transmitInfo.triggerType == Trigger.CONDITION) { - if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) - return (false, dedupID); - } else if (transmitInfo.triggerType == Trigger.LOG) { - bool valid; - (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); - if (!valid) return (false, dedupID); - } else { - revert InvalidTriggerType(); - } - if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { - // Can happen when an upkeep got cancelled after report was generated. - // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice - emit CancelledUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - */ - function _validateConditionalTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool) { - ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); - if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { - // Can happen when another report performed this upkeep after this report was generated - emit StaleUpkeepReport(upkeepId, rawTrigger); - return false; - } - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // There are two cases of reorged report - // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain - // which is always protected against - // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is - // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain - // when it is sent - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return false; - } - return true; - } - - function _validateLogTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); - bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // Reorg protection is same as conditional trigger upkeeps - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - if (s_dedupKeys[dedupID]) { - emit StaleUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Verify signatures attached to report - */ - function _verifyReportSignature( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) internal view { - bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount = 0; - - Signer memory signer; - address signerAddress; - for (uint256 i = 0; i < rs.length; i++) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - signer = s_signers[signerAddress]; - if (!signer.active) revert OnlyActiveSigners(); - unchecked { - signedCount += 1 << (8 * signer.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); - } - - /** - * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances - * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID - */ - function _updateTriggerMarker( - uint256 upkeepID, - uint256 blocknumber, - UpkeepTransmitInfo memory upkeepTransmitInfo - ) internal { - if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { - s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); - } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { - s_dedupKeys[upkeepTransmitInfo.dedupID] = true; - emit DedupKeyAdded(upkeepTransmitInfo.dedupID); - } - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * transmitter and the exact gas required by the Upkeep - */ - function _performUpkeep( - IAutomationForwarder forwarder, - uint256 performGas, - bytes memory performData - ) internal nonReentrant returns (bool success, uint256 gasUsed) { - performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); - return forwarder.forward(performGas, performData); - } - - /** - * @dev does postPerform payment processing for an upkeep. Deducts upkeep's balance and increases - * amount spent. - */ - function _postPerformPayment( - HotVars memory hotVars, - uint256 upkeepId, - uint256 gasUsed, - uint256 fastGasWei, - uint256 linkNative, - uint256 gasOverhead, - uint256 l1Fee - ) internal returns (uint96 gasReimbursement, uint96 premium) { - (gasReimbursement, premium) = _calculatePaymentAmount( - hotVars, - gasUsed, - gasOverhead, - l1Fee, - fastGasWei, - linkNative, - true // isExecution - ); - - uint96 balance = s_upkeep[upkeepId].balance; - uint96 payment = gasReimbursement + premium; - - // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user - // can't cover the amount owed - if (balance < gasReimbursement) { - payment = balance; - gasReimbursement = balance; - premium = 0; - } else if (balance < payment) { - payment = balance; - premium = payment - gasReimbursement; - } - - s_upkeep[upkeepId].balance -= payment; - s_upkeep[upkeepId].amountSpent += payment; - - return (gasReimbursement, premium); - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { - if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); - if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_hotVars.reentrancyGuard) revert ReentrantCall(); - s_hotVars.reentrancyGuard = true; - _; - s_hotVars.reentrancyGuard = false; - } - - /** - * @notice only allows a pre-configured address to initiate offchain read - */ - function _preventExecution() internal view { - // solhint-disable-next-line avoid-tx-origin - if (tx.origin != i_allowedReadOnlyAddress) { - revert OnlySimulatedBackend(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol deleted file mode 100644 index b176843..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicA2_2.sol +++ /dev/null @@ -1,433 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; -import {AutomationRegistryLogicB2_2} from "./AutomationRegistryLogicB2_2.sol"; -import {Chainable} from "../Chainable.sol"; -import {AutomationForwarder} from "../AutomationForwarder.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; - -/** - * @notice Logic contract, works in tandem with AutomationRegistry as a proxy - */ -contract AutomationRegistryLogicA2_2 is AutomationRegistryBase2_2, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @param logicB the address of the second logic contract - */ - constructor( - AutomationRegistryLogicB2_2 logicB - ) - AutomationRegistryBase2_2( - logicB.getLinkAddress(), - logicB.getLinkNativeFeedAddress(), - logicB.getFastGasFeedAddress(), - logicB.getAutomationForwarderLogic(), - logicB.getAllowedReadOnlyAddress() - ) - Chainable(address(logicB)) - {} - - /** - * @notice called by the automation DON to check if work is needed - * @param id the upkeep ID to check for work needed - * @param triggerData extra contextual data about the trigger (not used in all code paths) - * @dev this one of the core functions called in the hot path - * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility - * @dev there is an incongruency on what gets returned during failure modes - * ex sometimes we include price data, sometimes we omit it depending on the failure - */ - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - public - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ) - { - _preventExecution(); - - Trigger triggerType = _getTriggerType(id); - HotVars memory hotVars = s_hotVars; - Upkeep memory upkeep = s_upkeep[id]; - - if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); - if (upkeep.maxValidBlocknumber != UINT32_MAX) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); - if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); - - (fastGasWei, linkNative) = _getFeedData(hotVars); - uint96 maxLinkPayment = _getMaxLinkPayment(hotVars, triggerType, upkeep.performGas, fastGasWei, linkNative); - if (upkeep.balance < maxLinkPayment) { - return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); - } - - bytes memory callData = _checkPayload(id, triggerType, triggerData); - - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); - gasUsed = gasUsed - gasleft(); - - if (!success) { - // User's target check reverted. We capture the revert data here and pass it within performData - if (result.length > s_storage.maxRevertDataSize) { - return ( - false, - bytes(""), - UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - } - return ( - upkeepNeeded, - result, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - } - - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) - return ( - false, - bytes(""), - UpkeepFailureReason.UPKEEP_NOT_NEEDED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - - if (performData.length > s_storage.maxPerformDataSize) - return ( - false, - bytes(""), - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkNative - ); - - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkNative); - } - - /** - * @notice see other checkUpkeep function for description - * @dev this function may be deprecated in a future version of chainlink automation - */ - function checkUpkeep( - uint256 id - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkNative - ) - { - return checkUpkeep(id, bytes("")); - } - - /** - * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) - * @param id the upkeepID to execute a callback for - * @param values the values returned from the data streams lookup - * @param extraData the user-provided extra context data - */ - function checkCallback( - uint256 id, - bytes[] memory values, - bytes calldata extraData - ) - external - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); - return executeCallback(id, payload); - } - - /** - * @notice this is a generic callback executor that forwards a call to a user's contract with the configured - * gas limit - * @param id the upkeepID to execute a callback for - * @param payload the data (including function selector) to call on the upkeep target contract - */ - function executeCallback( - uint256 id, - bytes memory payload - ) - public - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - _preventExecution(); - - Upkeep memory upkeep = s_upkeep[id]; - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); - gasUsed = gasUsed - gasleft(); - if (!success) { - return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); - } - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) { - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); - } - if (performData.length > s_storage.maxPerformDataSize) { - return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); - } - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); - } - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param triggerType the trigger for the upkeep - * @param checkData data passed to the contract when checking for upkeep - * @param triggerConfig the config for the trigger - * @param offchainConfig arbitrary offchain config for the upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - Trigger triggerType, - bytes calldata checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) public returns (uint256 id) { - if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); - if (!target.isContract()) revert NotAContract(); - id = _createID(triggerType); - IAutomationForwarder forwarder = IAutomationForwarder( - address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) - ); - _createUpkeep( - id, - Upkeep({ - performGas: gasLimit, - balance: 0, - maxValidBlocknumber: UINT32_MAX, - lastPerformedBlockNumber: 0, - amountSpent: 0, - paused: false, - forwarder: forwarder - }), - admin, - checkData, - triggerConfig, - offchainConfig - ); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - emit UpkeepCheckDataSet(id, checkData); - emit UpkeepTriggerConfigSet(id, triggerConfig); - emit UpkeepOffchainConfigSet(id, offchainConfig); - return (id); - } - - /** - * @notice this function registers a conditional upkeep, using a backwards compatible function signature - * @dev this function is backwards compatible with versions <=2.0, but may be removed in a future version - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData, - bytes calldata offchainConfig - ) external returns (uint256 id) { - return registerUpkeep(target, gasLimit, admin, Trigger.CONDITION, checkData, bytes(""), offchainConfig); - } - - /** - * @notice cancels an upkeep - * @param id the upkeepID to cancel - * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to - * allow any pending performUpkeep txs time to get confirmed - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool isOwner = msg.sender == owner(); - - uint256 height = s_hotVars.chainModule.blockNumber(); - if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); - - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minUpkeepSpend is not met - uint96 minUpkeepSpend = s_storage.minUpkeepSpend; - uint96 cancellationFee = 0; - // cancellationFee is supposed to be min(max(minUpkeepSpend - amountSpent,0), amountLeft) - if (upkeep.amountSpent < minUpkeepSpend) { - cancellationFee = minUpkeepSpend - upkeep.amountSpent; - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_storage.ownerLinkBalance = s_storage.ownerLinkBalance + cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice adds fund to an upkeep - * @param id the upkeepID - * @param amount the amount of LINK to fund, in jules (jules = "wei" of LINK) - */ - function addFunds(uint256 id, uint96 amount) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - s_upkeep[id].balance = upkeep.balance + amount; - s_expectedLinkBalance = s_expectedLinkBalance + amount; - i_link.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice migrates upkeeps from one registry to another - * @param ids the upkeepIDs to migrate - * @param destination the destination registry address - * @dev a transcoder must be set in order to enable migration - * @dev migration permissions must be set on *both* sending and receiving registries - * @dev only an upkeep admin can migrate their upkeeps - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - uint256 id; - Upkeep memory upkeep; - uint256 totalBalanceRemaining; - address[] memory admins = new address[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - bytes[] memory checkDatas = new bytes[](ids.length); - bytes[] memory triggerConfigs = new bytes[](ids.length); - bytes[] memory offchainConfigs = new bytes[](ids.length); - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - _requireAdminAndNotCancelled(id); - upkeep.forwarder.updateRegistry(destination); - upkeeps[idx] = upkeep; - admins[idx] = s_upkeepAdmin[id]; - checkDatas[idx] = s_checkData[id]; - triggerConfigs[idx] = s_upkeepTriggerConfig[id]; - offchainConfigs[idx] = s_upkeepOffchainConfig[id]; - totalBalanceRemaining = totalBalanceRemaining + upkeep.balance; - delete s_upkeep[id]; - delete s_checkData[id]; - delete s_upkeepTriggerConfig[id]; - delete s_upkeepOffchainConfig[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - s_expectedLinkBalance = s_expectedLinkBalance - totalBalanceRemaining; - bytes memory encodedUpkeeps = abi.encode( - ids, - upkeeps, - new address[](ids.length), - admins, - checkDatas, - triggerConfigs, - offchainConfigs - ); - MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( - UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( - UPKEEP_VERSION_BASE, - MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), - encodedUpkeeps - ) - ); - i_link.transfer(destination, totalBalanceRemaining); - } - - /** - * @notice received upkeeps migrated from another registry - * @param encodedUpkeeps the raw upkeep data to import - * @dev this function is never called directly, it is only called by another registry's migrate function - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - ( - uint256[] memory ids, - Upkeep[] memory upkeeps, - address[] memory targets, - address[] memory upkeepAdmins, - bytes[] memory checkDatas, - bytes[] memory triggerConfigs, - bytes[] memory offchainConfigs - ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); - for (uint256 idx = 0; idx < ids.length; idx++) { - if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { - upkeeps[idx].forwarder = IAutomationForwarder( - address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) - ); - } - _createUpkeep( - ids[idx], - upkeeps[idx], - upkeepAdmins[idx], - checkDatas[idx], - triggerConfigs[idx], - offchainConfigs[idx] - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } - - /** - * @notice sets the upkeep trigger config - * @param id the upkeepID to change the trigger for - * @param triggerConfig the new trigger config - */ - function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { - _requireAdminAndNotCancelled(id); - s_upkeepTriggerConfig[id] = triggerConfig; - emit UpkeepTriggerConfigSet(id, triggerConfig); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol deleted file mode 100644 index f6d1ea8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationRegistryLogicB2_2.sol +++ /dev/null @@ -1,540 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {UpkeepFormat} from "../interfaces/UpkeepTranscoderInterface.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -contract AutomationRegistryLogicB2_2 is AutomationRegistryBase2_2 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @dev see AutomationRegistry master contract for constructor description - */ - constructor( - address link, - address linkNativeFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress - ) AutomationRegistryBase2_2(link, linkNativeFeed, fastGasFeed, automationForwarderLogic, allowedReadOnlyAddress) {} - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice transfers the address of an admin for an upkeep - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - _requireAdminAndNotCancelled(id); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of an upkeep admin - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = s_upkeepAdmin[id]; - s_upkeepAdmin[id] = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused - */ - function pauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @notice unpauses an upkeep - */ - function unpauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @notice updates the checkData for an upkeep - */ - function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { - _requireAdminAndNotCancelled(id); - if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataSet(id, newCheckData); - } - - /** - * @notice updates the gas limit for an upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - _requireAdminAndNotCancelled(id); - s_upkeep[id].performGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @notice updates the offchain config for an upkeep - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { - _requireAdminAndNotCancelled(id); - s_upkeepOffchainConfig[id] = config; - emit UpkeepOffchainConfigSet(id, config); - } - - /** - * @notice withdraws LINK funds from an upkeep - * @dev note that an upkeep must be cancelled first!! - */ - function withdrawFunds(uint256 id, address to) external nonReentrant { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); - uint96 amountToWithdraw = s_upkeep[id].balance; - s_expectedLinkBalance = s_expectedLinkBalance - amountToWithdraw; - s_upkeep[id].balance = 0; - i_link.transfer(to, amountToWithdraw); - emit FundsWithdrawn(id, amountToWithdraw, to); - } - - // ================================================================ - // | NODE MANAGEMENT | - // ================================================================ - - /** - * @notice transfers the address of payee for a transmitter - */ - function transferPayeeship(address transmitter, address proposed) external { - if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[transmitter] != proposed) { - s_proposedPayee[transmitter] = proposed; - emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of the payee - */ - function acceptPayeeship(address transmitter) external { - if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_transmitterPayees[transmitter]; - s_transmitterPayees[transmitter] = msg.sender; - s_proposedPayee[transmitter] = ZERO_ADDRESS; - - emit PayeeshipTransferred(transmitter, past, msg.sender); - } - - /** - * @notice withdraws LINK received as payment for work performed - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); - uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); - s_transmitters[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance - balance; - i_link.transfer(to, balance); - emit PaymentWithdrawn(from, balance, to, msg.sender); - } - - // ================================================================ - // | OWNER / MANAGER ACTIONS | - // ================================================================ - - /** - * @notice sets the privilege config for an upkeep - */ - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; - emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); - } - - /** - * @notice withdraws the owner's LINK balance - */ - function withdrawOwnerFunds() external onlyOwner { - uint96 amount = s_storage.ownerLinkBalance; - s_expectedLinkBalance = s_expectedLinkBalance - amount; - s_storage.ownerLinkBalance = 0; - emit OwnerFundsWithdrawn(amount); - i_link.transfer(msg.sender, amount); - } - - /** - * @notice allows the owner to withdraw any LINK accidentally sent to the contract - */ - function recoverFunds() external onlyOwner { - uint256 total = i_link.balanceOf(address(this)); - i_link.transfer(msg.sender, total - s_expectedLinkBalance); - } - - /** - * @notice sets the payees for the transmitters - */ - function setPayees(address[] calldata payees) external onlyOwner { - if (s_transmittersList.length != payees.length) revert ParameterLengthError(); - for (uint256 i = 0; i < s_transmittersList.length; i++) { - address transmitter = s_transmittersList[i]; - address oldPayee = s_transmitterPayees[transmitter]; - address newPayee = payees[i]; - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) revert InvalidPayee(); - if (newPayee != IGNORE_ADDRESS) { - s_transmitterPayees[transmitter] = newPayee; - } - } - emit PayeesUpdated(s_transmittersList, payees); - } - - /** - * @notice sets the migration permission for a peer registry - * @dev this must be done before upkeeps can be migrated to/from another registry - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @notice pauses the entire registry - */ - function pause() external onlyOwner { - s_hotVars.paused = true; - emit Paused(msg.sender); - } - - /** - * @notice unpauses the entire registry - */ - function unpause() external onlyOwner { - s_hotVars.paused = false; - emit Unpaused(msg.sender); - } - - /** - * @notice sets a generic bytes field used to indicate the privilege that this admin address had - * @param admin the address to set privilege for - * @param newPrivilegeConfig the privileges that this admin has - */ - function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - s_adminPrivilegeConfig[admin] = newPrivilegeConfig; - emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - function getConditionalGasOverhead() external pure returns (uint256) { - return REGISTRY_CONDITIONAL_OVERHEAD; - } - - function getLogGasOverhead() external pure returns (uint256) { - return REGISTRY_LOG_OVERHEAD; - } - - function getPerPerformByteGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; - } - - function getPerSignerGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_SIGNER_GAS_OVERHEAD; - } - - function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD; - } - - function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD; - } - - function getCancellationDelay() external pure returns (uint256) { - return CANCELLATION_DELAY; - } - - function getLinkAddress() external view returns (address) { - return address(i_link); - } - - function getLinkNativeFeedAddress() external view returns (address) { - return address(i_linkNativeFeed); - } - - function getFastGasFeedAddress() external view returns (address) { - return address(i_fastGasFeed); - } - - function getAutomationForwarderLogic() external view returns (address) { - return i_automationForwarderLogic; - } - - function getAllowedReadOnlyAddress() external view returns (address) { - return i_allowedReadOnlyAddress; - } - - function upkeepTranscoderVersion() public pure returns (UpkeepFormat) { - return UPKEEP_TRANSCODER_VERSION_BASE; - } - - function upkeepVersion() public pure returns (uint8) { - return UPKEEP_VERSION_BASE; - } - - /** - * @notice read all of the details about an upkeep - * @dev this function may be deprecated in a future version of automation in favor of individual - * getters for each field - */ - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { - Upkeep memory reg = s_upkeep[id]; - address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); - upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ - target: target, - performGas: reg.performGas, - checkData: s_checkData[id], - balance: reg.balance, - admin: s_upkeepAdmin[id], - maxValidBlocknumber: reg.maxValidBlocknumber, - lastPerformedBlockNumber: reg.lastPerformedBlockNumber, - amountSpent: reg.amountSpent, - paused: reg.paused, - offchainConfig: s_upkeepOffchainConfig[id] - }); - return upkeepInfo; - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { - uint256 numUpkeeps = s_upkeepIDs.length(); - if (startIndex >= numUpkeeps) revert IndexOutOfRange(); - uint256 endIndex = startIndex + maxCount; - endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; - uint256[] memory ids = new uint256[](endIndex - startIndex); - for (uint256 idx = 0; idx < ids.length; idx++) { - ids[idx] = s_upkeepIDs.at(idx + startIndex); - } - return ids; - } - - /** - * @notice returns the upkeep's trigger type - */ - function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { - return _getTriggerType(upkeepId); - } - - /** - * @notice returns the trigger config for an upkeeep - */ - function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { - return s_upkeepTriggerConfig[upkeepId]; - } - - /** - * @notice read the current info about any transmitter address - */ - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { - Transmitter memory transmitter = s_transmitters[query]; - - uint96 pooledShare = 0; - if (transmitter.active) { - uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; - pooledShare = totalDifference / uint96(s_transmittersList.length); - } - - return ( - transmitter.active, - transmitter.index, - (transmitter.balance + pooledShare), - transmitter.lastCollected, - s_transmitterPayees[query] - ); - } - - /** - * @notice read the current info about any signer address - */ - function getSignerInfo(address query) external view returns (bool active, uint8 index) { - Signer memory signer = s_signers[query]; - return (signer.active, signer.index); - } - - /** - * @notice read the current state of the registry - * @dev this function is deprecated - */ - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) - { - state = IAutomationV21PlusCommon.StateLegacy({ - nonce: s_storage.nonce, - ownerLinkBalance: s_storage.ownerLinkBalance, - expectedLinkBalance: s_expectedLinkBalance, - totalPremium: s_hotVars.totalPremium, - numUpkeeps: s_upkeepIDs.length(), - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - latestConfigDigest: s_latestConfigDigest, - latestEpoch: s_hotVars.latestEpoch, - paused: s_hotVars.paused - }); - - config = IAutomationV21PlusCommon.OnchainConfigLegacy({ - paymentPremiumPPB: s_hotVars.paymentPremiumPPB, - flatFeeMicroLink: s_hotVars.flatFeeMicroLink, - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - minUpkeepSpend: s_storage.minUpkeepSpend, - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager - }); - - return (state, config, s_signersList, s_transmittersList, s_hotVars.f); - } - - /** - * @notice get the chain module - */ - function getChainModule() external view returns (IChainModule chainModule) { - return s_hotVars.chainModule; - } - - /** - * @notice if this registry has reorg protection enabled - */ - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { - return s_hotVars.reorgProtectionEnabled; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getBalance(uint256 id) external view returns (uint96 balance) { - return s_upkeep[id].balance; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalance(uint256 id) external view returns (uint96) { - return getMinBalanceForUpkeep(id); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - * @dev this will be deprecated in a future version in favor of getMinBalance - */ - function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { - return getMaxPaymentForGas(_getTriggerType(id), s_upkeep[id].performGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas(Trigger triggerType, uint32 gasLimit) public view returns (uint96 maxPayment) { - HotVars memory hotVars = s_hotVars; - (uint256 fastGasWei, uint256 linkNative) = _getFeedData(hotVars); - return _getMaxLinkPayment(hotVars, triggerType, gasLimit, fastGasWei, linkNative); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { - return s_upkeepPrivilegeConfig[upkeepId]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { - return s_adminPrivilegeConfig[admin]; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { - return s_upkeep[upkeepID].forwarder; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function hasDedupKey(bytes32 dedupKey) external view returns (bool) { - return s_dedupKeys[dedupKey]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol deleted file mode 100644 index abdabeb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/AutomationUtils2_2.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationRegistryBase2_2} from "./AutomationRegistryBase2_2.sol"; -import {Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -/** - * @notice this file exposes structs that are otherwise internal to the automation registry - * doing this allows those structs to be encoded and decoded with type safety in offchain code - * and tests because generated wrappers are made available - */ - -/** - * @notice structure of trigger for log triggers - */ -struct LogTriggerConfig { - address contractAddress; - uint8 filterSelector; // denotes which topics apply to filter ex 000, 101, 111...only last 3 bits apply - bytes32 topic0; - bytes32 topic1; - bytes32 topic2; - bytes32 topic3; -} - -contract AutomationUtils2_2 { - /** - * @dev this can be removed as OnchainConfig is now exposed directly from the registry - */ - function _onChainConfig(IAutomationV21PlusCommon.OnchainConfigLegacy memory) external {} // 0x2ff92a81 - - function _report(AutomationRegistryBase2_2.Report memory) external {} // 0xe65d6546 - - function _logTriggerConfig(LogTriggerConfig memory) external {} // 0x21f373d7 - - function _logTrigger(AutomationRegistryBase2_2.LogTrigger memory) external {} // 0x1c8d8260 - - function _conditionalTrigger(AutomationRegistryBase2_2.ConditionalTrigger memory) external {} // 0x4b6df294 - - function _log(Log memory) external {} // 0xe9720a49 -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE deleted file mode 100644 index 9230d39..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/LICENSE +++ /dev/null @@ -1,57 +0,0 @@ -Business Source License 1.1 - -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ---- - -Parameters - -Licensor: SmartContract Chainlink Limited SEZC - -Licensed Work: Automation v2.2 -The Licensed Work is (c) 2024 SmartContract Chainlink Limited SEZC - -Additional Use Grant(s): -You may make use of Automation v2.1, v2.2 (which is available subject to the license here the “Licensed Work”) solely for purposes listed below: -https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md - -Change Date: January 22, 2028 - -Change License: MIT - ---- - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. - -If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. - -MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. - ---- - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. - -2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md deleted file mode 100644 index abd3eb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_2/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Automation Contract Structure - -The on-chain component of Chainlink automation is too large to fit into the [size requirements][size-limit-eip] of a single contract. It is also too large to fit into 2 contracts, a solution that works for most large projects. Therefore, we included this explanation of how the pieces fit together and various tradeoffs incurred. - -### Glossary - -**Master Contract** - also known as the “storage” contract. This is the contract whose state we care about. It is the entry-point into the chain of delegatecalls. (We avoid the term "proxy" because it is commonly associated with upgradability, and this system _is not upgradable_ even though it relies on some of the same mechanics.) - -**Logic Contract** - this a contract whose sole purpose is to hold code. We use the code at this address and execute it in the context of the master contract in order to increase our total capacity for on-chain code. - -### Overview - -We chain multiple logic contracts together using [fallback functions][fallback] and [delegatecall][delegatecall]. If a function definition is not found on one contract, we fall back to the next, always executing the function in the scope of the master contract. The actual implementation of this is based off of [OZ's Proxy contract][oz-proxy]. - -### Diagram - -```mermaid -graph LR - Master -- delegatecall --> la[Logic A] - la -- delegatecall --> lb[Logic B] - lb -. delegatecall .-> lx[Logic X] -``` - -### Special Considerations - -- functions on the master contract have the least gas overhead, therefore, our most price-sensitive functions live there -- functions on the master contract have first-class support from tools like etherscan and tenderly - functions that we (or users) call often to debug should live there -- etherscan supports executing logic contract functions that are once removed from the master - therefore we give secondary preference to the first logic contract for user and debugging functions -- functions on logic A through logic X (as of writing) have no support on etherscan and will essentially be "invisible" to everyone but advanced users - we will try to reserve this space for uncommon interactions that are mostly done progamatically -- We use Logic A, B, C... to avoid confusion with the version ex `AutomationRegistryLogicA2_2.sol` --> Logic Contract A verion 2.1 -- Storage locations for logic contract addresses MUST BE BYTECODE (this is done by marking them as "immutable") otherwise the chaining mechanism will break - -### Master Interface - -The Master Interface is a deduped combination of all the interfaces from all contracts in the chain. We generate this interface programatically using the script `generate-automation-master-interface.ts`. This process is not a hardened one. Users of this script should take great care to ensure it's efficacy. - -[size-limit-eip]: https://eips.ethereum.org/EIPS/eip-170 -[fallback]: https://docs.soliditylang.org/en/v0.8.12/contracts.html#fallback-function -[delegatecall]: https://docs.soliditylang.org/en/v0.8.12/introduction-to-smart-contracts.html?highlight=delegatecall#delegatecall-callcode-and-libraries -[oz-proxy]: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Proxy diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol deleted file mode 100644 index 2effb8d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistrar2_3.sol +++ /dev/null @@ -1,442 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/** - * @notice Contract to accept requests for upkeep registrations - * @dev There are 2 registration workflows in this contract - * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually - * calls `approve` to register upkeep and emit events to inform UI and others interested. - * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on - * keeper registry and then emits approved event to finish the flow automatically without manual intervention. - * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. - * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. - */ -contract AutomationRegistrar2_3 is TypeAndVersionInterface, ConfirmedOwner, IERC677Receiver { - using SafeERC20 for IERC20; - - /** - * DISABLED: No auto approvals, all new upkeeps should be approved manually. - * ENABLED_SENDER_ALLOWLIST: Auto approvals for allowed senders subject to max allowed. Manual for rest. - * ENABLED_ALL: Auto approvals for all new upkeeps subject to max allowed. - */ - enum AutoApproveType { - DISABLED, - ENABLED_SENDER_ALLOWLIST, - ENABLED_ALL - } - - /** - * @notice versions: - * - KeeperRegistrar 2.3.0: Update for compatability with registry 2.3.0 - * Add native billing and ERC20 billing support - * - KeeperRegistrar 2.1.0: Update for compatability with registry 2.1.0 - * Add auto approval levels by type - * - KeeperRegistrar 2.0.0: Remove source from register - * Breaks our example of "Register an Upkeep using your own deployed contract" - * - KeeperRegistrar 1.1.0: Add functionality for sender allowlist in auto approve - * : Remove rate limit and add max allowed for auto approve - * - KeeperRegistrar 1.0.0: initial release - */ - string public constant override typeAndVersion = "AutomationRegistrar 2.3.0"; - - /** - * @notice TriggerRegistrationStorage stores the auto-approval levels for upkeeps by type - * @member autoApproveType the auto approval setting (see enum) - * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - * @member approvedCount the count of upkeeps auto approved of this type - */ - struct TriggerRegistrationStorage { - AutoApproveType autoApproveType; - uint32 autoApproveMaxAllowed; - uint32 approvedCount; - } - - /** - * @notice InitialTriggerConfig configures the auto-approval levels for upkeeps by trigger type - * @dev this struct is only used in the constructor to set the initial values for various trigger configs - * @member triggerType the upkeep type to configure - * @member autoApproveType the auto approval setting (see enum) - * @member autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - */ - // solhint-disable-next-line gas-struct-packing - struct InitialTriggerConfig { - uint8 triggerType; - AutoApproveType autoApproveType; - uint32 autoApproveMaxAllowed; - } - - struct PendingRequest { - address admin; - uint96 balance; - IERC20 billingToken; - } - /** - * @member upkeepContract address to perform upkeep on - * @member amount quantity of billing token upkeep is funded with (specified in the billing token's decimals) - * @member adminAddress address to cancel upkeep and withdraw remaining funds - * @member gasLimit amount of gas to provide the target contract when performing upkeep - * @member triggerType the type of trigger for the upkeep - * @member billingToken the token to pay with - * @member name string of the upkeep to be registered - * @member encryptedEmail email address of upkeep contact - * @member checkData data passed to the contract when checking for upkeep - * @member triggerConfig the config for the trigger - * @member offchainConfig offchainConfig for upkeep in bytes - */ - struct RegistrationParams { - address upkeepContract; - uint96 amount; - // 1 word full - address adminAddress; - uint32 gasLimit; - uint8 triggerType; - // 7 bytes left in 2nd word - IERC20 billingToken; - // 12 bytes left in 3rd word - string name; - bytes encryptedEmail; - bytes checkData; - bytes triggerConfig; - bytes offchainConfig; - } - - LinkTokenInterface public immutable i_LINK; - IWrappedNative public immutable i_WRAPPED_NATIVE_TOKEN; - IAutomationRegistryMaster2_3 private s_registry; - - // Only applicable if trigger config is set to ENABLED_SENDER_ALLOWLIST - mapping(address => bool) private s_autoApproveAllowedSenders; - mapping(IERC20 => uint256) private s_minRegistrationAmounts; - mapping(bytes32 => PendingRequest) private s_pendingRequests; - mapping(uint8 => TriggerRegistrationStorage) private s_triggerRegistrations; - - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - uint8 triggerType, - bytes triggerConfig, - bytes offchainConfig, - bytes checkData, - uint96 amount, - IERC20 billingToken - ); - - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - - event RegistrationRejected(bytes32 indexed hash); - - event AutoApproveAllowedSenderSet(address indexed senderAddress, bool allowed); - - event ConfigChanged(); - - event TriggerConfigSet(uint8 triggerType, AutoApproveType autoApproveType, uint32 autoApproveMaxAllowed); - - error HashMismatch(); - error InsufficientPayment(); - error InvalidAdminAddress(); - error InvalidBillingToken(); - error InvalidDataLength(); - error TransferFailed(address to); - error DuplicateEntry(); - error OnlyAdminOrOwner(); - error OnlyLink(); - error RequestNotFound(); - - /** - * @param LINKAddress Address of Link token - * @param registry keeper registry address - * @param triggerConfigs the initial config for individual triggers - * @param billingTokens the tokens allowed for billing - * @param minRegistrationFees the minimum amount for registering with each billing token - * @param wrappedNativeToken wrapped native token - */ - constructor( - address LINKAddress, - IAutomationRegistryMaster2_3 registry, - InitialTriggerConfig[] memory triggerConfigs, - IERC20[] memory billingTokens, - uint256[] memory minRegistrationFees, - IWrappedNative wrappedNativeToken - ) ConfirmedOwner(msg.sender) { - i_LINK = LinkTokenInterface(LINKAddress); - i_WRAPPED_NATIVE_TOKEN = wrappedNativeToken; - setConfig(registry, billingTokens, minRegistrationFees); - for (uint256 idx = 0; idx < triggerConfigs.length; idx++) { - setTriggerConfig( - triggerConfigs[idx].triggerType, - triggerConfigs[idx].autoApproveType, - triggerConfigs[idx].autoApproveMaxAllowed - ); - } - } - - //EXTERNAL - - /** - * @notice Allows external users to register upkeeps; assumes amount is approved for transfer by the contract - * @param requestParams struct of all possible registration parameters - */ - function registerUpkeep(RegistrationParams memory requestParams) external payable returns (uint256) { - if (requestParams.billingToken == IERC20(i_WRAPPED_NATIVE_TOKEN) && msg.value != 0) { - requestParams.amount = SafeCast.toUint96(msg.value); - // wrap and send native payment - i_WRAPPED_NATIVE_TOKEN.deposit{value: msg.value}(); - } else { - // send ERC20 payment, including wrapped native token - requestParams.billingToken.safeTransferFrom(msg.sender, address(this), requestParams.amount); - } - - return _register(requestParams, msg.sender); - } - - /** - * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event - * @param requestParams struct of all possible registration parameters - */ - function approve(RegistrationParams calldata requestParams) external onlyOwner { - bytes32 hash = keccak256(abi.encode(requestParams)); - - PendingRequest memory request = s_pendingRequests[hash]; - if (request.admin == address(0)) { - revert RequestNotFound(); - } - - delete s_pendingRequests[hash]; - _approve(requestParams, hash); - } - - /** - * @notice cancel will remove a registration request from the pending request queue and return the refunds to the request.admin - * @param hash the request hash - */ - function cancel(bytes32 hash) external { - PendingRequest memory request = s_pendingRequests[hash]; - - if (!(msg.sender == request.admin || msg.sender == owner())) { - revert OnlyAdminOrOwner(); - } - if (request.admin == address(0)) { - revert RequestNotFound(); - } - delete s_pendingRequests[hash]; - - request.billingToken.safeTransfer(request.admin, request.balance); - - emit RegistrationRejected(hash); - } - - /** - * @notice owner calls this function to set contract config - * @param registry new keeper registry address - * @param billingTokens the billing tokens that this registrar supports (registy must also support these) - * @param minBalances minimum balances that users must supply to register with the corresponding billing token - */ - function setConfig( - IAutomationRegistryMaster2_3 registry, - IERC20[] memory billingTokens, - uint256[] memory minBalances - ) public onlyOwner { - if (billingTokens.length != minBalances.length) revert InvalidDataLength(); - s_registry = registry; - for (uint256 i = 0; i < billingTokens.length; i++) { - s_minRegistrationAmounts[billingTokens[i]] = minBalances[i]; - } - emit ConfigChanged(); - } - - /** - * @notice owner calls to set the config for this upkeep type - * @param triggerType the upkeep type to configure - * @param autoApproveType the auto approval setting (see enum) - * @param autoApproveMaxAllowed the max number of upkeeps that can be auto approved of this type - */ - function setTriggerConfig( - uint8 triggerType, - AutoApproveType autoApproveType, - uint32 autoApproveMaxAllowed - ) public onlyOwner { - s_triggerRegistrations[triggerType].autoApproveType = autoApproveType; - s_triggerRegistrations[triggerType].autoApproveMaxAllowed = autoApproveMaxAllowed; - emit TriggerConfigSet(triggerType, autoApproveType, autoApproveMaxAllowed); - } - - /** - * @notice owner calls this function to set allowlist status for senderAddress - * @param senderAddress senderAddress to set the allowlist status for - * @param allowed true if senderAddress needs to be added to allowlist, false if needs to be removed - */ - function setAutoApproveAllowedSender(address senderAddress, bool allowed) external onlyOwner { - s_autoApproveAllowedSenders[senderAddress] = allowed; - - emit AutoApproveAllowedSenderSet(senderAddress, allowed); - } - - /** - * @notice read the allowlist status of senderAddress - * @param senderAddress address to read the allowlist status for - */ - function getAutoApproveAllowedSender(address senderAddress) external view returns (bool) { - return s_autoApproveAllowedSenders[senderAddress]; - } - - /** - * @notice gets the registry that this registrar is pointed to - */ - function getRegistry() external view returns (IAutomationRegistryMaster2_3) { - return s_registry; - } - - /** - * @notice get the minimum registration fee for a particular billing token - */ - function getMinimumRegistrationAmount(IERC20 billingToken) external view returns (uint256) { - return s_minRegistrationAmounts[billingToken]; - } - - /** - * @notice read the config for this upkeep type - * @param triggerType upkeep type to read config for - */ - function getTriggerRegistrationDetails(uint8 triggerType) external view returns (TriggerRegistrationStorage memory) { - return s_triggerRegistrations[triggerType]; - } - - /** - * @notice gets the admin address and the current balance of a registration request - */ - function getPendingRequest(bytes32 hash) external view returns (address, uint96) { - PendingRequest memory request = s_pendingRequests[hash]; - return (request.admin, request.balance); - } - - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @param sender Address of the sender transfering LINK - * @param amount Amount of LINK sent (specified in Juels) - * @param data Payload of the transaction - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_LINK)) revert OnlyLink(); - RegistrationParams memory params = abi.decode(data, (RegistrationParams)); - if (address(params.billingToken) != address(i_LINK)) revert OnlyLink(); - params.amount = uint96(amount); // ignore whatever is sent in registration params, use actual value; casting safe because max supply LINK < 2^96 - _register(params, sender); - } - - // ================================================================ - // | PRIVATE | - // ================================================================ - - /** - * @dev verify registration request and emit RegistrationRequested event - * @dev we don't allow multiple duplicate registrations by adding to the original registration's balance - * users can cancel and re-register if they want to update the registration - */ - function _register(RegistrationParams memory params, address sender) private returns (uint256) { - if (params.amount < s_minRegistrationAmounts[params.billingToken]) { - revert InsufficientPayment(); - } - if (params.adminAddress == address(0)) { - revert InvalidAdminAddress(); - } - if (!s_registry.supportsBillingToken(address(params.billingToken))) { - revert InvalidBillingToken(); - } - bytes32 hash = keccak256(abi.encode(params)); - - if (s_pendingRequests[hash].admin != address(0)) { - revert DuplicateEntry(); - } - - emit RegistrationRequested( - hash, - params.name, - params.encryptedEmail, - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.triggerType, - params.triggerConfig, - params.offchainConfig, - params.checkData, - params.amount, - params.billingToken - ); - - uint256 upkeepId; - if (_shouldAutoApprove(s_triggerRegistrations[params.triggerType], sender)) { - s_triggerRegistrations[params.triggerType].approvedCount++; - upkeepId = _approve(params, hash); - } else { - s_pendingRequests[hash] = PendingRequest({ - admin: params.adminAddress, - balance: params.amount, - billingToken: params.billingToken - }); - } - - return upkeepId; - } - - /** - * @dev register upkeep on AutomationRegistry contract and emit RegistrationApproved event - * @dev safeApprove is deprecated and removed from the latest (v5) OZ release, Use safeIncreaseAllowance when we upgrade OZ (we are on v4.8) - * @dev we stick to the safeApprove because of the older version (v4.8) of safeIncreaseAllowance can't handle USDT correctly, but newer version can - */ - function _approve(RegistrationParams memory params, bytes32 hash) private returns (uint256) { - IAutomationRegistryMaster2_3 registry = s_registry; - uint256 upkeepId = registry.registerUpkeep( - params.upkeepContract, - params.gasLimit, - params.adminAddress, - params.triggerType, - address(params.billingToken), // have to cast as address because master interface doesn't use contract types - params.checkData, - params.triggerConfig, - params.offchainConfig - ); - - if (address(params.billingToken) == address(i_LINK)) { - bool success = i_LINK.transferAndCall(address(registry), params.amount, abi.encode(upkeepId)); - if (!success) { - revert TransferFailed(address(registry)); - } - } else { - params.billingToken.safeApprove(address(registry), params.amount); - registry.addFunds(upkeepId, params.amount); - } - - emit RegistrationApproved(hash, params.name, upkeepId); - return upkeepId; - } - - /** - * @dev verify sender allowlist if needed and check max limit - */ - function _shouldAutoApprove(TriggerRegistrationStorage memory config, address sender) private view returns (bool) { - if (config.autoApproveType == AutoApproveType.DISABLED) { - return false; - } - if (config.autoApproveType == AutoApproveType.ENABLED_SENDER_ALLOWLIST && (!s_autoApproveAllowedSenders[sender])) { - return false; - } - if (config.approvedCount < config.autoApproveMaxAllowed) { - return true; - } - return false; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol deleted file mode 100644 index 031d7b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistry2_3.sol +++ /dev/null @@ -1,391 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {AutomationRegistryLogicA2_3} from "./AutomationRegistryLogicA2_3.sol"; -import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - -/** - * @notice Registry for adding work for Chainlink nodes to perform on client - * contracts. Clients must support the AutomationCompatibleInterface interface. - */ -contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @notice versions: - * AutomationRegistry 2.3.0: supports native and ERC20 billing - * changes flat fee to USD-denominated - * adds support for custom billing overrides - * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module - * KeeperRegistry 2.1.0: introduces support for log triggers - * removes the need for "wrapped perform data" - * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts - * fixes issue with arbitrum block number - * does an early return in case of stale report instead of revert - * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X - * KeeperRegistry 2.0.0: implement OCR interface - * KeeperRegistry 1.3.0: split contract into Proxy and Logic - * account for Arbitrum and Optimism L1 gas fee - * allow users to configure upkeeps - * KeeperRegistry 1.2.0: allow funding within performUpkeep - * allow configurable registry maxPerformGas - * add function to let admin change upkeep gas limit - * add minUpkeepSpend requirement - * upgrade to solidity v0.8 - * KeeperRegistry 1.1.0: added flatFeeMicroLink - * KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "AutomationRegistry 2.3.0"; - - /** - * @param logicA the address of the first logic contract - * @dev we cast the contract to logicC in order to call logicC functions (via fallback) - */ - constructor( - AutomationRegistryLogicA2_3 logicA - ) - AutomationRegistryBase2_3( - AutomationRegistryLogicC2_3(address(logicA)).getLinkAddress(), - AutomationRegistryLogicC2_3(address(logicA)).getLinkUSDFeedAddress(), - AutomationRegistryLogicC2_3(address(logicA)).getNativeUSDFeedAddress(), - AutomationRegistryLogicC2_3(address(logicA)).getFastGasFeedAddress(), - AutomationRegistryLogicC2_3(address(logicA)).getAutomationForwarderLogic(), - AutomationRegistryLogicC2_3(address(logicA)).getAllowedReadOnlyAddress(), - AutomationRegistryLogicC2_3(address(logicA)).getPayoutMode(), - AutomationRegistryLogicC2_3(address(logicA)).getWrappedNativeTokenAddress() - ) - Chainable(address(logicA)) - {} - - /** - * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors - */ - struct TransmitVars { - uint16 numUpkeepsPassedChecks; - uint96 totalReimbursement; - uint96 totalPremium; - uint256 totalCalldataWeight; - } - - // ================================================================ - // | HOT PATH ACTIONS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function transmit( - bytes32[3] calldata reportContext, - bytes calldata rawReport, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external override { - uint256 gasOverhead = gasleft(); - // use this msg.data length check to ensure no extra data is included in the call - // 4 is first 4 bytes of the keccak-256 hash of the function signature. ss.length == rs.length so use one of them - // 4 + (32 * 3) + (rawReport.length + 32 + 32) + (32 * rs.length + 32 + 32) + (32 * ss.length + 32 + 32) + 32 - uint256 requiredLength = 324 + rawReport.length + 64 * rs.length; - if (msg.data.length != requiredLength) revert InvalidDataLength(); - HotVars memory hotVars = s_hotVars; - - if (hotVars.paused) revert RegistryPaused(); - if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); - - // Verify signatures - if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); - if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); - _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); - - Report memory report = _decodeReport(rawReport); - - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - - _handleReport(hotVars, report, gasOverhead); - - if (epoch > hotVars.latestEpoch) { - s_hotVars.latestEpoch = epoch; - } - } - - /** - * @notice handles the report by performing the upkeeps and updating the state - * @param hotVars the hot variables of the registry - * @param report the report to be handled (already verified and decoded) - * @param gasOverhead the running tally of gas overhead to be split across the upkeeps - * @dev had to split this function from transmit() to avoid stack too deep errors - * @dev all other internal / private functions are generally defined in the Base contract - * we leave this here because it is essentially a continuation of the transmit() function, - */ - function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private { - UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); - TransmitVars memory transmitVars = TransmitVars({ - numUpkeepsPassedChecks: 0, - totalCalldataWeight: 0, - totalReimbursement: 0, - totalPremium: 0 - }); - - uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); - - 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( - report.upkeepIds[i], - blocknumber, - report.triggers[i], - upkeepTransmitInfo[i], - hotVars - ); - - if (upkeepTransmitInfo[i].earlyChecksPassed) { - transmitVars.numUpkeepsPassedChecks += 1; - } else { - continue; - } - - // Actually perform the target upkeep - (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( - upkeepTransmitInfo[i].upkeep.forwarder, - report.gasLimits[i], - 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 the gasUsed by upkeep from the overhead tally - upkeeps pay for their own gas individually - 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 (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 - gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD; - gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; - - { - BillingTokenPaymentParams memory billingTokenParams; - uint256 nativeUSD = _getNativeUSD(hotVars); - for (uint256 i = 0; i < report.upkeepIds.length; i++) { - if (upkeepTransmitInfo[i].earlyChecksPassed) { - if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { - billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); - } - PaymentReceipt memory receipt = _handlePayment( - hotVars, - PaymentParams({ - gasLimit: upkeepTransmitInfo[i].gasUsed, - gasOverhead: gasOverhead, - l1CostWei: (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight, - fastGasWei: report.fastGasWei, - linkUSD: report.linkUSD, - nativeUSD: nativeUSD, - billingToken: upkeepTransmitInfo[i].upkeep.billingToken, - billingTokenParams: billingTokenParams, - isTransaction: true - }), - report.upkeepIds[i], - upkeepTransmitInfo[i].upkeep - ); - transmitVars.totalPremium += receipt.premiumInJuels; - transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; - - emit UpkeepPerformed( - report.upkeepIds[i], - upkeepTransmitInfo[i].performSuccess, - receipt.gasChargeInBillingToken + receipt.premiumInBillingToken, - upkeepTransmitInfo[i].gasUsed, - gasOverhead, - report.triggers[i] - ); - } - } - } - // record payments to NOPs, all in LINK - s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; - s_hotVars.totalPremium += transmitVars.totalPremium; - s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium; - } - - // ================================================================ - // | OCR2ABSTRACT | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override { - (OnchainConfig memory config, IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) = abi.decode( - onchainConfigBytes, - (OnchainConfig, IERC20[], BillingConfig[]) - ); - - setConfigTypeSafe( - signers, - transmitters, - f, - config, - offchainConfigVersion, - offchainConfig, - billingTokens, - billingConfigs - ); - } - - /** - * @notice sets the configuration for the registry - * @param signers the list of permitted signers - * @param transmitters the list of permitted transmitters - * @param f the maximum tolerance for faulty nodes - * @param onchainConfig configuration values that are used on-chain - * @param offchainConfigVersion the version of the offchainConfig - * @param offchainConfig configuration values that are used off-chain - * @param billingTokens the list of valid billing tokens - * @param billingConfigs the configurations for each billing token - */ - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - IERC20[] memory billingTokens, - BillingConfig[] memory billingConfigs - ) public onlyOwner { - if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); - if (f == 0) revert IncorrectNumberOfFaultyOracles(); - if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); - if (billingTokens.length != billingConfigs.length) revert ParameterLengthError(); - // set billing config for tokens - _setBillingConfig(billingTokens, billingConfigs); - - _updateTransmitters(signers, transmitters); - - s_hotVars = HotVars({ - f: f, - stalenessSeconds: onchainConfig.stalenessSeconds, - gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, - paused: s_hotVars.paused, - reentrancyGuard: s_hotVars.reentrancyGuard, - totalPremium: s_hotVars.totalPremium, - latestEpoch: 0, // DON restarts epoch - reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, - chainModule: onchainConfig.chainModule - }); - - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); - uint32 newConfigCount = s_storage.configCount + 1; - - s_storage = Storage({ - checkGasLimit: onchainConfig.checkGasLimit, - maxPerformGas: onchainConfig.maxPerformGas, - transcoder: onchainConfig.transcoder, - maxCheckDataSize: onchainConfig.maxCheckDataSize, - maxPerformDataSize: onchainConfig.maxPerformDataSize, - maxRevertDataSize: onchainConfig.maxRevertDataSize, - upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, - financeAdmin: onchainConfig.financeAdmin, - nonce: s_storage.nonce, - configCount: newConfigCount, - latestConfigBlockNumber: newLatestConfigBlockNumber - }); - s_fallbackGasPrice = onchainConfig.fallbackGasPrice; - s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; - s_fallbackNativePrice = onchainConfig.fallbackNativePrice; - - bytes memory onchainConfigBytes = abi.encode(onchainConfig); - - s_latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - - for (uint256 idx = s_registrars.length(); idx > 0; idx--) { - s_registrars.remove(s_registrars.at(idx - 1)); - } - - for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { - s_registrars.add(onchainConfig.registrars[idx]); - } - - emit ConfigSet( - previousConfigBlockNumber, - s_latestConfigDigest, - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - } - - /** - * @inheritdoc OCR2Abstract - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); - } - - /** - * @inheritdoc OCR2Abstract - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_latestConfigDigest, s_hotVars.latestEpoch); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol deleted file mode 100644 index 354a6a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryBase2_3.sol +++ /dev/null @@ -1,1216 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * AutomationRegistry and AutomationRegistryLogic - * @dev all errors, events, and internal functions should live here - */ -// solhint-disable-next-line max-states-count -abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; - bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint256 internal constant PERFORM_GAS_CUSHION = 5_000; - uint256 internal constant PPB_BASE = 1_000_000_000; - uint32 internal constant UINT32_MAX = type(uint32).max; - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - uint8 internal constant UPKEEP_VERSION_BASE = 4; - - // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation - // These values are calibrated using hardhat tests which simulate various cases and verify that - // the variables result in accurate estimation - uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps - uint256 internal constant REGISTRY_LOG_OVERHEAD = 123_500; // Fixed gas overhead for log upkeeps - uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f - uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead - - // The overhead (in bytes) in addition to perform data for upkeep sent in calldata - // This includes overhead for all struct encoding as well as report signatures - // There is a fixed component and a per signer component. This is calculated exactly by doing abi encoding - uint256 internal constant TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD = 932; - uint256 internal constant TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD = 64; - - // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the - // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants - // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that - // the variables result in accurate estimation - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_200; // Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 14_200; // Overhead per upkeep performed in batch - - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_linkUSDFeed; - AggregatorV3Interface internal immutable i_nativeUSDFeed; - AggregatorV3Interface internal immutable i_fastGasFeed; - address internal immutable i_automationForwarderLogic; - address internal immutable i_allowedReadOnlyAddress; - IWrappedNative internal immutable i_wrappedNativeToken; - - /** - * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit - * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path - */ - - // Upkeep storage - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit - mapping(uint256 => address) internal s_upkeepAdmin; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - mapping(bytes32 => bool) internal s_dedupKeys; - // Registry config and state - EnumerableSet.AddressSet internal s_registrars; - mapping(address => Transmitter) internal s_transmitters; - mapping(address => Signer) internal s_signers; - address[] internal s_signersList; // s_signersList contains the signing address of each oracle - address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle - EnumerableSet.AddressSet internal s_deactivatedTransmitters; - mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. - mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter - bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification - HotVars internal s_hotVars; // Mixture of config and state, used in transmit - Storage internal s_storage; // Mixture of config and state, not used in transmit - uint256 internal s_fallbackGasPrice; - uint256 internal s_fallbackLinkPrice; - uint256 internal s_fallbackNativePrice; - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro - mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers - mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep - mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep - mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin - // billing - mapping(IERC20 billingToken => uint256 reserveAmount) internal s_reserveAmounts; // unspent user deposits + unwithdrawn NOP payments - mapping(IERC20 billingToken => BillingConfig billingConfig) internal s_billingConfigs; // billing configurations for different tokens - mapping(uint256 upkeepID => BillingOverrides billingOverrides) internal s_billingOverrides; // billing overrides for specific upkeeps - IERC20[] internal s_billingTokens; // list of billing tokens - PayoutMode internal s_payoutMode; - - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientBalance(uint256 available, uint256 requested); - error InsufficientLinkLiquidity(); - error InvalidDataLength(); - error InvalidFeed(); - error InvalidTrigger(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidToken(); - error InvalidTransmitter(); - error InvalidTriggerType(); - error MigrationNotPermitted(); - error MustSettleOffchain(); - error MustSettleOnchain(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyFinanceAdmin(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error TransferFailed(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - error ZeroAddressNotAllowed(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum Trigger { - CONDITION, - LOG - } - - enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, - CALLBACK_REVERTED, - REVERT_DATA_EXCEEDS_LIMIT, - REGISTRY_PAUSED - } - - enum PayoutMode { - ON_CHAIN, - OFF_CHAIN - } - - /** - * @notice OnchainConfig of the registry - * @dev used only in setConfig() - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member maxPerformGas max performGas allowed for an upkeep on this registry - * @member maxCheckDataSize max length of checkData bytes - * @member maxPerformDataSize max length of performData bytes - * @member maxRevertDataSize max length of revertData bytes - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrars addresses of the registrar contracts - * @member upkeepPrivilegeManager address which can set privilege for upkeeps - * @member reorgProtectionEnabled if this registry enables re-org protection checks - * @member chainModule the chain specific module - */ - struct OnchainConfig { - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - address transcoder; - // 1 word full - bool reorgProtectionEnabled; - uint24 stalenessSeconds; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - address upkeepPrivilegeManager; - // 2 words full - uint16 gasCeilingMultiplier; - address financeAdmin; - // 3 words - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - uint256 fallbackNativePrice; - address[] registrars; - IChainModule chainModule; - } - - /** - * @notice relevant state of an upkeep which is used in transmit function - * @member paused if this upkeep has been paused - * @member overridesEnabled if this upkeep has overrides enabled - * @member performGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member forwarder the forwarder contract to use for this upkeep - * @member amountSpent the amount this upkeep has spent, in the upkeep's billing token - * @member balance the balance of this upkeep - * @member lastPerformedBlockNumber the last block number when this upkeep was performed - */ - struct Upkeep { - bool paused; - bool overridesEnabled; - uint32 performGas; - uint32 maxValidBlocknumber; - IAutomationForwarder forwarder; - // 2 bytes left in 1st EVM word - read in transmit path - uint128 amountSpent; - uint96 balance; - uint32 lastPerformedBlockNumber; - // 0 bytes left in 2nd EVM word - written in transmit path - IERC20 billingToken; - // 12 bytes left in 3rd EVM word - read in transmit path - } - - /// @dev Config + State storage struct which is on hot transmit path - struct HotVars { - uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium - uint32 latestEpoch; // │ latest epoch for which a report was transmitted - uint24 stalenessSeconds; // │ Staleness tolerance for feeds - uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound - uint8 f; // │ maximum number of faulty oracles - bool paused; // │ pause switch for all upkeeps in the registry - bool reentrancyGuard; // | guard against reentrancy - bool reorgProtectionEnabled; // ─╯ if this registry should enable the re-org protection mechanism - IChainModule chainModule; // the interface of chain specific module - } - - /// @dev Config + State storage struct which is not on hot transmit path - struct Storage { - address transcoder; // Address of transcoder contract used in migrations - uint32 checkGasLimit; // Gas limit allowed in checkUpkeep - uint32 maxPerformGas; // Max gas an upkeep can use on this registry - uint32 nonce; // Nonce for each upkeep created - // 1 EVM word full - address upkeepPrivilegeManager; // address which can set privilege for upkeeps - uint32 configCount; // incremented each time a new config is posted, The count is incorporated into the config digest to prevent replay attacks. - uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs - uint32 maxCheckDataSize; // max length of checkData bytes - // 2 EVM word full - address financeAdmin; // address which can withdraw funds from the contract - uint32 maxPerformDataSize; // max length of performData bytes - uint32 maxRevertDataSize; // max length of revertData bytes - // 4 bytes left in 3rd EVM word - } - - /// @dev Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkUSD; - uint256[] upkeepIds; - uint256[] gasLimits; - bytes[] triggers; - bytes[] performDatas; - } - - /** - * @dev This struct is used to maintain run time information about an upkeep in transmit function - * @member upkeep the upkeep struct - * @member earlyChecksPassed whether the upkeep passed early checks before perform - * @member performSuccess whether the perform was successful - * @member triggerType the type of trigger - * @member gasUsed gasUsed by this upkeep in perform - * @member calldataWeight weight assigned to this upkeep for its contribution to calldata. It is used to split L1 fee - * @member dedupID unique ID used to dedup an upkeep/trigger combo - */ - struct UpkeepTransmitInfo { - Upkeep upkeep; - bool earlyChecksPassed; - bool performSuccess; - Trigger triggerType; - uint256 gasUsed; - uint256 calldataWeight; - bytes32 dedupID; - } - - /** - * @notice holds information about a transmiter / node in the DON - * @member active can this transmitter submit reports - * @member index of oracle in s_signersList/s_transmittersList - * @member balance a node's balance in LINK - * @member lastCollected the total balance at which the node last withdrew - * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK - */ - struct Transmitter { - bool active; - uint8 index; - uint96 balance; - uint96 lastCollected; - } - - struct TransmitterPayeeInfo { - address transmitterAddress; - address payeeAddress; - } - - struct Signer { - bool active; - // Index of oracle in s_signersList/s_transmittersList - uint8 index; - } - - /** - * @notice the trigger structure conditional trigger type - */ - struct ConditionalTrigger { - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the trigger structure of log upkeeps - * @dev NOTE that blockNum / blockHash describe the block used for the callback, - * not necessarily the block number that the log was emitted in!!!! - */ - struct LogTrigger { - bytes32 logBlockHash; - bytes32 txHash; - uint32 logIndex; - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the billing config of a token - * @dev this is a storage struct - */ - // solhint-disable-next-line gas-struct-packing - struct BillingConfig { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; // min fee is $0.00001, max fee is $167 - AggregatorV3Interface priceFeed; - uint8 decimals; - // 1st word, read in calculating BillingTokenPaymentParams - uint256 fallbackPrice; - // 2nd word only read if stale - uint96 minSpend; - // 3rd word only read during cancellation - } - - /** - * @notice override-able billing params of a billing token - */ - struct BillingOverrides { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - } - - /** - * @notice pricing params for a billing token - * @dev this is a memory-only struct, so struct packing is less important - */ - struct BillingTokenPaymentParams { - uint8 decimals; - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - uint256 priceUSD; - } - - /** - * @notice struct containing price & payment information used in calculating payment amount - * @member gasLimit the amount of gas used - * @member gasOverhead the amount of gas overhead - * @member l1CostWei the amount to be charged for L1 fee in wei - * @member fastGasWei the fast gas price - * @member linkUSD the exchange ratio between LINK and USD - * @member nativeUSD the exchange ratio between the chain's native token and USD - * @member billingToken the billing token - * @member billingTokenParams the payment params specific to a particular payment token - * @member isTransaction is this an eth_call or a transaction - */ - struct PaymentParams { - uint256 gasLimit; - uint256 gasOverhead; - uint256 l1CostWei; - uint256 fastGasWei; - uint256 linkUSD; - uint256 nativeUSD; - IERC20 billingToken; - BillingTokenPaymentParams billingTokenParams; - bool isTransaction; - } - - /** - * @notice struct containing receipt information about a payment or cost estimation - * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals - * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals - * @member gasReimbursementInJuels the amount to reimburse a node for gas spent - * @member premiumInJuels the premium paid to NOPs, shared between all nodes - */ - // solhint-disable-next-line gas-struct-packing - struct PaymentReceipt { - uint96 gasChargeInBillingToken; - uint96 premiumInBillingToken; - // one word ends - uint96 gasReimbursementInJuels; - uint96 premiumInJuels; - // second word ends - IERC20 billingToken; - uint96 linkUSD; - // third word ends - uint96 nativeUSD; - uint96 billingUSD; - // fourth word ends - } - - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event BillingConfigOverridden(uint256 indexed id, BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - event BillingConfigSet(IERC20 indexed token, BillingConfig config); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - event Unpaused(address account); - - /** - * @param link address of the LINK Token - * @param linkUSDFeed address of the LINK/USD price feed - * @param nativeUSDFeed address of the Native/USD price feed - * @param fastGasFeed address of the Fast Gas price feed - * @param automationForwarderLogic the address of automation forwarder logic - * @param allowedReadOnlyAddress the address of the allowed read only address - * @param payoutMode the payout mode - */ - constructor( - address link, - address linkUSDFeed, - address nativeUSDFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress, - PayoutMode payoutMode, - address wrappedNativeTokenAddress - ) ConfirmedOwner(msg.sender) { - i_link = LinkTokenInterface(link); - i_linkUSDFeed = AggregatorV3Interface(linkUSDFeed); - i_nativeUSDFeed = AggregatorV3Interface(nativeUSDFeed); - i_fastGasFeed = AggregatorV3Interface(fastGasFeed); - i_automationForwarderLogic = automationForwarderLogic; - i_allowedReadOnlyAddress = allowedReadOnlyAddress; - s_payoutMode = payoutMode; - i_wrappedNativeToken = IWrappedNative(wrappedNativeTokenAddress); - if (i_linkUSDFeed.decimals() != i_nativeUSDFeed.decimals()) { - revert InvalidFeed(); - } - } - - // ================================================================ - // | INTERNAL FUNCTIONS ONLY | - // ================================================================ - - /** - * @dev creates a new upkeep with the given fields - * @param id the id of the upkeep - * @param upkeep the upkeep to create - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data which is passed to user's checkUpkeep - * @param triggerConfig the trigger config for this upkeep - * @param offchainConfig the off-chain config of this upkeep - */ - function _createUpkeep( - uint256 id, - Upkeep memory upkeep, - address admin, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) internal { - if (s_hotVars.paused) revert RegistryPaused(); - if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) - revert GasLimitOutsideRange(); - if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); - if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidToken(); - s_upkeep[id] = upkeep; - s_upkeepAdmin[id] = admin; - s_checkData[id] = checkData; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + upkeep.balance; - s_upkeepTriggerConfig[id] = triggerConfig; - s_upkeepOffchainConfig[id] = offchainConfig; - s_upkeepIDs.add(id); - } - - /** - * @dev creates an ID for the upkeep based on the upkeep's type - * @dev the format of the ID looks like this: - * ****00000000000X**************** - * 4 bytes of entropy - * 11 bytes of zeros - * 1 identifying byte for the trigger type - * 16 bytes of entropy - * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique - * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only - * see the first 4 and last 4 hex values ex 0x1234...ABCD - */ - function _createID(Trigger triggerType) internal view returns (uint256) { - bytes1 empty; - IChainModule chainModule = s_hotVars.chainModule; - bytes memory idBytes = abi.encodePacked( - keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) - ); - for (uint256 idx = 4; idx < 15; idx++) { - idBytes[idx] = empty; - } - idBytes[15] = bytes1(uint8(triggerType)); - return uint256(bytes32(idBytes)); - } - - /** - * @dev retrieves feed data for fast gas/native and link/native prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData( - HotVars memory hotVars - ) internal view returns (uint256 gasWei, uint256 linkUSD, uint256 nativeUSD) { - uint32 stalenessSeconds = hotVars.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = i_linkUSDFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - linkUSD = s_fallbackLinkPrice; - } else { - linkUSD = uint256(feedValue); - } - return (gasWei, linkUSD, _getNativeUSD(hotVars)); - } - - /** - * @dev this price has it's own getter for use in the transmit() hot path - * in the future, all price data should be included in the report instead of - * getting read during execution - */ - function _getNativeUSD(HotVars memory hotVars) internal view returns (uint256) { - (, int256 feedValue, , uint256 timestamp, ) = i_nativeUSDFeed.latestRoundData(); - if ( - feedValue <= 0 || - block.timestamp < timestamp || - (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) - ) { - return s_fallbackNativePrice; - } else { - return uint256(feedValue); - } - } - - /** - * @dev gets the price and billing params for a specific billing token - */ - function _getBillingTokenPaymentParams( - HotVars memory hotVars, - IERC20 billingToken - ) internal view returns (BillingTokenPaymentParams memory paymentParams) { - BillingConfig storage config = s_billingConfigs[billingToken]; - paymentParams.flatFeeMilliCents = config.flatFeeMilliCents; - paymentParams.gasFeePPB = config.gasFeePPB; - paymentParams.decimals = config.decimals; - (, int256 feedValue, , uint256 timestamp, ) = config.priceFeed.latestRoundData(); - if ( - feedValue <= 0 || - block.timestamp < timestamp || - (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) - ) { - paymentParams.priceUSD = config.fallbackPrice; - } else { - paymentParams.priceUSD = uint256(feedValue); - } - return paymentParams; - } - - /** - * @param hotVars the hot path variables - * @param paymentParams the pricing data and gas usage data - * @return receipt the receipt of payment with pricing breakdown - * @dev use of PaymentParams struct is necessary to avoid stack too deep errors - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @dev 1 USD = 1e18 attoUSD - * @dev 1 USD = 1e26 hexaicosaUSD (had to borrow this prefix from geometry because there is no metric prefix for 1e-26) - * @dev 1 millicent = 1e-5 USD = 1e13 attoUSD - */ - function _calculatePaymentAmount( - HotVars memory hotVars, - PaymentParams memory paymentParams - ) internal view returns (PaymentReceipt memory receipt) { - uint256 decimals = paymentParams.billingTokenParams.decimals; - uint256 gasWei = paymentParams.fastGasWei * hotVars.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (paymentParams.isTransaction && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - - // scaling factor is based on decimals of billing token, and applies to premium and gasCharge - uint256 numeratorScalingFactor = decimals > 18 ? 10 ** (decimals - 18) : 1; - uint256 denominatorScalingFactor = decimals < 18 ? 10 ** (18 - decimals) : 1; - - // gas calculation - uint256 gasPaymentHexaicosaUSD = (gasWei * - (paymentParams.gasLimit + paymentParams.gasOverhead) + - paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed - // gasChargeInBillingToken is scaled by the billing token's decimals. Round up to ensure a minimum billing token is charged for gas - receipt.gasChargeInBillingToken = SafeCast.toUint96( - ((gasPaymentHexaicosaUSD * numeratorScalingFactor) + - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) - ); - // 18 decimals: 26 decimals / 8 decimals - receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); - - // premium calculation - uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD - uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) * - paymentParams.billingTokenParams.gasFeePPB * - paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; - // premium is scaled by the billing token's decimals. Round up to ensure at least minimum charge - receipt.premiumInBillingToken = SafeCast.toUint96( - ((premiumHexaicosaUSD * numeratorScalingFactor) + - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) - ); - receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); - - receipt.billingToken = paymentParams.billingToken; - receipt.linkUSD = SafeCast.toUint96(paymentParams.linkUSD); - receipt.nativeUSD = SafeCast.toUint96(paymentParams.nativeUSD); - receipt.billingUSD = SafeCast.toUint96(paymentParams.billingTokenParams.priceUSD); - - return receipt; - } - - /** - * @dev calculates the max payment for an upkeep. Called during checkUpkeep simulation and assumes - * maximum gas overhead, L1 fee - */ - function _getMaxPayment( - uint256 upkeepId, - HotVars memory hotVars, - Trigger triggerType, - uint32 performGas, - uint256 fastGasWei, - uint256 linkUSD, - uint256 nativeUSD, - IERC20 billingToken - ) internal view returns (uint96) { - uint256 maxL1Fee; - uint256 maxGasOverhead; - - { - if (triggerType == Trigger.CONDITION) { - maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; - } else if (triggerType == Trigger.LOG) { - maxGasOverhead = REGISTRY_LOG_OVERHEAD; - } else { - revert InvalidTriggerType(); - } - uint256 maxCalldataSize = s_storage.maxPerformDataSize + - TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD + - (TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1)); - (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) = s_hotVars.chainModule.getGasOverhead(); - maxGasOverhead += - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + - ((REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD + chainModulePerByteOverhead) * maxCalldataSize) + - chainModuleFixedOverhead; - maxL1Fee = hotVars.gasCeilingMultiplier * hotVars.chainModule.getMaxL1Fee(maxCalldataSize); - } - - BillingTokenPaymentParams memory paymentParams = _getBillingTokenPaymentParams(hotVars, billingToken); - if (s_upkeep[upkeepId].overridesEnabled) { - BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; - // use the overridden configs - paymentParams.gasFeePPB = billingOverrides.gasFeePPB; - paymentParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; - } - - PaymentReceipt memory receipt = _calculatePaymentAmount( - hotVars, - PaymentParams({ - gasLimit: performGas, - gasOverhead: maxGasOverhead, - l1CostWei: maxL1Fee, - fastGasWei: fastGasWei, - linkUSD: linkUSD, - nativeUSD: nativeUSD, - billingToken: billingToken, - billingTokenParams: paymentParams, - isTransaction: false - }) - ); - - return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; - } - - /** - * @dev move a transmitter's balance from total pool to withdrawable balance - */ - function _updateTransmitterBalanceFromPool( - address transmitterAddress, - uint96 totalPremium, - uint96 payeeCount - ) internal returns (uint96) { - Transmitter memory transmitter = s_transmitters[transmitterAddress]; - - if (transmitter.active) { - uint96 uncollected = totalPremium - transmitter.lastCollected; - uint96 due = uncollected / payeeCount; - transmitter.balance += due; - transmitter.lastCollected += due * payeeCount; - s_transmitters[transmitterAddress] = transmitter; - } - - return transmitter.balance; - } - - /** - * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) - */ - function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { - bytes32 rawID = bytes32(upkeepId); - bytes1 empty = bytes1(0); - for (uint256 idx = 4; idx < 15; idx++) { - if (rawID[idx] != empty) { - // old IDs that were created before this standard and migrated to this registry - return Trigger.CONDITION; - } - } - return Trigger(uint8(rawID[15])); - } - - function _checkPayload( - uint256 upkeepId, - Trigger triggerType, - bytes memory triggerData - ) internal view returns (bytes memory) { - if (triggerType == Trigger.CONDITION) { - return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); - } else if (triggerType == Trigger.LOG) { - Log memory log = abi.decode(triggerData, (Log)); - return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); - } - revert InvalidTriggerType(); - } - - /** - * @dev _decodeReport decodes a serialized report into a Report struct - */ - function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { - Report memory report = abi.decode(rawReport, (Report)); - uint256 expectedLength = report.upkeepIds.length; - if ( - report.gasLimits.length != expectedLength || - report.triggers.length != expectedLength || - report.performDatas.length != expectedLength - ) { - revert InvalidReport(); - } - return report; - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - * @return bool whether the upkeep should be performed - * @return bytes32 dedupID for preventing duplicate performances of this trigger - */ - function _prePerformChecks( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - bytes32 dedupID; - if (transmitInfo.triggerType == Trigger.CONDITION) { - if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) - return (false, dedupID); - } else if (transmitInfo.triggerType == Trigger.LOG) { - bool valid; - (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); - if (!valid) return (false, dedupID); - } else { - revert InvalidTriggerType(); - } - if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { - // Can happen when an upkeep got cancelled after report was generated. - // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice - emit CancelledUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - */ - function _validateConditionalTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool) { - ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); - if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { - // Can happen when another report performed this upkeep after this report was generated - emit StaleUpkeepReport(upkeepId, rawTrigger); - return false; - } - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // There are two cases of reorged report - // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain - // which is always protected against - // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is - // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain - // when it is sent - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return false; - } - return true; - } - - function _validateLogTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); - bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // Reorg protection is same as conditional trigger upkeeps - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - if (s_dedupKeys[dedupID]) { - emit StaleUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Verify signatures attached to report - */ - function _verifyReportSignature( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) internal view { - bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount = 0; - - Signer memory signer; - address signerAddress; - for (uint256 i = 0; i < rs.length; i++) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - signer = s_signers[signerAddress]; - if (!signer.active) revert OnlyActiveSigners(); - unchecked { - signedCount += 1 << (8 * signer.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); - } - - /** - * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances - * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID - */ - function _updateTriggerMarker( - uint256 upkeepID, - uint256 blocknumber, - UpkeepTransmitInfo memory upkeepTransmitInfo - ) internal { - if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { - s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); - } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { - s_dedupKeys[upkeepTransmitInfo.dedupID] = true; - emit DedupKeyAdded(upkeepTransmitInfo.dedupID); - } - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * transmitter and the exact gas required by the Upkeep - */ - function _performUpkeep( - IAutomationForwarder forwarder, - uint256 performGas, - bytes memory performData - ) internal nonReentrant returns (bool success, uint256 gasUsed) { - performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); - return forwarder.forward(performGas, performData); - } - - /** - * @dev handles the payment processing after an upkeep has been performed. - * Deducts an upkeep's balance and increases the amount spent. - */ - function _handlePayment( - HotVars memory hotVars, - PaymentParams memory paymentParams, - uint256 upkeepId, - Upkeep memory upkeep - ) internal returns (PaymentReceipt memory) { - if (upkeep.overridesEnabled) { - BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; - // use the overridden configs - paymentParams.billingTokenParams.gasFeePPB = billingOverrides.gasFeePPB; - paymentParams.billingTokenParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; - } - - PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); - - // balance is in the token's native decimals - uint96 balance = upkeep.balance; - // payment is in the token's native decimals - uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; - - // scaling factors to adjust decimals between billing token and LINK - uint256 decimals = paymentParams.billingTokenParams.decimals; - uint256 scalingFactor1 = decimals < 18 ? 10 ** (18 - decimals) : 1; - uint256 scalingFactor2 = decimals > 18 ? 10 ** (decimals - 18) : 1; - - // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user - // can't cover the amount owed - if (balance < receipt.gasChargeInBillingToken) { - // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON - payment = balance; - receipt.gasReimbursementInJuels = SafeCast.toUint96( - (balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / - (paymentParams.linkUSD * scalingFactor2) - ); - receipt.premiumInJuels = 0; - receipt.premiumInBillingToken = 0; - receipt.gasChargeInBillingToken = balance; - } else if (balance < payment) { - // if the user can cover the gas fee, but not the premium, then reduce the premium - payment = balance; - receipt.premiumInJuels = SafeCast.toUint96( - ((balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / - (paymentParams.linkUSD * scalingFactor2)) - receipt.gasReimbursementInJuels - ); - // round up - receipt.premiumInBillingToken = SafeCast.toUint96( - ((receipt.premiumInJuels * paymentParams.linkUSD * scalingFactor2) + - (paymentParams.billingTokenParams.priceUSD * scalingFactor1 - 1)) / - (paymentParams.billingTokenParams.priceUSD * scalingFactor1) - ); - } - - s_upkeep[upkeepId].balance -= payment; - s_upkeep[upkeepId].amountSpent += payment; - s_reserveAmounts[paymentParams.billingToken] -= payment; - - emit UpkeepCharged(upkeepId, receipt); - return receipt; - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { - if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); - if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_hotVars.reentrancyGuard) revert ReentrantCall(); - s_hotVars.reentrancyGuard = true; - _; - s_hotVars.reentrancyGuard = false; - } - - /** - * @notice only allows a pre-configured address to initiate offchain read - */ - function _preventExecution() internal view { - // solhint-disable-next-line avoid-tx-origin - if (tx.origin != i_allowedReadOnlyAddress) { - revert OnlySimulatedBackend(); - } - } - - /** - * @notice only allows finance admin to call the function - */ - function _onlyFinanceAdminAllowed() internal view { - if (msg.sender != s_storage.financeAdmin) { - revert OnlyFinanceAdmin(); - } - } - - /** - * @notice only allows privilege manager to call the function - */ - function _onlyPrivilegeManagerAllowed() internal view { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - } - - /** - * @notice sets billing configuration for a token - * @param billingTokens the addresses of tokens - * @param billingConfigs the configs for tokens - */ - function _setBillingConfig(IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) internal { - // Clear existing data - for (uint256 i = 0; i < s_billingTokens.length; i++) { - delete s_billingConfigs[s_billingTokens[i]]; - } - delete s_billingTokens; - - PayoutMode mode = s_payoutMode; - for (uint256 i = 0; i < billingTokens.length; i++) { - IERC20 token = billingTokens[i]; - BillingConfig memory config = billingConfigs[i]; - - // most ERC20 tokens are 18 decimals, priceFeed must be 8 decimals - if (config.decimals != token.decimals() || config.priceFeed.decimals() != 8) { - revert InvalidToken(); - } - - // if LINK is a billing option, payout mode must be ON_CHAIN - if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { - revert InvalidToken(); - } - if (address(token) == ZERO_ADDRESS || address(config.priceFeed) == ZERO_ADDRESS) { - revert ZeroAddressNotAllowed(); - } - - // if this is a new token, add it to tokens list. Otherwise revert - if (address(s_billingConfigs[token].priceFeed) != ZERO_ADDRESS) { - revert DuplicateEntry(); - } - s_billingTokens.push(token); - - // update the billing config for an existing token or add a new one - s_billingConfigs[token] = config; - - emit BillingConfigSet(token, config); - } - } - - /** - * @notice updates the signers and transmitters lists - */ - function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { - uint96 transmittersListLength = uint96(s_transmittersList.length); - uint96 totalPremium = s_hotVars.totalPremium; - - // move all pooled payments out of the pool to each transmitter's balance - for (uint256 i = 0; i < s_transmittersList.length; i++) { - _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); - } - - // remove any old signer/transmitter addresses - address transmitterAddress; - PayoutMode mode = s_payoutMode; - for (uint256 i = 0; i < s_transmittersList.length; i++) { - transmitterAddress = s_transmittersList[i]; - delete s_signers[s_signersList[i]]; - // Do not delete the whole transmitter struct as it has balance information stored - s_transmitters[transmitterAddress].active = false; - if (mode == PayoutMode.OFF_CHAIN && s_transmitters[transmitterAddress].balance > 0) { - s_deactivatedTransmitters.add(transmitterAddress); - } - } - delete s_signersList; - delete s_transmittersList; - - // add new signer/transmitter addresses - Transmitter memory transmitter; - for (uint256 i = 0; i < signers.length; i++) { - if (s_signers[signers[i]].active) revert RepeatedSigner(); - if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); - s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); - - transmitterAddress = transmitters[i]; - if (transmitterAddress == ZERO_ADDRESS) revert InvalidTransmitter(); - transmitter = s_transmitters[transmitterAddress]; - if (transmitter.active) revert RepeatedTransmitter(); - transmitter.active = true; - transmitter.index = uint8(i); - // new transmitters start afresh from current totalPremium - // some spare change of premium from previous pool will be forfeited - transmitter.lastCollected = s_hotVars.totalPremium; - s_transmitters[transmitterAddress] = transmitter; - if (mode == PayoutMode.OFF_CHAIN) { - s_deactivatedTransmitters.remove(transmitterAddress); - } - } - - s_signersList = signers; - s_transmittersList = transmitters; - } - - /** - * @notice returns the size of the LINK liquidity pool - # @dev LINK max supply < 2^96, so casting to int256 is safe - */ - function _linkAvailableForPayment() internal view returns (int256) { - return int256(i_link.balanceOf(address(this))) - int256(s_reserveAmounts[IERC20(address(i_link))]); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol deleted file mode 100644 index 1ef3991..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicA2_3.sol +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; -import {AutomationRegistryLogicB2_3} from "./AutomationRegistryLogicB2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {AutomationForwarder} from "../AutomationForwarder.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Logic contract, works in tandem with AutomationRegistry as a proxy - */ -contract AutomationRegistryLogicA2_3 is AutomationRegistryBase2_3, Chainable, IERC677Receiver { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - using SafeERC20 for IERC20; - - /** - * @param logicB the address of the second logic contract - * @dev we cast the contract to logicC in order to call logicC functions (via fallback) - */ - constructor( - AutomationRegistryLogicB2_3 logicB - ) - AutomationRegistryBase2_3( - AutomationRegistryLogicC2_3(address(logicB)).getLinkAddress(), - AutomationRegistryLogicC2_3(address(logicB)).getLinkUSDFeedAddress(), - AutomationRegistryLogicC2_3(address(logicB)).getNativeUSDFeedAddress(), - AutomationRegistryLogicC2_3(address(logicB)).getFastGasFeedAddress(), - AutomationRegistryLogicC2_3(address(logicB)).getAutomationForwarderLogic(), - AutomationRegistryLogicC2_3(address(logicB)).getAllowedReadOnlyAddress(), - AutomationRegistryLogicC2_3(address(logicB)).getPayoutMode(), - AutomationRegistryLogicC2_3(address(logicB)).getWrappedNativeTokenAddress() - ) - Chainable(address(logicB)) - {} - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken(); - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount; - emit FundsAdded(id, sender, uint96(amount)); - } - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param triggerType the trigger for the upkeep - * @param billingToken the billing token for the upkeep - * @param checkData data passed to the contract when checking for upkeep - * @param triggerConfig the config for the trigger - * @param offchainConfig arbitrary offchain config for the upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - Trigger triggerType, - IERC20 billingToken, - bytes calldata checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) public returns (uint256 id) { - if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); - if (!target.isContract()) revert NotAContract(); - id = _createID(triggerType); - IAutomationForwarder forwarder = IAutomationForwarder( - address(new AutomationForwarder(target, address(this), i_automationForwarderLogic)) - ); - _createUpkeep( - id, - Upkeep({ - overridesEnabled: false, - performGas: gasLimit, - balance: 0, - maxValidBlocknumber: UINT32_MAX, - lastPerformedBlockNumber: 0, - amountSpent: 0, - paused: false, - forwarder: forwarder, - billingToken: billingToken - }), - admin, - checkData, - triggerConfig, - offchainConfig - ); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - emit UpkeepCheckDataSet(id, checkData); - emit UpkeepTriggerConfigSet(id, triggerConfig); - emit UpkeepOffchainConfigSet(id, offchainConfig); - return (id); - } - - /** - * @notice cancels an upkeep - * @param id the upkeepID to cancel - * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to - * allow any pending performUpkeep txs time to get confirmed - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool isOwner = msg.sender == owner(); - uint96 minSpend = s_billingConfigs[upkeep.billingToken].minSpend; - - uint256 height = s_hotVars.chainModule.blockNumber(); - if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); - - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minSpend is not met - uint96 cancellationFee = 0; - // cancellationFee is min(max(minSpend - amountSpent, 0), amountLeft) - if (upkeep.amountSpent < minSpend) { - cancellationFee = minSpend - uint96(upkeep.amountSpent); - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice migrates upkeeps from one registry to another. - * @param ids the upkeepIDs to migrate - * @param destination the destination registry address - * @dev a transcoder must be set in order to enable migration - * @dev migration permissions must be set on *both* sending and receiving registries - * @dev only an upkeep admin can migrate their upkeeps - * @dev this function is most gas-efficient if upkeepIDs are sorted by billing token - * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not migrated in this function - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - - IERC20 billingToken; - uint256 balanceToTransfer; - uint256 id; - Upkeep memory upkeep; - address[] memory admins = new address[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - bytes[] memory checkDatas = new bytes[](ids.length); - bytes[] memory triggerConfigs = new bytes[](ids.length); - bytes[] memory offchainConfigs = new bytes[](ids.length); - - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - - if (idx == 0) { - billingToken = upkeep.billingToken; - balanceToTransfer = upkeep.balance; - } - - // if we encounter a new billing token, send the sum from the last billing token to the destination registry - if (upkeep.billingToken != billingToken) { - s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; - billingToken.safeTransfer(destination, balanceToTransfer); - billingToken = upkeep.billingToken; - balanceToTransfer = upkeep.balance; - } else if (idx != 0) { - balanceToTransfer += upkeep.balance; - } - - _requireAdminAndNotCancelled(id); - upkeep.forwarder.updateRegistry(destination); - - upkeeps[idx] = upkeep; - admins[idx] = s_upkeepAdmin[id]; - checkDatas[idx] = s_checkData[id]; - triggerConfigs[idx] = s_upkeepTriggerConfig[id]; - offchainConfigs[idx] = s_upkeepOffchainConfig[id]; - delete s_upkeep[id]; - delete s_checkData[id]; - delete s_upkeepTriggerConfig[id]; - delete s_upkeepOffchainConfig[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - delete s_upkeepAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - // always transfer the rolling sum in the end - s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; - billingToken.safeTransfer(destination, balanceToTransfer); - - bytes memory encodedUpkeeps = abi.encode( - ids, - upkeeps, - new address[](ids.length), - admins, - checkDatas, - triggerConfigs, - offchainConfigs - ); - MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( - UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( - UPKEEP_VERSION_BASE, - MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), - encodedUpkeeps - ) - ); - } - - /** - * @notice received upkeeps migrated from another registry - * @param encodedUpkeeps the raw upkeep data to import - * @dev this function is never called directly, it is only called by another registry's migrate function - * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not handled in this function - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - ( - uint256[] memory ids, - Upkeep[] memory upkeeps, - address[] memory targets, - address[] memory upkeepAdmins, - bytes[] memory checkDatas, - bytes[] memory triggerConfigs, - bytes[] memory offchainConfigs - ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); - for (uint256 idx = 0; idx < ids.length; idx++) { - if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { - upkeeps[idx].forwarder = IAutomationForwarder( - address(new AutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) - ); - } - _createUpkeep( - ids[idx], - upkeeps[idx], - upkeepAdmins[idx], - checkDatas[idx], - triggerConfigs[idx], - offchainConfigs[idx] - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol deleted file mode 100644 index d854848..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicB2_3.sol +++ /dev/null @@ -1,449 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - using SafeERC20 for IERC20; - - /** - * @param logicC the address of the third logic contract - */ - constructor( - AutomationRegistryLogicC2_3 logicC - ) - AutomationRegistryBase2_3( - logicC.getLinkAddress(), - logicC.getLinkUSDFeedAddress(), - logicC.getNativeUSDFeedAddress(), - logicC.getFastGasFeedAddress(), - logicC.getAutomationForwarderLogic(), - logicC.getAllowedReadOnlyAddress(), - logicC.getPayoutMode(), - logicC.getWrappedNativeTokenAddress() - ) - Chainable(address(logicC)) - {} - - // ================================================================ - // | PIPELINE FUNCTIONS | - // ================================================================ - - /** - * @notice called by the automation DON to check if work is needed - * @param id the upkeep ID to check for work needed - * @param triggerData extra contextual data about the trigger (not used in all code paths) - * @dev this one of the core functions called in the hot path - * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility - * @dev there is an incongruency on what gets returned during failure modes - * ex sometimes we include price data, sometimes we omit it depending on the failure - */ - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - public - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ) - { - _preventExecution(); - - Trigger triggerType = _getTriggerType(id); - HotVars memory hotVars = s_hotVars; - Upkeep memory upkeep = s_upkeep[id]; - - { - uint256 nativeUSD; - uint96 maxPayment; - if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); - if (upkeep.maxValidBlocknumber != UINT32_MAX) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); - if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); - (fastGasWei, linkUSD, nativeUSD) = _getFeedData(hotVars); - maxPayment = _getMaxPayment( - id, - hotVars, - triggerType, - upkeep.performGas, - fastGasWei, - linkUSD, - nativeUSD, - upkeep.billingToken - ); - if (upkeep.balance < maxPayment) { - return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); - } - } - - bytes memory callData = _checkPayload(id, triggerType, triggerData); - - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); - gasUsed = gasUsed - gasleft(); - - if (!success) { - // User's target check reverted. We capture the revert data here and pass it within performData - if (result.length > s_storage.maxRevertDataSize) { - return ( - false, - bytes(""), - UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - } - return ( - upkeepNeeded, - result, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - } - - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, upkeep.performGas, fastGasWei, linkUSD); - - if (performData.length > s_storage.maxPerformDataSize) - return ( - false, - bytes(""), - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkUSD); - } - - /** - * @notice see other checkUpkeep function for description - * @dev this function may be deprecated in a future version of chainlink automation - */ - function checkUpkeep( - uint256 id - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ) - { - return checkUpkeep(id, bytes("")); - } - - /** - * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) - * @param id the upkeepID to execute a callback for - * @param values the values returned from the data streams lookup - * @param extraData the user-provided extra context data - */ - function checkCallback( - uint256 id, - bytes[] memory values, - bytes calldata extraData - ) - external - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); - return executeCallback(id, payload); - } - - /** - * @notice this is a generic callback executor that forwards a call to a user's contract with the configured - * gas limit - * @param id the upkeepID to execute a callback for - * @param payload the data (including function selector) to call on the upkeep target contract - */ - function executeCallback( - uint256 id, - bytes memory payload - ) - public - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - _preventExecution(); - - Upkeep memory upkeep = s_upkeep[id]; - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); - gasUsed = gasUsed - gasleft(); - if (!success) { - return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); - } - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) { - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); - } - if (performData.length > s_storage.maxPerformDataSize) { - return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); - } - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); - } - - /** - * @notice simulates the upkeep with the perform data returned from checkUpkeep - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - * @return success whether the call reverted or not - * @return gasUsed the amount of gas the target contract consumed - */ - function simulatePerformUpkeep( - uint256 id, - bytes calldata performData - ) external returns (bool success, uint256 gasUsed) { - _preventExecution(); - - if (s_hotVars.paused) revert RegistryPaused(); - Upkeep memory upkeep = s_upkeep[id]; - (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); - return (success, gasUsed); - } - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice adds fund to an upkeep - * @param id the upkeepID - * @param amount the amount of funds to add, in the upkeep's billing token - */ - function addFunds(uint256 id, uint96 amount) external payable { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - if (msg.value != 0) { - if (upkeep.billingToken != IERC20(i_wrappedNativeToken)) { - revert InvalidToken(); - } - amount = SafeCast.toUint96(msg.value); - } - - s_upkeep[id].balance = upkeep.balance + amount; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + amount; - - if (msg.value == 0) { - // ERC20 payment - upkeep.billingToken.safeTransferFrom(msg.sender, address(this), amount); - } else { - // native payment - i_wrappedNativeToken.deposit{value: amount}(); - } - - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice overrides the billing config for an upkeep - * @param id the upkeepID - * @param billingOverrides the override-able billing config - */ - function setBillingOverrides(uint256 id, BillingOverrides calldata billingOverrides) external { - _onlyPrivilegeManagerAllowed(); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].overridesEnabled = true; - s_billingOverrides[id] = billingOverrides; - emit BillingConfigOverridden(id, billingOverrides); - } - - /** - * @notice remove the overridden billing config for an upkeep - * @param id the upkeepID - */ - function removeBillingOverrides(uint256 id) external { - _onlyPrivilegeManagerAllowed(); - - s_upkeep[id].overridesEnabled = false; - delete s_billingOverrides[id]; - emit BillingConfigOverrideRemoved(id); - } - - /** - * @notice transfers the address of an admin for an upkeep - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - _requireAdminAndNotCancelled(id); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of an upkeep admin - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = s_upkeepAdmin[id]; - s_upkeepAdmin[id] = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused - */ - function pauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @notice unpauses an upkeep - */ - function unpauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @notice updates the checkData for an upkeep - */ - function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { - _requireAdminAndNotCancelled(id); - if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataSet(id, newCheckData); - } - - /** - * @notice updates the gas limit for an upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - _requireAdminAndNotCancelled(id); - s_upkeep[id].performGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @notice updates the offchain config for an upkeep - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { - _requireAdminAndNotCancelled(id); - s_upkeepOffchainConfig[id] = config; - emit UpkeepOffchainConfigSet(id, config); - } - - /** - * @notice sets the upkeep trigger config - * @param id the upkeepID to change the trigger for - * @param triggerConfig the new trigger config - */ - function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { - _requireAdminAndNotCancelled(id); - s_upkeepTriggerConfig[id] = triggerConfig; - emit UpkeepTriggerConfigSet(id, triggerConfig); - } - - /** - * @notice withdraws an upkeep's funds from an upkeep - * @dev note that an upkeep must be cancelled first!! - */ - function withdrawFunds(uint256 id, address to) external nonReentrant { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); - uint96 amountToWithdraw = s_upkeep[id].balance; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - amountToWithdraw; - s_upkeep[id].balance = 0; - upkeep.billingToken.safeTransfer(to, amountToWithdraw); - emit FundsWithdrawn(id, amountToWithdraw, to); - } - - // ================================================================ - // | FINANCE ACTIONS | - // ================================================================ - - /** - * @notice withdraws excess LINK from the liquidity pool - * @param to the address to send the fees to - * @param amount the amount to withdraw - */ - function withdrawLink(address to, uint256 amount) external { - _onlyFinanceAdminAllowed(); - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - - int256 available = _linkAvailableForPayment(); - if (available < 0) { - revert InsufficientBalance(0, amount); - } else if (amount > uint256(available)) { - revert InsufficientBalance(uint256(available), amount); - } - - bool transferStatus = i_link.transfer(to, amount); - if (!transferStatus) { - revert TransferFailed(); - } - emit FeesWithdrawn(address(i_link), to, amount); - } - - /** - * @notice withdraws non-LINK fees earned by the contract - * @param asset the asset to withdraw - * @param to the address to send the fees to - * @param amount the amount to withdraw - * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity - * to cover all outstanding debts on the registry - */ - function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { - _onlyFinanceAdminAllowed(); - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (address(asset) == address(i_link)) revert InvalidToken(); - if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); - uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; - if (amount > available) revert InsufficientBalance(available, amount); - - asset.safeTransfer(to, amount); - emit FeesWithdrawn(address(asset), to, amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol deleted file mode 100644 index 8fc9448..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationRegistryLogicC2_3.sol +++ /dev/null @@ -1,638 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @dev see AutomationRegistry master contract for constructor description - */ - constructor( - address link, - address linkUSDFeed, - address nativeUSDFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress, - PayoutMode payoutMode, - address wrappedNativeTokenAddress - ) - AutomationRegistryBase2_3( - link, - linkUSDFeed, - nativeUSDFeed, - fastGasFeed, - automationForwarderLogic, - allowedReadOnlyAddress, - payoutMode, - wrappedNativeTokenAddress - ) - {} - - // ================================================================ - // | NODE ACTIONS | - // ================================================================ - - /** - * @notice transfers the address of payee for a transmitter - */ - function transferPayeeship(address transmitter, address proposed) external { - if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[transmitter] != proposed) { - s_proposedPayee[transmitter] = proposed; - emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of the payee - */ - function acceptPayeeship(address transmitter) external { - if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_transmitterPayees[transmitter]; - s_transmitterPayees[transmitter] = msg.sender; - s_proposedPayee[transmitter] = ZERO_ADDRESS; - - emit PayeeshipTransferred(transmitter, past, msg.sender); - } - - /** - * @notice this is for NOPs to withdraw LINK received as payment for work performed - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (s_payoutMode == PayoutMode.OFF_CHAIN) revert MustSettleOffchain(); - if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); - uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); - s_transmitters[from].balance = 0; - s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] - balance; - bool transferStatus = i_link.transfer(to, balance); - if (!transferStatus) { - revert TransferFailed(); - } - emit PaymentWithdrawn(from, balance, to, msg.sender); - } - - // ================================================================ - // | OWNER / MANAGER ACTIONS | - // ================================================================ - - /** - * @notice sets the privilege config for an upkeep - */ - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { - _onlyPrivilegeManagerAllowed(); - s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; - emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); - } - - /** - * @notice this is used by the owner to set the initial payees for newly added transmitters. The owner is not allowed to change payees for existing transmitters. - * @dev the IGNORE_ADDRESS is a "helper" that makes it easier to construct a list of payees when you only care about setting the payee for a small number of transmitters. - */ - function setPayees(address[] calldata payees) external onlyOwner { - if (s_transmittersList.length != payees.length) revert ParameterLengthError(); - for (uint256 i = 0; i < s_transmittersList.length; i++) { - address transmitter = s_transmittersList[i]; - address oldPayee = s_transmitterPayees[transmitter]; - address newPayee = payees[i]; - - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) { - revert InvalidPayee(); - } - - if (newPayee != IGNORE_ADDRESS) { - s_transmitterPayees[transmitter] = newPayee; - } - } - emit PayeesUpdated(s_transmittersList, payees); - } - - /** - * @notice sets the migration permission for a peer registry - * @dev this must be done before upkeeps can be migrated to/from another registry - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @notice pauses the entire registry - */ - function pause() external onlyOwner { - s_hotVars.paused = true; - emit Paused(msg.sender); - } - - /** - * @notice unpauses the entire registry - */ - function unpause() external onlyOwner { - s_hotVars.paused = false; - emit Unpaused(msg.sender); - } - - /** - * @notice sets a generic bytes field used to indicate the privilege that this admin address had - * @param admin the address to set privilege for - * @param newPrivilegeConfig the privileges that this admin has - */ - function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { - _onlyPrivilegeManagerAllowed(); - s_adminPrivilegeConfig[admin] = newPrivilegeConfig; - emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); - } - - /** - * @notice settles NOPs' LINK payment offchain - */ - function settleNOPsOffchain() external { - _onlyFinanceAdminAllowed(); - if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); - - uint96 totalPremium = s_hotVars.totalPremium; - uint256 activeTransmittersLength = s_transmittersList.length; - uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); - uint256 length = activeTransmittersLength + deactivatedTransmittersLength; - uint256[] memory payments = new uint256[](length); - address[] memory payees = new address[](length); - - for (uint256 i = 0; i < activeTransmittersLength; i++) { - address transmitterAddr = s_transmittersList[i]; - uint96 balance = _updateTransmitterBalanceFromPool( - transmitterAddr, - totalPremium, - uint96(activeTransmittersLength) - ); - - payments[i] = balance; - payees[i] = s_transmitterPayees[transmitterAddr]; - s_transmitters[transmitterAddr].balance = 0; - } - - for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { - address deactivatedAddr = s_deactivatedTransmitters.at(i); - Transmitter memory transmitter = s_transmitters[deactivatedAddr]; - - payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; - payments[i + activeTransmittersLength] = transmitter.balance; - s_transmitters[deactivatedAddr].balance = 0; - } - - // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode - s_reserveAmounts[IERC20(address(i_link))] = 0; - - for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { - s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); - } - - emit NOPsSettledOffchain(payees, payments); - } - - /** - * @notice disables offchain payment for NOPs - */ - function disableOffchainPayments() external onlyOwner { - s_payoutMode = PayoutMode.ON_CHAIN; - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - function getConditionalGasOverhead() external pure returns (uint256) { - return REGISTRY_CONDITIONAL_OVERHEAD; - } - - function getLogGasOverhead() external pure returns (uint256) { - return REGISTRY_LOG_OVERHEAD; - } - - function getPerPerformByteGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD; - } - - function getPerSignerGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_SIGNER_GAS_OVERHEAD; - } - - function getTransmitCalldataFixedBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD; - } - - function getTransmitCalldataPerSignerBytesOverhead() external pure returns (uint256) { - return TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD; - } - - function getCancellationDelay() external pure returns (uint256) { - return CANCELLATION_DELAY; - } - - function getLinkAddress() external view returns (address) { - return address(i_link); - } - - function getLinkUSDFeedAddress() external view returns (address) { - return address(i_linkUSDFeed); - } - - function getNativeUSDFeedAddress() external view returns (address) { - return address(i_nativeUSDFeed); - } - - function getFastGasFeedAddress() external view returns (address) { - return address(i_fastGasFeed); - } - - function getAutomationForwarderLogic() external view returns (address) { - return i_automationForwarderLogic; - } - - function getAllowedReadOnlyAddress() external view returns (address) { - return i_allowedReadOnlyAddress; - } - - function getWrappedNativeTokenAddress() external view returns (address) { - return address(i_wrappedNativeToken); - } - - function getBillingToken(uint256 upkeepID) external view returns (IERC20) { - return s_upkeep[upkeepID].billingToken; - } - - function getBillingTokens() external view returns (IERC20[] memory) { - return s_billingTokens; - } - - function supportsBillingToken(IERC20 token) external view returns (bool) { - return address(s_billingConfigs[token].priceFeed) != address(0); - } - - function getBillingTokenConfig(IERC20 token) external view returns (BillingConfig memory) { - return s_billingConfigs[token]; - } - - function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool) { - return s_upkeep[upkeepID].overridesEnabled; - } - - function getPayoutMode() external view returns (PayoutMode) { - return s_payoutMode; - } - - function upkeepVersion() public pure returns (uint8) { - return UPKEEP_VERSION_BASE; - } - - /** - * @notice gets the number of upkeeps on the registry - */ - function getNumUpkeeps() external view returns (uint256) { - return s_upkeepIDs.length(); - } - - /** - * @notice read all of the details about an upkeep - * @dev this function may be deprecated in a future version of automation in favor of individual - * getters for each field - */ - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { - Upkeep memory reg = s_upkeep[id]; - address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); - upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ - target: target, - performGas: reg.performGas, - checkData: s_checkData[id], - balance: reg.balance, - admin: s_upkeepAdmin[id], - maxValidBlocknumber: reg.maxValidBlocknumber, - lastPerformedBlockNumber: reg.lastPerformedBlockNumber, - amountSpent: uint96(reg.amountSpent), // force casting to uint96 for backwards compatibility. Not an issue if it overflows. - paused: reg.paused, - offchainConfig: s_upkeepOffchainConfig[id] - }); - return upkeepInfo; - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { - uint256 numUpkeeps = s_upkeepIDs.length(); - if (startIndex >= numUpkeeps) revert IndexOutOfRange(); - uint256 endIndex = startIndex + maxCount; - endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; - uint256[] memory ids = new uint256[](endIndex - startIndex); - for (uint256 idx = 0; idx < ids.length; idx++) { - ids[idx] = s_upkeepIDs.at(idx + startIndex); - } - return ids; - } - - /** - * @notice returns the upkeep's trigger type - */ - function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { - return _getTriggerType(upkeepId); - } - - /** - * @notice returns the trigger config for an upkeeep - */ - function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { - return s_upkeepTriggerConfig[upkeepId]; - } - - /** - * @notice read the current info about any transmitter address - */ - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { - Transmitter memory transmitter = s_transmitters[query]; - - uint96 pooledShare = 0; - if (transmitter.active) { - uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; - pooledShare = totalDifference / uint96(s_transmittersList.length); - } - - return ( - transmitter.active, - transmitter.index, - (transmitter.balance + pooledShare), - transmitter.lastCollected, - s_transmitterPayees[query] - ); - } - - /** - * @notice read the current info about any signer address - */ - function getSignerInfo(address query) external view returns (bool active, uint8 index) { - Signer memory signer = s_signers[query]; - return (signer.active, signer.index); - } - - /** - * @notice read the current on-chain config of the registry - * @dev this function will change between versions, it should never be used where - * backwards compatibility matters! - */ - function getConfig() external view returns (OnchainConfig memory) { - return - OnchainConfig({ - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - fallbackNativePrice: s_fallbackNativePrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager, - chainModule: s_hotVars.chainModule, - reorgProtectionEnabled: s_hotVars.reorgProtectionEnabled, - financeAdmin: s_storage.financeAdmin - }); - } - - /** - * @notice read the current state of the registry - * @dev this function is deprecated - */ - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) - { - state = IAutomationV21PlusCommon.StateLegacy({ - nonce: s_storage.nonce, - ownerLinkBalance: 0, // deprecated - expectedLinkBalance: 0, // deprecated - totalPremium: s_hotVars.totalPremium, - numUpkeeps: s_upkeepIDs.length(), - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - latestConfigDigest: s_latestConfigDigest, - latestEpoch: s_hotVars.latestEpoch, - paused: s_hotVars.paused - }); - - config = IAutomationV21PlusCommon.OnchainConfigLegacy({ - paymentPremiumPPB: 0, // deprecated - flatFeeMicroLink: 0, // deprecated - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - minUpkeepSpend: 0, // deprecated - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager - }); - - return (state, config, s_signersList, s_transmittersList, s_hotVars.f); - } - - /** - * @notice read the Storage data - * @dev this function signature will change with each version of automation - * this should not be treated as a stable function - */ - function getStorage() external view returns (Storage memory) { - return s_storage; - } - - /** - * @notice read the HotVars data - * @dev this function signature will change with each version of automation - * this should not be treated as a stable function - */ - function getHotVars() external view returns (HotVars memory) { - return s_hotVars; - } - - /** - * @notice get the chain module - */ - function getChainModule() external view returns (IChainModule chainModule) { - return s_hotVars.chainModule; - } - - /** - * @notice if this registry has reorg protection enabled - */ - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { - return s_hotVars.reorgProtectionEnabled; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getBalance(uint256 id) external view returns (uint96 balance) { - return s_upkeep[id].balance; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalance(uint256 id) external view returns (uint96) { - return getMinBalanceForUpkeep(id); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - * @dev this will be deprecated in a future version in favor of getMinBalance - */ - function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { - Upkeep memory upkeep = s_upkeep[id]; - return getMaxPaymentForGas(id, _getTriggerType(id), upkeep.performGas, upkeep.billingToken); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas( - uint256 id, - Trigger triggerType, - uint32 gasLimit, - IERC20 billingToken - ) public view returns (uint96 maxPayment) { - HotVars memory hotVars = s_hotVars; - (uint256 fastGasWei, uint256 linkUSD, uint256 nativeUSD) = _getFeedData(hotVars); - return _getMaxPayment(id, hotVars, triggerType, gasLimit, fastGasWei, linkUSD, nativeUSD, billingToken); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { - return s_upkeepPrivilegeConfig[upkeepId]; - } - - /** - * @notice returns the admin's privilege config - */ - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { - return s_adminPrivilegeConfig[admin]; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { - return s_upkeep[upkeepID].forwarder; - } - - /** - * @notice returns if the dedupKey exists or not - */ - function hasDedupKey(bytes32 dedupKey) external view returns (bool) { - return s_dedupKeys[dedupKey]; - } - - /** - * @notice returns the fallback native price - */ - function getFallbackNativePrice() external view returns (uint256) { - return s_fallbackNativePrice; - } - - /** - * @notice returns the amount of a particular token that is reserved as - * user deposits / NOP payments - */ - function getReserveAmount(IERC20 billingToken) external view returns (uint256) { - return s_reserveAmounts[billingToken]; - } - - /** - * @notice returns the amount of a particular token that is withdraw-able by finance admin - */ - function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { - return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; - } - - /** - * @notice returns the size of the LINK liquidity pool - */ - function linkAvailableForPayment() public view returns (int256) { - return _linkAvailableForPayment(); - } - - /** - * @notice returns the BillingOverrides config for a given upkeep - */ - function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { - return s_billingOverrides[upkeepID]; - } - - /** - * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc - */ - function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { - return s_billingConfigs[billingToken]; - } - - /** - * @notice returns all active transmitters with their associated payees - */ - function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { - uint256 transmitterCount = s_transmittersList.length; - TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); - - for (uint256 i = 0; i < transmitterCount; i++) { - address transmitterAddress = s_transmittersList[i]; - address payeeAddress = s_transmitterPayees[transmitterAddress]; - - transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); - } - - return transmitters; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol deleted file mode 100644 index 59081b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/AutomationUtils2_3.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {AutomationRegistryBase2_3} from "./AutomationRegistryBase2_3.sol"; - -/** - * @notice this file exposes structs that are otherwise internal to the automation registry - * doing this allows those structs to be encoded and decoded with type safety in offchain code - * and tests because generated wrappers are made available - */ - -contract AutomationUtils2_3 { - /** - * @dev this uses the v2.3 Report, which uses linkUSD instead of linkNative (as in v2.2 and prior). This should be used only in typescript tests. - */ - function _report(AutomationRegistryBase2_3.Report memory) external {} // 0xe65d6546 -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE deleted file mode 100644 index 515985a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/LICENSE +++ /dev/null @@ -1,57 +0,0 @@ -Business Source License 1.1 - -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ---- - -Parameters - -Licensor: SmartContract Chainlink Limited SEZC - -Licensed Work: Automation v2.3 -The Licensed Work is (c) 2024 SmartContract Chainlink Limited SEZC - -Additional Use Grant(s): -You may make use of Automation v2.1, v2.2, v2.3 (which is available subject to the license here the “Licensed Work”) solely for purposes listed below: -https://github.com/smartcontractkit/chainlink-automation/tree/main/Automation_Grants.md - -Change Date: March 1, 2024 - -Change License: MIT - ---- - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. - -If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. - -MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. - ---- - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. - -2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol deleted file mode 100644 index 32530c7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3/UpkeepTranscoder5_0.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 - -pragma solidity 0.8.19; - -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; - -enum RegistryVersion { - V12, - V13, - V20, - V21, - V23 -} - -/** - * @notice UpkeepTranscoder is a contract that allows converting upkeep data from previous registry versions to newer versions - * @dev it currently only supports 2.3 -> 2.3 migrations - */ -contract UpkeepTranscoder5_0 is UpkeepTranscoderInterfaceV2, TypeAndVersionInterface { - error InvalidTranscoding(); - - string public constant override typeAndVersion = "UpkeepTranscoder 5.0.0"; - - /** - * @notice transcodeUpkeeps transforms upkeep data from the format expected by - * one registry to the format expected by another. It future-proofs migrations - * by allowing automation team to customize migration paths and set sensible defaults - * when new fields are added - * @param fromVersion version the upkeep is migrating from - * @param toVersion version the upkeep is migrating to - * @param encodedUpkeeps encoded upkeep data - * @dev this transcoder should ONLY be use for V23->V23 migrations for now - */ - function transcodeUpkeeps( - uint8 fromVersion, - uint8 toVersion, - bytes calldata encodedUpkeeps - ) external view override returns (bytes memory) { - if (toVersion == uint8(RegistryVersion.V23) && fromVersion == uint8(RegistryVersion.V23)) { - return encodedUpkeeps; - } - - revert InvalidTranscoding(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol deleted file mode 100644 index 5d5bf23..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistry2_3.sol +++ /dev/null @@ -1,386 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; -import {ZKSyncAutomationRegistryLogicA2_3} from "./ZKSyncAutomationRegistryLogicA2_3.sol"; -import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {OCR2Abstract} from "../../shared/ocr2/OCR2Abstract.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - -/** - * @notice Registry for adding work for Chainlink nodes to perform on client - * contracts. Clients must support the AutomationCompatibleInterface interface. - */ -contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abstract, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @notice versions: - * AutomationRegistry 2.3.0: supports native and ERC20 billing - * changes flat fee to USD-denominated - * adds support for custom billing overrides - * AutomationRegistry 2.2.0: moves chain-specific integration code into a separate module - * KeeperRegistry 2.1.0: introduces support for log triggers - * removes the need for "wrapped perform data" - * KeeperRegistry 2.0.2: pass revert bytes as performData when target contract reverts - * fixes issue with arbitrum block number - * does an early return in case of stale report instead of revert - * KeeperRegistry 2.0.1: implements workaround for buggy migrate function in 1.X - * KeeperRegistry 2.0.0: implement OCR interface - * KeeperRegistry 1.3.0: split contract into Proxy and Logic - * account for Arbitrum and Optimism L1 gas fee - * allow users to configure upkeeps - * KeeperRegistry 1.2.0: allow funding within performUpkeep - * allow configurable registry maxPerformGas - * add function to let admin change upkeep gas limit - * add minUpkeepSpend requirement - * upgrade to solidity v0.8 - * KeeperRegistry 1.1.0: added flatFeeMicroLink - * KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "AutomationRegistry 2.3.0"; - - /** - * @param logicA the address of the first logic contract - * @dev we cast the contract to logicC in order to call logicC functions (via fallback) - */ - constructor( - ZKSyncAutomationRegistryLogicA2_3 logicA - ) - ZKSyncAutomationRegistryBase2_3( - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getLinkAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getLinkUSDFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getNativeUSDFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getFastGasFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getAutomationForwarderLogic(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getAllowedReadOnlyAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getPayoutMode(), - ZKSyncAutomationRegistryLogicC2_3(address(logicA)).getWrappedNativeTokenAddress() - ) - Chainable(address(logicA)) - {} - - /** - * @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors - */ - struct TransmitVars { - uint16 numUpkeepsPassedChecks; - uint96 totalReimbursement; - uint96 totalPremium; - } - - // ================================================================ - // | HOT PATH ACTIONS | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - */ - function transmit( - bytes32[3] calldata reportContext, - bytes calldata rawReport, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external override { - // use this msg.data length check to ensure no extra data is included in the call - // 4 is first 4 bytes of the keccak-256 hash of the function signature. ss.length == rs.length so use one of them - // 4 + (32 * 3) + (rawReport.length + 32 + 32) + (32 * rs.length + 32 + 32) + (32 * ss.length + 32 + 32) + 32 - uint256 requiredLength = 324 + rawReport.length + 64 * rs.length; - if (msg.data.length != requiredLength) revert InvalidDataLength(); - HotVars memory hotVars = s_hotVars; - - if (hotVars.paused) revert RegistryPaused(); - if (!s_transmitters[msg.sender].active) revert OnlyActiveTransmitters(); - - // Verify signatures - if (s_latestConfigDigest != reportContext[0]) revert ConfigDigestMismatch(); - if (rs.length != hotVars.f + 1 || rs.length != ss.length) revert IncorrectNumberOfSignatures(); - _verifyReportSignature(reportContext, rawReport, rs, ss, rawVs); - - Report memory report = _decodeReport(rawReport); - - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - - _handleReport(hotVars, report); - - if (epoch > hotVars.latestEpoch) { - s_hotVars.latestEpoch = epoch; - } - } - - /** - * @notice handles the report by performing the upkeeps and updating the state - * @param hotVars the hot variables of the registry - * @param report the report to be handled (already verified and decoded) - * @dev had to split this function from transmit() to avoid stack too deep errors - * @dev all other internal / private functions are generally defined in the Base contract - * we leave this here because it is essentially a continuation of the transmit() function, - */ - function _handleReport(HotVars memory hotVars, Report memory report) private { - UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length); - TransmitVars memory transmitVars = TransmitVars({ - numUpkeepsPassedChecks: 0, - totalReimbursement: 0, - totalPremium: 0 - }); - - uint256 blocknumber = hotVars.chainModule.blockNumber(); - uint256 gasOverhead; - - 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].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks( - report.upkeepIds[i], - blocknumber, - report.triggers[i], - upkeepTransmitInfo[i], - hotVars - ); - - if (upkeepTransmitInfo[i].earlyChecksPassed) { - transmitVars.numUpkeepsPassedChecks += 1; - } else { - continue; - } - - // Actually perform the target upkeep - (upkeepTransmitInfo[i].performSuccess, upkeepTransmitInfo[i].gasUsed) = _performUpkeep( - upkeepTransmitInfo[i].upkeep.forwarder, - report.gasLimits[i], - report.performDatas[i] - ); - - // Store last perform block number / deduping key for upkeep - _updateTriggerMarker(report.upkeepIds[i], blocknumber, upkeepTransmitInfo[i]); - - if (upkeepTransmitInfo[i].triggerType == Trigger.CONDITION) { - gasOverhead += REGISTRY_CONDITIONAL_OVERHEAD; - } else if (upkeepTransmitInfo[i].triggerType == Trigger.LOG) { - gasOverhead += REGISTRY_LOG_OVERHEAD; - } else { - revert InvalidTriggerType(); - } - } - // No upkeeps to be performed in this report - if (transmitVars.numUpkeepsPassedChecks == 0) { - return; - } - - gasOverhead += - 16 * - msg.data.length + - ACCOUNTING_FIXED_GAS_OVERHEAD + - (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)); - gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD; - - { - BillingTokenPaymentParams memory billingTokenParams; - uint256 nativeUSD = _getNativeUSD(hotVars); - for (uint256 i = 0; i < report.upkeepIds.length; i++) { - if (upkeepTransmitInfo[i].earlyChecksPassed) { - if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { - billingTokenParams = _getBillingTokenPaymentParams(hotVars, upkeepTransmitInfo[i].upkeep.billingToken); - } - PaymentReceipt memory receipt = _handlePayment( - hotVars, - PaymentParams({ - gasLimit: upkeepTransmitInfo[i].gasUsed, - gasOverhead: gasOverhead, - l1CostWei: 0, - fastGasWei: report.fastGasWei, - linkUSD: report.linkUSD, - nativeUSD: nativeUSD, - billingToken: upkeepTransmitInfo[i].upkeep.billingToken, - billingTokenParams: billingTokenParams, - isTransaction: true - }), - report.upkeepIds[i], - upkeepTransmitInfo[i].upkeep - ); - transmitVars.totalPremium += receipt.premiumInJuels; - transmitVars.totalReimbursement += receipt.gasReimbursementInJuels; - - emit UpkeepPerformed( - report.upkeepIds[i], - upkeepTransmitInfo[i].performSuccess, - receipt.gasChargeInBillingToken + receipt.premiumInBillingToken, - upkeepTransmitInfo[i].gasUsed, - gasOverhead, - report.triggers[i] - ); - } - } - } - // record payments to NOPs, all in LINK - s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; - s_hotVars.totalPremium += transmitVars.totalPremium; - s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium; - } - - // ================================================================ - // | OCR2ABSTRACT | - // ================================================================ - - /** - * @inheritdoc OCR2Abstract - * @dev prefer the type-safe version of setConfig (below) whenever possible. The OnchainConfig could differ between registry versions - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfigBytes, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override { - (OnchainConfig memory config, IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) = abi.decode( - onchainConfigBytes, - (OnchainConfig, IERC20[], BillingConfig[]) - ); - - setConfigTypeSafe( - signers, - transmitters, - f, - config, - offchainConfigVersion, - offchainConfig, - billingTokens, - billingConfigs - ); - } - - /** - * @notice sets the configuration for the registry - * @param signers the list of permitted signers - * @param transmitters the list of permitted transmitters - * @param f the maximum tolerance for faulty nodes - * @param onchainConfig configuration values that are used on-chain - * @param offchainConfigVersion the version of the offchainConfig - * @param offchainConfig configuration values that are used off-chain - * @param billingTokens the list of valid billing tokens - * @param billingConfigs the configurations for each billing token - */ - function setConfigTypeSafe( - address[] memory signers, - address[] memory transmitters, - uint8 f, - OnchainConfig memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - IERC20[] memory billingTokens, - BillingConfig[] memory billingConfigs - ) public onlyOwner { - if (signers.length > MAX_NUM_ORACLES) revert TooManyOracles(); - if (f == 0) revert IncorrectNumberOfFaultyOracles(); - if (signers.length != transmitters.length || signers.length <= 3 * f) revert IncorrectNumberOfSigners(); - if (billingTokens.length != billingConfigs.length) revert ParameterLengthError(); - // set billing config for tokens - _setBillingConfig(billingTokens, billingConfigs); - - _updateTransmitters(signers, transmitters); - - s_hotVars = HotVars({ - f: f, - stalenessSeconds: onchainConfig.stalenessSeconds, - gasCeilingMultiplier: onchainConfig.gasCeilingMultiplier, - paused: s_hotVars.paused, - reentrancyGuard: s_hotVars.reentrancyGuard, - totalPremium: s_hotVars.totalPremium, - latestEpoch: 0, // DON restarts epoch - reorgProtectionEnabled: onchainConfig.reorgProtectionEnabled, - chainModule: onchainConfig.chainModule - }); - - uint32 previousConfigBlockNumber = s_storage.latestConfigBlockNumber; - uint32 newLatestConfigBlockNumber = uint32(onchainConfig.chainModule.blockNumber()); - uint32 newConfigCount = s_storage.configCount + 1; - - s_storage = Storage({ - checkGasLimit: onchainConfig.checkGasLimit, - maxPerformGas: onchainConfig.maxPerformGas, - transcoder: onchainConfig.transcoder, - maxCheckDataSize: onchainConfig.maxCheckDataSize, - maxPerformDataSize: onchainConfig.maxPerformDataSize, - maxRevertDataSize: onchainConfig.maxRevertDataSize, - upkeepPrivilegeManager: onchainConfig.upkeepPrivilegeManager, - financeAdmin: onchainConfig.financeAdmin, - nonce: s_storage.nonce, - configCount: newConfigCount, - latestConfigBlockNumber: newLatestConfigBlockNumber - }); - s_fallbackGasPrice = onchainConfig.fallbackGasPrice; - s_fallbackLinkPrice = onchainConfig.fallbackLinkPrice; - s_fallbackNativePrice = onchainConfig.fallbackNativePrice; - - bytes memory onchainConfigBytes = abi.encode(onchainConfig); - - s_latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - - for (uint256 idx = s_registrars.length(); idx > 0; idx--) { - s_registrars.remove(s_registrars.at(idx - 1)); - } - - for (uint256 idx = 0; idx < onchainConfig.registrars.length; idx++) { - s_registrars.add(onchainConfig.registrars[idx]); - } - - emit ConfigSet( - previousConfigBlockNumber, - s_latestConfigDigest, - s_storage.configCount, - signers, - transmitters, - f, - onchainConfigBytes, - offchainConfigVersion, - offchainConfig - ); - } - - /** - * @inheritdoc OCR2Abstract - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_storage.configCount, s_storage.latestConfigBlockNumber, s_latestConfigDigest); - } - - /** - * @inheritdoc OCR2Abstract - * @dev this function takes up precious space on the root contract, but must be implemented to conform to the OCR2Abstract interface - */ - function latestConfigDigestAndEpoch() - external - view - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (false, s_latestConfigDigest, s_hotVars.latestEpoch); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol deleted file mode 100644 index 41097af..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryBase2_3.sol +++ /dev/null @@ -1,1197 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {StreamsLookupCompatibleInterface} from "../interfaces/StreamsLookupCompatibleInterface.sol"; -import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {KeeperCompatibleInterface} from "../interfaces/KeeperCompatibleInterface.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; - -/** - * @notice Base Keeper Registry contract, contains shared logic between - * AutomationRegistry and AutomationRegistryLogic - * @dev all errors, events, and internal functions should live here - */ -// solhint-disable-next-line max-states-count -abstract contract ZKSyncAutomationRegistryBase2_3 is ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - address internal constant ZERO_ADDRESS = address(0); - address internal constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 internal constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 internal constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - bytes4 internal constant CHECK_CALLBACK_SELECTOR = StreamsLookupCompatibleInterface.checkCallback.selector; - bytes4 internal constant CHECK_LOG_SELECTOR = ILogAutomation.checkLog.selector; - uint256 internal constant PERFORM_GAS_MIN = 2_300; - uint256 internal constant CANCELLATION_DELAY = 50; - uint32 internal constant UINT32_MAX = type(uint32).max; - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - uint8 internal constant UPKEEP_VERSION_BASE = 4; - - // Next block of constants are only used in maxPayment estimation during checkUpkeep simulation - // These values are calibrated using hardhat tests which simulate various cases and verify that - // the variables result in accurate estimation - uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps - uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // Fixed gas overhead for log upkeeps - uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f - - // Next block of constants are used in actual payment calculation. We calculate the exact gas used within the - // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants - // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that - // the variables result in accurate estimation - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_000; // Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 20_000; // Overhead per upkeep performed in batch - - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_linkUSDFeed; - AggregatorV3Interface internal immutable i_nativeUSDFeed; - AggregatorV3Interface internal immutable i_fastGasFeed; - address internal immutable i_automationForwarderLogic; - address internal immutable i_allowedReadOnlyAddress; - IWrappedNative internal immutable i_wrappedNativeToken; - - /** - * @dev - The storage is gas optimised for one and only one function - transmit. All the storage accessed in transmit - * is stored compactly. Rest of the storage layout is not of much concern as transmit is the only hot path - */ - - // Upkeep storage - EnumerableSet.UintSet internal s_upkeepIDs; - mapping(uint256 => Upkeep) internal s_upkeep; // accessed during transmit - mapping(uint256 => address) internal s_upkeepAdmin; - mapping(uint256 => address) internal s_proposedAdmin; - mapping(uint256 => bytes) internal s_checkData; - mapping(bytes32 => bool) internal s_dedupKeys; - // Registry config and state - EnumerableSet.AddressSet internal s_registrars; - mapping(address => Transmitter) internal s_transmitters; - mapping(address => Signer) internal s_signers; - address[] internal s_signersList; // s_signersList contains the signing address of each oracle - address[] internal s_transmittersList; // s_transmittersList contains the transmission address of each oracle - EnumerableSet.AddressSet internal s_deactivatedTransmitters; - mapping(address => address) internal s_transmitterPayees; // s_payees contains the mapping from transmitter to payee. - mapping(address => address) internal s_proposedPayee; // proposed payee for a transmitter - bytes32 internal s_latestConfigDigest; // Read on transmit path in case of signature verification - HotVars internal s_hotVars; // Mixture of config and state, used in transmit - Storage internal s_storage; // Mixture of config and state, not used in transmit - uint256 internal s_fallbackGasPrice; - uint256 internal s_fallbackLinkPrice; - uint256 internal s_fallbackNativePrice; - mapping(address => MigrationPermission) internal s_peerRegistryMigrationPermission; // Permissions for migration to and fro - mapping(uint256 => bytes) internal s_upkeepTriggerConfig; // upkeep triggers - mapping(uint256 => bytes) internal s_upkeepOffchainConfig; // general config set by users for each upkeep - mapping(uint256 => bytes) internal s_upkeepPrivilegeConfig; // general config set by an administrative role for an upkeep - mapping(address => bytes) internal s_adminPrivilegeConfig; // general config set by an administrative role for an admin - // billing - mapping(IERC20 billingToken => uint256 reserveAmount) internal s_reserveAmounts; // unspent user deposits + unwithdrawn NOP payments - mapping(IERC20 billingToken => BillingConfig billingConfig) internal s_billingConfigs; // billing configurations for different tokens - mapping(uint256 upkeepID => BillingOverrides billingOverrides) internal s_billingOverrides; // billing overrides for specific upkeeps - IERC20[] internal s_billingTokens; // list of billing tokens - PayoutMode internal s_payoutMode; - - error ArrayHasNoEntries(); - error CannotCancel(); - error CheckDataExceedsLimit(); - error ConfigDigestMismatch(); - error DuplicateEntry(); - error DuplicateSigners(); - error GasLimitCanOnlyIncrease(); - error GasLimitOutsideRange(); - error IncorrectNumberOfFaultyOracles(); - error IncorrectNumberOfSignatures(); - error IncorrectNumberOfSigners(); - error IndexOutOfRange(); - error InsufficientBalance(uint256 available, uint256 requested); - error InsufficientLinkLiquidity(); - error InvalidDataLength(); - error InvalidFeed(); - error InvalidTrigger(); - error InvalidPayee(); - error InvalidRecipient(); - error InvalidReport(); - error InvalidSigner(); - error InvalidToken(); - error InvalidTransmitter(); - error InvalidTriggerType(); - error MigrationNotPermitted(); - error MustSettleOffchain(); - error MustSettleOnchain(); - error NotAContract(); - error OnlyActiveSigners(); - error OnlyActiveTransmitters(); - error OnlyCallableByAdmin(); - error OnlyCallableByLINKToken(); - error OnlyCallableByOwnerOrAdmin(); - error OnlyCallableByOwnerOrRegistrar(); - error OnlyCallableByPayee(); - error OnlyCallableByProposedAdmin(); - error OnlyCallableByProposedPayee(); - error OnlyCallableByUpkeepPrivilegeManager(); - error OnlyFinanceAdmin(); - error OnlyPausedUpkeep(); - error OnlySimulatedBackend(); - error OnlyUnpausedUpkeep(); - error ParameterLengthError(); - error ReentrantCall(); - error RegistryPaused(); - error RepeatedSigner(); - error RepeatedTransmitter(); - error TargetCheckReverted(bytes reason); - error TooManyOracles(); - error TranscoderNotSet(); - error TransferFailed(); - error UpkeepAlreadyExists(); - error UpkeepCancelled(); - error UpkeepNotCanceled(); - error UpkeepNotNeeded(); - error ValueNotChanged(); - error ZeroAddressNotAllowed(); - - enum MigrationPermission { - NONE, - OUTGOING, - INCOMING, - BIDIRECTIONAL - } - - enum Trigger { - CONDITION, - LOG - } - - enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, - CALLBACK_REVERTED, - REVERT_DATA_EXCEEDS_LIMIT, - REGISTRY_PAUSED - } - - enum PayoutMode { - ON_CHAIN, - OFF_CHAIN - } - - /** - * @notice OnchainConfig of the registry - * @dev used only in setConfig() - * @member checkGasLimit gas limit when checking for upkeep - * @member stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @member gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @member maxPerformGas max performGas allowed for an upkeep on this registry - * @member maxCheckDataSize max length of checkData bytes - * @member maxPerformDataSize max length of performData bytes - * @member maxRevertDataSize max length of revertData bytes - * @member fallbackGasPrice gas price used if the gas price feed is stale - * @member fallbackLinkPrice LINK price used if the LINK price feed is stale - * @member transcoder address of the transcoder contract - * @member registrars addresses of the registrar contracts - * @member upkeepPrivilegeManager address which can set privilege for upkeeps - * @member reorgProtectionEnabled if this registry enables re-org protection checks - * @member chainModule the chain specific module - */ - struct OnchainConfig { - uint32 checkGasLimit; - uint32 maxPerformGas; - uint32 maxCheckDataSize; - address transcoder; - // 1 word full - bool reorgProtectionEnabled; - uint24 stalenessSeconds; - uint32 maxPerformDataSize; - uint32 maxRevertDataSize; - address upkeepPrivilegeManager; - // 2 words full - uint16 gasCeilingMultiplier; - address financeAdmin; - // 3 words - uint256 fallbackGasPrice; - uint256 fallbackLinkPrice; - uint256 fallbackNativePrice; - address[] registrars; - IChainModule chainModule; - } - - /** - * @notice relevant state of an upkeep which is used in transmit function - * @member paused if this upkeep has been paused - * @member overridesEnabled if this upkeep has overrides enabled - * @member performGas the gas limit of upkeep execution - * @member maxValidBlocknumber until which block this upkeep is valid - * @member forwarder the forwarder contract to use for this upkeep - * @member amountSpent the amount this upkeep has spent, in the upkeep's billing token - * @member balance the balance of this upkeep - * @member lastPerformedBlockNumber the last block number when this upkeep was performed - */ - struct Upkeep { - bool paused; - bool overridesEnabled; - uint32 performGas; - uint32 maxValidBlocknumber; - IAutomationForwarder forwarder; - // 2 bytes left in 1st EVM word - read in transmit path - uint128 amountSpent; - uint96 balance; - uint32 lastPerformedBlockNumber; - // 0 bytes left in 2nd EVM word - written in transmit path - IERC20 billingToken; - // 12 bytes left in 3rd EVM word - read in transmit path - } - - /// @dev Config + State storage struct which is on hot transmit path - struct HotVars { - uint96 totalPremium; // ─────────╮ total historical payment to oracles for premium - uint32 latestEpoch; // │ latest epoch for which a report was transmitted - uint24 stalenessSeconds; // │ Staleness tolerance for feeds - uint16 gasCeilingMultiplier; // │ multiplier on top of fast gas feed for upper bound - uint8 f; // │ maximum number of faulty oracles - bool paused; // │ pause switch for all upkeeps in the registry - bool reentrancyGuard; // | guard against reentrancy - bool reorgProtectionEnabled; // ─╯ if this registry should enable the re-org protection mechanism - IChainModule chainModule; // the interface of chain specific module - } - - /// @dev Config + State storage struct which is not on hot transmit path - struct Storage { - address transcoder; // Address of transcoder contract used in migrations - uint32 checkGasLimit; // Gas limit allowed in checkUpkeep - uint32 maxPerformGas; // Max gas an upkeep can use on this registry - uint32 nonce; // Nonce for each upkeep created - // 1 EVM word full - address upkeepPrivilegeManager; // address which can set privilege for upkeeps - uint32 configCount; // incremented each time a new config is posted, The count is incorporated into the config digest to prevent replay attacks. - uint32 latestConfigBlockNumber; // makes it easier for offchain systems to extract config from logs - uint32 maxCheckDataSize; // max length of checkData bytes - // 2 EVM word full - address financeAdmin; // address which can withdraw funds from the contract - uint32 maxPerformDataSize; // max length of performData bytes - uint32 maxRevertDataSize; // max length of revertData bytes - // 4 bytes left in 3rd EVM word - } - - /// @dev Report transmitted by OCR to transmit function - struct Report { - uint256 fastGasWei; - uint256 linkUSD; - uint256[] upkeepIds; - uint256[] gasLimits; - bytes[] triggers; - bytes[] performDatas; - } - - /** - * @dev This struct is used to maintain run time information about an upkeep in transmit function - * @member upkeep the upkeep struct - * @member earlyChecksPassed whether the upkeep passed early checks before perform - * @member performSuccess whether the perform was successful - * @member triggerType the type of trigger - * @member gasUsed gasUsed by this upkeep in perform - * @member dedupID unique ID used to dedup an upkeep/trigger combo - */ - struct UpkeepTransmitInfo { - Upkeep upkeep; - bool earlyChecksPassed; - bool performSuccess; - Trigger triggerType; - uint256 gasUsed; - bytes32 dedupID; - } - - /** - * @notice holds information about a transmiter / node in the DON - * @member active can this transmitter submit reports - * @member index of oracle in s_signersList/s_transmittersList - * @member balance a node's balance in LINK - * @member lastCollected the total balance at which the node last withdrew - * @dev uint96 is safe for balance / last collected because transmitters are only ever paid in LINK - */ - struct Transmitter { - bool active; - uint8 index; - uint96 balance; - uint96 lastCollected; - } - - struct TransmitterPayeeInfo { - address transmitterAddress; - address payeeAddress; - } - - struct Signer { - bool active; - // Index of oracle in s_signersList/s_transmittersList - uint8 index; - } - - /** - * @notice the trigger structure conditional trigger type - */ - struct ConditionalTrigger { - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the trigger structure of log upkeeps - * @dev NOTE that blockNum / blockHash describe the block used for the callback, - * not necessarily the block number that the log was emitted in!!!! - */ - struct LogTrigger { - bytes32 logBlockHash; - bytes32 txHash; - uint32 logIndex; - uint32 blockNum; - bytes32 blockHash; - } - - /** - * @notice the billing config of a token - * @dev this is a storage struct - */ - // solhint-disable-next-line gas-struct-packing - struct BillingConfig { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; // min fee is $0.00001, max fee is $167 - AggregatorV3Interface priceFeed; - uint8 decimals; - // 1st word, read in calculating BillingTokenPaymentParams - uint256 fallbackPrice; - // 2nd word only read if stale - uint96 minSpend; - // 3rd word only read during cancellation - } - - /** - * @notice override-able billing params of a billing token - */ - struct BillingOverrides { - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - } - - /** - * @notice pricing params for a billing token - * @dev this is a memory-only struct, so struct packing is less important - */ - struct BillingTokenPaymentParams { - uint8 decimals; - uint32 gasFeePPB; - uint24 flatFeeMilliCents; - uint256 priceUSD; - } - - /** - * @notice struct containing price & payment information used in calculating payment amount - * @member gasLimit the amount of gas used - * @member gasOverhead the amount of gas overhead - * @member l1CostWei the amount to be charged for L1 fee in wei - * @member fastGasWei the fast gas price - * @member linkUSD the exchange ratio between LINK and USD - * @member nativeUSD the exchange ratio between the chain's native token and USD - * @member billingToken the billing token - * @member billingTokenParams the payment params specific to a particular payment token - * @member isTransaction is this an eth_call or a transaction - */ - struct PaymentParams { - uint256 gasLimit; - uint256 gasOverhead; - uint256 l1CostWei; - uint256 fastGasWei; - uint256 linkUSD; - uint256 nativeUSD; - IERC20 billingToken; - BillingTokenPaymentParams billingTokenParams; - bool isTransaction; - } - - /** - * @notice struct containing receipt information about a payment or cost estimation - * @member gasChargeInBillingToken the amount to charge a user for gas spent using the billing token's native decimals - * @member premiumInBillingToken the premium charged to the user, shared between all nodes, using the billing token's native decimals - * @member gasReimbursementInJuels the amount to reimburse a node for gas spent - * @member premiumInJuels the premium paid to NOPs, shared between all nodes - */ - // solhint-disable-next-line gas-struct-packing - struct PaymentReceipt { - uint96 gasChargeInBillingToken; - uint96 premiumInBillingToken; - // one word ends - uint96 gasReimbursementInJuels; - uint96 premiumInJuels; - // second word ends - IERC20 billingToken; - uint96 linkUSD; - // third word ends - uint96 nativeUSD; - uint96 billingUSD; - // fourth word ends - } - - event AdminPrivilegeConfigSet(address indexed admin, bytes privilegeConfig); - event BillingConfigOverridden(uint256 indexed id, BillingOverrides overrides); - event BillingConfigOverrideRemoved(uint256 indexed id); - event BillingConfigSet(IERC20 indexed token, BillingConfig config); - event CancelledUpkeepReport(uint256 indexed id, bytes trigger); - event ChainSpecificModuleUpdated(address newModule); - event DedupKeyAdded(bytes32 indexed dedupKey); - event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); - event NOPsSettledOffchain(address[] payees, uint256[] payments); - event Paused(address account); - event PayeesUpdated(address[] transmitters, address[] payees); - event PayeeshipTransferRequested(address indexed transmitter, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed transmitter, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); - event ReorgedUpkeepReport(uint256 indexed id, bytes trigger); - event StaleUpkeepReport(uint256 indexed id, bytes trigger); - event UpkeepAdminTransferred(uint256 indexed id, address indexed from, address indexed to); - event UpkeepAdminTransferRequested(uint256 indexed id, address indexed from, address indexed to); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepCheckDataSet(uint256 indexed id, bytes newCheckData); - event UpkeepGasLimitSet(uint256 indexed id, uint96 gasLimit); - event UpkeepMigrated(uint256 indexed id, uint256 remainingBalance, address destination); - event UpkeepOffchainConfigSet(uint256 indexed id, bytes offchainConfig); - event UpkeepPaused(uint256 indexed id); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - uint96 totalPayment, - uint256 gasUsed, - uint256 gasOverhead, - bytes trigger - ); - event UpkeepCharged(uint256 indexed id, PaymentReceipt receipt); - event UpkeepPrivilegeConfigSet(uint256 indexed id, bytes privilegeConfig); - event UpkeepReceived(uint256 indexed id, uint256 startingBalance, address importedFrom); - event UpkeepRegistered(uint256 indexed id, uint32 performGas, address admin); - event UpkeepTriggerConfigSet(uint256 indexed id, bytes triggerConfig); - event UpkeepUnpaused(uint256 indexed id); - event Unpaused(address account); - - /** - * @param link address of the LINK Token - * @param linkUSDFeed address of the LINK/USD price feed - * @param nativeUSDFeed address of the Native/USD price feed - * @param fastGasFeed address of the Fast Gas price feed - * @param automationForwarderLogic the address of automation forwarder logic - * @param allowedReadOnlyAddress the address of the allowed read only address - * @param payoutMode the payout mode - */ - constructor( - address link, - address linkUSDFeed, - address nativeUSDFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress, - PayoutMode payoutMode, - address wrappedNativeTokenAddress - ) ConfirmedOwner(msg.sender) { - i_link = LinkTokenInterface(link); - i_linkUSDFeed = AggregatorV3Interface(linkUSDFeed); - i_nativeUSDFeed = AggregatorV3Interface(nativeUSDFeed); - i_fastGasFeed = AggregatorV3Interface(fastGasFeed); - i_automationForwarderLogic = automationForwarderLogic; - i_allowedReadOnlyAddress = allowedReadOnlyAddress; - s_payoutMode = payoutMode; - i_wrappedNativeToken = IWrappedNative(wrappedNativeTokenAddress); - if (i_linkUSDFeed.decimals() != i_nativeUSDFeed.decimals()) { - revert InvalidFeed(); - } - } - - // ================================================================ - // | INTERNAL FUNCTIONS ONLY | - // ================================================================ - - /** - * @dev creates a new upkeep with the given fields - * @param id the id of the upkeep - * @param upkeep the upkeep to create - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data which is passed to user's checkUpkeep - * @param triggerConfig the trigger config for this upkeep - * @param offchainConfig the off-chain config of this upkeep - */ - function _createUpkeep( - uint256 id, - Upkeep memory upkeep, - address admin, - bytes memory checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) internal { - if (s_hotVars.paused) revert RegistryPaused(); - if (checkData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) - revert GasLimitOutsideRange(); - if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); - if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidToken(); - s_upkeep[id] = upkeep; - s_upkeepAdmin[id] = admin; - s_checkData[id] = checkData; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + upkeep.balance; - s_upkeepTriggerConfig[id] = triggerConfig; - s_upkeepOffchainConfig[id] = offchainConfig; - s_upkeepIDs.add(id); - } - - /** - * @dev creates an ID for the upkeep based on the upkeep's type - * @dev the format of the ID looks like this: - * ****00000000000X**************** - * 4 bytes of entropy - * 11 bytes of zeros - * 1 identifying byte for the trigger type - * 16 bytes of entropy - * @dev this maintains the same level of entropy as eth addresses, so IDs will still be unique - * @dev we add the "identifying" part in the middle so that it is mostly hidden from users who usually only - * see the first 4 and last 4 hex values ex 0x1234...ABCD - */ - function _createID(Trigger triggerType) internal view returns (uint256) { - bytes1 empty; - IChainModule chainModule = s_hotVars.chainModule; - bytes memory idBytes = abi.encodePacked( - keccak256(abi.encode(chainModule.blockHash((chainModule.blockNumber() - 1)), address(this), s_storage.nonce)) - ); - for (uint256 idx = 4; idx < 15; idx++) { - idBytes[idx] = empty; - } - idBytes[15] = bytes1(uint8(triggerType)); - return uint256(bytes32(idBytes)); - } - - /** - * @dev retrieves feed data for fast gas/native and link/native prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function _getFeedData( - HotVars memory hotVars - ) internal view returns (uint256 gasWei, uint256 linkUSD, uint256 nativeUSD) { - uint32 stalenessSeconds = hotVars.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = i_fastGasFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = i_linkUSDFeed.latestRoundData(); - if ( - feedValue <= 0 || block.timestamp < timestamp || (staleFallback && stalenessSeconds < block.timestamp - timestamp) - ) { - linkUSD = s_fallbackLinkPrice; - } else { - linkUSD = uint256(feedValue); - } - return (gasWei, linkUSD, _getNativeUSD(hotVars)); - } - - /** - * @dev this price has it's own getter for use in the transmit() hot path - * in the future, all price data should be included in the report instead of - * getting read during execution - */ - function _getNativeUSD(HotVars memory hotVars) internal view returns (uint256) { - (, int256 feedValue, , uint256 timestamp, ) = i_nativeUSDFeed.latestRoundData(); - if ( - feedValue <= 0 || - block.timestamp < timestamp || - (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) - ) { - return s_fallbackNativePrice; - } else { - return uint256(feedValue); - } - } - - /** - * @dev gets the price and billing params for a specific billing token - */ - function _getBillingTokenPaymentParams( - HotVars memory hotVars, - IERC20 billingToken - ) internal view returns (BillingTokenPaymentParams memory paymentParams) { - BillingConfig storage config = s_billingConfigs[billingToken]; - paymentParams.flatFeeMilliCents = config.flatFeeMilliCents; - paymentParams.gasFeePPB = config.gasFeePPB; - paymentParams.decimals = config.decimals; - (, int256 feedValue, , uint256 timestamp, ) = config.priceFeed.latestRoundData(); - if ( - feedValue <= 0 || - block.timestamp < timestamp || - (hotVars.stalenessSeconds > 0 && hotVars.stalenessSeconds < block.timestamp - timestamp) - ) { - paymentParams.priceUSD = config.fallbackPrice; - } else { - paymentParams.priceUSD = uint256(feedValue); - } - return paymentParams; - } - - /** - * @param hotVars the hot path variables - * @param paymentParams the pricing data and gas usage data - * @return receipt the receipt of payment with pricing breakdown - * @dev use of PaymentParams struct is necessary to avoid stack too deep errors - * @dev calculates LINK paid for gas spent plus a configure premium percentage - * @dev 1 USD = 1e18 attoUSD - * @dev 1 USD = 1e26 hexaicosaUSD (had to borrow this prefix from geometry because there is no metric prefix for 1e-26) - * @dev 1 millicent = 1e-5 USD = 1e13 attoUSD - */ - function _calculatePaymentAmount( - HotVars memory hotVars, - PaymentParams memory paymentParams - ) internal view returns (PaymentReceipt memory receipt) { - uint256 decimals = paymentParams.billingTokenParams.decimals; - uint256 gasWei = paymentParams.fastGasWei * hotVars.gasCeilingMultiplier; - // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier - if (paymentParams.isTransaction && tx.gasprice < gasWei) { - gasWei = tx.gasprice; - } - - // scaling factor is based on decimals of billing token, and applies to premium and gasCharge - uint256 numeratorScalingFactor = decimals > 18 ? 10 ** (decimals - 18) : 1; - uint256 denominatorScalingFactor = decimals < 18 ? 10 ** (18 - decimals) : 1; - - // gas calculation - uint256 gasPaymentHexaicosaUSD = (gasWei * - (paymentParams.gasLimit + paymentParams.gasOverhead) + - paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed - // gasChargeInBillingToken is scaled by the billing token's decimals. Round up to ensure a minimum billing token is charged for gas - receipt.gasChargeInBillingToken = SafeCast.toUint96( - ((gasPaymentHexaicosaUSD * numeratorScalingFactor) + - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) - ); - // 18 decimals: 26 decimals / 8 decimals - receipt.gasReimbursementInJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); - - // premium calculation - uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD - uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) * - paymentParams.billingTokenParams.gasFeePPB * - paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; - // premium is scaled by the billing token's decimals. Round up to ensure at least minimum charge - receipt.premiumInBillingToken = SafeCast.toUint96( - ((premiumHexaicosaUSD * numeratorScalingFactor) + - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor - 1)) / - (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) - ); - receipt.premiumInJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); - - receipt.billingToken = paymentParams.billingToken; - receipt.linkUSD = SafeCast.toUint96(paymentParams.linkUSD); - receipt.nativeUSD = SafeCast.toUint96(paymentParams.nativeUSD); - receipt.billingUSD = SafeCast.toUint96(paymentParams.billingTokenParams.priceUSD); - - return receipt; - } - - /** - * @dev calculates the max payment for an upkeep. Called during checkUpkeep simulation and assumes - * maximum gas overhead, L1 fee - */ - function _getMaxPayment( - uint256 upkeepId, - HotVars memory hotVars, - Trigger triggerType, - uint32 performGas, - uint256 fastGasWei, - uint256 linkUSD, - uint256 nativeUSD, - IERC20 billingToken - ) internal view returns (uint96) { - uint256 maxGasOverhead; - - { - if (triggerType == Trigger.CONDITION) { - maxGasOverhead = REGISTRY_CONDITIONAL_OVERHEAD; - } else if (triggerType == Trigger.LOG) { - maxGasOverhead = REGISTRY_LOG_OVERHEAD; - } else { - revert InvalidTriggerType(); - } - (uint256 chainModuleFixedOverhead, ) = s_hotVars.chainModule.getGasOverhead(); - maxGasOverhead += (REGISTRY_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1)) + chainModuleFixedOverhead; - } - - BillingTokenPaymentParams memory paymentParams = _getBillingTokenPaymentParams(hotVars, billingToken); - if (s_upkeep[upkeepId].overridesEnabled) { - BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; - // use the overridden configs - paymentParams.gasFeePPB = billingOverrides.gasFeePPB; - paymentParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; - } - - PaymentReceipt memory receipt = _calculatePaymentAmount( - hotVars, - PaymentParams({ - gasLimit: performGas, - gasOverhead: maxGasOverhead, - l1CostWei: 0, - fastGasWei: fastGasWei, - linkUSD: linkUSD, - nativeUSD: nativeUSD, - billingToken: billingToken, - billingTokenParams: paymentParams, - isTransaction: false - }) - ); - - return receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; - } - - /** - * @dev move a transmitter's balance from total pool to withdrawable balance - */ - function _updateTransmitterBalanceFromPool( - address transmitterAddress, - uint96 totalPremium, - uint96 payeeCount - ) internal returns (uint96) { - Transmitter memory transmitter = s_transmitters[transmitterAddress]; - - if (transmitter.active) { - uint96 uncollected = totalPremium - transmitter.lastCollected; - uint96 due = uncollected / payeeCount; - transmitter.balance += due; - transmitter.lastCollected += due * payeeCount; - s_transmitters[transmitterAddress] = transmitter; - } - - return transmitter.balance; - } - - /** - * @dev gets the trigger type from an upkeepID (trigger type is encoded in the middle of the ID) - */ - function _getTriggerType(uint256 upkeepId) internal pure returns (Trigger) { - bytes32 rawID = bytes32(upkeepId); - bytes1 empty = bytes1(0); - for (uint256 idx = 4; idx < 15; idx++) { - if (rawID[idx] != empty) { - // old IDs that were created before this standard and migrated to this registry - return Trigger.CONDITION; - } - } - return Trigger(uint8(rawID[15])); - } - - function _checkPayload( - uint256 upkeepId, - Trigger triggerType, - bytes memory triggerData - ) internal view returns (bytes memory) { - if (triggerType == Trigger.CONDITION) { - return abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[upkeepId]); - } else if (triggerType == Trigger.LOG) { - Log memory log = abi.decode(triggerData, (Log)); - return abi.encodeWithSelector(CHECK_LOG_SELECTOR, log, s_checkData[upkeepId]); - } - revert InvalidTriggerType(); - } - - /** - * @dev _decodeReport decodes a serialized report into a Report struct - */ - function _decodeReport(bytes calldata rawReport) internal pure returns (Report memory) { - Report memory report = abi.decode(rawReport, (Report)); - uint256 expectedLength = report.upkeepIds.length; - if ( - report.gasLimits.length != expectedLength || - report.triggers.length != expectedLength || - report.performDatas.length != expectedLength - ) { - revert InvalidReport(); - } - return report; - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - * @return bool whether the upkeep should be performed - * @return bytes32 dedupID for preventing duplicate performances of this trigger - */ - function _prePerformChecks( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - bytes32 dedupID; - if (transmitInfo.triggerType == Trigger.CONDITION) { - if (!_validateConditionalTrigger(upkeepId, blocknumber, rawTrigger, transmitInfo, hotVars)) - return (false, dedupID); - } else if (transmitInfo.triggerType == Trigger.LOG) { - bool valid; - (valid, dedupID) = _validateLogTrigger(upkeepId, blocknumber, rawTrigger, hotVars); - if (!valid) return (false, dedupID); - } else { - revert InvalidTriggerType(); - } - if (transmitInfo.upkeep.maxValidBlocknumber <= blocknumber) { - // Can happen when an upkeep got cancelled after report was generated. - // However we have a CANCELLATION_DELAY of 50 blocks so shouldn't happen in practice - emit CancelledUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Does some early sanity checks before actually performing an upkeep - */ - function _validateConditionalTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - UpkeepTransmitInfo memory transmitInfo, - HotVars memory hotVars - ) internal returns (bool) { - ConditionalTrigger memory trigger = abi.decode(rawTrigger, (ConditionalTrigger)); - if (trigger.blockNum < transmitInfo.upkeep.lastPerformedBlockNumber) { - // Can happen when another report performed this upkeep after this report was generated - emit StaleUpkeepReport(upkeepId, rawTrigger); - return false; - } - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // There are two cases of reorged report - // 1. trigger block number is in future: this is an edge case during extreme deep reorgs of chain - // which is always protected against - // 2. blockHash at trigger block number was same as trigger time. This is an optional check which is - // applied if DON sends non empty trigger.blockHash. Note: It only works for last 256 blocks on chain - // when it is sent - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return false; - } - return true; - } - - function _validateLogTrigger( - uint256 upkeepId, - uint256 blocknumber, - bytes memory rawTrigger, - HotVars memory hotVars - ) internal returns (bool, bytes32) { - LogTrigger memory trigger = abi.decode(rawTrigger, (LogTrigger)); - bytes32 dedupID = keccak256(abi.encodePacked(upkeepId, trigger.logBlockHash, trigger.txHash, trigger.logIndex)); - if ( - (hotVars.reorgProtectionEnabled && - (trigger.blockHash != bytes32("") && hotVars.chainModule.blockHash(trigger.blockNum) != trigger.blockHash)) || - trigger.blockNum >= blocknumber - ) { - // Reorg protection is same as conditional trigger upkeeps - emit ReorgedUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - if (s_dedupKeys[dedupID]) { - emit StaleUpkeepReport(upkeepId, rawTrigger); - return (false, dedupID); - } - return (true, dedupID); - } - - /** - * @dev Verify signatures attached to report - */ - function _verifyReportSignature( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) internal view { - bytes32 h = keccak256(abi.encode(keccak256(report), reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount = 0; - - Signer memory signer; - address signerAddress; - for (uint256 i = 0; i < rs.length; i++) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - signer = s_signers[signerAddress]; - if (!signer.active) revert OnlyActiveSigners(); - unchecked { - signedCount += 1 << (8 * signer.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert DuplicateSigners(); - } - - /** - * @dev updates a storage marker for this upkeep to prevent duplicate and out of order performances - * @dev for conditional triggers we set the latest block number, for log triggers we store a dedupID - */ - function _updateTriggerMarker( - uint256 upkeepID, - uint256 blocknumber, - UpkeepTransmitInfo memory upkeepTransmitInfo - ) internal { - if (upkeepTransmitInfo.triggerType == Trigger.CONDITION) { - s_upkeep[upkeepID].lastPerformedBlockNumber = uint32(blocknumber); - } else if (upkeepTransmitInfo.triggerType == Trigger.LOG) { - s_dedupKeys[upkeepTransmitInfo.dedupID] = true; - emit DedupKeyAdded(upkeepTransmitInfo.dedupID); - } - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * transmitter and the exact gas required by the Upkeep - */ - function _performUpkeep( - IAutomationForwarder forwarder, - uint256 performGas, - bytes memory performData - ) internal nonReentrant returns (bool success, uint256 gasUsed) { - performData = abi.encodeWithSelector(PERFORM_SELECTOR, performData); - return forwarder.forward(performGas, performData); - } - - /** - * @dev handles the payment processing after an upkeep has been performed. - * Deducts an upkeep's balance and increases the amount spent. - */ - function _handlePayment( - HotVars memory hotVars, - PaymentParams memory paymentParams, - uint256 upkeepId, - Upkeep memory upkeep - ) internal returns (PaymentReceipt memory) { - if (upkeep.overridesEnabled) { - BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; - // use the overridden configs - paymentParams.billingTokenParams.gasFeePPB = billingOverrides.gasFeePPB; - paymentParams.billingTokenParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; - } - - PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); - - // balance is in the token's native decimals - uint96 balance = upkeep.balance; - // payment is in the token's native decimals - uint96 payment = receipt.gasChargeInBillingToken + receipt.premiumInBillingToken; - - // scaling factors to adjust decimals between billing token and LINK - uint256 decimals = paymentParams.billingTokenParams.decimals; - uint256 scalingFactor1 = decimals < 18 ? 10 ** (18 - decimals) : 1; - uint256 scalingFactor2 = decimals > 18 ? 10 ** (decimals - 18) : 1; - - // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user - // can't cover the amount owed - if (balance < receipt.gasChargeInBillingToken) { - // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON - payment = balance; - receipt.gasReimbursementInJuels = SafeCast.toUint96( - (balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / - (paymentParams.linkUSD * scalingFactor2) - ); - receipt.premiumInJuels = 0; - receipt.premiumInBillingToken = 0; - receipt.gasChargeInBillingToken = balance; - } else if (balance < payment) { - // if the user can cover the gas fee, but not the premium, then reduce the premium - payment = balance; - receipt.premiumInJuels = SafeCast.toUint96( - ((balance * paymentParams.billingTokenParams.priceUSD * scalingFactor1) / - (paymentParams.linkUSD * scalingFactor2)) - receipt.gasReimbursementInJuels - ); - // round up - receipt.premiumInBillingToken = SafeCast.toUint96( - ((receipt.premiumInJuels * paymentParams.linkUSD * scalingFactor2) + - (paymentParams.billingTokenParams.priceUSD * scalingFactor1 - 1)) / - (paymentParams.billingTokenParams.priceUSD * scalingFactor1) - ); - } - - s_upkeep[upkeepId].balance -= payment; - s_upkeep[upkeepId].amountSpent += payment; - s_reserveAmounts[paymentParams.billingToken] -= payment; - - emit UpkeepCharged(upkeepId, receipt); - return receipt; - } - - /** - * @dev ensures the upkeep is not cancelled and the caller is the upkeep admin - */ - function _requireAdminAndNotCancelled(uint256 upkeepId) internal view { - if (msg.sender != s_upkeepAdmin[upkeepId]) revert OnlyCallableByAdmin(); - if (s_upkeep[upkeepId].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - } - - /** - * @dev replicates Open Zeppelin's ReentrancyGuard but optimized to fit our storage - */ - modifier nonReentrant() { - if (s_hotVars.reentrancyGuard) revert ReentrantCall(); - s_hotVars.reentrancyGuard = true; - _; - s_hotVars.reentrancyGuard = false; - } - - /** - * @notice only allows a pre-configured address to initiate offchain read - */ - function _preventExecution() internal view { - // solhint-disable-next-line avoid-tx-origin - if (tx.origin != i_allowedReadOnlyAddress) { - revert OnlySimulatedBackend(); - } - } - - /** - * @notice only allows finance admin to call the function - */ - function _onlyFinanceAdminAllowed() internal view { - if (msg.sender != s_storage.financeAdmin) { - revert OnlyFinanceAdmin(); - } - } - - /** - * @notice only allows privilege manager to call the function - */ - function _onlyPrivilegeManagerAllowed() internal view { - if (msg.sender != s_storage.upkeepPrivilegeManager) { - revert OnlyCallableByUpkeepPrivilegeManager(); - } - } - - /** - * @notice sets billing configuration for a token - * @param billingTokens the addresses of tokens - * @param billingConfigs the configs for tokens - */ - function _setBillingConfig(IERC20[] memory billingTokens, BillingConfig[] memory billingConfigs) internal { - // Clear existing data - for (uint256 i = 0; i < s_billingTokens.length; i++) { - delete s_billingConfigs[s_billingTokens[i]]; - } - delete s_billingTokens; - - PayoutMode mode = s_payoutMode; - for (uint256 i = 0; i < billingTokens.length; i++) { - IERC20 token = billingTokens[i]; - BillingConfig memory config = billingConfigs[i]; - - // most ERC20 tokens are 18 decimals, priceFeed must be 8 decimals - if (config.decimals != token.decimals() || config.priceFeed.decimals() != 8) { - revert InvalidToken(); - } - - // if LINK is a billing option, payout mode must be ON_CHAIN - if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { - revert InvalidToken(); - } - if (address(token) == ZERO_ADDRESS || address(config.priceFeed) == ZERO_ADDRESS) { - revert ZeroAddressNotAllowed(); - } - - // if this is a new token, add it to tokens list. Otherwise revert - if (address(s_billingConfigs[token].priceFeed) != ZERO_ADDRESS) { - revert DuplicateEntry(); - } - s_billingTokens.push(token); - - // update the billing config for an existing token or add a new one - s_billingConfigs[token] = config; - - emit BillingConfigSet(token, config); - } - } - - /** - * @notice updates the signers and transmitters lists - */ - function _updateTransmitters(address[] memory signers, address[] memory transmitters) internal { - uint96 transmittersListLength = uint96(s_transmittersList.length); - uint96 totalPremium = s_hotVars.totalPremium; - - // move all pooled payments out of the pool to each transmitter's balance - for (uint256 i = 0; i < s_transmittersList.length; i++) { - _updateTransmitterBalanceFromPool(s_transmittersList[i], totalPremium, transmittersListLength); - } - - // remove any old signer/transmitter addresses - address transmitterAddress; - PayoutMode mode = s_payoutMode; - for (uint256 i = 0; i < s_transmittersList.length; i++) { - transmitterAddress = s_transmittersList[i]; - delete s_signers[s_signersList[i]]; - // Do not delete the whole transmitter struct as it has balance information stored - s_transmitters[transmitterAddress].active = false; - if (mode == PayoutMode.OFF_CHAIN && s_transmitters[transmitterAddress].balance > 0) { - s_deactivatedTransmitters.add(transmitterAddress); - } - } - delete s_signersList; - delete s_transmittersList; - - // add new signer/transmitter addresses - Transmitter memory transmitter; - for (uint256 i = 0; i < signers.length; i++) { - if (s_signers[signers[i]].active) revert RepeatedSigner(); - if (signers[i] == ZERO_ADDRESS) revert InvalidSigner(); - s_signers[signers[i]] = Signer({active: true, index: uint8(i)}); - - transmitterAddress = transmitters[i]; - if (transmitterAddress == ZERO_ADDRESS) revert InvalidTransmitter(); - transmitter = s_transmitters[transmitterAddress]; - if (transmitter.active) revert RepeatedTransmitter(); - transmitter.active = true; - transmitter.index = uint8(i); - // new transmitters start afresh from current totalPremium - // some spare change of premium from previous pool will be forfeited - transmitter.lastCollected = s_hotVars.totalPremium; - s_transmitters[transmitterAddress] = transmitter; - if (mode == PayoutMode.OFF_CHAIN) { - s_deactivatedTransmitters.remove(transmitterAddress); - } - } - - s_signersList = signers; - s_transmittersList = transmitters; - } - - /** - * @notice returns the size of the LINK liquidity pool - # @dev LINK max supply < 2^96, so casting to int256 is safe - */ - function _linkAvailableForPayment() internal view returns (int256) { - return int256(i_link.balanceOf(address(this))) - int256(s_reserveAmounts[IERC20(address(i_link))]); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol deleted file mode 100644 index 64d697c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicA2_3.sol +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; -import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; -import {ZKSyncAutomationRegistryLogicB2_3} from "./ZKSyncAutomationRegistryLogicB2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {ZKSyncAutomationForwarder} from "../ZKSyncAutomationForwarder.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {UpkeepTranscoderInterfaceV2} from "../interfaces/UpkeepTranscoderInterfaceV2.sol"; -import {MigratableKeeperRegistryInterfaceV2} from "../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @notice Logic contract, works in tandem with AutomationRegistry as a proxy - */ -contract ZKSyncAutomationRegistryLogicA2_3 is ZKSyncAutomationRegistryBase2_3, Chainable, IERC677Receiver { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - using SafeERC20 for IERC20; - - /** - * @param logicB the address of the second logic contract - * @dev we cast the contract to logicC in order to call logicC functions (via fallback) - */ - constructor( - ZKSyncAutomationRegistryLogicB2_3 logicB - ) - ZKSyncAutomationRegistryBase2_3( - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getLinkAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getLinkUSDFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getNativeUSDFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getFastGasFeedAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getAutomationForwarderLogic(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getAllowedReadOnlyAddress(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getPayoutMode(), - ZKSyncAutomationRegistryLogicC2_3(address(logicB)).getWrappedNativeTokenAddress() - ) - Chainable(address(logicB)) - {} - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external override { - if (msg.sender != address(i_link)) revert OnlyCallableByLINKToken(); - if (data.length != 32) revert InvalidDataLength(); - uint256 id = abi.decode(data, (uint256)); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken(); - s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); - s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount; - emit FundsAdded(id, sender, uint96(amount)); - } - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param triggerType the trigger for the upkeep - * @param billingToken the billing token for the upkeep - * @param checkData data passed to the contract when checking for upkeep - * @param triggerConfig the config for the trigger - * @param offchainConfig arbitrary offchain config for the upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - Trigger triggerType, - IERC20 billingToken, - bytes calldata checkData, - bytes memory triggerConfig, - bytes memory offchainConfig - ) public returns (uint256 id) { - if (msg.sender != owner() && !s_registrars.contains(msg.sender)) revert OnlyCallableByOwnerOrRegistrar(); - if (!target.isContract()) revert NotAContract(); - id = _createID(triggerType); - IAutomationForwarder forwarder = IAutomationForwarder( - address(new ZKSyncAutomationForwarder(target, address(this), i_automationForwarderLogic)) - ); - _createUpkeep( - id, - Upkeep({ - overridesEnabled: false, - performGas: gasLimit, - balance: 0, - maxValidBlocknumber: UINT32_MAX, - lastPerformedBlockNumber: 0, - amountSpent: 0, - paused: false, - forwarder: forwarder, - billingToken: billingToken - }), - admin, - checkData, - triggerConfig, - offchainConfig - ); - s_storage.nonce++; - emit UpkeepRegistered(id, gasLimit, admin); - emit UpkeepCheckDataSet(id, checkData); - emit UpkeepTriggerConfigSet(id, triggerConfig); - emit UpkeepOffchainConfigSet(id, offchainConfig); - return (id); - } - - /** - * @notice cancels an upkeep - * @param id the upkeepID to cancel - * @dev if a user cancels an upkeep, their funds are locked for CANCELLATION_DELAY blocks to - * allow any pending performUpkeep txs time to get confirmed - */ - function cancelUpkeep(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - bool isOwner = msg.sender == owner(); - uint96 minSpend = s_billingConfigs[upkeep.billingToken].minSpend; - - uint256 height = s_hotVars.chainModule.blockNumber(); - if (upkeep.maxValidBlocknumber == 0) revert CannotCancel(); - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (!isOwner && msg.sender != s_upkeepAdmin[id]) revert OnlyCallableByOwnerOrAdmin(); - - if (!isOwner) { - height = height + CANCELLATION_DELAY; - } - s_upkeep[id].maxValidBlocknumber = uint32(height); - s_upkeepIDs.remove(id); - - // charge the cancellation fee if the minSpend is not met - uint96 cancellationFee = 0; - // cancellationFee is min(max(minSpend - amountSpent, 0), amountLeft) - if (upkeep.amountSpent < minSpend) { - cancellationFee = minSpend - uint96(upkeep.amountSpent); - if (cancellationFee > upkeep.balance) { - cancellationFee = upkeep.balance; - } - } - s_upkeep[id].balance = upkeep.balance - cancellationFee; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - cancellationFee; - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice migrates upkeeps from one registry to another. - * @param ids the upkeepIDs to migrate - * @param destination the destination registry address - * @dev a transcoder must be set in order to enable migration - * @dev migration permissions must be set on *both* sending and receiving registries - * @dev only an upkeep admin can migrate their upkeeps - * @dev this function is most gas-efficient if upkeepIDs are sorted by billing token - * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not migrated in this function - */ - function migrateUpkeeps(uint256[] calldata ids, address destination) external { - if ( - s_peerRegistryMigrationPermission[destination] != MigrationPermission.OUTGOING && - s_peerRegistryMigrationPermission[destination] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - if (s_storage.transcoder == ZERO_ADDRESS) revert TranscoderNotSet(); - if (ids.length == 0) revert ArrayHasNoEntries(); - - IERC20 billingToken; - uint256 balanceToTransfer; - uint256 id; - Upkeep memory upkeep; - address[] memory admins = new address[](ids.length); - Upkeep[] memory upkeeps = new Upkeep[](ids.length); - bytes[] memory checkDatas = new bytes[](ids.length); - bytes[] memory triggerConfigs = new bytes[](ids.length); - bytes[] memory offchainConfigs = new bytes[](ids.length); - - for (uint256 idx = 0; idx < ids.length; idx++) { - id = ids[idx]; - upkeep = s_upkeep[id]; - - if (idx == 0) { - billingToken = upkeep.billingToken; - balanceToTransfer = upkeep.balance; - } - - // if we encounter a new billing token, send the sum from the last billing token to the destination registry - if (upkeep.billingToken != billingToken) { - s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; - billingToken.safeTransfer(destination, balanceToTransfer); - billingToken = upkeep.billingToken; - balanceToTransfer = upkeep.balance; - } else if (idx != 0) { - balanceToTransfer += upkeep.balance; - } - - _requireAdminAndNotCancelled(id); - upkeep.forwarder.updateRegistry(destination); - - upkeeps[idx] = upkeep; - admins[idx] = s_upkeepAdmin[id]; - checkDatas[idx] = s_checkData[id]; - triggerConfigs[idx] = s_upkeepTriggerConfig[id]; - offchainConfigs[idx] = s_upkeepOffchainConfig[id]; - delete s_upkeep[id]; - delete s_checkData[id]; - delete s_upkeepTriggerConfig[id]; - delete s_upkeepOffchainConfig[id]; - // nullify existing proposed admin change if an upkeep is being migrated - delete s_proposedAdmin[id]; - delete s_upkeepAdmin[id]; - s_upkeepIDs.remove(id); - emit UpkeepMigrated(id, upkeep.balance, destination); - } - // always transfer the rolling sum in the end - s_reserveAmounts[billingToken] = s_reserveAmounts[billingToken] - balanceToTransfer; - billingToken.safeTransfer(destination, balanceToTransfer); - - bytes memory encodedUpkeeps = abi.encode( - ids, - upkeeps, - new address[](ids.length), - admins, - checkDatas, - triggerConfigs, - offchainConfigs - ); - MigratableKeeperRegistryInterfaceV2(destination).receiveUpkeeps( - UpkeepTranscoderInterfaceV2(s_storage.transcoder).transcodeUpkeeps( - UPKEEP_VERSION_BASE, - MigratableKeeperRegistryInterfaceV2(destination).upkeepVersion(), - encodedUpkeeps - ) - ); - } - - /** - * @notice received upkeeps migrated from another registry - * @param encodedUpkeeps the raw upkeep data to import - * @dev this function is never called directly, it is only called by another registry's migrate function - * @dev s_billingOverrides and s_upkeepPrivilegeConfig are not handled in this function - */ - function receiveUpkeeps(bytes calldata encodedUpkeeps) external { - if ( - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.INCOMING && - s_peerRegistryMigrationPermission[msg.sender] != MigrationPermission.BIDIRECTIONAL - ) revert MigrationNotPermitted(); - ( - uint256[] memory ids, - Upkeep[] memory upkeeps, - address[] memory targets, - address[] memory upkeepAdmins, - bytes[] memory checkDatas, - bytes[] memory triggerConfigs, - bytes[] memory offchainConfigs - ) = abi.decode(encodedUpkeeps, (uint256[], Upkeep[], address[], address[], bytes[], bytes[], bytes[])); - for (uint256 idx = 0; idx < ids.length; idx++) { - if (address(upkeeps[idx].forwarder) == ZERO_ADDRESS) { - upkeeps[idx].forwarder = IAutomationForwarder( - address(new ZKSyncAutomationForwarder(targets[idx], address(this), i_automationForwarderLogic)) - ); - } - _createUpkeep( - ids[idx], - upkeeps[idx], - upkeepAdmins[idx], - checkDatas[idx], - triggerConfigs[idx], - offchainConfigs[idx] - ); - emit UpkeepReceived(ids[idx], upkeeps[idx].balance, msg.sender); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol deleted file mode 100644 index 55af99f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicB2_3.sol +++ /dev/null @@ -1,449 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {ZKSyncAutomationRegistryLogicC2_3} from "./ZKSyncAutomationRegistryLogicC2_3.sol"; -import {Chainable} from "../Chainable.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -contract ZKSyncAutomationRegistryLogicB2_3 is ZKSyncAutomationRegistryBase2_3, Chainable { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - using SafeERC20 for IERC20; - - /** - * @param logicC the address of the third logic contract - */ - constructor( - ZKSyncAutomationRegistryLogicC2_3 logicC - ) - ZKSyncAutomationRegistryBase2_3( - logicC.getLinkAddress(), - logicC.getLinkUSDFeedAddress(), - logicC.getNativeUSDFeedAddress(), - logicC.getFastGasFeedAddress(), - logicC.getAutomationForwarderLogic(), - logicC.getAllowedReadOnlyAddress(), - logicC.getPayoutMode(), - logicC.getWrappedNativeTokenAddress() - ) - Chainable(address(logicC)) - {} - - // ================================================================ - // | PIPELINE FUNCTIONS | - // ================================================================ - - /** - * @notice called by the automation DON to check if work is needed - * @param id the upkeep ID to check for work needed - * @param triggerData extra contextual data about the trigger (not used in all code paths) - * @dev this one of the core functions called in the hot path - * @dev there is a 2nd checkUpkeep function (below) that is being maintained for backwards compatibility - * @dev there is an incongruency on what gets returned during failure modes - * ex sometimes we include price data, sometimes we omit it depending on the failure - */ - function checkUpkeep( - uint256 id, - bytes memory triggerData - ) - public - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ) - { - _preventExecution(); - - Trigger triggerType = _getTriggerType(id); - HotVars memory hotVars = s_hotVars; - Upkeep memory upkeep = s_upkeep[id]; - - { - uint256 nativeUSD; - uint96 maxPayment; - if (hotVars.paused) return (false, bytes(""), UpkeepFailureReason.REGISTRY_PAUSED, 0, upkeep.performGas, 0, 0); - if (upkeep.maxValidBlocknumber != UINT32_MAX) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_CANCELLED, 0, upkeep.performGas, 0, 0); - if (upkeep.paused) return (false, bytes(""), UpkeepFailureReason.UPKEEP_PAUSED, 0, upkeep.performGas, 0, 0); - (fastGasWei, linkUSD, nativeUSD) = _getFeedData(hotVars); - maxPayment = _getMaxPayment( - id, - hotVars, - triggerType, - upkeep.performGas, - fastGasWei, - linkUSD, - nativeUSD, - upkeep.billingToken - ); - if (upkeep.balance < maxPayment) { - return (false, bytes(""), UpkeepFailureReason.INSUFFICIENT_BALANCE, 0, upkeep.performGas, 0, 0); - } - } - - bytes memory callData = _checkPayload(id, triggerType, triggerData); - - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(callData); - gasUsed = gasUsed - gasleft(); - - if (!success) { - // User's target check reverted. We capture the revert data here and pass it within performData - if (result.length > s_storage.maxRevertDataSize) { - return ( - false, - bytes(""), - UpkeepFailureReason.REVERT_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - } - return ( - upkeepNeeded, - result, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - } - - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed, upkeep.performGas, fastGasWei, linkUSD); - - if (performData.length > s_storage.maxPerformDataSize) - return ( - false, - bytes(""), - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - gasUsed, - upkeep.performGas, - fastGasWei, - linkUSD - ); - - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed, upkeep.performGas, fastGasWei, linkUSD); - } - - /** - * @notice see other checkUpkeep function for description - * @dev this function may be deprecated in a future version of chainlink automation - */ - function checkUpkeep( - uint256 id - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData, - UpkeepFailureReason upkeepFailureReason, - uint256 gasUsed, - uint256 gasLimit, - uint256 fastGasWei, - uint256 linkUSD - ) - { - return checkUpkeep(id, bytes("")); - } - - /** - * @dev checkCallback is used specifically for automation data streams lookups (see StreamsLookupCompatibleInterface.sol) - * @param id the upkeepID to execute a callback for - * @param values the values returned from the data streams lookup - * @param extraData the user-provided extra context data - */ - function checkCallback( - uint256 id, - bytes[] memory values, - bytes calldata extraData - ) - external - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - bytes memory payload = abi.encodeWithSelector(CHECK_CALLBACK_SELECTOR, values, extraData); - return executeCallback(id, payload); - } - - /** - * @notice this is a generic callback executor that forwards a call to a user's contract with the configured - * gas limit - * @param id the upkeepID to execute a callback for - * @param payload the data (including function selector) to call on the upkeep target contract - */ - function executeCallback( - uint256 id, - bytes memory payload - ) - public - returns (bool upkeepNeeded, bytes memory performData, UpkeepFailureReason upkeepFailureReason, uint256 gasUsed) - { - _preventExecution(); - - Upkeep memory upkeep = s_upkeep[id]; - gasUsed = gasleft(); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = upkeep.forwarder.getTarget().call{gas: s_storage.checkGasLimit}(payload); - gasUsed = gasUsed - gasleft(); - if (!success) { - return (false, bytes(""), UpkeepFailureReason.CALLBACK_REVERTED, gasUsed); - } - (upkeepNeeded, performData) = abi.decode(result, (bool, bytes)); - if (!upkeepNeeded) { - return (false, bytes(""), UpkeepFailureReason.UPKEEP_NOT_NEEDED, gasUsed); - } - if (performData.length > s_storage.maxPerformDataSize) { - return (false, bytes(""), UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, gasUsed); - } - return (upkeepNeeded, performData, upkeepFailureReason, gasUsed); - } - - /** - * @notice simulates the upkeep with the perform data returned from checkUpkeep - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - * @return success whether the call reverted or not - * @return gasUsed the amount of gas the target contract consumed - */ - function simulatePerformUpkeep( - uint256 id, - bytes calldata performData - ) external returns (bool success, uint256 gasUsed) { - _preventExecution(); - - if (s_hotVars.paused) revert RegistryPaused(); - Upkeep memory upkeep = s_upkeep[id]; - (success, gasUsed) = _performUpkeep(upkeep.forwarder, upkeep.performGas, performData); - return (success, gasUsed); - } - - // ================================================================ - // | UPKEEP MANAGEMENT | - // ================================================================ - - /** - * @notice adds fund to an upkeep - * @param id the upkeepID - * @param amount the amount of funds to add, in the upkeep's billing token - */ - function addFunds(uint256 id, uint96 amount) external payable { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - if (msg.value != 0) { - if (upkeep.billingToken != IERC20(i_wrappedNativeToken)) { - revert InvalidToken(); - } - amount = SafeCast.toUint96(msg.value); - } - - s_upkeep[id].balance = upkeep.balance + amount; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] + amount; - - if (msg.value == 0) { - // ERC20 payment - upkeep.billingToken.safeTransferFrom(msg.sender, address(this), amount); - } else { - // native payment - i_wrappedNativeToken.deposit{value: amount}(); - } - - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice overrides the billing config for an upkeep - * @param id the upkeepID - * @param billingOverrides the override-able billing config - */ - function setBillingOverrides(uint256 id, BillingOverrides calldata billingOverrides) external { - _onlyPrivilegeManagerAllowed(); - if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - - s_upkeep[id].overridesEnabled = true; - s_billingOverrides[id] = billingOverrides; - emit BillingConfigOverridden(id, billingOverrides); - } - - /** - * @notice remove the overridden billing config for an upkeep - * @param id the upkeepID - */ - function removeBillingOverrides(uint256 id) external { - _onlyPrivilegeManagerAllowed(); - - s_upkeep[id].overridesEnabled = false; - delete s_billingOverrides[id]; - emit BillingConfigOverrideRemoved(id); - } - - /** - * @notice transfers the address of an admin for an upkeep - */ - function transferUpkeepAdmin(uint256 id, address proposed) external { - _requireAdminAndNotCancelled(id); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedAdmin[id] != proposed) { - s_proposedAdmin[id] = proposed; - emit UpkeepAdminTransferRequested(id, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of an upkeep admin - */ - function acceptUpkeepAdmin(uint256 id) external { - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (s_proposedAdmin[id] != msg.sender) revert OnlyCallableByProposedAdmin(); - address past = s_upkeepAdmin[id]; - s_upkeepAdmin[id] = msg.sender; - s_proposedAdmin[id] = ZERO_ADDRESS; - - emit UpkeepAdminTransferred(id, past, msg.sender); - } - - /** - * @notice pauses an upkeep - an upkeep will be neither checked nor performed while paused - */ - function pauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (upkeep.paused) revert OnlyUnpausedUpkeep(); - s_upkeep[id].paused = true; - s_upkeepIDs.remove(id); - emit UpkeepPaused(id); - } - - /** - * @notice unpauses an upkeep - */ - function unpauseUpkeep(uint256 id) external { - _requireAdminAndNotCancelled(id); - Upkeep memory upkeep = s_upkeep[id]; - if (!upkeep.paused) revert OnlyPausedUpkeep(); - s_upkeep[id].paused = false; - s_upkeepIDs.add(id); - emit UpkeepUnpaused(id); - } - - /** - * @notice updates the checkData for an upkeep - */ - function setUpkeepCheckData(uint256 id, bytes calldata newCheckData) external { - _requireAdminAndNotCancelled(id); - if (newCheckData.length > s_storage.maxCheckDataSize) revert CheckDataExceedsLimit(); - s_checkData[id] = newCheckData; - emit UpkeepCheckDataSet(id, newCheckData); - } - - /** - * @notice updates the gas limit for an upkeep - */ - function setUpkeepGasLimit(uint256 id, uint32 gasLimit) external { - if (gasLimit < PERFORM_GAS_MIN || gasLimit > s_storage.maxPerformGas) revert GasLimitOutsideRange(); - _requireAdminAndNotCancelled(id); - s_upkeep[id].performGas = gasLimit; - - emit UpkeepGasLimitSet(id, gasLimit); - } - - /** - * @notice updates the offchain config for an upkeep - */ - function setUpkeepOffchainConfig(uint256 id, bytes calldata config) external { - _requireAdminAndNotCancelled(id); - s_upkeepOffchainConfig[id] = config; - emit UpkeepOffchainConfigSet(id, config); - } - - /** - * @notice sets the upkeep trigger config - * @param id the upkeepID to change the trigger for - * @param triggerConfig the new trigger config - */ - function setUpkeepTriggerConfig(uint256 id, bytes calldata triggerConfig) external { - _requireAdminAndNotCancelled(id); - s_upkeepTriggerConfig[id] = triggerConfig; - emit UpkeepTriggerConfigSet(id, triggerConfig); - } - - /** - * @notice withdraws an upkeep's funds from an upkeep - * @dev note that an upkeep must be cancelled first!! - */ - function withdrawFunds(uint256 id, address to) external nonReentrant { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - Upkeep memory upkeep = s_upkeep[id]; - if (s_upkeepAdmin[id] != msg.sender) revert OnlyCallableByAdmin(); - if (upkeep.maxValidBlocknumber > s_hotVars.chainModule.blockNumber()) revert UpkeepNotCanceled(); - uint96 amountToWithdraw = s_upkeep[id].balance; - s_reserveAmounts[upkeep.billingToken] = s_reserveAmounts[upkeep.billingToken] - amountToWithdraw; - s_upkeep[id].balance = 0; - upkeep.billingToken.safeTransfer(to, amountToWithdraw); - emit FundsWithdrawn(id, amountToWithdraw, to); - } - - // ================================================================ - // | FINANCE ACTIONS | - // ================================================================ - - /** - * @notice withdraws excess LINK from the liquidity pool - * @param to the address to send the fees to - * @param amount the amount to withdraw - */ - function withdrawLink(address to, uint256 amount) external { - _onlyFinanceAdminAllowed(); - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - - int256 available = _linkAvailableForPayment(); - if (available < 0) { - revert InsufficientBalance(0, amount); - } else if (amount > uint256(available)) { - revert InsufficientBalance(uint256(available), amount); - } - - bool transferStatus = i_link.transfer(to, amount); - if (!transferStatus) { - revert TransferFailed(); - } - emit FeesWithdrawn(address(i_link), to, amount); - } - - /** - * @notice withdraws non-LINK fees earned by the contract - * @param asset the asset to withdraw - * @param to the address to send the fees to - * @param amount the amount to withdraw - * @dev in ON_CHAIN mode, we prevent withdrawing non-LINK fees unless there is sufficient LINK liquidity - * to cover all outstanding debts on the registry - */ - function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { - _onlyFinanceAdminAllowed(); - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (address(asset) == address(i_link)) revert InvalidToken(); - if (_linkAvailableForPayment() < 0 && s_payoutMode == PayoutMode.ON_CHAIN) revert InsufficientLinkLiquidity(); - uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; - if (amount > available) revert InsufficientBalance(available, amount); - - asset.safeTransfer(to, amount); - emit FeesWithdrawn(address(asset), to, amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol deleted file mode 100644 index 3b4b023..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/automation/v2_3_zksync/ZKSyncAutomationRegistryLogicC2_3.sol +++ /dev/null @@ -1,626 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -import {ZKSyncAutomationRegistryBase2_3} from "./ZKSyncAutomationRegistryBase2_3.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; -import {IAutomationForwarder} from "../interfaces/IAutomationForwarder.sol"; -import {IChainModule} from "../interfaces/IChainModule.sol"; -import {IERC20Metadata as IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {IAutomationV21PlusCommon} from "../interfaces/IAutomationV21PlusCommon.sol"; - -contract ZKSyncAutomationRegistryLogicC2_3 is ZKSyncAutomationRegistryBase2_3 { - using Address for address; - using EnumerableSet for EnumerableSet.UintSet; - using EnumerableSet for EnumerableSet.AddressSet; - - /** - * @dev see AutomationRegistry master contract for constructor description - */ - constructor( - address link, - address linkUSDFeed, - address nativeUSDFeed, - address fastGasFeed, - address automationForwarderLogic, - address allowedReadOnlyAddress, - PayoutMode payoutMode, - address wrappedNativeTokenAddress - ) - ZKSyncAutomationRegistryBase2_3( - link, - linkUSDFeed, - nativeUSDFeed, - fastGasFeed, - automationForwarderLogic, - allowedReadOnlyAddress, - payoutMode, - wrappedNativeTokenAddress - ) - {} - - // ================================================================ - // | NODE ACTIONS | - // ================================================================ - - /** - * @notice transfers the address of payee for a transmitter - */ - function transferPayeeship(address transmitter, address proposed) external { - if (s_transmitterPayees[transmitter] != msg.sender) revert OnlyCallableByPayee(); - if (proposed == msg.sender) revert ValueNotChanged(); - - if (s_proposedPayee[transmitter] != proposed) { - s_proposedPayee[transmitter] = proposed; - emit PayeeshipTransferRequested(transmitter, msg.sender, proposed); - } - } - - /** - * @notice accepts the transfer of the payee - */ - function acceptPayeeship(address transmitter) external { - if (s_proposedPayee[transmitter] != msg.sender) revert OnlyCallableByProposedPayee(); - address past = s_transmitterPayees[transmitter]; - s_transmitterPayees[transmitter] = msg.sender; - s_proposedPayee[transmitter] = ZERO_ADDRESS; - - emit PayeeshipTransferred(transmitter, past, msg.sender); - } - - /** - * @notice this is for NOPs to withdraw LINK received as payment for work performed - */ - function withdrawPayment(address from, address to) external { - if (to == ZERO_ADDRESS) revert InvalidRecipient(); - if (s_payoutMode == PayoutMode.OFF_CHAIN) revert MustSettleOffchain(); - if (s_transmitterPayees[from] != msg.sender) revert OnlyCallableByPayee(); - uint96 balance = _updateTransmitterBalanceFromPool(from, s_hotVars.totalPremium, uint96(s_transmittersList.length)); - s_transmitters[from].balance = 0; - s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] - balance; - bool transferStatus = i_link.transfer(to, balance); - if (!transferStatus) { - revert TransferFailed(); - } - emit PaymentWithdrawn(from, balance, to, msg.sender); - } - - // ================================================================ - // | OWNER / MANAGER ACTIONS | - // ================================================================ - - /** - * @notice sets the privilege config for an upkeep - */ - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes calldata newPrivilegeConfig) external { - _onlyPrivilegeManagerAllowed(); - s_upkeepPrivilegeConfig[upkeepId] = newPrivilegeConfig; - emit UpkeepPrivilegeConfigSet(upkeepId, newPrivilegeConfig); - } - - /** - * @notice this is used by the owner to set the initial payees for newly added transmitters. The owner is not allowed to change payees for existing transmitters. - * @dev the IGNORE_ADDRESS is a "helper" that makes it easier to construct a list of payees when you only care about setting the payee for a small number of transmitters. - */ - function setPayees(address[] calldata payees) external onlyOwner { - if (s_transmittersList.length != payees.length) revert ParameterLengthError(); - for (uint256 i = 0; i < s_transmittersList.length; i++) { - address transmitter = s_transmittersList[i]; - address oldPayee = s_transmitterPayees[transmitter]; - address newPayee = payees[i]; - - if ( - (newPayee == ZERO_ADDRESS) || (oldPayee != ZERO_ADDRESS && oldPayee != newPayee && newPayee != IGNORE_ADDRESS) - ) { - revert InvalidPayee(); - } - - if (newPayee != IGNORE_ADDRESS) { - s_transmitterPayees[transmitter] = newPayee; - } - } - emit PayeesUpdated(s_transmittersList, payees); - } - - /** - * @notice sets the migration permission for a peer registry - * @dev this must be done before upkeeps can be migrated to/from another registry - */ - function setPeerRegistryMigrationPermission(address peer, MigrationPermission permission) external onlyOwner { - s_peerRegistryMigrationPermission[peer] = permission; - } - - /** - * @notice pauses the entire registry - */ - function pause() external onlyOwner { - s_hotVars.paused = true; - emit Paused(msg.sender); - } - - /** - * @notice unpauses the entire registry - */ - function unpause() external onlyOwner { - s_hotVars.paused = false; - emit Unpaused(msg.sender); - } - - /** - * @notice sets a generic bytes field used to indicate the privilege that this admin address had - * @param admin the address to set privilege for - * @param newPrivilegeConfig the privileges that this admin has - */ - function setAdminPrivilegeConfig(address admin, bytes calldata newPrivilegeConfig) external { - _onlyPrivilegeManagerAllowed(); - s_adminPrivilegeConfig[admin] = newPrivilegeConfig; - emit AdminPrivilegeConfigSet(admin, newPrivilegeConfig); - } - - /** - * @notice settles NOPs' LINK payment offchain - */ - function settleNOPsOffchain() external { - _onlyFinanceAdminAllowed(); - if (s_payoutMode == PayoutMode.ON_CHAIN) revert MustSettleOnchain(); - - uint96 totalPremium = s_hotVars.totalPremium; - uint256 activeTransmittersLength = s_transmittersList.length; - uint256 deactivatedTransmittersLength = s_deactivatedTransmitters.length(); - uint256 length = activeTransmittersLength + deactivatedTransmittersLength; - uint256[] memory payments = new uint256[](length); - address[] memory payees = new address[](length); - - for (uint256 i = 0; i < activeTransmittersLength; i++) { - address transmitterAddr = s_transmittersList[i]; - uint96 balance = _updateTransmitterBalanceFromPool( - transmitterAddr, - totalPremium, - uint96(activeTransmittersLength) - ); - - payments[i] = balance; - payees[i] = s_transmitterPayees[transmitterAddr]; - s_transmitters[transmitterAddr].balance = 0; - } - - for (uint256 i = 0; i < deactivatedTransmittersLength; i++) { - address deactivatedAddr = s_deactivatedTransmitters.at(i); - Transmitter memory transmitter = s_transmitters[deactivatedAddr]; - - payees[i + activeTransmittersLength] = s_transmitterPayees[deactivatedAddr]; - payments[i + activeTransmittersLength] = transmitter.balance; - s_transmitters[deactivatedAddr].balance = 0; - } - - // reserve amount of LINK is reset to 0 since no user deposits of LINK are expected in offchain mode - s_reserveAmounts[IERC20(address(i_link))] = 0; - - for (uint256 idx = s_deactivatedTransmitters.length(); idx > 0; idx--) { - s_deactivatedTransmitters.remove(s_deactivatedTransmitters.at(idx - 1)); - } - - emit NOPsSettledOffchain(payees, payments); - } - - /** - * @notice disables offchain payment for NOPs - */ - function disableOffchainPayments() external onlyOwner { - s_payoutMode = PayoutMode.ON_CHAIN; - } - - // ================================================================ - // | GETTERS | - // ================================================================ - - function getConditionalGasOverhead() external pure returns (uint256) { - return REGISTRY_CONDITIONAL_OVERHEAD; - } - - function getLogGasOverhead() external pure returns (uint256) { - return REGISTRY_LOG_OVERHEAD; - } - - function getPerSignerGasOverhead() external pure returns (uint256) { - return REGISTRY_PER_SIGNER_GAS_OVERHEAD; - } - - function getCancellationDelay() external pure returns (uint256) { - return CANCELLATION_DELAY; - } - - function getLinkAddress() external view returns (address) { - return address(i_link); - } - - function getLinkUSDFeedAddress() external view returns (address) { - return address(i_linkUSDFeed); - } - - function getNativeUSDFeedAddress() external view returns (address) { - return address(i_nativeUSDFeed); - } - - function getFastGasFeedAddress() external view returns (address) { - return address(i_fastGasFeed); - } - - function getAutomationForwarderLogic() external view returns (address) { - return i_automationForwarderLogic; - } - - function getAllowedReadOnlyAddress() external view returns (address) { - return i_allowedReadOnlyAddress; - } - - function getWrappedNativeTokenAddress() external view returns (address) { - return address(i_wrappedNativeToken); - } - - function getBillingToken(uint256 upkeepID) external view returns (IERC20) { - return s_upkeep[upkeepID].billingToken; - } - - function getBillingTokens() external view returns (IERC20[] memory) { - return s_billingTokens; - } - - function supportsBillingToken(IERC20 token) external view returns (bool) { - return address(s_billingConfigs[token].priceFeed) != address(0); - } - - function getBillingTokenConfig(IERC20 token) external view returns (BillingConfig memory) { - return s_billingConfigs[token]; - } - - function getBillingOverridesEnabled(uint256 upkeepID) external view returns (bool) { - return s_upkeep[upkeepID].overridesEnabled; - } - - function getPayoutMode() external view returns (PayoutMode) { - return s_payoutMode; - } - - function upkeepVersion() public pure returns (uint8) { - return UPKEEP_VERSION_BASE; - } - - /** - * @notice gets the number of upkeeps on the registry - */ - function getNumUpkeeps() external view returns (uint256) { - return s_upkeepIDs.length(); - } - - /** - * @notice read all of the details about an upkeep - * @dev this function may be deprecated in a future version of automation in favor of individual - * getters for each field - */ - function getUpkeep(uint256 id) external view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory upkeepInfo) { - Upkeep memory reg = s_upkeep[id]; - address target = address(reg.forwarder) == address(0) ? address(0) : reg.forwarder.getTarget(); - upkeepInfo = IAutomationV21PlusCommon.UpkeepInfoLegacy({ - target: target, - performGas: reg.performGas, - checkData: s_checkData[id], - balance: reg.balance, - admin: s_upkeepAdmin[id], - maxValidBlocknumber: reg.maxValidBlocknumber, - lastPerformedBlockNumber: reg.lastPerformedBlockNumber, - amountSpent: uint96(reg.amountSpent), // force casting to uint96 for backwards compatibility. Not an issue if it overflows. - paused: reg.paused, - offchainConfig: s_upkeepOffchainConfig[id] - }); - return upkeepInfo; - } - - /** - * @notice retrieve active upkeep IDs. Active upkeep is defined as an upkeep which is not paused and not canceled. - * @param startIndex starting index in list - * @param maxCount max count to retrieve (0 = unlimited) - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveUpkeepIDs(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory) { - uint256 numUpkeeps = s_upkeepIDs.length(); - if (startIndex >= numUpkeeps) revert IndexOutOfRange(); - uint256 endIndex = startIndex + maxCount; - endIndex = endIndex > numUpkeeps || maxCount == 0 ? numUpkeeps : endIndex; - uint256[] memory ids = new uint256[](endIndex - startIndex); - for (uint256 idx = 0; idx < ids.length; idx++) { - ids[idx] = s_upkeepIDs.at(idx + startIndex); - } - return ids; - } - - /** - * @notice returns the upkeep's trigger type - */ - function getTriggerType(uint256 upkeepId) external pure returns (Trigger) { - return _getTriggerType(upkeepId); - } - - /** - * @notice returns the trigger config for an upkeeep - */ - function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { - return s_upkeepTriggerConfig[upkeepId]; - } - - /** - * @notice read the current info about any transmitter address - */ - function getTransmitterInfo( - address query - ) external view returns (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) { - Transmitter memory transmitter = s_transmitters[query]; - - uint96 pooledShare = 0; - if (transmitter.active) { - uint96 totalDifference = s_hotVars.totalPremium - transmitter.lastCollected; - pooledShare = totalDifference / uint96(s_transmittersList.length); - } - - return ( - transmitter.active, - transmitter.index, - (transmitter.balance + pooledShare), - transmitter.lastCollected, - s_transmitterPayees[query] - ); - } - - /** - * @notice read the current info about any signer address - */ - function getSignerInfo(address query) external view returns (bool active, uint8 index) { - Signer memory signer = s_signers[query]; - return (signer.active, signer.index); - } - - /** - * @notice read the current on-chain config of the registry - * @dev this function will change between versions, it should never be used where - * backwards compatibility matters! - */ - function getConfig() external view returns (OnchainConfig memory) { - return - OnchainConfig({ - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - fallbackNativePrice: s_fallbackNativePrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager, - chainModule: s_hotVars.chainModule, - reorgProtectionEnabled: s_hotVars.reorgProtectionEnabled, - financeAdmin: s_storage.financeAdmin - }); - } - - /** - * @notice read the current state of the registry - * @dev this function is deprecated - */ - function getState() - external - view - returns ( - IAutomationV21PlusCommon.StateLegacy memory state, - IAutomationV21PlusCommon.OnchainConfigLegacy memory config, - address[] memory signers, - address[] memory transmitters, - uint8 f - ) - { - state = IAutomationV21PlusCommon.StateLegacy({ - nonce: s_storage.nonce, - ownerLinkBalance: 0, // deprecated - expectedLinkBalance: 0, // deprecated - totalPremium: s_hotVars.totalPremium, - numUpkeeps: s_upkeepIDs.length(), - configCount: s_storage.configCount, - latestConfigBlockNumber: s_storage.latestConfigBlockNumber, - latestConfigDigest: s_latestConfigDigest, - latestEpoch: s_hotVars.latestEpoch, - paused: s_hotVars.paused - }); - - config = IAutomationV21PlusCommon.OnchainConfigLegacy({ - paymentPremiumPPB: 0, // deprecated - flatFeeMicroLink: 0, // deprecated - checkGasLimit: s_storage.checkGasLimit, - stalenessSeconds: s_hotVars.stalenessSeconds, - gasCeilingMultiplier: s_hotVars.gasCeilingMultiplier, - minUpkeepSpend: 0, // deprecated - maxPerformGas: s_storage.maxPerformGas, - maxCheckDataSize: s_storage.maxCheckDataSize, - maxPerformDataSize: s_storage.maxPerformDataSize, - maxRevertDataSize: s_storage.maxRevertDataSize, - fallbackGasPrice: s_fallbackGasPrice, - fallbackLinkPrice: s_fallbackLinkPrice, - transcoder: s_storage.transcoder, - registrars: s_registrars.values(), - upkeepPrivilegeManager: s_storage.upkeepPrivilegeManager - }); - - return (state, config, s_signersList, s_transmittersList, s_hotVars.f); - } - - /** - * @notice read the Storage data - * @dev this function signature will change with each version of automation - * this should not be treated as a stable function - */ - function getStorage() external view returns (Storage memory) { - return s_storage; - } - - /** - * @notice read the HotVars data - * @dev this function signature will change with each version of automation - * this should not be treated as a stable function - */ - function getHotVars() external view returns (HotVars memory) { - return s_hotVars; - } - - /** - * @notice get the chain module - */ - function getChainModule() external view returns (IChainModule chainModule) { - return s_hotVars.chainModule; - } - - /** - * @notice if this registry has reorg protection enabled - */ - function getReorgProtectionEnabled() external view returns (bool reorgProtectionEnabled) { - return s_hotVars.reorgProtectionEnabled; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getBalance(uint256 id) external view returns (uint96 balance) { - return s_upkeep[id].balance; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - */ - function getMinBalance(uint256 id) external view returns (uint96) { - return getMinBalanceForUpkeep(id); - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - * @param id the upkeep id to calculate minimum balance for - * @dev this will be deprecated in a future version in favor of getMinBalance - */ - function getMinBalanceForUpkeep(uint256 id) public view returns (uint96 minBalance) { - Upkeep memory upkeep = s_upkeep[id]; - return getMaxPaymentForGas(id, _getTriggerType(id), upkeep.performGas, upkeep.billingToken); - } - - /** - * @notice calculates the maximum payment for a given gas limit - * @param gasLimit the gas to calculate payment for - */ - function getMaxPaymentForGas( - uint256 id, - Trigger triggerType, - uint32 gasLimit, - IERC20 billingToken - ) public view returns (uint96 maxPayment) { - HotVars memory hotVars = s_hotVars; - (uint256 fastGasWei, uint256 linkUSD, uint256 nativeUSD) = _getFeedData(hotVars); - return _getMaxPayment(id, hotVars, triggerType, gasLimit, fastGasWei, linkUSD, nativeUSD, billingToken); - } - - /** - * @notice retrieves the migration permission for a peer registry - */ - function getPeerRegistryMigrationPermission(address peer) external view returns (MigrationPermission) { - return s_peerRegistryMigrationPermission[peer]; - } - - /** - * @notice returns the upkeep privilege config - */ - function getUpkeepPrivilegeConfig(uint256 upkeepId) external view returns (bytes memory) { - return s_upkeepPrivilegeConfig[upkeepId]; - } - - /** - * @notice returns the admin's privilege config - */ - function getAdminPrivilegeConfig(address admin) external view returns (bytes memory) { - return s_adminPrivilegeConfig[admin]; - } - - /** - * @notice returns the upkeep's forwarder contract - */ - function getForwarder(uint256 upkeepID) external view returns (IAutomationForwarder) { - return s_upkeep[upkeepID].forwarder; - } - - /** - * @notice returns if the dedupKey exists or not - */ - function hasDedupKey(bytes32 dedupKey) external view returns (bool) { - return s_dedupKeys[dedupKey]; - } - - /** - * @notice returns the fallback native price - */ - function getFallbackNativePrice() external view returns (uint256) { - return s_fallbackNativePrice; - } - - /** - * @notice returns the amount of a particular token that is reserved as - * user deposits / NOP payments - */ - function getReserveAmount(IERC20 billingToken) external view returns (uint256) { - return s_reserveAmounts[billingToken]; - } - - /** - * @notice returns the amount of a particular token that is withdraw-able by finance admin - */ - function getAvailableERC20ForPayment(IERC20 billingToken) external view returns (uint256) { - return billingToken.balanceOf(address(this)) - s_reserveAmounts[IERC20(address(billingToken))]; - } - - /** - * @notice returns the size of the LINK liquidity pool - */ - function linkAvailableForPayment() public view returns (int256) { - return _linkAvailableForPayment(); - } - - /** - * @notice returns the BillingOverrides config for a given upkeep - */ - function getBillingOverrides(uint256 upkeepID) external view returns (BillingOverrides memory) { - return s_billingOverrides[upkeepID]; - } - - /** - * @notice returns the BillingConfig for a given billing token, this includes decimals and price feed etc - */ - function getBillingConfig(IERC20 billingToken) external view returns (BillingConfig memory) { - return s_billingConfigs[billingToken]; - } - - /** - * @notice returns all active transmitters with their associated payees - */ - function getTransmittersWithPayees() external view returns (TransmitterPayeeInfo[] memory) { - uint256 transmitterCount = s_transmittersList.length; - TransmitterPayeeInfo[] memory transmitters = new TransmitterPayeeInfo[](transmitterCount); - - for (uint256 i = 0; i < transmitterCount; i++) { - address transmitterAddress = s_transmittersList[i]; - address payeeAddress = s_transmitterPayees[transmitterAddress]; - - transmitters[i] = TransmitterPayeeInfo(transmitterAddress, payeeAddress); - } - - return transmitters; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol deleted file mode 100644 index 8ae10d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/FeeQuoter.sol +++ /dev/null @@ -1,1020 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; - -import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; -import {AggregatorV3Interface} from "./../shared/interfaces/AggregatorV3Interface.sol"; -import {Client} from "./libraries/Client.sol"; -import {Internal} from "./libraries/Internal.sol"; -import {Pool} from "./libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; - -import {KeystoneFeedsPermissionHandler} from "../keystone/KeystoneFeedsPermissionHandler.sol"; -import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; -import {KeystoneFeedDefaultMetadataLib} from "../keystone/lib/KeystoneFeedDefaultMetadataLib.sol"; -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice The FeeQuoter contract responsibility is to: -/// - Store the current gas price in USD for a given destination chain, -/// - Store the price of a token in USD allowing the owner or priceUpdater to update this value. -/// - Manage chain specific fee calculations. -/// The authorized callers in the contract represent the fee price updaters. -contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, KeystoneFeedsPermissionHandler { - using EnumerableSet for EnumerableSet.AddressSet; - using USDPriceWith18Decimals for uint224; - using KeystoneFeedDefaultMetadataLib for bytes; - - error TokenNotSupported(address token); - error FeeTokenNotSupported(address token); - error ChainNotSupported(uint64 chain); - error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed); - error StaleKeystoneUpdate(address token, uint256 feedTimestamp, uint256 storedTimeStamp); - error DataFeedValueOutOfUint224Range(); - error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); - error MessageGasLimitTooHigh(); - error DestinationChainNotEnabled(uint64 destChainSelector); - error ExtraArgOutOfOrderExecutionMustBeTrue(); - error InvalidExtraArgsTag(); - error SourceTokenDataTooLarge(address token); - error InvalidDestChainConfig(uint64 destChainSelector); - error MessageFeeTooHigh(uint256 msgFeeJuels, uint256 maxFeeJuelsPerMsg); - error InvalidStaticConfig(); - error MessageTooLarge(uint256 maxSize, uint256 actualSize); - error UnsupportedNumberOfTokens(); - - event FeeTokenAdded(address indexed feeToken); - event FeeTokenRemoved(address indexed feeToken); - event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp); - event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); - event PriceFeedPerTokenUpdated(address indexed token, TokenPriceFeedConfig priceFeedConfig); - event TokenTransferFeeConfigUpdated( - uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig - ); - event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); - event PremiumMultiplierWeiPerEthUpdated(address indexed token, uint64 premiumMultiplierWeiPerEth); - event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); - event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); - - /// @dev Token price data feed configuration - struct TokenPriceFeedConfig { - address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) - uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents - } - - /// @dev Token price data feed update - struct TokenPriceFeedUpdate { - address sourceToken; // Source token to update feed for - TokenPriceFeedConfig feedConfig; // Feed config update data - } - - /// @dev Struct that contains the static configuration - /// RMN depends on this struct, if changing, please notify the RMN maintainers. - // solhint-disable-next-line gas-struct-packing - struct StaticConfig { - uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message - address linkToken; // ────────╯ LINK token address - uint32 stalenessThreshold; // The amount of time a gas price can be stale before it is considered invalid. - } - - /// @dev The struct representing the received CCIP feed report from keystone IReceiver.onReport() - struct ReceivedCCIPFeedReport { - address token; // Token address - uint224 price; // ─────────╮ Price of the token in USD with 18 decimals - uint32 timestamp; // ──────╯ Timestamp of the price update - } - - /// @dev Struct to hold the fee & validation configs for a destination chain - struct DestChainConfig { - bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs - uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs - uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver - uint32 destDataAvailabilityOverheadGas; // │ Extra data availability gas charged on top of the message, e.g. for OCR - uint16 destGasPerDataAvailabilityByte; // │ Amount of gas to charge per byte of message data that needs availability - uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 - // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token - uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer - uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute the token transfer on the destination chain - uint32 defaultTxGasLimit; //─────────────────╮ Default gas limit for a tx - uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. - uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD - bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. - bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. - } - - /// @dev Struct to hold the configs and its destination chain selector - /// Same as DestChainConfig but with the destChainSelector so that an array of these - /// can be passed in the constructor and the applyDestChainConfigUpdates function - //solhint-disable gas-struct-packing - struct DestChainConfigArgs { - uint64 destChainSelector; // Destination chain selector - DestChainConfig destChainConfig; // Config to update for the chain selector - } - - /// @dev Struct to hold the transfer fee configuration for token transfers - struct TokenTransferFeeConfig { - uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD - uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 - uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain - // │ Extra data availability bytes that are returned from the source pool and sent - uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees - } - - /// @dev Struct to hold the token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token address included so - /// that an array of these can be passed in the TokenTransferFeeConfigArgs struct to set the mapping - struct TokenTransferFeeConfigSingleTokenArgs { - address token; // Token address - TokenTransferFeeConfig tokenTransferFeeConfig; // Struct to hold the transfer fee configuration for token transfers - } - - /// @dev Struct to hold the token transfer fee configurations for a destination chain and a set of tokens. Same as TokenTransferFeeConfigSingleTokenArgs - /// but with the destChainSelector and an array of TokenTransferFeeConfigSingleTokenArgs included so that an array of these can be passed in the constructor - /// and the applyTokenTransferFeeConfigUpdates function - struct TokenTransferFeeConfigArgs { - uint64 destChainSelector; // Destination chain selector - TokenTransferFeeConfigSingleTokenArgs[] tokenTransferFeeConfigs; // Array of token transfer fee configurations - } - - /// @dev Struct to hold a pair of destination chain selector and token address so that an array of these can be passed in the - /// applyTokenTransferFeeConfigUpdates function to remove the token transfer fee configuration for a token - struct TokenTransferFeeConfigRemoveArgs { - uint64 destChainSelector; // ─╮ Destination chain selector - address token; // ────────────╯ Token address - } - - /// @dev Struct to hold the fee token configuration for a token, same as the s_premiumMultiplierWeiPerEth but with - /// the token address included so that an array of these can be passed in the constructor and - /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping - struct PremiumMultiplierWeiPerEthArgs { - address token; // // ───────────────────╮ Token address - uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. - } - - /// @dev The base decimals for cost calculations - uint256 public constant FEE_BASE_DECIMALS = 36; - /// @dev The decimals that Keystone reports prices in - uint256 public constant KEYSTONE_PRICE_DECIMALS = 18; - - string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; - - /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. - /// Multiple gas prices can be encoded into the same value. Each price takes {Internal.GAS_PRICE_BITS} bits. - /// For example, if Optimism is the destination chain, gas price can include L1 base fee and L2 gas price. - /// Logic to parse the price components is chain-specific, and should live in OnRamp. - /// @dev Price of 1e18 is 1 USD. Examples: - /// Very Expensive: 1 unit of gas costs 1 USD -> 1e18 - /// Expensive: 1 unit of gas costs 0.1 USD -> 1e17 - /// Cheap: 1 unit of gas costs 0.000001 USD -> 1e12 - mapping(uint64 destChainSelector => Internal.TimestampedPackedUint224 price) private - s_usdPerUnitGasByDestChainSelector; - - /// @dev The price, in USD with 18 decimals, per 1e18 of the smallest token denomination. - /// @dev Price of 1e18 represents 1 USD per 1e18 token amount. - /// 1 USDC = 1.00 USD per full token, each full token is 1e6 units -> 1 * 1e18 * 1e18 / 1e6 = 1e30 - /// 1 ETH = 2,000 USD per full token, each full token is 1e18 units -> 2000 * 1e18 * 1e18 / 1e18 = 2_000e18 - /// 1 LINK = 5.00 USD per full token, each full token is 1e18 units -> 5 * 1e18 * 1e18 / 1e18 = 5e18 - mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken; - - /// @dev Stores the price data feed configurations per token. - mapping(address token => TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; - - /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin - mapping(address token => uint64 premiumMultiplierWeiPerEth) private s_premiumMultiplierWeiPerEth; - - /// @dev The destination chain specific fee configs - mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; - - /// @dev The token transfer fee config that can be set by the owner or fee admin - mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) private - s_tokenTransferFeeConfig; - - /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. - uint96 internal immutable i_maxFeeJuelsPerMsg; - /// @dev The link token address - address internal immutable i_linkToken; - - /// @dev Subset of tokens which prices tracked by this registry which are fee tokens. - EnumerableSet.AddressSet private s_feeTokens; - /// @dev The amount of time a gas price can be stale before it is considered invalid. - uint32 private immutable i_stalenessThreshold; - - constructor( - StaticConfig memory staticConfig, - address[] memory priceUpdaters, - address[] memory feeTokens, - TokenPriceFeedUpdate[] memory tokenPriceFeeds, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, - DestChainConfigArgs[] memory destChainConfigArgs - ) AuthorizedCallers(priceUpdaters) { - if ( - staticConfig.linkToken == address(0) || staticConfig.maxFeeJuelsPerMsg == 0 - || staticConfig.stalenessThreshold == 0 - ) { - revert InvalidStaticConfig(); - } - - i_linkToken = staticConfig.linkToken; - i_maxFeeJuelsPerMsg = staticConfig.maxFeeJuelsPerMsg; - i_stalenessThreshold = staticConfig.stalenessThreshold; - - _applyFeeTokensUpdates(feeTokens, new address[](0)); - _updateTokenPriceFeeds(tokenPriceFeeds); - _applyDestChainConfigUpdates(destChainConfigArgs); - _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, new TokenTransferFeeConfigRemoveArgs[](0)); - } - - // ================================================================ - // │ Price calculations │ - // ================================================================ - - /// @inheritdoc IPriceRegistry - function getTokenPrice( - address token - ) public view override returns (Internal.TimestampedPackedUint224 memory) { - Internal.TimestampedPackedUint224 memory tokenPrice = s_usdPerToken[token]; - - // If the token price is not stale, return it - if (block.timestamp - tokenPrice.timestamp < i_stalenessThreshold) { - return tokenPrice; - } - - TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; - - // If the token price feed is not set, return the stale price - if (priceFeedConfig.dataFeedAddress == address(0)) { - return tokenPrice; - } - - // If the token price feed is set, return the price from the feed - // The price feed is the fallback because we do not expect it to be the default source due to the gas cost of reading from it - return _getTokenPriceFromDataFeed(priceFeedConfig); - } - - /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. - /// @param token The token to get the price for. - /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. - function getValidatedTokenPrice( - address token - ) external view returns (uint224) { - return _getValidatedTokenPrice(token); - } - - /// @notice Get the `tokenPrice` for an array of tokens. - /// @param tokens The tokens to get prices for. - /// @return tokenPrices The tokenPrices for the given tokens. - function getTokenPrices( - address[] calldata tokens - ) external view returns (Internal.TimestampedPackedUint224[] memory) { - uint256 length = tokens.length; - Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length); - for (uint256 i = 0; i < length; ++i) { - tokenPrices[i] = getTokenPrice(tokens[i]); - } - return tokenPrices; - } - - /// @notice Returns the token price data feed configuration - /// @param token The token to retrieve the feed config for - /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) - function getTokenPriceFeedConfig( - address token - ) external view returns (TokenPriceFeedConfig memory) { - return s_usdPriceFeedsPerToken[token]; - } - - /// @notice Get an encoded `gasPrice` for a given destination chain ID. - /// The 224-bit result encodes necessary gas price components. - /// On L1 chains like Ethereum or Avax, the only component is the gas price. - /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. - /// On future chains, there could be more or differing price components. - /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. - /// @param destChainSelector The destination chain to get the price for. - /// @return gasPrice The encoded gasPrice for the given destination chain ID. - function getDestinationChainGasPrice( - uint64 destChainSelector - ) external view returns (Internal.TimestampedPackedUint224 memory) { - return s_usdPerUnitGasByDestChainSelector[destChainSelector]; - } - - /// @notice Gets the fee token price and the gas price, both denominated in dollars. - /// @param token The source token to get the price for. - /// @param destChainSelector The destination chain to get the gas price for. - /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. - /// @return gasPriceValue The price of gas in 1e18 dollars per base unit. - function getTokenAndGasPrices( - address token, - uint64 destChainSelector - ) public view returns (uint224 tokenPrice, uint224 gasPriceValue) { - Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; - // We do allow a gas price of 0, but no stale or unset gas prices - if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector); - uint256 timePassed = block.timestamp - gasPrice.timestamp; - if (timePassed > i_stalenessThreshold) revert StaleGasPrice(destChainSelector, i_stalenessThreshold, timePassed); - - return (_getValidatedTokenPrice(token), gasPrice.value); - } - - /// @notice Convert a given token amount to target token amount. - /// @dev this function assumes that no more than 1e59 dollars are sent as payment. - /// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow. - /// Since there isn't even close to 1e59 dollars in the world economy this is safe. - /// @param fromToken The given token address. - /// @param fromTokenAmount The given token amount. - /// @param toToken The target token address. - /// @return toTokenAmount The target token amount. - function convertTokenAmount( - address fromToken, - uint256 fromTokenAmount, - address toToken - ) public view returns (uint256) { - /// Example: - /// fromTokenAmount: 1e18 // 1 ETH - /// ETH: 2_000e18 - /// LINK: 5e18 - /// return: 1e18 * 2_000e18 / 5e18 = 400e18 (400 LINK) - return (fromTokenAmount * _getValidatedTokenPrice(fromToken)) / _getValidatedTokenPrice(toToken); - } - - /// @notice Gets the token price for a given token and reverts if the token is not supported - /// @param token The address of the token to get the price for - /// @return tokenPriceValue The token price - function _getValidatedTokenPrice( - address token - ) internal view returns (uint224) { - Internal.TimestampedPackedUint224 memory tokenPrice = getTokenPrice(token); - // Token price must be set at least once - if (tokenPrice.timestamp == 0 || tokenPrice.value == 0) revert TokenNotSupported(token); - return tokenPrice.value; - } - - /// @notice Gets the token price from a data feed address, rebased to the same units as s_usdPerToken - /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) - /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp - function _getTokenPriceFromDataFeed( - TokenPriceFeedConfig memory priceFeedConfig - ) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) { - AggregatorV3Interface dataFeedContract = AggregatorV3Interface(priceFeedConfig.dataFeedAddress); - ( - /* uint80 roundID */ - , - int256 dataFeedAnswer, - /* uint startedAt */ - , - /* uint256 updatedAt */ - , - /* uint80 answeredInRound */ - ) = dataFeedContract.latestRoundData(); - - if (dataFeedAnswer < 0) { - revert DataFeedValueOutOfUint224Range(); - } - uint224 rebasedValue = - _calculateRebasedValue(dataFeedContract.decimals(), priceFeedConfig.tokenDecimals, uint256(dataFeedAnswer)); - - // Data feed staleness is unchecked to decouple the FeeQuoter from data feed delay issues - return Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: uint32(block.timestamp)}); - } - - // ================================================================ - // │ Fee tokens │ - // ================================================================ - - /// @inheritdoc IPriceRegistry - function getFeeTokens() external view returns (address[] memory) { - return s_feeTokens.values(); - } - - /// @notice Add and remove tokens from feeTokens set. - /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. - /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens - /// and can be used to calculate fees. - function applyFeeTokensUpdates( - address[] memory feeTokensToAdd, - address[] memory feeTokensToRemove - ) external onlyOwner { - _applyFeeTokensUpdates(feeTokensToAdd, feeTokensToRemove); - } - - /// @notice Add and remove tokens from feeTokens set. - /// @param feeTokensToRemove The addresses of the tokens which are no longer considered feeTokens. - /// @param feeTokensToAdd The addresses of the tokens which are now considered fee tokens - /// and can be used to calculate fees. - function _applyFeeTokensUpdates(address[] memory feeTokensToAdd, address[] memory feeTokensToRemove) private { - for (uint256 i = 0; i < feeTokensToAdd.length; ++i) { - if (s_feeTokens.add(feeTokensToAdd[i])) { - emit FeeTokenAdded(feeTokensToAdd[i]); - } - } - for (uint256 i = 0; i < feeTokensToRemove.length; ++i) { - if (s_feeTokens.remove(feeTokensToRemove[i])) { - emit FeeTokenRemoved(feeTokensToRemove[i]); - } - } - } - - // ================================================================ - // │ Price updates │ - // ================================================================ - - /// @inheritdoc IPriceRegistry - function updatePrices( - Internal.PriceUpdates calldata priceUpdates - ) external override { - // The caller must be the fee updater - _validateCaller(); - - uint256 tokenUpdatesLength = priceUpdates.tokenPriceUpdates.length; - - for (uint256 i = 0; i < tokenUpdatesLength; ++i) { - Internal.TokenPriceUpdate memory update = priceUpdates.tokenPriceUpdates[i]; - s_usdPerToken[update.sourceToken] = - Internal.TimestampedPackedUint224({value: update.usdPerToken, timestamp: uint32(block.timestamp)}); - emit UsdPerTokenUpdated(update.sourceToken, update.usdPerToken, block.timestamp); - } - - uint256 gasUpdatesLength = priceUpdates.gasPriceUpdates.length; - - for (uint256 i = 0; i < gasUpdatesLength; ++i) { - Internal.GasPriceUpdate memory update = priceUpdates.gasPriceUpdates[i]; - s_usdPerUnitGasByDestChainSelector[update.destChainSelector] = - Internal.TimestampedPackedUint224({value: update.usdPerUnitGas, timestamp: uint32(block.timestamp)}); - emit UsdPerUnitGasUpdated(update.destChainSelector, update.usdPerUnitGas, block.timestamp); - } - } - - /// @notice Updates the USD token price feeds for given tokens - /// @param tokenPriceFeedUpdates Token price feed updates to apply - function updateTokenPriceFeeds( - TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates - ) external onlyOwner { - _updateTokenPriceFeeds(tokenPriceFeedUpdates); - } - - /// @notice Updates the USD token price feeds for given tokens - /// @param tokenPriceFeedUpdates Token price feed updates to apply - function _updateTokenPriceFeeds( - TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates - ) private { - for (uint256 i; i < tokenPriceFeedUpdates.length; ++i) { - TokenPriceFeedUpdate memory update = tokenPriceFeedUpdates[i]; - address sourceToken = update.sourceToken; - TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; - - s_usdPriceFeedsPerToken[sourceToken] = tokenPriceFeedConfig; - emit PriceFeedPerTokenUpdated(sourceToken, tokenPriceFeedConfig); - } - } - - /// @notice Handles the report containing price feeds and updates the internal price storage - /// @inheritdoc IReceiver - /// @dev This function is called to process incoming price feed data. - /// @param metadata Arbitrary metadata associated with the report (not used in this implementation). - /// @param report Encoded report containing an array of `ReceivedCCIPFeedReport` structs. - function onReport(bytes calldata metadata, bytes calldata report) external { - (bytes10 workflowName, address workflowOwner, bytes2 reportName) = metadata._extractMetadataInfo(); - - _validateReportPermission(msg.sender, workflowOwner, workflowName, reportName); - - ReceivedCCIPFeedReport[] memory feeds = abi.decode(report, (ReceivedCCIPFeedReport[])); - - for (uint256 i = 0; i < feeds.length; ++i) { - uint8 tokenDecimals = s_usdPriceFeedsPerToken[feeds[i].token].tokenDecimals; - if (tokenDecimals == 0) { - revert TokenNotSupported(feeds[i].token); - } - // Keystone reports prices in USD with 18 decimals, so we passing it as 18 in the _calculateRebasedValue function - uint224 rebasedValue = _calculateRebasedValue(18, tokenDecimals, feeds[i].price); - - //if stale update then revert - if (feeds[i].timestamp < s_usdPerToken[feeds[i].token].timestamp) { - revert StaleKeystoneUpdate(feeds[i].token, feeds[i].timestamp, s_usdPerToken[feeds[i].token].timestamp); - } - - s_usdPerToken[feeds[i].token] = - Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: feeds[i].timestamp}); - emit UsdPerTokenUpdated(feeds[i].token, rebasedValue, feeds[i].timestamp); - } - } - - // ================================================================ - // │ Fee quoting │ - // ================================================================ - - /// @inheritdoc IFeeQuoter - /// @dev The function should always validate message.extraArgs, message.receiver and family-specific configs - function getValidatedFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount) { - DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; - if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); - if (!s_feeTokens.contains(message.feeToken)) revert FeeTokenNotSupported(message.feeToken); - - uint256 numberOfTokens = message.tokenAmounts.length; - _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); - - // The below call asserts that feeToken is a supported token - (uint224 feeTokenPrice, uint224 packedGasPrice) = getTokenAndGasPrices(message.feeToken, destChainSelector); - - // Calculate premiumFee in USD with 18 decimals precision first. - // If message-only and no token transfers, a flat network fee is charged. - // If there are token transfers, premiumFee is calculated from token transfer fee. - // If there are both token transfers and message, premiumFee is only calculated from token transfer fee. - uint256 premiumFee = 0; - uint32 tokenTransferGas = 0; - uint32 tokenTransferBytesOverhead = 0; - if (numberOfTokens > 0) { - (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = - _getTokenTransferCost(destChainConfig, destChainSelector, message.feeToken, feeTokenPrice, message.tokenAmounts); - } else { - // Convert USD cents with 2 decimals to 18 decimals. - premiumFee = uint256(destChainConfig.networkFeeUSDCents) * 1e16; - } - - // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to post - // transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs. - uint256 dataAvailabilityCost = 0; - - // Only calculate data availability cost if data availability multiplier is non-zero. - // The multiplier should be set to 0 if destination chain does not charge data availability cost. - if (destChainConfig.destDataAvailabilityMultiplierBps > 0) { - dataAvailabilityCost = _getDataAvailabilityCost( - destChainConfig, - // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. - uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), - message.data.length, - numberOfTokens, - tokenTransferBytesOverhead - ); - } - - // Calculate execution gas fee on destination chain in USD with 36 decimals. - // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together. - // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals. - // uint112(packedGasPrice) = executionGasPrice - - // NOTE: when supporting non-EVM chains, revisit how generic this fee logic can be - // NOTE: revisit parsing non-EVM args - uint256 executionCost = uint112(packedGasPrice) - * ( - destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas - + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit - ) * destChainConfig.gasMultiplierWeiPerEth; - - // Calculate number of fee tokens to charge. - // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. - // Result of the division is the number of smallest token denominations. - return ((premiumFee * s_premiumMultiplierWeiPerEth[message.feeToken]) + executionCost + dataAvailabilityCost) - / feeTokenPrice; - } - - /// @notice Sets the fee configuration for a token. - /// @param premiumMultiplierWeiPerEthArgs Array of PremiumMultiplierWeiPerEthArgs structs. - function applyPremiumMultiplierWeiPerEthUpdates( - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs - ) external onlyOwner { - _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - } - - /// @dev Sets the fee config. - /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. - function _applyPremiumMultiplierWeiPerEthUpdates( - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs - ) internal { - for (uint256 i = 0; i < premiumMultiplierWeiPerEthArgs.length; ++i) { - address token = premiumMultiplierWeiPerEthArgs[i].token; - uint64 premiumMultiplierWeiPerEth = premiumMultiplierWeiPerEthArgs[i].premiumMultiplierWeiPerEth; - s_premiumMultiplierWeiPerEth[token] = premiumMultiplierWeiPerEth; - - emit PremiumMultiplierWeiPerEthUpdated(token, premiumMultiplierWeiPerEth); - } - } - - /// @notice Gets the fee configuration for a token. - /// @param token The token to get the fee configuration for. - /// @return premiumMultiplierWeiPerEth The multiplier for destination chain specific premiums. - function getPremiumMultiplierWeiPerEth( - address token - ) external view returns (uint64 premiumMultiplierWeiPerEth) { - return s_premiumMultiplierWeiPerEth[token]; - } - - /// @notice Returns the token transfer cost parameters. - /// A basis point fee is calculated from the USD value of each token transfer. - /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD]. - /// Total transfer fee is the sum of each individual token transfer fee. - /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere. - /// @dev Splitting one token transfer into multiple transfers is discouraged, - /// as it will result in a transferFee equal or greater than the same amount aggregated/de-duped. - /// @param destChainConfig the config configured for the destination chain selector. - /// @param destChainSelector the destination chain selector. - /// @param feeToken address of the feeToken. - /// @param feeTokenPrice price of feeToken in USD with 18 decimals. - /// @param tokenAmounts token transfers in the message. - /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals. - /// @return tokenTransferGas total execution gas of the token transfers. - /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - function _getTokenTransferCost( - DestChainConfig memory destChainConfig, - uint64 destChainSelector, - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) { - uint256 numberOfTokens = tokenAmounts.length; - - for (uint256 i = 0; i < numberOfTokens; ++i) { - Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i]; - TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][tokenAmount.token]; - - // If the token has no specific overrides configured, we use the global defaults. - if (!transferFeeConfig.isEnabled) { - tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; - tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; - tokenTransferBytesOverhead += Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES; - continue; - } - - uint256 bpsFeeUSDWei = 0; - // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. - // Useful for when the FeeQuoter cannot return a valid price for the token. - if (transferFeeConfig.deciBps > 0) { - uint224 tokenPrice = 0; - if (tokenAmount.token != feeToken) { - tokenPrice = _getValidatedTokenPrice(tokenAmount.token); - } else { - tokenPrice = feeTokenPrice; - } - - // Calculate token transfer value, then apply fee ratio - // ratio represents multiples of 0.1bps, or 1e-5 - bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5; - } - - tokenTransferGas += transferFeeConfig.destGasOverhead; - tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead; - - // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD]. - // Convert USD values with 2 decimals to 18 decimals. - uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16; - if (bpsFeeUSDWei < minFeeUSDWei) { - tokenTransferFeeUSDWei += minFeeUSDWei; - continue; - } - - uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16; - if (bpsFeeUSDWei > maxFeeUSDWei) { - tokenTransferFeeUSDWei += maxFeeUSDWei; - continue; - } - - tokenTransferFeeUSDWei += bpsFeeUSDWei; - } - - return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); - } - - /// @notice calculates the rebased value for 1e18 smallest token denomination - /// @param dataFeedDecimal decimal of the data feed - /// @param tokenDecimal decimal of the token - /// @param feedValue value of the data feed - /// @return rebasedValue rebased value - function _calculateRebasedValue( - uint8 dataFeedDecimal, - uint8 tokenDecimal, - uint256 feedValue - ) internal pure returns (uint224 rebasedValue) { - // Rebase formula for units in smallest token denomination: usdValue * (1e18 * 1e18) / 1eTokenDecimals - // feedValue * (10 ** (18 - feedDecimals)) * (10 ** (18 - erc20Decimals)) - // feedValue * (10 ** ((18 - feedDecimals) + (18 - erc20Decimals))) - // feedValue * (10 ** (36 - feedDecimals - erc20Decimals)) - // feedValue * (10 ** (36 - (feedDecimals + erc20Decimals))) - // feedValue * (10 ** (36 - excessDecimals)) - // If excessDecimals > 36 => flip it to feedValue / (10 ** (excessDecimals - 36)) - uint8 excessDecimals = dataFeedDecimal + tokenDecimal; - uint256 rebasedVal; - - if (excessDecimals > FEE_BASE_DECIMALS) { - rebasedVal = feedValue / (10 ** (excessDecimals - FEE_BASE_DECIMALS)); - } else { - rebasedVal = feedValue * (10 ** (FEE_BASE_DECIMALS - excessDecimals)); - } - - if (rebasedVal > type(uint224).max) { - revert DataFeedValueOutOfUint224Range(); - } - - return uint224(rebasedVal); - } - - /// @notice Returns the estimated data availability cost of the message. - /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. - /// @param destChainConfig the config configured for the destination chain selector. - /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals. - /// @param messageDataLength length of the data field in the message. - /// @param numberOfTokens number of distinct token transfers in the message. - /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals. - function _getDataAvailabilityCost( - DestChainConfig memory destChainConfig, - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) internal pure returns (uint256 dataAvailabilityCostUSD36Decimal) { - // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. - // Fixed message fields do account for the offset and length slot of the dynamic fields. - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. - // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. - uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * destChainConfig.destGasPerDataAvailabilityByte) - + destChainConfig.destDataAvailabilityOverheadGas; - - // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals - // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee. - return ((dataAvailabilityGas * dataAvailabilityGasPrice) * destChainConfig.destDataAvailabilityMultiplierBps) * 1e14; - } - - /// @notice Gets the transfer fee config for a given token. - /// @param destChainSelector The destination chain selector. - /// @param token The token address. - /// @return tokenTransferFeeConfig The transfer fee config for the token. - function getTokenTransferFeeConfig( - uint64 destChainSelector, - address token - ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) { - return s_tokenTransferFeeConfig[destChainSelector][token]; - } - - /// @notice Sets the transfer fee config. - /// @dev only callable by the owner or admin. - function applyTokenTransferFeeConfigUpdates( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs - ) external onlyOwner { - _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs); - } - - /// @notice internal helper to set the token transfer fee config. - function _applyTokenTransferFeeConfigUpdates( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs - ) internal { - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = tokenTransferFeeConfigArgs[i]; - uint64 destChainSelector = tokenTransferFeeConfigArg.destChainSelector; - - for (uint256 j = 0; j < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++j) { - TokenTransferFeeConfig memory tokenTransferFeeConfig = - tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].tokenTransferFeeConfig; - address token = tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].token; - - if (tokenTransferFeeConfig.destBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - revert InvalidDestBytesOverhead(token, tokenTransferFeeConfig.destBytesOverhead); - } - - s_tokenTransferFeeConfig[destChainSelector][token] = tokenTransferFeeConfig; - - emit TokenTransferFeeConfigUpdated(destChainSelector, token, tokenTransferFeeConfig); - } - } - - // Remove the custom fee configs for the tokens that are in the tokensToUseDefaultFeeConfigs array - for (uint256 i = 0; i < tokensToUseDefaultFeeConfigs.length; ++i) { - uint64 destChainSelector = tokensToUseDefaultFeeConfigs[i].destChainSelector; - address token = tokensToUseDefaultFeeConfigs[i].token; - delete s_tokenTransferFeeConfig[destChainSelector][token]; - emit TokenTransferFeeConfigDeleted(destChainSelector, token); - } - } - - // ================================================================ - // │ Validations & message processing │ - // ================================================================ - - /// @notice Validates that the destAddress matches the expected format of the family. - /// @param chainFamilySelector Tag to identify the target family. - /// @param destAddress Dest address to validate. - /// @dev precondition - assumes the family tag is correct and validated. - function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { - if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { - Internal._validateEVMAddress(destAddress); - } - } - - /// @dev Convert the extra args bytes into a struct with validations against the dest chain config. - /// @param extraArgs The extra args bytes. - /// @param destChainConfig Dest chain config to validate against. - /// @return evmExtraArgs The EVMExtraArgs struct (latest version). - function _parseEVMExtraArgsFromBytes( - bytes calldata extraArgs, - DestChainConfig memory destChainConfig - ) internal pure returns (Client.EVMExtraArgsV2 memory) { - Client.EVMExtraArgsV2 memory evmExtraArgs = - _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); - - if (evmExtraArgs.gasLimit > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); - if (destChainConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { - revert ExtraArgOutOfOrderExecutionMustBeTrue(); - } - - return evmExtraArgs; - } - - /// @dev Convert the extra args bytes into a struct. - /// @param extraArgs The extra args bytes. - /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args. - /// @return EVMExtraArgs the extra args struct (latest version) - function _parseUnvalidatedEVMExtraArgsFromBytes( - bytes calldata extraArgs, - uint64 defaultTxGasLimit - ) private pure returns (Client.EVMExtraArgsV2 memory) { - if (extraArgs.length == 0) { - // If extra args are empty, generate default values - return Client.EVMExtraArgsV2({gasLimit: defaultTxGasLimit, allowOutOfOrderExecution: false}); - } - - bytes4 extraArgsTag = bytes4(extraArgs); - bytes memory argsData = extraArgs[4:]; - - if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(argsData, (Client.EVMExtraArgsV2)); - } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { - // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. - // Clients may still include it but it will be ignored. - return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); - } - - revert InvalidExtraArgsTag(); - } - - /// @notice Validate the forwarded message to ensure it matches the configuration limits (message length, number of tokens) - /// and family-specific expectations (address format). - /// @param destChainConfig The destination chain config. - /// @param dataLength The length of the data field of the message. - /// @param numberOfTokens The number of tokens to be sent. - /// @param receiver Message receiver on the dest chain. - function _validateMessage( - DestChainConfig memory destChainConfig, - uint256 dataLength, - uint256 numberOfTokens, - bytes memory receiver - ) internal pure { - // Check that payload is formed correctly - if (dataLength > uint256(destChainConfig.maxDataBytes)) { - revert MessageTooLarge(uint256(destChainConfig.maxDataBytes), dataLength); - } - if (numberOfTokens > uint256(destChainConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); - _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); - } - - /// @inheritdoc IFeeQuoter - /// @dev precondition - onRampTokenTransfers and sourceTokenAmounts lengths must be equal - function processMessageArgs( - uint64 destChainSelector, - address feeToken, - uint256 feeTokenAmount, - bytes calldata extraArgs, - Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, - Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) - external - view - returns ( - uint256 msgFeeJuels, - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - bytes[] memory destExecDataPerToken - ) - { - // Convert feeToken to link if not already in link - if (feeToken == i_linkToken) { - msgFeeJuels = feeTokenAmount; - } else { - msgFeeJuels = convertTokenAmount(feeToken, feeTokenAmount, i_linkToken); - } - - if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); - - uint64 defaultTxGasLimit = s_destChainConfigs[destChainSelector].defaultTxGasLimit; - // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args. - // We can parse unvalidated args since this message is called after getFee (which will already validate the params) - Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); - isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; - destExecDataPerToken = _processPoolReturnData(destChainSelector, onRampTokenTransfers, sourceTokenAmounts); - - return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); - } - - /// @notice Validates pool return data - /// @param destChainSelector Destination chain selector to which the token amounts are sent to - /// @param onRampTokenTransfers Token amounts with populated pool return data - /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - /// @return destExecDataPerToken Destination chain execution data - function _processPoolReturnData( - uint64 destChainSelector, - Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, - Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) internal view returns (bytes[] memory destExecDataPerToken) { - bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; - destExecDataPerToken = new bytes[](onRampTokenTransfers.length); - for (uint256 i = 0; i < onRampTokenTransfers.length; ++i) { - address sourceToken = sourceTokenAmounts[i].token; - - // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the - // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both - // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. - uint256 destPoolDataLength = onRampTokenTransfers[i].extraData.length; - if (destPoolDataLength > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - if (destPoolDataLength > s_tokenTransferFeeConfig[destChainSelector][sourceToken].destBytesOverhead) { - revert SourceTokenDataTooLarge(sourceToken); - } - } - - _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress); - FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = - s_tokenTransferFeeConfig[destChainSelector][sourceToken]; - uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; - // NOTE: Revisit this when adding new non-EVM chain family selector support - uint32 destGasAmount = - tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : defaultGasOverhead; - - // The user will be billed either the default or the override, so we send the exact amount that we billed for - // to the destination chain to be used for the token releaseOrMint and transfer. - destExecDataPerToken[i] = abi.encode(destGasAmount); - } - return destExecDataPerToken; - } - - // ================================================================ - // │ Configs │ - // ================================================================ - - /// @notice Returns the configured config for the dest chain selector. - /// @param destChainSelector Destination chain selector to fetch config for. - /// @return destChainConfig Config for the destination chain. - function getDestChainConfig( - uint64 destChainSelector - ) external view returns (DestChainConfig memory) { - return s_destChainConfigs[destChainSelector]; - } - - /// @notice Updates the destination chain specific config. - /// @param destChainConfigArgs Array of source chain specific configs. - function applyDestChainConfigUpdates( - DestChainConfigArgs[] memory destChainConfigArgs - ) external onlyOwner { - _applyDestChainConfigUpdates(destChainConfigArgs); - } - - /// @notice Internal version of applyDestChainConfigUpdates. - function _applyDestChainConfigUpdates( - DestChainConfigArgs[] memory destChainConfigArgs - ) internal { - for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; - uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig; - - // NOTE: when supporting non-EVM chains, update chainFamilySelector validations - if ( - destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 - || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM - || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit - ) { - revert InvalidDestChainConfig(destChainSelector); - } - - // The chain family selector cannot be zero - indicates that it is a new chain - if (s_destChainConfigs[destChainSelector].chainFamilySelector == 0) { - emit DestChainAdded(destChainSelector, destChainConfig); - } else { - emit DestChainConfigUpdated(destChainSelector, destChainConfig); - } - - s_destChainConfigs[destChainSelector] = destChainConfig; - } - } - - /// @notice Returns the static FeeQuoter config. - /// @dev RMN depends on this function, if updated, please notify the RMN maintainers. - /// @return staticConfig The static configuration. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, - linkToken: i_linkToken, - stalenessThreshold: i_stalenessThreshold - }); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md deleted file mode 100644 index 812debd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE-MIT.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 SmartContract ChainLink, Ltd. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md deleted file mode 100644 index b2e8248..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/LICENSE.md +++ /dev/null @@ -1,56 +0,0 @@ -Business Source License 1.1 - -License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved. -"Business Source License" is a trademark of MariaDB Corporation Ab. - ------------------------------------------------------------------------------ - -Parameters - -Licensor: SmartContract Chainlink Limited SEZC - -Licensed Work: Cross-Chain Interoperability Protocol v1.5 -The Licensed Work is (c) 2023 SmartContract Chainlink Limited SEZC - -Additional Use Grant: Any uses listed and defined at [v1.5-CCIP-License-grants]( -./v1.5-CCIP-License-grants.md) - -Change Date: Aug 16, 2028 - -Change License: MIT - ------------------------------------------------------------------------------ - -Terms - -The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make non-production use of the Licensed Work. The Licensor may make an Additional Use Grant, above, permitting limited production use. - -Effective on the Change Date, or the fourth anniversary of the first publicly available distribution of a specific version of the Licensed Work under this License, whichever comes first, the Licensor hereby grants you rights under the terms of the Change License, and the rights granted in the paragraph above terminate. - -If your use of the Licensed Work does not comply with the requirements currently in effect as described in this License, you must purchase a commercial license from the Licensor, its affiliated entities, or authorized resellers, or you must refrain from using the Licensed Work. - -All copies of the original and modified Licensed Work, and derivative works of the Licensed Work, are subject to this License. This License applies separately for each version of the Licensed Work and the Change Date may vary for each version of the Licensed Work released by Licensor. - -You must conspicuously display this License on each original or modified copy of the Licensed Work. If you receive the Licensed Work in original or modified form from a third party, the terms and conditions set forth in this License apply to your use of that work. - -Any use of the Licensed Work in violation of this License will automatically terminate your rights under this License for the current and all other versions of the Licensed Work. - -This License does not grant you any right in any trademark or logo of Licensor or its affiliates (provided that you may use a trademark or logo of Licensor as expressly required by this License). - -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE. - -MariaDB hereby grants you permission to use this License’s text to license your works, and to refer to it using the trademark "Business Source License", as long as you comply with the Covenants of Licensor below. - ------------------------------------------------------------------------------ - -Covenants of Licensor - -In consideration of the right to use this License’s text and the "Business Source License" name and trademark, Licensor covenants to MariaDB, and to all other recipients of the licensed work to be provided by Licensor: - -1. To specify as the Change License the GPL Version 2.0 or any later version, or a license that is compatible with GPL Version 2.0 or a later version, where "compatible" means that software provided under the Change License can be included in a program with software provided under GPL Version 2.0 or a later version. Licensor may specify additional Change Licenses without limitation. - -2. To either: (a) specify an additional grant of rights to use that does not impose any additional restriction on the right granted in this License, as the Additional Use Grant; or (b) insert the text "None". - -3. To specify a Change Date. - -4. Not to modify this License in any other way. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol deleted file mode 100644 index 7dfcc0e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ /dev/null @@ -1,281 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; -import {IMessageInterceptor} from "./interfaces/IMessageInterceptor.sol"; - -import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; -import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; -import {Client} from "./libraries/Client.sol"; -import {RateLimiter} from "./libraries/RateLimiter.sol"; -import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; - -/// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter -/// which permits rate limiting based on the aggregate value of a group of -/// token transfers, using a fee quoter to convert to a numeraire asset (e.g. USD). -/// The contract is a standalone multi-lane message validator contract, which can be called by authorized -/// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. -contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, ITypeAndVersion { - using RateLimiter for RateLimiter.TokenBucket; - using USDPriceWith18Decimals for uint224; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - error PriceNotFoundForToken(address token); - error ZeroChainSelectorNotAllowed(); - - event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, bool isOutboundLane, RateLimiter.Config config); - event FeeQuoterSet(address newFeeQuoter); - event TokenAggregateRateLimitAdded(uint64 remoteChainSelector, bytes remoteToken, address localToken); - event TokenAggregateRateLimitRemoved(uint64 remoteChainSelector, address localToken); - - /// @notice LocalRateLimitToken struct containing the local token address with the remote chain selector. - /// The struct is used for removals and updates, since the local -> remote token mappings are scoped per-chain. - struct LocalRateLimitToken { - uint64 remoteChainSelector; // ────╮ Remote chain selector for which to update the rate limit token mapping - address localToken; // ────────────╯ Token on the chain on which the multi-ARL is deployed - } - - /// @notice RateLimitTokenArgs struct containing both the local and remote token addresses. - struct RateLimitTokenArgs { - LocalRateLimitToken localTokenArgs; // Local token update args scoped to one remote chain - bytes remoteToken; // Token on the remote chain (for OnRamp - dest, of OffRamp - source) - } - - /// @notice Update args for a single rate limiter config update. - struct RateLimiterConfigArgs { - uint64 remoteChainSelector; // ────╮ Remote chain selector to set config for - bool isOutboundLane; // ───────────╯ If set to true, represents the outbound message lane (OnRamp), and the inbound message lane otherwise (OffRamp) - RateLimiter.Config rateLimiterConfig; // Rate limiter config to set - } - - /// @notice Struct to store rate limit token buckets for both lane directions. - struct RateLimiterBuckets { - RateLimiter.TokenBucket inboundLaneBucket; // Bucket for the inbound lane (remote -> local) - RateLimiter.TokenBucket outboundLaneBucket; // Bucket for the outbound lane (local -> remote) - } - - string public constant override typeAndVersion = "MultiAggregateRateLimiter 1.6.0-dev"; - - /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote), - /// grouped per-remote chain. - mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) private - s_rateLimitedTokensLocalToRemote; - - /// @notice The address of the FeeQuoter used to query token values for ratelimiting. - address internal s_feeQuoter; - - /// @notice Rate limiter token bucket states per chain, with separate buckets for inbound and outbound lanes. - mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) private s_rateLimitersByChainSelector; - - /// @param feeQuoter the fee quoter to set. - /// @param authorizedCallers the authorized callers to set. - constructor(address feeQuoter, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { - _setFeeQuoter(feeQuoter); - } - - /// @inheritdoc IMessageInterceptor - function onInboundMessage( - Client.Any2EVMMessage memory message - ) external onlyAuthorizedCallers { - _applyRateLimit(message.sourceChainSelector, message.destTokenAmounts, false); - } - - /// @inheritdoc IMessageInterceptor - function onOutboundMessage( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external onlyAuthorizedCallers { - _applyRateLimit(destChainSelector, message.tokenAmounts, true); - } - - /// @notice Applies the rate limit to the token bucket if enabled. - /// @param remoteChainSelector The remote chain selector. - /// @param tokenAmounts The tokens and amounts to rate limit. - /// @param isOutgoingLane if set to true, fetches the bucket for the outgoing message lane (OnRamp). - function _applyRateLimit( - uint64 remoteChainSelector, - Client.EVMTokenAmount[] memory tokenAmounts, - bool isOutgoingLane - ) private { - RateLimiter.TokenBucket storage tokenBucket = _getTokenBucket(remoteChainSelector, isOutgoingLane); - - // Skip rate limiting if it is disabled - if (tokenBucket.isEnabled) { - uint256 value; - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].contains(tokenAmounts[i].token)) { - value += _getTokenValue(tokenAmounts[i]); - } - } - // Rate limit on aggregated token value - if (value > 0) tokenBucket._consume(value, address(0)); - } - } - - /// @param remoteChainSelector chain selector to retrieve token bucket for. - /// @param isOutboundLane if set to true, fetches the bucket for the outbound message lane (OnRamp). - /// Otherwise fetches for the inbound message lane (OffRamp). - /// @return bucket Storage pointer to the token bucket representing a specific lane. - function _getTokenBucket( - uint64 remoteChainSelector, - bool isOutboundLane - ) internal view returns (RateLimiter.TokenBucket storage) { - RateLimiterBuckets storage rateLimiterBuckets = s_rateLimitersByChainSelector[remoteChainSelector]; - if (isOutboundLane) { - return rateLimiterBuckets.outboundLaneBucket; - } else { - return rateLimiterBuckets.inboundLaneBucket; - } - } - - /// @notice Retrieves the token value for a token using the FeeQuoter. - /// @param tokenAmount The token and amount to get the value for. - /// @return tokenValue USD value in 18 decimals. - function _getTokenValue( - Client.EVMTokenAmount memory tokenAmount - ) internal view returns (uint256) { - // not fetching validated price, as price staleness is not important for value-based rate limiting - // we only need to verify the price is not 0 - uint224 pricePerToken = IFeeQuoter(s_feeQuoter).getTokenPrice(tokenAmount.token).value; - if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); - return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @param remoteChainSelector chain selector to retrieve state for - /// @param isOutboundLane if set to true, fetches the rate limit state for the outbound message lane (OnRamp). - /// Otherwise fetches for the inbound message lane (OffRamp). - /// The outbound and inbound message rate limit state is completely separated. - /// @return tokenBucket The token bucket. - function currentRateLimiterState( - uint64 remoteChainSelector, - bool isOutboundLane - ) external view returns (RateLimiter.TokenBucket memory) { - return _getTokenBucket(remoteChainSelector, isOutboundLane)._currentTokenBucketState(); - } - - /// @notice Applies the provided rate limiter config updates. - /// @param rateLimiterUpdates Rate limiter updates. - /// @dev Only callable by the owner. - function applyRateLimiterConfigUpdates( - RateLimiterConfigArgs[] memory rateLimiterUpdates - ) external onlyOwner { - for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { - RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; - RateLimiter.Config memory configUpdate = updateArgs.rateLimiterConfig; - uint64 remoteChainSelector = updateArgs.remoteChainSelector; - - if (remoteChainSelector == 0) { - revert ZeroChainSelectorNotAllowed(); - } - - bool isOutboundLane = updateArgs.isOutboundLane; - - RateLimiter.TokenBucket storage tokenBucket = _getTokenBucket(remoteChainSelector, isOutboundLane); - - if (tokenBucket.lastUpdated == 0) { - // Token bucket needs to be newly added - RateLimiter.TokenBucket memory newTokenBucket = RateLimiter.TokenBucket({ - rate: configUpdate.rate, - capacity: configUpdate.capacity, - tokens: configUpdate.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: configUpdate.isEnabled - }); - - if (isOutboundLane) { - s_rateLimitersByChainSelector[remoteChainSelector].outboundLaneBucket = newTokenBucket; - } else { - s_rateLimitersByChainSelector[remoteChainSelector].inboundLaneBucket = newTokenBucket; - } - } else { - tokenBucket._setTokenBucketConfig(configUpdate); - } - emit RateLimiterConfigUpdated(remoteChainSelector, isOutboundLane, configUpdate); - } - } - - /// @notice Gets all tokens which are included in Aggregate Rate Limiting. - /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when - /// making successive calls, one should keep the block height constant to ensure a consistent result. - /// @param remoteChainSelector chain selector to get rate limit tokens for. - /// @return localTokens The local chain representation of the tokens that are rate limited. - /// @return remoteTokens The remote representation of the tokens that are rate limited. - function getAllRateLimitTokens( - uint64 remoteChainSelector - ) external view returns (address[] memory localTokens, bytes[] memory remoteTokens) { - uint256 tokenCount = s_rateLimitedTokensLocalToRemote[remoteChainSelector].length(); - - localTokens = new address[](tokenCount); - remoteTokens = new bytes[](tokenCount); - - for (uint256 i = 0; i < tokenCount; ++i) { - (address localToken, bytes memory remoteToken) = s_rateLimitedTokensLocalToRemote[remoteChainSelector].at(i); - localTokens[i] = localToken; - remoteTokens[i] = remoteToken; - } - return (localTokens, remoteTokens); - } - - /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. - /// @param removes - A list of one or more tokens to be removed. - /// @param adds - A list of one or more tokens to be added. - function updateRateLimitTokens( - LocalRateLimitToken[] memory removes, - RateLimitTokenArgs[] memory adds - ) external onlyOwner { - for (uint256 i = 0; i < removes.length; ++i) { - address localToken = removes[i].localToken; - uint64 remoteChainSelector = removes[i].remoteChainSelector; - - if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].remove(localToken)) { - emit TokenAggregateRateLimitRemoved(remoteChainSelector, localToken); - } - } - - for (uint256 i = 0; i < adds.length; ++i) { - LocalRateLimitToken memory localTokenArgs = adds[i].localTokenArgs; - bytes memory remoteToken = adds[i].remoteToken; - address localToken = localTokenArgs.localToken; - - if (localToken == address(0) || remoteToken.length == 0) { - revert ZeroAddressNotAllowed(); - } - - uint64 remoteChainSelector = localTokenArgs.remoteChainSelector; - - if (s_rateLimitedTokensLocalToRemote[remoteChainSelector].set(localToken, remoteToken)) { - emit TokenAggregateRateLimitAdded(remoteChainSelector, remoteToken, localToken); - } - } - } - - /// @return feeQuoter The configured FeeQuoter address. - function getFeeQuoter() external view returns (address feeQuoter) { - return s_feeQuoter; - } - - /// @notice Sets the FeeQuoter address. - /// @param newFeeQuoter the address of the new FeeQuoter. - /// @dev precondition The address must be a non-zero address. - function setFeeQuoter( - address newFeeQuoter - ) external onlyOwner { - _setFeeQuoter(newFeeQuoter); - } - - /// @notice Sets the FeeQuoter address. - /// @param newFeeQuoter the address of the new FeeQuoter. - /// @dev precondition The address must be a non-zero address. - function _setFeeQuoter( - address newFeeQuoter - ) internal { - if (newFeeQuoter == address(0)) { - revert ZeroAddressNotAllowed(); - } - - s_feeQuoter = newFeeQuoter; - emit FeeQuoterSet(newFeeQuoter); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol deleted file mode 100644 index a1db80a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/NonceManager.sol +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; -import {INonceManager} from "./interfaces/INonceManager.sol"; - -import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; - -/// @title NonceManager -/// @notice NonceManager contract that manages sender nonces for the on/off ramps -contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { - error PreviousRampAlreadySet(); - - event PreviousRampsUpdated(uint64 indexed remoteChainSelector, PreviousRamps prevRamp); - event SkippedIncorrectNonce(uint64 sourceChainSelector, uint64 nonce, bytes sender); - - /// @dev Struct that contains the previous on/off ramp addresses - struct PreviousRamps { - address prevOnRamp; // Previous onRamp - address prevOffRamp; // Previous offRamp - } - - /// @dev Struct that contains the chain selector and the previous on/off ramps, same as PreviousRamps but with the chain selector - /// so that an array of these can be passed to the applyPreviousRampsUpdates function - struct PreviousRampsArgs { - uint64 remoteChainSelector; // Chain selector - PreviousRamps prevRamps; // Previous on/off ramps - } - - string public constant override typeAndVersion = "NonceManager 1.6.0-dev"; - - /// @dev The previous on/off ramps per chain selector - mapping(uint64 chainSelector => PreviousRamps previousRamps) private s_previousRamps; - /// @dev The current outbound nonce per sender used on the onramp - mapping(uint64 destChainSelector => mapping(address sender => uint64 outboundNonce)) private s_outboundNonces; - /// @dev The current inbound nonce per sender used on the offramp - /// Eventually in sync with the outbound nonce in the remote source chain NonceManager, used to enforce that messages are - /// executed in the same order they are sent (assuming they are DON) - mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 inboundNonce)) private s_inboundNonces; - - constructor( - address[] memory authorizedCallers - ) AuthorizedCallers(authorizedCallers) {} - - /// @inheritdoc INonceManager - function getIncrementedOutboundNonce( - uint64 destChainSelector, - address sender - ) external onlyAuthorizedCallers returns (uint64) { - uint64 outboundNonce = _getOutboundNonce(destChainSelector, sender) + 1; - s_outboundNonces[destChainSelector][sender] = outboundNonce; - - return outboundNonce; - } - - /// @notice Returns the outbound nonce for a given sender on a given destination chain. - /// @param destChainSelector The destination chain selector. - /// @param sender The sender address. - /// @return outboundNonce The outbound nonce. - function getOutboundNonce(uint64 destChainSelector, address sender) external view returns (uint64) { - return _getOutboundNonce(destChainSelector, sender); - } - - function _getOutboundNonce(uint64 destChainSelector, address sender) private view returns (uint64) { - uint64 outboundNonce = s_outboundNonces[destChainSelector][sender]; - - // When introducing the NonceManager with existing lanes, we still want to have sequential nonces. - // Referencing the old onRamp preserves sequencing between updates. - if (outboundNonce == 0) { - address prevOnRamp = s_previousRamps[destChainSelector].prevOnRamp; - if (prevOnRamp != address(0)) { - return IEVM2AnyOnRamp(prevOnRamp).getSenderNonce(sender); - } - } - - return outboundNonce; - } - - /// @inheritdoc INonceManager - function incrementInboundNonce( - uint64 sourceChainSelector, - uint64 expectedNonce, - bytes calldata sender - ) external onlyAuthorizedCallers returns (bool) { - uint64 inboundNonce = _getInboundNonce(sourceChainSelector, sender) + 1; - - if (inboundNonce != expectedNonce) { - // If the nonce is not the expected one, this means that there are still messages in flight so we skip - // the nonce increment - emit SkippedIncorrectNonce(sourceChainSelector, expectedNonce, sender); - return false; - } - - s_inboundNonces[sourceChainSelector][sender] = inboundNonce; - - return true; - } - - /// @notice Returns the inbound nonce for a given sender on a given source chain. - /// @param sourceChainSelector The source chain selector. - /// @param sender The encoded sender address. - /// @return inboundNonce The inbound nonce. - function getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) external view returns (uint64) { - return _getInboundNonce(sourceChainSelector, sender); - } - - function _getInboundNonce(uint64 sourceChainSelector, bytes calldata sender) private view returns (uint64) { - uint64 inboundNonce = s_inboundNonces[sourceChainSelector][sender]; - - // When introducing the NonceManager with existing lanes, we still want to have sequential nonces. - // Referencing the old offRamp to check the expected nonce if none is set for a - // given sender allows us to skip the current message in the current offRamp if it would not be the next according - // to the old offRamp. This preserves sequencing between updates. - if (inboundNonce == 0) { - address prevOffRamp = s_previousRamps[sourceChainSelector].prevOffRamp; - if (prevOffRamp != address(0)) { - // We only expect EVM previous offRamps here so we can safely decode the sender - return IEVM2AnyOnRamp(prevOffRamp).getSenderNonce(abi.decode(sender, (address))); - } - } - - return inboundNonce; - } - - /// @notice Updates the previous ramps addresses. - /// @param previousRampsArgs The previous on/off ramps addresses. - function applyPreviousRampsUpdates( - PreviousRampsArgs[] calldata previousRampsArgs - ) external onlyOwner { - for (uint256 i = 0; i < previousRampsArgs.length; ++i) { - PreviousRampsArgs calldata previousRampsArg = previousRampsArgs[i]; - - PreviousRamps storage prevRamps = s_previousRamps[previousRampsArg.remoteChainSelector]; - - // If the previous ramps are already set then they should not be updated. - // In versions prior to the introduction of the NonceManager contract, nonces were tracked in the on/off ramps. - // This config does a 1-time migration to move the nonce from on/off ramps into NonceManager - if (prevRamps.prevOnRamp != address(0) || prevRamps.prevOffRamp != address(0)) { - revert PreviousRampAlreadySet(); - } - - prevRamps.prevOnRamp = previousRampsArg.prevRamps.prevOnRamp; - prevRamps.prevOffRamp = previousRampsArg.prevRamps.prevOffRamp; - - emit PreviousRampsUpdated(previousRampsArg.remoteChainSelector, previousRampsArg.prevRamps); - } - } - - /// @notice Gets the previous onRamp address for the given chain selector - /// @param chainSelector The chain selector - /// @return previousRamps The previous on/offRamp addresses - function getPreviousRamps( - uint64 chainSelector - ) external view returns (PreviousRamps memory) { - return s_previousRamps[chainSelector]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol deleted file mode 100644 index d83216f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/Router.sol +++ /dev/null @@ -1,298 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {IAny2EVMMessageReceiver} from "./interfaces/IAny2EVMMessageReceiver.sol"; -import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; -import {IRMN} from "./interfaces/IRMN.sol"; -import {IRouter} from "./interfaces/IRouter.sol"; -import {IRouterClient} from "./interfaces/IRouterClient.sol"; -import {IWrappedNative} from "./interfaces/IWrappedNative.sol"; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -import {CallWithExactGas} from "../shared/call/CallWithExactGas.sol"; -import {Client} from "./libraries/Client.sol"; -import {Internal} from "./libraries/Internal.sol"; - -import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @title Router -/// @notice This is the entry point for the end user wishing to send data across chains. -/// @dev This contract is used as a router for both on-ramps and off-ramps -contract Router is IRouter, IRouterClient, ITypeAndVersion, OwnerIsCreator { - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.UintSet; - - error FailedToSendValue(); - error InvalidRecipientAddress(address to); - error OffRampMismatch(uint64 chainSelector, address offRamp); - error BadARMSignal(); - - event OnRampSet(uint64 indexed destChainSelector, address onRamp); - event OffRampAdded(uint64 indexed sourceChainSelector, address offRamp); - event OffRampRemoved(uint64 indexed sourceChainSelector, address offRamp); - event MessageExecuted(bytes32 messageId, uint64 sourceChainSelector, address offRamp, bytes32 calldataHash); - - struct OnRamp { - uint64 destChainSelector; - address onRamp; - } - - struct OffRamp { - uint64 sourceChainSelector; - address offRamp; - } - - string public constant override typeAndVersion = "Router 1.2.0"; - // We limit return data to a selector plus 4 words. This is to avoid - // malicious contracts from returning large amounts of data and causing - // repeated out-of-gas scenarios. - uint16 public constant MAX_RET_BYTES = 4 + 4 * 32; - // STATIC CONFIG - // Address of RMN proxy contract (formerly known as ARM) - address private immutable i_armProxy; - - // DYNAMIC CONFIG - address private s_wrappedNative; - // destChainSelector => onRamp address - // Only ever one onRamp enabled at a time for a given destChainSelector. - mapping(uint256 destChainSelector => address onRamp) private s_onRamps; - // Stores [sourceChainSelector << 160 + offramp] as a pair to allow for - // lookups for specific chain/offramp pairs. - EnumerableSet.UintSet private s_chainSelectorAndOffRamps; - - constructor(address wrappedNative, address armProxy) { - // Zero address indicates unsupported auto-wrapping, therefore, unsupported - // native fee token payments. - s_wrappedNative = wrappedNative; - i_armProxy = armProxy; - } - - // ================================================================ - // │ Message sending │ - // ================================================================ - - /// @inheritdoc IRouterClient - function getFee( - uint64 destinationChainSelector, - Client.EVM2AnyMessage memory message - ) external view returns (uint256 fee) { - if (message.feeToken == address(0)) { - // For empty feeToken return native quote. - message.feeToken = address(s_wrappedNative); - } - address onRamp = s_onRamps[destinationChainSelector]; - if (onRamp == address(0)) revert UnsupportedDestinationChain(destinationChainSelector); - return IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); - } - - /// @notice This functionality has been removed and will revert when called. - function getSupportedTokens( - uint64 chainSelector - ) external view returns (address[] memory) { - if (!isChainSupported(chainSelector)) { - return new address[](0); - } - return IEVM2AnyOnRamp(s_onRamps[uint256(chainSelector)]).getSupportedTokens(chainSelector); - } - - /// @inheritdoc IRouterClient - function isChainSupported( - uint64 chainSelector - ) public view returns (bool) { - return s_onRamps[chainSelector] != address(0); - } - - /// @inheritdoc IRouterClient - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage memory message - ) external payable whenNotCursed returns (bytes32) { - address onRamp = s_onRamps[destinationChainSelector]; - if (onRamp == address(0)) revert UnsupportedDestinationChain(destinationChainSelector); - uint256 feeTokenAmount; - // address(0) signals payment in true native - if (message.feeToken == address(0)) { - // for fee calculation we check the wrapped native price as we wrap - // as part of the native fee coin payment. - message.feeToken = s_wrappedNative; - // We rely on getFee to validate that the feeToken is whitelisted. - feeTokenAmount = IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); - // Ensure sufficient native. - if (msg.value < feeTokenAmount) revert InsufficientFeeTokenAmount(); - // Wrap and send native payment. - // Note we take the whole msg.value regardless if its larger. - feeTokenAmount = msg.value; - IWrappedNative(message.feeToken).deposit{value: feeTokenAmount}(); - IERC20(message.feeToken).safeTransfer(onRamp, feeTokenAmount); - } else { - if (msg.value > 0) revert InvalidMsgValue(); - // We rely on getFee to validate that the feeToken is whitelisted. - feeTokenAmount = IEVM2AnyOnRamp(onRamp).getFee(destinationChainSelector, message); - IERC20(message.feeToken).safeTransferFrom(msg.sender, onRamp, feeTokenAmount); - } - - // Transfer the tokens to the token pools. - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - IERC20 token = IERC20(message.tokenAmounts[i].token); - // We rely on getPoolBySourceToken to validate that the token is whitelisted. - token.safeTransferFrom( - msg.sender, - address(IEVM2AnyOnRamp(onRamp).getPoolBySourceToken(destinationChainSelector, token)), - message.tokenAmounts[i].amount - ); - } - - return IEVM2AnyOnRamp(onRamp).forwardFromRouter(destinationChainSelector, message, feeTokenAmount, msg.sender); - } - - // ================================================================ - // │ Message execution │ - // ================================================================ - - /// @inheritdoc IRouter - /// @dev _callWithExactGas protects against return data bombs by capping the return data size at MAX_RET_BYTES. - function routeMessage( - Client.Any2EVMMessage calldata message, - uint16 gasForCallExactCheck, - uint256 gasLimit, - address receiver - ) external override whenNotCursed returns (bool success, bytes memory retData, uint256 gasUsed) { - // We only permit offRamps to call this function. - if (!isOffRamp(message.sourceChainSelector, msg.sender)) revert OnlyOffRamp(); - - // We encode here instead of the offRamps to constrain specifically what functions - // can be called from the router. - bytes memory data = abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message); - - (success, retData, gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( - data, receiver, gasLimit, gasForCallExactCheck, Internal.MAX_RET_BYTES - ); - - emit MessageExecuted(message.messageId, message.sourceChainSelector, msg.sender, keccak256(data)); - return (success, retData, gasUsed); - } - - // @notice Merges a chain selector and offRamp address into a single uint256 by shifting the - // chain selector 160 bits to the left. - function _mergeChainSelectorAndOffRamp( - uint64 sourceChainSelector, - address offRampAddress - ) internal pure returns (uint256) { - return (uint256(sourceChainSelector) << 160) + uint160(offRampAddress); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Gets the wrapped representation of the native fee coin. - /// @return The address of the ERC20 wrapped native. - function getWrappedNative() external view returns (address) { - return s_wrappedNative; - } - - /// @notice Sets a new wrapped native token. - /// @param wrappedNative The address of the new wrapped native ERC20 token. - function setWrappedNative( - address wrappedNative - ) external onlyOwner { - s_wrappedNative = wrappedNative; - } - - /// @notice Gets the RMN address, formerly known as ARM - /// @return The address of the RMN proxy contract, formerly known as ARM - function getArmProxy() external view returns (address) { - return i_armProxy; - } - - /// @inheritdoc IRouter - function getOnRamp( - uint64 destChainSelector - ) external view returns (address) { - return s_onRamps[destChainSelector]; - } - - function getOffRamps() external view returns (OffRamp[] memory) { - uint256[] memory encodedOffRamps = s_chainSelectorAndOffRamps.values(); - OffRamp[] memory offRamps = new OffRamp[](encodedOffRamps.length); - for (uint256 i = 0; i < encodedOffRamps.length; ++i) { - uint256 encodedOffRamp = encodedOffRamps[i]; - offRamps[i] = - OffRamp({sourceChainSelector: uint64(encodedOffRamp >> 160), offRamp: address(uint160(encodedOffRamp))}); - } - return offRamps; - } - - /// @inheritdoc IRouter - function isOffRamp(uint64 sourceChainSelector, address offRamp) public view returns (bool) { - // We have to encode the sourceChainSelector and offRamp into a uint256 to use as a key in the set. - return s_chainSelectorAndOffRamps.contains(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRamp)); - } - - /// @notice applyRampUpdates applies a set of ramp changes which provides - /// the ability to add new chains and upgrade ramps. - function applyRampUpdates( - OnRamp[] calldata onRampUpdates, - OffRamp[] calldata offRampRemoves, - OffRamp[] calldata offRampAdds - ) external onlyOwner { - // Apply egress updates. - // We permit zero address as way to disable egress. - for (uint256 i = 0; i < onRampUpdates.length; ++i) { - OnRamp memory onRampUpdate = onRampUpdates[i]; - s_onRamps[onRampUpdate.destChainSelector] = onRampUpdate.onRamp; - emit OnRampSet(onRampUpdate.destChainSelector, onRampUpdate.onRamp); - } - - // Apply ingress updates. - for (uint256 i = 0; i < offRampRemoves.length; ++i) { - uint64 sourceChainSelector = offRampRemoves[i].sourceChainSelector; - address offRampAddress = offRampRemoves[i].offRamp; - - // If the selector-offRamp pair does not exist, revert. - if (!s_chainSelectorAndOffRamps.remove(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRampAddress))) { - revert OffRampMismatch(sourceChainSelector, offRampAddress); - } - - emit OffRampRemoved(sourceChainSelector, offRampAddress); - } - - for (uint256 i = 0; i < offRampAdds.length; ++i) { - uint64 sourceChainSelector = offRampAdds[i].sourceChainSelector; - address offRampAddress = offRampAdds[i].offRamp; - - if (s_chainSelectorAndOffRamps.add(_mergeChainSelectorAndOffRamp(sourceChainSelector, offRampAddress))) { - emit OffRampAdded(sourceChainSelector, offRampAddress); - } - } - } - - /// @notice Provides the ability for the owner to recover any tokens accidentally - /// sent to this contract. - /// @dev Must be onlyOwner to avoid malicious token contract calls. - /// @param tokenAddress ERC20-token to recover - /// @param to Destination address to send the tokens to. - function recoverTokens(address tokenAddress, address to, uint256 amount) external onlyOwner { - if (to == address(0)) revert InvalidRecipientAddress(to); - - if (tokenAddress == address(0)) { - (bool success,) = to.call{value: amount}(""); - if (!success) revert FailedToSendValue(); - return; - } - IERC20(tokenAddress).safeTransfer(to, amount); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Ensure that the RMN has not cursed the network. - modifier whenNotCursed() { - if (IRMN(i_armProxy).isCursed()) revert BadARMSignal(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol deleted file mode 100644 index 56f3cd1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.sol"; -import {CCIPReceiver} from "./CCIPReceiver.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -// @notice Example of a client which supports EVM/non-EVM chains -// @dev If chain specific logic is required for different chain families (e.g. particular -// decoding the bytes sender for authorization checks), it may be required to point to a helper -// authorization contract unless all chain families are known up front. -// @dev If contract does not implement IAny2EVMMessageReceiver and IERC165, -// and tokens are sent to it, ccipReceive will not be called but tokens will be transferred. -// @dev If the client is upgradeable you have significantly more flexibility and -// can avoid storage based options like the below contract uses. However it's -// worth carefully considering how the trust assumptions of your client dapp will -// change if you introduce upgradeability. An immutable dapp building on top of CCIP -// like the example below will inherit the trust properties of CCIP (i.e. the oracle network). -// @dev The receiver's are encoded offchain and passed as direct arguments to permit supporting -// new chain family receivers (e.g. a Solana encoded receiver address) without upgrading. -contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { - error InvalidChain(uint64 chainSelector); - - event MessageSent(bytes32 messageId); - event MessageReceived(bytes32 messageId); - - // Current feeToken - IERC20 public s_feeToken; - // Below is a simplistic example (same params for all messages) of using storage to allow for new options without - // upgrading the dapp. Note that extra args are chain family specific (e.g. gasLimit is EVM specific etc.). - // and will always be backwards compatible i.e. upgrades are opt-in. - // Offchain we can compute the V1 extraArgs: - // Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); - // bytes memory encodedV1ExtraArgs = Client._argsToBytes(extraArgs); - // Then later compute V2 extraArgs, for example if a refund feature was added: - // Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 300_000, destRefundAddress: 0x1234}); - // bytes memory encodedV2ExtraArgs = Client._argsToBytes(extraArgs); - // and update storage with the new args. - // If different options are required for different messages, for example different gas limits, - // one can simply key based on (chainSelector, messageType) instead of only chainSelector. - mapping(uint64 destChainSelector => bytes extraArgsBytes) public s_chains; - - constructor(IRouterClient router, IERC20 feeToken) CCIPReceiver(address(router)) { - s_feeToken = feeToken; - s_feeToken.approve(address(router), type(uint256).max); - } - - function enableChain(uint64 chainSelector, bytes memory extraArgs) external onlyOwner { - s_chains[chainSelector] = extraArgs; - } - - function disableChain( - uint64 chainSelector - ) external onlyOwner { - delete s_chains[chainSelector]; - } - - function ccipReceive( - Client.Any2EVMMessage calldata message - ) external virtual override onlyRouter validChain(message.sourceChainSelector) { - // Extremely important to ensure only router calls this. - // Tokens in message if any will be transferred to this contract - // TODO: Validate sender/origin chain and process message and/or tokens. - _ccipReceive(message); - } - - function _ccipReceive( - Client.Any2EVMMessage memory message - ) internal override { - emit MessageReceived(message.messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native asset. - function sendDataPayNative( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data - ) external validChain(destChainSelector) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(0) // We leave the feeToken empty indicating we'll pay raw native. - }); - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend{ - value: IRouterClient(i_ccipRouter).getFee(destChainSelector, message) - }(destChainSelector, message); - emit MessageSent(messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient feeToken. - function sendDataPayFeeToken( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data - ) external validChain(destChainSelector) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - /// @notice sends data to receiver on dest chain. Assumes address(this) has sufficient native token. - function sendDataAndTokens( - uint64 destChainSelector, - bytes memory receiver, - bytes memory data, - Client.EVMTokenAmount[] memory tokenAmounts - ) external validChain(destChainSelector) { - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); - IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); - } - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - // @notice user sends tokens to a receiver - // Approvals can be optimized with a whitelist of tokens and inf approvals if desired. - function sendTokens( - uint64 destChainSelector, - bytes memory receiver, - Client.EVMTokenAmount[] memory tokenAmounts - ) external validChain(destChainSelector) { - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - IERC20(tokenAmounts[i].token).transferFrom(msg.sender, address(this), tokenAmounts[i].amount); - IERC20(tokenAmounts[i].token).approve(i_ccipRouter, tokenAmounts[i].amount); - } - bytes memory data; - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: receiver, - data: data, - tokenAmounts: tokenAmounts, - extraArgs: s_chains[destChainSelector], - feeToken: address(s_feeToken) - }); - // Optional uint256 fee = i_ccipRouter.getFee(destChainSelector, message); - // Can decide if fee is acceptable. - // address(this) must have sufficient feeToken or the send will revert. - bytes32 messageId = IRouterClient(i_ccipRouter).ccipSend(destChainSelector, message); - emit MessageSent(messageId); - } - - modifier validChain( - uint64 chainSelector - ) { - if (s_chains[chainSelector].length == 0) revert InvalidChain(chainSelector); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol deleted file mode 100644 index 8caeb3f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/CCIPReceiver.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; - -import {Client} from "../libraries/Client.sol"; - -import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -/// @title CCIPReceiver - Base contract for CCIP applications that can receive messages. -abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165 { - address internal immutable i_ccipRouter; - - constructor( - address router - ) { - if (router == address(0)) revert InvalidRouter(address(0)); - i_ccipRouter = router; - } - - /// @notice IERC165 supports an interfaceId - /// @param interfaceId The interfaceId to check - /// @return true if the interfaceId is supported - /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver - /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId - /// This allows CCIP to check if ccipReceive is available before calling it. - /// If this returns false or reverts, only tokens are transferred to the receiver. - /// If this returns true, tokens are transferred and ccipReceive is called atomically. - /// Additionally, if the receiver address does not have code associated with - /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. - function supportsInterface( - bytes4 interfaceId - ) public view virtual override returns (bool) { - return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - /// @inheritdoc IAny2EVMMessageReceiver - function ccipReceive( - Client.Any2EVMMessage calldata message - ) external virtual override onlyRouter { - _ccipReceive(message); - } - - /// @notice Override this function in your implementation. - /// @param message Any2EVMMessage - function _ccipReceive( - Client.Any2EVMMessage memory message - ) internal virtual; - - ///////////////////////////////////////////////////////////////////// - // Plumbing - ///////////////////////////////////////////////////////////////////// - - /// @notice Return the current router - /// @return CCIP router address - function getRouter() public view virtual returns (address) { - return address(i_ccipRouter); - } - - error InvalidRouter(address router); - - /// @dev only calls from the set router are accepted. - modifier onlyRouter() { - if (msg.sender != getRouter()) revert InvalidRouter(msg.sender); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol deleted file mode 100644 index dbe8550..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/DefensiveExample.sol +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; - -import {Client} from "../libraries/Client.sol"; -import {CCIPClientExample} from "./CCIPClientExample.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; - -contract DefensiveExample is CCIPClientExample { - using EnumerableMap for EnumerableMap.Bytes32ToUintMap; - using SafeERC20 for IERC20; - - error OnlySelf(); - error ErrorCase(); - error MessageNotFailed(bytes32 messageId); - - event MessageFailed(bytes32 indexed messageId, bytes reason); - event MessageSucceeded(bytes32 indexed messageId); - event MessageRecovered(bytes32 indexed messageId); - - // Example error code, could have many different error codes. - enum ErrorCode { - // RESOLVED is first so that the default value is resolved. - RESOLVED, - // Could have any number of error codes here. - BASIC - } - - // The message contents of failed messages are stored here. - mapping(bytes32 messageId => Client.Any2EVMMessage contents) public s_messageContents; - - // Contains failed messages and their state. - EnumerableMap.Bytes32ToUintMap internal s_failedMessages; - - // This is used to simulate a revert in the processMessage function. - bool internal s_simRevert = false; - - constructor(IRouterClient router, IERC20 feeToken) CCIPClientExample(router, feeToken) {} - - /// @notice The entrypoint for the CCIP router to call. This function should - /// never revert, all errors should be handled internally in this contract. - /// @param message The message to process. - /// @dev Extremely important to ensure only router calls this. - function ccipReceive( - Client.Any2EVMMessage calldata message - ) external override onlyRouter validChain(message.sourceChainSelector) { - try this.processMessage(message) {} - catch (bytes memory err) { - // Could set different error codes based on the caught error. Each could be - // handled differently. - s_failedMessages.set(message.messageId, uint256(ErrorCode.BASIC)); - s_messageContents[message.messageId] = message; - // Don't revert so CCIP doesn't revert. Emit event instead. - // The message can be retried later without having to do manual execution of CCIP. - emit MessageFailed(message.messageId, err); - return; - } - emit MessageSucceeded(message.messageId); - } - - /// @notice This function the entrypoint for this contract to process messages. - /// @param message The message to process. - /// @dev This example just sends the tokens to the owner of this contracts. More - /// interesting functions could be implemented. - /// @dev It has to be external because of the try/catch. - function processMessage( - Client.Any2EVMMessage calldata message - ) external onlySelf validChain(message.sourceChainSelector) { - // Simulate a revert - if (s_simRevert) revert ErrorCase(); - - // Send tokens to the owner - for (uint256 i = 0; i < message.destTokenAmounts.length; ++i) { - IERC20(message.destTokenAmounts[i].token).safeTransfer(owner(), message.destTokenAmounts[i].amount); - } - // Do other things that might revert - } - - /// @notice This function is callable by the owner when a message has failed - /// to unblock the tokens that are associated with that message. - /// @dev This function is only callable by the owner. - function retryFailedMessage(bytes32 messageId, address tokenReceiver) external onlyOwner { - if (s_failedMessages.get(messageId) != uint256(ErrorCode.BASIC)) revert MessageNotFailed(messageId); - // Set the error code to 0 to disallow reentry and retry the same failed message - // multiple times. - s_failedMessages.set(messageId, uint256(ErrorCode.RESOLVED)); - - // Do stuff to retry message, potentially just releasing the associated tokens - Client.Any2EVMMessage memory message = s_messageContents[messageId]; - - // send the tokens to the receiver as escape hatch - for (uint256 i = 0; i < message.destTokenAmounts.length; ++i) { - IERC20(message.destTokenAmounts[i].token).safeTransfer(tokenReceiver, message.destTokenAmounts[i].amount); - } - - emit MessageRecovered(messageId); - } - - // An example function to demonstrate recovery - function setSimRevert( - bool simRevert - ) external onlyOwner { - s_simRevert = simRevert; - } - - modifier onlySelf() { - if (msg.sender != address(this)) revert OnlySelf(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol deleted file mode 100644 index 5bb0193..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ /dev/null @@ -1,184 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {IRouterClient} from "../interfaces/IRouterClient.sol"; -import {IWrappedNative} from "../interfaces/IWrappedNative.sol"; - -import {Client} from "./../libraries/Client.sol"; -import {CCIPReceiver} from "./CCIPReceiver.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -//solhint-disable interface-starts-with-i -interface CCIPRouter { - function getWrappedNative() external view returns (address); -} - -/// @notice A contract that can send raw ether cross-chain using CCIP. -/// Since CCIP only supports ERC-20 token transfers, this contract accepts -/// normal ether, wraps it, and uses CCIP to send it cross-chain. -/// On the receiving side, the wrapped ether is unwrapped and sent to the final receiver. -/// @notice This contract only supports chains where the wrapped native contract -/// is the WETH contract (i.e not WMATIC, or WAVAX, etc.). This is because the -/// receiving contract will always unwrap the ether using it's local wrapped native contract. -/// @dev This contract is both a sender and a receiver. This same contract can be -/// deployed on source and destination chains to facilitate cross-chain ether transfers -/// and act as a sender and a receiver. -/// @dev This contract is intentionally ownerless and permissionless. This contract -/// will never hold any excess funds, native or otherwise, when used correctly. -contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { - using SafeERC20 for IERC20; - - error InvalidTokenAmounts(uint256 gotAmounts); - error InvalidToken(address gotToken, address expectedToken); - error TokenAmountNotEqualToMsgValue(uint256 gotAmount, uint256 msgValue); - - string public constant override typeAndVersion = "EtherSenderReceiver 1.5.0"; - - /// @notice The wrapped native token address. - /// @dev If the wrapped native token address changes on the router, this contract will need to be redeployed. - IWrappedNative public immutable i_weth; - - /// @param router The CCIP router address. - constructor( - address router - ) CCIPReceiver(router) { - i_weth = IWrappedNative(CCIPRouter(router).getWrappedNative()); - i_weth.approve(router, type(uint256).max); - } - - /// @notice Need this in order to unwrap correctly. - receive() external payable {} - - /// @notice Get the fee for sending a message to a destination chain. - /// This is mirrored from the router for convenience, construct the appropriate - /// message and get it's fee. - /// @param destinationChainSelector The destination chainSelector - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return fee returns execution fee for the message - /// delivery to destination chain, denominated in the feeToken specified in the message. - /// @dev Reverts with appropriate reason upon invalid message. - function getFee( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 fee) { - Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); - - return IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); - } - - /// @notice Send raw native tokens cross-chain. - /// @param destinationChainSelector The destination chain selector. - /// @param message The CCIP message with the following fields correctly set: - /// - bytes receiver: The _contract_ address on the destination chain that will receive the wrapped ether. - /// The caller must ensure that this contract address is correct, otherwise funds may be lost forever. - /// - address feeToken: The fee token address. Must be address(0) for native tokens, or a supported CCIP fee token otherwise (i.e, LINK token). - /// In the event a feeToken is set, we will transferFrom the caller the fee amount before sending the message, in order to forward them to the router. - /// - EVMTokenAmount[] tokenAmounts: The tokenAmounts array must contain a single element with the following fields: - /// - uint256 amount: The amount of ether to send. - /// There are a couple of cases here that depend on the fee token specified: - /// 1. If feeToken == address(0), the fee must be included in msg.value. Therefore tokenAmounts[0].amount must be less than msg.value, - /// and the difference will be used as the fee. - /// 2. If feeToken != address(0), the fee is not included in msg.value, and tokenAmounts[0].amount must be equal to msg.value. - /// these fees to the CCIP router. - /// @return messageId The CCIP message ID. - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external payable returns (bytes32) { - _validateFeeToken(message); - Client.EVM2AnyMessage memory validatedMessage = _validatedMessage(message); - - i_weth.deposit{value: validatedMessage.tokenAmounts[0].amount}(); - - uint256 fee = IRouterClient(getRouter()).getFee(destinationChainSelector, validatedMessage); - if (validatedMessage.feeToken != address(0)) { - // If the fee token is not native, we need to transfer the fee to this contract and re-approve it to the router. - // Its not possible to have any leftover tokens in this path because we transferFrom the exact fee that CCIP - // requires from the caller. - IERC20(validatedMessage.feeToken).safeTransferFrom(msg.sender, address(this), fee); - - // We gave an infinite approval of weth to the router in the constructor. - if (validatedMessage.feeToken != address(i_weth)) { - IERC20(validatedMessage.feeToken).approve(getRouter(), fee); - } - - return IRouterClient(getRouter()).ccipSend(destinationChainSelector, validatedMessage); - } - - // We don't want to keep any excess ether in this contract, so we send over the entire address(this).balance as the fee. - // CCIP will revert if the fee is insufficient, so we don't need to check here. - return IRouterClient(getRouter()).ccipSend{value: address(this).balance}(destinationChainSelector, validatedMessage); - } - - /// @notice Validate the message content. - /// @dev Only allows a single token to be sent. Always overwritten to be address(i_weth) - /// and receiver is always msg.sender. - function _validatedMessage( - Client.EVM2AnyMessage calldata message - ) internal view returns (Client.EVM2AnyMessage memory) { - Client.EVM2AnyMessage memory validatedMessage = message; - - if (validatedMessage.tokenAmounts.length != 1) { - revert InvalidTokenAmounts(validatedMessage.tokenAmounts.length); - } - - validatedMessage.data = abi.encode(msg.sender); - validatedMessage.tokenAmounts[0].token = address(i_weth); - - return validatedMessage; - } - - function _validateFeeToken( - Client.EVM2AnyMessage calldata message - ) internal view { - uint256 tokenAmount = message.tokenAmounts[0].amount; - - if (message.feeToken != address(0)) { - // If the fee token is NOT native, then the token amount must be equal to msg.value. - // This is done to ensure that there is no leftover ether in this contract. - if (msg.value != tokenAmount) { - revert TokenAmountNotEqualToMsgValue(tokenAmount, msg.value); - } - } - } - - /// @notice Receive the wrapped ether, unwrap it, and send it to the specified EOA in the data field. - /// @param message The CCIP message containing the wrapped ether amount and the final receiver. - /// @dev The code below should never revert if the message being is valid according - /// to the above _validatedMessage and _validateFeeToken functions. - function _ccipReceive( - Client.Any2EVMMessage memory message - ) internal override { - address receiver = abi.decode(message.data, (address)); - - if (message.destTokenAmounts.length != 1) { - revert InvalidTokenAmounts(message.destTokenAmounts.length); - } - - if (message.destTokenAmounts[0].token != address(i_weth)) { - revert InvalidToken(message.destTokenAmounts[0].token, address(i_weth)); - } - - uint256 tokenAmount = message.destTokenAmounts[0].amount; - i_weth.withdraw(tokenAmount); - - // it is possible that the below call may fail if receiver.code.length > 0 and the contract - // doesn't e.g have a receive() or a fallback() function. - (bool success,) = payable(receiver).call{value: tokenAmount}(""); - if (!success) { - // We have a few options here: - // 1. Revert: this is bad generally because it may mean that these tokens are stuck. - // 2. Store the tokens in a mapping and allow the user to withdraw them with another tx. - // 3. Send WETH to the receiver address. - // We opt for (3) here because at least the receiver will have the funds and can unwrap them if needed. - // However it is worth noting that if receiver is actually a contract AND the contract _cannot_ withdraw - // the WETH, then the WETH will be stuck in this contract. - i_weth.deposit{value: tokenAmount}(); - i_weth.transfer(receiver, tokenAmount); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol deleted file mode 100644 index 3fd3eec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/applications/PingPongDemo.sol +++ /dev/null @@ -1,130 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IRouterClient} from "../interfaces/IRouterClient.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.sol"; -import {CCIPReceiver} from "./CCIPReceiver.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -/// @title PingPongDemo - A simple ping-pong contract for demonstrating cross-chain communication -contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { - event Ping(uint256 pingPongCount); - event Pong(uint256 pingPongCount); - event OutOfOrderExecutionChange(bool isOutOfOrder); - - // Default gas limit used for EVMExtraArgsV2 construction - uint64 private constant DEFAULT_GAS_LIMIT = 200_000; - - // The chain ID of the counterpart ping pong contract - uint64 internal s_counterpartChainSelector; - // The contract address of the counterpart ping pong contract - address internal s_counterpartAddress; - // Pause ping-ponging - bool private s_isPaused; - // The fee token used to pay for CCIP transactions - IERC20 internal s_feeToken; - // Allowing out of order execution - bool private s_outOfOrderExecution; - - constructor(address router, IERC20 feeToken) CCIPReceiver(router) { - s_isPaused = false; - s_feeToken = feeToken; - s_feeToken.approve(address(router), type(uint256).max); - } - - function typeAndVersion() external pure virtual returns (string memory) { - return "PingPongDemo 1.5.0"; - } - - function setCounterpart(uint64 counterpartChainSelector, address counterpartAddress) external onlyOwner { - s_counterpartChainSelector = counterpartChainSelector; - s_counterpartAddress = counterpartAddress; - } - - function startPingPong() external onlyOwner { - s_isPaused = false; - _respond(1); - } - - function _respond( - uint256 pingPongCount - ) internal virtual { - if (pingPongCount & 1 == 1) { - emit Ping(pingPongCount); - } else { - emit Pong(pingPongCount); - } - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(s_counterpartAddress), - data: abi.encode(pingPongCount), - tokenAmounts: new Client.EVMTokenAmount[](0), - extraArgs: Client._argsToBytes( - Client.EVMExtraArgsV2({gasLimit: uint256(DEFAULT_GAS_LIMIT), allowOutOfOrderExecution: s_outOfOrderExecution}) - ), - feeToken: address(s_feeToken) - }); - IRouterClient(getRouter()).ccipSend(s_counterpartChainSelector, message); - } - - function _ccipReceive( - Client.Any2EVMMessage memory message - ) internal override { - uint256 pingPongCount = abi.decode(message.data, (uint256)); - if (!s_isPaused) { - _respond(pingPongCount + 1); - } - } - - ///////////////////////////////////////////////////////////////////// - // Plumbing - ///////////////////////////////////////////////////////////////////// - - function getCounterpartChainSelector() external view returns (uint64) { - return s_counterpartChainSelector; - } - - function setCounterpartChainSelector( - uint64 chainSelector - ) external onlyOwner { - s_counterpartChainSelector = chainSelector; - } - - function getCounterpartAddress() external view returns (address) { - return s_counterpartAddress; - } - - function getFeeToken() external view returns (IERC20) { - return s_feeToken; - } - - function setCounterpartAddress( - address addr - ) external onlyOwner { - s_counterpartAddress = addr; - } - - function isPaused() external view returns (bool) { - return s_isPaused; - } - - function setPaused( - bool pause - ) external onlyOwner { - s_isPaused = pause; - } - - function getOutOfOrderExecution() external view returns (bool) { - return s_outOfOrderExecution; - } - - function setOutOfOrderExecution( - bool outOfOrderExecution - ) external onlyOwner { - s_outOfOrderExecution = outOfOrderExecution; - emit OutOfOrderExecutionChange(outOfOrderExecution); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol deleted file mode 100644 index e66e2f5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/capability/CCIPHome.sol +++ /dev/null @@ -1,624 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {ICapabilitiesRegistry} from "../interfaces/ICapabilitiesRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Internal} from "../libraries/Internal.sol"; - -import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice CCIPHome stores the configuration for the CCIP capability. -/// We have two classes of configuration: chain configuration and DON (in the CapabilitiesRegistry sense) configuration. -/// Each chain will have a single configuration which includes information like the router address. -/// @dev This contract is a state machine with the following states: -/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. -/// [0, 0] -/// -/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. -/// [0, 1] -/// -/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. -/// [1, 0] -/// -/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. -/// [1, 1] -/// -/// The following state transitions are allowed: -/// - Init -> Candidate: setCandidate() -/// - Candidate -> Active: promoteCandidateAndRevokeActive() -/// - Candidate -> Candidate: setCandidate() -/// - Candidate -> Init: revokeCandidate() -/// - Active -> ActiveAndCandidate: setCandidate() -/// - Active -> Init: promoteCandidateAndRevokeActive() -/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() -/// - ActiveAndCandidate -> Active: revokeCandidate() -/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() -/// -/// This means the following calls are not allowed at the following states: -/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. -/// - Init: revokeCandidate(), as there is no config to revoke -/// - Active: revokeCandidate(), as there is no candidate to revoke -/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but -/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable -/// config as candidate and promote that, but fully clearing it is cleaner. -/// -/// ┌─────────────┐ setCandidate ┌─────────────┐ -/// │ ├───────────────────►│ │ setCandidate -/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ -/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ -/// │ │ ┌─────────────────┤ │ -/// └─────────────┘ │ promote- └─────────────┘ -/// ▲ │ Candidate -/// promote- │ │ -/// Candidate │ │ -/// │ │ -/// ┌──────────┴──┐ │ promote- ┌─────────────┐ -/// │ │◄─┘ Candidate OR │ Active & │ setCandidate -/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ -/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ -/// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ -/// -contract CCIPHome is OwnerIsCreator, ITypeAndVersion, ICapabilityConfiguration, IERC165 { - using EnumerableSet for EnumerableSet.UintSet; - - event ChainConfigRemoved(uint64 chainSelector); - event ChainConfigSet(uint64 chainSelector, ChainConfig chainConfig); - event ConfigSet(bytes32 indexed configDigest, uint32 version, OCR3Config config); - event ActiveConfigRevoked(bytes32 indexed configDigest); - event CandidateConfigRevoked(bytes32 indexed configDigest); - event ConfigPromoted(bytes32 indexed configDigest); - - error NodeNotInRegistry(bytes32 p2pId); - error ChainSelectorNotFound(uint64 chainSelector); - error FChainMustBePositive(); - error ChainSelectorNotSet(); - error InvalidPluginType(); - error OfframpAddressCannotBeZero(); - error FChainTooHigh(uint256 fChain, uint256 FRoleDON); - error TooManySigners(); - error FTooHigh(); - error RMNHomeAddressCannotBeZero(); - error InvalidNode(OCR3Node node); - error NotEnoughTransmitters(uint256 got, uint256 minimum); - error OnlyCapabilitiesRegistryCanCall(); - error ZeroAddressNotAllowed(); - error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); - error CanOnlySelfCall(); - error RevokingZeroDigestNotAllowed(); - error NoOpStateTransitionNotAllowed(); - error InvalidSelector(bytes4 selector); - error DONIdMismatch(uint32 callDonId, uint32 capabilityRegistryDonId); - - error InvalidStateTransition( - bytes32 currentActiveDigest, - bytes32 currentCandidateDigest, - bytes32 proposedActiveDigest, - bytes32 proposedCandidateDigest - ); - - /// @notice Represents an oracle node in OCR3 configs part of the role DON. - /// Every configured node should be a signer, but does not have to be a transmitter. - struct OCR3Node { - bytes32 p2pId; // Peer2Peer connection ID of the oracle - bytes signerKey; // On-chain signer public key - bytes transmitterKey; // On-chain transmitter public key. Can be set to empty bytes to represent that the node is a signer but not a transmitter. - } - - /// @notice OCR3 configuration. - /// Note that FRoleDON >= fChain, since FRoleDON represents the role DON, and fChain represents sub-committees. - /// FRoleDON values are typically identical across multiple OCR3 configs since the chains pertain to one role DON, - /// but FRoleDON values can change across OCR3 configs to indicate role DON splits. - struct OCR3Config { - Internal.OCRPluginType pluginType; // ─╮ The plugin that the configuration is for. - uint64 chainSelector; // │ The (remote) chain that the configuration is for. - uint8 FRoleDON; // │ The "big F" parameter for the role DON. - uint64 offchainConfigVersion; // ──────╯ The version of the exec offchain configuration. - bytes offrampAddress; // The remote chain offramp address. - bytes rmnHomeAddress; // The home chain RMN home address. - OCR3Node[] nodes; // Keys & IDs of nodes part of the role DON - bytes offchainConfig; // The offchain configuration for the OCR3 plugin. Protobuf encoded. - } - - struct VersionedConfig { - uint32 version; - bytes32 configDigest; - OCR3Config config; - } - - /// @notice Chain configuration. - /// Changes to chain configuration are detected out-of-band in plugins and decoded offchain. - struct ChainConfig { - bytes32[] readers; // The P2P IDs of the readers for the chain. These IDs must be registered in the capabilities registry. - uint8 fChain; // The fault tolerance parameter of the chain. - bytes config; // The chain configuration. This is kept intentionally opaque so as to add fields in the future if needed. - } - - /// @notice Chain configuration information struct used in applyChainConfigUpdates and getAllChainConfigs. - struct ChainConfigArgs { - uint64 chainSelector; - ChainConfig chainConfig; - } - - string public constant override typeAndVersion = "CCIPHome 1.6.0-dev"; - - /// @dev A prefix added to all config digests that is unique to the implementation - uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000a00..00 - bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); - /// @dev 256 is the hard limit due to the bit encoding of their indexes into a uint256. - uint256 internal constant MAX_NUM_ORACLES = 256; - - /// @notice Used for encoding the config digest prefix - uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 - /// @notice The max number of configs that can be active at the same time. - uint256 private constant MAX_CONCURRENT_CONFIGS = 2; - /// @notice Helper to identify the zero config digest with less casting. - bytes32 private constant ZERO_DIGEST = bytes32(uint256(0)); - - /// @dev The canonical capabilities registry address. - address internal immutable i_capabilitiesRegistry; - - /// @dev chain configuration for each chain that CCIP is deployed on. - mapping(uint64 chainSelector => ChainConfig chainConfig) private s_chainConfigurations; - - /// @dev All chains that are configured. - EnumerableSet.UintSet private s_remoteChainSelectors; - - /// @notice This array holds the configs. - /// @dev A DonID covers a single chain, and the plugin type is used to differentiate between the commit and execution - mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => VersionedConfig[MAX_CONCURRENT_CONFIGS])) private - s_configs; - - /// @notice The total number of configs ever set, used for generating the version of the configs. - /// @dev Used to ensure unique digests across all configurations. - uint32 private s_currentVersion = 0; - /// @notice The index of the active config on a per-don and per-plugin basis. - mapping(uint32 donId => mapping(Internal.OCRPluginType pluginType => uint32)) private s_activeConfigIndexes; - - /// @notice Constructor for the CCIPHome contract takes in the address of the capabilities registry. This address - /// is the only allowed caller to mutate the configuration through beforeCapabilityConfigSet. - constructor( - address capabilitiesRegistry - ) { - if (capabilitiesRegistry == address(0)) { - revert ZeroAddressNotAllowed(); - } - i_capabilitiesRegistry = capabilitiesRegistry; - } - - // ================================================================ - // │ Capability Registry │ - // ================================================================ - - /// @notice Returns the capabilities registry address. - /// @return The capabilities registry address. - function getCapabilityRegistry() external view returns (address) { - return i_capabilitiesRegistry; - } - - /// @inheritdoc IERC165 - /// @dev Required for the capabilities registry to recognize this contract. - function supportsInterface( - bytes4 interfaceId - ) external pure override returns (bool) { - return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - /// @notice Called by the registry prior to the config being set for a particular DON. - /// @dev precondition Requires destination chain config to be set - function beforeCapabilityConfigSet( - bytes32[] calldata, // nodes - bytes calldata update, - // Config count is unused because we don't want to invalidate a config on blue/green promotions so we keep track of - // the actual newly submitted configs instead of the number of config mutations. - uint64, // config count - uint32 donId - ) external override { - if (msg.sender != i_capabilitiesRegistry) { - revert OnlyCapabilitiesRegistryCanCall(); - } - - bytes4 selector = bytes4(update[:4]); - // We only allow self-calls to the following approved methods - if ( - selector != this.setCandidate.selector && selector != this.revokeCandidate.selector - && selector != this.promoteCandidateAndRevokeActive.selector - ) { - revert InvalidSelector(selector); - } - - // We validate that the call contains the correct DON ID. The DON ID is always the first function argument. - uint256 callDonId = abi.decode(update[4:36], (uint256)); - if (callDonId != donId) { - revert DONIdMismatch(uint32(callDonId), donId); - } - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory retData) = address(this).call(update); - // if not successful, revert with the original revert - if (!success) { - assembly { - revert(add(retData, 0x20), returndatasize()) - } - } - } - - /// @inheritdoc ICapabilityConfiguration - /// @dev The CCIP capability will fetch the configuration needed directly from this contract. - /// The offchain syncer will call this function, so its important that it doesn't revert. - function getCapabilityConfiguration( - uint32 /* donId */ - ) external pure override returns (bytes memory configuration) { - return bytes(""); - } - - // ================================================================ - // │ Getters │ - // ================================================================ - - /// @notice Returns the current active and candidate config digests. - /// @dev Can be bytes32(0) if no config has been set yet or it has been revoked. - /// @param donId The key of the plugin to get the config digests for. - /// @return activeConfigDigest The digest of the active config. - /// @return candidateConfigDigest The digest of the candidate config. - function getConfigDigests( - uint32 donId, - Internal.OCRPluginType pluginType - ) public view returns (bytes32 activeConfigDigest, bytes32 candidateConfigDigest) { - return ( - s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest, - s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest - ); - } - - /// @notice Returns the active config digest for for a given key. - /// @param donId The key of the plugin to get the config digests for. - function getActiveDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { - return s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)].configDigest; - } - - /// @notice Returns the candidate config digest for for a given key. - /// @param donId The key of the plugin to get the config digests for. - function getCandidateDigest(uint32 donId, Internal.OCRPluginType pluginType) public view returns (bytes32) { - return s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)].configDigest; - } - - /// @notice The offchain code can use this to fetch an old config which might still be in use by some remotes. Use - /// in case one of the configs is too large to be returnable by one of the other getters. - /// @param donId The unique key for the DON that the configuration applies to. - /// @param configDigest The digest of the config to fetch. - /// @return versionedConfig The config and its version. - /// @return ok True if the config was found, false otherwise. - function getConfig( - uint32 donId, - Internal.OCRPluginType pluginType, - bytes32 configDigest - ) external view returns (VersionedConfig memory versionedConfig, bool ok) { - for (uint256 i = 0; i < MAX_CONCURRENT_CONFIGS; ++i) { - // We never want to return true for a zero digest, even if the caller is asking for it, as this can expose old - // config state that is invalid. - if (s_configs[donId][pluginType][i].configDigest == configDigest && configDigest != ZERO_DIGEST) { - return (s_configs[donId][pluginType][i], true); - } - } - // versionConfig is uninitialized so it contains default values. - return (versionedConfig, false); - } - - /// @notice Returns the active and candidate configuration for a given plugin key. - /// @param donId The unique key for the DON that the configuration applies to. - /// @return activeConfig The active configuration. - /// @return candidateConfig The candidate configuration. - function getAllConfigs( - uint32 donId, - Internal.OCRPluginType pluginType - ) external view returns (VersionedConfig memory activeConfig, VersionedConfig memory candidateConfig) { - VersionedConfig memory storedActiveConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; - if (storedActiveConfig.configDigest != ZERO_DIGEST) { - activeConfig = storedActiveConfig; - } - - VersionedConfig memory storedCandidateConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; - if (storedCandidateConfig.configDigest != ZERO_DIGEST) { - candidateConfig = storedCandidateConfig; - } - - return (activeConfig, candidateConfig); - } - - // ================================================================ - // │ State transitions │ - // ================================================================ - - /// @notice Sets a new config as the candidate config. Does not influence the active config. - /// @param donId The key of the plugin to set the config for. - /// @return newConfigDigest The digest of the new config. - function setCandidate( - uint32 donId, - Internal.OCRPluginType pluginType, - OCR3Config calldata config, - bytes32 digestToOverwrite - ) external returns (bytes32 newConfigDigest) { - _onlySelfCall(); - _validateConfig(config); - - bytes32 existingDigest = getCandidateDigest(donId, pluginType); - - if (existingDigest != digestToOverwrite) { - revert ConfigDigestMismatch(existingDigest, digestToOverwrite); - } - - // are we going to overwrite a config? If so, emit an event. - if (existingDigest != ZERO_DIGEST) { - emit CandidateConfigRevoked(digestToOverwrite); - } - - uint32 newVersion = ++s_currentVersion; - newConfigDigest = _calculateConfigDigest(donId, pluginType, abi.encode(config), newVersion); - - VersionedConfig storage existingConfig = s_configs[donId][pluginType][_getCandidateIndex(donId, pluginType)]; - existingConfig.configDigest = newConfigDigest; - existingConfig.version = newVersion; - existingConfig.config = config; - - emit ConfigSet(newConfigDigest, newVersion, config); - - return newConfigDigest; - } - - /// @notice Revokes a specific config by digest. - /// @param donId The key of the plugin to revoke the config for. - /// @param configDigest The digest of the config to revoke. This is done to prevent accidental revokes. - function revokeCandidate(uint32 donId, Internal.OCRPluginType pluginType, bytes32 configDigest) external { - _onlySelfCall(); - - if (configDigest == ZERO_DIGEST) { - revert RevokingZeroDigestNotAllowed(); - } - - uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); - if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != configDigest) { - revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, configDigest); - } - - emit CandidateConfigRevoked(configDigest); - // Delete only the digest, as that's what's used to determine if a config is active. This means the actual - // config stays in storage which should significantly reduce the gas cost of overwriting that storage space in - // the future. - delete s_configs[donId][pluginType][candidateConfigIndex].configDigest; - } - - /// @notice Promotes the candidate config to the active config and revokes the active config. - /// @param donId The key of the plugin to promote the config for. - /// @param digestToPromote The digest of the config to promote. - function promoteCandidateAndRevokeActive( - uint32 donId, - Internal.OCRPluginType pluginType, - bytes32 digestToPromote, - bytes32 digestToRevoke - ) external { - _onlySelfCall(); - - if (digestToPromote == ZERO_DIGEST && digestToRevoke == ZERO_DIGEST) { - revert NoOpStateTransitionNotAllowed(); - } - - uint256 candidateConfigIndex = _getCandidateIndex(donId, pluginType); - if (s_configs[donId][pluginType][candidateConfigIndex].configDigest != digestToPromote) { - revert ConfigDigestMismatch(s_configs[donId][pluginType][candidateConfigIndex].configDigest, digestToPromote); - } - - VersionedConfig storage activeConfig = s_configs[donId][pluginType][_getActiveIndex(donId, pluginType)]; - if (activeConfig.configDigest != digestToRevoke) { - revert ConfigDigestMismatch(activeConfig.configDigest, digestToRevoke); - } - - delete activeConfig.configDigest; - - s_activeConfigIndexes[donId][pluginType] ^= 1; - if (digestToRevoke != ZERO_DIGEST) { - emit ActiveConfigRevoked(digestToRevoke); - } - emit ConfigPromoted(digestToPromote); - } - - /// @notice Calculates the config digest for a given plugin key, static config, and version. - /// @param donId The key of the plugin to calculate the digest for. - /// @param staticConfig The static part of the config. - /// @param version The version of the config. - /// @return The calculated config digest. - function _calculateConfigDigest( - uint32 donId, - Internal.OCRPluginType pluginType, - bytes memory staticConfig, - uint32 version - ) internal view returns (bytes32) { - return bytes32( - (PREFIX & PREFIX_MASK) - | ( - uint256( - keccak256( - bytes.concat( - abi.encode(bytes32("EVM"), block.chainid, address(this), donId, pluginType, version), staticConfig - ) - ) - ) & ~PREFIX_MASK - ) - ); - } - - function _getActiveIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { - return s_activeConfigIndexes[donId][pluginType]; - } - - function _getCandidateIndex(uint32 donId, Internal.OCRPluginType pluginType) private view returns (uint32) { - return s_activeConfigIndexes[donId][pluginType] ^ 1; - } - - // ================================================================ - // │ Validation │ - // ================================================================ - - function _validateConfig( - OCR3Config memory cfg - ) internal view { - if (cfg.chainSelector == 0) revert ChainSelectorNotSet(); - if (cfg.pluginType != Internal.OCRPluginType.Commit && cfg.pluginType != Internal.OCRPluginType.Execution) { - revert InvalidPluginType(); - } - if (cfg.offrampAddress.length == 0 || keccak256(cfg.offrampAddress) == EMPTY_ENCODED_ADDRESS_HASH) { - revert OfframpAddressCannotBeZero(); - } - if (cfg.rmnHomeAddress.length == 0 || keccak256(cfg.rmnHomeAddress) == EMPTY_ENCODED_ADDRESS_HASH) { - revert RMNHomeAddressCannotBeZero(); - } - if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); - - // fChain cannot exceed FRoleDON, since it is a subcommittee in the larger DON - uint256 FRoleDON = cfg.FRoleDON; - uint256 fChain = s_chainConfigurations[cfg.chainSelector].fChain; - // fChain > 0 is enforced in applyChainConfigUpdates, and the presence of a chain config is checked above - // FRoleDON != 0 because FRoleDON >= fChain is enforced here - if (fChain > FRoleDON) { - revert FChainTooHigh(fChain, FRoleDON); - } - - // len(nodes) >= 3 * FRoleDON + 1 - // len(nodes) == numberOfSigners - uint256 numberOfNodes = cfg.nodes.length; - if (numberOfNodes > MAX_NUM_ORACLES) revert TooManySigners(); - if (numberOfNodes <= 3 * FRoleDON) revert FTooHigh(); - - uint256 nonZeroTransmitters = 0; - bytes32[] memory p2pIds = new bytes32[](numberOfNodes); - for (uint256 i = 0; i < numberOfNodes; ++i) { - OCR3Node memory node = cfg.nodes[i]; - - // 3 * fChain + 1 <= nonZeroTransmitters <= 3 * FRoleDON + 1 - // Transmitters can be set to 0 since there can be more signers than transmitters, - if (node.transmitterKey.length != 0) { - nonZeroTransmitters++; - } - - // Signer key and p2pIds must always be present - if (node.signerKey.length == 0 || node.p2pId == bytes32(0)) { - revert InvalidNode(node); - } - - p2pIds[i] = node.p2pId; - } - - // We check for chain config presence above, so fChain here must be non-zero. fChain <= FRoleDON due to the checks above. - // There can be less transmitters than signers - so they can be set to zero (which indicates that a node is a signer, but not a transmitter). - uint256 minTransmittersLength = 3 * fChain + 1; - if (nonZeroTransmitters < minTransmittersLength) { - revert NotEnoughTransmitters(nonZeroTransmitters, minTransmittersLength); - } - - // Check that the readers are in the capabilities registry. - _ensureInRegistry(p2pIds); - } - - function _onlySelfCall() internal view { - if (msg.sender != address(this)) { - revert CanOnlySelfCall(); - } - } - - // ================================================================ - // │ Chain Configuration │ - // ================================================================ - - /// @notice Returns the total number of chains configured. - /// @return The total number of chains configured. - function getNumChainConfigurations() external view returns (uint256) { - return s_remoteChainSelectors.length(); - } - - /// @notice Returns all the chain configurations. - /// @param pageIndex The page index. - /// @param pageSize The page size. - /// @return paginatedChainConfigs chain configurations. - function getAllChainConfigs(uint256 pageIndex, uint256 pageSize) external view returns (ChainConfigArgs[] memory) { - uint256 numberOfChains = s_remoteChainSelectors.length(); - uint256 startIndex = pageIndex * pageSize; - - if (pageSize == 0 || startIndex >= numberOfChains) { - return new ChainConfigArgs[](0); // Return an empty array if pageSize is 0 or pageIndex is out of bounds - } - - uint256 endIndex = startIndex + pageSize; - if (endIndex > numberOfChains) { - endIndex = numberOfChains; - } - - ChainConfigArgs[] memory paginatedChainConfigs = new ChainConfigArgs[](endIndex - startIndex); - - uint256[] memory chainSelectors = s_remoteChainSelectors.values(); - for (uint256 i = startIndex; i < endIndex; ++i) { - uint64 chainSelector = uint64(chainSelectors[i]); - paginatedChainConfigs[i - startIndex] = - ChainConfigArgs({chainSelector: chainSelector, chainConfig: s_chainConfigurations[chainSelector]}); - } - - return paginatedChainConfigs; - } - - /// @notice Sets and/or removes chain configurations. - /// Does not validate that fChain <= FRoleDON and relies on OCR3Configs to be changed in case fChain becomes larger than the FRoleDON value. - /// @param chainSelectorRemoves The chain configurations to remove. - /// @param chainConfigAdds The chain configurations to add. - function applyChainConfigUpdates( - uint64[] calldata chainSelectorRemoves, - ChainConfigArgs[] calldata chainConfigAdds - ) external onlyOwner { - // Process removals first. - for (uint256 i = 0; i < chainSelectorRemoves.length; ++i) { - // check if the chain selector is in s_remoteChainSelectors first. - if (!s_remoteChainSelectors.contains(chainSelectorRemoves[i])) { - revert ChainSelectorNotFound(chainSelectorRemoves[i]); - } - - delete s_chainConfigurations[chainSelectorRemoves[i]]; - s_remoteChainSelectors.remove(chainSelectorRemoves[i]); - - emit ChainConfigRemoved(chainSelectorRemoves[i]); - } - - // Process additions next. - for (uint256 i = 0; i < chainConfigAdds.length; ++i) { - ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; - uint64 chainSelector = chainConfigAdds[i].chainSelector; - - // Verify that the provided readers are present in the capabilities registry. - _ensureInRegistry(chainConfig.readers); - - // Verify that fChain is positive. - if (chainConfig.fChain == 0) { - revert FChainMustBePositive(); - } - - s_chainConfigurations[chainSelector] = chainConfig; - s_remoteChainSelectors.add(chainSelector); - - emit ChainConfigSet(chainSelector, chainConfig); - } - } - - /// @notice Helper function to ensure that a node is in the capabilities registry. - /// @param p2pIds The P2P IDs of the node to check. - function _ensureInRegistry( - bytes32[] memory p2pIds - ) internal view { - for (uint256 i = 0; i < p2pIds.length; ++i) { - // TODO add a method that does the validation in the ICapabilitiesRegistry contract - if (ICapabilitiesRegistry(i_capabilitiesRegistry).getNode(p2pIds[i]).p2pId == bytes32("")) { - revert NodeNotInRegistry(p2pIds[i]); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol deleted file mode 100644 index 2a38d82..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Client} from "../libraries/Client.sol"; - -/// @notice Application contracts that intend to receive messages from -/// the router should implement this interface. -interface IAny2EVMMessageReceiver { - /// @notice Called by the Router to deliver a message. - /// If this reverts, any token transfers also revert. The message - /// will move to a FAILED state and become available for manual execution. - /// @param message CCIP Message - /// @dev Note ensure you check the msg.sender is the OffRampRouter - function ccipReceive( - Client.Any2EVMMessage calldata message - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol deleted file mode 100644 index f18c6a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IAny2EVMOffRamp.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IAny2EVMOffRamp { - /// @notice Returns the the current nonce for a receiver. - /// @param sender The sender address - /// @return nonce The nonce value belonging to the sender address. - function getSenderNonce( - address sender - ) external view returns (uint64 nonce); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol deleted file mode 100644 index d036642..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICapabilitiesRegistry.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -interface ICapabilitiesRegistry { - struct NodeInfo { - /// @notice The id of the node operator that manages this node - uint32 nodeOperatorId; - /// @notice The number of times the node's configuration has been updated - uint32 configCount; - /// @notice The ID of the Workflow DON that the node belongs to. A node can - /// only belong to one DON that accepts Workflows. - uint32 workflowDONId; - /// @notice The signer address for application-layer message verification. - bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. - /// This key is guaranteed to be unique in the CapabilitiesRegistry. It is - /// used to identify a node in the the P2P network. - bytes32 p2pId; - /// @notice Public key used to encrypt secrets for this node - bytes32 encryptionPublicKey; - /// @notice The list of hashed capability IDs supported by the node - bytes32[] hashedCapabilityIds; - /// @notice The list of capabilities DON Ids supported by the node. A node - /// can belong to multiple capabilities DONs. This list does not include a - /// Workflow DON id if the node belongs to one. - uint256[] capabilitiesDONIds; - } - - /// @notice Gets a node's data - /// @param p2pId The P2P ID of the node to query for - /// @return NodeInfo The node data - function getNode( - bytes32 p2pId - ) external view returns (NodeInfo memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol deleted file mode 100644 index 1183eb2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ICommitStore.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface ICommitStore { - /// @notice Returns timestamp of when root was accepted or 0 if verification fails. - /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, - /// proofs and proofFlagBits being used to get the root of the inner tree. - /// This root is then used as the singular leaf of the outer tree. - function verify( - bytes32[] calldata hashedLeaves, - bytes32[] calldata proofs, - uint256 proofFlagBits - ) external view returns (uint256 timestamp); - - /// @notice Returns the expected next sequence number - function getExpectedNextSequenceNumber() external view returns (uint64 sequenceNumber); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol deleted file mode 100644 index c2d0d6c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IEVM2AnyOnRampClient} from "./IEVM2AnyOnRampClient.sol"; - -interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient { - /// @notice Gets the next sequence number to be used in the onRamp - /// @return the next sequence number to be used - function getExpectedNextSequenceNumber() external view returns (uint64); - - /// @notice Get the next nonce for a given sender - /// @param sender The sender to get the nonce for - /// @return nonce The next nonce for the sender - function getSenderNonce( - address sender - ) external view returns (uint64 nonce); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol deleted file mode 100644 index d2fe347..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRampClient.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IPoolV1} from "./IPool.sol"; - -import {Client} from "../libraries/Client.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -interface IEVM2AnyOnRampClient { - /// @notice Get the fee for a given ccip message - /// @param destChainSelector The destination chain selector - /// @param message The message to calculate the cost for - /// @return fee The calculated fee - function getFee(uint64 destChainSelector, Client.EVM2AnyMessage calldata message) external view returns (uint256 fee); - - /// @notice Get the pool for a specific token - /// @param destChainSelector The destination chain selector - /// @param sourceToken The source chain token to get the pool for - /// @return pool Token pool - function getPoolBySourceToken(uint64 destChainSelector, IERC20 sourceToken) external view returns (IPoolV1); - - /// @notice Gets a list of all supported source chain tokens. - /// @param destChainSelector The destination chain selector - /// @return tokens The addresses of all tokens that this onRamp supports the given destination chain - function getSupportedTokens( - uint64 destChainSelector - ) external view returns (address[] memory tokens); - - /// @notice Send a message to the remote chain - /// @dev only callable by the Router - /// @dev approve() must have already been called on the token using the this ramp address as the spender. - /// @dev if the contract is paused, this function will revert. - /// @param destChainSelector The destination chain selector - /// @param message Message struct to send - /// @param feeTokenAmount Amount of fee tokens for payment - /// @param originalSender The original initiator of the CCIP request - /// @return messageId The message id - function forwardFromRouter( - uint64 destChainSelector, - Client.EVM2AnyMessage memory message, - uint256 feeTokenAmount, - address originalSender - ) external returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol deleted file mode 100644 index 84d4304..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {IPriceRegistry} from "./IPriceRegistry.sol"; - -interface IFeeQuoter is IPriceRegistry { - /// @notice Validates the ccip message & returns the fee - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getValidatedFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount); - - /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels - /// @notice Validates pool return data - /// @param destChainSelector destination chain selector to process - /// @param feeToken Fee token address used to pay for message fees - /// @param feeTokenAmount Fee token amount - /// @param extraArgs Message extra args that were passed in by the client - /// @param onRampTokenTransfers Token amounts with populated pool return data - /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - /// @return msgFeeJuels message fee in juels - /// @return isOutOfOrderExecution true if the message should be executed out of order - /// @return convertedExtraArgs extra args converted to the latest family-specific args version - /// @return destExecDataPerToken Destination chain execution data - function processMessageArgs( - uint64 destChainSelector, - address feeToken, - uint256 feeTokenAmount, - bytes memory extraArgs, - Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, - Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) - external - view - returns ( - uint256 msgFeeJuels, - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - bytes[] memory destExecDataPerToken - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol deleted file mode 100644 index d83a1f3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IGetCCIPAdmin.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IGetCCIPAdmin { - /// @notice Returns the admin of the token. - /// @dev This method is named to never conflict with existing methods. - function getCCIPAdmin() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol deleted file mode 100644 index 0432a22..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Client} from "../libraries/Client.sol"; - -/// @notice Interface for plug-in message hook contracts that intercept OffRamp & OnRamp messages -/// and perform validations / state changes on top of the messages. The interceptor functions are expected to -/// revert on validation failures. -interface IMessageInterceptor { - /// @notice Common error that can be thrown on validation failures and used by consumers - /// @param errorReason abi encoded revert reason - error MessageValidationError(bytes errorReason); - - /// @notice Intercepts & validates the given OffRamp message. Reverts on validation failure - /// @param message to validate - function onInboundMessage( - Client.Any2EVMMessage memory message - ) external; - - /// @notice Intercepts & validates the given OnRamp message. Reverts on validation failure - /// @param destChainSelector remote destination chain selector where the message is being sent to - /// @param message to validate - function onOutboundMessage(uint64 destChainSelector, Client.EVM2AnyMessage memory message) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol deleted file mode 100644 index 3a6eff6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/INonceManager.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice Contract interface that allows managing sender nonces -interface INonceManager { - /// @notice Increments the outbound nonce for a given sender on a given destination chain. - /// @param destChainSelector The destination chain selector. - /// @param sender The sender address. - /// @return incrementedOutboundNonce The new outbound nonce. - function getIncrementedOutboundNonce(uint64 destChainSelector, address sender) external returns (uint64); - - /// @notice Increments the inbound nonce for a given sender on a given source chain. - /// @notice The increment is only applied if the resulting nonce matches the expectedNonce. - /// @param sourceChainSelector The destination chain selector. - /// @param expectedNonce The expected inbound nonce. - /// @param sender The encoded sender address. - /// @return incremented True if the nonce was incremented, false otherwise. - function incrementInboundNonce( - uint64 sourceChainSelector, - uint64 expectedNonce, - bytes calldata sender - ) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol deleted file mode 100644 index ccb1039..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IOwner.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IOwner { - /// @notice Returns the owner of the contract. - /// @dev This method is named to match with the OpenZeppelin Ownable contract. - function owner() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol deleted file mode 100644 index 3545e57..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPool.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Pool} from "../libraries/Pool.sol"; - -import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -/// @notice Shared public interface for multiple V1 pool types. -/// Each pool type handles a different child token model (lock/unlock, mint/burn.) -interface IPoolV1 is IERC165 { - /// @notice Lock tokens into the pool or burn the tokens. - /// @param lockOrBurnIn Encoded data fields for the processing of tokens on the source chain. - /// @return lockOrBurnOut Encoded data fields for the processing of tokens on the destination chain. - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); - - /// @notice Releases or mints tokens to the receiver address. - /// @param releaseOrMintIn All data required to release or mint tokens. - /// @return releaseOrMintOut The amount of tokens released or minted on the local chain, denominated - /// in the local token's decimals. - /// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number - /// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts. - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external returns (Pool.ReleaseOrMintOutV1 memory); - - /// @notice Checks whether a remote chain is supported in the token pool. - /// @param remoteChainSelector The selector of the remote chain. - /// @return true if the given chain is a permissioned remote chain. - function isSupportedChain( - uint64 remoteChainSelector - ) external view returns (bool); - - /// @notice Returns if the token pool supports the given token. - /// @param token The address of the token. - /// @return true if the token is supported by the pool. - function isSupportedToken( - address token - ) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol deleted file mode 100644 index d8a2f15..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPoolPriorTo1_5.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -// Shared public interface for multiple pool types. -// Each pool type handles a different child token model (lock/unlock, mint/burn.) -interface IPoolPriorTo1_5 { - /// @notice Lock tokens into the pool or burn the tokens. - /// @param originalSender Original sender of the tokens. - /// @param receiver Receiver of the tokens on destination chain. - /// @param amount Amount to lock or burn. - /// @param remoteChainSelector Destination chain Id. - /// @param extraArgs Additional data passed in by sender for lockOrBurn processing - /// in custom pools on source chain. - /// @return retData Optional field that contains bytes. Unused for now but already - /// implemented to allow future upgrades while preserving the interface. - function lockOrBurn( - address originalSender, - bytes calldata receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes calldata extraArgs - ) external returns (bytes memory); - - /// @notice Releases or mints tokens to the receiver address. - /// @param originalSender Original sender of the tokens. - /// @param receiver Receiver of the tokens. - /// @param amount Amount to release or mint. - /// @param remoteChainSelector Source chain Id. - /// @param extraData Additional data supplied offchain for releaseOrMint processing in - /// custom pools on dest chain. This could be an attestation that was retrieved through a - /// third party API. - /// @dev offchainData can come from any untrusted source. - function releaseOrMint( - bytes memory originalSender, - address receiver, - uint256 amount, - uint64 remoteChainSelector, - bytes memory extraData - ) external; - - /// @notice Gets the IERC20 token that this pool can lock or burn. - /// @return token The IERC20 token representation. - function getToken() external view returns (IERC20 token); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol deleted file mode 100644 index b20c1b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Internal} from "../libraries/Internal.sol"; - -interface IPriceRegistry { - /// @notice Update the price for given tokens and gas prices for given chains. - /// @param priceUpdates The price updates to apply. - function updatePrices( - Internal.PriceUpdates memory priceUpdates - ) external; - - /// @notice Get the `tokenPrice` for a given token. - /// @param token The token to get the price for. - /// @return tokenPrice The tokenPrice for the given token. - function getTokenPrice( - address token - ) external view returns (Internal.TimestampedPackedUint224 memory); - - /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. - /// @param token The token to get the price for. - /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. - function getValidatedTokenPrice( - address token - ) external view returns (uint224); - - /// @notice Get the `tokenPrice` for an array of tokens. - /// @param tokens The tokens to get prices for. - /// @return tokenPrices The tokenPrices for the given tokens. - function getTokenPrices( - address[] calldata tokens - ) external view returns (Internal.TimestampedPackedUint224[] memory); - - /// @notice Get an encoded `gasPrice` for a given destination chain ID. - /// The 224-bit result encodes necessary gas price components. - /// On L1 chains like Ethereum or Avax, the only component is the gas price. - /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. - /// On future chains, there could be more or differing price components. - /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. - /// @param destChainSelector The destination chain to get the price for. - /// @return gasPrice The encoded gasPrice for the given destination chain ID. - function getDestinationChainGasPrice( - uint64 destChainSelector - ) external view returns (Internal.TimestampedPackedUint224 memory); - - /// @notice Gets the fee token price and the gas price, both denominated in dollars. - /// @param token The source token to get the price for. - /// @param destChainSelector The destination chain to get the gas price for. - /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. - /// @return gasPrice The price of gas in 1e18 dollars per base unit. - function getTokenAndGasPrices( - address token, - uint64 destChainSelector - ) external view returns (uint224 tokenPrice, uint224 gasPrice); - - /// @notice Convert a given token amount to target token amount. - /// @param fromToken The given token address. - /// @param fromTokenAmount The given token amount. - /// @param toToken The target token address. - /// @return toTokenAmount The target token amount. - function convertTokenAmount( - address fromToken, - uint256 fromTokenAmount, - address toToken - ) external view returns (uint256 toTokenAmount); - - /// @notice Get the list of fee tokens. - /// @return feeTokens The tokens set as fee tokens. - function getFeeTokens() external view returns (address[] memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol deleted file mode 100644 index 4bd8f83..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMN.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. -interface IRMN { - /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. - struct TaggedRoot { - address commitStore; - bytes32 root; - } - - /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. - function isBlessed( - TaggedRoot calldata taggedRoot - ) external view returns (bool); - - /// @notice Iff there is an active global or legacy curse, this function returns true. - function isCursed() external view returns (bool); - - /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true. - /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). - function isCursed( - bytes16 subject - ) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol deleted file mode 100644 index 3754a2f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRMNRemote.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Internal} from "../libraries/Internal.sol"; - -/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. -interface IRMNRemote { - /// @notice signature components from RMN nodes - struct Signature { - bytes32 r; - bytes32 s; - } - - /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport - /// @param offRampAddress is not inferred by msg.sender, in case the call is made through ARMProxy - /// @param merkleRoots must be well formed, and is a representation of the CommitReport received from the oracles - /// @param signatures rmnNodes ECDSA sigs, only r & s, must be sorted in ascending order by signer address - /// @param rawVs rmnNodes ECDSA sigs, part v bitmap - /// @dev Will revert if verification fails - function verify( - address offRampAddress, - Internal.MerkleRoot[] memory merkleRoots, - Signature[] memory signatures, - uint256 rawVs - ) external view; - - /// @notice gets the current set of cursed subjects - /// @return subjects the list of cursed subjects - function getCursedSubjects() external view returns (bytes16[] memory subjects); - - /// @notice If there is an active global or legacy curse, this function returns true. - /// @return bool true if there is an active global curse - function isCursed() external view returns (bool); - - /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. - /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). - /// @return bool true if the provided subject is cured *or* if there is an active global curse - function isCursed( - bytes16 subject - ) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol deleted file mode 100644 index d8f19bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouter.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Client} from "../libraries/Client.sol"; - -interface IRouter { - error OnlyOffRamp(); - - /// @notice Route the message to its intended receiver contract. - /// @param message Client.Any2EVMMessage struct. - /// @param gasForCallExactCheck of params for exec - /// @param gasLimit set of params for exec - /// @param receiver set of params for exec - /// @dev if the receiver is a contracts that signals support for CCIP execution through EIP-165. - /// the contract is called. If not, only tokens are transferred. - /// @return success A boolean value indicating whether the ccip message was received without errors. - /// @return retBytes A bytes array containing return data form CCIP receiver. - /// @return gasUsed the gas used by the external customer call. Does not include any overhead. - function routeMessage( - Client.Any2EVMMessage calldata message, - uint16 gasForCallExactCheck, - uint256 gasLimit, - address receiver - ) external returns (bool success, bytes memory retBytes, uint256 gasUsed); - - /// @notice Returns the configured onramp for a specific destination chain. - /// @param destChainSelector The destination chain Id to get the onRamp for. - /// @return onRampAddress The address of the onRamp. - function getOnRamp( - uint64 destChainSelector - ) external view returns (address onRampAddress); - - /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. - /// @param sourceChainSelector The source chain selector to check. - /// @param offRamp The address of the offRamp to check. - function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool isOffRamp); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol deleted file mode 100644 index 36218b3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IRouterClient.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Client} from "../libraries/Client.sol"; - -interface IRouterClient { - error UnsupportedDestinationChain(uint64 destChainSelector); - error InsufficientFeeTokenAmount(); - error InvalidMsgValue(); - - /// @notice Checks if the given chain ID is supported for sending/receiving. - /// @param destChainSelector The chain to check. - /// @return supported is true if it is supported, false if not. - function isChainSupported( - uint64 destChainSelector - ) external view returns (bool supported); - - /// @param destinationChainSelector The destination chainSelector - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return fee returns execution fee for the message - /// delivery to destination chain, denominated in the feeToken specified in the message. - /// @dev Reverts with appropriate reason upon invalid message. - function getFee( - uint64 destinationChainSelector, - Client.EVM2AnyMessage memory message - ) external view returns (uint256 fee); - - /// @notice Request a message to be sent to the destination chain - /// @param destinationChainSelector The destination chain ID - /// @param message The cross-chain CCIP message including data and/or tokens - /// @return messageId The message ID - /// @dev Note if msg.value is larger than the required fee (from getFee) we accept - /// the overpayment with no refund. - /// @dev Reverts with appropriate reason upon invalid message. - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external payable returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol deleted file mode 100644 index 04bacba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/ITokenAdminRegistry.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -interface ITokenAdminRegistry { - /// @notice Returns the pool for the given token. - function getPool( - address token - ) external view returns (address); - - /// @notice Proposes an administrator for the given token as pending administrator. - /// @param localToken The token to register the administrator for. - /// @param administrator The administrator to register. - function proposeAdministrator(address localToken, address administrator) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol deleted file mode 100644 index f4f8243..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/IWrappedNative.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -interface IWrappedNative is IERC20 { - function deposit() external payable; - - function withdraw( - uint256 wad - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol deleted file mode 100644 index b0dad9a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/automation/ILinkAvailable.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice Implement this contract so that a keeper-compatible contract can monitor -/// and fund the implementation contract with LINK if it falls below a defined threshold. -interface ILinkAvailable { - function linkAvailableForPayment() external view returns (int256 availableBalance); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol deleted file mode 100644 index a5792f1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/interfaces/encodingutils/ICCIPEncodingUtils.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {CCIPHome} from "../../capability/CCIPHome.sol"; - -import {OffRamp} from "../../offRamp/OffRamp.sol"; -import {RMNRemote} from "../../rmn/RMNRemote.sol"; - -/// @dev this file exposes structs that are otherwise internal to the CCIP codebase -/// doing this allows those structs to be encoded and decoded with type safety in offchain code -/// and tests because generated wrappers are available -interface ICCIPEncodingUtils { - /// @dev the RMN Report struct is used in integration / E2E tests - function exposeRmnReport(bytes32 rmnReportVersion, RMNRemote.Report memory rmnReport) external; - - /// @dev the OCR3Config Config struct is used in integration / E2E tests - function exposeOCR3Config( - CCIPHome.OCR3Config[] calldata config - ) external view returns (bytes memory); - - /// @dev used to encode commit reports for onchain transmission. - function exposeCommitReport( - OffRamp.CommitReport memory commitReport - ) external view returns (bytes memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol deleted file mode 100644 index de1f6f1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Client.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// End consumer library. -library Client { - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct EVMTokenAmount { - address token; // token address on the local chain. - uint256 amount; // Amount of tokens. - } - - struct Any2EVMMessage { - bytes32 messageId; // MessageId corresponding to ccipSend on source. - uint64 sourceChainSelector; // Source chain selector. - bytes sender; // abi.decode(sender) if coming from an EVM chain. - bytes data; // payload sent in original message. - EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation. - } - - // If extraArgs is empty bytes, the default is 200k gas limit. - struct EVM2AnyMessage { - bytes receiver; // abi.encode(receiver address) for dest EVM chains - bytes data; // Data payload - EVMTokenAmount[] tokenAmounts; // Token transfers - address feeToken; // Address of feeToken. address(0) means you will send msg.value. - bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV2) - } - - // bytes4(keccak256("CCIP EVMExtraArgsV1")); - bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; - - struct EVMExtraArgsV1 { - uint256 gasLimit; - } - - function _argsToBytes( - EVMExtraArgsV1 memory extraArgs - ) internal pure returns (bytes memory bts) { - return abi.encodeWithSelector(EVM_EXTRA_ARGS_V1_TAG, extraArgs); - } - - // bytes4(keccak256("CCIP EVMExtraArgsV2")); - bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; - - /// @param gasLimit: gas limit for the callback on the destination chain. - /// @param allowOutOfOrderExecution: if true, it indicates that the message can be executed in any order relative to other messages from the same sender. - /// This value's default varies by chain. On some chains, a particular value is enforced, meaning if the expected value - /// is not set, the message request will revert. - struct EVMExtraArgsV2 { - uint256 gasLimit; - bool allowOutOfOrderExecution; - } - - function _argsToBytes( - EVMExtraArgsV2 memory extraArgs - ) internal pure returns (bytes memory bts) { - return abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol deleted file mode 100644 index 7e58c96..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Internal.sol +++ /dev/null @@ -1,275 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; - -// Library for CCIP internal definitions common to multiple contracts. -library Internal { - error InvalidEVMAddress(bytes encodedAddress); - - /// @dev The minimum amount of gas to perform the call with exact gas. - /// We include this in the offramp so that we can redeploy to adjust it - /// should a hardfork change the gas costs of relevant opcodes in callWithExactGas. - uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - // @dev We limit return data to a selector plus 4 words. This is to avoid - // malicious contracts from returning large amounts of data and causing - // repeated out-of-gas scenarios. - uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32; - /// @dev The expected number of bytes returned by the balanceOf function. - uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32; - - /// @notice A collection of token price and gas price updates. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct PriceUpdates { - TokenPriceUpdate[] tokenPriceUpdates; - GasPriceUpdate[] gasPriceUpdates; - } - - /// @notice Token price in USD. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct TokenPriceUpdate { - address sourceToken; // Source token - uint224 usdPerToken; // 1e18 USD per 1e18 of the smallest token denomination. - } - - /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct GasPriceUpdate { - uint64 destChainSelector; // Destination chain selector - uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas - } - - /// @notice A timestamped uint224 value that can contain several tightly packed fields. - struct TimestampedPackedUint224 { - uint224 value; // ──────╮ Value in uint224, packed. - uint32 timestamp; // ───╯ Timestamp of the most recent price update. - } - - /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices. - /// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits. - /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning. - uint8 public constant GAS_PRICE_BITS = 112; - - struct SourceTokenData { - // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be - // relied upon by the destination pool to validate the source pool. - bytes sourcePoolAddress; - // The address of the destination token, abi encoded in the case of EVM chains - // This value is UNTRUSTED as any pool owner can return whatever value they want. - bytes destTokenAddress; - // Optional pool data to be transferred to the destination chain. Be default this is capped at - // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead - // has to be set for the specific token. - bytes extraData; - uint32 destGasAmount; // The amount of gas available for the releaseOrMint and balanceOf calls on the offRamp - } - - /// @notice Report that is submitted by the execution DON at the execution phase. (including chain selector data) - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct ExecutionReport { - uint64 sourceChainSelector; // Source chain selector for which the report is submitted - Any2EVMRampMessage[] messages; - // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token - bytes[][] offchainTokenData; - bytes32[] proofs; - uint256 proofFlagBits; - } - - /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays (data, receiver and tokenAmounts). - /// Each variable array takes 1 more slot to store its length. - /// When abi encoded, excluding array contents, - /// Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each. - /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14. - /// The fixed bytes does not cover struct data (this is represented by MESSAGE_FIXED_BYTES_PER_TOKEN) - uint256 public constant MESSAGE_FIXED_BYTES = 32 * 14; - - /// @dev Each token transfer adds 1 RampTokenAmount - /// RampTokenAmount has 5 fields, 2 of which are bytes type, 1 Address, 1 uint256 and 1 uint32. - /// Each bytes type takes 1 slot for length, 1 slot for data and 1 slot for the offset. - /// address - /// uint256 amount takes 1 slot. - /// uint32 destGasAmount takes 1 slot. - uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((2 * 3) + 3); - - bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); - bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1"); - - /// @dev Used to hash messages for multi-lane family-agnostic OffRamps. - /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId - /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage) - /// @param original OffRamp message to hash - /// @param metadataHash Hash preimage to ensure global uniqueness - /// @return hashedMessage hashed message as a keccak256 - function _hash(Any2EVMRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { - // Fixed-size message fields are included in nested hash to reduce stack pressure. - // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. - return keccak256( - abi.encode( - MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, - metadataHash, - keccak256( - abi.encode( - original.header.messageId, - original.receiver, - original.header.sequenceNumber, - original.gasLimit, - original.header.nonce - ) - ), - keccak256(original.sender), - keccak256(original.data), - keccak256(abi.encode(original.tokenAmounts)) - ) - ); - } - - function _hash(EVM2AnyRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { - // Fixed-size message fields are included in nested hash to reduce stack pressure. - // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. - return keccak256( - abi.encode( - MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, - metadataHash, - keccak256( - abi.encode( - original.sender, - original.header.sequenceNumber, - original.header.nonce, - original.feeToken, - original.feeTokenAmount - ) - ), - keccak256(original.receiver), - keccak256(original.data), - keccak256(abi.encode(original.tokenAmounts)), - keccak256(original.extraArgs) - ) - ); - } - - /// @dev We disallow the first 1024 addresses to avoid calling into a range known for hosting precompiles. Calling - /// into precompiles probably won't cause any issues, but to be safe we can disallow this range. It is extremely - /// unlikely that anyone would ever be able to generate an address in this range. There is no official range of - /// precompiles, but EIP-7587 proposes to reserve the range 0x100 to 0x1ff. Our range is more conservative, even - /// though it might not be exhaustive for all chains, which is OK. We also disallow the zero address, which is a - /// common practice. - uint256 public constant PRECOMPILE_SPACE = 1024; - - /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the - /// address is within the EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which - /// we can catch and handle more gracefully than a revert from abi.decode. - /// @return The address if it is valid, the function will revert otherwise. - function _validateEVMAddress( - bytes memory encodedAddress - ) internal pure returns (address) { - if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress); - uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256)); - if (encodedAddressUint > type(uint160).max || encodedAddressUint < PRECOMPILE_SPACE) { - revert InvalidEVMAddress(encodedAddress); - } - return address(uint160(encodedAddressUint)); - } - - /// @notice Enum listing the possible message execution states within - /// the offRamp contract. - /// UNTOUCHED never executed - /// IN_PROGRESS currently being executed, used a replay protection - /// SUCCESS successfully executed. End state - /// FAILURE unsuccessfully executed, manual execution is now enabled. - /// @dev RMN depends on this enum, if changing, please notify the RMN maintainers. - enum MessageExecutionState { - UNTOUCHED, - IN_PROGRESS, - SUCCESS, - FAILURE - } - - /// @notice CCIP OCR plugin type, used to separate execution & commit transmissions and configs - enum OCRPluginType { - Commit, - Execution - } - - /// @notice Family-agnostic header for OnRamp & OffRamp messages. - /// The messageId is not expected to match hash(message), since it may originate from another ramp family - struct RampMessageHeader { - bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) - uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId - uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId - uint64 sequenceNumber; // │ sequence number, not unique across lanes - uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes - } - - struct EVM2AnyTokenTransfer { - // The source pool EVM address. This value is trusted as it was obtained through the onRamp. It can be - // relied upon by the destination pool to validate the source pool. - address sourcePoolAddress; - // The EVM address of the destination token - // This value is UNTRUSTED as any pool owner can return whatever value they want. - bytes destTokenAddress; - // Optional pool data to be transferred to the destination chain. Be default this is capped at - // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead - // has to be set for the specific token. - bytes extraData; - uint256 amount; // Amount of tokens. - // Destination chain specific execution data encoded in bytes - // for an EVM destination, it consists of the amount of gas available for the releaseOrMint - // and transfer calls made by the offRamp - bytes destExecData; - } - - struct Any2EVMTokenTransfer { - // The source pool EVM address encoded to bytes. This value is trusted as it is obtained through the onRamp. It can be - // relied upon by the destination pool to validate the source pool. - bytes sourcePoolAddress; - address destTokenAddress; // ───╮ Address of destination token - uint32 destGasAmount; //────────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. - // Optional pool data to be transferred to the destination chain. Be default this is capped at - // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead - // has to be set for the specific token. - bytes extraData; - uint256 amount; // Amount of tokens. - } - - /// @notice Family-agnostic message routed to an OffRamp - /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage), hash(Any2EVMRampMessage) != messageId - /// due to encoding & parameter differences - struct Any2EVMRampMessage { - RampMessageHeader header; // Message header - bytes sender; // sender address on the source chain - bytes data; // arbitrary data payload supplied by the message sender - address receiver; // receiver address on the destination chain - uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution - Any2EVMTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer - } - - /// @notice Family-agnostic message emitted from the OnRamp - /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage) due to encoding & parameter differences - /// messageId = hash(EVM2AnyRampMessage) using the source EVM chain's encoding format - struct EVM2AnyRampMessage { - RampMessageHeader header; // Message header - address sender; // sender address on the source chain - bytes data; // arbitrary data payload supplied by the message sender - bytes receiver; // receiver address on the destination chain - bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains - address feeToken; // fee token - uint256 feeTokenAmount; // fee token amount - uint256 feeValueJuels; // fee amount in Juels - EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer - } - - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - - /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - /// @dev inefficient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. - // solhint-disable-next-line gas-struct-packing - struct MerkleRoot { - uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode - uint64 minSeqNr; // ──────────╮ Minimum sequence number, inclusive - uint64 maxSeqNr; // ──────────╯ Maximum sequence number, inclusive - bytes32 merkleRoot; // Merkle root covering the interval & source chain messages - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol deleted file mode 100644 index 95f52bd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/MerkleMultiProof.sol +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.4; - -library MerkleMultiProof { - /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage. - bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000; - /// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preiimage. - bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR = - 0x0000000000000000000000000000000000000000000000000000000000000001; - - uint256 internal constant MAX_NUM_HASHES = 256; - - error InvalidProof(); - error LeavesCannotBeEmpty(); - - /// @notice Computes the root based on provided pre-hashed leaf nodes in - /// leaves, internal nodes in proofs, and using proofFlagBits' i-th bit to - /// determine if an element of proofs or one of the previously computed leafs - /// or internal nodes will be used for the i-th hash. - /// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's - /// preimage should match LEAF_DOMAIN_SEPARATOR. - /// @param proofs The hashes to be used instead of a leaf hash when the proofFlagBits - /// indicates a proof should be used. - /// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or - /// a proof needs to be used in a hash operation. - /// @dev the maximum number of hash operations it set to 256. Any input that would require - /// more than 256 hashes to get to a root will revert. - /// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5 - /// totalHashes = 3 + 1 - 1 = 3 - /// ** round 1 ** - /// proofFlagBits = (5 >> 0) & 1 = true - /// hashes[0] = hashPair(a, b) - /// (leafPos, hashPos, proofPos) = (2, 0, 0); - /// - /// ** round 2 ** - /// proofFlagBits = (5 >> 1) & 1 = false - /// hashes[1] = hashPair(D, c) - /// (leafPos, hashPos, proofPos) = (3, 0, 1); - /// - /// ** round 3 ** - /// proofFlagBits = (5 >> 2) & 1 = true - /// hashes[2] = hashPair(hashes[0], hashes[1]) - /// (leafPos, hashPos, proofPos) = (3, 2, 1); - /// - /// i = 3 and no longer < totalHashes. The algorithm is done - /// return hashes[totalHashes - 1] = hashes[2]; the last hash we computed. - // We mark this function as internal to force it to be inlined in contracts - // that use it, but semantically it is public. - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function merkleRoot( - bytes32[] memory leaves, - bytes32[] memory proofs, - uint256 proofFlagBits - ) internal pure returns (bytes32) { - unchecked { - uint256 leavesLen = leaves.length; - uint256 proofsLen = proofs.length; - if (leavesLen == 0) revert LeavesCannotBeEmpty(); - if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof(); - uint256 totalHashes = leavesLen + proofsLen - 1; - if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof(); - if (totalHashes == 0) { - return leaves[0]; - } - bytes32[] memory hashes = new bytes32[](totalHashes); - (uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0); - - for (uint256 i = 0; i < totalHashes; ++i) { - // Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash. - bytes32 a; - if (proofFlagBits & (1 << i) == (1 << i)) { - // Use a leaf or a previously computed hash. - if (leafPos < leavesLen) { - a = leaves[leafPos++]; - } else { - a = hashes[hashPos++]; - } - } else { - // Use a supplied proof. - a = proofs[proofPos++]; - } - - // The second part of the hashed pair is never a proof as hashing two proofs would result in a - // hash that can already be computed offchain. - bytes32 b; - if (leafPos < leavesLen) { - b = leaves[leafPos++]; - } else { - b = hashes[hashPos++]; - } - - if (!(hashPos <= i)) revert InvalidProof(); - - hashes[i] = _hashPair(a, b); - } - if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof(); - // Return the last hash. - return hashes[totalHashes - 1]; - } - } - - /// @notice Hashes two bytes32 objects in their given order, prepended by the - /// INTERNAL_DOMAIN_SEPARATOR. - function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) { - return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right)); - } - - /// @notice Hashes two bytes32 objects. The order is taken into account, - /// using the lower value first. - function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { - return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol deleted file mode 100644 index 391beb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/Pool.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice This library contains various token pool functions to aid constructing the return data. -library Pool { - // The tag used to signal support for the pool v1 standard - // bytes4(keccak256("CCIP_POOL_V1")) - bytes4 public constant CCIP_POOL_V1 = 0xaff2afbf; - - // The number of bytes in the return data for a pool v1 releaseOrMint call. - // This should match the size of the ReleaseOrMintOutV1 struct. - uint16 public constant CCIP_POOL_V1_RET_BYTES = 32; - - // The default max number of bytes in the return data for a pool v1 lockOrBurn call. - // This data can be used to send information to the destination chain token pool. Can be overwritten - // in the TokenTransferFeeConfig.destBytesOverhead if more data is required. - uint32 public constant CCIP_LOCK_OR_BURN_V1_RET_BYTES = 32; - - struct LockOrBurnInV1 { - bytes receiver; // The recipient of the tokens on the destination chain, abi encoded - uint64 remoteChainSelector; // ─╮ The chain ID of the destination chain - address originalSender; // ─────╯ The original sender of the tx on the source chain - uint256 amount; // The amount of tokens to lock or burn, denominated in the source token's decimals - address localToken; // The address on this chain of the token to lock or burn - } - - struct LockOrBurnOutV1 { - // The address of the destination token, abi encoded in the case of EVM chains - // This value is UNTRUSTED as any pool owner can return whatever value they want. - bytes destTokenAddress; - // Optional pool data to be transferred to the destination chain. Be default this is capped at - // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead - // has to be set for the specific token. - bytes destPoolData; - } - - struct ReleaseOrMintInV1 { - bytes originalSender; // The original sender of the tx on the source chain - uint64 remoteChainSelector; // ─╮ The chain ID of the source chain - address receiver; // ───────────╯ The recipient of the tokens on the destination chain. - uint256 amount; // The amount of tokens to release or mint, denominated in the source token's decimals - address localToken; // The address on this chain of the token to release or mint - /// @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the - /// expected pool address for the given remoteChainSelector. - bytes sourcePoolAddress; // The address of the source pool, abi encoded in the case of EVM chains - bytes sourcePoolData; // The data received from the source pool to process the release or mint - /// @dev WARNING: offchainTokenData is untrusted data. - bytes offchainTokenData; // The offchain data to process the release or mint - } - - struct ReleaseOrMintOutV1 { - // The number of tokens released or minted on the destination chain, denominated in the local token's decimals. - // This value is expected to be equal to the ReleaseOrMintInV1.amount in the case where the source and destination - // chain have the same number of decimals. - uint256 destinationAmount; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol deleted file mode 100644 index 431b772..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/RateLimiter.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.4; - -/// @notice Implements Token Bucket rate limiting. -/// @dev uint128 is safe for rate limiter state. -/// For USD value rate limiting, it can adequately store USD value in 18 decimals. -/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most -/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. -/// In exceptional scenarios where tokens consumed may be larger than uint128, -/// e.g. compromised issuer, an enabled RateLimiter will check and revert. -library RateLimiter { - error BucketOverfilled(); - error OnlyCallableByAdminOrOwner(); - error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); - error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); - error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); - error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); - error InvalidRateLimitRate(Config rateLimiterConfig); - error DisabledNonZeroRateLimit(Config config); - error RateLimitMustBeDisabled(); - - event TokensConsumed(uint256 tokens); - event ConfigChanged(Config config); - - struct TokenBucket { - uint128 tokens; // ──────╮ Current number of tokens that are in the bucket. - uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years. - bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not - uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket. - uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled. - } - - struct Config { - bool isEnabled; // Indication whether the rate limiting should be enabled - uint128 capacity; // ────╮ Specifies the capacity of the rate limiter - uint128 rate; // ───────╯ Specifies the rate of the rate limiter - } - - /// @notice _consume removes the given tokens from the pool, lowering the - /// rate tokens allowed to be consumed for subsequent calls. - /// @param requestTokens The total tokens to be consumed from the bucket. - /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. - /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket - /// @dev emits removal of requestTokens if requestTokens is > 0 - function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal { - // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage - if (!s_bucket.isEnabled || requestTokens == 0) { - return; - } - - uint256 tokens = s_bucket.tokens; - uint256 capacity = s_bucket.capacity; - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - - if (timeDiff != 0) { - if (tokens > capacity) revert BucketOverfilled(); - - // Refill tokens when arriving at a new block time - tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - if (capacity < requestTokens) { - // Token address 0 indicates consuming aggregate value rate limit capacity. - if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); - revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); - } - if (tokens < requestTokens) { - uint256 rate = s_bucket.rate; - // Wait required until the bucket is refilled enough to accept this value, round up to next higher second - // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. - // This acts as a lower bound of wait time. - uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; - - if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); - revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); - } - tokens -= requestTokens; - - // Downcast is safe here, as tokens is not larger than capacity - s_bucket.tokens = uint128(tokens); - emit TokensConsumed(requestTokens); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function _currentTokenBucketState( - TokenBucket memory bucket - ) internal view returns (TokenBucket memory) { - // We update the bucket to reflect the status at the exact time of the - // call. This means we might need to refill a part of the bucket based - // on the time that has passed since the last update. - bucket.tokens = - uint128(_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)); - bucket.lastUpdated = uint32(block.timestamp); - return bucket; - } - - /// @notice Sets the rate limited config. - /// @param s_bucket The token bucket - /// @param config The new config - function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { - // First update the bucket to make sure the proper rate is used for all the time - // up until the config change. - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - if (timeDiff != 0) { - s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate)); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); - s_bucket.isEnabled = config.isEnabled; - s_bucket.capacity = config.capacity; - s_bucket.rate = config.rate; - - emit ConfigChanged(config); - } - - /// @notice Validates the token bucket config - function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { - if (config.isEnabled) { - if (config.rate >= config.capacity || config.rate == 0) { - revert InvalidRateLimitRate(config); - } - if (mustBeDisabled) { - revert RateLimitMustBeDisabled(); - } - } else { - if (config.rate != 0 || config.capacity != 0) { - revert DisabledNonZeroRateLimit(config); - } - } - } - - /// @notice Calculate refilled tokens - /// @param capacity bucket capacity - /// @param tokens current bucket tokens - /// @param timeDiff block time difference since last refill - /// @param rate bucket refill rate - /// @return the value of tokens after refill - function _calculateRefill( - uint256 capacity, - uint256 tokens, - uint256 timeDiff, - uint256 rate - ) private pure returns (uint256) { - return _min(capacity, tokens + timeDiff * rate); - } - - /// @notice Return the smallest of two integers - /// @param a first int - /// @param b second int - /// @return smallest - function _min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol deleted file mode 100644 index 3508276..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -library USDPriceWith18Decimals { - /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount, - /// and amount of the smallest token denomination, - /// calculates the value in USD with 18 decimals. - /// @param tokenPrice The USD price of the token. - /// @param tokenAmount Amount of the smallest token denomination. - /// @return USD value with 18 decimals. - /// @dev this function assumes that no more than 1e59 US dollar worth of token is passed in. - /// If more is sent, this function will overflow and revert. - /// Since there isn't even close to 1e59 dollars, this is ok for all legit tokens. - function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { - /// LINK Example: - /// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals - /// tokenAmount: 2e18 -> 2 LINK - /// result: 8e18 * 2e18 / 1e18 -> 16e18 with 18 decimals = $16 - - /// USDC Example: - /// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals - /// tokenAmount: 5e6 -> 5 USDC - /// result: 1e30 * 5e6 / 1e18 -> 5e18 with 18 decimals = $5 - return (tokenPrice * tokenAmount) / 1e18; - } - - /// @notice Takes a price in USD, with 18 decimals per 1e18 token amount, - /// and USD value with 18 decimals, - /// calculates amount of the smallest token denomination. - /// @param tokenPrice The USD price of the token. - /// @param usdValue USD value with 18 decimals. - /// @return Amount of the smallest token denomination. - function _calcTokenAmountFromUSDValue(uint224 tokenPrice, uint256 usdValue) internal pure returns (uint256) { - /// LINK Example: - /// tokenPrice: 8e18 -> $8/LINK, as 1e18 token amount is 1 LINK, worth 8 USD, or 8e18 with 18 decimals - /// usdValue: 16e18 -> $16 - /// result: 16e18 * 1e18 / 8e18 -> 2e18 = 2 LINK - - /// USDC Example: - /// tokenPrice: 1e30 -> $1/USDC, as 1e18 token amount is 1e12 USDC, worth 1e12 USD, or 1e30 with 18 decimals - /// usdValue: 5e18 -> $5 - /// result: 5e18 * 1e18 / 1e30 -> 5e6 = 5 USDC - return (usdValue * 1e18) / tokenPrice; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol deleted file mode 100644 index ba1dc1e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.4; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -/// @notice Onchain verification of reports from the offchain reporting protocol -/// with multiple OCR plugin support. -abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 256; - - /// @notice Triggers a new run of the offchain reporting protocol - /// @param ocrPluginType OCR plugin type for which the config was set - /// @param configDigest configDigest of this configuration - /// @param signers ith element is address ith oracle uses to sign a report - /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - /// @param F maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - event ConfigSet(uint8 ocrPluginType, bytes32 configDigest, address[] signers, address[] transmitters, uint8 F); - - /// @notice Optionally emitted to indicate the latest configDigest and sequence number - /// for which a report was successfully transmitted. Alternatively, the contract may - /// use latestConfigDigestAndEpoch with scanLogs set to false. - event Transmitted(uint8 indexed ocrPluginType, bytes32 configDigest, uint64 sequenceNumber); - - enum InvalidConfigErrorType { - F_MUST_BE_POSITIVE, - TOO_MANY_TRANSMITTERS, - TOO_MANY_SIGNERS, - F_TOO_HIGH, - REPEATED_ORACLE_ADDRESS, - NO_TRANSMITTERS - } - - error InvalidConfig(InvalidConfigErrorType errorType); - error WrongMessageLength(uint256 expected, uint256 actual); - error ConfigDigestMismatch(bytes32 expected, bytes32 actual); - error ForkedChain(uint256 expected, uint256 actual); - error WrongNumberOfSignatures(); - error SignaturesOutOfRegistration(); - error UnauthorizedTransmitter(); - error UnauthorizedSigner(); - error NonUniqueSignatures(); - error OracleCannotBeZeroAddress(); - error StaticConfigCannotBeChanged(uint8 ocrPluginType); - - /// @dev Packing these fields used on the hot path in a ConfigInfo variable reduces the - /// retrieval of all of them to a minimum number of SLOADs. - struct ConfigInfo { - bytes32 configDigest; - uint8 F; // ──────────────────────────────╮ maximum number of faulty/dishonest oracles the system can tolerate - uint8 n; // │ number of signers / transmitters - bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification - } - - /// @notice Used for s_oracles[a].role, where a is an address, to track the purpose - /// of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // ───╮ Index of oracle in s_signers/s_transmitters - Role role; // ─────╯ Role of the address which mapped to this struct - } - - /// @notice OCR configuration for a single OCR plugin within a DON. - struct OCRConfig { - ConfigInfo configInfo; // latest OCR config - // NOTE: len(signers) can be different from len(transmitters). There is no index relationship between the two arrays - address[] signers; // addresses oracles use to sign the reports - address[] transmitters; // addresses oracles use to transmit the reports - } - - /// @notice Args to update an OCR Config. - struct OCRConfigArgs { - bytes32 configDigest; // Config digest to update to - uint8 ocrPluginType; // ──────────────────╮ OCR plugin type to update config for - uint8 F; // │ maximum number of faulty/dishonest oracles - bool isSignatureVerificationEnabled; // ──╯ if true, requires signers and verifies signatures on transmission verification - address[] signers; // signing address of each oracle - address[] transmitters; // transmission address of each oracle (i.e. the address the oracle actually sends transactions to the contract from) - } - - /// @notice mapping of OCR plugin type -> DON config - mapping(uint8 ocrPluginType => OCRConfig config) internal s_ocrConfigs; - - /// @notice OCR plugin type => signer OR transmitter address mapping - mapping(uint8 ocrPluginType => mapping(address signerOrTransmiter => Oracle oracle)) internal s_oracles; - - // Constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - - /// @notice Constant length component for transmit functions with no signatures. - /// The signatures are expected to match transmitPlugin(reportContext, report). - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector - + 3 * 32 // 3 words containing reportContext - + 32 // word containing start location of abiencoded report value - + 32; // word containing length of report - - /// @notice Extra constant length component for transmit functions with signatures (relative to no signatures). - /// The signatures are expected to match transmitPlugin(reportContext, report, rs, ss, rawVs). - uint16 private constant TRANSMIT_MSGDATA_EXTRA_CONSTANT_LENGTH_COMPONENT_FOR_SIGNATURES = 32 // word containing location start of abiencoded rs value - + 32 // word containing start location of abiencoded ss value - + 32 // rawVs value - + 32 // word containing length rs - + 32; // word containing length of ss - - uint256 internal immutable i_chainID; - - constructor() { - i_chainID = block.chainid; - } - - /// @notice Sets offchain reporting protocol configuration incl. participating oracles. - /// NOTE: The OCR3 config must be sanity-checked against the home-chain registry configuration, to ensure - /// home-chain and remote-chain parity! - /// @param ocrConfigArgs OCR config update args. - /// @dev precondition number of transmitters should match the expected F/fChain relationship. - /// For transmitters, the function only validates that len(transmitters) > 0 && len(transmitters) <= MAX_NUM_ORACLES - /// && len(transmitters) <= len(signers) [if sig verification is enabled] - function setOCR3Configs( - OCRConfigArgs[] memory ocrConfigArgs - ) external onlyOwner { - for (uint256 i; i < ocrConfigArgs.length; ++i) { - _setOCR3Config(ocrConfigArgs[i]); - } - } - - /// @notice Sets offchain reporting protocol configuration incl. participating oracles for a single OCR plugin type. - /// @param ocrConfigArgs OCR config update args. - function _setOCR3Config( - OCRConfigArgs memory ocrConfigArgs - ) internal { - if (ocrConfigArgs.F == 0) revert InvalidConfig(InvalidConfigErrorType.F_MUST_BE_POSITIVE); - - uint8 ocrPluginType = ocrConfigArgs.ocrPluginType; - OCRConfig storage ocrConfig = s_ocrConfigs[ocrPluginType]; - ConfigInfo storage configInfo = ocrConfig.configInfo; - - // If F is 0, then the config is not yet set - if (configInfo.F == 0) { - configInfo.isSignatureVerificationEnabled = ocrConfigArgs.isSignatureVerificationEnabled; - } else if (configInfo.isSignatureVerificationEnabled != ocrConfigArgs.isSignatureVerificationEnabled) { - revert StaticConfigCannotBeChanged(ocrPluginType); - } - - address[] memory transmitters = ocrConfigArgs.transmitters; - if (transmitters.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); - if (transmitters.length == 0) revert InvalidConfig(InvalidConfigErrorType.NO_TRANSMITTERS); - - _clearOracleRoles(ocrPluginType, ocrConfig.transmitters); - - if (ocrConfigArgs.isSignatureVerificationEnabled) { - _clearOracleRoles(ocrPluginType, ocrConfig.signers); - - address[] memory signers = ocrConfigArgs.signers; - - if (signers.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); - if (signers.length <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); - // NOTE: Transmitters cannot exceed signers. Transmitters do not have to be >= 3F + 1 because they can match >= 3fChain + 1, where fChain <= F. - // fChain is not represented in MultiOCR3Base - so we skip this check. - if (signers.length < transmitters.length) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); - - configInfo.n = uint8(signers.length); - ocrConfig.signers = signers; - - _assignOracleRoles(ocrPluginType, signers, Role.Signer); - } - - _assignOracleRoles(ocrPluginType, transmitters, Role.Transmitter); - - ocrConfig.transmitters = transmitters; - configInfo.F = ocrConfigArgs.F; - configInfo.configDigest = ocrConfigArgs.configDigest; - - emit ConfigSet( - ocrPluginType, ocrConfigArgs.configDigest, ocrConfig.signers, ocrConfigArgs.transmitters, ocrConfigArgs.F - ); - _afterOCR3ConfigSet(ocrPluginType); - } - - /// @notice Hook that is called after a plugin's OCR3 config changes. - /// @param ocrPluginType Plugin type for which the config changed. - function _afterOCR3ConfigSet( - uint8 ocrPluginType - ) internal virtual; - - /// @notice Clears oracle roles for the provided oracle addresses. - /// @param ocrPluginType OCR plugin type to clear roles for. - /// @param oracleAddresses Oracle addresses to clear roles for. - function _clearOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses) internal { - for (uint256 i = 0; i < oracleAddresses.length; ++i) { - delete s_oracles[ocrPluginType][oracleAddresses[i]]; - } - } - - /// @notice Assigns oracles roles for the provided oracle addresses with uniqueness verification. - /// @param ocrPluginType OCR plugin type to assign roles for. - /// @param oracleAddresses Oracle addresses to assign roles to. - /// @param role Role to assign. - function _assignOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses, Role role) internal { - for (uint256 i = 0; i < oracleAddresses.length; ++i) { - address oracle = oracleAddresses[i]; - if (s_oracles[ocrPluginType][oracle].role != Role.Unset) { - revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); - } - if (oracle == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[ocrPluginType][oracle] = Oracle(uint8(i), role); - } - } - - /// @notice _transmit is called to post a new report to the contract. - /// The function should be called after the per-DON reporting logic is completed. - /// @param ocrPluginType OCR plugin type to transmit report for - /// @param report serialized report, which the signatures are signing. - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. - /// @param rawVs ith element is the the V component of the ith signature. - function _transmit( - uint8 ocrPluginType, - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs // signatures - ) internal { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 24 byte padding, 8 byte sequence number - // reportContext[2]: ExtraHash - ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; - bytes32 configDigest = reportContext[0]; - - // Scoping this reduces stack pressure and gas usage - { - uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES) + report.length; // one byte pure entry in _report - - if (configInfo.isSignatureVerificationEnabled) { - expectedDataLength += TRANSMIT_MSGDATA_EXTRA_CONSTANT_LENGTH_COMPONENT_FOR_SIGNATURES + rs.length * 32 // 32 bytes per entry in _rs - + ss.length * 32; // 32 bytes per entry in _ss) - } - - if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); - } - - if (configInfo.configDigest != configDigest) { - revert ConfigDigestMismatch(configInfo.configDigest, configDigest); - } - // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. - // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest - // calculated from chain A and so OCR reports will be valid on both forks. - _whenChainNotForked(); - - // Scoping this reduces stack pressure and gas usage - { - Oracle memory transmitter = s_oracles[ocrPluginType][msg.sender]; - // Check that sender is authorized to report - if ( - !( - transmitter.role == Role.Transmitter - && msg.sender == s_ocrConfigs[ocrPluginType].transmitters[transmitter.index] - ) - ) { - revert UnauthorizedTransmitter(); - } - } - - if (configInfo.isSignatureVerificationEnabled) { - // Scoping to reduce stack pressure - { - if (rs.length != configInfo.F + 1) revert WrongNumberOfSignatures(); - if (rs.length != ss.length) revert SignaturesOutOfRegistration(); - } - - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - _verifySignatures(ocrPluginType, h, rs, ss, rawVs); - } - - emit Transmitted(ocrPluginType, configDigest, uint64(uint256(reportContext[1]))); - } - - /// @notice Verifies the signatures of a hashed report value for one OCR plugin type. - /// @param ocrPluginType OCR plugin type to transmit report for. - /// @param hashedReport hashed encoded packing of report + reportContext. - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries. - /// @param rawVs ith element is the the V component of the ith signature. - function _verifySignatures( - uint8 ocrPluginType, - bytes32 hashedReport, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) internal view { - // Verify signatures attached to report. Using a uint256 means we can only verify up to 256 oracles. - uint256 signed = 0; - - uint256 numberOfSignatures = rs.length; - for (uint256 i; i < numberOfSignatures; ++i) { - // Safe from ECDSA malleability here since we check for duplicate signers. - address signer = ecrecover(hashedReport, uint8(rawVs[i]) + 27, rs[i], ss[i]); - // Since we disallow address(0) as a valid signer address, it can never have a signer role. - Oracle memory oracle = s_oracles[ocrPluginType][signer]; - if (oracle.role != Role.Signer) revert UnauthorizedSigner(); - if (signed & (0x1 << oracle.index) != 0) revert NonUniqueSignatures(); - signed |= 0x1 << oracle.index; - } - } - - /// @notice Validates that the chain ID has not diverged after deployment. Reverts if the chain IDs do not match. - function _whenChainNotForked() internal view { - if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); - } - - /// @notice Information about current offchain reporting protocol configuration. - /// @param ocrPluginType OCR plugin type to return config details for. - /// @return ocrConfig OCR config for the plugin type. - function latestConfigDetails( - uint8 ocrPluginType - ) external view returns (OCRConfig memory ocrConfig) { - return s_ocrConfigs[ocrPluginType]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol deleted file mode 100644 index 51e8787..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ /dev/null @@ -1,1044 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; -import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; -import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; -import {INonceManager} from "../interfaces/INonceManager.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; -import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {MultiOCR3Base} from "../ocr/MultiOCR3Base.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice OffRamp enables OCR networks to execute multiple messages -/// in an OffRamp in a single transaction. -/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them -/// results an onchain upgrade of both contracts. -/// @dev MultiOCR3Base is used to store multiple OCR configs for the OffRamp. -/// The execution plugin type has to be configured without signature verification, and the commit -/// plugin type with verification. -contract OffRamp is ITypeAndVersion, MultiOCR3Base { - using ERC165Checker for address; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableSet for EnumerableSet.UintSet; - - error ZeroChainSelectorNotAllowed(); - error ExecutionError(bytes32 messageId, bytes err); - error SourceChainNotEnabled(uint64 sourceChainSelector); - error TokenDataMismatch(uint64 sourceChainSelector, uint64 sequenceNumber); - error UnexpectedTokenData(); - error ManualExecutionNotYetEnabled(uint64 sourceChainSelector); - error ManualExecutionGasLimitMismatch(); - error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, bytes32 messageId, uint256 newLimit); - error InvalidManualExecutionTokenGasOverride( - bytes32 messageId, uint256 tokenIndex, uint256 oldLimit, uint256 tokenGasOverride - ); - error ManualExecutionGasAmountCountMismatch(bytes32 messageId, uint64 sequenceNumber); - error RootNotCommitted(uint64 sourceChainSelector); - error RootAlreadyCommitted(uint64 sourceChainSelector, bytes32 merkleRoot); - error InvalidRoot(); - error CanOnlySelfCall(); - error ReceiverError(bytes err); - error TokenHandlingError(bytes err); - error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost); - error EmptyReport(); - error CursedByRMN(uint64 sourceChainSelector); - error NotACompatiblePool(address notPool); - error InvalidDataLength(uint256 expected, uint256 got); - error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); - error StaleCommitReport(); - error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); - error ZeroAddressNotAllowed(); - error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); - error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); - error SignatureVerificationDisabled(); - error CommitOnRampMismatch(bytes reportOnRamp, bytes configOnRamp); - error InvalidOnRampUpdate(uint64 sourceChainSelector); - - /// @dev Atlas depends on this event, if changing, please notify Atlas. - event StaticConfigSet(StaticConfig staticConfig); - event DynamicConfigSet(DynamicConfig dynamicConfig); - /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event ExecutionStateChanged( - uint64 indexed sourceChainSelector, - uint64 indexed sequenceNumber, - bytes32 indexed messageId, - bytes32 messageHash, - Internal.MessageExecutionState state, - bytes returnData, - uint256 gasUsed - ); - event SourceChainSelectorAdded(uint64 sourceChainSelector); - event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig); - event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); - event AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); - /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event CommitReportAccepted(Internal.MerkleRoot[] merkleRoots, Internal.PriceUpdates priceUpdates); - event RootRemoved(bytes32 root); - event SkippedReportExecution(uint64 sourceChainSelector); - - /// @dev Struct that contains the static configuration - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - /// @dev not sure why solhint complains about this, seems like a buggy detector - /// https://github.com/protofire/solhint/issues/597 - // solhint-disable-next-line gas-struct-packing - struct StaticConfig { - uint64 chainSelector; // ───╮ Destination chainSelector - IRMNRemote rmnRemote; // ───╯ RMN Verification Contract - address tokenAdminRegistry; // Token admin registry address - address nonceManager; // Nonce manager address - } - - /// @dev Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) - struct SourceChainConfig { - IRouter router; // ──────────╮ Local router to use for messages coming from this source chain - bool isEnabled; // | Flag whether the source chain is enabled or not - uint64 minSeqNr; // ─────────╯ The min sequence number expected for future messages - bytes onRamp; // OnRamp address on the source chain - } - - /// @dev Same as SourceChainConfig but with source chain selector so that an array of these - /// can be passed in the constructor and the applySourceChainConfigUpdates function. - struct SourceChainConfigArgs { - IRouter router; // ────────────────╮ Local router to use for messages coming from this source chain - uint64 sourceChainSelector; // | Source chain selector of the config to update - bool isEnabled; // ────────────────╯ Flag whether the source chain is enabled or not - bytes onRamp; // OnRamp address on the source chain - } - - /// @dev Dynamic offRamp config - /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas - struct DynamicConfig { - address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain - uint32 permissionLessExecutionThresholdSeconds; //──╯ Waiting time before manual execution is enabled - address messageInterceptor; // Optional message interceptor to validate incoming messages (zero address = no interceptor) - } - - /// @dev Report that is committed by the observing DON at the committing phase - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct CommitReport { - Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit - Internal.MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit - IRMNRemote.Signature[] rmnSignatures; // RMN signatures on the merkle roots - uint256 rmnRawVs; // Raw v values of the RMN signatures - } - - struct GasLimitOverride { - // A value of zero in both fields signifies no override and allows the corresponding field to be overridden as valid - uint256 receiverExecutionGasLimit; // Overrides EVM2EVMMessage.gasLimit. - uint32[] tokenGasOverrides; // Overrides EVM2EVMMessage.sourceTokenData.destGasAmount, length must be same as tokenAmounts. - } - - // STATIC CONFIG - string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; - /// @dev Hash of encoded address(0) used for empty address checks - bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); - /// @dev ChainSelector of this chain - uint64 internal immutable i_chainSelector; - /// @dev The RMN verification contract - IRMNRemote internal immutable i_rmnRemote; - /// @dev The address of the token admin registry - address internal immutable i_tokenAdminRegistry; - /// @dev The address of the nonce manager - address internal immutable i_nonceManager; - - // DYNAMIC CONFIG - DynamicConfig internal s_dynamicConfig; - - /// @notice Set of source chain selectors - EnumerableSet.UintSet internal s_sourceChainSelectors; - - /// @notice SourceChainConfig per chain - /// (forms lane configurations from sourceChainSelector => StaticConfig.chainSelector) - mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) private s_sourceChainConfigs; - - // STATE - /// @dev A mapping of sequence numbers (per source chain) to execution state using a bitmap with each execution - /// state only taking up 2 bits of the uint256, packing 128 states into a single slot. - /// Message state is tracked to ensure message can only be executed successfully once. - mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => uint256 executionStateBitmap)) internal - s_executionStates; - - /// @notice Commit timestamp of merkle roots per source chain - mapping(uint64 sourceChainSelector => mapping(bytes32 merkleRoot => uint256 timestamp)) internal s_roots; - /// @dev The sequence number of the last price update - uint64 private s_latestPriceSequenceNumber; - - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - SourceChainConfigArgs[] memory sourceChainConfigs - ) MultiOCR3Base() { - if ( - address(staticConfig.rmnRemote) == address(0) || staticConfig.tokenAdminRegistry == address(0) - || staticConfig.nonceManager == address(0) - ) { - revert ZeroAddressNotAllowed(); - } - - if (staticConfig.chainSelector == 0) { - revert ZeroChainSelectorNotAllowed(); - } - - i_chainSelector = staticConfig.chainSelector; - i_rmnRemote = staticConfig.rmnRemote; - i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; - i_nonceManager = staticConfig.nonceManager; - emit StaticConfigSet(staticConfig); - - _setDynamicConfig(dynamicConfig); - _applySourceChainConfigUpdates(sourceChainConfigs); - } - - // ================================================================ - // │ Execution │ - // ================================================================ - - // The size of the execution state in bits - uint256 private constant MESSAGE_EXECUTION_STATE_BIT_WIDTH = 2; - // The mask for the execution state bits - uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1; - - /// @notice Returns the current execution state of a message based on its sequenceNumber. - /// @param sourceChainSelector The source chain to get the execution state for - /// @param sequenceNumber The sequence number of the message to get the execution state for. - /// @return executionState The current execution state of the message. - /// @dev We use the literal number 128 because using a constant increased gas usage. - function getExecutionState( - uint64 sourceChainSelector, - uint64 sequenceNumber - ) public view returns (Internal.MessageExecutionState) { - return Internal.MessageExecutionState( - ( - _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber) - >> ((sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH) - ) & MESSAGE_EXECUTION_STATE_MASK - ); - } - - /// @notice Sets a new execution state for a given sequence number. It will overwrite any existing state. - /// @param sourceChainSelector The source chain to set the execution state for - /// @param sequenceNumber The sequence number for which the state will be saved. - /// @param newState The new value the state will be in after this function is called. - /// @dev We use the literal number 128 because using a constant increased gas usage. - function _setExecutionState( - uint64 sourceChainSelector, - uint64 sequenceNumber, - Internal.MessageExecutionState newState - ) internal { - uint256 offset = (sequenceNumber % 128) * MESSAGE_EXECUTION_STATE_BIT_WIDTH; - uint256 bitmap = _getSequenceNumberBitmap(sourceChainSelector, sequenceNumber); - // To unset any potential existing state we zero the bits of the section the state occupies, - // then we do an AND operation to blank out any existing state for the section. - bitmap &= ~(MESSAGE_EXECUTION_STATE_MASK << offset); - // Set the new state - bitmap |= uint256(newState) << offset; - - s_executionStates[sourceChainSelector][sequenceNumber / 128] = bitmap; - } - - /// @param sourceChainSelector remote source chain selector to get sequence number bitmap for - /// @param sequenceNumber sequence number to get bitmap for - /// @return bitmap Bitmap of the given sequence number for the provided source chain selector. One bitmap represents 128 sequence numbers - function _getSequenceNumberBitmap( - uint64 sourceChainSelector, - uint64 sequenceNumber - ) internal view returns (uint256 bitmap) { - return s_executionStates[sourceChainSelector][sequenceNumber / 128]; - } - - /// @notice Manually executes a set of reports. - /// @param reports Internal.ExecutionReportSingleChain[] - list of reports to execute - /// @param gasLimitOverrides New gasLimit for each message per report - // The outer array represents each report, inner array represents each message in the report. - // i.e. gasLimitOverrides[report1][report1Message1] -> access message1 from report1 - /// @dev We permit gas limit overrides so that users may manually execute messages which failed due to - /// insufficient gas provided. - /// The reports do not have to contain all the messages (they can be omitted). Multiple reports can be passed in simultaneously. - function manuallyExecute( - Internal.ExecutionReport[] memory reports, - GasLimitOverride[][] memory gasLimitOverrides - ) external { - // We do this here because the other _execute path is already covered by MultiOCR3Base. - _whenChainNotForked(); - - uint256 numReports = reports.length; - if (numReports != gasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); - - for (uint256 reportIndex = 0; reportIndex < numReports; ++reportIndex) { - Internal.ExecutionReport memory report = reports[reportIndex]; - - uint256 numMsgs = report.messages.length; - GasLimitOverride[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; - if (numMsgs != msgGasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); - - for (uint256 msgIndex = 0; msgIndex < numMsgs; ++msgIndex) { - uint256 newLimit = msgGasLimitOverrides[msgIndex].receiverExecutionGasLimit; - // Checks to ensure message cannot be executed with less gas than specified. - Internal.Any2EVMRampMessage memory message = report.messages[msgIndex]; - if (newLimit != 0) { - if (newLimit < message.gasLimit) { - revert InvalidManualExecutionGasLimit(report.sourceChainSelector, message.header.messageId, newLimit); - } - } - if (message.tokenAmounts.length != msgGasLimitOverrides[msgIndex].tokenGasOverrides.length) { - revert ManualExecutionGasAmountCountMismatch(message.header.messageId, message.header.sequenceNumber); - } - - // The gas limit can not be lowered as that could cause the message to fail. If manual execution is done - // from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with - // lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON - // would not attempt it with the correct gas limit. - for (uint256 tokenIndex = 0; tokenIndex < message.tokenAmounts.length; ++tokenIndex) { - uint256 tokenGasOverride = msgGasLimitOverrides[msgIndex].tokenGasOverrides[tokenIndex]; - if (tokenGasOverride != 0) { - uint256 destGasAmount = message.tokenAmounts[tokenIndex].destGasAmount; - if (tokenGasOverride < destGasAmount) { - revert InvalidManualExecutionTokenGasOverride( - message.header.messageId, tokenIndex, destGasAmount, tokenGasOverride - ); - } - } - } - } - } - - _batchExecute(reports, gasLimitOverrides); - } - - /// @notice Transmit function for execution reports. The function takes no signatures, - /// and expects the exec plugin type to be configured with no signatures. - /// @param report serialized execution report - function execute(bytes32[3] calldata reportContext, bytes calldata report) external { - _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); - - bytes32[] memory emptySigs = new bytes32[](0); - _transmit(uint8(Internal.OCRPluginType.Execution), reportContext, report, emptySigs, emptySigs, bytes32("")); - } - - /// @notice Batch executes a set of reports, each report matching one single source chain - /// @param reports Set of execution reports (one per chain) containing the messages and proofs - /// @param manualExecGasLimits An array of gas limits to use for manual execution - // The outer array represents each report, inner array represents each message in the report. - // i.e. gasLimitOverrides[report1][report1Message1] -> access message1 from report1 - /// @dev The manualExecGasLimits array should either be empty, or match the length of the reports array - /// @dev If called from manual execution, each inner array's length has to match the number of messages. - function _batchExecute( - Internal.ExecutionReport[] memory reports, - GasLimitOverride[][] memory manualExecGasOverrides - ) internal { - if (reports.length == 0) revert EmptyReport(); - - bool areManualGasLimitsEmpty = manualExecGasOverrides.length == 0; - // Cache array for gas savings in the loop's condition - GasLimitOverride[] memory emptyGasLimits = new GasLimitOverride[](0); - - for (uint256 i = 0; i < reports.length; ++i) { - _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasOverrides[i]); - } - } - - /// @notice Executes a report, executing each message in order. - /// @param report The execution report containing the messages and proofs. - /// @param manualExecGasExecOverrides An array of gas limits to use for manual execution. - /// @dev If called from the DON, this array is always empty. - /// @dev If called from manual execution, this array is always same length as messages. - function _executeSingleReport( - Internal.ExecutionReport memory report, - GasLimitOverride[] memory manualExecGasExecOverrides - ) internal { - uint64 sourceChainSelector = report.sourceChainSelector; - bool manualExecution = manualExecGasExecOverrides.length != 0; - if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { - if (manualExecution) { - // For manual execution we don't want to silently fail so we revert - revert CursedByRMN(sourceChainSelector); - } - // For DON execution we do not revert as a single lane curse can revert the entire batch - emit SkippedReportExecution(sourceChainSelector); - return; - } - - bytes memory onRamp = _getEnabledSourceChainConfig(sourceChainSelector).onRamp; - - uint256 numMsgs = report.messages.length; - if (numMsgs == 0) revert EmptyReport(); - if (numMsgs != report.offchainTokenData.length) revert UnexpectedTokenData(); - - bytes32[] memory hashedLeaves = new bytes32[](numMsgs); - - for (uint256 i = 0; i < numMsgs; ++i) { - Internal.Any2EVMRampMessage memory message = report.messages[i]; - - // Commits do not verify the destChainSelector in the message, since only the root is committed, - // so we have to check it explicitly - if (message.header.destChainSelector != i_chainSelector) { - revert InvalidMessageDestChainSelector(message.header.destChainSelector); - } - // If the message source chain selector does not match the report's source chain selector and - // the root has not been committed for the report source chain selector, this will be caught by the root verification. - // This acts as an extra check. - if (message.header.sourceChainSelector != sourceChainSelector) { - revert SourceChainSelectorMismatch(sourceChainSelector, message.header.sourceChainSelector); - } - - // We do this hash here instead of in _verify to avoid two separate loops - // over the same data, which increases gas cost. - // Hashing all of the message fields ensures that the message being executed is correct and not tampered with. - // Including the known OnRamp ensures that the message originates from the correct on ramp version - hashedLeaves[i] = Internal._hash( - message, - keccak256( - abi.encode( - Internal.ANY_2_EVM_MESSAGE_HASH, - message.header.sourceChainSelector, - message.header.destChainSelector, - keccak256(onRamp) - ) - ) - ); - } - - // SECURITY CRITICAL CHECK - // NOTE: This check also verifies that all messages match the report's sourceChainSelector - uint256 timestampCommitted = _verify(sourceChainSelector, hashedLeaves, report.proofs, report.proofFlagBits); - if (timestampCommitted == 0) revert RootNotCommitted(sourceChainSelector); - - // Execute messages - for (uint256 i = 0; i < numMsgs; ++i) { - uint256 gasStart = gasleft(); - Internal.Any2EVMRampMessage memory message = report.messages[i]; - - Internal.MessageExecutionState originalState = - getExecutionState(sourceChainSelector, message.header.sequenceNumber); - // Two valid cases here, we either have never touched this message before, or we tried to execute - // and failed. This check protects against reentry and re-execution because the other state is - // IN_PROGRESS which should not be allowed to execute. - if ( - !( - originalState == Internal.MessageExecutionState.UNTOUCHED - || originalState == Internal.MessageExecutionState.FAILURE - ) - ) { - // If the message has already been executed, we skip it. We want to not revert on race conditions between - // executing parties. This will allow us to open up manual exec while also attempting with the DON, without - // reverting an entire DON batch when a user manually executes while the tx is inflight. - emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); - continue; - } - uint32[] memory tokenGasOverrides; - if (manualExecution) { - tokenGasOverrides = manualExecGasExecOverrides[i].tokenGasOverrides; - bool isOldCommitReport = - (block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds; - // Manually execution is fine if we previously failed or if the commit report is just too old - // Acceptable state transitions: FAILURE->SUCCESS, UNTOUCHED->SUCCESS, FAILURE->FAILURE - if (!(isOldCommitReport || originalState == Internal.MessageExecutionState.FAILURE)) { - revert ManualExecutionNotYetEnabled(sourceChainSelector); - } - - // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override. - if (manualExecGasExecOverrides[i].receiverExecutionGasLimit != 0) { - message.gasLimit = manualExecGasExecOverrides[i].receiverExecutionGasLimit; - } - } else { - // DON can only execute a message once - // Acceptable state transitions: UNTOUCHED->SUCCESS, UNTOUCHED->FAILURE - if (originalState != Internal.MessageExecutionState.UNTOUCHED) { - emit AlreadyAttempted(sourceChainSelector, message.header.sequenceNumber); - continue; - } - } - - // Nonce changes per state transition (these only apply for ordered messages): - // UNTOUCHED -> FAILURE nonce bump - // UNTOUCHED -> SUCCESS nonce bump - // FAILURE -> FAILURE no nonce bump - // FAILURE -> SUCCESS no nonce bump - // UNTOUCHED messages MUST be executed in order always - // If nonce == 0 then out of order execution is allowed - if (message.header.nonce != 0) { - if (originalState == Internal.MessageExecutionState.UNTOUCHED) { - // If a nonce is not incremented, that means it was skipped, and we can ignore the message - if ( - !INonceManager(i_nonceManager).incrementInboundNonce( - sourceChainSelector, message.header.nonce, message.sender - ) - ) continue; - } - } - - // Although we expect only valid messages will be committed, we check again - // when executing as a defense in depth measure. - bytes[] memory offchainTokenData = report.offchainTokenData[i]; - if (message.tokenAmounts.length != offchainTokenData.length) { - revert TokenDataMismatch(sourceChainSelector, message.header.sequenceNumber); - } - - _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); - (Internal.MessageExecutionState newState, bytes memory returnData) = - _trialExecute(message, offchainTokenData, tokenGasOverrides); - _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); - - // Since it's hard to estimate whether manual execution will succeed, we - // revert the entire transaction if it fails. This will show the user if - // their manual exec will fail before they submit it. - if (manualExecution) { - if (newState == Internal.MessageExecutionState.FAILURE) { - if (originalState != Internal.MessageExecutionState.UNTOUCHED) { - // If manual execution fails, we revert the entire transaction, unless the originalState is UNTOUCHED as we - // would still be making progress by changing the state from UNTOUCHED to FAILURE. - revert ExecutionError(message.header.messageId, returnData); - } - } - } - - // The only valid prior states are UNTOUCHED and FAILURE (checked above) - // The only valid post states are FAILURE and SUCCESS (checked below) - if (newState != Internal.MessageExecutionState.SUCCESS) { - if (newState != Internal.MessageExecutionState.FAILURE) { - revert InvalidNewState(sourceChainSelector, message.header.sequenceNumber, newState); - } - } - - emit ExecutionStateChanged( - sourceChainSelector, - message.header.sequenceNumber, - message.header.messageId, - hashedLeaves[i], - newState, - returnData, - // This emit covers not only the execution through the router, but also all of the overhead in executing the - // message. This gives the most accurate representation of the gas used in the execution. - gasStart - gasleft() - ); - } - } - - /// @notice Try executing a message. - /// @param message Internal.Any2EVMRampMessage memory message. - /// @param offchainTokenData Data provided by the DON for token transfers. - /// @return executionState The new state of the message, being either SUCCESS or FAILURE. - /// @return errData Revert data in bytes if CCIP receiver reverted during execution. - function _trialExecute( - Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData, - uint32[] memory tokenGasOverrides - ) internal returns (Internal.MessageExecutionState executionState, bytes memory) { - try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {} - catch (bytes memory err) { - // return the message execution state as FAILURE and the revert data - // Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES - return (Internal.MessageExecutionState.FAILURE, err); - } - // If message execution succeeded, no CCIP receiver return data is expected, return with empty bytes. - return (Internal.MessageExecutionState.SUCCESS, ""); - } - - /// @notice Executes a single message. - /// @param message The message that will be executed. - /// @param offchainTokenData Token transfer data to be passed to TokenPool. - /// @dev We make this external and callable by the contract itself, in order to try/catch - /// its execution and enforce atomicity among successful message processing and token transfer. - /// @dev We use ERC-165 to check for the ccipReceive interface to permit sending tokens to contracts - /// (for example smart contract wallets) without an associated message. - function executeSingleMessage( - Internal.Any2EVMRampMessage memory message, - bytes[] calldata offchainTokenData, - uint32[] calldata tokenGasOverrides - ) external { - if (msg.sender != address(this)) revert CanOnlySelfCall(); - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); - if (message.tokenAmounts.length > 0) { - destTokenAmounts = _releaseOrMintTokens( - message.tokenAmounts, - message.sender, - message.receiver, - message.header.sourceChainSelector, - offchainTokenData, - tokenGasOverrides - ); - } - - Client.Any2EVMMessage memory any2EvmMessage = Client.Any2EVMMessage({ - messageId: message.header.messageId, - sourceChainSelector: message.header.sourceChainSelector, - sender: abi.encode(message.sender), - data: message.data, - destTokenAmounts: destTokenAmounts - }); - - address messageInterceptor = s_dynamicConfig.messageInterceptor; - if (messageInterceptor != address(0)) { - try IMessageInterceptor(messageInterceptor).onInboundMessage(any2EvmMessage) {} - catch (bytes memory err) { - revert IMessageInterceptor.MessageValidationError(err); - } - } - - // There are three cases in which we skip calling the receiver: - // 1. If the message data is empty AND the gas limit is 0. - // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract - // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the - // receiver without any gas, which would revert the transaction. - // 2. If the receiver is not a contract. - // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. - // - // The ordering of these checks is important, as the first check is the cheapest to execute. - if ( - (message.data.length == 0 && message.gasLimit == 0) || message.receiver.code.length == 0 - || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) - ) return; - - (bool success, bytes memory returnData,) = s_sourceChainConfigs[message.header.sourceChainSelector] - .router - .routeMessage(any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver); - // If CCIP receiver execution is not successful, revert the call including token transfers - if (!success) revert ReceiverError(returnData); - } - - // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @notice Uses a pool to release or mint a token to a receiver address, with balance checks before and after the - /// transfer. This is done to ensure the exact number of tokens the pool claims to release are actually transferred. - /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the - /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by - /// registering the token on this chain, and re-trying the msg. - /// @param sourceTokenAmount Amount and source data of the token to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector - /// @param offchainTokenData Data fetched offchain by the DON. - /// @return destTokenAmount local token address with amount - function _releaseOrMintSingleToken( - Internal.Any2EVMTokenTransfer memory sourceTokenAmount, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes memory offchainTokenData - ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { - // We need to safely decode the token address from the sourceTokenData, as it could be wrong, - // in which case it doesn't have to be a valid EVM address. - // We assume this destTokenAddress has already been fully validated by a (trusted) OnRamp. - address localToken = sourceTokenAmount.destTokenAddress; - // We check with the token admin registry if the token has a pool on this chain. - address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); - // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. - // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. - // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should - // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { - revert NotACompatiblePool(localPoolAddress); - } - - // We retrieve the local token balance of the receiver before the pool call. - (uint256 balancePre, uint256 gasLeft) = _getBalanceOfReceiver(receiver, localToken, sourceTokenAmount.destGasAmount); - - // We determined that the pool address is a valid EVM address, but that does not mean the code at this - // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location - // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. - // We call the pool with exact gas to increase resistance against malicious tokens or token pools. - // We protect against return data bombs by capping the return data size at MAX_RET_BYTES. - (bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas - ._callWithExactGasSafeReturnData( - abi.encodeCall( - IPoolV1.releaseOrMint, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: receiver, - amount: sourceTokenAmount.amount, - localToken: localToken, - remoteChainSelector: sourceChainSelector, - sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, - sourcePoolData: sourceTokenAmount.extraData, - offchainTokenData: offchainTokenData - }) - ), - localPoolAddress, - gasLeft, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - // Wrap and rethrow the error so we can catch it lower in the stack - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should be the local token address. - if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { - revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); - } - - uint256 localAmount = abi.decode(returnData, (uint256)); - // We don't need to do balance checks if the pool is the receiver, as they would always fail in the case - // of a lockRelease pool. - if (receiver != localPoolAddress) { - (uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint); - - // First we check if the subtraction would result in an underflow to ensure we revert with a clear error - if (balancePost < balancePre || balancePost - balancePre != localAmount) { - revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost); - } - } - - return Client.EVMTokenAmount({token: localToken, amount: localAmount}); - } - - /// @notice Retrieves the balance of a receiver address for a given token. - /// @param receiver The address to check the balance of. - /// @param token The token address. - /// @param gasLimit The gas limit to use for the call. - /// @return balance The balance of the receiver. - /// @return gasLeft The gas left after the call. - function _getBalanceOfReceiver( - address receiver, - address token, - uint256 gasLimit - ) internal returns (uint256 balance, uint256 gasLeft) { - (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall(IERC20.balanceOf, (receiver)), - token, - gasLimit, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should contain only the balance. - if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { - revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length); - } - - // Return the decoded balance, which cannot fail as we checked the length, and the gas that is left - // after this call. - return (abi.decode(returnData, (uint256)), gasLimit - gasUsed); - } - - /// @notice Uses pools to release or mint a number of different tokens to a receiver address. - /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector. - /// @param offchainTokenData Array of token data fetched offchain by the DON. - /// @return destTokenAmounts local token addresses with amounts - /// @dev This function wraps the token pool call in a try catch block to gracefully handle - /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error - /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. - function _releaseOrMintTokens( - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes[] calldata offchainTokenData, - uint32[] calldata tokenGasOverrides - ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { - destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); - bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; - for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { - if (!isTokenGasOverridesEmpty) { - if (tokenGasOverrides[i] != 0) { - sourceTokenAmounts[i].destGasAmount = tokenGasOverrides[i]; - } - } - destTokenAmounts[i] = _releaseOrMintSingleToken( - sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] - ); - } - - return destTokenAmounts; - } - - // ================================================================ - // │ Commit │ - // ================================================================ - - /// @notice Transmit function for commit reports. The function requires signatures, - /// and expects the commit plugin type to be configured with signatures. - /// @param report serialized commit report - /// @dev A commitReport can have two distinct parts (batched together to amortize the cost of checking sigs): - /// 1. Price updates - /// 2. A batch of merkle root and sequence number intervals (per-source) - /// Both have their own, separate, staleness checks, with price updates using the epoch and round - /// number of the latest price update. The merkle root checks for staleness are based on the seqNums. - /// They need to be separate because a price report for round t+2 might be included before a report - /// containing a merkle root for round t+1. This merkle root report for round t+1 is still valid - /// and should not be rejected. When a report with a stale root but valid price updates is submitted, - /// we are OK to revert to preserve the invariant that we always revert on invalid sequence number ranges. - /// If that happens, prices will be updated in later rounds. - function commit( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external { - CommitReport memory commitReport = abi.decode(report, (CommitReport)); - - // Verify RMN signatures - if (commitReport.merkleRoots.length > 0) { - i_rmnRemote.verify(address(this), commitReport.merkleRoots, commitReport.rmnSignatures, commitReport.rmnRawVs); - } - - // Check if the report contains price updates - if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) - { - uint64 ocrSequenceNumber = uint64(uint256(reportContext[1])); - - // Check for price staleness based on the epoch and round - if (s_latestPriceSequenceNumber < ocrSequenceNumber) { - // If prices are not stale, update the latest epoch and round - s_latestPriceSequenceNumber = ocrSequenceNumber; - // And update the prices in the fee quoter - IFeeQuoter(s_dynamicConfig.feeQuoter).updatePrices(commitReport.priceUpdates); - } else { - // If prices are stale and the report doesn't contain a root, this report - // does not have any valid information and we revert. - // If it does contain a merkle root, continue to the root checking section. - if (commitReport.merkleRoots.length == 0) revert StaleCommitReport(); - } - } - - for (uint256 i = 0; i < commitReport.merkleRoots.length; ++i) { - Internal.MerkleRoot memory root = commitReport.merkleRoots[i]; - uint64 sourceChainSelector = root.sourceChainSelector; - - if (i_rmnRemote.isCursed(bytes16(uint128(sourceChainSelector)))) { - revert CursedByRMN(sourceChainSelector); - } - - SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); - - if (keccak256(root.onRampAddress) != keccak256(sourceChainConfig.onRamp)) { - revert CommitOnRampMismatch(root.onRampAddress, sourceChainConfig.onRamp); - } - - if (sourceChainConfig.minSeqNr != root.minSeqNr || root.minSeqNr > root.maxSeqNr) { - revert InvalidInterval(root.sourceChainSelector, root.minSeqNr, root.maxSeqNr); - } - - bytes32 merkleRoot = root.merkleRoot; - if (merkleRoot == bytes32(0)) revert InvalidRoot(); - // If we reached this section, the report should contain a valid root - // We disallow duplicate roots as that would reset the timestamp and - // delay potential manual execution. - if (s_roots[root.sourceChainSelector][merkleRoot] != 0) { - revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot); - } - - sourceChainConfig.minSeqNr = root.maxSeqNr + 1; - s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; - } - - emit CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); - } - - /// @notice Returns the sequence number of the last price update. - /// @return sequenceNumber The latest price update sequence number. - function getLatestPriceSequenceNumber() external view returns (uint64) { - return s_latestPriceSequenceNumber; - } - - /// @notice Returns the timestamp of a potentially previously committed merkle root. - /// If the root was never committed 0 will be returned. - /// @param sourceChainSelector The source chain selector. - /// @param root The merkle root to check the commit status for. - /// @return timestamp The timestamp of the committed root or zero in the case that it was never - /// committed. - function getMerkleRoot(uint64 sourceChainSelector, bytes32 root) external view returns (uint256) { - return s_roots[sourceChainSelector][root]; - } - - /// @notice Returns timestamp of when root was accepted or 0 if verification fails. - /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, - /// proofs and proofFlagBits being used to get the root of the inner tree. - /// This root is then used as the singular leaf of the outer tree. - /// @return timestamp The commit timestamp of the root - function _verify( - uint64 sourceChainSelector, - bytes32[] memory hashedLeaves, - bytes32[] memory proofs, - uint256 proofFlagBits - ) internal view virtual returns (uint256 timestamp) { - bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); - return s_roots[sourceChainSelector][root]; - } - - /// @inheritdoc MultiOCR3Base - function _afterOCR3ConfigSet( - uint8 ocrPluginType - ) internal override { - if (ocrPluginType == uint8(Internal.OCRPluginType.Commit)) { - // Signature verification must be enabled for commit plugin - if (!s_ocrConfigs[ocrPluginType].configInfo.isSignatureVerificationEnabled) { - revert SignatureVerificationDisabled(); - } - // When the OCR config changes, we reset the sequence number - // since it is scoped per config digest. - // Note that s_minSeqNr/roots do not need to be reset as the roots persist - // across reconfigurations and are de-duplicated separately. - s_latestPriceSequenceNumber = 0; - } - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static config. - /// @dev This function will always return the same struct as the contents is static and can never change. - /// RMN depends on this function, if changing, please notify the RMN maintainers. - /// @return staticConfig The static config. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - chainSelector: i_chainSelector, - rmnRemote: i_rmnRemote, - tokenAdminRegistry: i_tokenAdminRegistry, - nonceManager: i_nonceManager - }); - } - - /// @notice Returns the current dynamic config. - /// @return dynamicConfig The current dynamic config. - function getDynamicConfig() external view returns (DynamicConfig memory) { - return s_dynamicConfig; - } - - /// @notice Returns the source chain config for the provided source chain selector - /// @param sourceChainSelector chain to retrieve configuration for - /// @return sourceChainConfig The config for the source chain - function getSourceChainConfig( - uint64 sourceChainSelector - ) external view returns (SourceChainConfig memory) { - return s_sourceChainConfigs[sourceChainSelector]; - } - - /// @notice Returns all source chain configs - /// @return sourceChainConfigs The source chain configs corresponding to all the supported chain selectors - function getAllSourceChainConfigs() external view returns (uint64[] memory, SourceChainConfig[] memory) { - SourceChainConfig[] memory sourceChainConfigs = new SourceChainConfig[](s_sourceChainSelectors.length()); - uint64[] memory sourceChainSelectors = new uint64[](s_sourceChainSelectors.length()); - for (uint256 i = 0; i < s_sourceChainSelectors.length(); ++i) { - sourceChainSelectors[i] = uint64(s_sourceChainSelectors.at(i)); - sourceChainConfigs[i] = s_sourceChainConfigs[sourceChainSelectors[i]]; - } - return (sourceChainSelectors, sourceChainConfigs); - } - - /// @notice Updates source configs - /// @param sourceChainConfigUpdates Source chain configs - function applySourceChainConfigUpdates( - SourceChainConfigArgs[] memory sourceChainConfigUpdates - ) external onlyOwner { - _applySourceChainConfigUpdates(sourceChainConfigUpdates); - } - - /// @notice Updates source configs - /// @param sourceChainConfigUpdates Source chain configs - function _applySourceChainConfigUpdates( - SourceChainConfigArgs[] memory sourceChainConfigUpdates - ) internal { - for (uint256 i = 0; i < sourceChainConfigUpdates.length; ++i) { - SourceChainConfigArgs memory sourceConfigUpdate = sourceChainConfigUpdates[i]; - uint64 sourceChainSelector = sourceConfigUpdate.sourceChainSelector; - - if (sourceChainSelector == 0) { - revert ZeroChainSelectorNotAllowed(); - } - - if (address(sourceConfigUpdate.router) == address(0)) { - revert ZeroAddressNotAllowed(); - } - - SourceChainConfig storage currentConfig = s_sourceChainConfigs[sourceChainSelector]; - bytes memory newOnRamp = sourceConfigUpdate.onRamp; - - if (currentConfig.onRamp.length == 0) { - currentConfig.minSeqNr = 1; - emit SourceChainSelectorAdded(sourceChainSelector); - } else if (currentConfig.minSeqNr != 1) { - // OnRamp updates should only happens due to a misconfiguration - // If an OnRamp is misconfigured not reports should have been committed and no messages should have been executed - // This is enforced byt the onRamp address check in the commit function - revert InvalidOnRampUpdate(sourceChainSelector); - } - - // OnRamp can never be zero - if it is, then the source chain has been added for the first time - if (newOnRamp.length == 0 || keccak256(newOnRamp) == EMPTY_ENCODED_ADDRESS_HASH) { - revert ZeroAddressNotAllowed(); - } - - currentConfig.onRamp = newOnRamp; - currentConfig.isEnabled = sourceConfigUpdate.isEnabled; - currentConfig.router = sourceConfigUpdate.router; - - // We don't need to check the return value, as inserting the item twice has no effect. - s_sourceChainSelectors.add(sourceChainSelector); - - emit SourceChainConfigSet(sourceChainSelector, currentConfig); - } - } - - /// @notice Sets the dynamic config. - /// @param dynamicConfig The new dynamic config. - function setDynamicConfig( - DynamicConfig memory dynamicConfig - ) external onlyOwner { - _setDynamicConfig(dynamicConfig); - } - - /// @notice Sets the dynamic config. - /// @param dynamicConfig The dynamic config. - function _setDynamicConfig( - DynamicConfig memory dynamicConfig - ) internal { - if (dynamicConfig.feeQuoter == address(0)) { - revert ZeroAddressNotAllowed(); - } - - s_dynamicConfig = dynamicConfig; - - emit DynamicConfigSet(dynamicConfig); - } - - /// @notice Returns a source chain config with a check that the config is enabled - /// @param sourceChainSelector Source chain selector to check for cursing - /// @return sourceChainConfig The source chain config storage pointer - function _getEnabledSourceChainConfig( - uint64 sourceChainSelector - ) internal view returns (SourceChainConfig storage) { - SourceChainConfig storage sourceChainConfig = s_sourceChainConfigs[sourceChainSelector]; - if (!sourceChainConfig.isEnabled) { - revert SourceChainNotEnabled(sourceChainSelector); - } - - return sourceChainConfig; - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Reverts as this contract should not be able to receive CCIP messages - function ccipReceive( - Client.Any2EVMMessage calldata - ) external pure { - // solhint-disable-next-line - revert(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol deleted file mode 100644 index d7af0d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ /dev/null @@ -1,526 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; -import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; -import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; -import {INonceManager} from "../interfaces/INonceManager.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice The OnRamp is a contract that handles lane-specific fee logic -/// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them -/// results in an onchain upgrade of all 3. -contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.AddressSet; - using USDPriceWith18Decimals for uint224; - - error CannotSendZeroTokens(); - error UnsupportedToken(address token); - error MustBeCalledByRouter(); - error RouterMustSetOriginalSender(); - error InvalidConfig(); - error CursedByRMN(uint64 sourceChainSelector); - error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - error InvalidDestChainConfig(uint64 sourceChainSelector); - error OnlyCallableByOwnerOrAllowlistAdmin(); - error SenderNotAllowed(address sender); - error InvalidAllowListRequest(uint64 destChainSelector); - error ReentrancyGuardReentrantCall(); - - event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event DestChainConfigSet( - uint64 indexed destChainSelector, uint64 sequenceNumber, IRouter router, bool allowListEnabled - ); - event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); - /// RMN depends on this event, if changing, please notify the RMN maintainers. - event CCIPMessageSent( - uint64 indexed destChainSelector, uint64 indexed sequenceNumber, Internal.EVM2AnyRampMessage message - ); - event AllowListAdminSet(address indexed allowListAdmin); - event AllowListSendersAdded(uint64 indexed destChainSelector, address[] senders); - event AllowListSendersRemoved(uint64 indexed destChainSelector, address[] senders); - - /// @dev Struct that contains the static configuration - /// RMN depends on this struct, if changing, please notify the RMN maintainers. - // solhint-disable-next-line gas-struct-packing - struct StaticConfig { - uint64 chainSelector; // ─────╮ Source chain selector - IRMNRemote rmnRemote; // ─────╯ RMN remote address - address nonceManager; // Nonce manager address - address tokenAdminRegistry; // Token admin registry address - } - - /// @dev Struct that contains the dynamic configuration - // solhint-disable-next-line gas-struct-packing - struct DynamicConfig { - address feeQuoter; // FeeQuoter address - bool reentrancyGuardEntered; // Reentrancy protection - address messageInterceptor; // Optional message interceptor to validate outbound messages (zero address = no interceptor) - address feeAggregator; // Fee aggregator address - address allowListAdmin; // authorized admin to add or remove allowed senders - } - - /// @dev Struct to hold the configs for a destination chain - /// @dev sequenceNumber, allowListEnabled, router will all be packed in 1 slot - struct DestChainConfig { - // The last used sequence number. This is zero in the case where no messages have yet been sent. - // 0 is not a valid sequence number for any real transaction. - uint64 sequenceNumber; // ──────╮ The last used sequence number - bool allowListEnabled; // │ boolean indicator to specify if allowList check is enabled - IRouter router; // ─────────────╯ Local router address that is allowed to send messages to the destination chain. - // This is the list of addresses allowed to send messages from onRamp - EnumerableSet.AddressSet allowedSendersList; - } - - /// @dev Same as DestChainConfig but with the destChainSelector so that an array of these - /// can be passed in the constructor and the applyDestChainConfigUpdates function - //solhint-disable gas-struct-packing - struct DestChainConfigArgs { - uint64 destChainSelector; // ─╮ Destination chain selector - IRouter router; // │ Source router address - bool allowListEnabled; //─────╯ Boolean indicator to specify if allowList check is enabled - } - - /// @dev Struct used to apply AllowList Senders for multiple destChainSelectors - /// @dev the senders in the AllowlistedSenders here is the user that sends the message - /// @dev the config restricts the chain to allow only allowedList of senders to send message from this chain to a destChainSelector - /// @dev destChainSelector, allowListEnabled will be packed in 1 slot - //solhint-disable gas-struct-packing - struct AllowListConfigArgs { - uint64 destChainSelector; // ─────────────╮ Destination chain selector - // │ destChainSelector and allowListEnabled are packed in the same slot - bool allowListEnabled; // ────────────────╯ boolean indicator to specify if allowList check is enabled. - address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList - address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList - } - - // STATIC CONFIG - string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; - /// @dev The chain ID of the source chain that this contract is deployed to - uint64 private immutable i_chainSelector; - /// @dev The rmn contract - IRMNRemote private immutable i_rmnRemote; - /// @dev The address of the nonce manager - address private immutable i_nonceManager; - /// @dev The address of the token admin registry - address private immutable i_tokenAdminRegistry; - - // DYNAMIC CONFIG - /// @dev The dynamic config for the onRamp - DynamicConfig private s_dynamicConfig; - - /// @dev The destination chain specific configs - mapping(uint64 destChainSelector => DestChainConfig destChainConfig) private s_destChainConfigs; - - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - DestChainConfigArgs[] memory destChainConfigArgs - ) { - if ( - staticConfig.chainSelector == 0 || address(staticConfig.rmnRemote) == address(0) - || staticConfig.nonceManager == address(0) || staticConfig.tokenAdminRegistry == address(0) - ) { - revert InvalidConfig(); - } - - i_chainSelector = staticConfig.chainSelector; - i_rmnRemote = staticConfig.rmnRemote; - i_nonceManager = staticConfig.nonceManager; - i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; - - _setDynamicConfig(dynamicConfig); - _applyDestChainConfigUpdates(destChainConfigArgs); - } - - // ================================================================ - // │ Messaging │ - // ================================================================ - - /// @notice Gets the next sequence number to be used in the onRamp - /// @param destChainSelector The destination chain selector - /// @return nextSequenceNumber The next sequence number to be used - function getExpectedNextSequenceNumber( - uint64 destChainSelector - ) external view returns (uint64) { - return s_destChainConfigs[destChainSelector].sequenceNumber + 1; - } - - /// @inheritdoc IEVM2AnyOnRampClient - function forwardFromRouter( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message, - uint256 feeTokenAmount, - address originalSender - ) external returns (bytes32) { - // We rely on a reentrancy guard here due to the untrusted calls performed to the pools - // This enables some optimizations by not following the CEI pattern - if (s_dynamicConfig.reentrancyGuardEntered) revert ReentrancyGuardReentrantCall(); - - s_dynamicConfig.reentrancyGuardEntered = true; - - DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; - - // NOTE: assumes the message has already been validated through the getFee call - // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. - if (originalSender == address(0)) revert RouterMustSetOriginalSender(); - - if (destChainConfig.allowListEnabled) { - if (!destChainConfig.allowedSendersList.contains(originalSender)) { - revert SenderNotAllowed(originalSender); - } - } - - // Router address may be zero intentionally to pause. - if (msg.sender != address(destChainConfig.router)) revert MustBeCalledByRouter(); - - { - // scoped to reduce stack usage - address messageInterceptor = s_dynamicConfig.messageInterceptor; - if (messageInterceptor != address(0)) { - IMessageInterceptor(messageInterceptor).onOutboundMessage(destChainSelector, message); - } - } - - Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ - header: Internal.RampMessageHeader({ - // Should be generated after the message is complete - messageId: "", - sourceChainSelector: i_chainSelector, - destChainSelector: destChainSelector, - // We need the next available sequence number so we increment before we use the value - sequenceNumber: ++destChainConfig.sequenceNumber, - // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we - // may block ordered message nonces, which is not what we want. - nonce: 0 - }), - sender: originalSender, - data: message.data, - extraArgs: "", - receiver: message.receiver, - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - feeValueJuels: 0, // calculated later - // Should be populated via lock / burn pool calls - tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) - }); - - // Lock / burn the tokens as last step. TokenPools may not always be trusted. - Client.EVMTokenAmount[] memory tokenAmounts = message.tokenAmounts; - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - newMessage.tokenAmounts[i] = - _lockOrBurnSingleToken(tokenAmounts[i], destChainSelector, message.receiver, originalSender); - } - - // Convert message fee to juels and retrieve converted args - // Validate pool return data after it is populated (view function - no state changes) - bool isOutOfOrderExecution; - bytes memory convertedExtraArgs; - bytes[] memory destExecDataPerToken; - (newMessage.feeValueJuels, isOutOfOrderExecution, convertedExtraArgs, destExecDataPerToken) = IFeeQuoter( - s_dynamicConfig.feeQuoter - ).processMessageArgs( - destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs, newMessage.tokenAmounts, tokenAmounts - ); - - newMessage.header.nonce = isOutOfOrderExecution - ? 0 - : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); - newMessage.extraArgs = convertedExtraArgs; - - for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { - newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; - } - - // Hash only after all fields have been set - newMessage.header.messageId = Internal._hash( - newMessage, - // Metadata hash preimage to ensure global uniqueness, ensuring 2 identical messages sent to 2 different - // lanes will have a distinct hash. - keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) - ); - - // Emit message request - // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this - // event in the offchain code. - emit CCIPMessageSent(destChainSelector, newMessage.header.sequenceNumber, newMessage); - - s_dynamicConfig.reentrancyGuardEntered = false; - - return newMessage.header.messageId; - } - - /// @notice Uses a pool to lock or burn a token - /// @param tokenAndAmount Token address and amount to lock or burn - /// @param destChainSelector Target destination chain selector of the message - /// @param receiver Message receiver - /// @param originalSender Message sender - /// @return evm2AnyTokenTransfer EVM2Any token and amount data - function _lockOrBurnSingleToken( - Client.EVMTokenAmount memory tokenAndAmount, - uint64 destChainSelector, - bytes memory receiver, - address originalSender - ) internal returns (Internal.EVM2AnyTokenTransfer memory) { - if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); - - IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); - // We don't have to check if it supports the pool version in a non-reverting way here because - // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface - // function and not through the ERC165Checker. - if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { - revert UnsupportedToken(tokenAndAmount.token); - } - - Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: receiver, - remoteChainSelector: destChainSelector, - originalSender: originalSender, - amount: tokenAndAmount.amount, - localToken: tokenAndAmount.token - }) - ); - - // NOTE: pool data validations are outsourced to the FeeQuoter to handle family-specific logic handling - return Internal.EVM2AnyTokenTransfer({ - sourcePoolAddress: address(sourcePool), - destTokenAddress: poolReturnData.destTokenAddress, - extraData: poolReturnData.destPoolData, - amount: tokenAndAmount.amount, - destExecData: "" // This is set in the processPoolReturnData function - }); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Returns the static onRamp config. - /// @dev RMN depends on this function, if modified, please notify the RMN maintainers. - /// @return staticConfig the static configuration. - function getStaticConfig() external view returns (StaticConfig memory) { - return StaticConfig({ - chainSelector: i_chainSelector, - rmnRemote: i_rmnRemote, - nonceManager: i_nonceManager, - tokenAdminRegistry: i_tokenAdminRegistry - }); - } - - /// @notice Returns the dynamic onRamp config. - /// @return dynamicConfig the dynamic configuration. - function getDynamicConfig() external view returns (DynamicConfig memory dynamicConfig) { - return s_dynamicConfig; - } - - /// @notice Sets the dynamic configuration. - /// @param dynamicConfig The configuration. - function setDynamicConfig( - DynamicConfig memory dynamicConfig - ) external onlyOwner { - _setDynamicConfig(dynamicConfig); - } - - /// @notice Gets the source router for a destination chain - /// @param destChainSelector The destination chain selector - /// @return router the router for the provided destination chain - function getRouter( - uint64 destChainSelector - ) external view returns (IRouter) { - return s_destChainConfigs[destChainSelector].router; - } - - /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. - function _setDynamicConfig( - DynamicConfig memory dynamicConfig - ) internal { - if ( - dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0) - || dynamicConfig.reentrancyGuardEntered - ) revert InvalidConfig(); - - s_dynamicConfig = dynamicConfig; - - emit ConfigSet( - StaticConfig({ - chainSelector: i_chainSelector, - rmnRemote: i_rmnRemote, - nonceManager: i_nonceManager, - tokenAdminRegistry: i_tokenAdminRegistry - }), - dynamicConfig - ); - } - - /// @notice Updates destination chains specific configs. - /// @param destChainConfigArgs Array of destination chain specific configs. - function applyDestChainConfigUpdates( - DestChainConfigArgs[] memory destChainConfigArgs - ) external onlyOwner { - _applyDestChainConfigUpdates(destChainConfigArgs); - } - - /// @notice Internal version of applyDestChainConfigUpdates. - function _applyDestChainConfigUpdates( - DestChainConfigArgs[] memory destChainConfigArgs - ) internal { - for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; - uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - - if (destChainSelector == 0) { - revert InvalidDestChainConfig(destChainSelector); - } - - DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; - destChainConfig.router = destChainConfigArg.router; - destChainConfig.allowListEnabled = destChainConfigArg.allowListEnabled; - - emit DestChainConfigSet( - destChainSelector, destChainConfig.sequenceNumber, destChainConfigArg.router, destChainConfig.allowListEnabled - ); - } - } - - /// @notice get ChainConfig configured for the DestinationChainSelector - /// @param destChainSelector The destination chain selector - /// @return sequenceNumber The last used sequence number - /// @return allowListEnabled boolean indicator to specify if allowList check is enabled - /// @return router address of the router - function getDestChainConfig( - uint64 destChainSelector - ) public view returns (uint64 sequenceNumber, bool allowListEnabled, address router) { - DestChainConfig storage config = s_destChainConfigs[destChainSelector]; - sequenceNumber = config.sequenceNumber; - allowListEnabled = config.allowListEnabled; - router = address(config.router); - return (sequenceNumber, allowListEnabled, router); - } - - /// @notice get allowedSenders List configured for the DestinationChainSelector - /// @param destChainSelector The destination chain selector - /// @return array of allowedList of Senders - function getAllowedSendersList( - uint64 destChainSelector - ) public view returns (address[] memory) { - return s_destChainConfigs[destChainSelector].allowedSendersList.values(); - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - /// @notice Updates allowListConfig for Senders - /// @dev configuration used to set the list of senders who are authorized to send messages - /// @param allowListConfigArgsItems Array of AllowListConfigArguments where each item is for a destChainSelector - function applyAllowListUpdates( - AllowListConfigArgs[] calldata allowListConfigArgsItems - ) external { - if (msg.sender != owner()) { - if (msg.sender != s_dynamicConfig.allowListAdmin) { - revert OnlyCallableByOwnerOrAllowlistAdmin(); - } - } - - for (uint256 i = 0; i < allowListConfigArgsItems.length; ++i) { - AllowListConfigArgs memory allowListConfigArgs = allowListConfigArgsItems[i]; - - DestChainConfig storage destChainConfig = s_destChainConfigs[allowListConfigArgs.destChainSelector]; - destChainConfig.allowListEnabled = allowListConfigArgs.allowListEnabled; - - if (allowListConfigArgs.addedAllowlistedSenders.length > 0) { - if (allowListConfigArgs.allowListEnabled) { - for (uint256 j = 0; j < allowListConfigArgs.addedAllowlistedSenders.length; ++j) { - address toAdd = allowListConfigArgs.addedAllowlistedSenders[j]; - if (toAdd == address(0)) { - revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); - } - destChainConfig.allowedSendersList.add(toAdd); - } - - emit AllowListSendersAdded(allowListConfigArgs.destChainSelector, allowListConfigArgs.addedAllowlistedSenders); - } else { - revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); - } - } - - for (uint256 j = 0; j < allowListConfigArgs.removedAllowlistedSenders.length; ++j) { - destChainConfig.allowedSendersList.remove(allowListConfigArgs.removedAllowlistedSenders[j]); - } - - if (allowListConfigArgs.removedAllowlistedSenders.length > 0) { - emit AllowListSendersRemoved( - allowListConfigArgs.destChainSelector, allowListConfigArgs.removedAllowlistedSenders - ); - } - } - } - - // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - function getPoolBySourceToken(uint64, /*destChainSelector*/ IERC20 sourceToken) public view returns (IPoolV1) { - return IPoolV1(ITokenAdminRegistry(i_tokenAdminRegistry).getPool(address(sourceToken))); - } - - /// @inheritdoc IEVM2AnyOnRampClient - function getSupportedTokens( - uint64 /*destChainSelector*/ - ) external pure returns (address[] memory) { - revert GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - } - - // ================================================================ - // │ Fees │ - // ================================================================ - - /// @inheritdoc IEVM2AnyOnRampClient - /// @dev getFee MUST revert if the feeToken is not listed in the fee token config, as the router assumes it does. - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount) { - if (i_rmnRemote.isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); - - return IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedFee(destChainSelector, message); - } - - /// @notice Withdraws the outstanding fee token balances to the fee aggregator. - /// @dev This function can be permissionless as it only transfers accepted fee tokens to the fee aggregator which is a trusted address. - function withdrawFeeTokens() external { - address[] memory feeTokens = IFeeQuoter(s_dynamicConfig.feeQuoter).getFeeTokens(); - address feeAggregator = s_dynamicConfig.feeAggregator; - - for (uint256 i = 0; i < feeTokens.length; ++i) { - IERC20 feeToken = IERC20(feeTokens[i]); - uint256 feeTokenBalance = feeToken.balanceOf(address(this)); - - if (feeTokenBalance > 0) { - feeToken.safeTransfer(feeAggregator, feeTokenBalance); - - emit FeeTokenWithdrawn(feeAggregator, address(feeToken), feeTokenBalance); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol deleted file mode 100644 index 1ba13a4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; -import {TokenPool} from "./TokenPool.sol"; - -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice This pool mints and burns a 3rd-party token. -/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. -/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. -/// The only way to change whitelisting mode is to deploy a new pool. -/// If that is expected, please make sure the token's burner/minter roles are adjustable. -/// @dev This contract is a variant of BurnMintTokenPool that uses `burnFrom(from, amount)`. -contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - using SafeERC20 for IBurnMintERC20; - - string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) { - // Some tokens allow burning from the sender without approval, but not all do. - // To be safe, we approve the pool to burn from the pool. - token.safeIncreaseAllowance(address(this), type(uint256).max); - } - - /// @inheritdoc BurnMintTokenPoolAbstract - function _burn( - uint256 amount - ) internal virtual override { - IBurnMintERC20(address(i_token)).burnFrom(address(this), amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol deleted file mode 100644 index 33026cf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; -import {TokenPool} from "./TokenPool.sol"; - -/// @notice This pool mints and burns a 3rd-party token. -/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. -/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. -/// The only way to change whitelisting mode is to deploy a new pool. -/// If that is expected, please make sure the token's burner/minter roles are adjustable. -/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`. -contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) {} - - /// @inheritdoc BurnMintTokenPoolAbstract - function _burn( - uint256 amount - ) internal virtual override { - IBurnMintERC20(address(i_token)).burn(amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol deleted file mode 100644 index 6d743ed..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {TokenPool} from "./TokenPool.sol"; - -abstract contract BurnMintTokenPoolAbstract is TokenPool { - /// @notice Contains the specific burn call for a pool. - /// @dev overriding this method allows us to create pools with different burn signatures - /// without duplicating the underlying logic. - function _burn( - uint256 amount - ) internal virtual; - - /// @notice Burn the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - _burn(lockOrBurnIn.amount); - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - // Mint to the receiver - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol deleted file mode 100644 index 37541bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintTokenPoolAbstract} from "./BurnMintTokenPoolAbstract.sol"; -import {TokenPool} from "./TokenPool.sol"; - -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice This pool mints and burns a 3rd-party token. -/// @dev Pool whitelisting mode is set in the constructor and cannot be modified later. -/// It either accepts any address as originalSender, or only accepts whitelisted originalSender. -/// The only way to change whitelisting mode is to deploy a new pool. -/// If that is expected, please make sure the token's burner/minter roles are adjustable. -/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(from, amount)`. -contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - using SafeERC20 for IBurnMintERC20; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) { - // Some tokens allow burning from the sender without approval, but not all do. - // To be safe, we approve the pool to burn from the pool. - token.safeIncreaseAllowance(address(this), type(uint256).max); - } - - /// @inheritdoc BurnMintTokenPoolAbstract - function _burn( - uint256 amount - ) internal virtual override { - IBurnMintERC20(address(i_token)).burn(address(this), amount); - } - - function typeAndVersion() external pure virtual override returns (string memory) { - return "BurnWithFromMintTokenPool 1.5.0"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol deleted file mode 100644 index 0f77304..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ /dev/null @@ -1,139 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {TokenPool} from "./TokenPool.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice Token pool used for tokens on their native chain. This uses a lock and release mechanism. -/// Because of lock/unlock requiring liquidity, this pool contract also has function to add and remove -/// liquidity. This allows for proper bookkeeping for both user and liquidity provider balances. -/// @dev One token per LockReleaseTokenPool. -contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion { - using SafeERC20 for IERC20; - - error InsufficientLiquidity(); - error LiquidityNotAccepted(); - - event LiquidityTransferred(address indexed from, uint256 amount); - - string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0"; - - /// @dev Whether or not the pool accepts liquidity. - /// External liquidity is not required when there is one canonical token deployed to a chain, - /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant - /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold - bool internal immutable i_acceptLiquidity; - /// @notice The address of the rebalancer. - address internal s_rebalancer; - - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - bool acceptLiquidity, - address router - ) TokenPool(token, allowlist, rmnProxy, router) { - i_acceptLiquidity = acceptLiquidity; - } - - /// @notice Locks the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - emit Locked(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Release tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - // Release to the recipient - getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); - - emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - // @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public pure virtual override returns (bool) { - return interfaceId == type(ILiquidityContainer).interfaceId || super.supportsInterface(interfaceId); - } - - /// @notice Gets LiquidityManager, can be address(0) if none is configured. - /// @return The current liquidity manager. - function getRebalancer() external view returns (address) { - return s_rebalancer; - } - - /// @notice Sets the LiquidityManager address. - /// @dev Only callable by the owner. - function setRebalancer( - address rebalancer - ) external onlyOwner { - s_rebalancer = rebalancer; - } - - /// @notice Checks if the pool can accept liquidity. - /// @return true if the pool can accept liquidity, false otherwise. - function canAcceptLiquidity() external view returns (bool) { - return i_acceptLiquidity; - } - - /// @notice Adds liquidity to the pool. The tokens should be approved first. - /// @param amount The amount of liquidity to provide. - function provideLiquidity( - uint256 amount - ) external { - if (!i_acceptLiquidity) revert LiquidityNotAccepted(); - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - i_token.safeTransferFrom(msg.sender, address(this), amount); - emit LiquidityAdded(msg.sender, amount); - } - - /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. - /// @param amount The amount of liquidity to remove. - function withdrawLiquidity( - uint256 amount - ) external { - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); - i_token.safeTransfer(msg.sender, amount); - emit LiquidityRemoved(msg.sender, amount); - } - - /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so - /// this pool will have to be set as the rebalancer in the older version of the pool. This allows it to transfer the - /// funds in the old pool to the new pool. - /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the - /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. - /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before - /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the - /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its - /// liquidity. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. - /// @param from The address of the old pool. - /// @param amount The amount of liquidity to transfer. - function transferLiquidity(address from, uint256 amount) external onlyOwner { - LockReleaseTokenPool(from).withdrawLiquidity(amount); - - emit LiquidityTransferred(from, amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol deleted file mode 100644 index e3b4e92..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ /dev/null @@ -1,464 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolV1} from "../interfaces/IPool.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice Base abstract class with common functions for all token pools. -/// A token pool serves as isolated place for holding tokens and token specific logic -/// that may execute as tokens move across the bridge. -abstract contract TokenPool is IPoolV1, OwnerIsCreator { - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - using RateLimiter for RateLimiter.TokenBucket; - - error CallerIsNotARampOnRouter(address caller); - error ZeroAddressNotAllowed(); - error SenderNotAllowed(address sender); - error AllowListNotEnabled(); - error NonExistentChain(uint64 remoteChainSelector); - error ChainNotAllowed(uint64 remoteChainSelector); - error CursedByRMN(); - error ChainAlreadyExists(uint64 chainSelector); - error InvalidSourcePoolAddress(bytes sourcePoolAddress); - error InvalidToken(address token); - error Unauthorized(address caller); - - event Locked(address indexed sender, uint256 amount); - event Burned(address indexed sender, uint256 amount); - event Released(address indexed sender, address indexed recipient, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - event ChainAdded( - uint64 remoteChainSelector, - bytes remoteToken, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainConfigured( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainRemoved(uint64 remoteChainSelector); - event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); - event AllowListAdd(address sender); - event AllowListRemove(address sender); - event RouterUpdated(address oldRouter, address newRouter); - - struct ChainUpdate { - uint64 remoteChainSelector; // ──╮ Remote chain selector - bool allowed; // ────────────────╯ Whether the chain should be enabled - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. - RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - } - - struct RemoteChainConfig { - RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. - } - - /// @dev The bridgeable token that is managed by this pool. - IERC20 internal immutable i_token; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; - /// @dev The immutable flag that indicates if the pool is access-controlled. - bool internal immutable i_allowlistEnabled; - /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. - /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; - /// @dev The address of the router - IRouter internal s_router; - /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to - /// be able to quickly determine (without parsing logs) who can access the pool. - /// @dev The chain selectors are in uint256 format because of the EnumerableSet implementation. - EnumerableSet.UintSet internal s_remoteChainSelectors; - mapping(uint64 remoteChainSelector => RemoteChainConfig) internal s_remoteChainConfigs; - /// @notice The address of the rate limiter admin. - /// @dev Can be address(0) if none is configured. - address internal s_rateLimitAdmin; - - constructor(IERC20 token, address[] memory allowlist, address rmnProxy, address router) { - if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); - i_token = token; - i_rmnProxy = rmnProxy; - s_router = IRouter(router); - - // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. - i_allowlistEnabled = allowlist.length > 0; - if (i_allowlistEnabled) { - _applyAllowListUpdates(new address[](0), allowlist); - } - } - - /// @notice Get RMN proxy address - /// @return rmnProxy Address of RMN proxy - function getRmnProxy() public view returns (address rmnProxy) { - return i_rmnProxy; - } - - /// @inheritdoc IPoolV1 - function isSupportedToken( - address token - ) public view virtual returns (bool) { - return token == address(i_token); - } - - /// @notice Gets the IERC20 token that this pool can lock or burn. - /// @return token The IERC20 token representation. - function getToken() public view returns (IERC20 token) { - return i_token; - } - - /// @notice Gets the pool's Router - /// @return router The pool's Router - function getRouter() public view returns (address router) { - return address(s_router); - } - - /// @notice Sets the pool's Router - /// @param newRouter The new Router - function setRouter( - address newRouter - ) public onlyOwner { - if (newRouter == address(0)) revert ZeroAddressNotAllowed(); - address oldRouter = address(s_router); - s_router = IRouter(newRouter); - - emit RouterUpdated(oldRouter, newRouter); - } - - /// @notice Signals which version of the pool interface is supported - function supportsInterface( - bytes4 interfaceId - ) public pure virtual override returns (bool) { - return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId - || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Validation │ - // ================================================================ - - /// @notice Validates the lock or burn input for correctness on - /// - token to be locked or burned - /// - RMN curse status - /// - allowlist status - /// - if the sender is a valid onRamp - /// - rate limit status - /// @param lockOrBurnIn The input to validate. - /// @dev This function should always be called before executing a lock or burn. Not doing so would allow - /// for various exploits. - function _validateLockOrBurn( - Pool.LockOrBurnInV1 memory lockOrBurnIn - ) internal { - if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); - _checkAllowList(lockOrBurnIn.originalSender); - - _onlyOnRamp(lockOrBurnIn.remoteChainSelector); - _consumeOutboundRateLimit(lockOrBurnIn.remoteChainSelector, lockOrBurnIn.amount); - } - - /// @notice Validates the release or mint input for correctness on - /// - token to be released or minted - /// - RMN curse status - /// - if the sender is a valid offRamp - /// - if the source pool is valid - /// - rate limit status - /// @param releaseOrMintIn The input to validate. - /// @dev This function should always be called before executing a release or mint. Not doing so would allow - /// for various exploits. - function _validateReleaseOrMint( - Pool.ReleaseOrMintInV1 memory releaseOrMintIn - ) internal { - if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); - _onlyOffRamp(releaseOrMintIn.remoteChainSelector); - - // Validates that the source pool address is configured on this pool. - bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.remoteChainSelector); - if ( - configuredRemotePool.length == 0 - || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) - ) { - revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); - } - _consumeInboundRateLimit(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); - } - - // ================================================================ - // │ Chain permissions │ - // ================================================================ - - /// @notice Gets the pool address on the remote chain. - /// @param remoteChainSelector Remote chain selector. - /// @dev To support non-evm chains, this value is encoded into bytes - function getRemotePool( - uint64 remoteChainSelector - ) public view returns (bytes memory) { - return s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; - } - - /// @notice Gets the token address on the remote chain. - /// @param remoteChainSelector Remote chain selector. - /// @dev To support non-evm chains, this value is encoded into bytes - function getRemoteToken( - uint64 remoteChainSelector - ) public view returns (bytes memory) { - return s_remoteChainConfigs[remoteChainSelector].remoteTokenAddress; - } - - /// @notice Sets the remote pool address for a given chain selector. - /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. - /// @param remotePoolAddress The address of the remote pool. - function setRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - - bytes memory prevAddress = s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; - s_remoteChainConfigs[remoteChainSelector].remotePoolAddress = remotePoolAddress; - - emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); - } - - /// @inheritdoc IPoolV1 - function isSupportedChain( - uint64 remoteChainSelector - ) public view returns (bool) { - return s_remoteChainSelectors.contains(remoteChainSelector); - } - - /// @notice Get list of allowed chains - /// @return list of chains. - function getSupportedChains() public view returns (uint64[] memory) { - uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); - uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); - for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { - chainSelectors[i] = uint64(uint256ChainSelectors[i]); - } - - return chainSelectors; - } - - /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains - /// need to be allowed on the Router to interact with this pool. - /// @dev Only callable by the owner - /// @param chains A list of chains and their new permission status & rate limits. Rate limits - /// are only used when the chain is being added through `allowed` being true. - function applyChainUpdates( - ChainUpdate[] calldata chains - ) external virtual onlyOwner { - for (uint256 i = 0; i < chains.length; ++i) { - ChainUpdate memory update = chains[i]; - RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); - RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); - - if (update.allowed) { - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { - revert ChainAlreadyExists(update.remoteChainSelector); - } - - if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { - revert ZeroAddressNotAllowed(); - } - - s_remoteChainConfigs[update.remoteChainSelector] = RemoteChainConfig({ - outboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.outboundRateLimiterConfig.rate, - capacity: update.outboundRateLimiterConfig.capacity, - tokens: update.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.outboundRateLimiterConfig.isEnabled - }), - inboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.inboundRateLimiterConfig.rate, - capacity: update.inboundRateLimiterConfig.capacity, - tokens: update.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.inboundRateLimiterConfig.isEnabled - }), - remotePoolAddress: update.remotePoolAddress, - remoteTokenAddress: update.remoteTokenAddress - }); - - emit ChainAdded( - update.remoteChainSelector, - update.remoteTokenAddress, - update.outboundRateLimiterConfig, - update.inboundRateLimiterConfig - ); - } else { - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { - revert NonExistentChain(update.remoteChainSelector); - } - - delete s_remoteChainConfigs[update.remoteChainSelector]; - - emit ChainRemoved(update.remoteChainSelector); - } - } - } - - // ================================================================ - // │ Rate limiting │ - // ================================================================ - - /// @notice Sets the rate limiter admin address. - /// @dev Only callable by the owner. - /// @param rateLimitAdmin The new rate limiter admin address. - function setRateLimitAdmin( - address rateLimitAdmin - ) external onlyOwner { - s_rateLimitAdmin = rateLimitAdmin; - } - - /// @notice Gets the rate limiter admin address. - function getRateLimitAdmin() external view returns (address) { - return s_rateLimitAdmin; - } - - /// @notice Consumes outbound rate limiting capacity in this pool - function _consumeOutboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._consume(amount, address(i_token)); - } - - /// @notice Consumes inbound rate limiting capacity in this pool - function _consumeInboundRateLimit(uint64 remoteChainSelector, uint256 amount) internal { - s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._consume(amount, address(i_token)); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentOutboundRateLimiterState( - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentInboundRateLimiterState( - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); - } - - /// @notice Sets the chain rate limiter config. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. - /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function setChainRateLimiterConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) external { - if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); - - _setRateLimitConfig(remoteChainSelector, outboundConfig, inboundConfig); - } - - function _setRateLimitConfig( - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) internal { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - RateLimiter._validateTokenBucketConfig(outboundConfig, false); - s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._setTokenBucketConfig(outboundConfig); - RateLimiter._validateTokenBucketConfig(inboundConfig, false); - s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._setTokenBucketConfig(inboundConfig); - emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned onRamp for the given chain on the Router. - function _onlyOnRamp( - uint64 remoteChainSelector - ) internal view { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); - } - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned offRamp for the given chain on the Router. - function _onlyOffRamp( - uint64 remoteChainSelector - ) internal view { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - function _checkAllowList( - address sender - ) internal view { - if (i_allowlistEnabled) { - if (!s_allowList.contains(sender)) { - revert SenderNotAllowed(sender); - } - } - } - - /// @notice Gets whether the allowList functionality is enabled. - /// @return true is enabled, false if not. - function getAllowListEnabled() external view returns (bool) { - return i_allowlistEnabled; - } - - /// @notice Gets the allowed addresses. - /// @return The allowed addresses. - function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); - } - - /// @notice Apply updates to the allow list. - /// @param removes The addresses to be removed. - /// @param adds The addresses to be added. - function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { - _applyAllowListUpdates(removes, adds); - } - - /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. - function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { - if (!i_allowlistEnabled) revert AllowListNotEnabled(); - - for (uint256 i = 0; i < removes.length; ++i) { - address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { - emit AllowListRemove(toRemove); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - address toAdd = adds[i]; - if (toAdd == address(0)) { - continue; - } - if (s_allowList.add(toAdd)) { - emit AllowListAdd(toAdd); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol deleted file mode 100644 index 3691ef1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ /dev/null @@ -1,261 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; - -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {TokenPool} from "../TokenPool.sol"; -import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; -import {USDCBridgeMigrator} from "./USDCBridgeMigrator.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice A token pool for USDC which uses CCTP for supported chains and Lock/Release for all others -/// @dev The functionality from LockReleaseTokenPool.sol has been duplicated due to lack of compiler support for shared -/// constructors between parents -/// @dev The primary token mechanism in this pool is Burn/Mint with CCTP, with Lock/Release as the -/// secondary, opt in mechanism for chains not currently supporting CCTP. -contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { - using SafeERC20 for IERC20; - using EnumerableSet for EnumerableSet.UintSet; - - event LiquidityTransferred(address indexed from, uint64 indexed remoteChainSelector, uint256 amount); - event LiquidityProviderSet( - address indexed oldProvider, address indexed newProvider, uint64 indexed remoteChainSelector - ); - - event LockReleaseEnabled(uint64 indexed remoteChainSelector); - event LockReleaseDisabled(uint64 indexed remoteChainSelector); - - error LanePausedForCCTPMigration(uint64 remoteChainSelector); - error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); - - /// bytes4(keccak256("NO_CTTP_USE_LOCK_RELEASE")) - bytes4 public constant LOCK_RELEASE_FLAG = 0xd43c7897; - - /// @notice The address of the liquidity provider for a specific chain. - /// External liquidity is not required when there is one canonical token deployed to a chain, - /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant - /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold - mapping(uint64 remoteChainSelector => address liquidityProvider) internal s_liquidityProvider; - - constructor( - ITokenMessenger tokenMessenger, - IERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token), router) {} - - // ================================================================ - // │ Incoming/Outgoing Mechanisms | - // ================================================================ - - /// @notice Locks the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { - // // If the alternative mechanism (L/R) for chains which have it enabled - if (!shouldUseLockRelease(lockOrBurnIn.remoteChainSelector)) { - return super.lockOrBurn(lockOrBurnIn); - } - - // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. - // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected - if (s_proposedUSDCMigrationChain == lockOrBurnIn.remoteChainSelector) { - revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); - } - - return _lockReleaseOutgoingMessage(lockOrBurnIn); - } - - /// @notice Release tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - // Use CCTP Burn/Mint mechanism for chains which have it enabled. The LOCK_RELEASE_FLAG is used in sourcePoolData to - // discern this, since the source-chain will not be a hybrid-pool but a standard burn-mint. In the event of a - // stuck message after a migration has occured, and the message was not executed properly before the migration - // began, and locked tokens were not released until now, the message will already have been committed to with this - // flag so it is safe to release the tokens. The source USDC pool is trusted to send messages with the correct - // flag as well. - if (bytes4(releaseOrMintIn.sourcePoolData) != LOCK_RELEASE_FLAG) { - return super.releaseOrMint(releaseOrMintIn); - } - - return _lockReleaseIncomingMessage(releaseOrMintIn); - } - - /// @notice Contains the alternative mechanism for incoming tokens, in this implementation is "Release" incoming tokens - function _lockReleaseIncomingMessage( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) internal virtual returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - // Circle requires a supply-lock to prevent incoming messages once the migration process begins. - // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected - if (s_proposedUSDCMigrationChain == releaseOrMintIn.remoteChainSelector) { - revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); - } - - // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration - // If the chain has already been migrated, then this mapping would be zero, and the operation would underflow. - // This branch ensures that we're subtracting from the correct mapping. It is also safe to subtract from the - // excluded tokens mapping, as this function would only be invoked in the event of a stuck tx after a migration - if (s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] == 0) { - s_tokensExcludedFromBurn[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; - } else { - s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; - } - - // Release to the offRamp, which forwards it to the recipient - getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); - - emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - /// @notice Contains the alternative mechanism, in this implementation is "Lock" on outgoing tokens - function _lockReleaseOutgoingMessage( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) internal virtual returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - // Increase internal accounting of locked tokens for burnLockedUSDC() migration - s_lockedTokensByChainSelector[lockOrBurnIn.remoteChainSelector] += lockOrBurnIn.amount; - - emit Locked(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: abi.encode(LOCK_RELEASE_FLAG) - }); - } - - // ================================================================ - // │ Liquidity Management | - // ================================================================ - - /// @notice Gets LiquidityManager, can be address(0) if none is configured. - /// @return The current liquidity manager for the given chain selector - function getLiquidityProvider( - uint64 remoteChainSelector - ) external view returns (address) { - return s_liquidityProvider[remoteChainSelector]; - } - - /// @notice Sets the LiquidityManager address. - /// @dev Only callable by the owner. - function setLiquidityProvider(uint64 remoteChainSelector, address liquidityProvider) external onlyOwner { - address oldProvider = s_liquidityProvider[remoteChainSelector]; - - s_liquidityProvider[remoteChainSelector] = liquidityProvider; - - emit LiquidityProviderSet(oldProvider, liquidityProvider, remoteChainSelector); - } - - /// @notice Adds liquidity to the pool for a specific chain. The tokens should be approved first. - /// @dev Liquidity is expected to be added on a per chain basis. Parties are expected to provide liquidity for their - /// own chain which implements non canonical USDC and liquidity is not shared across lanes. - /// @dev Once liquidity is added, it is locked in the pool until it is removed by an incoming message on the - /// lock release mechanism. This is a hard requirement by Circle to ensure parity with the destination chain - /// supply is maintained. - /// @param amount The amount of tokens to provide as liquidity. - /// @param remoteChainSelector The chain for which liquidity is provided to. Necessary to ensure there's accurate - /// parity between locked USDC in this contract and the circulating supply on the remote chain - function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { - if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); - - s_lockedTokensByChainSelector[remoteChainSelector] += amount; - - i_token.safeTransferFrom(msg.sender, address(this), amount); - - emit ILiquidityContainer.LiquidityAdded(msg.sender, amount); - } - - /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. - /// @param remoteChainSelector The chain where liquidity is being released. - /// @param amount The amount of liquidity to remove. - /// @dev The function should only be called if non canonical USDC on the remote chain has been burned and is not being - /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply - /// which may block a potential future migration of the chain to CCTP. - function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external onlyOwner { - // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. - // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected - if (remoteChainSelector == s_proposedUSDCMigrationChain) { - revert LanePausedForCCTPMigration(remoteChainSelector); - } - - s_lockedTokensByChainSelector[remoteChainSelector] -= amount; - - i_token.safeTransfer(msg.sender, amount); - - emit ILiquidityContainer.LiquidityRemoved(msg.sender, amount); - } - - /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so - /// this pool must be the owner of the old pool. Since the pool uses two-step ownership transfer, the old pool must - /// first propose the ownership transfer, and then this pool must accept it. This function can only be called after - /// the ownership transfer has been proposed, as it will accept it and then make the call to withdrawLiquidity - /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the - /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. - /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before - /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the - /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its - /// liquidity. - /// @param from The address of the old pool. - /// @param remoteChainSelector The chain for which liquidity is being transferred. - function transferLiquidity(address from, uint64 remoteChainSelector) external onlyOwner { - // Prevent Liquidity Transfers when a migration is pending. This prevents requiring the new pool to manage - // token exclusions for edge-case messages and ensures that the migration is completed before any new liquidity - // is added to the pool. - if (HybridLockReleaseUSDCTokenPool(from).getCurrentProposedCCTPChainMigration() == remoteChainSelector) { - revert LanePausedForCCTPMigration(remoteChainSelector); - } - - OwnerIsCreator(from).acceptOwnership(); - - // Withdraw all available liquidity from the old pool. - uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); - HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); - - s_lockedTokensByChainSelector[remoteChainSelector] += withdrawAmount; - - emit LiquidityTransferred(from, remoteChainSelector, withdrawAmount); - } - - // ================================================================ - // │ Alt Mechanism Logic | - // ================================================================ - - /// @notice Return whether a lane should use the alternative L/R mechanism in the token pool. - /// @param remoteChainSelector the remote chain the lane is interacting with - /// @return bool Return true if the alternative L/R mechanism should be used - function shouldUseLockRelease( - uint64 remoteChainSelector - ) public view virtual returns (bool) { - return s_shouldUseLockRelease[remoteChainSelector]; - } - - /// @notice Updates Updates designations for chains on whether to use primary or alt mechanism on CCIP messages - /// @param removes A list of chain selectors to disable Lock-Release, and enforce BM - /// @param adds A list of chain selectors to enable LR instead of BM - function updateChainSelectorMechanisms(uint64[] calldata removes, uint64[] calldata adds) external onlyOwner { - for (uint256 i = 0; i < removes.length; ++i) { - delete s_shouldUseLockRelease[removes[i]]; - emit LockReleaseDisabled(removes[i]); - } - - for (uint256 i = 0; i < adds.length; ++i) { - s_shouldUseLockRelease[adds[i]] = true; - emit LockReleaseEnabled(adds[i]); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol deleted file mode 100644 index 1b2a0f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/IMessageTransmitter.sol +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2022, Circle Internet Financial Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pragma solidity ^0.8.0; - -interface IMessageTransmitter { - /// @notice Unlocks USDC tokens on the destination chain - /// @param message The original message on the source chain - /// * Message format: - /// * Field Bytes Type Index - /// * version 4 uint32 0 - /// * sourceDomain 4 uint32 4 - /// * destinationDomain 4 uint32 8 - /// * nonce 8 uint64 12 - /// * sender 32 bytes32 20 - /// * recipient 32 bytes32 52 - /// * destinationCaller 32 bytes32 84 - /// * messageBody dynamic bytes 116 - /// param attestation A valid attestation is the concatenated 65-byte signature(s) of - /// exactly `thresholdSignature` signatures, in increasing order of attester address. - /// ***If the attester addresses recovered from signatures are not in increasing order, - /// signature verification will fail.*** - /// If incorrect number of signatures or duplicate signatures are supplied, - /// signature verification will fail. - function receiveMessage(bytes calldata message, bytes calldata attestation) external returns (bool success); - - /// Returns domain of chain on which the contract is deployed. - /// @dev immutable - function localDomain() external view returns (uint32); - - /// Returns message format version. - /// @dev immutable - function version() external view returns (uint32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol deleted file mode 100644 index ce5923c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/ITokenMessenger.sol +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2022, Circle Internet Financial Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pragma solidity ^0.8.0; - -interface ITokenMessenger { - /// @notice Emitted when a DepositForBurn message is sent - /// @param nonce Unique nonce reserved by message - /// @param burnToken Address of token burnt on source domain - /// @param amount Deposit amount - /// @param depositor Address where deposit is transferred from - /// @param mintRecipient Address receiving minted tokens on destination domain as bytes32 - /// @param destinationDomain Destination domain - /// @param destinationTokenMessenger Address of TokenMessenger on destination domain as bytes32 - /// @param destinationCaller Authorized caller as bytes32 of receiveMessage() on destination domain, - /// if not equal to bytes32(0). If equal to bytes32(0), any address can call receiveMessage(). - event DepositForBurn( - uint64 indexed nonce, - address indexed burnToken, - uint256 amount, - address indexed depositor, - bytes32 mintRecipient, - uint32 destinationDomain, - bytes32 destinationTokenMessenger, - bytes32 destinationCaller - ); - - /// @notice Burns the tokens on the source side to produce a nonce through - /// Circles Cross Chain Transfer Protocol. - /// @param amount Amount of tokens to deposit and burn. - /// @param destinationDomain Destination domain identifier. - /// @param mintRecipient Address of mint recipient on destination domain. - /// @param burnToken Address of contract to burn deposited tokens, on local domain. - /// @param destinationCaller Caller on the destination domain, as bytes32. - /// @return nonce The unique nonce used in unlocking the funds on the destination chain. - /// @dev emits DepositForBurn - function depositForBurnWithCaller( - uint256 amount, - uint32 destinationDomain, - bytes32 mintRecipient, - address burnToken, - bytes32 destinationCaller - ) external returns (uint64 nonce); - - /// Returns the version of the message body format. - /// @dev immutable - function messageBodyVersion() external view returns (uint32); - - /// Returns local Message Transmitter responsible for sending and receiving messages - /// to/from remote domainsmessage transmitter for this token messenger. - /// @dev immutable - function localMessageTransmitter() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol deleted file mode 100644 index 4737a83..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol +++ /dev/null @@ -1,162 +0,0 @@ -pragma solidity ^0.8.24; - -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -import {Router} from "../../Router.sol"; - -/// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract -/// functionality is based on hard requirements defined by Circle to allow for future CCTP compatibility -/// https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md -abstract contract USDCBridgeMigrator is OwnerIsCreator { - using EnumerableSet for EnumerableSet.UintSet; - - event CCTPMigrationProposed(uint64 remoteChainSelector); - event CCTPMigrationExecuted(uint64 remoteChainSelector, uint256 USDCBurned); - event CCTPMigrationCancelled(uint64 existingProposalSelector); - event CircleMigratorAddressSet(address migratorAddress); - event TokensExcludedFromBurn( - uint64 indexed remoteChainSelector, uint256 amount, uint256 burnableAmountAfterExclusion - ); - - error onlyCircle(); - error ExistingMigrationProposal(); - error NoExistingMigrationProposal(); - error NoMigrationProposalPending(); - error InvalidChainSelector(uint64 remoteChainSelector); - - IBurnMintERC20 internal immutable i_USDC; - Router internal immutable i_router; - - address internal s_circleUSDCMigrator; - uint64 internal s_proposedUSDCMigrationChain; - - mapping(uint64 chainSelector => uint256 lockedBalance) internal s_lockedTokensByChainSelector; - mapping(uint64 remoteChainSelector => uint256 excludedTokens) internal s_tokensExcludedFromBurn; - - mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; - - constructor(address token, address router) { - i_USDC = IBurnMintERC20(token); - i_router = Router(router); - } - - /// @notice Burn USDC locked for a specific lane so that destination USDC can be converted from - /// non-canonical to canonical USDC. - /// @dev This function can only be called by an address specified by the owner to be controlled by circle - /// @dev proposeCCTPMigration must be called first on an approved lane to execute properly. - /// @dev This function signature should NEVER be overwritten, otherwise it will be unable to be called by - /// circle to properly migrate USDC over to CCTP. - function burnLockedUSDC() public { - if (msg.sender != s_circleUSDCMigrator) revert onlyCircle(); - if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); - - uint64 burnChainSelector = s_proposedUSDCMigrationChain; - - // Burnable tokens is the total locked minus the amount excluded from burn - uint256 tokensToBurn = - s_lockedTokensByChainSelector[burnChainSelector] - s_tokensExcludedFromBurn[burnChainSelector]; - - // Even though USDC is a trusted call, ensure CEI by updating state first - delete s_lockedTokensByChainSelector[burnChainSelector]; - delete s_proposedUSDCMigrationChain; - - // This should only be called after this contract has been granted a "zero allowance minter role" on USDC by Circle, - // otherwise the call will revert. Executing this burn will functionally convert all USDC on the destination chain - // to canonical USDC by removing the canonical USDC backing it from circulation. - i_USDC.burn(tokensToBurn); - - // Disable L/R automatically on burned chain and enable CCTP - delete s_shouldUseLockRelease[burnChainSelector]; - - emit CCTPMigrationExecuted(burnChainSelector, tokensToBurn); - } - - /// @notice Propose a destination chain to migrate from lock/release mechanism to CCTP enabled burn/mint - /// through a Circle controlled burn. - /// @param remoteChainSelector the CCIP specific selector for the remote chain currently using a - /// non-canonical form of USDC which they wish to update to canonical. Function will revert if an existing migration - /// proposal is already in progress. - /// @dev This function can only be called by the owner - function proposeCCTPMigration( - uint64 remoteChainSelector - ) external onlyOwner { - // Prevent overwriting existing migration proposals until the current one is finished - if (s_proposedUSDCMigrationChain != 0) revert ExistingMigrationProposal(); - - s_proposedUSDCMigrationChain = remoteChainSelector; - - emit CCTPMigrationProposed(remoteChainSelector); - } - - /// @notice Cancel an existing proposal to migrate a lane to CCTP. - /// @notice This function will revert if no proposal is currently in progress. - function cancelExistingCCTPMigrationProposal() external onlyOwner { - if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); - - uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; - delete s_proposedUSDCMigrationChain; - - // If a migration is cancelled, the tokens excluded from burn should be reset, and must be manually - // re-excluded if the proposal is re-proposed in the future - delete s_tokensExcludedFromBurn[currentProposalChainSelector]; - - emit CCTPMigrationCancelled(currentProposalChainSelector); - } - - /// @notice retrieve the chain selector for an ongoing CCTP migration in progress. - /// @return uint64 the chain selector of the lane to be migrated. Will be zero if no proposal currently - /// exists - function getCurrentProposedCCTPChainMigration() public view returns (uint64) { - return s_proposedUSDCMigrationChain; - } - - /// @notice Set the address of the circle-controlled wallet which will execute a CCTP lane migration - /// @dev The function should only be invoked once the address has been confirmed by Circle prior to - /// chain expansion. - function setCircleMigratorAddress( - address migrator - ) external onlyOwner { - s_circleUSDCMigrator = migrator; - - emit CircleMigratorAddressSet(migrator); - } - - /// @notice Retrieve the amount of canonical USDC locked into this lane and minted on the destination - /// @param remoteChainSelector the CCIP specific destination chain implementing a mintable and - /// non-canonical form of USDC at present. - /// @return uint256 the amount of USDC locked into the specified lane. If non-zero, the number - /// should match the current circulating supply of USDC on the destination chain - function getLockedTokensForChain( - uint64 remoteChainSelector - ) public view returns (uint256) { - return s_lockedTokensByChainSelector[remoteChainSelector]; - } - - /// @notice Exclude tokens to be burned in a CCTP-migration because the amount are locked in an undelivered message. - /// @dev When a message is sitting in manual execution from the L/R chain, those tokens need to be excluded from - /// being burned in a CCTP-migration otherwise the message will never be able to be delivered due to it not having - /// an attestation on the source-chain to mint. In that instance it should use provided liquidity that was designated - /// @dev This function should ONLY be called on the home chain, where tokens are locked, NOT on the remote chain - /// and strict scrutiny should be applied to ensure that the amount of tokens excluded is accurate. - function excludeTokensFromBurn(uint64 remoteChainSelector, uint256 amount) external onlyOwner { - s_tokensExcludedFromBurn[remoteChainSelector] += amount; - - uint256 burnableAmountAfterExclusion = - s_lockedTokensByChainSelector[remoteChainSelector] - s_tokensExcludedFromBurn[remoteChainSelector]; - - emit TokensExcludedFromBurn(remoteChainSelector, amount, burnableAmountAfterExclusion); - } - - /// @notice Get the amount of tokens excluded from being burned in a CCTP-migration - /// @dev The sum of locked tokens and excluded tokens should equal the supply of the token on the remote chain - /// @param remoteChainSelector The chain for which the excluded tokens are being queried - /// @return uint256 amount of tokens excluded from being burned in a CCTP-migration - function getExcludedTokensByChain( - uint64 remoteChainSelector - ) public view returns (uint256) { - return s_tokensExcludedFromBurn[remoteChainSelector]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol deleted file mode 100644 index addfe06..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IMessageTransmitter} from "./IMessageTransmitter.sol"; -import {ITokenMessenger} from "./ITokenMessenger.sol"; - -import {Pool} from "../../libraries/Pool.sol"; -import {TokenPool} from "../TokenPool.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice This pool mints and burns USDC tokens through the Cross Chain Transfer -/// Protocol (CCTP). -contract USDCTokenPool is TokenPool, ITypeAndVersion { - using SafeERC20 for IERC20; - - event DomainsSet(DomainUpdate[]); - event ConfigSet(address tokenMessenger); - - error UnknownDomain(uint64 domain); - error UnlockingUSDCFailed(); - error InvalidConfig(); - error InvalidDomain(DomainUpdate domain); - error InvalidMessageVersion(uint32 version); - error InvalidTokenMessengerVersion(uint32 version); - error InvalidNonce(uint64 expected, uint64 got); - error InvalidSourceDomain(uint32 expected, uint32 got); - error InvalidDestinationDomain(uint32 expected, uint32 got); - error InvalidReceiver(bytes receiver); - - // This data is supplied from offchain and contains everything needed - // to receive the USDC tokens. - struct MessageAndAttestation { - bytes message; - bytes attestation; - } - - // A domain is a USDC representation of a chain. - struct DomainUpdate { - bytes32 allowedCaller; // Address allowed to mint on the domain - uint32 domainIdentifier; // ──╮ Unique domain ID - uint64 destChainSelector; // │ The destination chain for this domain - bool enabled; // ─────────────╯ Whether the domain is enabled - } - - struct SourceTokenDataPayload { - uint64 nonce; - uint32 sourceDomain; - } - - string public constant override typeAndVersion = "USDCTokenPool 1.5.0"; - - // We restrict to the first version. New pool may be required for subsequent versions. - uint32 public constant SUPPORTED_USDC_VERSION = 0; - - // The local USDC config - ITokenMessenger public immutable i_tokenMessenger; - IMessageTransmitter public immutable i_messageTransmitter; - uint32 public immutable i_localDomainIdentifier; - - /// A domain is a USDC representation of a destination chain. - /// @dev Zero is a valid domain identifier. - /// @dev The address to mint on the destination chain is the corresponding USDC pool. - struct Domain { - bytes32 allowedCaller; // Address allowed to mint on the domain - uint32 domainIdentifier; // ─╮ Unique domain ID - bool enabled; // ────────────╯ Whether the domain is enabled - } - - // A mapping of CCIP chain identifiers to destination domains - mapping(uint64 chainSelector => Domain CCTPDomain) private s_chainToDomain; - - constructor( - ITokenMessenger tokenMessenger, - IERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) { - if (address(tokenMessenger) == address(0)) revert InvalidConfig(); - IMessageTransmitter transmitter = IMessageTransmitter(tokenMessenger.localMessageTransmitter()); - uint32 transmitterVersion = transmitter.version(); - if (transmitterVersion != SUPPORTED_USDC_VERSION) revert InvalidMessageVersion(transmitterVersion); - uint32 tokenMessengerVersion = tokenMessenger.messageBodyVersion(); - if (tokenMessengerVersion != SUPPORTED_USDC_VERSION) revert InvalidTokenMessengerVersion(tokenMessengerVersion); - - i_tokenMessenger = tokenMessenger; - i_messageTransmitter = transmitter; - i_localDomainIdentifier = transmitter.localDomain(); - i_token.safeIncreaseAllowance(address(i_tokenMessenger), type(uint256).max); - emit ConfigSet(address(tokenMessenger)); - } - - /// @notice Burn the token in the pool - /// @dev emits ITokenMessenger.DepositForBurn - /// @dev Assumes caller has validated destinationReceiver - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - Domain memory domain = s_chainToDomain[lockOrBurnIn.remoteChainSelector]; - if (!domain.enabled) revert UnknownDomain(lockOrBurnIn.remoteChainSelector); - - if (lockOrBurnIn.receiver.length != 32) { - revert InvalidReceiver(lockOrBurnIn.receiver); - } - bytes32 decodedReceiver = abi.decode(lockOrBurnIn.receiver, (bytes32)); - - // Since this pool is the msg sender of the CCTP transaction, only this contract - // is able to call replaceDepositForBurn. Since this contract does not implement - // replaceDepositForBurn, the tokens cannot be maliciously re-routed to another address. - uint64 nonce = i_tokenMessenger.depositForBurnWithCaller( - lockOrBurnIn.amount, domain.domainIdentifier, decodedReceiver, address(i_token), domain.allowedCaller - ); - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: abi.encode(SourceTokenDataPayload({nonce: nonce, sourceDomain: i_localDomainIdentifier})) - }); - } - - /// @notice Mint tokens from the pool to the recipient - /// * sourceTokenData is part of the verified message and passed directly from - /// the offramp so it is guaranteed to be what the lockOrBurn pool released on the - /// source chain. It contains (nonce, sourceDomain) which is guaranteed by CCTP - /// to be unique. - /// * offchainTokenData is untrusted (can be supplied by manual execution), but we assert - /// that (nonce, sourceDomain) is equal to the message's (nonce, sourceDomain) and - /// receiveMessage will assert that Attestation contains a valid attestation signature - /// for that message, including its (nonce, sourceDomain). This way, the only - /// non-reverting offchainTokenData that can be supplied is a valid attestation for the - /// specific message that was sent on source. - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - SourceTokenDataPayload memory sourceTokenDataPayload = - abi.decode(releaseOrMintIn.sourcePoolData, (SourceTokenDataPayload)); - MessageAndAttestation memory msgAndAttestation = - abi.decode(releaseOrMintIn.offchainTokenData, (MessageAndAttestation)); - - _validateMessage(msgAndAttestation.message, sourceTokenDataPayload); - - if (!i_messageTransmitter.receiveMessage(msgAndAttestation.message, msgAndAttestation.attestation)) { - revert UnlockingUSDCFailed(); - } - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - /// @notice Validates the USDC encoded message against the given parameters. - /// @param usdcMessage The USDC encoded message - /// @param sourceTokenData The expected source chain token data to check against - /// @dev Only supports version SUPPORTED_USDC_VERSION of the CCTP message format - /// @dev Message format for USDC: - /// * Field Bytes Type Index - /// * version 4 uint32 0 - /// * sourceDomain 4 uint32 4 - /// * destinationDomain 4 uint32 8 - /// * nonce 8 uint64 12 - /// * sender 32 bytes32 20 - /// * recipient 32 bytes32 52 - /// * destinationCaller 32 bytes32 84 - /// * messageBody dynamic bytes 116 - function _validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) internal view { - uint32 version; - // solhint-disable-next-line no-inline-assembly - assembly { - // We truncate using the datatype of the version variable, meaning - // we will only be left with the first 4 bytes of the message. - version := mload(add(usdcMessage, 4)) // 0 + 4 = 4 - } - // This token pool only supports version 0 of the CCTP message format - // We check the version prior to loading the rest of the message - // to avoid unexpected reverts due to out-of-bounds reads. - if (version != SUPPORTED_USDC_VERSION) revert InvalidMessageVersion(version); - - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - - // solhint-disable-next-line no-inline-assembly - assembly { - sourceDomain := mload(add(usdcMessage, 8)) // 4 + 4 = 8 - destinationDomain := mload(add(usdcMessage, 12)) // 8 + 4 = 12 - nonce := mload(add(usdcMessage, 20)) // 12 + 8 = 20 - } - - if (sourceDomain != sourceTokenData.sourceDomain) { - revert InvalidSourceDomain(sourceTokenData.sourceDomain, sourceDomain); - } - if (destinationDomain != i_localDomainIdentifier) { - revert InvalidDestinationDomain(i_localDomainIdentifier, destinationDomain); - } - if (nonce != sourceTokenData.nonce) revert InvalidNonce(sourceTokenData.nonce, nonce); - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Gets the CCTP domain for a given CCIP chain selector. - function getDomain( - uint64 chainSelector - ) external view returns (Domain memory) { - return s_chainToDomain[chainSelector]; - } - - /// @notice Sets the CCTP domain for a CCIP chain selector. - /// @dev Must verify mapping of selectors -> (domain, caller) offchain. - function setDomains( - DomainUpdate[] calldata domains - ) external onlyOwner { - for (uint256 i = 0; i < domains.length; ++i) { - DomainUpdate memory domain = domains[i]; - if (domain.allowedCaller == bytes32(0) || domain.destChainSelector == 0) revert InvalidDomain(domain); - - s_chainToDomain[domain.destChainSelector] = Domain({ - domainIdentifier: domain.domainIdentifier, - allowedCaller: domain.allowedCaller, - enabled: domain.enabled - }); - } - emit DomainsSet(domains); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol deleted file mode 100644 index 9645826..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/ARMProxy.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; - -/// @notice The ARMProxy serves to allow CCIP contracts -/// to point to a static address for ARM queries, which saves gas -/// since each contract need not store an ARM address in storage. That way -/// we can add ARM queries along many code paths for increased defense in depth -/// with minimal additional cost. -contract ARMProxy is OwnerIsCreator, ITypeAndVersion { - error ZeroAddressNotAllowed(); - - event ARMSet(address arm); - - // STATIC CONFIG - string public constant override typeAndVersion = "ARMProxy 1.0.0"; - - // DYNAMIC CONFIG - address private s_arm; - - constructor( - address arm - ) { - setARM(arm); - } - - /// @notice SetARM sets the ARM implementation contract address. - /// @param arm The address of the arm implementation contract. - function setARM( - address arm - ) public onlyOwner { - if (arm == address(0)) revert ZeroAddressNotAllowed(); - s_arm = arm; - emit ARMSet(arm); - } - - /// @notice getARM gets the ARM implementation contract address. - /// @return arm The address of the arm implementation contract. - function getARM() external view returns (address) { - return s_arm; - } - - // We use a fallback function instead of explicit implementations of the functions - // defined in IRMN.sol to preserve compatibility with future additions to the IRMN - // interface. Calling IRMN interface methods in ARMProxy should be transparent, i.e. - // their input/output behaviour should be identical to calling the proxied s_arm - // contract directly. (If s_arm doesn't point to a contract, we always revert.) - // solhint-disable-next-line payable-fallback, no-complex-fallback - fallback() external { - address arm = s_arm; - // solhint-disable-next-line no-inline-assembly - assembly { - // Revert if no contract present at destination address, otherwise call - // might succeed unintentionally. - if iszero(extcodesize(arm)) { revert(0, 0) } - // We use memory starting at zero, overwriting anything that might already - // be stored there. This messes with Solidity's expectations around memory - // layout, but it's fine because we always exit execution of this contract - // inside this assembly block, i.e. we don't cede control to code generated - // by the Solidity compiler that might have expectations around memory - // layout. - // Copy calldatasize() bytes from calldata offset 0 to memory offset 0. - calldatacopy(0, 0, calldatasize()) - // Call the underlying ARM implementation. out and outsize are 0 because - // we don't know the size yet. We hardcode value to zero. - let success := call(gas(), arm, 0, 0, calldatasize(), 0, 0) - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - // Pass through successful return or revert and associated data. - if success { return(0, returndatasize()) } - revert(0, returndatasize()) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol deleted file mode 100644 index 978b200..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ /dev/null @@ -1,395 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; - -/// @notice Stores the home configuration for RMN, that is referenced by CCIP oracles, RMN nodes, and the RMNRemote -/// contracts. -/// @dev This contract is a state machine with the following states: -/// - Init: The initial state of the contract, no config has been set, or all configs have been revoked. -/// [0, 0] -/// -/// - Candidate: A new config has been set, but it has not been promoted yet, or all active configs have been revoked. -/// [0, 1] -/// -/// - Active: A non-zero config has been promoted and is active, there is no candidate configured. -/// [1, 0] -/// -/// - ActiveAndCandidate: A non-zero config has been promoted and is active, and a new config has been set as candidate. -/// [1, 1] -/// -/// The following state transitions are allowed: -/// - Init -> Candidate: setCandidate() -/// - Candidate -> Active: promoteCandidateAndRevokeActive() -/// - Candidate -> Candidate: setCandidate() -/// - Candidate -> Init: revokeCandidate() -/// - Active -> ActiveAndCandidate: setCandidate() -/// - Active -> Init: promoteCandidateAndRevokeActive() -/// - ActiveAndCandidate -> Active: promoteCandidateAndRevokeActive() -/// - ActiveAndCandidate -> Active: revokeCandidate() -/// - ActiveAndCandidate -> ActiveAndCandidate: setCandidate() -/// -/// This means the following calls are not allowed at the following states: -/// - Init: promoteCandidateAndRevokeActive(), as there is no config to promote. -/// - Init: revokeCandidate(), as there is no config to revoke -/// - Active: revokeCandidate(), as there is no candidate to revoke -/// Note that we explicitly do allow promoteCandidateAndRevokeActive() to be called when there is an active config but -/// no candidate config. This is the only way to remove the active config. The alternative would be to set some unusable -/// config as candidate and promote that, but fully clearing it is cleaner. -/// -/// ┌─────────────┐ setCandidate ┌─────────────┐ -/// │ ├───────────────────►│ │ setCandidate -/// │ Init │ revokeCandidate │ Candidate │◄───────────┐ -/// │ [0,0] │◄───────────────────┤ [0,1] │────────────┘ -/// │ │ ┌─────────────────┤ │ -/// └─────────────┘ │ promote- └─────────────┘ -/// ▲ │ Candidate -/// promote- │ │ -/// Candidate │ │ -/// │ │ -/// ┌──────────┴──┐ │ promote- ┌─────────────┐ -/// │ │◄─┘ Candidate OR │ Active & │ setCandidate -/// │ Active │ revokeCandidate │ Candidate │◄───────────┐ -/// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ -/// │ ├───────────────────►│ │ -/// └─────────────┘ setSecondary └─────────────┘ -/// -contract RMNHome is OwnerIsCreator, ITypeAndVersion { - event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); - event ActiveConfigRevoked(bytes32 indexed configDigest); - event CandidateConfigRevoked(bytes32 indexed configDigest); - event DynamicConfigSet(bytes32 indexed configDigest, DynamicConfig dynamicConfig); - event ConfigPromoted(bytes32 indexed configDigest); - - error OutOfBoundsNodesLength(); - error DuplicatePeerId(); - error DuplicateOffchainPublicKey(); - error DuplicateSourceChain(); - error OutOfBoundsObserverNodeIndex(); - error MinObserversTooHigh(); - error ConfigDigestMismatch(bytes32 expectedConfigDigest, bytes32 gotConfigDigest); - error DigestNotFound(bytes32 configDigest); - error RevokingZeroDigestNotAllowed(); - error NoOpStateTransitionNotAllowed(); - - struct Node { - bytes32 peerId; // Used for p2p communication. - bytes32 offchainPublicKey; // Observations are signed with this public key, and are only verified offchain. - } - - struct SourceChain { - uint64 chainSelector; // ─────╮ The Source chain selector. - uint64 minObservers; // ──────╯ Required number of observers to agree on an observation for this source chain. - // ObserverNodesBitmap & (1< MAX_NODES) { - revert OutOfBoundsNodesLength(); - } - - // Ensure no peerId or offchainPublicKey is duplicated. - for (uint256 i = 0; i < staticConfig.nodes.length; ++i) { - for (uint256 j = i + 1; j < staticConfig.nodes.length; ++j) { - if (staticConfig.nodes[i].peerId == staticConfig.nodes[j].peerId) { - revert DuplicatePeerId(); - } - if (staticConfig.nodes[i].offchainPublicKey == staticConfig.nodes[j].offchainPublicKey) { - revert DuplicateOffchainPublicKey(); - } - } - } - - _validateDynamicConfig(dynamicConfig, staticConfig.nodes.length); - } - - /// @notice Validates the dynamic config. Reverts when the config is invalid. - /// @param dynamicConfig The dynamic part of the config. - /// @param numberOfNodes The number of nodes in the static config. - function _validateDynamicConfig(DynamicConfig memory dynamicConfig, uint256 numberOfNodes) internal pure { - uint256 numberOfSourceChains = dynamicConfig.sourceChains.length; - for (uint256 i = 0; i < numberOfSourceChains; ++i) { - SourceChain memory currentSourceChain = dynamicConfig.sourceChains[i]; - // Ensure the source chain is unique. - for (uint256 j = i + 1; j < numberOfSourceChains; ++j) { - if (currentSourceChain.chainSelector == dynamicConfig.sourceChains[j].chainSelector) { - revert DuplicateSourceChain(); - } - } - - // all observer node indices are valid - uint256 bitmap = currentSourceChain.observerNodesBitmap; - // Check if there are any bits set for indexes outside of the expected range. - if (bitmap & (type(uint256).max >> (256 - numberOfNodes)) != bitmap) { - revert OutOfBoundsObserverNodeIndex(); - } - - uint256 observersCount = 0; - for (; bitmap != 0; ++observersCount) { - bitmap &= bitmap - 1; - } - - // minObservers are tenable - if (currentSourceChain.minObservers > observersCount) { - revert MinObserversTooHigh(); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol deleted file mode 100644 index 6a4366e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/rmn/RMNRemote.sol +++ /dev/null @@ -1,261 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; -import {Internal} from "../libraries/Internal.sol"; - -/// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a -/// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is -/// deployed, relying on isCursed(). -bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; - -/// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject for -/// issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using -/// the local chain selector as a subject. -bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; - -/// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. -contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNRemote { - using EnumerableSet for EnumerableSet.Bytes16Set; - - error AlreadyCursed(bytes16 subject); - error ConfigNotSet(); - error DuplicateOnchainPublicKey(); - error InvalidSignature(); - error InvalidSignerOrder(); - error MinSignersTooHigh(); - error NotCursed(bytes16 subject); - error OutOfOrderSignatures(); - error ThresholdNotMet(); - error UnexpectedSigner(); - error ZeroValueNotAllowed(); - - event ConfigSet(uint32 indexed version, Config config); - event Cursed(bytes16[] subjects); - event Uncursed(bytes16[] subjects); - - /// @dev the configuration of an RMN signer - struct Signer { - address onchainPublicKey; // ────╮ For signing reports - uint64 nodeIndex; // ────────────╯ Maps to nodes in home chain config, should be strictly increasing - } - - /// @dev the contract config - /// @dev note: minSigners can be set to 0 to disable verification for chains without RMN support - struct Config { - bytes32 rmnHomeContractConfigDigest; // Digest of the RMNHome contract config - Signer[] signers; // List of signers - uint64 minSigners; // Threshold for the number of signers required to verify a report - } - - /// @dev part of the payload that RMN nodes sign: keccak256(abi.encode(RMN_V1_6_ANY2EVM_REPORT, report)) - /// @dev this struct is only ever abi-encoded and hashed; it is never stored - struct Report { - uint256 destChainId; // To guard against chain selector misconfiguration - uint64 destChainSelector; // ────────────╮ The chain selector of the destination chain - address rmnRemoteContractAddress; // ─────╯ The address of this contract - address offrampAddress; // The address of the offramp on the same chain as this contract - bytes32 rmnHomeContractConfigDigest; // The digest of the RMNHome contract config - Internal.MerkleRoot[] merkleRoots; // The dest lane updates - } - - /// @dev this is included in the preimage of the digest that RMN nodes sign - bytes32 private constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); - - string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; - uint64 internal immutable i_localChainSelector; - - Config private s_config; - uint32 private s_configCount; - - EnumerableSet.Bytes16Set private s_cursedSubjects; - mapping(address signer => bool exists) private s_signers; // for more gas efficient verify - - /// @param localChainSelector the chain selector of the chain this contract is deployed to - constructor( - uint64 localChainSelector - ) { - if (localChainSelector == 0) revert ZeroValueNotAllowed(); - i_localChainSelector = localChainSelector; - } - - // ================================================================ - // │ Verification │ - // ================================================================ - - /// @inheritdoc IRMNRemote - function verify( - address offrampAddress, - Internal.MerkleRoot[] calldata merkleRoots, - Signature[] calldata signatures, - uint256 rawVs - ) external view { - if (s_configCount == 0) { - revert ConfigNotSet(); - } - if (signatures.length < s_config.minSigners) revert ThresholdNotMet(); - - bytes32 digest = keccak256( - abi.encode( - RMN_V1_6_ANY2EVM_REPORT, - Report({ - destChainId: block.chainid, - destChainSelector: i_localChainSelector, - rmnRemoteContractAddress: address(this), - offrampAddress: offrampAddress, - rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, - merkleRoots: merkleRoots - }) - ) - ); - - address prevAddress; - address signerAddress; - for (uint256 i = 0; i < signatures.length; ++i) { - // The v value is bit-encoded into rawVs - signerAddress = ecrecover(digest, 27 + uint8(rawVs & 0x01 << i), signatures[i].r, signatures[i].s); - if (signerAddress == address(0)) revert InvalidSignature(); - if (prevAddress >= signerAddress) revert OutOfOrderSignatures(); - if (!s_signers[signerAddress]) revert UnexpectedSigner(); - prevAddress = signerAddress; - } - } - - // ================================================================ - // │ Config │ - // ================================================================ - - /// @notice Sets the configuration of the contract - /// @param newConfig the new configuration - /// @dev setting config is atomic; we delete all pre-existing config and set everything from scratch - function setConfig( - Config calldata newConfig - ) external onlyOwner { - // signers are in ascending order of nodeIndex - for (uint256 i = 1; i < newConfig.signers.length; ++i) { - if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { - revert InvalidSignerOrder(); - } - } - - // minSigners is tenable - if (!(newConfig.minSigners <= newConfig.signers.length)) { - revert MinSignersTooHigh(); - } - - // clear the old signers - for (uint256 i = s_config.signers.length; i > 0; --i) { - delete s_signers[s_config.signers[i - 1].onchainPublicKey]; - } - - // set the new signers - for (uint256 i = 0; i < newConfig.signers.length; ++i) { - if (s_signers[newConfig.signers[i].onchainPublicKey]) { - revert DuplicateOnchainPublicKey(); - } - s_signers[newConfig.signers[i].onchainPublicKey] = true; - } - - s_config = newConfig; - uint32 newConfigCount = ++s_configCount; - emit ConfigSet(newConfigCount, newConfig); - } - - /// @notice Returns the current configuration of the contract and a version number - /// @return version the current configs version - /// @return config the current config - function getVersionedConfig() external view returns (uint32 version, Config memory config) { - return (s_configCount, s_config); - } - - /// @notice Returns the chain selector configured at deployment time - /// @return localChainSelector the chain selector (not the chain ID) - function getLocalChainSelector() external view returns (uint64 localChainSelector) { - return i_localChainSelector; - } - - /// @notice Returns the 32 byte header used in computing the report digest - /// @return digestHeader the digest header - function getReportDigestHeader() external pure returns (bytes32 digestHeader) { - return RMN_V1_6_ANY2EVM_REPORT; - } - - // ================================================================ - // │ Cursing │ - // ================================================================ - - /// @notice Curse a single subject - /// @param subject the subject to curse - function curse( - bytes16 subject - ) external { - bytes16[] memory subjects = new bytes16[](1); - subjects[0] = subject; - curse(subjects); - } - - /// @notice Curse an array of subjects - /// @param subjects the subjects to curse - /// @dev reverts if any of the subjects are already cursed or if there is a duplicate - function curse( - bytes16[] memory subjects - ) public onlyOwner { - for (uint256 i = 0; i < subjects.length; ++i) { - if (!s_cursedSubjects.add(subjects[i])) { - revert AlreadyCursed(subjects[i]); - } - } - emit Cursed(subjects); - } - - /// @notice Uncurse a single subject - /// @param subject the subject to uncurse - function uncurse( - bytes16 subject - ) external { - bytes16[] memory subjects = new bytes16[](1); - subjects[0] = subject; - uncurse(subjects); - } - - /// @notice Uncurse an array of subjects - /// @param subjects the subjects to uncurse - /// @dev reverts if any of the subjects are not cursed or if there is a duplicate - function uncurse( - bytes16[] memory subjects - ) public onlyOwner { - for (uint256 i = 0; i < subjects.length; ++i) { - if (!s_cursedSubjects.remove(subjects[i])) { - revert NotCursed(subjects[i]); - } - } - emit Uncursed(subjects); - } - - /// @inheritdoc IRMNRemote - function getCursedSubjects() external view returns (bytes16[] memory subjects) { - return s_cursedSubjects.values(); - } - - /// @inheritdoc IRMNRemote - function isCursed() external view returns (bool) { - if (s_cursedSubjects.length() == 0) { - return false; - } - return s_cursedSubjects.contains(LEGACY_CURSE_SUBJECT) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); - } - - /// @inheritdoc IRMNRemote - function isCursed( - bytes16 subject - ) external view returns (bool) { - if (s_cursedSubjects.length() == 0) { - return false; - } - return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol deleted file mode 100644 index ea75b4e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -// Imports to any non-library are not allowed due to the significant cascading -// compile time increase they cause when imported into this base test. - -import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {MockRMN} from "./mocks/MockRMN.sol"; -import {Test} from "forge-std/Test.sol"; - -contract BaseTest is Test { - // Addresses - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - address internal constant STRANGER = address(999999); - address internal constant DUMMY_CONTRACT_ADDRESS = 0x1111111111111111111111111111111111111112; - address internal constant ON_RAMP_ADDRESS = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; - address internal constant ZERO_ADDRESS = address(0); - address internal constant FEE_AGGREGATOR = 0xa33CDB32eAEce34F6affEfF4899cef45744EDea3; - - address internal constant USER_1 = address(1); - address internal constant USER_2 = address(2); - address internal constant USER_3 = address(3); - address internal constant USER_4 = address(4); - - // Message info - uint64 internal constant SOURCE_CHAIN_SELECTOR = 1; - uint64 internal constant DEST_CHAIN_SELECTOR = 2; - uint32 internal constant GAS_LIMIT = 200_000; - - // Timing - uint256 internal constant BLOCK_TIME = 1234567890; - uint32 internal constant TWELVE_HOURS = 60 * 60 * 12; - - // Onramp - uint96 internal constant MAX_NOP_FEES_JUELS = 1e27; - uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; - uint32 internal constant DEST_GAS_OVERHEAD = 300_000; - uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE = 16; - - uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; - uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 90_000; - uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; - - bool private s_baseTestInitialized; - - // Use 16 gas per data availability byte in our tests. - // This is an overestimation in OP stack, it ignores 4 gas per 0 byte rule. - // Arbitrum on the other hand, does always use 16 gas per data availability byte. - // This value may be substantially decreased after EIP 4844. - uint16 internal constant DEST_GAS_PER_DATA_AVAILABILITY_BYTE = 16; - - // Total L1 data availability overhead estimate is 33_596 gas. - // This value includes complete CommitStore and OffRamp call data. - uint32 internal constant DEST_DATA_AVAILABILITY_OVERHEAD_GAS = 188 // Fixed data availability overhead in OP stack. - + (32 * 31 + 4) * DEST_GAS_PER_DATA_AVAILABILITY_BYTE // CommitStore single-root transmission takes up about 31 slots, plus selector. - + (32 * 34 + 4) * DEST_GAS_PER_DATA_AVAILABILITY_BYTE; // OffRamp transmission excluding EVM2EVMMessage takes up about 34 slots, plus selector. - - // Multiples of bps, or 0.0001, use 6840 to be same as OP mainnet compression factor of 0.684. - uint16 internal constant DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS = 6840; - - // OffRamp - uint32 internal constant MAX_DATA_SIZE = 30_000; - uint16 internal constant MAX_TOKENS_LENGTH = 5; - uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5000; - uint32 internal constant PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS = 500; - uint32 internal constant MAX_GAS_LIMIT = 4_000_000; - - // Rate limiter - address internal constant ADMIN = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; - - MockRMN internal s_mockRMN; - IRMNRemote internal s_mockRMNRemote; - - // nonce for pseudo-random number generation, not to be exposed to test suites - uint256 private randNonce; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - // Set the sender to OWNER permanently - vm.startPrank(OWNER); - deal(OWNER, 1e20); - vm.label(OWNER, "Owner"); - vm.label(STRANGER, "Stranger"); - - // Set the block time to a constant known value - vm.warp(BLOCK_TIME); - - // setup mock RMN & RMNRemote - s_mockRMN = new MockRMN(); - s_mockRMNRemote = IRMNRemote(makeAddr("MOCK RMN REMOTE")); - vm.etch(address(s_mockRMNRemote), bytes("fake bytecode")); - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); - _setMockRMNGlobalCurse(false); - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(false)); // no curses by defaule - } - - function _setMockRMNGlobalCurse( - bool isCursed - ) internal { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(isCursed)); - } - - function _setMockRMNChainCurse(uint64 chainSelector, bool isCursed) internal { - vm.mockCall( - address(s_mockRMNRemote), - abi.encodeWithSignature("isCursed(bytes16)", bytes16(uint128(chainSelector))), - abi.encode(isCursed) - ); - } - - function _getOutboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e15}); - } - - function _getInboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { - return RateLimiter.Config({isEnabled: true, capacity: 222e30, rate: 1e18}); - } - - function _getSingleTokenPriceUpdateStruct( - address token, - uint224 price - ) internal pure returns (Internal.PriceUpdates memory) { - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](1); - tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: token, usdPerToken: price}); - - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); - - return priceUpdates; - } - - /// @dev returns a pseudo-random bytes32 - function _randomBytes32() internal returns (bytes32) { - return keccak256(abi.encodePacked(++randNonce)); - } - - /// @dev returns a pseudo-random number - function _randomNum() internal returns (uint256) { - return uint256(_randomBytes32()); - } - - /// @dev returns a pseudo-random address - function _randomAddress() internal returns (address) { - return address(uint160(_randomNum())); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol deleted file mode 100644 index 0dfa2fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ /dev/null @@ -1,520 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICommitStore} from "../interfaces/ICommitStore.sol"; -import {IEVM2AnyOnRamp} from "../interfaces/IEVM2AnyOnRamp.sol"; - -import {NonceManager} from "../NonceManager.sol"; -import {Router} from "../Router.sol"; -import {Client} from "../libraries/Client.sol"; -import {Internal} from "../libraries/Internal.sol"; -import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {OffRamp} from "../offRamp/OffRamp.sol"; -import {OnRamp} from "../onRamp/OnRamp.sol"; -import {BaseTest} from "./BaseTest.t.sol"; -import {EVM2EVMOffRampHelper} from "./helpers/EVM2EVMOffRampHelper.sol"; -import {OnRampHelper} from "./helpers/OnRampHelper.sol"; -import {OffRampSetup} from "./offRamp/OffRampSetup.t.sol"; -import {OnRampSetup} from "./onRamp/OnRampSetup.t.sol"; - -import {Test} from "forge-std/Test.sol"; - -contract NonceManager_typeAndVersion is Test { - NonceManager private s_nonceManager; - - function setUp() public { - s_nonceManager = new NonceManager(new address[](0)); - } - - function test_typeAndVersion() public view { - assertEq(s_nonceManager.typeAndVersion(), "NonceManager 1.6.0-dev"); - } -} - -contract NonceManager_NonceIncrementation is BaseTest { - NonceManager private s_nonceManager; - - function setUp() public override { - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(this); - s_nonceManager = new NonceManager(authorizedCallers); - } - - function test_getIncrementedOutboundNonce_Success() public { - address sender = address(this); - - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); - - uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); - assertEq(outboundNonce, 1); - } - - function test_incrementInboundNonce_Success() public { - address sender = address(this); - - s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, 1, abi.encode(sender)); - - assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 1); - } - - function test_incrementInboundNonce_Skip() public { - address sender = address(this); - uint64 expectedNonce = 2; - - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); - - s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); - - assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 0); - } - - function test_incrementNoncesInboundAndOutbound_Success() public { - address sender = address(this); - - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); - uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); - assertEq(outboundNonce, 1); - - // Inbound nonce unchanged - assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 0); - - s_nonceManager.incrementInboundNonce(DEST_CHAIN_SELECTOR, 1, abi.encode(sender)); - assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 1); - - // Outbound nonce unchanged - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 1); - } -} - -contract NonceManager_applyPreviousRampsUpdates is OnRampSetup { - function test_SingleRampUpdate() public { - address prevOnRamp = makeAddr("prevOnRamp"); - address prevOffRamp = makeAddr("prevOffRamp"); - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); - - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); - } - - function test_MultipleRampsUpdates() public { - address prevOnRamp1 = makeAddr("prevOnRamp1"); - address prevOnRamp2 = makeAddr("prevOnRamp2"); - address prevOffRamp1 = makeAddr("prevOffRamp1"); - address prevOffRamp2 = makeAddr("prevOffRamp2"); - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](2); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1)); - previousRamps[1] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR + 1, NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2)); - - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR + 1, previousRamps[1].prevRamps); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); - _assertPreviousRampsEqual( - s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR + 1), previousRamps[1].prevRamps - ); - } - - function test_ZeroInput() public { - vm.recordLogs(); - s_outboundNonceManager.applyPreviousRampsUpdates(new NonceManager.PreviousRampsArgs[](0)); - - assertEq(vm.getRecordedLogs().length, 0); - } - - function test_PreviousRampAlreadySetOnRamp_Revert() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOnRamp = makeAddr("prevOnRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, address(0))); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function test_PreviousRampAlreadySetOffRamp_Revert() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(0), prevOffRamp)); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOnRamp = makeAddr("prevOnRamp"); - address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(prevOnRamp, prevOffRamp)); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function _assertPreviousRampsEqual( - NonceManager.PreviousRamps memory a, - NonceManager.PreviousRamps memory b - ) internal pure { - assertEq(a.prevOnRamp, b.prevOnRamp); - assertEq(a.prevOffRamp, b.prevOffRamp); - } -} - -contract NonceManager_OnRampUpgrade is OnRampSetup { - uint256 internal constant FEE_AMOUNT = 1234567890; - OnRampHelper internal s_prevOnRamp; - - function setUp() public virtual override { - super.setUp(); - - (s_prevOnRamp,) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - // Since the previous onRamp is not a 1.5 ramp it doesn't have the getSenderNonce function. We mock it to return 0 - vm.mockCall(address(s_prevOnRamp), abi.encodeWithSelector(IEVM2AnyOnRamp.getSenderNonce.selector), abi.encode(0)); - - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = - NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(s_prevOnRamp), address(0))); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - (s_onRamp, s_metadataHash) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - vm.startPrank(address(s_sourceRouter)); - } - - function test_Upgrade_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - } - - function test_UpgradeSenderNoncesReadsPreviousRamp_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - assertEq(startNonce + i, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - } - } - - function test_UpgradeNonceStartsAtV1Nonce_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - - // send 1 message from previous onramp - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 1, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - - // new onramp nonce should start from 2, while sequence number start from 1 - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - - // after another send, nonce should be 3, and sequence number be 2 - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 2, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - } - - function test_UpgradeNonceNewSenderStartsAtZero_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - // send 1 message from previous onramp from OWNER - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - address newSender = address(1234567); - // new onramp nonce should start from 1 for new sender - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); - } -} - -contract NonceManager_OffRampUpgrade is OffRampSetup { - EVM2EVMOffRampHelper internal s_prevOffRamp; - - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_3 = abi.decode(ON_RAMP_ADDRESS_3, (address)); - - function setUp() public virtual override { - super.setUp(); - - s_prevOffRamp = new EVM2EVMOffRampHelper(); - - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = NonceManager.PreviousRampsArgs( - SOURCE_CHAIN_SELECTOR_1, NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)) - ); - - s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_2 - }); - sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_3 - }); - - _setupMultipleOffRampsFromConfigs(sourceChainConfigs); - - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); - } - - function test_Upgraded_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_NoPrevOffRampForChain_Success() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0])); - s_prevOffRamp.execute(senders); - - // Nonce unchanged for chain 3 - assertEq(startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0]))); - - Internal.Any2EVMRampMessage[] memory messagesChain3 = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - - vm.recordLogs(); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_3, - messagesChain3[0].header.sequenceNumber, - messagesChain3[0].header.messageId, - _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) - ); - } - - function test_UpgradedSenderNoncesReadsPreviousRamp_Success() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute(senders); - - assertEq(startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - } - } - - function test_UpgradedNonceStartsAtV1Nonce_Success() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); - s_prevOffRamp.execute(senders); - - assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - - Internal.Any2EVMRampMessage[] memory messagesMultiRamp = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) - ); - - messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.sequenceNumber++; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) - ); - } - - function test_UpgradedNonceNewSenderStartsAtZero_Success() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - s_prevOffRamp.execute(senders); - - Internal.Any2EVMRampMessage[] memory messagesMultiRamp = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - bytes memory newSender = abi.encode(address(1234567)); - messagesMultiRamp[0].sender = newSender; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - // new sender nonce in new offramp should go from 0 -> 1 - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); - } - - function test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - address newSender = address(1234567); - messages[0].sender = abi.encode(newSender); - messages[0].header.nonce = 2; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - - // new offramp sees msg nonce higher than senderNonce - // it waits for previous offramp to execute - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); - - address[] memory senders = new address[](1); - senders[0] = newSender; - - // previous offramp executes msg and increases nonce - s_prevOffRamp.execute(senders); - assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - - messages[0].header.nonce = 2; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - // new offramp is able to execute - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md deleted file mode 100644 index 99223e1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Foundry Test Guidelines - -We're using Foundry to test our CCIP smart contracts here. This enables us to test in Solidity. If you need to add tests for anything outside the CCIP contracts, please write them in hardhat (for the time being). - -## Directory Structure - -The test directory structure mimics the source contract file structure as closely as possible. Example: - -`./offRamp/SomeOffRamp.sol` should have a test contract `./test/offRamp/SomeOffRamp.t.sol`. - -## Test File Structure - -Break the test file down into multiple contracts, each contract testing a specific function inside the source contract. - -For Example, here's a source contract `SomeOffRamp`: - -``` -contract SomeOffRamp { - - constructor() { - ... set some state - } - - function firstFunction() public { - ... - } - - function theNextFunction() public { - ... - } - - function _anInternalFunction() internal { - ... - } -} -``` - -Our test file `SomeOffRamp.t.sol` should be structured like this: - -``` -contract SomeOffRamp_constructor { - // constructor state setup tests here -} - -contract SomeOffRamp_firstFunction { - // first function tests here -} - -contract SomeOffRamp_theNextFunction { - // tests here too... -} - -contract SomeOffRamp_anInternalFunction { - // This function will require a helper contract to expose it. -} -``` - -## Test Structure - -Inside each test contract, group tests into `Success` and `Reverts` by starting with all the success cases and then adding a `// Reverts` comments to indicate the failure cases below. - -``` -contract SomeOffRamp_firstFunction { - function testZeroValueSuccess() public { - ... - } - - ... - - - // Reverts - - function testOwnerReverts() public { - // test that an ownable function reverts when not called by the owner - ... - } - - ... - -} -``` - -Function naming should follow this structure, where the `_fuzz_` section denotes whether it's a fuzz test. Do not write tests that are named `testSuccess`, always include the description of the test, even if it's just the name of the function that is being called. - -`test{_fuzz_}{description of test}[Success|Reverts]` - -Try to cover all the code paths present in each function being tested. In most cases, this will result in many more failure tests than success tests. - -If a test file requires a complicated setUp, or if it requires many helper functions (like `_generateAMessageWithNoTokensStruct()`), create a separate file to perform this setup in. Using the example above, `SomeOffRampSetup.t.sol`. Inherit this and call the setUp function in the test file. diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol deleted file mode 100644 index 2031458..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/TokenSetup.t.sol +++ /dev/null @@ -1,178 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {BurnMintERC677} from "../../shared/token/ERC677/BurnMintERC677.sol"; -import {Client} from "../libraries/Client.sol"; -import {BurnMintTokenPool} from "../pools/BurnMintTokenPool.sol"; -import {LockReleaseTokenPool} from "../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../pools/TokenPool.sol"; -import {TokenAdminRegistry} from "../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {MaybeRevertingBurnMintTokenPool} from "./helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {RouterSetup} from "./router/RouterSetup.t.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenSetup is RouterSetup { - address[] internal s_sourceTokens; - address[] internal s_destTokens; - - address internal s_sourceFeeToken; - address internal s_destFeeToken; - - TokenAdminRegistry internal s_tokenAdminRegistry; - - mapping(address sourceToken => address sourcePool) internal s_sourcePoolByToken; - mapping(address sourceToken => address destPool) internal s_destPoolBySourceToken; - mapping(address destToken => address destPool) internal s_destPoolByToken; - mapping(address sourceToken => address destToken) internal s_destTokenBySourceToken; - - function _deploySourceToken(string memory tokenName, uint256 dealAmount, uint8 decimals) internal returns (address) { - BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, decimals, 0); - s_sourceTokens.push(address(token)); - deal(address(token), OWNER, dealAmount); - return address(token); - } - - function _deployDestToken(string memory tokenName, uint256 dealAmount) internal returns (address) { - BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, 18, 0); - s_destTokens.push(address(token)); - deal(address(token), OWNER, dealAmount); - return address(token); - } - - function _deployLockReleasePool(address token, bool isSourcePool) internal { - address router = address(s_sourceRouter); - if (!isSourcePool) { - router = address(s_destRouter); - } - - LockReleaseTokenPool pool = - new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, router); - - if (isSourcePool) { - s_sourcePoolByToken[address(token)] = address(pool); - } else { - s_destPoolByToken[address(token)] = address(pool); - s_destPoolBySourceToken[s_sourceTokens[s_destTokens.length - 1]] = address(pool); - } - } - - function _deployTokenAndBurnMintPool(address token, bool isSourcePool) internal { - address router = address(s_sourceRouter); - if (!isSourcePool) { - router = address(s_destRouter); - } - - BurnMintTokenPool pool = - new MaybeRevertingBurnMintTokenPool(BurnMintERC677(token), new address[](0), address(s_mockRMN), router); - BurnMintERC677(token).grantMintAndBurnRoles(address(pool)); - - if (isSourcePool) { - s_sourcePoolByToken[address(token)] = address(pool); - } else { - s_destPoolByToken[address(token)] = address(pool); - s_destPoolBySourceToken[s_sourceTokens[s_destTokens.length - 1]] = address(pool); - } - } - - function setUp() public virtual override { - RouterSetup.setUp(); - - bool isSetup = s_sourceTokens.length != 0; - if (isSetup) { - return; - } - - // Source tokens & pools - address sourceLink = _deploySourceToken("sLINK", type(uint256).max, 18); - _deployLockReleasePool(sourceLink, true); - s_sourceFeeToken = sourceLink; - - address sourceEth = _deploySourceToken("sETH", 2 ** 128, 18); - _deployTokenAndBurnMintPool(sourceEth, true); - - // Destination tokens & pools - address destLink = _deployDestToken("dLINK", type(uint256).max); - _deployLockReleasePool(destLink, false); - s_destFeeToken = destLink; - - s_destTokenBySourceToken[sourceLink] = destLink; - - address destEth = _deployDestToken("dETH", 2 ** 128); - _deployTokenAndBurnMintPool(destEth, false); - - s_destTokenBySourceToken[sourceEth] = destEth; - - // Float the dest link lock release pool with funds - IERC20(destLink).transfer(s_destPoolByToken[destLink], 1000 ether); - - s_tokenAdminRegistry = new TokenAdminRegistry(); - - // Set pools in the registry - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - address token = s_sourceTokens[i]; - address pool = s_sourcePoolByToken[token]; - - _setPool( - s_tokenAdminRegistry, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] - ); - } - - for (uint256 i = 0; i < s_destTokens.length; ++i) { - address token = s_destTokens[i]; - address pool = s_destPoolByToken[token]; - s_tokenAdminRegistry.proposeAdministrator(token, OWNER); - s_tokenAdminRegistry.acceptAdminRole(token); - s_tokenAdminRegistry.setPool(token, pool); - - _setPool( - s_tokenAdminRegistry, - token, - pool, - SOURCE_CHAIN_SELECTOR, - s_sourcePoolByToken[s_sourceTokens[i]], - s_sourceTokens[i] - ); - } - } - - function _getCastedSourceEVMTokenAmountsWithZeroAmounts() - internal - view - returns (Client.EVMTokenAmount[] memory tokenAmounts) - { - tokenAmounts = new Client.EVMTokenAmount[](s_sourceTokens.length); - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - tokenAmounts[i].token = s_sourceTokens[i]; - } - return tokenAmounts; - } - - function _setPool( - TokenAdminRegistry tokenAdminRegistry, - address token, - address pool, - uint64 remoteChainSelector, - address remotePoolAddress, - address remoteToken - ) internal { - if (!tokenAdminRegistry.isAdministrator(token, OWNER)) { - tokenAdminRegistry.proposeAdministrator(token, OWNER); - tokenAdminRegistry.acceptAdminRole(token); - } - - tokenAdminRegistry.setPool(token, pool); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: remoteChainSelector, - remotePoolAddress: abi.encode(remotePoolAddress), - remoteTokenAddress: abi.encode(remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - TokenPool(pool).applyChainUpdates(chainUpdates); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol deleted file mode 100644 index bfd2b5f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/WETH9.sol +++ /dev/null @@ -1,84 +0,0 @@ -// Submitted for verification at Etherscan.io on 2017-12-12 - -// Copyright (C) 2015, 2016, 2017 Dapphub - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -pragma solidity 0.8.24; - -// solhint-disable -contract WETH9 { - string public name = "Wrapped Ether"; - string public symbol = "WETH"; - uint8 public decimals = 18; - - event Approval(address indexed src, address indexed guy, uint256 wad); - event Transfer(address indexed src, address indexed dst, uint256 wad); - event Deposit(address indexed dst, uint256 wad); - event Withdrawal(address indexed src, uint256 wad); - - mapping(address => uint256) public balanceOf; - mapping(address => mapping(address => uint256)) public allowance; - - receive() external payable { - _deposit(); - } - - function _deposit() internal { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - - function deposit() external payable { - _deposit(); - } - - function withdraw( - uint256 wad - ) external { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - payable(msg.sender).transfer(wad); - emit Withdrawal(msg.sender, wad); - } - - function totalSupply() public view returns (uint256) { - return address(this).balance; - } - - function approve(address guy, uint256 wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - function transfer(address dst, uint256 wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint256 wad) public returns (bool) { - require(balanceOf[src] >= wad); - - if (src != msg.sender && allowance[src][msg.sender] != type(uint128).max) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol deleted file mode 100644 index c68907b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/DefensiveExample.t.sol +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {DefensiveExample} from "../../applications/DefensiveExample.sol"; -import {Client} from "../../libraries/Client.sol"; -import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract DefensiveExampleTest is OnRampSetup { - event MessageFailed(bytes32 indexed messageId, bytes reason); - event MessageSucceeded(bytes32 indexed messageId); - event MessageRecovered(bytes32 indexed messageId); - - DefensiveExample internal s_receiver; - uint64 internal sourceChainSelector = 7331; - - function setUp() public virtual override { - super.setUp(); - - s_receiver = new DefensiveExample(s_destRouter, IERC20(s_destFeeToken)); - s_receiver.enableChain(sourceChainSelector, abi.encode("")); - } - - function test_Recovery() public { - bytes32 messageId = keccak256("messageId"); - address token = address(s_destFeeToken); - uint256 amount = 111333333777; - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - // Make sure we give the receiver contract enough tokens like CCIP would. - deal(token, address(s_receiver), amount); - - // Make sure the contract call reverts so we can test recovery. - s_receiver.setSimRevert(true); - - // The receiver contract will revert if the router is not the sender. - vm.startPrank(address(s_destRouter)); - - vm.expectEmit(); - emit MessageFailed(messageId, abi.encodeWithSelector(DefensiveExample.ErrorCase.selector)); - - s_receiver.ccipReceive( - Client.Any2EVMMessage({ - messageId: messageId, - sourceChainSelector: sourceChainSelector, - sender: abi.encode(address(0)), // wrong sender, will revert internally - data: "", - destTokenAmounts: destTokenAmounts - }) - ); - - address tokenReceiver = address(0x000001337); - uint256 tokenReceiverBalancePre = IERC20(token).balanceOf(tokenReceiver); - uint256 receiverBalancePre = IERC20(token).balanceOf(address(s_receiver)); - - // Recovery can only be done by the owner. - vm.startPrank(OWNER); - - vm.expectEmit(); - emit MessageRecovered(messageId); - - s_receiver.retryFailedMessage(messageId, tokenReceiver); - - // Assert the tokens have successfully been rescued from the contract. - assertEq(IERC20(token).balanceOf(tokenReceiver), tokenReceiverBalancePre + amount); - assertEq(IERC20(token).balanceOf(address(s_receiver)), receiverBalancePre - amount); - } - - function test_HappyPath_Success() public { - bytes32 messageId = keccak256("messageId"); - address token = address(s_destFeeToken); - uint256 amount = 111333333777; - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - // Make sure we give the receiver contract enough tokens like CCIP would. - deal(token, address(s_receiver), amount); - - // The receiver contract will revert if the router is not the sender. - vm.startPrank(address(s_destRouter)); - - vm.expectEmit(); - emit MessageSucceeded(messageId); - - s_receiver.ccipReceive( - Client.Any2EVMMessage({ - messageId: messageId, - sourceChainSelector: sourceChainSelector, - sender: abi.encode(address(s_receiver)), // correct sender - data: "", - destTokenAmounts: destTokenAmounts - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol deleted file mode 100644 index 489ebcf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver.t.sol +++ /dev/null @@ -1,724 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; - -import {CCIPRouter} from "../../applications/EtherSenderReceiver.sol"; - -import {IRouterClient} from "../../interfaces/IRouterClient.sol"; -import {Client} from "../../libraries/Client.sol"; -import {WETH9} from "../WETH9.sol"; -import {EtherSenderReceiverHelper} from "./../helpers/EtherSenderReceiverHelper.sol"; - -import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; - -contract EtherSenderReceiverTest is Test { - EtherSenderReceiverHelper internal s_etherSenderReceiver; - WETH9 internal s_weth; - WETH9 internal s_someOtherWeth; - ERC20 internal s_linkToken; - - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - address internal constant ROUTER = 0x0F3779ee3a832D10158073ae2F5e61ac7FBBF880; - address internal constant XCHAIN_RECEIVER = 0xBd91b2073218AF872BF73b65e2e5950ea356d147; - - function setUp() public { - vm.startPrank(OWNER); - - s_linkToken = new ERC20("Chainlink Token", "LINK"); - s_someOtherWeth = new WETH9(); - s_weth = new WETH9(); - vm.mockCall(ROUTER, abi.encodeWithSelector(CCIPRouter.getWrappedNative.selector), abi.encode(address(s_weth))); - s_etherSenderReceiver = new EtherSenderReceiverHelper(ROUTER); - - deal(OWNER, 1_000_000 ether); - deal(address(s_linkToken), OWNER, 1_000_000 ether); - - // deposit some eth into the weth contract. - s_weth.deposit{value: 10 ether}(); - uint256 wethSupply = s_weth.totalSupply(); - assertEq(wethSupply, 10 ether, "total weth supply must be 10 ether"); - } -} - -contract EtherSenderReceiverTest_constructor is EtherSenderReceiverTest { - function test_constructor() public view { - assertEq(s_etherSenderReceiver.getRouter(), ROUTER, "router must be set correctly"); - uint256 allowance = s_weth.allowance(address(s_etherSenderReceiver), ROUTER); - assertEq(allowance, type(uint256).max, "allowance must be set infinite"); - } -} - -contract EtherSenderReceiverTest_validateFeeToken is EtherSenderReceiverTest { - uint256 internal constant amount = 100; - - error InsufficientMsgValue(uint256 gotAmount, uint256 msgValue); - error TokenAmountNotEqualToMsgValue(uint256 gotAmount, uint256 msgValue); - - function test_validateFeeToken_valid_native() public { - Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); - tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmount, - feeToken: address(0), - extraArgs: "" - }); - - s_etherSenderReceiver.validateFeeToken{value: amount + 1}(message); - } - - function test_validateFeeToken_valid_feeToken() public { - Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); - tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmount, - feeToken: address(s_weth), - extraArgs: "" - }); - - s_etherSenderReceiver.validateFeeToken{value: amount}(message); - } - - function test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() public { - Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); - tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmount, - feeToken: address(s_weth), - extraArgs: "" - }); - - vm.expectRevert(abi.encodeWithSelector(TokenAmountNotEqualToMsgValue.selector, amount, amount + 1)); - s_etherSenderReceiver.validateFeeToken{value: amount + 1}(message); - } -} - -contract EtherSenderReceiverTest_validatedMessage is EtherSenderReceiverTest { - error InvalidDestinationReceiver(bytes destReceiver); - error InvalidTokenAmounts(uint256 gotAmounts); - error InvalidWethAddress(address want, address got); - error GasLimitTooLow(uint256 minLimit, uint256 gotLimit); - - uint256 internal constant amount = 100; - - function test_Fuzz_validatedMessage_msgSenderOverwrite( - bytes memory data - ) public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: data, - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); - } - - function test_Fuzz_validatedMessage_tokenAddressOverwrite( - address token - ) public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); - } - - function test_validatedMessage_emptyDataOverwrittenToMsgSender() public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); - } - - function test_validatedMessage_dataOverwrittenToMsgSender() public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: abi.encode(address(42)), - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); - } - - function test_validatedMessage_tokenOverwrittenToWeth() public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(42), // incorrect token. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq(validatedMessage.extraArgs, bytes(""), "extraArgs must be empty"); - } - - function test_validatedMessage_validMessage_extraArgs() public view { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})) - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - assertEq(validatedMessage.receiver, abi.encode(XCHAIN_RECEIVER), "receiver must be XCHAIN_RECEIVER"); - assertEq(validatedMessage.data, abi.encode(OWNER), "data must be msg.sender"); - assertEq(validatedMessage.tokenAmounts[0].token, address(s_weth), "token must be weth"); - assertEq(validatedMessage.tokenAmounts[0].amount, amount, "amount must be correct"); - assertEq(validatedMessage.feeToken, address(0), "feeToken must be 0"); - assertEq( - validatedMessage.extraArgs, - Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - "extraArgs must be correct" - ); - } - - function test_validatedMessage_invalidTokenAmounts() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: address(0), amount: amount}); - tokenAmounts[1] = Client.EVMTokenAmount({token: address(0), amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - vm.expectRevert(abi.encodeWithSelector(InvalidTokenAmounts.selector, uint256(2))); - s_etherSenderReceiver.validatedMessage(message); - } -} - -contract EtherSenderReceiverTest_getFee is EtherSenderReceiverTest { - uint64 internal constant destinationChainSelector = 424242; - uint256 internal constant feeWei = 121212; - uint256 internal constant amount = 100; - - function test_getFee() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: address(0), amount: amount}); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - - uint256 fee = s_etherSenderReceiver.getFee(destinationChainSelector, message); - assertEq(fee, feeWei, "fee must be feeWei"); - } -} - -contract EtherSenderReceiverTest_ccipReceive is EtherSenderReceiverTest { - uint256 internal constant amount = 100; - uint64 internal constant sourceChainSelector = 424242; - address internal constant XCHAIN_SENDER = 0x9951529C13B01E542f7eE3b6D6665D292e9BA2E0; - - error InvalidTokenAmounts(uint256 gotAmounts); - error InvalidToken(address gotToken, address expectedToken); - - function test_Fuzz_ccipReceive( - uint256 tokenAmount - ) public { - // cap to 10 ether because OWNER only has 10 ether. - if (tokenAmount > 10 ether) { - return; - } - - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: tokenAmount}); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256(abi.encode("ccip send")), - sourceChainSelector: sourceChainSelector, - sender: abi.encode(XCHAIN_SENDER), - data: abi.encode(OWNER), - destTokenAmounts: destTokenAmounts - }); - - // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. - s_weth.transfer(address(s_etherSenderReceiver), tokenAmount); - - uint256 balanceBefore = OWNER.balance; - s_etherSenderReceiver.publicCcipReceive(message); - uint256 balanceAfter = OWNER.balance; - assertEq(balanceAfter, balanceBefore + tokenAmount, "balance must be correct"); - } - - function test_ccipReceive_happyPath() public { - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256(abi.encode("ccip send")), - sourceChainSelector: 424242, - sender: abi.encode(XCHAIN_SENDER), - data: abi.encode(OWNER), - destTokenAmounts: destTokenAmounts - }); - - // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. - s_weth.transfer(address(s_etherSenderReceiver), amount); - - uint256 balanceBefore = OWNER.balance; - s_etherSenderReceiver.publicCcipReceive(message); - uint256 balanceAfter = OWNER.balance; - assertEq(balanceAfter, balanceBefore + amount, "balance must be correct"); - } - - function test_ccipReceive_fallbackToWethTransfer() public { - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256(abi.encode("ccip send")), - sourceChainSelector: 424242, - sender: abi.encode(XCHAIN_SENDER), - data: abi.encode(address(s_linkToken)), // ERC20 cannot receive() ether. - destTokenAmounts: destTokenAmounts - }); - - // simulate a cross-chain token transfer, just transfer the weth to s_etherSenderReceiver. - s_weth.transfer(address(s_etherSenderReceiver), amount); - - uint256 balanceBefore = address(s_linkToken).balance; - s_etherSenderReceiver.publicCcipReceive(message); - uint256 balanceAfter = address(s_linkToken).balance; - assertEq(balanceAfter, balanceBefore, "balance must be unchanged"); - uint256 wethBalance = s_weth.balanceOf(address(s_linkToken)); - assertEq(wethBalance, amount, "weth balance must be correct"); - } - - function test_ccipReceive_wrongTokenAmount() public { - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](2); - destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - destTokenAmounts[1] = Client.EVMTokenAmount({token: address(s_weth), amount: amount}); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256(abi.encode("ccip send")), - sourceChainSelector: 424242, - sender: abi.encode(XCHAIN_SENDER), - data: abi.encode(OWNER), - destTokenAmounts: destTokenAmounts - }); - - vm.expectRevert(abi.encodeWithSelector(InvalidTokenAmounts.selector, uint256(2))); - s_etherSenderReceiver.publicCcipReceive(message); - } - - function test_ccipReceive_wrongToken() public { - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](1); - destTokenAmounts[0] = Client.EVMTokenAmount({token: address(s_someOtherWeth), amount: amount}); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: keccak256(abi.encode("ccip send")), - sourceChainSelector: 424242, - sender: abi.encode(XCHAIN_SENDER), - data: abi.encode(OWNER), - destTokenAmounts: destTokenAmounts - }); - - vm.expectRevert(abi.encodeWithSelector(InvalidToken.selector, address(s_someOtherWeth), address(s_weth))); - s_etherSenderReceiver.publicCcipReceive(message); - } -} - -contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTest { - error InsufficientFee(uint256 gotFee, uint256 fee); - - uint256 internal constant amount = 100; - uint64 internal constant destinationChainSelector = 424242; - uint256 internal constant feeWei = 121212; - uint256 internal constant feeJuels = 232323; - - function test_Fuzz_ccipSend(uint256 feeFromRouter, uint256 feeSupplied) public { - // cap the fuzzer because OWNER only has a million ether. - vm.assume(feeSupplied < 1_000_000 ether - amount); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeFromRouter) - ); - - if (feeSupplied < feeFromRouter) { - vm.expectRevert(); - s_etherSenderReceiver.ccipSend{value: amount + feeSupplied}(destinationChainSelector, message); - } else { - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - feeSupplied, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - bytes32 actualMsgId = - s_etherSenderReceiver.ccipSend{value: amount + feeSupplied}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - } - } - - function test_Fuzz_ccipSend_feeToken(uint256 feeFromRouter, uint256 feeSupplied) public { - // cap the fuzzer because OWNER only has a million LINK. - vm.assume(feeSupplied < 1_000_000 ether - amount); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(s_linkToken), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeFromRouter) - ); - - s_linkToken.approve(address(s_etherSenderReceiver), feeSupplied); - - if (feeSupplied < feeFromRouter) { - vm.expectRevert(); - s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - } else { - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - } - } - - function test_ccipSend_reverts_insufficientFee_weth() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(s_weth), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - - s_weth.approve(address(s_etherSenderReceiver), feeWei - 1); - - vm.expectRevert("SafeERC20: low-level call failed"); - s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - } - - function test_ccipSend_reverts_insufficientFee_feeToken() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(s_linkToken), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeJuels) - ); - - s_linkToken.approve(address(s_etherSenderReceiver), feeJuels - 1); - - vm.expectRevert("ERC20: insufficient allowance"); - s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - } - - function test_ccipSend_reverts_insufficientFee_native() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - - vm.expectRevert(); - s_etherSenderReceiver.ccipSend{value: amount + feeWei - 1}(destinationChainSelector, message); - } - - function test_ccipSend_success_nativeExcess() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - - // we assert that the correct value is sent to the router call, which should be - // the msg.value - feeWei. - vm.mockCall( - ROUTER, - feeWei + 1, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount + feeWei + 1}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - } - - function test_ccipSend_success_native() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(0), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - vm.mockCall( - ROUTER, - feeWei, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount + feeWei}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - } - - function test_ccipSend_success_feeToken() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(s_linkToken), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeJuels) - ); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - s_linkToken.approve(address(s_etherSenderReceiver), feeJuels); - - bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - uint256 routerAllowance = s_linkToken.allowance(address(s_etherSenderReceiver), ROUTER); - assertEq(routerAllowance, feeJuels, "router allowance must be feeJuels"); - } - - function test_ccipSend_success_weth() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({ - token: address(0), // callers may not specify this. - amount: amount - }); - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(XCHAIN_RECEIVER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: address(s_weth), - extraArgs: "" - }); - - Client.EVM2AnyMessage memory validatedMessage = s_etherSenderReceiver.validatedMessage(message); - - bytes32 expectedMsgId = keccak256(abi.encode("ccip send")); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.getFee.selector, destinationChainSelector, validatedMessage), - abi.encode(feeWei) - ); - vm.mockCall( - ROUTER, - abi.encodeWithSelector(IRouterClient.ccipSend.selector, destinationChainSelector, validatedMessage), - abi.encode(expectedMsgId) - ); - - s_weth.approve(address(s_etherSenderReceiver), feeWei); - - bytes32 actualMsgId = s_etherSenderReceiver.ccipSend{value: amount}(destinationChainSelector, message); - assertEq(actualMsgId, expectedMsgId, "message id must be correct"); - uint256 routerAllowance = s_weth.allowance(address(s_etherSenderReceiver), ROUTER); - assertEq(routerAllowance, type(uint256).max, "router allowance must be max for weth"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol deleted file mode 100644 index 61b0204..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/ImmutableExample.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -pragma solidity ^0.8.0; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; - -import {CCIPClientExample} from "../../applications/CCIPClientExample.sol"; -import {Client} from "../../libraries/Client.sol"; -import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC165Checker} from - "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; - -contract CCIPClientExample_sanity is OnRampSetup { - function test_ImmutableExamples_Success() public { - CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); - deal(address(exampleContract), 100 ether); - deal(s_sourceFeeToken, address(exampleContract), 100 ether); - - // feeToken approval works - assertEq(IERC20(s_sourceFeeToken).allowance(address(exampleContract), address(s_sourceRouter)), 2 ** 256 - 1); - - // Can set chain - Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 300_000}); - bytes memory encodedExtraArgs = Client._argsToBytes(extraArgs); - exampleContract.enableChain(DEST_CHAIN_SELECTOR, encodedExtraArgs); - assertEq(exampleContract.s_chains(DEST_CHAIN_SELECTOR), encodedExtraArgs); - - address toAddress = makeAddr("toAddress"); - - // Can send data pay native - exampleContract.sendDataPayNative(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); - - // Can send data pay feeToken - exampleContract.sendDataPayFeeToken(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello")); - - // Can send data tokens - address sourceToken = s_sourceTokens[1]; - assertEq( - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(sourceToken))), - address(s_sourcePoolByToken[sourceToken]) - ); - deal(sourceToken, OWNER, 100 ether); - IERC20(sourceToken).approve(address(exampleContract), 1 ether); - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: sourceToken, amount: 1 ether}); - exampleContract.sendDataAndTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), bytes("hello"), tokenAmounts); - // Tokens transferred from owner to router then burned in pool. - assertEq(IERC20(sourceToken).balanceOf(OWNER), 99 ether); - assertEq(IERC20(sourceToken).balanceOf(address(s_sourceRouter)), 0); - - // Can send just tokens - IERC20(sourceToken).approve(address(exampleContract), 1 ether); - exampleContract.sendTokens(DEST_CHAIN_SELECTOR, abi.encode(toAddress), tokenAmounts); - - // Can receive - assertTrue(ERC165Checker.supportsInterface(address(exampleContract), type(IAny2EVMMessageReceiver).interfaceId)); - - // Can disable chain - exampleContract.disableChain(DEST_CHAIN_SELECTOR); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol deleted file mode 100644 index d47ba1c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/applications/PingPongDemo.t.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {PingPongDemo} from "../../applications/PingPongDemo.sol"; -import {Client} from "../../libraries/Client.sol"; -import "../onRamp/OnRampSetup.t.sol"; - -// setup -contract PingPongDappSetup is OnRampSetup { - PingPongDemo internal s_pingPong; - IERC20 internal s_feeToken; - - address internal immutable i_pongContract = makeAddr("ping_pong_counterpart"); - - function setUp() public virtual override { - super.setUp(); - - s_feeToken = IERC20(s_sourceTokens[0]); - s_pingPong = new PingPongDemo(address(s_sourceRouter), s_feeToken); - s_pingPong.setCounterpart(DEST_CHAIN_SELECTOR, i_pongContract); - - uint256 fundingAmount = 1e18; - - // Fund the contract with LINK tokens - s_feeToken.transfer(address(s_pingPong), fundingAmount); - } -} - -contract PingPong_startPingPong is PingPongDappSetup { - uint256 internal pingPongNumber = 1; - - function test_StartPingPong_With_Sequenced_Ordered_Success() public { - _assertPingPongSuccess(); - } - - function test_StartPingPong_With_OOO_Success() public { - s_pingPong.setOutOfOrderExecution(true); - - _assertPingPongSuccess(); - } - - function _assertPingPongSuccess() internal { - vm.expectEmit(); - emit PingPongDemo.Ping(pingPongNumber); - - Internal.EVM2AnyRampMessage memory message; - - vm.expectEmit(false, false, false, false); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, message); - - s_pingPong.startPingPong(); - } -} - -contract PingPong_ccipReceive is PingPongDappSetup { - function test_CcipReceive_Success() public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); - - uint256 pingPongNumber = 5; - - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: DEST_CHAIN_SELECTOR, - sender: abi.encode(i_pongContract), - data: abi.encode(pingPongNumber), - destTokenAmounts: tokenAmounts - }); - - vm.startPrank(address(s_sourceRouter)); - - vm.expectEmit(); - emit PingPongDemo.Pong(pingPongNumber + 1); - - s_pingPong.ccipReceive(message); - } -} - -contract PingPong_plumbing is PingPongDappSetup { - function test_Fuzz_CounterPartChainSelector_Success( - uint64 chainSelector - ) public { - s_pingPong.setCounterpartChainSelector(chainSelector); - - assertEq(s_pingPong.getCounterpartChainSelector(), chainSelector); - } - - function test_Fuzz_CounterPartAddress_Success( - address counterpartAddress - ) public { - s_pingPong.setCounterpartAddress(counterpartAddress); - - assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); - } - - function test_Fuzz_CounterPartAddress_Success(uint64 chainSelector, address counterpartAddress) public { - s_pingPong.setCounterpartChainSelector(chainSelector); - - s_pingPong.setCounterpart(chainSelector, counterpartAddress); - - assertEq(s_pingPong.getCounterpartAddress(), counterpartAddress); - assertEq(s_pingPong.getCounterpartChainSelector(), chainSelector); - } - - function test_Pausing_Success() public { - assertFalse(s_pingPong.isPaused()); - - s_pingPong.setPaused(true); - - assertTrue(s_pingPong.isPaused()); - } - - function test_OutOfOrderExecution_Success() public { - assertFalse(s_pingPong.getOutOfOrderExecution()); - - vm.expectEmit(); - emit PingPongDemo.OutOfOrderExecutionChange(true); - - s_pingPong.setOutOfOrderExecution(true); - - assertTrue(s_pingPong.getOutOfOrderExecution()); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol deleted file mode 100644 index 8947a27..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/FacadeClient.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; - -import {Client} from "../../../libraries/Client.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -/// @title FacadeClient - A simple proxy for calling Router -contract FacadeClient { - address private immutable i_router; - uint64 private immutable i_destChainSelector; - IERC20 private immutable i_sourceToken; - IERC20 private immutable i_feeToken; - address private immutable i_receiver; - - uint256 private s_msg_sequence = 1; - - constructor(address router, uint64 destChainSelector, IERC20 sourceToken, IERC20 feeToken, address receiver) { - i_router = router; - i_destChainSelector = destChainSelector; - i_sourceToken = sourceToken; - i_feeToken = feeToken; - i_receiver = receiver; - - sourceToken.approve(address(router), 2 ** 256 - 1); - feeToken.approve(address(router), 2 ** 256 - 1); - } - - /// @dev Calls Router to initiate CCIP send. - /// The expectation is that s_msg_sequence will always match the sequence in emitted CCIP messages. - function send( - uint256 amount - ) public { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0].token = address(i_sourceToken); - tokenAmounts[0].amount = amount; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(s_msg_sequence), - tokenAmounts: tokenAmounts, - extraArgs: "", - feeToken: address(i_feeToken) - }); - - s_msg_sequence++; - - IRouterClient(i_router).ccipSend(i_destChainSelector, message); - } - - function getSequence() public view returns (uint256) { - return s_msg_sequence; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol deleted file mode 100644 index 0c1cc71..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Client} from "../../../libraries/Client.sol"; -import {Internal} from "../../../libraries/Internal.sol"; -import {OnRamp} from "../../../onRamp/OnRamp.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {OnRampSetup} from "../../onRamp/OnRampSetup.t.sol"; -import {FacadeClient} from "./FacadeClient.sol"; -import {ReentrantMaliciousTokenPool} from "./ReentrantMaliciousTokenPool.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -/// @title MultiOnRampTokenPoolReentrancy -/// Attempts to perform a reentrancy exploit on Onramp with a malicious TokenPool -contract OnRampTokenPoolReentrancy is OnRampSetup { - FacadeClient internal s_facadeClient; - ReentrantMaliciousTokenPool internal s_maliciousTokenPool; - IERC20 internal s_sourceToken; - IERC20 internal s_feeToken; - address internal immutable i_receiver = makeAddr("receiver"); - - function setUp() public virtual override { - OnRampSetup.setUp(); - - s_sourceToken = IERC20(s_sourceTokens[0]); - s_feeToken = IERC20(s_sourceTokens[0]); - - s_facadeClient = - new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); - - s_maliciousTokenPool = new ReentrantMaliciousTokenPool( - address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) - ); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), - remoteTokenAddress: abi.encode(s_destTokens[0]), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_maliciousTokenPool.applyChainUpdates(chainUpdates); - s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); - - s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); - - s_sourceToken.transfer(address(s_facadeClient), 1e18); - s_feeToken.transfer(address(s_facadeClient), 1e18); - } - - /// @dev This test was used to showcase a reentrancy exploit on OnRamp with malicious TokenPool. - /// How it worked: OnRamp used to construct EVM2Any messages after calling TokenPool's lockOrBurn. - /// This allowed the malicious TokenPool to break message sequencing expectations as follows: - /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> - /// (reenter)-> Facade -> 2nd call to ccipSend - /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. - /// The issue was fixed by implementing a reentrancy guard in OnRamp. - function test_OnRampTokenPoolReentrancy_Success() public { - uint256 amount = 1; - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0].token = address(s_sourceToken); - tokenAmounts[0].amount = amount; - - Client.EVM2AnyMessage memory message1 = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(uint256(1)), // message 1 contains data 1 - tokenAmounts: tokenAmounts, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - feeToken: address(s_feeToken) - }); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); - assertGt(expectedFee, 0); - - vm.expectRevert(OnRamp.ReentrancyGuardReentrantCall.selector); - s_facadeClient.send(amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol deleted file mode 100644 index f50f233..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../../libraries/Pool.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {FacadeClient} from "./FacadeClient.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract ReentrantMaliciousTokenPool is TokenPool { - address private immutable i_facade; - - bool private s_attacked; - - constructor( - address facade, - IERC20 token, - address rmnProxy, - address router - ) TokenPool(token, new address[](0), rmnProxy, router) { - i_facade = facade; - } - - /// @dev Calls into Facade to reenter Router exactly 1 time - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external override returns (Pool.LockOrBurnOutV1 memory) { - if (s_attacked) { - return - Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - s_attacked = true; - - // solhint-disable-next-line check-send-result - FacadeClient(i_facade).send(lockOrBurnIn.amount); - emit Burned(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol deleted file mode 100644 index b03081b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/capability/CCIPHome.t.sol +++ /dev/null @@ -1,969 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ICapabilityConfiguration} from "../../../keystone/interfaces/ICapabilityConfiguration.sol"; -import {ICapabilitiesRegistry} from "../../interfaces/ICapabilitiesRegistry.sol"; - -import {CCIPHome} from "../../capability/CCIPHome.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {CCIPHomeHelper} from "../helpers/CCIPHomeHelper.sol"; -import {Test} from "forge-std/Test.sol"; -import {Vm} from "forge-std/Vm.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; - -contract CCIPHomeTest is Test { - // address internal constant OWNER = address(0x0000000123123123123); - bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); - address internal constant CAPABILITIES_REGISTRY = address(0x0000000123123123123); - Internal.OCRPluginType internal constant DEFAULT_PLUGIN_TYPE = Internal.OCRPluginType.Commit; - uint32 internal constant DEFAULT_DON_ID = 78978987; - - CCIPHomeHelper public s_ccipHome; - - uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 private constant PREFIX = 0x000a << (256 - 16); // 0x000b00..00 - - uint64 private constant DEFAULT_CHAIN_SELECTOR = 9381579735; - - function setUp() public virtual { - s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), _getBaseChainConfigs()); - - ICapabilitiesRegistry.NodeInfo memory nodeInfo = ICapabilitiesRegistry.NodeInfo({ - p2pId: keccak256("p2pId"), - signer: keccak256("signer"), - nodeOperatorId: 1, - configCount: 1, - workflowDONId: 1, - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - capabilitiesDONIds: new uint256[](0) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector), abi.encode(nodeInfo) - ); - - vm.startPrank(address(s_ccipHome)); - } - - function _getBaseChainConfigs() internal pure returns (CCIPHome.ChainConfigArgs[] memory) { - CCIPHome.ChainConfigArgs[] memory configs = new CCIPHome.ChainConfigArgs[](1); - CCIPHome.ChainConfig memory chainConfig = - CCIPHome.ChainConfig({readers: new bytes32[](0), fChain: 1, config: abi.encode("chainConfig")}); - configs[0] = CCIPHome.ChainConfigArgs({chainSelector: DEFAULT_CHAIN_SELECTOR, chainConfig: chainConfig}); - - return configs; - } - - function _getConfigDigest( - uint32 donId, - Internal.OCRPluginType pluginType, - bytes memory config, - uint32 version - ) internal view returns (bytes32) { - return bytes32( - (PREFIX & PREFIX_MASK) - | ( - uint256( - keccak256( - bytes.concat( - abi.encode(bytes32("EVM"), block.chainid, address(s_ccipHome), donId, pluginType, version), config - ) - ) - ) & ~PREFIX_MASK - ) - ); - } - - function _getBaseConfig( - Internal.OCRPluginType pluginType - ) internal pure returns (CCIPHome.OCR3Config memory) { - CCIPHome.OCR3Node[] memory nodes = new CCIPHome.OCR3Node[](4); - for (uint256 i = 0; i < nodes.length; i++) { - nodes[i] = CCIPHome.OCR3Node({ - p2pId: keccak256(abi.encode("p2pId", i)), - signerKey: abi.encode("signerKey"), - transmitterKey: abi.encode("transmitterKey") - }); - } - - return CCIPHome.OCR3Config({ - pluginType: pluginType, - chainSelector: DEFAULT_CHAIN_SELECTOR, - FRoleDON: 1, - offchainConfigVersion: 98765, - offrampAddress: abi.encode("offrampAddress"), - rmnHomeAddress: abi.encode("rmnHomeAddress"), - nodes: nodes, - offchainConfig: abi.encode("offchainConfig") - }); - } -} - -contract CCIPHome_constructor is CCIPHomeTest { - function test_constructor_success() public { - CCIPHome ccipHome = new CCIPHome(CAPABILITIES_REGISTRY); - - assertEq(address(ccipHome.getCapabilityRegistry()), CAPABILITIES_REGISTRY); - } - - function test_supportsInterface_success() public view { - assertTrue(s_ccipHome.supportsInterface(type(IERC165).interfaceId)); - assertTrue(s_ccipHome.supportsInterface(type(ICapabilityConfiguration).interfaceId)); - } - - function test_getCapabilityConfiguration_success() public view { - bytes memory config = s_ccipHome.getCapabilityConfiguration(DEFAULT_DON_ID); - assertEq(config.length, 0); - } - - function test_constructor_CapabilitiesRegistryAddressZero_reverts() public { - vm.expectRevert(CCIPHome.ZeroAddressNotAllowed.selector); - new CCIPHome(address(0)); - } -} - -contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTest { - function setUp() public virtual override { - super.setUp(); - vm.stopPrank(); - vm.startPrank(address(CAPABILITIES_REGISTRY)); - } - - function test_beforeCapabilityConfigSet_success() public { - // first set a config - bytes memory callData = abi.encodeCall( - CCIPHome.setCandidate, - (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) - ); - - vm.expectCall(address(s_ccipHome), callData); - - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - - // Then revoke the config - bytes32 candidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertNotEq(candidateDigest, ZERO_DIGEST); - - callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, candidateDigest)); - - vm.expectCall(address(s_ccipHome), callData); - - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - - // Then set a new config - callData = abi.encodeCall( - CCIPHome.setCandidate, - (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) - ); - - vm.expectCall(address(s_ccipHome), callData); - - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - - // Then promote the new config - - bytes32 newCandidateDigest = s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertNotEq(newCandidateDigest, ZERO_DIGEST); - - callData = abi.encodeCall( - CCIPHome.promoteCandidateAndRevokeActive, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, newCandidateDigest, ZERO_DIGEST) - ); - - vm.expectCall(address(s_ccipHome), callData); - - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - - bytes32 activeDigest = s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, newCandidateDigest); - } - - function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() public { - bytes memory callData = abi.encodeCall( - CCIPHome.setCandidate, - (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) - ); - - vm.stopPrank(); - - vm.expectRevert(CCIPHome.OnlyCapabilitiesRegistryCanCall.selector); - - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - } - - function test_beforeCapabilityConfigSet_InvalidSelector_reverts() public { - bytes memory callData = abi.encodeCall(CCIPHome.getConfigDigests, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidSelector.selector, CCIPHome.getConfigDigests.selector)); - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - } - - function test_beforeCapabilityConfigSet_DONIdMismatch_reverts() public { - uint32 wrongDonId = DEFAULT_DON_ID + 1; - - bytes memory callData = abi.encodeCall( - CCIPHome.setCandidate, - (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) - ); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.DONIdMismatch.selector, DEFAULT_DON_ID, wrongDonId)); - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, wrongDonId); - } - - function test_beforeCapabilityConfigSet_InnerCallReverts_reverts() public { - bytes memory callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST)); - - vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); - s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); - } -} - -contract CCIPHome_getConfigDigests is CCIPHomeTest { - function test_getConfigDigests_success() public { - (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, ZERO_DIGEST); - assertEq(candidateDigest, ZERO_DIGEST); - - CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); - bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, ZERO_DIGEST); - assertEq(candidateDigest, firstDigest); - - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, firstDigest); - assertEq(candidateDigest, ZERO_DIGEST); - - bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, firstDigest); - assertEq(candidateDigest, secondDigest); - - assertEq(activeDigest, s_ccipHome.getActiveDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); - assertEq(candidateDigest, s_ccipHome.getCandidateDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); - } -} - -contract CCIPHome_getAllConfigs is CCIPHomeTest { - function test_getAllConfigs_success() public { - CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); - bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = - s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeConfig.configDigest, ZERO_DIGEST); - assertEq(candidateConfig.configDigest, firstDigest); - - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, firstDigest, ZERO_DIGEST); - - (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeConfig.configDigest, firstDigest); - assertEq(candidateConfig.configDigest, ZERO_DIGEST); - - bytes32 secondDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeConfig.configDigest, firstDigest); - assertEq(candidateConfig.configDigest, secondDigest); - - (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID + 1, DEFAULT_PLUGIN_TYPE); - assertEq(activeConfig.configDigest, ZERO_DIGEST); - assertEq(candidateConfig.configDigest, ZERO_DIGEST); - - (activeConfig, candidateConfig) = s_ccipHome.getAllConfigs(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); - assertEq(activeConfig.configDigest, ZERO_DIGEST); - assertEq(candidateConfig.configDigest, ZERO_DIGEST); - } -} - -contract CCIPHome_setCandidate is CCIPHomeTest { - function test_setCandidate_success() public { - CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); - CCIPHome.VersionedConfig memory versionedConfig = - CCIPHome.VersionedConfig({version: 1, config: config, configDigest: ZERO_DIGEST}); - - versionedConfig.configDigest = - _getConfigDigest(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, abi.encode(versionedConfig.config), versionedConfig.version); - - vm.expectEmit(); - emit CCIPHome.ConfigSet(versionedConfig.configDigest, versionedConfig.version, versionedConfig.config); - - s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.config, ZERO_DIGEST); - - (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = - s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, versionedConfig.configDigest); - assertTrue(ok); - assertEq(storedVersionedConfig.version, versionedConfig.version); - assertEq(storedVersionedConfig.configDigest, versionedConfig.configDigest); - assertEq(keccak256(abi.encode(storedVersionedConfig.config)), keccak256(abi.encode(versionedConfig.config))); - } - - function test_setCandidate_ConfigDigestMismatch_reverts() public { - CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); - - bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); - s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - - vm.expectEmit(); - emit CCIPHome.CandidateConfigRevoked(digest); - - s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, digest); - } - - function test_setCandidate_CanOnlySelfCall_reverts() public { - vm.stopPrank(); - - vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); - s_ccipHome.setCandidate( - DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST - ); - } -} - -contract CCIPHome_revokeCandidate is CCIPHomeTest { - // Sets two configs - function setUp() public virtual override { - super.setUp(); - CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); - bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, digest, ZERO_DIGEST); - - config.offrampAddress = abi.encode("new_offrampAddress"); - s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); - } - - function test_revokeCandidate_success() public { - (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = - s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - - vm.expectEmit(); - emit CCIPHome.CandidateConfigRevoked(priorCandidateDigest); - - s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); - - (CCIPHome.VersionedConfig memory storedVersionedConfig, bool ok) = - s_ccipHome.getConfig(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest); - assertFalse(ok); - // Ensure no old data is returned, even though it's still in storage - assertEq(storedVersionedConfig.version, 0); - assertEq(storedVersionedConfig.config.chainSelector, 0); - assertEq(storedVersionedConfig.config.FRoleDON, 0); - - // Asser the active digest is unaffected but the candidate digest is set to zero - (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - assertEq(activeDigest, priorActiveDigest); - assertEq(candidateDigest, ZERO_DIGEST); - assertTrue(candidateDigest != priorCandidateDigest); - } - - function test_revokeCandidate_ConfigDigestMismatch_reverts() public { - (, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - - bytes32 wrongDigest = keccak256("wrong_digest"); - vm.expectRevert(abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); - s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongDigest); - } - - function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { - vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); - s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST); - } - - function test_revokeCandidate_CanOnlySelfCall_reverts() public { - vm.startPrank(address(0)); - - vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); - s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("configDigest")); - } -} - -contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTest { - function test_promoteCandidateAndRevokeActive_multiplePlugins_success() public { - promoteCandidateAndRevokeActive(Internal.OCRPluginType.Commit); - promoteCandidateAndRevokeActive(Internal.OCRPluginType.Execution); - - // check that the two plugins have only active configs and no candidates. - (bytes32 activeDigest, bytes32 candidateDigest) = - s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Commit); - assertTrue(activeDigest != ZERO_DIGEST); - assertEq(candidateDigest, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, Internal.OCRPluginType.Execution); - assertTrue(activeDigest != ZERO_DIGEST); - assertEq(candidateDigest, ZERO_DIGEST); - } - - function promoteCandidateAndRevokeActive( - Internal.OCRPluginType pluginType - ) public { - CCIPHome.OCR3Config memory config = _getBaseConfig(pluginType); - bytes32 firstConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); - - vm.expectEmit(); - emit CCIPHome.ConfigPromoted(firstConfigToPromote); - - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, firstConfigToPromote, ZERO_DIGEST); - - // Assert the active digest is updated and the candidate digest is set to zero - (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, pluginType); - assertEq(activeDigest, firstConfigToPromote); - assertEq(candidateDigest, ZERO_DIGEST); - - // Set a new candidate to promote over a non-zero active config. - config.offchainConfig = abi.encode("new_offchainConfig_config"); - bytes32 secondConfigToPromote = s_ccipHome.setCandidate(DEFAULT_DON_ID, pluginType, config, ZERO_DIGEST); - - vm.expectEmit(); - emit CCIPHome.ActiveConfigRevoked(firstConfigToPromote); - - vm.expectEmit(); - emit CCIPHome.ConfigPromoted(secondConfigToPromote); - - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, pluginType, secondConfigToPromote, firstConfigToPromote); - - (CCIPHome.VersionedConfig memory activeConfig, CCIPHome.VersionedConfig memory candidateConfig) = - s_ccipHome.getAllConfigs(DEFAULT_DON_ID, pluginType); - assertEq(activeConfig.configDigest, secondConfigToPromote); - assertEq(candidateConfig.configDigest, ZERO_DIGEST); - assertEq(keccak256(abi.encode(activeConfig.config)), keccak256(abi.encode(config))); - } - - function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { - vm.expectRevert(CCIPHome.NoOpStateTransitionNotAllowed.selector); - s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST, ZERO_DIGEST); - } - - function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { - (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = - s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); - bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); - bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); - - vm.expectRevert( - abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) - ); - s_ccipHome.promoteCandidateAndRevokeActive( - DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongCandidateDigest, wrongActiveDigest - ); - - vm.expectRevert( - abi.encodeWithSelector(CCIPHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest) - ); - - s_ccipHome.promoteCandidateAndRevokeActive( - DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, priorCandidateDigest, wrongActiveDigest - ); - } - - function test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() public { - vm.stopPrank(); - - vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); - s_ccipHome.promoteCandidateAndRevokeActive( - DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, keccak256("toPromote"), keccak256("ToRevoke") - ); - } -} - -contract CCIPHome__validateConfig is CCIPHomeTest { - function setUp() public virtual override { - s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); - } - - function _addChainConfig( - uint256 numNodes - ) internal returns (CCIPHome.OCR3Node[] memory nodes) { - return _addChainConfig(numNodes, 1); - } - - function _makeBytes32Array(uint256 length, uint256 seed) internal pure returns (bytes32[] memory arr) { - arr = new bytes32[](length); - for (uint256 i = 0; i < length; i++) { - arr[i] = keccak256(abi.encode(i, 1, seed)); - } - return arr; - } - - function _makeBytesArray(uint256 length, uint256 seed) internal pure returns (bytes[] memory arr) { - arr = new bytes[](length); - for (uint256 i = 0; i < length; i++) { - arr[i] = abi.encode(keccak256(abi.encode(i, 1, seed))); - } - return arr; - } - - function _addChainConfig(uint256 numNodes, uint8 fChain) internal returns (CCIPHome.OCR3Node[] memory nodes) { - bytes32[] memory p2pIds = _makeBytes32Array(numNodes, 0); - bytes[] memory signers = _makeBytesArray(numNodes, 10); - bytes[] memory transmitters = _makeBytesArray(numNodes, 20); - - nodes = new CCIPHome.OCR3Node[](numNodes); - - for (uint256 i = 0; i < numNodes; i++) { - nodes[i] = CCIPHome.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, p2pIds[i]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(signers[i]), - p2pId: p2pIds[i], - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - } - // Add chain selector for chain 1. - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: p2pIds, fChain: fChain, config: bytes("config1")}) - }); - - vm.expectEmit(); - emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - - return nodes; - } - - function _getCorrectOCR3Config(uint8 numNodes, uint8 FRoleDON) internal returns (CCIPHome.OCR3Config memory) { - CCIPHome.OCR3Node[] memory nodes = _addChainConfig(numNodes); - - return CCIPHome.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encode(keccak256(abi.encode("offramp"))), - rmnHomeAddress: abi.encode(keccak256(abi.encode("rmnHome"))), - chainSelector: 1, - nodes: nodes, - FRoleDON: FRoleDON, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - } - - function _getCorrectOCR3Config() internal returns (CCIPHome.OCR3Config memory) { - return _getCorrectOCR3Config(4, 1); - } - - // Successes. - - function test__validateConfig_Success() public { - s_ccipHome.validateConfig(_getCorrectOCR3Config()); - } - - function test__validateConfigLessTransmittersThanSigners_Success() public { - // fChain is 1, so there should be at least 4 transmitters. - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(5, 1); - config.nodes[1].transmitterKey = bytes(""); - - s_ccipHome.validateConfig(config); - } - - function test__validateConfigSmallerFChain_Success() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(11, 3); - - // Set fChain to 2 - _addChainConfig(4, 2); - - s_ccipHome.validateConfig(config); - } - - // Reverts - - function test__validateConfig_ChainSelectorNotSet_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.chainSelector = 0; // invalid - - vm.expectRevert(CCIPHome.ChainSelectorNotSet.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.offrampAddress = ""; // invalid - - vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.offrampAddress = abi.encode(address(0)); // invalid - - vm.expectRevert(CCIPHome.OfframpAddressCannotBeZero.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.rmnHomeAddress = ""; // invalid - - vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.rmnHomeAddress = abi.encode(address(0)); // invalid - - vm.expectRevert(CCIPHome.RMNHomeAddressCannotBeZero.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_ChainSelectorNotFound_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.chainSelector = 2; // not set - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 2)); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_NotEnoughTransmitters_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - uint256 numberOfTransmitters = 3; - - // 32 > 31 (max num oracles) - CCIPHome.OCR3Node[] memory nodes = _addChainConfig(31); - - // truncate transmitters to < 3 * fChain + 1 - // since fChain is 1 in this case, we need to truncate to 3 transmitters. - for (uint256 i = numberOfTransmitters; i < nodes.length; ++i) { - nodes[i].transmitterKey = bytes(""); - } - - config.nodes = nodes; - vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, numberOfTransmitters, 4)); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.nodes[0].transmitterKey = bytes(""); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 3, 4)); - s_ccipHome.validateConfig(config); - - // Zero out remaining transmitters to verify error changes - for (uint256 i = 1; i < config.nodes.length; ++i) { - config.nodes[i].transmitterKey = bytes(""); - } - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.NotEnoughTransmitters.selector, 0, 4)); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_TooManySigners_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.nodes = new CCIPHome.OCR3Node[](257); - - vm.expectRevert(CCIPHome.TooManySigners.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_FChainTooHigh_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.FRoleDON = 2; // too low - - // Set fChain to 3 - _addChainConfig(4, 3); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 3, 2)); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_FMustBePositive_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.FRoleDON = 0; // not positive - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.FChainTooHigh.selector, 1, 0)); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_FTooHigh_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.FRoleDON = 2; // too high - - vm.expectRevert(CCIPHome.FTooHigh.selector); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_ZeroP2PId_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.nodes[1].p2pId = bytes32(0); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[1])); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_ZeroSignerKey_Reverts() public { - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.nodes[2].signerKey = bytes(""); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidNode.selector, config.nodes[2])); - s_ccipHome.validateConfig(config); - } - - function test__validateConfig_NodeNotInRegistry_Reverts() public { - CCIPHome.OCR3Node[] memory nodes = _addChainConfig(4); - bytes32 nonExistentP2PId = keccak256("notInRegistry"); - nodes[0].p2pId = nonExistentP2PId; - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, nonExistentP2PId), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 0, - signer: bytes32(0), - p2pId: bytes32(uint256(0)), - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); - config.nodes = nodes; - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.NodeNotInRegistry.selector, nonExistentP2PId)); - s_ccipHome.validateConfig(config); - } -} - -contract CCIPHome_applyChainConfigUpdates is CCIPHomeTest { - function setUp() public virtual override { - s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); - } - - function test_applyChainConfigUpdates_addChainConfigs_Success() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPHome.ChainConfigArgs({ - chainSelector: 2, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) - }); - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - vm.expectEmit(); - emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); - vm.expectEmit(); - emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - - CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); - assertEq(configs.length, 2, "chain configs length must be 2"); - assertEq(configs[0].chainSelector, 1, "chain selector must match"); - assertEq(configs[1].chainSelector, 2, "chain selector must match"); - assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); - } - - function test_getPaginatedCCIPHomes_Success() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPHome.ChainConfigArgs({ - chainSelector: 2, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) - }); - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - - CCIPHome.ChainConfigArgs[] memory configs = s_ccipHome.getAllChainConfigs(0, 2); - assertEq(configs.length, 2, "chain configs length must be 2"); - assertEq(configs[0].chainSelector, 1, "chain selector must match"); - assertEq(configs[1].chainSelector, 2, "chain selector must match"); - - configs = s_ccipHome.getAllChainConfigs(0, 1); - assertEq(configs.length, 1, "chain configs length must be 1"); - assertEq(configs[0].chainSelector, 1, "chain selector must match"); - - configs = s_ccipHome.getAllChainConfigs(0, 10); - assertEq(configs.length, 2, "chain configs length must be 2"); - assertEq(configs[0].chainSelector, 1, "chain selector must match"); - assertEq(configs[1].chainSelector, 2, "chain selector must match"); - - configs = s_ccipHome.getAllChainConfigs(1, 1); - assertEq(configs.length, 1, "chain configs length must be 1"); - - configs = s_ccipHome.getAllChainConfigs(1, 2); - assertEq(configs.length, 0, "chain configs length must be 0"); - } - - function test_applyChainConfigUpdates_removeChainConfigs_Success() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPHome.ChainConfigArgs({ - chainSelector: 2, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config2")}) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectEmit(); - emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); - vm.expectEmit(); - emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - - assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); - - uint64[] memory removes = new uint64[](1); - removes[0] = uint64(1); - - vm.expectEmit(); - emit CCIPHome.ChainConfigRemoved(1); - s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); - - assertEq(s_ccipHome.getNumChainConfigurations(), 1, "total chain configs must be 1"); - } - - // Reverts. - - function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { - uint64[] memory removes = new uint64[](1); - removes[0] = uint64(1); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.ChainSelectorNotFound.selector, 1)); - s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); - } - - function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: abi.encode(1, 2, 3)}) - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 0, - signer: bytes32(0), - p2pId: bytes32(uint256(0)), - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectRevert(abi.encodeWithSelector(CCIPHome.NodeNotInRegistry.selector, chainReaders[0])); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - } - - function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { - bytes32[] memory chainReaders = new bytes32[](1); - chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); - adds[0] = CCIPHome.ChainConfigArgs({ - chainSelector: 1, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 1, config: bytes("config1")}) - }); - adds[1] = CCIPHome.ChainConfigArgs({ - chainSelector: 2, - chainConfig: CCIPHome.ChainConfig({readers: chainReaders, fChain: 0, config: bytes("config2")}) // bad fChain - }); - - vm.mockCall( - CAPABILITIES_REGISTRY, - abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, chainReaders[0]), - abi.encode( - ICapabilitiesRegistry.NodeInfo({ - nodeOperatorId: 1, - signer: bytes32(uint256(1)), - p2pId: chainReaders[0], - encryptionPublicKey: keccak256("encryptionPublicKey"), - hashedCapabilityIds: new bytes32[](0), - configCount: uint32(1), - workflowDONId: uint32(1), - capabilitiesDONIds: new uint256[](0) - }) - ) - ); - - vm.expectRevert(CCIPHome.FChainMustBePositive.selector); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol deleted file mode 100644 index 4d462ad..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol +++ /dev/null @@ -1,305 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {NonceManager} from "../../NonceManager.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import "../helpers/MerkleHelper.sol"; -import "../offRamp/OffRampSetup.t.sol"; -import "../onRamp/OnRampSetup.t.sol"; - -/// @notice This E2E test implements the following scenario: -/// 1. Send multiple messages from multiple source chains to a single destination chain (2 messages from source chain 1 and 1 from -/// source chain 2). -/// 2. Commit multiple merkle roots (1 for each source chain). -/// 3. Batch execute all the committed messages. -contract E2E is OnRampSetup, OffRampSetup { - using Internal for Internal.Any2EVMRampMessage; - - Router internal s_sourceRouter2; - OnRampHelper internal s_onRamp2; - TokenAdminRegistry internal s_tokenAdminRegistry2; - NonceManager internal s_nonceManager2; - - bytes32 internal s_metadataHash2; - - mapping(address destPool => address sourcePool) internal s_sourcePoolByDestPool; - - function setUp() public virtual override(OnRampSetup, OffRampSetup) { - OnRampSetup.setUp(); - OffRampSetup.setUp(); - - // Deploy new source router for the new source chain - s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); - - // Deploy new TokenAdminRegistry for the new source chain - s_tokenAdminRegistry2 = new TokenAdminRegistry(); - - // Deploy new token pools and set them on the new TokenAdminRegistry - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - address token = s_sourceTokens[i]; - address pool = address( - new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) - ); - - s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; - - _setPool( - s_tokenAdminRegistry2, token, pool, DEST_CHAIN_SELECTOR, s_destPoolByToken[s_destTokens[i]], s_destTokens[i] - ); - } - - for (uint256 i = 0; i < s_destTokens.length; ++i) { - address token = s_destTokens[i]; - address pool = s_destPoolByToken[token]; - - _setPool( - s_tokenAdminRegistry2, token, pool, SOURCE_CHAIN_SELECTOR + 1, s_sourcePoolByDestPool[pool], s_sourceTokens[i] - ); - } - - s_nonceManager2 = new NonceManager(new address[](0)); - - ( - // Deploy the new source chain onramp - // Outsource to shared helper function with OnRampSetup - s_onRamp2, - s_metadataHash2 - ) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR + 1, s_sourceRouter2, address(s_nonceManager2), address(s_tokenAdminRegistry2) - ); - - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(s_onRamp2); - s_nonceManager2.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - - // Enable destination chain on new source chain router - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp2)}); - s_sourceRouter2.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - // Deploy offramp - _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); - - // Enable source chains on offramp - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - isEnabled: true, - // Must match OnRamp address - onRamp: abi.encode(address(s_onRamp)) - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - isEnabled: true, - onRamp: abi.encode(address(s_onRamp2)) - }); - - _setupMultipleOffRampsFromConfigs(sourceChainConfigs); - } - - function test_E2E_3MessagesMMultiOffRampSuccess_gas() public { - vm.pauseGasMetering(); - - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - // Scoped to sending to reduce stack pressure - { - IERC20 token0 = IERC20(s_sourceTokens[0]); - IERC20 token1 = IERC20(s_sourceTokens[1]); - - uint256 balance0Pre = token0.balanceOf(OWNER); - uint256 balance1Pre = token1.balanceOf(OWNER); - - // Send messages - messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); - messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); - messages2[0] = - _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); - // Asserts that the tokens have been sent and the fee has been paid. - assertEq( - balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) - ); - assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); - } - - // Commit - - bytes32[] memory merkleRoots = new bytes32[](2); - - // Scoped to commit to reduce stack pressure - { - bytes32[] memory hashedMessages1 = new bytes32[](2); - hashedMessages1[0] = _hashMessage(messages1[0], abi.encode(address(s_onRamp))); - hashedMessages1[1] = _hashMessage(messages1[1], abi.encode(address(s_onRamp))); - bytes32[] memory hashedMessages2 = new bytes32[](1); - hashedMessages2[0] = _hashMessage(messages2[0], abi.encode(address(s_onRamp2))); - - merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); - merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - - // TODO make these real sigs :) - IRMNRemote.Signature[] memory rmnSignatures = new IRMNRemote.Signature[](0); - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - onRampAddress: abi.encode(address(s_onRamp)), - minSeqNr: messages1[0].header.sequenceNumber, - maxSeqNr: messages1[1].header.sequenceNumber, - merkleRoot: merkleRoots[0] - }); - roots[1] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - onRampAddress: abi.encode(address(s_onRamp2)), - minSeqNr: messages2[0].header.sequenceNumber, - maxSeqNr: messages2[0].header.sequenceNumber, - merkleRoot: merkleRoots[1] - }); - - OffRamp.CommitReport memory report = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: rmnSignatures, - rmnRawVs: 0 - }); - - vm.resumeGasMetering(); - _commit(report, ++s_latestSequenceNumber); - vm.pauseGasMetering(); - } - - // Scoped to RMN and verify to reduce stack pressure - { - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); - - bytes32[] memory proofs = new bytes32[](0); - bytes32[] memory hashedLeaves = new bytes32[](1); - hashedLeaves[0] = merkleRoots[0]; - - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); - hashedLeaves[0] = merkleRoots[1]; - timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); - - // We change the block time so when execute would e.g. use the current - // block time instead of the committed block time the value would be - // incorrect in the checks below. - vm.warp(BLOCK_TIME + 2000); - } - - // Execute - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR + 1, messages2); - - vm.resumeGasMetering(); - vm.recordLogs(); - _execute(reports); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - _hashMessage(messages1[0], abi.encode(address(s_onRamp))), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - _hashMessage(messages1[1], abi.encode(address(s_onRamp))), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR + 1, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - _hashMessage(messages2[0], abi.encode(address(s_onRamp2))), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function _sendRequest( - uint64 expectedSeqNum, - uint64 sourceChainSelector, - uint64 nonce, - bytes32 metadataHash, - Router router, - TokenAdminRegistry tokenAdminRegistry - ) public returns (Internal.Any2EVMRampMessage memory) { - Client.EVM2AnyMessage memory message = _generateTokenMessage(); - IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + router.getFee(DEST_CHAIN_SELECTOR, message)); - IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); - - uint256 feeAmount = router.getFee(DEST_CHAIN_SELECTOR, message); - - message.receiver = abi.encode(address(s_receiver)); - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( - message, - sourceChainSelector, - DEST_CHAIN_SELECTOR, - expectedSeqNum, - nonce, - feeAmount, - feeAmount, - OWNER, - metadataHash, - tokenAdminRegistry - ); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedSeqNum, msgEvent); - - vm.resumeGasMetering(); - router.ccipSend(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = - new Internal.Any2EVMTokenTransfer[](message.tokenAmounts.length); - - for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { - any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(msgEvent.tokenAmounts[i].sourcePoolAddress), - destTokenAddress: abi.decode(msgEvent.tokenAmounts[i].destTokenAddress, (address)), - extraData: msgEvent.tokenAmounts[i].extraData, - amount: msgEvent.tokenAmounts[i].amount, - destGasAmount: abi.decode(msgEvent.tokenAmounts[i].destExecData, (uint32)) - }); - } - - return Internal.Any2EVMRampMessage({ - header: Internal.RampMessageHeader({ - messageId: msgEvent.header.messageId, - sourceChainSelector: sourceChainSelector, - destChainSelector: DEST_CHAIN_SELECTOR, - sequenceNumber: msgEvent.header.sequenceNumber, - nonce: msgEvent.header.nonce - }), - sender: abi.encode(msgEvent.sender), - data: msgEvent.data, - receiver: abi.decode(msgEvent.receiver, (address)), - gasLimit: s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit, - tokenAmounts: any2EVMTokenTransfer - }); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol deleted file mode 100644 index 3356b25..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ /dev/null @@ -1,2251 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; - -import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {FeeQuoter} from "../../FeeQuoter.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; -import {FeeQuoterFeeSetup, FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; - -import {Vm} from "forge-std/Vm.sol"; - -contract FeeQuoter_constructor is FeeQuoterSetup { - function test_Setup_Success() public virtual { - address[] memory priceUpdaters = new address[](2); - priceUpdaters[0] = STRANGER; - priceUpdaters[1] = OWNER; - address[] memory feeTokens = new address[](2); - feeTokens[0] = s_sourceTokens[0]; - feeTokens[1] = s_sourceTokens[1]; - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - tokenPriceFeedUpdates[1] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); - - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - - FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - s_feeQuoter = new FeeQuoterHelper( - staticConfig, - priceUpdaters, - feeTokens, - tokenPriceFeedUpdates, - s_feeQuoterTokenTransferFeeConfigArgs, - s_feeQuoterPremiumMultiplierWeiPerEthArgs, - destChainConfigArgs - ); - - _assertFeeQuoterStaticConfigsEqual(s_feeQuoter.getStaticConfig(), staticConfig); - assertEq(feeTokens, s_feeQuoter.getFeeTokens()); - assertEq(priceUpdaters, s_feeQuoter.getAllAuthorizedCallers()); - assertEq(s_feeQuoter.typeAndVersion(), "FeeQuoter 1.6.0-dev"); - - _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[0].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[0]) - ); - - _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[1].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[1]) - ); - - assertEq( - s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].token) - ); - - assertEq( - s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].token) - ); - - FeeQuoter.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = s_feeQuoterTokenTransferFeeConfigArgs[0]; - for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { - FeeQuoter.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = - s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; - - _assertTokenTransferFeeConfigEqual( - tokenFeeArgs.tokenTransferFeeConfig, - s_feeQuoter.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) - ); - } - - for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - FeeQuoter.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; - uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - - _assertFeeQuoterDestChainConfigsEqual(expectedConfig, s_feeQuoter.getDestChainConfig(destChainSelector)); - } - } - - function test_InvalidStalenessThreshold_Revert() public { - FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: 0 - }); - - vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - - s_feeQuoter = new FeeQuoterHelper( - staticConfig, - new address[](0), - new address[](0), - new FeeQuoter.TokenPriceFeedUpdate[](0), - s_feeQuoterTokenTransferFeeConfigArgs, - s_feeQuoterPremiumMultiplierWeiPerEthArgs, - new FeeQuoter.DestChainConfigArgs[](0) - ); - } - - function test_InvalidLinkTokenEqZeroAddress_Revert() public { - FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ - linkToken: address(0), - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - - vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - - s_feeQuoter = new FeeQuoterHelper( - staticConfig, - new address[](0), - new address[](0), - new FeeQuoter.TokenPriceFeedUpdate[](0), - s_feeQuoterTokenTransferFeeConfigArgs, - s_feeQuoterPremiumMultiplierWeiPerEthArgs, - new FeeQuoter.DestChainConfigArgs[](0) - ); - } - - function test_InvalidMaxFeeJuelsPerMsg_Revert() public { - FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: 0, - stalenessThreshold: uint32(TWELVE_HOURS) - }); - - vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - - s_feeQuoter = new FeeQuoterHelper( - staticConfig, - new address[](0), - new address[](0), - new FeeQuoter.TokenPriceFeedUpdate[](0), - s_feeQuoterTokenTransferFeeConfigArgs, - s_feeQuoterPremiumMultiplierWeiPerEthArgs, - new FeeQuoter.DestChainConfigArgs[](0) - ); - } -} - -contract FeeQuoter_getTokenPrices is FeeQuoterSetup { - function test_GetTokenPrices_Success() public view { - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - - address[] memory tokens = new address[](3); - tokens[0] = s_sourceTokens[0]; - tokens[1] = s_sourceTokens[1]; - tokens[2] = s_weth; - - Internal.TimestampedPackedUint224[] memory tokenPrices = s_feeQuoter.getTokenPrices(tokens); - - assertEq(tokenPrices.length, 3); - assertEq(tokenPrices[0].value, priceUpdates.tokenPriceUpdates[0].usdPerToken); - assertEq(tokenPrices[1].value, priceUpdates.tokenPriceUpdates[1].usdPerToken); - assertEq(tokenPrices[2].value, priceUpdates.tokenPriceUpdates[2].usdPerToken); - } -} - -contract FeeQuoter_getTokenPrice is FeeQuoterSetup { - function test_GetTokenPriceFromFeed_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Above staleness threshold - vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().stalenessThreshold + 1); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer.value, uint224(1e18)); - assertEq(tokenPriceAnswer.timestamp, uint32(block.timestamp)); - } -} - -contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { - function test_GetValidatedTokenPrice_Success() public view { - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - - uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); - - assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); - } - - function test_GetValidatedTokenPriceFromFeed_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Right below staleness threshold - vm.warp(originalTimestampValue + TWELVE_HOURS); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { - uint256 originalTimestampValue = block.timestamp; - - // Right above staleness threshold - vm.warp(originalTimestampValue + TWELVE_HOURS + 1); - - address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); - - // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is: uint224.MAX_VALUE * (10 ** (36 - 18 - 18)) - assertEq(tokenPriceAnswer, uint224(type(uint224).max)); - } - - function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 6); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 6); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e6) -> expected 1e30 - assertEq(tokenPriceAnswer, uint224(1e30)); - } - - function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 24); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 24); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e24) -> expected 1e12 - assertEq(tokenPriceAnswer, uint224(1e12)); - } - - function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 - assertEq(tokenPriceAnswer, uint224(1e18)); - } - - function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 0); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 0); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e31 (0 decimal token) - unit is (1e18 * 1e18 / 1e0) -> expected 1e36 - assertEq(tokenPriceAnswer, uint224(1e67)); - } - - function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { - address tokenAddress = _deploySourceToken("testToken", 0, 20); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 20); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); - - // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e20) -> expected 1e14 - assertEq(tokenPriceAnswer, uint224(1e14)); - } - - function test_StaleFeeToken_Success() public { - vm.warp(block.timestamp + TWELVE_HOURS + 1); - - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - - uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); - - assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); - } - - // Reverts - - function test_OverflowFeedPrice_Revert() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); - s_feeQuoter.getValidatedTokenPrice(tokenAddress); - } - - function test_UnderflowFeedPrice_Revert() public { - address tokenAddress = _deploySourceToken("testToken", 0, 18); - address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); - s_feeQuoter.getValidatedTokenPrice(tokenAddress); - } - - function test_TokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); - } - - function test_TokenNotSupportedFeed_Revert() public { - address sourceToken = _initialiseSingleTokenPriceFeed(); - MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); - Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: sourceToken, usdPerToken: 0}); - - s_feeQuoter.updatePrices(priceUpdates); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, sourceToken)); - s_feeQuoter.getValidatedTokenPrice(sourceToken); - } -} - -contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { - function test_ApplyFeeTokensUpdates_Success() public { - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - - vm.expectEmit(); - emit FeeQuoter.FeeTokenAdded(feeTokens[0]); - - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_feeQuoter.getFeeTokens().length, 3); - assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); - - // add same feeToken is no-op - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_feeQuoter.getFeeTokens().length, 3); - assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); - - vm.expectEmit(); - emit FeeQuoter.FeeTokenRemoved(feeTokens[0]); - - s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_feeQuoter.getFeeTokens().length, 2); - - // removing already removed feeToken is no-op - s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_feeQuoter.getFeeTokens().length, 2); - } - - function test_OnlyCallableByOwner_Revert() public { - address[] memory feeTokens = new address[](1); - feeTokens[0] = STRANGER; - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - } -} - -contract FeeQuoter_updatePrices is FeeQuoterSetup { - function test_OnlyTokenPrice_Success() public { - Internal.PriceUpdates memory update = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - update.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated( - update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp - ); - - s_feeQuoter.updatePrices(update); - - assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); - } - - function test_OnlyGasPrice_Success() public { - Internal.PriceUpdates memory update = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](1) - }); - update.gasPriceUpdates[0] = - Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); - - vm.expectEmit(); - emit FeeQuoter.UsdPerUnitGasUpdated( - update.gasPriceUpdates[0].destChainSelector, update.gasPriceUpdates[0].usdPerUnitGas, block.timestamp - ); - - s_feeQuoter.updatePrices(update); - - assertEq( - s_feeQuoter.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas - ); - } - - function test_UpdateMultiplePrices_Success() public { - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](3); - tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); - tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[1], usdPerToken: 1800e18}); - tokenPriceUpdates[2] = Internal.TokenPriceUpdate({sourceToken: address(12345), usdPerToken: 1e18}); - - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](3); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2e6}); - gasPriceUpdates[1] = Internal.GasPriceUpdate({destChainSelector: SOURCE_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); - gasPriceUpdates[2] = Internal.GasPriceUpdate({destChainSelector: 12345, usdPerUnitGas: 1e18}); - - Internal.PriceUpdates memory update = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); - - for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated( - update.tokenPriceUpdates[i].sourceToken, update.tokenPriceUpdates[i].usdPerToken, block.timestamp - ); - } - for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { - vm.expectEmit(); - emit FeeQuoter.UsdPerUnitGasUpdated( - update.gasPriceUpdates[i].destChainSelector, update.gasPriceUpdates[i].usdPerUnitGas, block.timestamp - ); - } - - s_feeQuoter.updatePrices(update); - - for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { - assertEq( - s_feeQuoter.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken - ); - } - for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { - assertEq( - s_feeQuoter.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, - gasPriceUpdates[i].usdPerUnitGas - ); - } - } - - function test_UpdatableByAuthorizedCaller_Success() public { - Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); - - // Revert when caller is not authorized - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_feeQuoter.updatePrices(priceUpdates); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = STRANGER; - vm.startPrank(OWNER); - s_feeQuoter.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) - ); - - // Stranger is now an authorized caller to update prices - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated( - priceUpdates.tokenPriceUpdates[0].sourceToken, priceUpdates.tokenPriceUpdates[0].usdPerToken, block.timestamp - ); - s_feeQuoter.updatePrices(priceUpdates); - - assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); - - vm.startPrank(OWNER); - s_feeQuoter.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: new address[](0), removedCallers: priceUpdaters}) - ); - - // Revert when authorized caller is removed - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_feeQuoter.updatePrices(priceUpdates); - } - - // Reverts - - function test_OnlyCallableByUpdater_Revert() public { - Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_feeQuoter.updatePrices(priceUpdates); - } -} - -contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { - function test_ConvertTokenAmount_Success() public view { - Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - uint256 amount = 3e16; - uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) - / uint256(initialPriceUpdates.tokenPriceUpdates[0].usdPerToken); - uint256 expected = (amount * conversionRate) / 1e18; - assertEq(s_feeQuoter.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); - } - - function test_Fuzz_ConvertTokenAmount_Success( - uint256 feeTokenAmount, - uint224 usdPerFeeToken, - uint160 usdPerLinkToken, - uint224 usdPerUnitGas - ) public { - vm.assume(usdPerFeeToken > 0); - vm.assume(usdPerLinkToken > 0); - // We bound the max fees to be at most uint96.max link. - feeTokenAmount = bound(feeTokenAmount, 0, (uint256(type(uint96).max) * usdPerLinkToken) / usdPerFeeToken); - - address feeToken = address(1); - address linkToken = address(2); - address[] memory feeTokens = new address[](1); - feeTokens[0] = feeToken; - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](2); - tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: feeToken, usdPerToken: usdPerFeeToken}); - tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: linkToken, usdPerToken: usdPerLinkToken}); - - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: usdPerUnitGas}); - - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); - - s_feeQuoter.updatePrices(priceUpdates); - - uint256 linkFee = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, linkToken); - assertEq(linkFee, (feeTokenAmount * usdPerFeeToken) / usdPerLinkToken); - } - - // Reverts - - function test_LinkTokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_feeQuoter.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); - } -} - -contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { - function test_GetFeeTokenAndGasPrices_Success() public view { - (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); - - Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); - - assertEq(feeTokenPrice, s_sourceTokenPrices[0]); - assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); - } - - function test_ZeroGasPrice_Success() public { - uint64 zeroGasDestChainSelector = 345678; - Internal.GasPriceUpdate[] memory gasPriceUpdates = new Internal.GasPriceUpdate[](1); - gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: zeroGasDestChainSelector, usdPerUnitGas: 0}); - - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); - s_feeQuoter.updatePrices(priceUpdates); - - (, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); - - assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); - } - - function test_UnsupportedChain_Revert() public { - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.ChainNotSupported.selector, DEST_CHAIN_SELECTOR + 1)); - s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); - } - - function test_StaleGasPrice_Revert() public { - uint256 diff = TWELVE_HOURS + 1; - vm.warp(block.timestamp + diff); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); - s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); - } -} - -contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { - function test_ZeroFeeds_Success() public { - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); - vm.recordLogs(); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - // Verify no log emissions - assertEq(logEntries.length, 0); - } - - function test_SingleFeedUpdate_Success() public { - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken)); - - vm.expectEmit(); - emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - } - - function test_MultipleFeedUpdate_Success() public { - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); - - for (uint256 i = 0; i < 2; ++i) { - tokenPriceFeedUpdates[i] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[i], s_dataFeedByToken[s_sourceTokens[i]], 18); - - _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken)); - - vm.expectEmit(); - emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig); - } - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig - ); - } - - function test_FeedUnset_Success() public { - Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); - assertFalse(priceQueryInitial.value == 0); - assertFalse(priceQueryInitial.timestamp == 0); - - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - - tokenPriceFeedUpdates[0].feedConfig.dataFeedAddress = address(0); - vm.expectEmit(); - emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - - // Price data should remain after a feed has been set->unset - Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); - assertEq(priceQueryPostUnsetFeed.value, priceQueryInitial.value); - assertEq(priceQueryPostUnsetFeed.timestamp, priceQueryInitial.timestamp); - } - - function test_FeedNotUpdated() public { - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - - _assertTokenPriceFeedConfigEquality( - s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig - ); - } - - // Reverts - - function test_FeedUpdatedByNonOwner_Revert() public { - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - } -} - -contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { - function test_Fuzz_applyDestChainConfigUpdates_Success( - FeeQuoter.DestChainConfigArgs memory destChainConfigArgs - ) public { - vm.assume(destChainConfigArgs.destChainSelector != 0); - vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); - destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( - bound( - destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit - ) - ); - destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - - bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; - - FeeQuoter.DestChainConfigArgs[] memory newDestChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); - newDestChainConfigArgs[0] = destChainConfigArgs; - - if (isNewChain) { - vm.expectEmit(); - emit FeeQuoter.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); - } else { - vm.expectEmit(); - emit FeeQuoter.DestChainConfigUpdated(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); - } - - s_feeQuoter.applyDestChainConfigUpdates(newDestChainConfigArgs); - - _assertFeeQuoterDestChainConfigsEqual( - destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector) - ); - } - - function test_applyDestChainConfigUpdates_Success() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); - destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; - destChainConfigArgs[0].destChainConfig.isEnabled = false; - destChainConfigArgs[1] = _generateFeeQuoterDestChainConfigArgs()[0]; - destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - vm.expectEmit(); - emit FeeQuoter.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); - vm.expectEmit(); - emit FeeQuoter.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); - - vm.recordLogs(); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - FeeQuoter.DestChainConfig memory gotDestChainConfig0 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - FeeQuoter.DestChainConfig memory gotDestChainConfig1 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); - - assertEq(vm.getRecordedLogs().length, 2); - _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); - _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); - } - - function test_applyDestChainConfigUpdatesZeroIntput_Success() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); - - vm.recordLogs(); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - // Allow setting to the max value - destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - // Revert when exceeding max value - destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainSelector = 0; - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidChainFamilySelector_Revert() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); - - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - } -} - -contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { - function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { - uint256 dataAvailabilityCostUSD = - s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - - // Test that the cost is destnation chain specific - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = - destChainConfig.destDataAvailabilityOverheadGas * 2; - destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = - destChainConfig.destGasPerDataAvailabilityByte * 2; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = - destChainConfig.destDataAvailabilityMultiplierBps * 2; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); - uint256 dataAvailabilityCostUSD2 = - s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * Internal.MESSAGE_FIXED_BYTES; - expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); - assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); - } - - function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { - uint256 dataAvailabilityCostUSD = - s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 dataAvailabilityLengthBytes = - Internal.MESSAGE_FIXED_BYTES + 100 + (5 * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; - uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas - + destChainConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } - - function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { - uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - assertEq(dataAvailabilityCostUSD, 0); - } - - function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public view { - uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead - ); - - assertEq(0, dataAvailabilityCostUSD); - } - - function test_Fuzz_CalculateDataAvailabilityCost_Success( - uint64 destChainSelector, - uint32 destDataAvailabilityOverheadGas, - uint16 destGasPerDataAvailabilityByte, - uint16 destDataAvailabilityMultiplierBps, - uint112 dataAvailabilityGasPrice, - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public { - vm.assume(destChainSelector != 0); - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(destChainSelector); - destChainConfigArgs[0] = - FeeQuoter.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); - destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; - destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; - destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; - destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; - destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( - destChainConfigArgs[0].destChainSelector, - dataAvailabilityGasPrice, - messageDataLength, - numberOfTokens, - tokenTransferBytesOverhead - ); - - uint256 dataAvailabilityLengthBytes = Internal.MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - uint256 dataAvailabilityGas = - destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } -} - -contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { - function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( - FeeQuoter.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg - ) public { - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; - - vm.expectEmit(); - emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( - premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth - ); - - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - - vm.expectEmit(); - emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); - premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); - - vm.expectEmit(); - emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - vm.expectEmit(); - emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( - vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth - ); - - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - assertEq( - premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(2)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { - vm.recordLogs(); - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](0)); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - } -} - -contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { - function test_Fuzz_ApplyTokenTransferFeeConfig_Success( - FeeQuoter.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs - ) public { - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(2, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { - tokenTransferFeeConfigs[j].destBytesOverhead = uint32( - bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) - ); - address feeToken = s_sourceTokens[j]; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; - - vm.expectEmit(); - emit FeeQuoter.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] - ); - } - } - - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - - for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigs[i], - s_feeQuoter.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token - ) - ); - } - } - - function test_ApplyTokenTransferFeeConfig_Success() public { - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: 312, - isEnabled: true - }); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 12, - maxFeeUSDCents: 13, - deciBps: 14, - destGasOverhead: 15, - destBytesOverhead: 394, - isEnabled: true - }); - - vm.expectEmit(); - emit FeeQuoter.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig - ); - vm.expectEmit(); - emit FeeQuoter.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig - ); - - FeeQuoter.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = - new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0); - s_feeQuoter.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); - - FeeQuoter.TokenTransferFeeConfig memory config0 = s_feeQuoter.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - FeeQuoter.TokenTransferFeeConfig memory config1 = s_feeQuoter.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 - ); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - - // Remove only the first token and validate only the first token is removed - tokensToRemove = new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](1); - tokensToRemove[0] = FeeQuoter.TokenTransferFeeConfigRemoveArgs({ - destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, - token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - }); - - vm.expectEmit(); - emit FeeQuoter.TokenTransferFeeConfigDeleted( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - - s_feeQuoter.applyTokenTransferFeeConfigUpdates(new FeeQuoter.TokenTransferFeeConfigArgs[](0), tokensToRemove); - - config0 = s_feeQuoter.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - config1 = s_feeQuoter.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - FeeQuoter.TokenTransferFeeConfig memory emptyConfig; - - _assertTokenTransferFeeConfigEqual(emptyConfig, config0); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - } - - function test_ApplyTokenTransferFeeZeroInput() public { - vm.recordLogs(); - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - new FeeQuoter.TokenTransferFeeConfigArgs[](0), new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; - - vm.expectRevert("Only callable by owner"); - - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - } - - function test_InvalidDestBytesOverhead_Revert() public { - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), - isEnabled: true - }); - - vm.expectRevert( - abi.encodeWithSelector( - FeeQuoter.InvalidDestBytesOverhead.selector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead - ) - ); - - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - } -} - -contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_NoTokenTransferChargesZeroFee_Success() public view { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(0, feeUSDWei); - assertEq(0, destGasOverhead); - assertEq(0, destBytesOverhead); - } - - function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); - - // Get config to assert it isn't set - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - assertFalse(transferFeeConfig.isEnabled); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // Assert that the default values are used - assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); - assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); - assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); - } - - function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(_configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_FeeTokenBpsFee_Success() public view { - uint256 tokenAmount = 10000e18; - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = _calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); - uint256 bpsUSDWei = _applyBpsRatio( - usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps - ); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_CustomTokenBpsFee_Success() public view { - uint256 tokenAmount = 200000e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); - - FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = _calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); - uint256 bpsUSDWei = _applyBpsRatio( - usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps - ); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroFeeConfigChargesMinFee_Success() public { - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - isEnabled: true - }); - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // if token charges 0 bps, it should cost minFee to transfer - assertEq( - _configUSDCentToWei( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents - ), - feeUSDWei - ); - assertEq(0, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { - // It shouldn't be possible to pay materially lower fees by splitting up the transfers. - // Note it is possible to pay higher fees since the minimum fees are added. - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); - // Cap amount to avoid overflow - amount = bound(amount, 0, 1e36); - Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); - for (uint256 i = 0; i < transfers; ++i) { - multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); - } - Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); - single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); - - address feeToken = s_sourceRouter.getWrappedNative(); - - (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); - (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); - - // Note that there can be a rounding error once per split. - assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); - assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); - assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); - } - - function test_MixedTokenTransferFee_Success() public view { - address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; - uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; - FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) - ]; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](3), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - uint256 expectedTotalGas = 0; - uint256 expectedTotalBytes = 0; - - // Start with small token transfers, total bps fee is lower than min token transfer fee - for (uint256 i = 0; i < testTokens.length; ++i) { - message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); - FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]); - - expectedTotalGas += tokenTransferFeeConfig.destGasOverhead == 0 - ? DEFAULT_TOKEN_DEST_GAS_OVERHEAD - : tokenTransferFeeConfig.destGasOverhead; - expectedTotalBytes += tokenTransferFeeConfig.destBytesOverhead == 0 - ? DEFAULT_TOKEN_BYTES_OVERHEAD - : tokenTransferFeeConfig.destBytesOverhead; - } - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - - uint256 expectedFeeUSDWei = 0; - for (uint256 i = 0; i < testTokens.length; ++i) { - expectedFeeUSDWei += _configUSDCentToWei( - tokenTransferFeeConfigs[i].minFeeUSDCents == 0 - ? DEFAULT_TOKEN_FEE_USD_CENTS - : tokenTransferFeeConfigs[i].minFeeUSDCents - ); - } - - assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 1"); - assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 1"); - assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 1"); - - // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee - message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); - - uint256 token0USDWei = _applyBpsRatio( - _calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - uint256 token1USDWei = _configUSDCentToWei(DEFAULT_TOKEN_FEE_USD_CENTS); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 2"); - assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 2"); - assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 2"); - - // Set 2nd token transfer to a large amount that is higher than maxFeeUSD - message.tokenAmounts[2] = Client.EVMTokenAmount({token: testTokens[2], amount: 1e36}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].maxFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 3"); - assertEq(expectedTotalGas, destGasOverhead, "wrong destGasOverhead 3"); - assertEq(expectedTotalBytes, destBytesOverhead, "wrong destBytesOverhead 3"); - } -} - -contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_ZeroDataAvailabilityMultiplier_Success() public { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - destChainConfigArgs[0] = - FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); - - uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; - assertEq(totalPriceInFeeToken, feeAmount); - } - - function test_HighGasMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = MAX_GAS_LIMIT; - uint256 customDataSize = MAX_DATA_SIZE; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: new bytes(customDataSize), - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - - uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - - uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - uint32 destBytesOverhead = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; - uint32 tokenBytesOverhead = - destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - - uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD - + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken)); - uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_MessageWithDataAndTokenTransfer_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = 1_000_000; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](2), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); - FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount - message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount - message.data = "random bits and bytes that should be factored into the cost of the message"; - - uint32 tokenGasOverhead = 0; - uint32 tokenBytesOverhead = 0; - for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { - tokenGasOverhead += - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; - uint32 destBytesOverhead = - s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destBytesOverhead; - tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - } - - uint256 gasUsed = - customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message)); - } - } - - function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { - // Update config to enforce allowOutOfOrderExecution = defaultVal. - vm.stopPrank(); - vm.startPrank(OWNER); - - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) - ); - - // If enforcement is on, only true should be allowed. - if (enforce && !allowOutOfOrderExecution) { - vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - } - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - // Reverts - - function test_DestinationChainNotEnabled_Revert() public { - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); - } - - function test_EnforceOutOfOrder_Revert() public { - // Update config to enforce allowOutOfOrderExecution = true. - vm.stopPrank(); - vm.startPrank(OWNER); - - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - vm.stopPrank(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Empty extraArgs to should revert since it enforceOutOfOrder is true. - message.extraArgs = ""; - - vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); - - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(FeeQuoter.UnsupportedNumberOfTokens.selector); - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageGasLimitTooHigh.selector)); - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_NotAFeeToken_Revert() public { - address notAFeeToken = address(0x111111); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); - message.feeToken = notAFeeToken; - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, notAFeeToken)); - - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } - - function test_InvalidEVMAddress_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(type(uint208).max); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { - using USDPriceWith18Decimals for uint224; - - function setUp() public virtual override { - super.setUp(); - } - - function test_processMessageArgs_WithLinkTokenAmount_Success() public view { - ( - uint256 msgFeeJuels, - /* bool isOutOfOrderExecution */ - , - /* bytes memory convertedExtraArgs */ - , - /* destExecDataPerToken */ - ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - // LINK - s_sourceTokens[0], - MAX_MSG_FEES_JUELS, - "", - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - - assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); - } - - function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { - address feeToken = s_sourceTokens[1]; - uint256 feeTokenAmount = 10_000 gwei; - uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); - - ( - uint256 msgFeeJuels, - /* bool isOutOfOrderExecution */ - , - /* bytes memory convertedExtraArgs */ - , - /* destExecDataPerToken */ - ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - feeToken, - feeTokenAmount, - "", - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - - assertEq(msgFeeJuels, expectedConvertedAmount); - } - - function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - /* destExecDataPerToken */ - ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - "", - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - - assertEq(isOutOfOrderExecution, false); - assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); - } - - function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { - bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); - - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - /* destExecDataPerToken */ - ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - extraArgs, - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - - assertEq(isOutOfOrderExecution, false); - assertEq( - convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) - ); - } - - function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { - bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); - - ( - /* uint256 msgFeeJuels */ - , - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - /* destExecDataPerToken */ - ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - extraArgs, - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - - assertEq(isOutOfOrderExecution, true); - assertEq( - convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) - ); - } - - // Reverts - - function test_processMessageArgs_MessageFeeTooHigh_Revert() public { - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) - ); - - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - MAX_MSG_FEES_JUELS + 1, - "", - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - } - - function test_processMessageArgs_InvalidExtraArgs_Revert() public { - vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - "abcde", - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - } - - function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { - // abi.decode error - vm.expectRevert(); - - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - 0, - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})), - new Internal.EVM2AnyTokenTransfer[](0), - new Client.EVMTokenAmount[](0) - ); - } - - function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - sourceTokenAmounts[1].amount = 1e18; - sourceTokenAmounts[1].token = CUSTOM_TOKEN_2; - - Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](2); - tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - tokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - bytes[] memory expectedDestExecData = new bytes[](2); - expectedDestExecData[0] = abi.encode( - s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead - ); - expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false - - // No revert - successful - ( /* msgFeeJuels */ , /* isOutOfOrderExecution */, /* convertedExtraArgs */, bytes[] memory destExecData) = - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - - for (uint256 i = 0; i < destExecData.length; ++i) { - assertEq(destExecData[i], expectedDestExecData[i]); - } - } - - function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - - Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); - tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - - // Revert due to index out of bounds access - vm.expectRevert(); - - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, - s_sourceTokens[0], - MAX_MSG_FEES_JUELS, - "", - new Internal.EVM2AnyTokenTransfer[](1), - new Client.EVMTokenAmount[](0) - ); - } - - function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { - address sourceETH = s_sourceTokens[1]; - - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1000; - sourceTokenAmounts[0].token = sourceETH; - - Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); - tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - - // No data set, should succeed - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - - // Set max data length, should succeed - tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - - // Set data to max length +1, should revert - tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - - // Set token config to allow larger data - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, - isEnabled: true - }); - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - - // Set the token data larger than the configured token data, should revert - tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - } - - function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { - bytes memory nonEvmAddress = abi.encode(type(uint208).max); - - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); - sourceTokenAmounts[0].amount = 1e18; - sourceTokenAmounts[0].token = s_sourceTokens[0]; - - Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); - tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - tokenAmounts[0].destTokenAddress = nonEvmAddress; - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts - ); - } -} - -contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { - function test_ValidEVMAddress_Success() public view { - bytes memory encodedAddress = abi.encode(address(10000)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); - } - - function test_ValidNonEVMAddress_Success() public view { - s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); - } - - // Reverts - - function test_InvalidEVMAddress_Revert() public { - bytes memory invalidAddress = abi.encode(type(uint208).max); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - function test_InvalidEVMAddressEncodePacked_Revert() public { - bytes memory invalidAddress = abi.encodePacked(address(234)); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - function test_InvalidEVMAddressPrecompiles_Revert() public { - for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { - bytes memory invalidAddress = abi.encode(address(i)); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } - - s_feeQuoter.validateDestFamilyAddress( - Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) - ); - } -} - -contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { - FeeQuoter.DestChainConfig private s_destChainConfig; - - function setUp() public virtual override { - super.setUp(); - s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; - } - - function test_EVMExtraArgsV1_Success() public view { - Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - Client.EVMExtraArgsV2 memory expectedOutputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); - - vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), - abi.encode(expectedOutputArgs) - ); - } - - function test_EVMExtraArgsV2_Success() public view { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) - ); - } - - function test_EVMExtraArgsDefault_Success() public view { - Client.EVMExtraArgsV2 memory expectedOutputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); - - vm.assertEq( - abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) - ); - } - - // Reverts - - function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - // Invalidate selector - inputExtraArgs[0] = bytes1(uint8(0)); - - vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } - - function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - s_destChainConfig.enforceOutOfOrder = true; - - vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } - - function test_EVMExtraArgsGasLimitTooHigh_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.expectRevert(FeeQuoter.MessageGasLimitTooHigh.selector); - s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); - } -} - -contract FeeQuoter_KeystoneSetup is FeeQuoterSetup { - address internal constant FORWARDER_1 = address(0x1); - address internal constant WORKFLOW_OWNER_1 = address(0x3); - bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; - bytes2 internal constant REPORT_NAME_1 = "01"; - address internal onReportTestToken1; - address internal onReportTestToken2; - - function setUp() public virtual override { - super.setUp(); - onReportTestToken1 = s_sourceTokens[0]; - onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); - - KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); - permissions[0] = KeystoneFeedsPermissionHandler.Permission({ - forwarder: FORWARDER_1, - workflowOwner: WORKFLOW_OWNER_1, - workflowName: WORKFLOW_NAME_1, - reportName: REPORT_NAME_1, - isAllowed: true - }); - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); - tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ - sourceToken: onReportTestToken1, - feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) - }); - tokenPriceFeeds[1] = FeeQuoter.TokenPriceFeedUpdate({ - sourceToken: onReportTestToken2, - feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) - }); - s_feeQuoter.setReportPermissions(permissions); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); - } -} - -contract FeeQuoter_onReport is FeeQuoter_KeystoneSetup { - function test_onReport_Success() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); - report[1] = - FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); - - uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); - uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, report[1].price); - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredToken1Price, block.timestamp); - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken2, expectedStoredToken2Price, block.timestamp); - - changePrank(FORWARDER_1); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - - vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); - vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).timestamp, report[0].timestamp); - - vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).value, expectedStoredToken2Price); - vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); - } - - function test_onReport_InvalidForwarder_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); - - vm.expectRevert( - abi.encodeWithSelector( - KeystoneFeedsPermissionHandler.ReportForwarderUnauthorized.selector, - STRANGER, - WORKFLOW_OWNER_1, - WORKFLOW_NAME_1, - REPORT_NAME_1 - ) - ); - changePrank(STRANGER); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - } - - function test_onReport_UnsupportedToken_Reverts() public { - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - changePrank(FORWARDER_1); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - } - - function test_OnReport_StaleUpdate_Revert() public { - //Creating a correct report - bytes memory encodedPermissionsMetadata = - abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - - FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); - - uint224 expectedStoredTokenPrice = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredTokenPrice, block.timestamp); - - changePrank(FORWARDER_1); - //setting the correct price and time with the correct report - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - - //create a stale report - report[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp - 1)}); - //expecting a revert - vm.expectRevert( - abi.encodeWithSelector( - FeeQuoter.StaleKeystoneUpdate.selector, onReportTestToken1, block.timestamp - 1, block.timestamp - ) - ); - s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol deleted file mode 100644 index 056c749..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ /dev/null @@ -1,442 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; - -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {FeeQuoter} from "../../FeeQuoter.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; -import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; - -contract FeeQuoterSetup is TokenSetup { - uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei - uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei - - address internal constant CUSTOM_TOKEN = address(12345); - address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); - - uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM - uint224 internal constant CUSTOM_TOKEN_PRICE_2 = 1e18; // $1 CUSTOM - - // Encode L1 gas price and L2 gas price into a packed price. - // L1 gas price is left-shifted to the higher-order bits. - uint224 internal constant PACKED_USD_PER_GAS = - (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; - - FeeQuoterHelper internal s_feeQuoter; - // Cheat to store the price updates in storage since struct arrays aren't supported. - bytes internal s_encodedInitialPriceUpdates; - address internal s_weth; - - address[] internal s_sourceFeeTokens; - uint224[] internal s_sourceTokenPrices; - address[] internal s_destFeeTokens; - uint224[] internal s_destTokenPrices; - - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] internal s_feeQuoterPremiumMultiplierWeiPerEthArgs; - FeeQuoter.TokenTransferFeeConfigArgs[] internal s_feeQuoterTokenTransferFeeConfigArgs; - - mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; - - function setUp() public virtual override { - TokenSetup.setUp(); - - _deployTokenPriceDataFeed(s_sourceFeeToken, 8, 1e8); - - s_weth = s_sourceRouter.getWrappedNative(); - _deployTokenPriceDataFeed(s_weth, 8, 1e11); - - address[] memory sourceFeeTokens = new address[](3); - sourceFeeTokens[0] = s_sourceTokens[0]; - sourceFeeTokens[1] = s_sourceTokens[1]; - sourceFeeTokens[2] = s_sourceRouter.getWrappedNative(); - s_sourceFeeTokens = sourceFeeTokens; - - uint224[] memory sourceTokenPrices = new uint224[](3); - sourceTokenPrices[0] = 5e18; - sourceTokenPrices[1] = 2000e18; - sourceTokenPrices[2] = 2000e18; - s_sourceTokenPrices = sourceTokenPrices; - - address[] memory destFeeTokens = new address[](3); - destFeeTokens[0] = s_destTokens[0]; - destFeeTokens[1] = s_destTokens[1]; - destFeeTokens[2] = s_destRouter.getWrappedNative(); - s_destFeeTokens = destFeeTokens; - - uint224[] memory destTokenPrices = new uint224[](3); - destTokenPrices[0] = 5e18; - destTokenPrices[1] = 2000e18; - destTokenPrices[2] = 2000e18; - s_destTokenPrices = destTokenPrices; - - uint256 sourceTokenCount = sourceFeeTokens.length; - uint256 destTokenCount = destFeeTokens.length; - address[] memory pricedTokens = new address[](sourceTokenCount + destTokenCount); - uint224[] memory tokenPrices = new uint224[](sourceTokenCount + destTokenCount); - for (uint256 i = 0; i < sourceTokenCount; ++i) { - pricedTokens[i] = sourceFeeTokens[i]; - tokenPrices[i] = sourceTokenPrices[i]; - } - for (uint256 i = 0; i < destTokenCount; ++i) { - pricedTokens[i + sourceTokenCount] = destFeeTokens[i]; - tokenPrices[i + sourceTokenCount] = destTokenPrices[i]; - } - - Internal.PriceUpdates memory priceUpdates = _getPriceUpdatesStruct(pricedTokens, tokenPrices); - priceUpdates.gasPriceUpdates = new Internal.GasPriceUpdate[](1); - priceUpdates.gasPriceUpdates[0] = - Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: PACKED_USD_PER_GAS}); - - s_encodedInitialPriceUpdates = abi.encode(priceUpdates); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = OWNER; - address[] memory feeTokens = new address[](2); - feeTokens[0] = s_sourceTokens[0]; - feeTokens[1] = s_weth; - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); - - s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( - FeeQuoter.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceFeeToken, - premiumMultiplierWeiPerEth: 5e17 // 0.5x - }) - ); - s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( - FeeQuoter.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceRouter.getWrappedNative(), - premiumMultiplierWeiPerEth: 2e18 // 2x - }) - ); - - s_feeQuoterTokenTransferFeeConfigArgs.push(); - s_feeQuoterTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ - token: s_sourceFeeToken, - tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 1_00, // 1 USD - maxFeeUSDCents: 1000_00, // 1,000 USD - deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 100_000, - destBytesOverhead: 32, - isEnabled: true - }) - }) - ); - s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ - token: CUSTOM_TOKEN, - tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 2_00, // 1 USD - maxFeeUSDCents: 2000_00, // 1,000 USD - deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 95_000, - destBytesOverhead: 200, - isEnabled: true - }) - }) - ); - s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ - token: CUSTOM_TOKEN_2, - tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 2_00, // 1 USD - maxFeeUSDCents: 2000_00, // 1,000 USD - deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 1, - destBytesOverhead: 200, - isEnabled: false - }) - }) - ); - - //setting up the destination token for CUSTOM_TOKEN_2 here as it is specific to these tests - s_destTokenBySourceToken[CUSTOM_TOKEN_2] = address(bytes20(keccak256("CUSTOM_TOKEN_2_DEST"))); - - s_feeQuoter = new FeeQuoterHelper( - FeeQuoter.StaticConfig({ - linkToken: s_sourceTokens[0], - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, - stalenessThreshold: uint32(TWELVE_HOURS) - }), - priceUpdaters, - feeTokens, - tokenPriceFeedUpdates, - s_feeQuoterTokenTransferFeeConfigArgs, - s_feeQuoterPremiumMultiplierWeiPerEthArgs, - _generateFeeQuoterDestChainConfigArgs() - ); - s_feeQuoter.updatePrices(priceUpdates); - } - - function _deployTokenPriceDataFeed(address token, uint8 decimals, int256 initialAnswer) internal returns (address) { - MockV3Aggregator dataFeed = new MockV3Aggregator(decimals, initialAnswer); - s_dataFeedByToken[token] = address(dataFeed); - return address(dataFeed); - } - - function _getPriceUpdatesStruct( - address[] memory tokens, - uint224[] memory prices - ) internal pure returns (Internal.PriceUpdates memory) { - uint256 length = tokens.length; - - Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](length); - for (uint256 i = 0; i < length; ++i) { - tokenPriceUpdates[i] = Internal.TokenPriceUpdate({sourceToken: tokens[i], usdPerToken: prices[i]}); - } - Internal.PriceUpdates memory priceUpdates = - Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: new Internal.GasPriceUpdate[](0)}); - - return priceUpdates; - } - - function _getEmptyPriceUpdates() internal pure returns (Internal.PriceUpdates memory priceUpdates) { - return Internal.PriceUpdates({ - tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), - gasPriceUpdates: new Internal.GasPriceUpdate[](0) - }); - } - - function _getSingleTokenPriceFeedUpdateStruct( - address sourceToken, - address dataFeedAddress, - uint8 tokenDecimals - ) internal pure returns (FeeQuoter.TokenPriceFeedUpdate memory) { - return FeeQuoter.TokenPriceFeedUpdate({ - sourceToken: sourceToken, - feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) - }); - } - - function _initialiseSingleTokenPriceFeed() internal returns (address) { - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); - tokenPriceFeedUpdates[0] = - _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - return s_sourceTokens[0]; - } - - function _generateTokenTransferFeeConfigArgs( - uint256 destChainSelectorLength, - uint256 tokenLength - ) internal pure returns (FeeQuoter.TokenTransferFeeConfigArgs[] memory) { - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new FeeQuoter.TokenTransferFeeConfigArgs[](destChainSelectorLength); - for (uint256 i = 0; i < destChainSelectorLength; ++i) { - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = - new FeeQuoter.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); - } - return tokenTransferFeeConfigArgs; - } - - function _generateFeeQuoterDestChainConfigArgs() internal pure returns (FeeQuoter.DestChainConfigArgs[] memory) { - FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); - destChainConfigs[0] = FeeQuoter.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - destChainConfig: FeeQuoter.DestChainConfig({ - isEnabled: true, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - maxDataBytes: MAX_DATA_SIZE, - maxPerMsgGasLimit: MAX_GAS_LIMIT, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTxGasLimit: GAS_LIMIT, - gasMultiplierWeiPerEth: 5e17, - networkFeeUSDCents: 1_00, - enforceOutOfOrder: false, - chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM - }) - }); - return destChainConfigs; - } - - function _assertTokenPriceFeedConfigEquality( - FeeQuoter.TokenPriceFeedConfig memory config1, - FeeQuoter.TokenPriceFeedConfig memory config2 - ) internal pure virtual { - assertEq(config1.dataFeedAddress, config2.dataFeedAddress); - assertEq(config1.tokenDecimals, config2.tokenDecimals); - } - - function _assertTokenPriceFeedConfigUnconfigured( - FeeQuoter.TokenPriceFeedConfig memory config - ) internal pure virtual { - _assertTokenPriceFeedConfigEquality( - config, FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) - ); - } - - function _assertTokenTransferFeeConfigEqual( - FeeQuoter.TokenTransferFeeConfig memory a, - FeeQuoter.TokenTransferFeeConfig memory b - ) internal pure { - assertEq(a.minFeeUSDCents, b.minFeeUSDCents); - assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); - assertEq(a.deciBps, b.deciBps); - assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destBytesOverhead, b.destBytesOverhead); - assertEq(a.isEnabled, b.isEnabled); - } - - function _assertFeeQuoterStaticConfigsEqual( - FeeQuoter.StaticConfig memory a, - FeeQuoter.StaticConfig memory b - ) internal pure { - assertEq(a.linkToken, b.linkToken); - assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); - } - - function _assertFeeQuoterDestChainConfigsEqual( - FeeQuoter.DestChainConfig memory a, - FeeQuoter.DestChainConfig memory b - ) internal pure { - assertEq(a.isEnabled, b.isEnabled); - assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); - assertEq(a.maxDataBytes, b.maxDataBytes); - assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); - assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); - assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); - assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); - assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); - assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); - assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); - assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); - } -} - -contract FeeQuoterFeeSetup is FeeQuoterSetup { - uint224 internal s_feeTokenPrice; - uint224 internal s_wrappedTokenPrice; - uint224 internal s_customTokenPrice; - - address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); - - address internal s_destTokenPool = makeAddr("destTokenPool"); - address internal s_destToken = makeAddr("destToken"); - - function setUp() public virtual override { - super.setUp(); - - s_feeTokenPrice = s_sourceTokenPrices[0]; - s_wrappedTokenPrice = s_sourceTokenPrices[2]; - s_customTokenPrice = CUSTOM_TOKEN_PRICE; - - s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); - } - - function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateSingleTokenMessage( - address token, - uint256 amount - ) public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 sourceChainSelector, - uint64 destChainSelector, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - uint256 feeValueJuels, - address originalSender, - bytes32 metadataHash, - TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.EVM2AnyRampMessage memory) { - Client.EVMExtraArgsV2 memory extraArgs = - s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); - - Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ - header: Internal.RampMessageHeader({ - messageId: "", - sourceChainSelector: sourceChainSelector, - destChainSelector: destChainSelector, - sequenceNumber: seqNum, - nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce - }), - sender: originalSender, - data: message.data, - receiver: message.receiver, - extraArgs: Client._argsToBytes(extraArgs), - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - feeValueJuels: feeValueJuels, - tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) - }); - - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - messageEvent.tokenAmounts[i] = - _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry, DEST_CHAIN_SELECTOR); - } - - messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); - return messageEvent; - } - - function _getSourceTokenData( - Client.EVMTokenAmount memory tokenAmount, - TokenAdminRegistry tokenAdminRegistry, - uint64 destChainSelector - ) internal view returns (Internal.EVM2AnyTokenTransfer memory) { - address destToken = s_destTokenBySourceToken[tokenAmount.token]; - - uint32 expectedDestGasAmount; - FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = - FeeQuoter(s_feeQuoter).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); - expectedDestGasAmount = - tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; - - return Internal.EVM2AnyTokenTransfer({ - sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, - destTokenAddress: abi.encode(destToken), - extraData: "", - amount: tokenAmount.amount, - destExecData: abi.encode(expectedDestGasAmount) - }); - } - - function _calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { - return (tokenPrice * tokenAmount) / 1e18; - } - - function _applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { - return (tokenAmount * ratio) / 1e5; - } - - function _configUSDCentToWei( - uint256 usdCent - ) internal pure returns (uint256) { - return usdCent * 1e16; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol deleted file mode 100644 index c3f95a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; - -contract BurnMintERC677Helper is BurnMintERC677, IGetCCIPAdmin { - constructor(string memory name, string memory symbol) BurnMintERC677(name, symbol, 18, 0) {} - - // Gives one full token to any given address. - function drip( - address to - ) external { - _mint(to, 1e18); - } - - function getCCIPAdmin() external view override returns (address) { - return owner(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol deleted file mode 100644 index bb1d4c9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../../libraries/Pool.sol"; -import {MultiTokenPool} from "./MultiTokenPool.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnMintMultiTokenPool is MultiTokenPool { - constructor( - IERC20[] memory tokens, - address[] memory allowlist, - address rmnProxy, - address router - ) MultiTokenPool(tokens, allowlist, rmnProxy, router) {} - - /// @notice Burn the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - IBurnMintERC20(lockOrBurnIn.localToken).burn(lockOrBurnIn.amount); - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.localToken, lockOrBurnIn.remoteChainSelector), - destPoolData: "" - }); - } - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - // Mint to the receiver - IBurnMintERC20(releaseOrMintIn.localToken).mint(msg.sender, releaseOrMintIn.amount); - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol deleted file mode 100644 index 0bc97c7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {CCIPHome} from "../../capability/CCIPHome.sol"; - -contract CCIPHomeHelper is CCIPHome { - constructor( - address capabilitiesRegistry - ) CCIPHome(capabilitiesRegistry) {} - - function validateConfig( - OCR3Config memory cfg - ) external view { - return _validateConfig(cfg); - } - - function ensureInRegistry( - bytes32[] memory p2pIds - ) external view { - return _ensureInRegistry(p2pIds); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol deleted file mode 100644 index 617d39a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; - -contract ERC20RebasingHelper is ERC20 { - uint16 public s_multiplierPercentage = 100; - bool public s_mintShouldBurn = false; - - constructor() ERC20("Rebasing", "REB") {} - - function mint(address to, uint256 amount) external { - if (!s_mintShouldBurn) { - _mint(to, amount * s_multiplierPercentage / 100); - return; - } - _burn(to, amount * s_multiplierPercentage / 100); - } - - function setMultiplierPercentage( - uint16 multiplierPercentage - ) external { - s_multiplierPercentage = multiplierPercentage; - } - - function setMintShouldBurn( - bool mintShouldBurn - ) external { - s_mintShouldBurn = mintShouldBurn; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol deleted file mode 100644 index 9f4ca68..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -contract EVM2EVMOffRampHelper { - uint64 public s_nonce; - mapping(address sender => uint64 nonce) public s_nonces; - - function execute( - address[] memory senders - ) external { - for (uint256 i; i < senders.length; i++) { - s_nonces[senders[i]]++; - } - } - - function metadataHash() external pure returns (bytes32) { - return 0x0; - } - - function getSenderNonce( - address sender - ) external view returns (uint64 nonce) { - return s_nonces[sender]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol deleted file mode 100644 index e357645..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {EtherSenderReceiver} from "../../applications/EtherSenderReceiver.sol"; -import {Client} from "../../libraries/Client.sol"; - -contract EtherSenderReceiverHelper is EtherSenderReceiver { - constructor( - address router - ) EtherSenderReceiver(router) {} - - function validatedMessage( - Client.EVM2AnyMessage calldata message - ) public view returns (Client.EVM2AnyMessage memory) { - return _validatedMessage(message); - } - - function validateFeeToken( - Client.EVM2AnyMessage calldata message - ) public payable { - _validateFeeToken(message); - } - - function publicCcipReceive( - Client.Any2EVMMessage memory message - ) public { - _ccipReceive(message); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol deleted file mode 100644 index e392ba0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {FeeQuoter} from "../../FeeQuoter.sol"; -import {Client} from "../../libraries/Client.sol"; - -contract FeeQuoterHelper is FeeQuoter { - constructor( - StaticConfig memory staticConfig, - address[] memory priceUpdaters, - address[] memory feeTokens, - TokenPriceFeedUpdate[] memory tokenPriceFeeds, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, - DestChainConfigArgs[] memory destChainConfigArgs - ) - FeeQuoter( - staticConfig, - priceUpdaters, - feeTokens, - tokenPriceFeeds, - tokenTransferFeeConfigArgs, - premiumMultiplierWeiPerEthArgs, - destChainConfigArgs - ) - {} - - function getDataAvailabilityCost( - uint64 destChainSelector, - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) external view returns (uint256) { - return _getDataAvailabilityCost( - s_destChainConfigs[destChainSelector], - dataAvailabilityGasPrice, - messageDataLength, - numberOfTokens, - tokenTransferBytesOverhead - ); - } - - function getTokenTransferCost( - uint64 destChainSelector, - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) external view returns (uint256, uint32, uint32) { - return _getTokenTransferCost( - s_destChainConfigs[destChainSelector], destChainSelector, feeToken, feeTokenPrice, tokenAmounts - ); - } - - function parseEVMExtraArgsFromBytes( - bytes calldata extraArgs, - uint64 destChainSelector - ) external view returns (Client.EVMExtraArgsV2 memory) { - return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfigs[destChainSelector]); - } - - function parseEVMExtraArgsFromBytes( - bytes calldata extraArgs, - DestChainConfig memory destChainConfig - ) external pure returns (Client.EVMExtraArgsV2 memory) { - return _parseEVMExtraArgsFromBytes(extraArgs, destChainConfig); - } - - function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { - _validateDestFamilyAddress(chainFamilySelector, destAddress); - } - - function calculateRebasedValue( - uint8 dataFeedDecimal, - uint8 tokenDecimal, - uint256 feedValue - ) external pure returns (uint224) { - return _calculateRebasedValue(dataFeedDecimal, tokenDecimal, feedValue); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol deleted file mode 100644 index b301240..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -contract IgnoreContractSize { - // test contracts are excluded from forge build --sizes by default - // --sizes exits with code 1 if any contract is over limit, which fails CI - // for helper contracts that are not explicit test contracts - // use this flag to exclude from --sizes - bool public IS_SCRIPT = true; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol deleted file mode 100644 index 23e13aa..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../../libraries/Pool.sol"; -import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; - -contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { - bytes public s_revertReason = ""; - bytes public s_sourceTokenData = ""; - uint256 public s_releaseOrMintMultiplier = 1; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} - - function setShouldRevert( - bytes calldata revertReason - ) external { - s_revertReason = revertReason; - } - - function setSourceTokenData( - bytes calldata sourceTokenData - ) external { - s_sourceTokenData = sourceTokenData; - } - - function setReleaseOrMintMultiplier( - uint256 multiplier - ) external { - s_releaseOrMintMultiplier = multiplier; - } - - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - bytes memory revertReason = s_revertReason; - if (revertReason.length != 0) { - assembly { - revert(add(32, revertReason), mload(revertReason)) - } - } - - IBurnMintERC20(address(i_token)).burn(lockOrBurnIn.amount); - emit Burned(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: s_sourceTokenData - }); - } - - /// @notice Reverts depending on the value of `s_revertReason` - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - bytes memory revertReason = s_revertReason; - if (revertReason.length != 0) { - assembly { - revert(add(32, revertReason), mload(revertReason)) - } - } - uint256 amount = releaseOrMintIn.amount * s_releaseOrMintMultiplier; - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, amount); - - emit Minted(msg.sender, releaseOrMintIn.receiver, amount); - return Pool.ReleaseOrMintOutV1({destinationAmount: amount}); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol deleted file mode 100644 index 3893d08..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; - -library MerkleHelper { - /// @notice Generate a Merkle Root from a full set of leaves. When a tree is unbalanced - /// the value is brought up in the tree. For example consider (a,b,c) as leaves. This would - /// result in the following tree with d being computed from hash(a,c) and the root r from - /// hash(d,c). Notice c is not being rehashed when it is brought up in the tree, so the - /// root is NOT hash(d,hash(c)) but instead hash(d,c) == hash(hash(a,b),c). - /// r - /// / \ - /// d c - /// / \ - /// a b - function getMerkleRoot( - bytes32[] memory hashedLeaves - ) public pure returns (bytes32) { - // solhint-disable-next-line reason-string,gas-custom-errors - require(hashedLeaves.length <= 256); - while (hashedLeaves.length > 1) { - hashedLeaves = computeNextLayer(hashedLeaves); - } - return hashedLeaves[0]; - } - - /// @notice Computes a single layer of a merkle proof by hashing each pair (i, i+1) for - /// each i, i+2, i+4.. n. When an uneven number of leaves is supplied the last item - /// is simply included as the last element in the result set and not hashed. - function computeNextLayer( - bytes32[] memory layer - ) public pure returns (bytes32[] memory) { - uint256 leavesLen = layer.length; - if (leavesLen == 1) return layer; - - unchecked { - bytes32[] memory nextLayer = new bytes32[]((leavesLen + 1) / 2); - for (uint256 i = 0; i < leavesLen; i += 2) { - if (i == leavesLen - 1) { - nextLayer[i / 2] = layer[i]; - } else { - nextLayer[i / 2] = hashPair(layer[i], layer[i + 1]); - } - } - return nextLayer; - } - } - - function hashPair(bytes32 a, bytes32 b) public pure returns (bytes32) { - return a < b ? hashInternalNode(a, b) : hashInternalNode(b, a); - } - - function hashInternalNode(bytes32 left, bytes32 right) public pure returns (bytes32 hash) { - return keccak256(abi.encode(MerkleMultiProof.INTERNAL_DOMAIN_SEPARATOR, left, right)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol deleted file mode 100644 index 68d6dc4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.4; - -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; - -/// @notice MessageHasher is a contract that utility functions to hash an Any2EVMRampMessage -/// and encode various preimages for the final hash of the message. -/// @dev This is only deployed in tests and is not part of the production contracts. -contract MessageHasher { - function hash(Internal.Any2EVMRampMessage memory message, bytes memory onRamp) public pure returns (bytes32) { - return Internal._hash( - message, - keccak256( - abi.encode( - Internal.ANY_2_EVM_MESSAGE_HASH, - message.header.sourceChainSelector, - message.header.destChainSelector, - keccak256(onRamp) - ) - ) - ); - } - - function encodeAny2EVMTokenAmountsHashPreimage( - Internal.Any2EVMTokenTransfer[] memory tokenAmounts - ) public pure returns (bytes memory) { - return abi.encode(tokenAmounts); - } - - function encodeEVM2AnyTokenAmountsHashPreimage( - Internal.EVM2AnyTokenTransfer[] memory tokenAmount - ) public pure returns (bytes memory) { - return abi.encode(tokenAmount); - } - - function encodeMetadataHashPreimage( - bytes32 any2EVMMessageHash, - uint64 sourceChainSelector, - uint64 destChainSelector, - bytes32 onRampHash - ) public pure returns (bytes memory) { - return abi.encode(any2EVMMessageHash, sourceChainSelector, destChainSelector, onRampHash); - } - - function encodeFixedSizeFieldsHashPreimage( - bytes32 messageId, - address receiver, - uint64 sequenceNumber, - uint256 gasLimit, - uint64 nonce - ) public pure returns (bytes memory) { - return abi.encode(messageId, receiver, sequenceNumber, gasLimit, nonce); - } - - function encodeFinalHashPreimage( - bytes32 leafDomainSeparator, - bytes32 metaDataHash, - bytes32 fixedSizeFieldsHash, - bytes32 senderHash, - bytes32 dataHash, - bytes32 tokenAmountsHash - ) public pure returns (bytes memory) { - return abi.encode(leafDomainSeparator, metaDataHash, fixedSizeFieldsHash, senderHash, dataHash, tokenAmountsHash); - } - - function encodeEVMExtraArgsV1( - Client.EVMExtraArgsV1 memory extraArgs - ) public pure returns (bytes memory) { - return Client._argsToBytes(extraArgs); - } - - function encodeEVMExtraArgsV2( - Client.EVMExtraArgsV2 memory extraArgs - ) public pure returns (bytes memory) { - return Client._argsToBytes(extraArgs); - } - - function decodeEVMExtraArgsV1( - uint256 gasLimit - ) public pure returns (Client.EVMExtraArgsV1 memory) { - return Client.EVMExtraArgsV1(gasLimit); - } - - function decodeEVMExtraArgsV2( - uint256 gasLimit, - bool allowOutOfOrderExecution - ) public pure returns (Client.EVMExtraArgsV2 memory) { - return Client.EVMExtraArgsV2(gasLimit, allowOutOfOrderExecution); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol deleted file mode 100644 index 80cdf61..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {Client} from "../../libraries/Client.sol"; - -contract MessageInterceptorHelper is IMessageInterceptor { - mapping(bytes32 messageId => bool isInvalid) internal s_invalidMessageIds; - - constructor() {} - - function setMessageIdValidationState(bytes32 messageId, bool isInvalid) external { - s_invalidMessageIds[messageId] = isInvalid; - } - - /// @inheritdoc IMessageInterceptor - function onInboundMessage( - Client.Any2EVMMessage memory message - ) external view { - if (s_invalidMessageIds[message.messageId]) { - revert MessageValidationError(bytes("Invalid message")); - } - } - - /// @inheritdoc IMessageInterceptor - function onOutboundMessage(uint64, Client.EVM2AnyMessage calldata message) external view { - if (s_invalidMessageIds[keccak256(abi.encode(message))]) { - revert MessageValidationError(bytes("Invalid message")); - } - return; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol deleted file mode 100644 index 7c2e6cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; -import {Client} from "../../libraries/Client.sol"; - -contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { - constructor( - address feeQuoter, - address[] memory authorizedCallers - ) MultiAggregateRateLimiter(feeQuoter, authorizedCallers) {} - - function getTokenValue( - Client.EVMTokenAmount memory tokenAmount - ) public view returns (uint256) { - return _getTokenValue(tokenAmount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol deleted file mode 100644 index e760b79..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; - -contract MultiOCR3Helper is MultiOCR3Base { - event AfterConfigSet(uint8 ocrPluginType); - - /// @dev OCR plugin type used for transmit. - /// Defined in storage since it cannot be passed as calldata due to strict transmit checks - uint8 internal s_transmitOcrPluginType; - - function setTransmitOcrPluginType( - uint8 ocrPluginType - ) external { - s_transmitOcrPluginType = ocrPluginType; - } - - /// @dev transmit function with signatures - function transmitWithSignatures( - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs - ) external { - _transmit(s_transmitOcrPluginType, reportContext, report, rs, ss, rawVs); - } - - /// @dev transmit function with no signatures - function transmitWithoutSignatures(bytes32[3] calldata reportContext, bytes calldata report) external { - bytes32[] memory emptySigs = new bytes32[](0); - _transmit(s_transmitOcrPluginType, reportContext, report, emptySigs, emptySigs, bytes32("")); - } - - function getOracle(uint8 ocrPluginType, address oracleAddress) external view returns (Oracle memory) { - return s_oracles[ocrPluginType][oracleAddress]; - } - - function typeAndVersion() public pure override returns (string memory) { - return "MultiOCR3BaseHelper 1.0.0"; - } - - function _afterOCR3ConfigSet( - uint8 ocrPluginType - ) internal virtual override { - emit AfterConfigSet(ocrPluginType); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol deleted file mode 100644 index 316439b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol +++ /dev/null @@ -1,438 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; - -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice This contract is a proof of concept and should NOT be used in production. -abstract contract MultiTokenPool is IPoolV1, OwnerIsCreator { - using EnumerableSet for EnumerableSet.AddressSet; - using EnumerableSet for EnumerableSet.UintSet; - using RateLimiter for RateLimiter.TokenBucket; - - error CallerIsNotARampOnRouter(address caller); - error ZeroAddressNotAllowed(); - error SenderNotAllowed(address sender); - error AllowListNotEnabled(); - error NonExistentChain(uint64 remoteChainSelector); - error ChainNotAllowed(uint64 remoteChainSelector); - error CursedByRMN(); - error ChainAlreadyExists(uint64 chainSelector); - error InvalidSourcePoolAddress(bytes sourcePoolAddress); - error InvalidToken(address token); - - event Locked(address indexed sender, uint256 amount); - event Burned(address indexed sender, uint256 amount); - event Released(address indexed sender, address indexed recipient, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - event ChainAdded( - uint64 remoteChainSelector, - bytes remoteToken, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainConfigured( - uint64 remoteChainSelector, - RateLimiter.Config outboundRateLimiterConfig, - RateLimiter.Config inboundRateLimiterConfig - ); - event ChainRemoved(uint64 remoteChainSelector); - event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); - event AllowListAdd(address sender); - event AllowListRemove(address sender); - event RouterUpdated(address oldRouter, address newRouter); - - struct ChainUpdate { - uint64 remoteChainSelector; // ──╮ Remote chain selector - bool allowed; // ────────────────╯ Whether the chain is allowed - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. - RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - } - - struct RemoteChainConfig { - RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain - RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. - } - - /// @dev The IERC20 token that this pool supports - EnumerableSet.AddressSet internal s_tokens; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; - /// @dev The immutable flag that indicates if the pool is access-controlled. - bool internal immutable i_allowlistEnabled; - /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. - /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; - /// @dev The address of the router - IRouter internal s_router; - /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to - /// be able to quickly determine (without parsing logs) who can access the pool. - /// @dev The chain selectors are in uin256 format because of the EnumerableSet implementation. - EnumerableSet.UintSet internal s_remoteChainSelectors; - mapping(address token => mapping(uint64 remoteChainSelector => RemoteChainConfig)) internal s_remoteChainConfigs; - - constructor(IERC20[] memory token, address[] memory allowlist, address rmnProxy, address router) { - if (router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); - for (uint256 i = 0; i < token.length; ++i) { - s_tokens.add(address(token[i])); - } - i_rmnProxy = rmnProxy; - s_router = IRouter(router); - - // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. - i_allowlistEnabled = allowlist.length > 0; - if (i_allowlistEnabled) { - _applyAllowListUpdates(new address[](0), allowlist); - } - } - - /// @notice Get RMN proxy address - /// @return rmnProxy Address of RMN proxy - function getRmnProxy() public view returns (address rmnProxy) { - return i_rmnProxy; - } - - /// @inheritdoc IPoolV1 - function isSupportedToken( - address token - ) public view virtual returns (bool) { - return s_tokens.contains(token); - } - - /// @notice Gets the IERC20 token that this pool can lock or burn. - /// @return tokens The IERC20 token representation. - function getTokens() public view returns (IERC20[] memory tokens) { - tokens = new IERC20[](s_tokens.length()); - for (uint256 i = 0; i < s_tokens.length(); ++i) { - tokens[i] = IERC20(s_tokens.at(i)); - } - return tokens; - } - - /// @notice Gets the pool's Router - /// @return router The pool's Router - function getRouter() public view returns (address router) { - return address(s_router); - } - - /// @notice Sets the pool's Router - /// @param newRouter The new Router - function setRouter( - address newRouter - ) public onlyOwner { - if (newRouter == address(0)) revert ZeroAddressNotAllowed(); - address oldRouter = address(s_router); - s_router = IRouter(newRouter); - - emit RouterUpdated(oldRouter, newRouter); - } - - /// @notice Signals which version of the pool interface is supported - function supportsInterface( - bytes4 interfaceId - ) public pure virtual override returns (bool) { - return interfaceId == Pool.CCIP_POOL_V1 || interfaceId == type(IPoolV1).interfaceId - || interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // │ Validation │ - // ================================================================ - - /// @notice Validates the lock or burn input for correctness on - /// - token to be locked or burned - /// - RMN curse status - /// - allowlist status - /// - if the sender is a valid onRamp - /// - rate limit status - /// @param lockOrBurnIn The input to validate. - /// @dev This function should always be called before executing a lock or burn. Not doing so would allow - /// for various exploits. - function _validateLockOrBurn( - Pool.LockOrBurnInV1 memory lockOrBurnIn - ) internal { - if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); - _checkAllowList(lockOrBurnIn.originalSender); - - _onlyOnRamp(lockOrBurnIn.remoteChainSelector); - _consumeOutboundRateLimit(lockOrBurnIn.localToken, lockOrBurnIn.remoteChainSelector, lockOrBurnIn.amount); - } - - /// @notice Validates the release or mint input for correctness on - /// - token to be released or minted - /// - RMN curse status - /// - if the sender is a valid offRamp - /// - if the source pool is valid - /// - rate limit status - /// @param releaseOrMintIn The input to validate. - /// @dev This function should always be called before executing a lock or burn. Not doing so would allow - /// for various exploits. - function _validateReleaseOrMint( - Pool.ReleaseOrMintInV1 memory releaseOrMintIn - ) internal { - if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); - _onlyOffRamp(releaseOrMintIn.remoteChainSelector); - - // Validates that the source pool address is configured on this pool. - bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.localToken, releaseOrMintIn.remoteChainSelector); - if ( - configuredRemotePool.length == 0 - || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) - ) { - revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); - } - _consumeInboundRateLimit(releaseOrMintIn.localToken, releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); - } - - // ================================================================ - // │ Chain permissions │ - // ================================================================ - - /// @notice Gets the pool address on the remote chain. - /// @param remoteChainSelector Remote chain selector. - /// @dev To support non-evm chains, this value is encoded into bytes - function getRemotePool(address token, uint64 remoteChainSelector) public view returns (bytes memory) { - return s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress; - } - - /// @notice Gets the token address on the remote chain. - /// @param remoteChainSelector Remote chain selector. - /// @dev To support non-evm chains, this value is encoded into bytes - function getRemoteToken(address token, uint64 remoteChainSelector) public view returns (bytes memory) { - return s_remoteChainConfigs[token][remoteChainSelector].remoteTokenAddress; - } - - /// @notice Sets the remote pool address for a given chain selector. - /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. - /// @param remotePoolAddress The address of the remote pool. - function setRemotePool( - address token, - uint64 remoteChainSelector, - bytes calldata remotePoolAddress - ) external onlyOwner { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - - bytes memory prevAddress = s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress; - s_remoteChainConfigs[token][remoteChainSelector].remotePoolAddress = remotePoolAddress; - - emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); - } - - /// @inheritdoc IPoolV1 - function isSupportedChain( - uint64 remoteChainSelector - ) public view returns (bool) { - return s_remoteChainSelectors.contains(remoteChainSelector); - } - - /// @notice Get list of allowed chains - /// @return list of chains. - function getSupportedChains() public view returns (uint64[] memory) { - uint256[] memory uint256ChainSelectors = s_remoteChainSelectors.values(); - uint64[] memory chainSelectors = new uint64[](uint256ChainSelectors.length); - for (uint256 i = 0; i < uint256ChainSelectors.length; ++i) { - chainSelectors[i] = uint64(uint256ChainSelectors[i]); - } - - return chainSelectors; - } - - /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains - /// need to be allowed on the Router to interact with this pool. - /// @dev Only callable by the owner - /// @param chains A list of chains and their new permission status & rate limits. Rate limits - /// are only used when the chain is being added through `allowed` being true. - function applyChainUpdates(address token, ChainUpdate[] calldata chains) external virtual onlyOwner { - for (uint256 i = 0; i < chains.length; ++i) { - ChainUpdate memory update = chains[i]; - RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); - RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); - - if (update.allowed) { - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { - revert ChainAlreadyExists(update.remoteChainSelector); - } - - if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { - revert ZeroAddressNotAllowed(); - } - - s_remoteChainConfigs[token][update.remoteChainSelector] = RemoteChainConfig({ - outboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.outboundRateLimiterConfig.rate, - capacity: update.outboundRateLimiterConfig.capacity, - tokens: update.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.outboundRateLimiterConfig.isEnabled - }), - inboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.inboundRateLimiterConfig.rate, - capacity: update.inboundRateLimiterConfig.capacity, - tokens: update.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.inboundRateLimiterConfig.isEnabled - }), - remotePoolAddress: update.remotePoolAddress, - remoteTokenAddress: update.remoteTokenAddress - }); - - emit ChainAdded( - update.remoteChainSelector, - update.remoteTokenAddress, - update.outboundRateLimiterConfig, - update.inboundRateLimiterConfig - ); - } else { - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { - revert NonExistentChain(update.remoteChainSelector); - } - - delete s_remoteChainConfigs[token][update.remoteChainSelector]; - - emit ChainRemoved(update.remoteChainSelector); - } - } - } - - // ================================================================ - // │ Rate limiting │ - // ================================================================ - - /// @notice Consumes outbound rate limiting capacity in this pool - function _consumeOutboundRateLimit(address token, uint64 remoteChainSelector, uint256 amount) internal { - s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._consume(amount, token); - } - - /// @notice Consumes inbound rate limiting capacity in this pool - function _consumeInboundRateLimit(address token, uint64 remoteChainSelector, uint256 amount) internal { - s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._consume(amount, token); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentOutboundRateLimiterState( - address token, - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function getCurrentInboundRateLimiterState( - address token, - uint64 remoteChainSelector - ) external view returns (RateLimiter.TokenBucket memory) { - return s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); - } - - /// @notice Sets the chain rate limiter config. - /// @param remoteChainSelector The remote chain selector for which the rate limits apply. - /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. - /// @param inboundConfig The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function _setChainRateLimiterConfig( - address token, - uint64 remoteChainSelector, - RateLimiter.Config memory outboundConfig, - RateLimiter.Config memory inboundConfig - ) internal { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - RateLimiter._validateTokenBucketConfig(outboundConfig, false); - s_remoteChainConfigs[token][remoteChainSelector].outboundRateLimiterConfig._setTokenBucketConfig(outboundConfig); - RateLimiter._validateTokenBucketConfig(inboundConfig, false); - s_remoteChainConfigs[token][remoteChainSelector].inboundRateLimiterConfig._setTokenBucketConfig(inboundConfig); - emit ChainConfigured(remoteChainSelector, outboundConfig, inboundConfig); - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned onRamp for the given chain on the Router. - function _onlyOnRamp( - uint64 remoteChainSelector - ) internal view { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!(msg.sender == s_router.getOnRamp(remoteChainSelector))) revert CallerIsNotARampOnRouter(msg.sender); - } - - /// @notice Checks whether remote chain selector is configured on this contract, and if the msg.sender - /// is a permissioned offRamp for the given chain on the Router. - function _onlyOffRamp( - uint64 remoteChainSelector - ) internal view { - if (!isSupportedChain(remoteChainSelector)) revert ChainNotAllowed(remoteChainSelector); - if (!s_router.isOffRamp(remoteChainSelector, msg.sender)) revert CallerIsNotARampOnRouter(msg.sender); - } - - // ================================================================ - // │ Allowlist │ - // ================================================================ - - function _checkAllowList( - address sender - ) internal view { - if (i_allowlistEnabled && !s_allowList.contains(sender)) revert SenderNotAllowed(sender); - } - - /// @notice Gets whether the allowList functionality is enabled. - /// @return true is enabled, false if not. - function getAllowListEnabled() external view returns (bool) { - return i_allowlistEnabled; - } - - /// @notice Gets the allowed addresses. - /// @return The allowed addresses. - function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); - } - - /// @notice Apply updates to the allow list. - /// @param removes The addresses to be removed. - /// @param adds The addresses to be added. - /// @dev allowListing will be removed before public launch - function applyAllowListUpdates(address[] calldata removes, address[] calldata adds) external onlyOwner { - _applyAllowListUpdates(removes, adds); - } - - /// @notice Internal version of applyAllowListUpdates to allow for reuse in the constructor. - function _applyAllowListUpdates(address[] memory removes, address[] memory adds) internal { - if (!i_allowlistEnabled) revert AllowListNotEnabled(); - - for (uint256 i = 0; i < removes.length; ++i) { - address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { - emit AllowListRemove(toRemove); - } - } - for (uint256 i = 0; i < adds.length; ++i) { - address toAdd = adds[i]; - if (toAdd == address(0)) { - continue; - } - if (s_allowList.add(toAdd)) { - emit AllowListAdd(toAdd); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol deleted file mode 100644 index 40f7ccb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {OffRamp} from "../../offRamp/OffRamp.sol"; -import {IgnoreContractSize} from "./IgnoreContractSize.sol"; - -contract OffRampHelper is OffRamp, IgnoreContractSize { - using EnumerableSet for EnumerableSet.UintSet; - - mapping(uint64 sourceChainSelector => uint256 overrideTimestamp) private s_sourceChainVerificationOverride; - - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - SourceChainConfigArgs[] memory sourceChainConfigs - ) OffRamp(staticConfig, dynamicConfig, sourceChainConfigs) {} - - function setExecutionStateHelper( - uint64 sourceChainSelector, - uint64 sequenceNumber, - Internal.MessageExecutionState state - ) public { - _setExecutionState(sourceChainSelector, sequenceNumber, state); - } - - function getExecutionStateBitMap(uint64 sourceChainSelector, uint64 bitmapIndex) public view returns (uint256) { - return s_executionStates[sourceChainSelector][bitmapIndex]; - } - - function releaseOrMintSingleToken( - Internal.Any2EVMTokenTransfer calldata sourceTokenAmount, - bytes calldata originalSender, - address receiver, - uint64 sourceChainSelector, - bytes calldata offchainTokenData - ) external returns (Client.EVMTokenAmount memory) { - return - _releaseOrMintSingleToken(sourceTokenAmount, originalSender, receiver, sourceChainSelector, offchainTokenData); - } - - function releaseOrMintTokens( - Internal.Any2EVMTokenTransfer[] calldata sourceTokenAmounts, - bytes calldata originalSender, - address receiver, - uint64 sourceChainSelector, - bytes[] calldata offchainTokenData, - uint32[] calldata tokenGasOverrides - ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens( - sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData, tokenGasOverrides - ); - } - - function trialExecute( - Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData, - uint32[] memory tokenGasOverrides - ) external returns (Internal.MessageExecutionState, bytes memory) { - return _trialExecute(message, offchainTokenData, tokenGasOverrides); - } - - function executeSingleReport( - Internal.ExecutionReport memory rep, - GasLimitOverride[] memory manualExecGasExecOverrides - ) external { - _executeSingleReport(rep, manualExecGasExecOverrides); - } - - function batchExecute( - Internal.ExecutionReport[] memory reports, - GasLimitOverride[][] memory manualExecGasLimits - ) external { - _batchExecute(reports, manualExecGasLimits); - } - - function verify( - uint64 sourceChainSelector, - bytes32[] memory hashedLeaves, - bytes32[] memory proofs, - uint256 proofFlagBits - ) external view returns (uint256 timestamp) { - return super._verify(sourceChainSelector, hashedLeaves, proofs, proofFlagBits); - } - - function _verify( - uint64 sourceChainSelector, - bytes32[] memory hashedLeaves, - bytes32[] memory proofs, - uint256 proofFlagBits - ) internal view override returns (uint256 timestamp) { - uint256 overrideTimestamp = s_sourceChainVerificationOverride[sourceChainSelector]; - - return overrideTimestamp == 0 - ? super._verify(sourceChainSelector, hashedLeaves, proofs, proofFlagBits) - : overrideTimestamp; - } - - /// @dev Test helper to override _verify result for easier exec testing - function setVerifyOverrideResult(uint64 sourceChainSelector, uint256 overrideTimestamp) external { - s_sourceChainVerificationOverride[sourceChainSelector] = overrideTimestamp; - } - - /// @dev Test helper to directly set a root's timestamp - function setRootTimestamp(uint64 sourceChainSelector, bytes32 root, uint256 timestamp) external { - s_roots[sourceChainSelector][root] = timestamp; - } - - function getSourceChainSelectors() external view returns (uint256[] memory chainSelectors) { - return s_sourceChainSelectors.values(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol deleted file mode 100644 index d315a58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OnRamp} from "../../onRamp/OnRamp.sol"; -import {IgnoreContractSize} from "./IgnoreContractSize.sol"; - -contract OnRampHelper is OnRamp, IgnoreContractSize { - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - DestChainConfigArgs[] memory destChainConfigArgs - ) OnRamp(staticConfig, dynamicConfig, destChainConfigArgs) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol deleted file mode 100644 index 6cd1c18..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -contract RateLimiterHelper { - using RateLimiter for RateLimiter.TokenBucket; - - RateLimiter.TokenBucket internal s_rateLimiter; - - constructor( - RateLimiter.Config memory config - ) { - s_rateLimiter = RateLimiter.TokenBucket({ - rate: config.rate, - capacity: config.capacity, - tokens: config.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: config.isEnabled - }); - } - - function consume(uint256 requestTokens, address tokenAddress) external { - s_rateLimiter._consume(requestTokens, tokenAddress); - } - - function currentTokenBucketState() external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimiter._currentTokenBucketState(); - } - - function setTokenBucketConfig( - RateLimiter.Config memory config - ) external { - s_rateLimiter._setTokenBucketConfig(config); - } - - function getRateLimiter() external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimiter; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol deleted file mode 100644 index 41e4a95..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Internal} from "../../libraries/Internal.sol"; -import {OffRamp} from "../../offRamp/OffRamp.sol"; - -contract ReportCodec { - event ExecuteReportDecoded(Internal.ExecutionReport[] report); - event CommitReportDecoded(OffRamp.CommitReport report); - - function decodeExecuteReport( - bytes memory report - ) public pure returns (Internal.ExecutionReport[] memory) { - return abi.decode(report, (Internal.ExecutionReport[])); - } - - function decodeCommitReport( - bytes memory report - ) public pure returns (OffRamp.CommitReport memory) { - return abi.decode(report, (OffRamp.CommitReport)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol deleted file mode 100644 index 75f6b1b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../libraries/Pool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenPoolHelper is TokenPool { - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) {} - - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external view override returns (Pool.LockOrBurnOutV1 memory) { - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - function onlyOnRampModifier( - uint64 remoteChainSelector - ) external view { - _onlyOnRamp(remoteChainSelector); - } - - function onlyOffRampModifier( - uint64 remoteChainSelector - ) external view { - _onlyOffRamp(remoteChainSelector); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol deleted file mode 100644 index d1baa22..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -contract USDCReaderTester { - event MessageSent(bytes); - - // emitMessageSent reflects the logic from Circle's MessageTransmitter emitting MeseageSent(bytes) events - // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L41 - // https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/MessageTransmitter.sol#L365 - function emitMessageSent( - uint32 version, - uint32 sourceDomain, - uint32 destinationDomain, - bytes32 recipient, - bytes32 destinationCaller, - bytes32 sender, - uint64 nonce, - bytes calldata messageBody - ) external { - bytes memory _message = - _formatMessage(version, sourceDomain, destinationDomain, nonce, sender, recipient, destinationCaller, messageBody); - emit MessageSent(_message); - } - - /** - * @notice Returns formatted (packed) message with provided fields - * It's a copy paste of the Message._formatMessage() call in MessageTransmitter.sol - * https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/Message.sol#L54C1-L65C9 - * Check the chainlink-ccip repo for the offchain implementation of matching this format - * @param _msgVersion the version of the message format - * @param _msgSourceDomain Domain of home chain - * @param _msgDestinationDomain Domain of destination chain - * @param _msgNonce Destination-specific nonce - * @param _msgSender Address of sender on source chain as bytes32 - * @param _msgRecipient Address of recipient on destination chain as bytes32 - * @param _msgDestinationCaller Address of caller on destination chain as bytes32 - * @param _msgRawBody Raw bytes of message body - * @return Formatted message - * - */ - function _formatMessage( - uint32 _msgVersion, - uint32 _msgSourceDomain, - uint32 _msgDestinationDomain, - uint64 _msgNonce, - bytes32 _msgSender, - bytes32 _msgRecipient, - bytes32 _msgDestinationCaller, - bytes memory _msgRawBody - ) internal pure returns (bytes memory) { - return abi.encodePacked( - _msgVersion, - _msgSourceDomain, - _msgDestinationDomain, - _msgNonce, - _msgSender, - _msgRecipient, - _msgDestinationCaller, - _msgRawBody - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol deleted file mode 100644 index 7a34005..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; -import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; - -contract USDCTokenPoolHelper is USDCTokenPool { - constructor( - ITokenMessenger tokenMessenger, - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) {} - - function validateMessage(bytes memory usdcMessage, SourceTokenDataPayload memory sourceTokenData) external view { - return _validateMessage(usdcMessage, sourceTokenData); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol deleted file mode 100644 index d4102da..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; -import {Client} from "../../../libraries/Client.sol"; - -contract ConformingReceiver is CCIPReceiver { - event MessageReceived(); - - constructor(address router, address feeToken) CCIPReceiver(router) {} - - function _ccipReceive( - Client.Any2EVMMessage memory - ) internal virtual override { - emit MessageReceived(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol deleted file mode 100644 index b40b2c3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; -import {Client} from "../../../libraries/Client.sol"; - -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -contract MaybeRevertMessageReceiver is IAny2EVMMessageReceiver, IERC165 { - error ReceiveRevert(); - error CustomError(bytes err); - - event ValueReceived(uint256 amount); - event MessageReceived(); - - address private s_manager; - bool public s_toRevert; - bytes private s_err; - - constructor( - bool toRevert - ) { - s_manager = msg.sender; - s_toRevert = toRevert; - } - - function setRevert( - bool toRevert - ) external { - s_toRevert = toRevert; - } - - function setErr( - bytes memory err - ) external { - s_err = err; - } - - /// @notice IERC165 supports an interfaceId - /// @param interfaceId The interfaceId to check - /// @return true if the interfaceId is supported - function supportsInterface( - bytes4 interfaceId - ) public pure override returns (bool) { - return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } - - function ccipReceive( - Client.Any2EVMMessage calldata - ) external override { - if (s_toRevert) { - revert CustomError(s_err); - } - emit MessageReceived(); - } - - // solhint-disable-next-line no-complex-fallback - receive() external payable { - if (s_toRevert) { - revert ReceiveRevert(); - } - - emit ValueReceived(msg.value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol deleted file mode 100644 index 07e5ac8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; - -import {Client} from "../../../libraries/Client.sol"; - -contract MaybeRevertMessageReceiverNo165 is IAny2EVMMessageReceiver { - address private s_manager; - bool public s_toRevert; - - event MessageReceived(); - - constructor( - bool toRevert - ) { - s_manager = msg.sender; - s_toRevert = toRevert; - } - - function setRevert( - bool toRevert - ) external { - s_toRevert = toRevert; - } - - function ccipReceive( - Client.Any2EVMMessage calldata - ) external override { - if (s_toRevert) { - // solhint-disable-next-line reason-string,gas-custom-errors - revert(); - } - emit MessageReceived(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol deleted file mode 100644 index b8aeeb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; -import {Client} from "../../../libraries/Client.sol"; -import {Internal} from "../../../libraries/Internal.sol"; -import {OffRamp} from "../../../offRamp/OffRamp.sol"; - -contract ReentrancyAbuser is CCIPReceiver { - event ReentrancySucceeded(); - - uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 144_000; - - bool internal s_ReentrancyDone = false; - Internal.ExecutionReport internal s_payload; - OffRamp internal s_offRamp; - - constructor(address router, OffRamp offRamp) CCIPReceiver(router) { - s_offRamp = offRamp; - } - - function setPayload( - Internal.ExecutionReport calldata payload - ) public { - s_payload = payload; - } - - function _ccipReceive( - Client.Any2EVMMessage memory - ) internal override { - // Use original message gas limits in manual execution - OffRamp.GasLimitOverride[][] memory gasOverrides = _getGasLimitsFromMessages(s_payload.messages); - - if (!s_ReentrancyDone) { - // Could do more rounds but a PoC one is enough - s_ReentrancyDone = true; - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); - reports[0] = s_payload; - - s_offRamp.manuallyExecute(reports, gasOverrides); - } else { - emit ReentrancySucceeded(); - } - } - - function _getGasLimitsFromMessages( - Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (OffRamp.GasLimitOverride[][] memory) { - OffRamp.GasLimitOverride[] memory gasLimitOverrides = new OffRamp.GasLimitOverride[](messages.length); - for (uint256 i = 0; i < messages.length; ++i) { - gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit; - gasLimitOverrides[i].tokenGasOverrides = new uint32[](messages[i].tokenAmounts.length); - - for (uint256 j = 0; j < messages[i].tokenAmounts.length; ++j) { - gasLimitOverrides[i].tokenGasOverrides[j] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; - } - } - - OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); - gasOverrides[0] = gasLimitOverrides; - return gasOverrides; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol deleted file mode 100644 index d3d0fd3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.19; - -import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; -import {Client} from "../../../libraries/Client.sol"; -import {Internal} from "../../../libraries/Internal.sol"; -import {OffRamp} from "../../../offRamp/OffRamp.sol"; - -contract ReentrancyAbuserMultiRamp is CCIPReceiver { - event ReentrancySucceeded(); - - bool internal s_ReentrancyDone = false; - Internal.ExecutionReport internal s_payload; - OffRamp internal s_offRamp; - - constructor(address router, OffRamp offRamp) CCIPReceiver(router) { - s_offRamp = offRamp; - } - - function setPayload( - Internal.ExecutionReport calldata payload - ) public { - s_payload = payload; - } - - function _ccipReceive( - Client.Any2EVMMessage memory - ) internal override { - // Use original message gas limits in manual execution - uint256 numMsgs = s_payload.messages.length; - OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); - gasOverrides[0] = new OffRamp.GasLimitOverride[](numMsgs); - for (uint256 i = 0; i < numMsgs; ++i) { - gasOverrides[0][i].receiverExecutionGasLimit = 0; - gasOverrides[0][i].tokenGasOverrides = new uint32[](s_payload.messages[i].tokenAmounts.length); - } - - Internal.ExecutionReport[] memory batchPayload = new Internal.ExecutionReport[](1); - batchPayload[0] = s_payload; - - if (!s_ReentrancyDone) { - // Could do more rounds but a PoC one is enough - s_ReentrancyDone = true; - s_offRamp.manuallyExecute(batchPayload, gasOverrides); - } else { - emit ReentrancySucceeded(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol deleted file mode 100644 index e2fc981..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; -import {MerkleHelper} from "../helpers/MerkleHelper.sol"; -import {Test} from "forge-std/Test.sol"; - -contract MerkleMultiProofTest is Test { - // This must match the spec - function test_SpecSync_gas() public pure { - bytes32 expectedRoot = 0xd4f0f3c40a4d583d98c17d89e550b1143fe4d3d759f25ccc63131c90b183928e; - - bytes32[] memory leaves = new bytes32[](10); - leaves[0] = 0xa20c0244af79697a4ef4e2378c9d5d14cbd49ddab3427b12594c7cfa67a7f240; - leaves[1] = 0x3de96afb24ce2ac45a5595aa13d1a5163ae0b3c94cef6b2dc306b5966f32dfa5; - leaves[2] = 0xacadf7b4d13cd57c5d25f1d27be39b656347fe8f8e0de8db9c76d979dff57736; - leaves[3] = 0xc21c26a709802fe1ae52a9cd8ad94d15bf142ded26314339cd87a13e5b468165; - leaves[4] = 0x55f6df03562738c9a6437cd9ad221c52b76906a175ae96188cff60e0a2a59933; - leaves[5] = 0x2dbbe66452e43fec839dc65d5945aad6433d410c65863eaf1d876e1e0b06343c; - leaves[6] = 0x8beab00297b94bf079fcd5893b0a33ebf6b0ce862cd06be07c87d3c63e1c4acf; - leaves[7] = 0xcabdd3ad25daeb1e0541042f2ea4cd177f54e67aa4a2c697acd4bb682e94de59; - leaves[8] = 0x7e01d497203685e99e34df33d55465c66b2253fa1630ee2fe5c4997968e4a6fa; - leaves[9] = 0x1a03d013f1e2fa9cc04f89c7528ac3216e3e096a1185d7247304e97c59f9661f; - - bytes32[] memory proofs = new bytes32[](33); - proofs[0] = 0xde96f24fcf9ddd20c803dc9c5fba7c478a5598a08a0faa5f032c65823b8e26a3; - proofs[1] = 0xe1303cffc3958a6b93e2dc04caf21f200ff5aa5be090c5013f37804b91488bc2; - proofs[2] = 0x90d80c76bccb44a91f4e16604976163aaa39e9a1588b0b24b33a61f1d4ba7bb5; - proofs[3] = 0x012a299b25539d513c8677ecf37968774e9e4b045e79737f48defd350224cdfd; - proofs[4] = 0x420a36c5a73f87d8fb98e70c48d0d6f9dd83f50b7b91416a6f5f91fac4db800f; - proofs[5] = 0x5857d8d1b56abcd7f863cedd3c3f8677256f54d675be61f05efa45d6495fc30a; - proofs[6] = 0xbf176d20166fdeb72593ff97efec1ce6244af41ca46cf0bc902d19d50c446f7b; - proofs[7] = 0xa9221608e4380250a1815fb308632bce99f611a673d2e17fc617123fdc6afcd2; - proofs[8] = 0xbd14f3366c73186314f182027217d0f70eba55817561de9e9a1f2c78bf5cbead; - proofs[9] = 0x2f9aa48c0c9f82aaac65d7a9374a52d9dc138ed100a5809ede57e70697f48b56; - proofs[10] = 0x2ae60afa54271cb421c12e4441c2dac0a25f25c9433a6d07cb32419e993fe344; - proofs[11] = 0xc765c091680f0434b74c44507b932e5c80f6e995a975a275e5b130af1de1064c; - proofs[12] = 0x59d2d6e0c4a5d07b169dbcdfa39dad7aea7b7783a814399f4f44c4a36b6336d3; - proofs[13] = 0xdd14d1387d10740187d71ad9500475399559c0922dbe2576882e61f1edd84692; - proofs[14] = 0x5412b8395509935406811ab3da43ab80be7acd8ffb5f398ab70f056ff3740f46; - proofs[15] = 0xeadab258ae7d779ce5f10fbb1bb0273116b8eccbf738ed878db570de78bed1e4; - proofs[16] = 0x6133aa40e6db75373b7cfc79e6f8b8ce80e441e6c1f98b85a593464dda3cf9c0; - proofs[17] = 0x5418948467112660639b932af9b1b212e40d71b24326b4606679d168a765af4f; - proofs[18] = 0x44f618505355c7e4e7c0f81d6bb15d2ec9cf9b366f9e1dc37db52745486e6b0f; - proofs[19] = 0xa410ee174a66a4d64f3c000b93efe15b5b1f3e39e962af2580fcd30bce07d039; - proofs[20] = 0x09c3eb05ac9552022a45c00d01a47cd56f95f94afdd4402299dba1291a17f976; - proofs[21] = 0x0e780f6acd081b07320a55208fa3e1d884e2e95cb13d1c98c74b7e853372c813; - proofs[22] = 0x2b60e8c21f78ef22fa4297f28f1d8c747181edfc465121b39c16be97d4fb8a04; - proofs[23] = 0xf24da95060a8598c06e9dfb3926e1a8c8bd8ec2c65be10e69323442840724888; - proofs[24] = 0x7e220fc095bcd2b0f5ef134d9620d89f6d7a1e8719ce8893bb9aff15e847578f; - proofs[25] = 0xcfe9e475c4bd32f1e36b2cc65a959c403c59979ff914fb629a64385b0c680a71; - proofs[26] = 0x25237fb8d1bfdc01ca5363ec3166a2b40789e38d5adcc8627801da683d2e1d76; - proofs[27] = 0x42647949fed0250139c01212d739d8c83d2852589ebc892d3490ae52e411432c; - proofs[28] = 0x34397a30930e6dd4fb5af48084afc5cfbe02c18dd9544b3faff4e2e90bf00cb9; - proofs[29] = 0xa028f33226adc3d1cb72b19eb6808dab9190b25066a45cacb5dfe5d640e57cf2; - proofs[30] = 0x7cff66ba47a05f932d06d168c294266dcb0d3943a4f2a4a75c860b9fd6e53092; - proofs[31] = 0x5ca1b32f1dbfadd83205882be5eb76f34c49e834726f5239905a0e70d0a5e0eb; - proofs[32] = 0x1b4b087a89e4eca6cdd237210932559dc8fd167d5f4f2d9acb13264e1e305479; - - uint256 flagsUint256 = 0x2f3c0000000; - - bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, flagsUint256); - - assertEq(expectedRoot, root); - } - - function test_Fuzz_MerkleRoot2(bytes32 left, bytes32 right) public pure { - bytes32[] memory leaves = new bytes32[](2); - leaves[0] = left; - leaves[1] = right; - bytes32[] memory proofs = new bytes32[](0); - - bytes32 expectedRoot = MerkleHelper.hashPair(left, right); - - bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, 2 ** 2 - 1); - - assertEq(root, expectedRoot); - } - - function test_MerkleRoot256() public pure { - bytes32[] memory leaves = new bytes32[](256); - for (uint256 i = 0; i < leaves.length; ++i) { - leaves[i] = keccak256("a"); - } - bytes32[] memory proofs = new bytes32[](0); - - bytes32 expectedRoot = MerkleHelper.getMerkleRoot(leaves); - - bytes32 root = MerkleMultiProof.merkleRoot(leaves, proofs, 2 ** 256 - 1); - - assertEq(root, expectedRoot); - } - - function test_Fuzz_MerkleMulti1of4(bytes32 leaf1, bytes32 proof1, bytes32 proof2) public pure { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = leaf1; - bytes32[] memory proofs = new bytes32[](2); - proofs[0] = proof1; - proofs[1] = proof2; - - // Proof flag = false - bytes32 result = MerkleHelper.hashPair(leaves[0], proofs[0]); - // Proof flag = false - result = MerkleHelper.hashPair(result, proofs[1]); - - assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 0), result); - } - - function test_Fuzz_MerkleMulti2of4(bytes32 leaf1, bytes32 leaf2, bytes32 proof1, bytes32 proof2) public pure { - bytes32[] memory leaves = new bytes32[](2); - leaves[0] = leaf1; - leaves[1] = leaf2; - bytes32[] memory proofs = new bytes32[](2); - proofs[0] = proof1; - proofs[1] = proof2; - - // Proof flag = false - bytes32 result1 = MerkleHelper.hashPair(leaves[0], proofs[0]); - // Proof flag = false - bytes32 result2 = MerkleHelper.hashPair(leaves[1], proofs[1]); - // Proof flag = true - bytes32 finalResult = MerkleHelper.hashPair(result1, result2); - - assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 4), finalResult); - } - - function test_Fuzz_MerkleMulti3of4(bytes32 leaf1, bytes32 leaf2, bytes32 leaf3, bytes32 proof) public pure { - bytes32[] memory leaves = new bytes32[](3); - leaves[0] = leaf1; - leaves[1] = leaf2; - leaves[2] = leaf3; - bytes32[] memory proofs = new bytes32[](1); - proofs[0] = proof; - - // Proof flag = true - bytes32 result1 = MerkleHelper.hashPair(leaves[0], leaves[1]); - // Proof flag = false - bytes32 result2 = MerkleHelper.hashPair(leaves[2], proofs[0]); - // Proof flag = true - bytes32 finalResult = MerkleHelper.hashPair(result1, result2); - - assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 5), finalResult); - } - - function test_Fuzz_MerkleMulti4of4(bytes32 leaf1, bytes32 leaf2, bytes32 leaf3, bytes32 leaf4) public pure { - bytes32[] memory leaves = new bytes32[](4); - leaves[0] = leaf1; - leaves[1] = leaf2; - leaves[2] = leaf3; - leaves[3] = leaf4; - bytes32[] memory proofs = new bytes32[](0); - - // Proof flag = true - bytes32 result1 = MerkleHelper.hashPair(leaves[0], leaves[1]); - // Proof flag = true - bytes32 result2 = MerkleHelper.hashPair(leaves[2], leaves[3]); - // Proof flag = true - bytes32 finalResult = MerkleHelper.hashPair(result1, result2); - - assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 7), finalResult); - } - - function test_MerkleRootSingleLeaf_Success() public pure { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - bytes32[] memory proofs = new bytes32[](0); - assertEq(MerkleMultiProof.merkleRoot(leaves, proofs, 0), leaves[0]); - } - - function test_EmptyLeaf_Revert() public { - bytes32[] memory leaves = new bytes32[](0); - bytes32[] memory proofs = new bytes32[](0); - - vm.expectRevert(abi.encodeWithSelector(MerkleMultiProof.LeavesCannotBeEmpty.selector)); - MerkleMultiProof.merkleRoot(leaves, proofs, 0); - } - - function test_CVE_2023_34459() public { - bytes32[] memory leaves = new bytes32[](2); - // leaves[0] stays uninitialized, i.e., 0x000...0 - leaves[1] = "leaf"; - - bytes32[] memory proof = new bytes32[](2); - proof[0] = leaves[1]; - proof[1] = "will never be used"; - - bytes32[] memory malicious = new bytes32[](2); - malicious[0] = "malicious leaf"; - malicious[1] = "another malicious leaf"; - - vm.expectRevert(abi.encodeWithSelector(MerkleMultiProof.InvalidProof.selector)); - MerkleMultiProof.merkleRoot(malicious, proof, 3); - // Note, that without the revert the above computed root - // would equal MerkleHelper.hashPair(leaves[0], leaves[1]). - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol deleted file mode 100644 index da6a6f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol +++ /dev/null @@ -1,297 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {RateLimiterHelper} from "../helpers/RateLimiterHelper.sol"; -import {Test} from "forge-std/Test.sol"; - -contract RateLimiterSetup is Test { - RateLimiterHelper internal s_helper; - RateLimiter.Config internal s_config; - - uint256 internal constant BLOCK_TIME = 1234567890; - - function setUp() public virtual { - s_config = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); - s_helper = new RateLimiterHelper(s_config); - } -} - -contract RateLimiter_constructor is RateLimiterSetup { - function test_Constructor_Success() public view { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } -} - -contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { - function test_SetRateLimiterConfig_Success() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - - s_config = - RateLimiter.Config({isEnabled: true, rate: uint128(rateLimiter.rate * 2), capacity: rateLimiter.capacity * 8}); - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(s_config); - - s_helper.setTokenBucketConfig(s_config); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity / 8, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } -} - -contract RateLimiter_currentTokenBucketState is RateLimiterSetup { - function test_CurrentTokenBucketState_Success() public { - RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - s_config = RateLimiter.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); - - s_helper.setTokenBucketConfig(s_config); - - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 8, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } - - function test_Refill_Success() public { - RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - s_config = RateLimiter.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); - - s_helper.setTokenBucketConfig(s_config); - - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 8, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - bucket = s_helper.currentTokenBucketState(); - - assertEq(s_config.capacity / 8 + warpTime * s_config.rate, bucket.tokens); - - vm.warp(BLOCK_TIME + warpTime * 100); - - // Bucket overflow - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.capacity, bucket.tokens); - } -} - -contract RateLimiter_consume is RateLimiterSetup { - address internal s_token = address(100); - - function test_ConsumeAggregateValue_Success() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - - uint256 requestTokens = 50; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(requestTokens); - - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } - - function test_ConsumeTokens_Success() public { - uint256 requestTokens = 50; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(requestTokens); - - s_helper.consume(requestTokens, s_token); - } - - function test_Refill_Success() public { - uint256 requestTokens = 50; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(requestTokens); - - s_helper.consume(requestTokens, address(0)); - - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(requestTokens); - - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens * 2 + warpTime * s_config.rate, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); - } - - function test_ConsumeUnlimited_Success() public { - s_helper.consume(0, address(0)); - - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - - RateLimiter.Config memory disableConfig = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); - - s_helper.setTokenBucketConfig(disableConfig); - - uint256 requestTokens = 50; - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(disableConfig.capacity, rateLimiter.tokens); - assertEq(disableConfig.isEnabled, rateLimiter.isEnabled); - - s_helper.setTokenBucketConfig(s_config); - - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 10, 0)); - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(0, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - } - - // Reverts - - function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1 - ) - ); - s_helper.consume(rateLimiter.capacity + 1, address(0)); - } - - function test_TokenMaxCapacityExceeded_Revert() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.TokenMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1, s_token - ) - ); - s_helper.consume(rateLimiter.capacity + 1, s_token); - } - - function test_ConsumingMoreThanUint128_Revert() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 request = uint256(type(uint128).max) + 1; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, request) - ); - s_helper.consume(request, address(0)); - } - - function test_AggregateValueRateLimitReached_Revert() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 overLimit = 20; - uint256 requestTokens1 = rateLimiter.capacity / 2; - uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; - - uint256 waitInSeconds = overLimit / rateLimiter.rate; - - s_helper.consume(requestTokens1, address(0)); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueRateLimitReached.selector, waitInSeconds, rateLimiter.capacity - requestTokens1 - ) - ); - s_helper.consume(requestTokens2, address(0)); - } - - function test_TokenRateLimitReached_Revert() public { - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 overLimit = 20; - uint256 requestTokens1 = rateLimiter.capacity / 2; - uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; - - uint256 waitInSeconds = overLimit / rateLimiter.rate; - - s_helper.consume(requestTokens1, s_token); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.TokenRateLimitReached.selector, waitInSeconds, rateLimiter.capacity - requestTokens1, s_token - ) - ); - s_helper.consume(requestTokens2, s_token); - } - - function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { - uint256 initBlockTime = BLOCK_TIME + 10000; - vm.warp(initBlockTime); - - RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(rateLimiter.capacity); - - s_helper.consume(rateLimiter.capacity, address(0)); - - vm.warp(initBlockTime + 1); - - // Over rate limit by 1, force 1 second wait - uint256 overLimit = 1; - - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 1, rateLimiter.rate)); - s_helper.consume(rateLimiter.rate + overLimit, address(0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol deleted file mode 100644 index c142cb8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2022, Circle Internet Financial Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; -import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWithRelay.sol"; - -// This contract mocks both the ITokenMessenger and IMessageTransmitter -// contracts involved with the Cross Chain Token Protocol. -// solhint-disable -contract MockE2EUSDCTokenMessenger is ITokenMessenger { - uint32 private immutable i_messageBodyVersion; - address private immutable i_transmitter; - - bytes32 public constant DESTINATION_TOKEN_MESSENGER = keccak256("i_destinationTokenMessenger"); - - uint64 public s_nonce; - - // Local Message Transmitter responsible for sending and receiving messages to/from remote domains - IMessageTransmitterWithRelay public immutable localMessageTransmitterWithRelay; - - constructor(uint32 version, address transmitter) { - i_messageBodyVersion = version; - s_nonce = 1; - i_transmitter = transmitter; - localMessageTransmitterWithRelay = IMessageTransmitterWithRelay(transmitter); - } - - // The mock function is based on the same function in https://github.com/circlefin/evm-cctp-contracts/blob/master/src/TokenMessenger.sol - function depositForBurnWithCaller( - uint256 amount, - uint32 destinationDomain, - bytes32 mintRecipient, - address burnToken, - bytes32 destinationCaller - ) external returns (uint64) { - IBurnMintERC20(burnToken).transferFrom(msg.sender, address(this), amount); - IBurnMintERC20(burnToken).burn(amount); - // Format message body - bytes memory _burnMessage = _formatMessage( - i_messageBodyVersion, - bytes32(uint256(uint160(burnToken))), - mintRecipient, - amount, - bytes32(uint256(uint160(msg.sender))) - ); - s_nonce = - _sendDepositForBurnMessage(destinationDomain, DESTINATION_TOKEN_MESSENGER, destinationCaller, _burnMessage); - emit DepositForBurn( - s_nonce, - burnToken, - amount, - msg.sender, - mintRecipient, - destinationDomain, - DESTINATION_TOKEN_MESSENGER, - destinationCaller - ); - return s_nonce; - } - - function messageBodyVersion() external view returns (uint32) { - return i_messageBodyVersion; - } - - function localMessageTransmitter() external view returns (address) { - return i_transmitter; - } - - /** - * @notice Sends a BurnMessage through the local message transmitter - * @dev calls local message transmitter's sendMessage() function if `_destinationCaller` == bytes32(0), - * or else calls sendMessageWithCaller(). - * @param _destinationDomain destination domain - * @param _destinationTokenMessenger address of registered TokenMessenger contract on destination domain, as bytes32 - * @param _destinationCaller caller on the destination domain, as bytes32. If `_destinationCaller` == bytes32(0), - * any address can call receiveMessage() on destination domain. - * @param _burnMessage formatted BurnMessage bytes (message body) - * @return nonce unique nonce reserved by message - */ - function _sendDepositForBurnMessage( - uint32 _destinationDomain, - bytes32 _destinationTokenMessenger, - bytes32 _destinationCaller, - bytes memory _burnMessage - ) internal returns (uint64 nonce) { - if (_destinationCaller == bytes32(0)) { - return localMessageTransmitterWithRelay.sendMessage(_destinationDomain, _destinationTokenMessenger, _burnMessage); - } else { - return localMessageTransmitterWithRelay.sendMessageWithCaller( - _destinationDomain, _destinationTokenMessenger, _destinationCaller, _burnMessage - ); - } - } - - /** - * @notice Formats Burn message - * @param _version The message body version - * @param _burnToken The burn token address on source domain as bytes32 - * @param _mintRecipient The mint recipient address as bytes32 - * @param _amount The burn amount - * @param _messageSender The message sender - * @return Burn formatted message. - */ - function _formatMessage( - uint32 _version, - bytes32 _burnToken, - bytes32 _mintRecipient, - uint256 _amount, - bytes32 _messageSender - ) internal pure returns (bytes memory) { - return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol deleted file mode 100644 index 4ed47b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2022, Circle Internet Financial Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pragma solidity ^0.8.0; - -import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWithRelay.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; - -// solhint-disable -contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { - // Indicated whether the receiveMessage() call should succeed. - bool public s_shouldSucceed; - uint32 private immutable i_version; - uint32 private immutable i_localDomain; - // Next available nonce from this source domain - uint64 public nextAvailableNonce; - - BurnMintERC677 internal immutable i_token; - - /** - * @notice Emitted when a new message is dispatched - * @param message Raw bytes of message - */ - event MessageSent(bytes message); - - constructor(uint32 _version, uint32 _localDomain, address token) { - i_version = _version; - i_localDomain = _localDomain; - s_shouldSucceed = true; - - i_token = BurnMintERC677(token); - } - - /// @param message The original message on the source chain - /// * Message format: - /// * Field Bytes Type Index - /// * version 4 uint32 0 - /// * sourceDomain 4 uint32 4 - /// * destinationDomain 4 uint32 8 - /// * nonce 8 uint64 12 - /// * sender 32 bytes32 20 - /// * recipient 32 bytes32 52 - /// * destinationCaller 32 bytes32 84 - /// * messageBody dynamic bytes 116 - function receiveMessage(bytes calldata message, bytes calldata) external returns (bool success) { - // The receiver of the funds is the _mintRecipient in the following encoded format - // function _formatMessage( - // uint32 _version, 4 - // bytes32 _burnToken, 32 - // bytes32 _mintRecipient, 32, first 12 empty for EVM addresses - // uint256 _amount, - // bytes32 _messageSender - // ) internal pure returns (bytes memory) { - // return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); - // } - address recipient = address(bytes20(message[116 + 36 + 12:116 + 36 + 12 + 20])); - // We always mint 1 token to not complicate the test. - i_token.mint(recipient, 1); - - return s_shouldSucceed; - } - - function setShouldSucceed( - bool shouldSucceed - ) external { - s_shouldSucceed = shouldSucceed; - } - - function version() external view returns (uint32) { - return i_version; - } - - function localDomain() external view returns (uint32) { - return i_localDomain; - } - - /** - * This is based on similar function in https://github.com/circlefin/evm-cctp-contracts/blob/master/src/MessageTransmitter.sol - * @notice Send the message to the destination domain and recipient - * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. - * @param destinationDomain Domain of destination chain - * @param recipient Address of message recipient on destination chain as bytes32 - * @param messageBody Raw bytes content of message - * @return nonce reserved by message - */ - function sendMessage( - uint32 destinationDomain, - bytes32 recipient, - bytes calldata messageBody - ) external returns (uint64) { - bytes32 _emptyDestinationCaller = bytes32(0); - uint64 _nonce = _reserveAndIncrementNonce(); - bytes32 _messageSender = bytes32(uint256(uint160((msg.sender)))); - - _sendMessage(destinationDomain, recipient, _emptyDestinationCaller, _messageSender, _nonce, messageBody); - - return _nonce; - } - - /** - * @notice Send the message to the destination domain and recipient, for a specified `destinationCaller` on the - * destination domain. - * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. - * WARNING: if the `destinationCaller` does not represent a valid address, then it will not be possible - * to broadcast the message on the destination domain. This is an advanced feature, and the standard - * sendMessage() should be preferred for use cases where a specific destination caller is not required. - * @param destinationDomain Domain of destination chain - * @param recipient Address of message recipient on destination domain as bytes32 - * @param destinationCaller caller on the destination domain, as bytes32 - * @param messageBody Raw bytes content of message - * @return nonce reserved by message - */ - function sendMessageWithCaller( - uint32 destinationDomain, - bytes32 recipient, - bytes32 destinationCaller, - bytes calldata messageBody - ) external returns (uint64) { - require(destinationCaller != bytes32(0), "Destination caller must be nonzero"); - - uint64 _nonce = _reserveAndIncrementNonce(); - bytes32 _messageSender = bytes32(uint256(uint160((msg.sender)))); - - _sendMessage(destinationDomain, recipient, destinationCaller, _messageSender, _nonce, messageBody); - - return _nonce; - } - - /** - * Reserve and increment next available nonce - * @return nonce reserved - */ - function _reserveAndIncrementNonce() internal returns (uint64) { - uint64 _nonceReserved = nextAvailableNonce; - nextAvailableNonce = nextAvailableNonce + 1; - return _nonceReserved; - } - - /** - * @notice Send the message to the destination domain and recipient. If `_destinationCaller` is not equal to bytes32(0), - * the message can only be received on the destination chain when called by `_destinationCaller`. - * @dev Format the message and emit `MessageSent` event with message information. - * @param _destinationDomain Domain of destination chain - * @param _recipient Address of message recipient on destination domain as bytes32 - * @param _destinationCaller caller on the destination domain, as bytes32 - * @param _sender message sender, as bytes32 - * @param _nonce nonce reserved for message - * @param _messageBody Raw bytes content of message - */ - function _sendMessage( - uint32 _destinationDomain, - bytes32 _recipient, - bytes32 _destinationCaller, - bytes32 _sender, - uint64 _nonce, - bytes calldata _messageBody - ) internal { - require(_recipient != bytes32(0), "Recipient must be nonzero"); - // serialize message - bytes memory _message = abi.encodePacked( - i_version, i_localDomain, _destinationDomain, _nonce, _sender, _recipient, _destinationCaller, _messageBody - ); - - // Emit MessageSent event - emit MessageSent(_message); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol deleted file mode 100644 index 435c669..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; - -/// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. -contract MockRMN is IRMN { - error CustomError(bytes err); - - bytes private s_isCursedRevert; - - bool private s_globalCursed; - mapping(bytes16 subject => bool cursed) private s_cursedBySubject; - mapping(address commitStore => mapping(bytes32 root => bool blessed)) private s_blessedByRoot; - - function setTaggedRootBlessed(IRMN.TaggedRoot calldata taggedRoot, bool blessed) external { - s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root] = blessed; - } - - function setGlobalCursed( - bool cursed - ) external { - s_globalCursed = cursed; - } - - function setChainCursed(uint64 chainSelector, bool cursed) external { - s_cursedBySubject[bytes16(uint128(chainSelector))] = cursed; - } - - /// @notice Setting a revert error with length of 0 will disable reverts - /// @dev Useful to test revert handling of ARMProxy - function setIsCursedRevert( - bytes calldata revertErr - ) external { - s_isCursedRevert = revertErr; - } - - // IRMN implementation follows - - function isCursed() external view returns (bool) { - if (s_isCursedRevert.length > 0) { - revert CustomError(s_isCursedRevert); - } - return s_globalCursed; - } - - function isCursed( - bytes16 subject - ) external view returns (bool) { - if (s_isCursedRevert.length > 0) { - revert CustomError(s_isCursedRevert); - } - return s_globalCursed || s_cursedBySubject[subject]; - } - - function isBlessed( - IRMN.TaggedRoot calldata taggedRoot - ) external view returns (bool) { - return s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol deleted file mode 100644 index 0abe4fd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; -import {IRouterClient} from "../../interfaces/IRouterClient.sol"; - -import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {ERC165Checker} from - "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; - -contract MockCCIPRouter is IRouter, IRouterClient { - using SafeERC20 for IERC20; - using ERC165Checker for address; - - error InvalidAddress(bytes encodedAddress); - error InvalidExtraArgsTag(); - error ReceiverError(bytes err); - - event MessageExecuted(bytes32 messageId, uint64 sourceChainSelector, address offRamp, bytes32 calldataHash); - event MsgExecuted(bool success, bytes retData, uint256 gasUsed); - - uint16 public constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - uint32 public constant DEFAULT_GAS_LIMIT = 200_000; - - uint256 internal s_mockFeeTokenAmount; //use setFee() to change to non-zero to test fees - - function routeMessage( - Client.Any2EVMMessage calldata message, - uint16 gasForCallExactCheck, - uint256 gasLimit, - address receiver - ) external returns (bool success, bytes memory retData, uint256 gasUsed) { - return _routeMessage(message, gasForCallExactCheck, gasLimit, receiver); - } - - function _routeMessage( - Client.Any2EVMMessage memory message, - uint16 gasForCallExactCheck, - uint256 gasLimit, - address receiver - ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { - // There are three cases in which we skip calling the receiver: - // 1. If the message data is empty AND the gas limit is 0. - // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract - // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the - // receiver without any gas, which would revert the transaction. - // 2. If the receiver is not a contract. - // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. - // - // The ordering of these checks is important, as the first check is the cheapest to execute. - if ( - (message.data.length == 0 && gasLimit == 0) || receiver.code.length == 0 - || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) - ) { - return (true, "", 0); - } - - bytes memory data = abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message); - - (success, retData, gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( - data, receiver, gasLimit, gasForCallExactCheck, Internal.MAX_RET_BYTES - ); - - // Event to assist testing, does not exist on real deployments - emit MsgExecuted(success, retData, gasUsed); - - // Real router event - emit MessageExecuted(message.messageId, message.sourceChainSelector, msg.sender, keccak256(data)); - return (success, retData, gasUsed); - } - - /// @notice Sends the tx locally to the receiver instead of on the destination chain. - /// @dev Ignores destinationChainSelector - /// @dev Returns a mock message ID, which is not calculated from the message contents in the - /// same way as the real message ID. - function ccipSend( - uint64 destinationChainSelector, - Client.EVM2AnyMessage calldata message - ) external payable returns (bytes32) { - if (message.receiver.length != 32) revert InvalidAddress(message.receiver); - uint256 decodedReceiver = abi.decode(message.receiver, (uint256)); - // We want to disallow sending to address(0) and to precompiles, which exist on address(1) through address(9). - if (decodedReceiver > type(uint160).max || decodedReceiver < 10) revert InvalidAddress(message.receiver); - - uint256 feeTokenAmount = getFee(destinationChainSelector, message); - if (message.feeToken == address(0)) { - if (msg.value < feeTokenAmount) revert InsufficientFeeTokenAmount(); - } else { - if (msg.value > 0) revert InvalidMsgValue(); - IERC20(message.feeToken).safeTransferFrom(msg.sender, address(this), feeTokenAmount); - } - - address receiver = address(uint160(decodedReceiver)); - uint256 gasLimit = _fromBytes(message.extraArgs).gasLimit; - bytes32 mockMsgId = keccak256(abi.encode(message)); - - Client.Any2EVMMessage memory executableMsg = Client.Any2EVMMessage({ - messageId: mockMsgId, - sourceChainSelector: 16015286601757825753, // Sepolia - sender: abi.encode(msg.sender), - data: message.data, - destTokenAmounts: message.tokenAmounts - }); - - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - IERC20(message.tokenAmounts[i].token).safeTransferFrom(msg.sender, receiver, message.tokenAmounts[i].amount); - } - - (bool success, bytes memory retData,) = _routeMessage(executableMsg, GAS_FOR_CALL_EXACT_CHECK, gasLimit, receiver); - - if (!success) revert ReceiverError(retData); - - return mockMsgId; - } - - function _fromBytes( - bytes calldata extraArgs - ) internal pure returns (Client.EVMExtraArgsV1 memory) { - if (extraArgs.length == 0) { - return Client.EVMExtraArgsV1({gasLimit: DEFAULT_GAS_LIMIT}); - } - if (bytes4(extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV1)); - } - - /// @notice Always returns true to make sure this check can be performed on any chain. - function isChainSupported( - uint64 - ) external pure returns (bool supported) { - return true; - } - - /// @notice Returns an empty array. - function getSupportedTokens( - uint64 - ) external pure returns (address[] memory tokens) { - return new address[](0); - } - - /// @notice Returns 0 as the fee is not supported in this mock contract. - function getFee(uint64, Client.EVM2AnyMessage memory) public view returns (uint256) { - return s_mockFeeTokenAmount; - } - - /// @notice Sets the fees returned by getFee but is only checked when using native fee tokens - function setFee( - uint256 feeAmount - ) external { - s_mockFeeTokenAmount = feeAmount; - } - - /// @notice Always returns address(1234567890) - function getOnRamp( - uint64 /* destChainSelector */ - ) external pure returns (address onRampAddress) { - return address(1234567890); - } - - /// @notice Always returns true - function isOffRamp(uint64, /* sourceChainSelector */ address /* offRamp */ ) external pure returns (bool) { - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol deleted file mode 100644 index 562a9f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; - -// This contract mocks both the ITokenMessenger and IMessageTransmitter -// contracts involved with the Cross Chain Token Protocol. -contract MockUSDCTokenMessenger is ITokenMessenger { - uint32 private immutable i_messageBodyVersion; - address private immutable i_transmitter; - - bytes32 public constant DESTINATION_TOKEN_MESSENGER = keccak256("i_destinationTokenMessenger"); - - uint64 public s_nonce; - - constructor(uint32 version, address transmitter) { - i_messageBodyVersion = version; - s_nonce = 1; - i_transmitter = transmitter; - } - - function depositForBurnWithCaller( - uint256 amount, - uint32 destinationDomain, - bytes32 mintRecipient, - address burnToken, - bytes32 destinationCaller - ) external returns (uint64) { - IBurnMintERC20(burnToken).transferFrom(msg.sender, address(this), amount); - IBurnMintERC20(burnToken).burn(amount); - emit DepositForBurn( - s_nonce, - burnToken, - amount, - msg.sender, - mintRecipient, - destinationDomain, - DESTINATION_TOKEN_MESSENGER, - destinationCaller - ); - return s_nonce++; - } - - function messageBodyVersion() external view returns (uint32) { - return i_messageBodyVersion; - } - - function localMessageTransmitter() external view returns (address) { - return i_transmitter; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol deleted file mode 100644 index dc9c644..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/interfaces/IMessageTransmitterWithRelay.sol +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2022, Circle Internet Financial Limited. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -pragma solidity ^0.8.0; - -import {IMessageTransmitter} from "../../../pools/USDC/IMessageTransmitter.sol"; - -// This follows https://github.com/circlefin/evm-cctp-contracts/blob/master/src/interfaces/IMessageTransmitter.sol -interface IMessageTransmitterWithRelay is IMessageTransmitter { - /** - * @notice Sends an outgoing message from the source domain. - * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. - * @param destinationDomain Domain of destination chain - * @param recipient Address of message recipient on destination domain as bytes32 - * @param messageBody Raw bytes content of message - * @return nonce reserved by message - */ - function sendMessage( - uint32 destinationDomain, - bytes32 recipient, - bytes calldata messageBody - ) external returns (uint64); - - /** - * @notice Sends an outgoing message from the source domain, with a specified caller on the - * destination domain. - * @dev Increment nonce, format the message, and emit `MessageSent` event with message information. - * WARNING: if the `destinationCaller` does not represent a valid address as bytes32, then it will not be possible - * to broadcast the message on the destination domain. This is an advanced feature, and the standard - * sendMessage() should be preferred for use cases where a specific destination caller is not required. - * @param destinationDomain Domain of destination chain - * @param recipient Address of message recipient on destination domain as bytes32 - * @param destinationCaller caller on the destination domain, as bytes32 - * @param messageBody Raw bytes content of message - * @return nonce reserved by message - */ - function sendMessageWithCaller( - uint32 destinationDomain, - bytes32 recipient, - bytes32 destinationCaller, - bytes calldata messageBody - ) external returns (uint64); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol deleted file mode 100644 index 6cbe7bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol +++ /dev/null @@ -1,68 +0,0 @@ -pragma solidity ^0.8.0; - -import {Client} from "../../../libraries/Client.sol"; - -import {TokenSetup} from "../../TokenSetup.t.sol"; -import {IRouterClient, MockCCIPRouter} from "../MockRouter.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -contract MockRouterTest is TokenSetup { - using SafeERC20 for IERC20; - - MockCCIPRouter public mockRouter; - - uint64 public constant mockChainSelector = 123456; - - Client.EVM2AnyMessage public message; - - function setUp() public override { - mockRouter = new MockCCIPRouter(); - - //Configure the Fee to 0.1 ether for native token fees - mockRouter.setFee(0.1 ether); - - deal(address(this), 100 ether); - - message.receiver = abi.encode(address(0x12345)); - message.data = abi.encode("Hello World"); - - s_sourceFeeToken = _deploySourceToken("sLINK", type(uint256).max, 18); - } - - function test_ccipSendWithInsufficientNativeTokens_Revert() public { - //Should revert because did not include sufficient eth to pay for fees - vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); - mockRouter.ccipSend(mockChainSelector, message); - } - - function test_ccipSendWithSufficientNativeFeeTokens_Success() public { - //ccipSend with sufficient native tokens for fees - mockRouter.ccipSend{value: 0.1 ether}(mockChainSelector, message); - } - - function test_ccipSendWithInvalidMsgValue_Revert() public { - message.feeToken = address(1); //Set to non native-token fees - - vm.expectRevert(IRouterClient.InvalidMsgValue.selector); - mockRouter.ccipSend{value: 0.1 ether}(mockChainSelector, message); - } - - function test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() public { - message.feeToken = s_sourceFeeToken; - - vm.expectRevert(bytes("ERC20: insufficient allowance")); - mockRouter.ccipSend(mockChainSelector, message); - } - - function test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() public { - message.feeToken = s_sourceFeeToken; - - vm.startPrank(OWNER, OWNER); - - IERC20(s_sourceFeeToken).safeApprove(address(mockRouter), type(uint256).max); - - mockRouter.ccipSend(mockChainSelector, message); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol deleted file mode 100644 index 2783608..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol +++ /dev/null @@ -1,1006 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {MultiOCR3Helper} from "../helpers/MultiOCR3Helper.sol"; -import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; - -import {Vm} from "forge-std/Vm.sol"; - -contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { - bytes32 internal s_configDigest1; - bytes32 internal s_configDigest2; - bytes32 internal s_configDigest3; - - function setUp() public virtual override { - super.setUp(); - - s_configDigest1 = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); - s_configDigest2 = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); - s_configDigest3 = _getBasicConfigDigest(2, s_emptySigners, s_validTransmitters); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](3); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: s_configDigest1, - F: 1, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 1, - configDigest: s_configDigest2, - F: 2, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - ocrConfigs[2] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 2, - configDigest: s_configDigest3, - F: 1, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_TransmitSigners_gas_Success() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - // F = 2, need 2 signatures - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(0, s_configDigest1, uint64(uint256(s_configDigest1))); - - vm.startPrank(s_validTransmitters[1]); - vm.resumeGasMetering(); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_TransmitWithoutSignatureVerification_gas_Success() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; - - s_multiOCR3.setTransmitOcrPluginType(2); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(2, s_configDigest3, uint64(uint256(s_configDigest3))); - - vm.startPrank(s_validTransmitters[0]); - vm.resumeGasMetering(); - s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); - } - - function test_Fuzz_TransmitSignersWithSignatures_Success(uint8 F, uint64 randomAddressOffset) public { - vm.pauseGasMetering(); - - F = uint8(bound(F, 1, 3)); - - // condition: signers.length > 3F - uint8 signersLength = 3 * F + 1; - address[] memory signers = new address[](signersLength); - address[] memory transmitters = new address[](signersLength); - uint256[] memory signerKeys = new uint256[](signersLength); - - // Force addresses to be unique (with a random offset for broader testing) - for (uint160 i = 0; i < signersLength; ++i) { - transmitters[i] = vm.addr(PRIVATE0 + randomAddressOffset + i); - // condition: non-zero oracle address - vm.assume(transmitters[i] != address(0)); - - // condition: non-repeating addresses (no clashes with transmitters) - signerKeys[i] = PRIVATE0 + randomAddressOffset + i + signersLength; - signers[i] = vm.addr(signerKeys[i]); - vm.assume(signers[i] != address(0)); - } - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 3, - configDigest: s_configDigest1, - F: F, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - s_multiOCR3.setOCR3Configs(ocrConfigs); - s_multiOCR3.setTransmitOcrPluginType(3); - - // Randomise picked transmitter with random offset - vm.startPrank(transmitters[randomAddressOffset % signersLength]); - - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - // condition: matches signature expectation for transmit - uint8 numSignatures = F + 1; - uint256[] memory pickedSignerKeys = new uint256[](numSignatures); - - // Randomise picked signers with random offset - for (uint256 i; i < numSignatures; ++i) { - pickedSignerKeys[i] = signerKeys[(i + randomAddressOffset) % numSignatures]; - } - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(pickedSignerKeys, REPORT, reportContext, numSignatures); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(3, s_configDigest1, uint64(uint256(s_configDigest1))); - - vm.resumeGasMetering(); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - // Reverts - function test_ForkedChain_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); - - s_multiOCR3.setTransmitOcrPluginType(0); - - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); - - vm.startPrank(s_validTransmitters[0]); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_ZeroSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), bytes32("")); - } - - function test_TooManySignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - // 1 signature too many - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 6); - - s_multiOCR3.setTransmitOcrPluginType(1); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_InsufficientSignatures_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - // Missing 1 signature for unique report - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 4); - - s_multiOCR3.setTransmitOcrPluginType(1); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.WrongNumberOfSignatures.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_ConfigDigestMismatch_Revert() public { - bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - - (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ConfigDigestMismatch.selector, s_configDigest1, configDigest)); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), rawVs); - } - - function test_SignatureOutOfRegistration_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](1); - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.SignaturesOutOfRegistration.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); - } - - function test_UnAuthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); - } - - function test_NonUniqueSignature_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); - - rs[1] = rs[0]; - ss[1] = ss[0]; - // Need to reset the rawVs to be valid - rawVs = bytes32(bytes1(vs[0] - 27)) | (bytes32(bytes1(vs[0] - 27)) >> 8); - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.NonUniqueSignatures.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_UnauthorizedSigner_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); - - rs[0] = s_configDigest1; - ss = rs; - - s_multiOCR3.setTransmitOcrPluginType(0); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.UnauthorizedSigner.selector); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); - } - - function test_UnconfiguredPlugin_Revert() public { - bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - - s_multiOCR3.setTransmitOcrPluginType(42); - - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); - } - - function test_TransmitWithLessCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - - s_multiOCR3.setTransmitOcrPluginType(0); - - // The transmit should fail, since we are trying to transmit without signatures when signatures are enabled - vm.startPrank(s_validTransmitters[1]); - - // report length + function selector + report length + abiencoded location of report value + report context words - uint256 receivedLength = REPORT.length + 4 + 5 * 32; - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.WrongMessageLength.selector, - // Expecting inclusion of signature constant length components - receivedLength + 5 * 32, - receivedLength - ) - ); - s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); - } - - function test_TransmitWithExtraCalldataArgs_Revert() public { - bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - - s_multiOCR3.setTransmitOcrPluginType(2); - - // The transmit should fail, since we are trying to transmit with signatures when signatures are disabled - vm.startPrank(s_validTransmitters[1]); - - // dynamic length + function selector + report length + abiencoded location of report value + report context words - // rawVs value, lengths of rs, ss, and start locations of rs & ss -> 5 words - uint256 receivedLength = REPORT.length + 4 + (5 * 32) + (5 * 32) + (2 * 32) + (2 * 32); - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.WrongMessageLength.selector, - // Expecting exclusion of signature constant length components and rs, ss words - receivedLength - (5 * 32) - (4 * 32), - receivedLength - ) - ); - s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); - } -} - -contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { - function test_SetConfigsZeroInput_Success() public { - vm.recordLogs(); - s_multiOCR3.setOCR3Configs(new MultiOCR3Base.OCRConfigArgs[](0)); - - // No logs emitted - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - } - - function test_SetConfigWithSigners_Success() public { - uint8 F = 2; - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), - F: F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - ocrConfigs[0].signers, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: uint8(ocrConfigs[0].signers.length), - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: s_validSigners, - transmitters: s_validTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - } - - function test_SetConfigWithSignersMismatchingTransmitters_Success() public { - uint8 F = 2; - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, s_validSigners, s_partialTransmitters), - F: F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_partialTransmitters - }); - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - ocrConfigs[0].signers, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: uint8(ocrConfigs[0].signers.length), - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: s_validSigners, - transmitters: s_partialTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - } - - function test_SetConfigWithoutSigners_Success() public { - uint8 F = 1; - address[] memory signers = new address[](0); - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, signers, s_validTransmitters), - F: F, - isSignatureVerificationEnabled: false, - signers: signers, - transmitters: s_validTransmitters - }); - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - ocrConfigs[0].signers, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: uint8(ocrConfigs[0].signers.length), - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: signers, - transmitters: s_validTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - } - - function test_SetConfigIgnoreSigners_Success() public { - uint8 F = 1; - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, new address[](0), s_validTransmitters), - F: F, - isSignatureVerificationEnabled: false, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - s_emptySigners, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: 0, - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - - // Verify no signer role is set - for (uint256 i = 0; i < s_validSigners.length; ++i) { - MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, s_validSigners[i]); - assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Unset)); - } - } - - function test_SetMultipleConfigs_Success() public { - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(1)); - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(2)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](3); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), - F: 2, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 1, - configDigest: _getBasicConfigDigest(1, s_validSigners, s_validTransmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - ocrConfigs[2] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 2, - configDigest: _getBasicConfigDigest(1, s_partialSigners, s_partialTransmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: s_partialSigners, - transmitters: s_partialTransmitters - }); - - for (uint256 i; i < ocrConfigs.length; ++i) { - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[i].ocrPluginType, - ocrConfigs[i].configDigest, - ocrConfigs[i].signers, - ocrConfigs[i].transmitters, - ocrConfigs[i].F - ); - - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[i].ocrPluginType); - } - s_multiOCR3.setOCR3Configs(ocrConfigs); - - for (uint256 i; i < ocrConfigs.length; ++i) { - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[i].configDigest, - F: ocrConfigs[i].F, - n: uint8(ocrConfigs[i].signers.length), - isSignatureVerificationEnabled: ocrConfigs[i].isSignatureVerificationEnabled - }), - signers: ocrConfigs[i].signers, - transmitters: ocrConfigs[i].transmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfigs[i].ocrPluginType), expectedConfig); - } - - // pluginType 3 remains unconfigured - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(3)); - } - - function test_Fuzz_SetConfig_Success(MultiOCR3Base.OCRConfigArgs memory ocrConfig, uint64 randomAddressOffset) public { - // condition: cannot assume max oracle count - vm.assume(ocrConfig.transmitters.length <= 255); - vm.assume(ocrConfig.signers.length <= 255); - // condition: at least one transmitter - vm.assume(ocrConfig.transmitters.length > 0); - // condition: number of transmitters does not exceed signers - vm.assume(ocrConfig.signers.length == 0 || ocrConfig.transmitters.length <= ocrConfig.signers.length); - - // condition: F > 0 - ocrConfig.F = uint8(bound(ocrConfig.F, 1, 3)); - - uint256 transmittersLength = ocrConfig.transmitters.length; - - // Force addresses to be unique (with a random offset for broader testing) - for (uint160 i = 0; i < transmittersLength; ++i) { - ocrConfig.transmitters[i] = vm.addr(PRIVATE0 + randomAddressOffset + i); - // condition: non-zero oracle address - vm.assume(ocrConfig.transmitters[i] != address(0)); - } - - if (ocrConfig.signers.length == 0) { - ocrConfig.isSignatureVerificationEnabled = false; - } else { - ocrConfig.isSignatureVerificationEnabled = true; - - // condition: number of signers > 3F - vm.assume(ocrConfig.signers.length > 3 * ocrConfig.F); - - uint256 signersLength = ocrConfig.signers.length; - - // Force addresses to be unique - continuing generation with an offset after the transmitter addresses - for (uint160 i = 0; i < signersLength; ++i) { - ocrConfig.signers[i] = vm.addr(PRIVATE0 + randomAddressOffset + i + transmittersLength); - // condition: non-zero oracle address - vm.assume(ocrConfig.signers[i] != address(0)); - } - } - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = ocrConfig; - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfig.ocrPluginType, ocrConfig.configDigest, ocrConfig.signers, ocrConfig.transmitters, ocrConfig.F - ); - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfig.ocrPluginType); - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfig.configDigest, - F: ocrConfig.F, - n: ocrConfig.isSignatureVerificationEnabled ? uint8(ocrConfig.signers.length) : 0, - isSignatureVerificationEnabled: ocrConfig.isSignatureVerificationEnabled - }), - signers: ocrConfig.signers, - transmitters: ocrConfig.transmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType), expectedConfig); - } - - function test_UpdateConfigTransmittersWithoutSigners_Success() public { - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, s_emptySigners, s_validTransmitters), - F: 1, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_multiOCR3.setOCR3Configs(ocrConfigs); - - address[] memory newTransmitters = s_partialSigners; - - ocrConfigs[0].F = 2; - ocrConfigs[0].configDigest = _getBasicConfigDigest(2, s_emptySigners, newTransmitters); - ocrConfigs[0].transmitters = newTransmitters; - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - ocrConfigs[0].signers, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: uint8(ocrConfigs[0].signers.length), - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: s_emptySigners, - transmitters: newTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - - // Verify oracle roles get correctly re-assigned - for (uint256 i; i < newTransmitters.length; ++i) { - MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, newTransmitters[i]); - assertEq(transmitterOracle.index, i); - assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Transmitter)); - } - - // Verify old transmitters get correctly unset - for (uint256 i = newTransmitters.length; i < s_validTransmitters.length; ++i) { - MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, s_validTransmitters[i]); - assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Unset)); - } - } - - function test_UpdateConfigSigners_Success() public { - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(2, s_validSigners, s_validTransmitters), - F: 2, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - s_multiOCR3.setOCR3Configs(ocrConfigs); - - address[] memory newSigners = s_partialTransmitters; - address[] memory newTransmitters = s_partialSigners; - - ocrConfigs[0].F = 1; - ocrConfigs[0].configDigest = _getBasicConfigDigest(1, newSigners, newTransmitters); - ocrConfigs[0].signers = newSigners; - ocrConfigs[0].transmitters = newTransmitters; - - vm.expectEmit(); - emit MultiOCR3Base.ConfigSet( - ocrConfigs[0].ocrPluginType, - ocrConfigs[0].configDigest, - ocrConfigs[0].signers, - ocrConfigs[0].transmitters, - ocrConfigs[0].F - ); - vm.expectEmit(); - emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: uint8(ocrConfigs[0].signers.length), - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: newSigners, - transmitters: newTransmitters - }); - _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); - - // Verify oracle roles get correctly re-assigned - for (uint256 i; i < newSigners.length; ++i) { - MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, newSigners[i]); - assertEq(signerOracle.index, i); - assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Signer)); - - MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, newTransmitters[i]); - assertEq(transmitterOracle.index, i); - assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Transmitter)); - } - - // Verify old signers / transmitters get correctly unset - for (uint256 i = newSigners.length; i < s_validSigners.length; ++i) { - MultiOCR3Base.Oracle memory signerOracle = s_multiOCR3.getOracle(0, s_validSigners[i]); - assertEq(uint8(signerOracle.role), uint8(MultiOCR3Base.Role.Unset)); - - MultiOCR3Base.Oracle memory transmitterOracle = s_multiOCR3.getOracle(0, s_validTransmitters[i]); - assertEq(uint8(transmitterOracle.role), uint8(MultiOCR3Base.Role.Unset)); - } - } - - // Reverts - - function test_RepeatTransmitterAddress_Revert() public { - address[] memory signers = s_validSigners; - address[] memory transmitters = s_validTransmitters; - transmitters[0] = signers[0]; - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, signers, transmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_RepeatSignerAddress_Revert() public { - address[] memory signers = s_validSigners; - address[] memory transmitters = s_validTransmitters; - signers[1] = signers[0]; - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, signers, transmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_SignerCannotBeZeroAddress_Revert() public { - uint8 F = 1; - address[] memory signers = new address[](3 * F + 1); - address[] memory transmitters = new address[](3 * F + 1); - for (uint160 i = 0; i < 3 * F + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - signers[0] = address(0); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, signers, transmitters), - F: F, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert(MultiOCR3Base.OracleCannotBeZeroAddress.selector); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_TransmitterCannotBeZeroAddress_Revert() public { - uint8 F = 1; - address[] memory signers = new address[](3 * F + 1); - address[] memory transmitters = new address[](3 * F + 1); - for (uint160 i = 0; i < 3 * F + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - transmitters[0] = address(0); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, signers, transmitters), - F: F, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert(MultiOCR3Base.OracleCannotBeZeroAddress.selector); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_StaticConfigChange_Revert() public { - uint8 F = 1; - - _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(F, s_validSigners, s_validTransmitters), - F: F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - s_multiOCR3.setOCR3Configs(ocrConfigs); - - // signature verification cannot change - ocrConfigs[0].isSignatureVerificationEnabled = false; - vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.StaticConfigCannotBeChanged.selector, 0)); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_FTooHigh_Revert() public { - address[] memory signers = new address[](0); - address[] memory transmitters = new address[](1); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, signers, transmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert( - abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.F_TOO_HIGH) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_FMustBePositive_Revert() public { - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(0, s_validSigners, s_validTransmitters), - F: 0, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.F_MUST_BE_POSITIVE - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_NoTransmitters_Revert() public { - address[] memory signers = new address[](0); - address[] memory transmitters = new address[](0); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(10, signers, transmitters), - F: 1, - isSignatureVerificationEnabled: false, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert( - abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.NO_TRANSMITTERS) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_TooManyTransmitters_Revert() public { - address[] memory signers = new address[](0); - address[] memory transmitters = new address[](257); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(10, signers, transmitters), - F: 10, - isSignatureVerificationEnabled: false, - signers: signers, - transmitters: transmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_TooManySigners_Revert() public { - address[] memory signers = new address[](257); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, signers, s_validTransmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: signers, - transmitters: s_validTransmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_SIGNERS - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } - - function test_MoreTransmittersThanSigners_Revert() public { - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: 0, - configDigest: _getBasicConfigDigest(1, s_validSigners, s_partialTransmitters), - F: 1, - isSignatureVerificationEnabled: true, - signers: s_partialSigners, - transmitters: s_validTransmitters - }); - - vm.expectRevert( - abi.encodeWithSelector( - MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS - ) - ); - s_multiOCR3.setOCR3Configs(ocrConfigs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol deleted file mode 100644 index 9cfddf0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/ocr/MultiOCR3BaseSetup.t.sol +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {MultiOCR3Helper} from "../helpers/MultiOCR3Helper.sol"; - -contract MultiOCR3BaseSetup is BaseTest { - // Signer private keys used for these test - uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - - address[] internal s_validSigners; - address[] internal s_validTransmitters; - uint256[] internal s_validSignerKeys; - - address[] internal s_partialSigners; - address[] internal s_partialTransmitters; - uint256[] internal s_partialSignerKeys; - - address[] internal s_emptySigners; - - bytes internal constant REPORT = abi.encode("testReport"); - MultiOCR3Helper internal s_multiOCR3; - - function setUp() public virtual override { - BaseTest.setUp(); - - uint160 numSigners = 7; - s_validSignerKeys = new uint256[](numSigners); - s_validSigners = new address[](numSigners); - s_validTransmitters = new address[](numSigners); - - for (uint160 i; i < numSigners; ++i) { - s_validTransmitters[i] = address(4 + i); - s_validSignerKeys[i] = PRIVATE0 + i; - s_validSigners[i] = vm.addr(s_validSignerKeys[i]); - } - - s_partialSigners = new address[](4); - s_partialSignerKeys = new uint256[](4); - s_partialTransmitters = new address[](4); - for (uint256 i; i < s_partialSigners.length; ++i) { - s_partialSigners[i] = s_validSigners[i]; - s_partialSignerKeys[i] = s_validSignerKeys[i]; - s_partialTransmitters[i] = s_validTransmitters[i]; - } - - s_emptySigners = new address[](0); - - s_multiOCR3 = new MultiOCR3Helper(); - } - - /// @dev returns a mock config digest with config digest computation logic similar to OCR2Base - function _getBasicConfigDigest( - uint8 F, - address[] memory signers, - address[] memory transmitters - ) internal view returns (bytes32) { - bytes memory configBytes = abi.encode(""); - uint256 configVersion = 1; - - uint256 h = uint256( - keccak256( - abi.encode( - block.chainid, address(s_multiOCR3), signers, transmitters, F, configBytes, configVersion, configBytes - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - function _assertOCRConfigEquality( - MultiOCR3Base.OCRConfig memory configA, - MultiOCR3Base.OCRConfig memory configB - ) internal pure { - vm.assertEq(configA.configInfo.configDigest, configB.configInfo.configDigest); - vm.assertEq(configA.configInfo.F, configB.configInfo.F); - vm.assertEq(configA.configInfo.n, configB.configInfo.n); - vm.assertEq(configA.configInfo.isSignatureVerificationEnabled, configB.configInfo.isSignatureVerificationEnabled); - - vm.assertEq(configA.signers, configB.signers); - vm.assertEq(configA.transmitters, configB.transmitters); - } - - function _assertOCRConfigUnconfigured( - MultiOCR3Base.OCRConfig memory config - ) internal pure { - assertEq(config.configInfo.configDigest, bytes32("")); - assertEq(config.signers.length, 0); - assertEq(config.transmitters.length, 0); - } - - function _getSignaturesForDigest( - uint256[] memory signerPrivateKeys, - bytes memory report, - bytes32[3] memory reportContext, - uint8 signatureCount - ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { - rs = new bytes32[](signatureCount); - ss = new bytes32[](signatureCount); - vs = new uint8[](signatureCount); - - bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - // Calculate signatures - for (uint256 i; i < signatureCount; ++i) { - (vs[i], rs[i], ss[i]) = vm.sign(signerPrivateKeys[i], reportDigest); - rawVs = rawVs | (bytes32(bytes1(vs[i] - 27)) >> (8 * i)); - } - - return (rs, ss, vs, rawVs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol deleted file mode 100644 index c458b67..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ /dev/null @@ -1,3797 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; -import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; -import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; - -import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; -import {FeeQuoter} from "../../FeeQuoter.sol"; -import {NonceManager} from "../../NonceManager.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {OffRamp} from "../../offRamp/OffRamp.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {OffRampHelper} from "../helpers/OffRampHelper.sol"; -import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; -import {ReentrancyAbuserMultiRamp} from "../helpers/receivers/ReentrancyAbuserMultiRamp.sol"; -import {OffRampSetup} from "./OffRampSetup.t.sol"; -import {Vm} from "forge-std/Vm.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract OffRamp_constructor is OffRampSetup { - function test_Constructor_Success() public { - OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }); - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, - onRamp: ON_RAMP_ADDRESS_2, - isEnabled: true - }); - - OffRamp.SourceChainConfig memory expectedSourceChainConfig1 = OffRamp.SourceChainConfig({ - router: s_destRouter, - isEnabled: true, - minSeqNr: 1, - onRamp: sourceChainConfigs[0].onRamp - }); - - OffRamp.SourceChainConfig memory expectedSourceChainConfig2 = OffRamp.SourceChainConfig({ - router: s_destRouter, - isEnabled: true, - minSeqNr: 1, - onRamp: sourceChainConfigs[1].onRamp - }); - - uint64[] memory expectedSourceChainSelectors = new uint64[](2); - expectedSourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - expectedSourceChainSelectors[1] = SOURCE_CHAIN_SELECTOR_1 + 1; - - vm.expectEmit(); - emit OffRamp.StaticConfigSet(staticConfig); - - vm.expectEmit(); - emit OffRamp.DynamicConfigSet(dynamicConfig); - - vm.expectEmit(); - emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig1); - - vm.expectEmit(); - emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1 + 1); - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1 + 1, expectedSourceChainConfig2); - - s_offRamp = new OffRampHelper(staticConfig, dynamicConfig, sourceChainConfigs); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - - s_offRamp.setOCR3Configs(ocrConfigs); - - // Static config - OffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); - assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(address(staticConfig.rmnRemote), address(gotStaticConfig.rmnRemote)); - assertEq(staticConfig.tokenAdminRegistry, gotStaticConfig.tokenAdminRegistry); - - // Dynamic config - OffRamp.DynamicConfig memory gotDynamicConfig = s_offRamp.getDynamicConfig(); - _assertSameConfig(dynamicConfig, gotDynamicConfig); - - // OCR Config - MultiOCR3Base.OCRConfig memory expectedOCRConfig = MultiOCR3Base.OCRConfig({ - configInfo: MultiOCR3Base.ConfigInfo({ - configDigest: ocrConfigs[0].configDigest, - F: ocrConfigs[0].F, - n: 0, - isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled - }), - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - MultiOCR3Base.OCRConfig memory gotOCRConfig = s_offRamp.latestConfigDetails(uint8(Internal.OCRPluginType.Execution)); - _assertOCRConfigEquality(expectedOCRConfig, gotOCRConfig); - - (uint64[] memory actualSourceChainSelectors, OffRamp.SourceChainConfig[] memory actualSourceChainConfigs) = - s_offRamp.getAllSourceChainConfigs(); - - _assertSourceChainConfigEquality(actualSourceChainConfigs[0], expectedSourceChainConfig1); - _assertSourceChainConfigEquality(actualSourceChainConfigs[1], expectedSourceChainConfig2); - - // OffRamp initial values - assertEq("OffRamp 1.6.0-dev", s_offRamp.typeAndVersion()); - assertEq(OWNER, s_offRamp.owner()); - assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - - // assertion for source chain selector - for (uint256 i = 0; i < expectedSourceChainSelectors.length; i++) { - assertEq(expectedSourceChainSelectors[i], actualSourceChainSelectors[i]); - } - } - - // Revert - function test_ZeroOnRampAddress_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: new bytes(0), - isEnabled: true - }); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } - - function test_SourceChainSelector_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: 0, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } - - function test_ZeroRMNRemote_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: IRMNRemote(ZERO_ADDRESS), - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } - - function test_ZeroChainSelector_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: 0, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } - - function test_ZeroTokenAdminRegistry_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: ZERO_ADDRESS, - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } - - function test_ZeroNonceManager_Revert() public { - uint64[] memory sourceChainSelectors = new uint64[](1); - sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: ZERO_ADDRESS - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - } -} - -contract OffRamp_setDynamicConfig is OffRampSetup { - function test_SetDynamicConfig_Success() public { - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - - vm.expectEmit(); - emit OffRamp.DynamicConfigSet(dynamicConfig); - - s_offRamp.setDynamicConfig(dynamicConfig); - - OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); - _assertSameConfig(dynamicConfig, newConfig); - } - - function test_SetDynamicConfigWithInterceptor_Success() public { - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); - - vm.expectEmit(); - emit OffRamp.DynamicConfigSet(dynamicConfig); - - s_offRamp.setDynamicConfig(dynamicConfig); - - OffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); - _assertSameConfig(dynamicConfig, newConfig); - } - - // Reverts - - function test_NonOwner_Revert() public { - vm.startPrank(STRANGER); - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - - vm.expectRevert("Only callable by owner"); - - s_offRamp.setDynamicConfig(dynamicConfig); - } - - function test_FeeQuoterZeroAddress_Revert() public { - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(ZERO_ADDRESS); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - - s_offRamp.setDynamicConfig(dynamicConfig); - } -} - -contract OffRamp_ccipReceive is OffRampSetup { - // Reverts - - function test_Reverts() public { - Client.Any2EVMMessage memory message = - _convertToGeneralMessage(_generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1)); - vm.expectRevert(); - s_offRamp.ccipReceive(message); - } -} - -contract OffRamp_executeSingleReport is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); - } - - function test_SingleMessageNoTokens_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - messages[0].header.nonce++; - messages[0].header.sequenceNumber++; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); - } - - function test_SingleMessageNoTokensUnordered_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].header.nonce = 0; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - // Nonce never increments on unordered messages. - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), - nonceBefore, - "nonce must remain unchanged on unordered messages" - ); - - messages[0].header.sequenceNumber++; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - // Nonce never increments on unordered messages. - nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertEq( - s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), - nonceBefore, - "nonce must remain unchanged on unordered messages" - ); - } - - function test_SingleMessageNoTokensOtherChain_Success() public { - Internal.Any2EVMRampMessage[] memory messagesChain1 = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new OffRamp.GasLimitOverride[](0) - ); - - uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender); - assertGt(nonceChain1, 0); - - Internal.Any2EVMRampMessage[] memory messagesChain2 = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new OffRamp.GasLimitOverride[](0) - ); - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); - - // Other chain's nonce is unaffected - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender), nonceChain1); - } - - function test_ReceiverError_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - bytes memory realError1 = new bytes(2); - realError1[0] = 0xbe; - realError1[1] = 0xef; - s_reverting_receiver.setErr(realError1); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - // Nonce should increment on non-strict - assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - OffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) - ) - ); - assertEq(uint64(1), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - } - - function test_SkippedIncorrectNonce_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - messages[0].header.nonce++; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce( - messages[0].header.sourceChainSelector, messages[0].header.nonce, messages[0].sender - ); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - function test_SkippedIncorrectNonceStillExecutes_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - messages[1].header.nonce++; - messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test__execute_SkippedAlreadyExecutedMessage_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - vm.expectEmit(); - emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].header.nonce = 0; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - vm.expectEmit(); - emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - // Send a message to a contract that does not implement the CCIPReceiver interface - // This should execute successfully. - function test_SingleMessageToNonCCIPReceiver_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); - messages[0].receiver = address(newReceiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_SingleMessagesNoTokensSuccess_gas() public { - vm.pauseGasMetering(); - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.resumeGasMetering(); - vm.recordLogs(); - s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_TwoMessagesWithTokensSuccess_gas() public { - vm.pauseGasMetering(); - Internal.Any2EVMRampMessage[] memory messages = - _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - // Set message 1 to use another receiver to simulate more fair gas costs - messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.resumeGasMetering(); - vm.recordLogs(); - s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[1].header.sequenceNumber, - messages[1].header.messageId, - _hashMessage(messages[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_TwoMessagesWithTokensAndGE_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - // Set message 1 to use another receiver to simulate more fair gas costs - messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - - assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) - ); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[1].header.sequenceNumber, - messages[1].header.messageId, - _hashMessage(messages[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertEq(uint64(2), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); - } - - function test_Fuzz_InterleavingOrderedAndUnorderedMessages_Success( - bool[7] memory orderings - ) public { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](orderings.length); - // number of tokens needs to be capped otherwise we hit UnsupportedNumberOfTokens. - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](3); - for (uint256 i = 0; i < 3; ++i) { - tokenAmounts[i].token = s_sourceTokens[i % s_sourceTokens.length]; - tokenAmounts[i].amount = 1e18; - } - uint64 expectedNonce = 0; - - for (uint256 i = 0; i < orderings.length; ++i) { - messages[i] = - _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, uint64(i + 1), tokenAmounts, !orderings[i]); - if (orderings[i]) { - messages[i].header.nonce = ++expectedNonce; - } - messages[i].header.messageId = _hashMessage(messages[i], ON_RAMP_ADDRESS_1); - } - - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)); - assertEq(uint64(0), nonceBefore, "nonce before exec should be 0"); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) - ); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - // all executions should succeed. - for (uint256 i = 0; i < orderings.length; ++i) { - assertEq( - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber)), - uint256(Internal.MessageExecutionState.SUCCESS) - ); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[i].header.sequenceNumber, - messages[i].header.messageId, - _hashMessage(messages[i], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - assertEq( - nonceBefore + expectedNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)) - ); - } - - function test_InvalidSourcePoolAddress_Success() public { - address fakePoolAddress = address(0x0000000000333333); - - Internal.Any2EVMRampMessage[] memory messages = - _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].tokenAmounts[0].sourcePoolAddress = abi.encode(fakePoolAddress); - - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - OffRamp.TokenHandlingError.selector, - abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) - ) - ); - } - - function test_WithCurseOnAnotherSourceChain_Success() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[](0) - ); - } - - function test_Unhealthy_Success() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - - vm.expectEmit(); - emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[](0) - ); - - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[](0) - ); - - _assertNoEmit(OffRamp.SkippedReportExecution.selector); - } - - // Reverts - - function test_MismatchingDestChainSelector_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; - - Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert( - abi.encodeWithSelector(OffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector) - ); - s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); - } - - function test_UnhealthySingleChainCurse_Revert() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - vm.expectEmit(); - emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[](0) - ); - vm.recordLogs(); - // Uncurse should succeed - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[](0) - ); - _assertNoEmit(OffRamp.SkippedReportExecution.selector); - } - - function test_UnexpectedTokenData_Revert() public { - Internal.ExecutionReport memory report = _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ); - report.offchainTokenData = new bytes[][](report.messages.length + 1); - - vm.expectRevert(OffRamp.UnexpectedTokenData.selector); - - s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); - } - - function test_EmptyReport_Revert() public { - vm.expectRevert(OffRamp.EmptyReport.selector); - s_offRamp.executeSingleReport( - Internal.ExecutionReport({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - proofs: new bytes32[](0), - proofFlagBits: 0, - messages: new Internal.Any2EVMRampMessage[](0), - offchainTokenData: new bytes[][](0) - }), - new OffRamp.GasLimitOverride[](0) - ); - } - - function test_RootNotCommitted_Revert() public { - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); - vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) - ); - } - - function test_ManualExecutionNotYetEnabled_Revert() public { - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, BLOCK_TIME); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1)); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) - ); - } - - function test_NonExistingSourceChain_Revert() public { - uint64 newSourceChainSelector = SOURCE_CHAIN_SELECTOR_1 + 1; - bytes memory newOnRamp = abi.encode(ON_RAMP_ADDRESS, 1); - - Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); - s_offRamp.executeSingleReport( - _generateReportFromMessages(newSourceChainSelector, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - function test_DisabledSourceChain_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - function test_TokenDataMismatch_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - report.offchainTokenData[0] = new bytes[](messages[0].tokenAmounts.length + 1); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber - ) - ); - s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); - } - - function test_RouterYULCall_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - // gas limit too high, Router's external call should revert - messages[0].gasLimit = 1e36; - messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.recordLogs(); - s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) - ); - } - - function test_RetryFailedMessageWithoutManualExecution_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - bytes memory realError1 = new bytes(2); - realError1[0] = 0xbe; - realError1[1] = 0xef; - s_reverting_receiver.setErr(realError1); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - OffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1) - ) - ); - - // The second time should skip the msg - vm.expectEmit(); - emit OffRamp.AlreadyAttempted(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - } - - function _constructCommitReport( - bytes32 merkleRoot - ) internal view returns (OffRamp.CommitReport memory) { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), - minSeqNr: 1, - maxSeqNr: 2, - merkleRoot: merkleRoot - }); - - return OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - } -} - -contract OffRamp_executeSingleMessage is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - vm.startPrank(address(s_offRamp)); - } - - function test_executeSingleMessage_NoTokens_Success() public { - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_executeSingleMessage_WithTokens_Success() public { - Internal.Any2EVMRampMessage memory message = - _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; - bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); - - vm.expectCall( - s_destPoolByToken[s_destTokens[0]], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: message.sender, - receiver: message.receiver, - amount: message.tokenAmounts[0].amount, - localToken: message.tokenAmounts[0].destTokenAddress, - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: message.tokenAmounts[0].sourcePoolAddress, - sourcePoolData: message.tokenAmounts[0].extraData, - offchainTokenData: offchainTokenData[0] - }) - ) - ); - - s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); - } - - function test_executeSingleMessage_WithVInterception_Success() public { - vm.stopPrank(); - vm.startPrank(OWNER); - _enableInboundMessageInterceptor(); - vm.startPrank(address(s_offRamp)); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_NonContract_Success() public { - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_NonContractWithTokens_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - vm.expectEmit(); - emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); - vm.expectEmit(); - emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - // Reverts - - function test_TokenHandlingError_Revert() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - bytes memory errorMessage = "Random token pool issue"; - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_ZeroGasDONExecution_Revert() public { - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - message.gasLimit = 0; - - vm.expectRevert(abi.encodeWithSelector(OffRamp.ReceiverError.selector, "")); - - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_MessageSender_Revert() public { - vm.stopPrank(); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - vm.expectRevert(OffRamp.CanOnlySelfCall.selector); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_executeSingleMessage_WithFailingValidation_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - _enableInboundMessageInterceptor(); - vm.startPrank(address(s_offRamp)); - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); - vm.expectRevert( - abi.encodeWithSelector( - IMessageInterceptor.MessageValidationError.selector, - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ) - ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } - - function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - _enableInboundMessageInterceptor(); - vm.startPrank(address(s_offRamp)); - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - - // Setup the receiver to a non-CCIP Receiver, which will skip the Router call (but should still perform the validation) - MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); - message.receiver = address(newReceiver); - message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); - - s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); - vm.expectRevert( - abi.encodeWithSelector( - IMessageInterceptor.MessageValidationError.selector, - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ) - ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - } -} - -contract OffRamp_batchExecute is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); - } - - function test_SingleReport_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - - vm.recordLogs(); - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); - } - - function test_MultipleReportsSameChain_Success() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - - uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); - vm.recordLogs(); - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - assertExecutionStateChangedEventLogs( - logs, - messages1[0].header.sourceChainSelector, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages1[1].header.sourceChainSelector, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages2[0].header.sourceChainSelector, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); - } - - function test_MultipleReportsDifferentChains_Success() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - vm.recordLogs(); - - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - assertExecutionStateChangedEventLogs( - logs, - messages1[0].header.sourceChainSelector, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages1[1].header.sourceChainSelector, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages2[0].header.sourceChainSelector, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - _hashMessage(messages2[0], ON_RAMP_ADDRESS_3), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); - uint64 nonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messages2[0].sender); - - assertTrue(nonceChain1 != nonceChain3); - assertGt(nonceChain1, 0); - assertGt(nonceChain3, 0); - } - - function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - vm.recordLogs(); - - vm.expectEmit(); - emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); - - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - for (uint256 i = 0; i < logs.length; ++i) { - if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { - uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); - uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); - bytes32 logMessageId = bytes32(logs[i].topics[3]); - (bytes32 logMessageHash, uint8 logState,,) = abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); - assertEq(logMessageId, messages2[0].header.messageId); - assertEq(logSourceChainSelector, messages2[0].header.sourceChainSelector); - assertEq(logSequenceNumber, messages2[0].header.sequenceNumber); - assertEq(logMessageId, messages2[0].header.messageId); - assertEq(logMessageHash, _hashMessage(messages2[0], ON_RAMP_ADDRESS_3)); - assertEq(logState, uint8(Internal.MessageExecutionState.SUCCESS)); - } - } - } - - function test_MultipleReportsSkipDuplicate_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectEmit(); - emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - - vm.recordLogs(); - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); - assertExecutionStateChangedEventLogs( - messages[0].header.sourceChainSelector, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_Unhealthy_Success() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - vm.expectEmit(); - emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); - s_offRamp.batchExecute( - _generateBatchReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[][](1) - ); - - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); - - vm.recordLogs(); - s_offRamp.batchExecute( - _generateBatchReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new OffRamp.GasLimitOverride[][](1) - ); - - _assertNoEmit(OffRamp.SkippedReportExecution.selector); - } - - // Reverts - function test_ZeroReports_Revert() public { - vm.expectRevert(OffRamp.EmptyReport.selector); - s_offRamp.batchExecute(new Internal.ExecutionReport[](0), new OffRamp.GasLimitOverride[][](1)); - } - - function test_OutOfBoundsGasLimitsAccess_Revert() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - - vm.expectRevert(); - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](1)); - } -} - -contract OffRamp_manuallyExecute is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); - } - - function test_manuallyExecute_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - - s_reverting_receiver.setRevert(false); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](messages.length); - - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_manuallyExecute_WithGasOverride_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - - s_reverting_receiver.setRevert(false); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - assertEq( - messages[0].header.nonce - 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) - ); - - s_reverting_receiver.setRevert(true); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") - ) - ); - - assertEq( - messages[0].header.nonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) - ); - } - - function test_manuallyExecute_WithMultiReportGasOverride_Success() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); - - for (uint64 i = 0; i < 3; ++i) { - messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); - messages1[i].receiver = address(s_reverting_receiver); - messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); - } - - for (uint64 i = 0; i < 2; ++i) { - messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); - messages2[i].receiver = address(s_reverting_receiver); - messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); - } - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); - - s_reverting_receiver.setRevert(false); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); - gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); - - for (uint256 i = 0; i < 3; ++i) { - gasLimitOverrides[0][i].receiverExecutionGasLimit += 1; - } - - for (uint256 i = 0; i < 2; ++i) { - gasLimitOverrides[1][i].receiverExecutionGasLimit += 1; - } - - vm.recordLogs(); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - for (uint256 j = 0; j < 3; ++j) { - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages1[j].header.sequenceNumber, - messages1[j].header.messageId, - _hashMessage(messages1[j], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - for (uint256 k = 0; k < 2; ++k) { - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_3, - messages2[k].header.sequenceNumber, - messages2[k].header.messageId, - _hashMessage(messages2[k], ON_RAMP_ADDRESS_3), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - } - - function test_manuallyExecute_WithPartialMessages_Success() public { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); - - for (uint64 i = 0; i < 3; ++i) { - messages[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); - } - - messages[1].receiver = address(s_reverting_receiver); - messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[1].header.sequenceNumber, - messages[1].header.messageId, - _hashMessage(messages[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - OffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) - ) - ); - - assertExecutionStateChangedEventLogs( - logs, - SOURCE_CHAIN_SELECTOR_1, - messages[2].header.sequenceNumber, - messages[2].header.messageId, - _hashMessage(messages[2], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - s_reverting_receiver.setRevert(false); - - // Only the 2nd message reverted - Internal.Any2EVMRampMessage[] memory newMessages = new Internal.Any2EVMRampMessage[](1); - newMessages[0] = messages[1]; - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(newMessages); - gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; - - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, newMessages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_manuallyExecute_LowGasLimit_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].gasLimit = 1; - messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") - ); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); - gasLimitOverrides[0][0].receiverExecutionGasLimit = 100_000; - - vm.expectEmit(); - emit ConformingReceiver.MessageReceived(); - - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - // Reverts - - function test_manuallyExecute_ForkedChain_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - } - - function test_ManualExecGasLimitMismatchSingleReport_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); - messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - // No overrides for report - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); - - // No messages - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - // 1 message missing - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - // 1 message in excess - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - } - - function test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](1)); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - // 2nd report empty - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](2); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - // 1st report empty - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](0); - gasLimitOverrides[1] = new OffRamp.GasLimitOverride[](1); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - - // 1st report oversized - gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); - - vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - } - - function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0].receiverExecutionGasLimit--; - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.InvalidManualExecutionGasLimit.selector, - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.messageId, - gasLimitOverrides[0][0].receiverExecutionGasLimit - ) - ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - } - - function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 1000; - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); - messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - // empty tokenGasOverride array provided - vm.expectRevert( - abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) - ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - - //trying with excesss elements tokenGasOverride array provided - gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](3); - vm.expectRevert( - abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) - ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - } - - function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 1000; - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); - messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - uint32[] memory tokenGasOverrides = new uint32[](2); - tokenGasOverrides[0] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD; - tokenGasOverrides[1] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD - 1; //invalid token gas override value - gasLimitOverrides[0][0].tokenGasOverrides = tokenGasOverrides; - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.InvalidManualExecutionTokenGasOverride.selector, - messages[0].header.messageId, - 1, - DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - tokenGasOverrides[1] - ) - ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - } - - function test_manuallyExecute_FailedTx_Revert() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - s_offRamp.batchExecute( - _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) - ); - - s_reverting_receiver.setRevert(true); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.ExecutionError.selector, - messages[0].header.messageId, - abi.encodeWithSelector( - OffRamp.ReceiverError.selector, - abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, bytes("")) - ) - ) - ); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - } - - function test_manuallyExecute_ReentrancyFails_Success() public { - uint256 tokenAmount = 1e9; - IERC20 tokenToAbuse = IERC20(s_destFeeToken); - - // This needs to be deployed before the source chain message is sent - // because we need the address for the receiver. - ReentrancyAbuserMultiRamp receiver = new ReentrancyAbuserMultiRamp(address(s_destRouter), s_offRamp); - uint256 balancePre = tokenToAbuse.balanceOf(address(receiver)); - - // For this test any message will be flagged as correct by the - // commitStore. In a real scenario the abuser would have to actually - // send the message that they want to replay. - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].tokenAmounts = new Internal.Any2EVMTokenTransfer[](1); - messages[0].tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), - destTokenAddress: s_destTokenBySourceToken[s_sourceFeeToken], - extraData: "", - amount: tokenAmount, - destGasAmount: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS - }); - - messages[0].receiver = address(receiver); - - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - // sets the report to be repeated on the ReentrancyAbuser to be able to replay - receiver.setPayload(report); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](messages[0].tokenAmounts.length); - - // The first entry should be fine and triggers the second entry which is skipped. Due to the reentrancy - // the second completes first, so we expect the skip event before the success event. - vm.expectEmit(); - emit OffRamp.SkippedAlreadyExecutedMessage( - messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber - ); - - vm.recordLogs(); - s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - // Since the tx failed we don't release the tokens - assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); - } - - function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); - - for (uint64 i = 0; i < 3; ++i) { - messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); - messages1[i].receiver = address(s_reverting_receiver); - messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); - } - - for (uint64 i = 0; i < 2; ++i) { - messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); - messages2[i].receiver = address(s_reverting_receiver); - messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); - } - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); - gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); - - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_3, true); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_3)); - - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - } - - function test_manuallyExecute_SourceChainSelectorMismatch_Revert() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](1); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - - OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); - gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); - gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.SourceChainSelectorMismatch.selector, SOURCE_CHAIN_SELECTOR_3, SOURCE_CHAIN_SELECTOR_1 - ) - ); - s_offRamp.manuallyExecute(reports, gasLimitOverrides); - } -} - -contract OffRamp_execute is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - } - - // Asserts that execute completes - function test_SingleReport_Success() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - vm.recordLogs(); - - _execute(reports); - - assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_MultipleReports_Success() public { - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - vm.recordLogs(); - _execute(reports); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - assertExecutionStateChangedEventLogs( - logs, - messages1[0].header.sourceChainSelector, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages1[1].header.sourceChainSelector, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages2[0].header.sourceChainSelector, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_LargeBatch_Success() public { - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](10); - for (uint64 i = 0; i < reports.length; ++i) { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); - messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1 + i * 3); - messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2 + i * 3); - messages[2] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3 + i * 3); - - reports[i] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - } - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - vm.recordLogs(); - _execute(reports); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - for (uint64 i = 0; i < reports.length; ++i) { - for (uint64 j = 0; j < reports[i].messages.length; ++j) { - assertExecutionStateChangedEventLogs( - logs, - reports[i].messages[j].header.sourceChainSelector, - reports[i].messages[j].header.sequenceNumber, - reports[i].messages[j].header.messageId, - _hashMessage(reports[i].messages[j], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - } - } - - function test_MultipleReportsWithPartialValidationFailures_Success() public { - _enableInboundMessageInterceptor(); - - Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - - messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); - messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); - - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](2); - reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); - reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - - s_inboundMessageInterceptor.setMessageIdValidationState(messages1[0].header.messageId, true); - s_inboundMessageInterceptor.setMessageIdValidationState(messages2[0].header.messageId, true); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted( - uint8(Internal.OCRPluginType.Execution), s_configDigestExec, uint64(uint256(s_configDigestExec)) - ); - - vm.recordLogs(); - _execute(reports); - - Vm.Log[] memory logs = vm.getRecordedLogs(); - - assertExecutionStateChangedEventLogs( - logs, - messages1[0].header.sourceChainSelector, - messages1[0].header.sequenceNumber, - messages1[0].header.messageId, - _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - IMessageInterceptor.MessageValidationError.selector, - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ) - ); - - assertExecutionStateChangedEventLogs( - logs, - messages1[1].header.sourceChainSelector, - messages1[1].header.sequenceNumber, - messages1[1].header.messageId, - _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertExecutionStateChangedEventLogs( - logs, - messages2[0].header.sourceChainSelector, - messages2[0].header.sequenceNumber, - messages2[0].header.messageId, - _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.FAILURE, - abi.encodeWithSelector( - IMessageInterceptor.MessageValidationError.selector, - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ) - ); - } - - // Reverts - - function test_UnauthorizedTransmitter_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_offRamp.execute(reportContext, abi.encode(reports)); - } - - function test_NoConfig_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_offRamp.execute(reportContext, abi.encode(reports)); - } - - function test_NoConfigWithOtherConfigPresent_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - bytes32[3] memory reportContext = [bytes32(""), s_configDigestExec, s_configDigestExec]; - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_offRamp.execute(reportContext, abi.encode(reports)); - } - - function test_WrongConfigWithSigners_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - - s_configDigestExec = _getBasicConfigDigest(1, s_validSigners, s_validTransmitters); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.expectRevert(); - _execute(reports); - } - - function test_ZeroReports_Revert() public { - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](0); - - vm.expectRevert(OffRamp.EmptyReport.selector); - _execute(reports); - } - - function test_IncorrectArrayType_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - - uint256[] memory wrongData = new uint256[](2); - wrongData[0] = 1; - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.execute(reportContext, abi.encode(wrongData)); - } - - function test_NonArray_Revert() public { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.execute(reportContext, abi.encode(report)); - } -} - -contract OffRamp_getExecutionState is OffRampSetup { - mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => Internal.MessageExecutionState state)) internal - s_differentialExecutionState; - - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 32 - function test_Fuzz_Differential_Success( - uint64 sourceChainSelector, - uint16[500] memory seqNums, - uint8[500] memory values - ) public { - for (uint256 i = 0; i < seqNums.length; ++i) { - // Only use the first three slots. This makes sure existing slots get overwritten - // as the tests uses 500 sequence numbers. - uint16 seqNum = seqNums[i] % 386; - Internal.MessageExecutionState state = Internal.MessageExecutionState(values[i] % 4); - s_differentialExecutionState[sourceChainSelector][seqNum] = state; - s_offRamp.setExecutionStateHelper(sourceChainSelector, seqNum, state); - assertEq(uint256(state), uint256(s_offRamp.getExecutionState(sourceChainSelector, seqNum))); - } - - for (uint256 i = 0; i < seqNums.length; ++i) { - uint16 seqNum = seqNums[i] % 386; - Internal.MessageExecutionState expectedState = s_differentialExecutionState[sourceChainSelector][seqNum]; - assertEq(uint256(expectedState), uint256(s_offRamp.getExecutionState(sourceChainSelector, seqNum))); - } - } - - function test_GetExecutionState_Success() public { - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 1, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (3 << 2)); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 1, Internal.MessageExecutionState.IN_PROGRESS); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2)); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 2, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4)); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 127, Internal.MessageExecutionState.IN_PROGRESS); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 128, Internal.MessageExecutionState.SUCCESS); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 2) + (3 << 4) + (1 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); - - assertEq( - uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 0)) - ); - assertEq( - uint256(Internal.MessageExecutionState.IN_PROGRESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 1)) - ); - assertEq( - uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 2)) - ); - assertEq( - uint256(Internal.MessageExecutionState.IN_PROGRESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 127)) - ); - assertEq( - uint256(Internal.MessageExecutionState.SUCCESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 128)) - ); - } - - function test_GetDifferentChainExecutionState_Success() public { - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 127, Internal.MessageExecutionState.IN_PROGRESS); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 128, Internal.MessageExecutionState.SUCCESS); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 1), 0); - - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1 + 1, 127, Internal.MessageExecutionState.FAILURE); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3 + (1 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 1), 2); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), (3 << 254)); - assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 1), 0); - - assertEq( - uint256(Internal.MessageExecutionState.FAILURE), uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 0)) - ); - assertEq( - uint256(Internal.MessageExecutionState.IN_PROGRESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 127)) - ); - assertEq( - uint256(Internal.MessageExecutionState.SUCCESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, 128)) - ); - - assertEq( - uint256(Internal.MessageExecutionState.UNTOUCHED), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 0)) - ); - assertEq( - uint256(Internal.MessageExecutionState.FAILURE), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 127)) - ); - assertEq( - uint256(Internal.MessageExecutionState.UNTOUCHED), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1 + 1, 128)) - ); - } - - function test_FillExecutionState_Success() public { - for (uint64 i = 0; i < 384; ++i) { - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.FAILURE); - } - - for (uint64 i = 0; i < 384; ++i) { - assertEq( - uint256(Internal.MessageExecutionState.FAILURE), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, i)) - ); - } - - for (uint64 i = 0; i < 3; ++i) { - assertEq(type(uint256).max, s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, i)); - } - - for (uint64 i = 0; i < 384; ++i) { - s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.IN_PROGRESS); - } - - for (uint64 i = 0; i < 384; ++i) { - assertEq( - uint256(Internal.MessageExecutionState.IN_PROGRESS), - uint256(s_offRamp.getExecutionState(SOURCE_CHAIN_SELECTOR_1, i)) - ); - } - - for (uint64 i = 0; i < 3; ++i) { - // 0x555... == 0b101010101010..... - assertEq( - 0x5555555555555555555555555555555555555555555555555555555555555555, - s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, i) - ); - } - } -} - -contract OffRamp_trialExecute is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - } - - function test_trialExecute_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(message.receiver); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - - // Check that the tokens were transferred - assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); - } - - function test_TokenHandlingErrorIsCaught_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(OWNER); - - bytes memory errorMessage = "Random token pool issue"; - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); - - // Expect the balance to remain the same - assertEq(startingBalance, dstToken0.balanceOf(OWNER)); - } - - function test_RateLimitError_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1000; - amounts[1] = 50; - - bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - s_maybeRevertingPool.setShouldRevert(errorMessage); - - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); - } - - // TODO test actual pool exists but isn't compatible instead of just no pool - function test_TokenPoolIsNotAContract_Success() public { - uint256[] memory amounts = new uint256[](2); - amounts[0] = 10000; - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - - // Happy path, pool is correct - (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); - assertEq("", err); - - // address 0 has no contract - assertEq(address(0).code.length, 0); - - message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: address(0), - extraData: "", - amount: message.tokenAmounts[0].amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); - - // Unhappy path, no revert but marked as failed. - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); - - address notAContract = makeAddr("not_a_contract"); - - message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: notAContract, - extraData: "", - amount: message.tokenAmounts[0].amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); - - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); - } -} - -contract OffRamp_releaseOrMintSingleToken is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - } - - function test__releaseOrMintSingleToken_Success() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); - uint256 startingBalance = dstToken1.balanceOf(OWNER); - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - vm.expectCall( - s_destPoolBySourceToken[token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: OWNER, - amount: amount, - localToken: s_destTokenBySourceToken[token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: tokenAmount.sourcePoolAddress, - sourcePoolData: tokenAmount.extraData, - offchainTokenData: offchainTokenData - }) - ) - ); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); - - assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); - } - - function test_releaseOrMintToken_InvalidDataLength_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - // Mock the call so returns 2 slots of data - vm.mockCall( - s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), abi.encode(0, 0) - ); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Internal.MAX_BALANCE_OF_RET_BYTES, 64)); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); - } - - function test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - bytes memory revertData = "failed to balanceOf"; - - // Mock the call so returns 2 slots of data - vm.mockCallRevert( - s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData - ); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); - } - - function test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - uint256 mockedStaticBalance = 50000; - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - vm.mockCall( - s_destTokenBySourceToken[token], - abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), - abi.encode(mockedStaticBalance) - ); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.ReleaseOrMintBalanceMismatch.selector, amount, mockedStaticBalance, mockedStaticBalance - ) - ); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); - } - - function test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - uint256 mockedStaticBalance = 50000; - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: s_destTokenBySourceToken[token], - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - // This should make the call fail if it does not skip the check - vm.mockCall( - s_destTokenBySourceToken[token], - abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), - abi.encode(mockedStaticBalance) - ); - - s_offRamp.releaseOrMintSingleToken( - tokenAmount, abi.encode(OWNER), s_destPoolBySourceToken[token], SOURCE_CHAIN_SELECTOR, "" - ); - } - - function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { - uint256 amount = 123123; - address token = s_sourceTokens[0]; - address destToken = s_destTokenBySourceToken[token]; - vm.label(destToken, "destToken"); - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: destToken, - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - // Address(0) should always revert - address returnedPool = address(0); - - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), - abi.encode(returnedPool) - ); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); - - // A contract that doesn't support the interface should also revert - returnedPool = address(s_offRamp); - - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, destToken), - abi.encode(returnedPool) - ); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, returnedPool)); - - s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); - } - - function test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() public { - address receiver = makeAddr("receiver"); - uint256 amount = 123123; - address token = s_sourceTokens[0]; - address destToken = s_destTokenBySourceToken[token]; - bytes memory originalSender = abi.encode(OWNER); - bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - - Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: destToken, - extraData: "", - amount: amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - bytes memory revertData = "call reverted :o"; - - vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); - s_offRamp.releaseOrMintSingleToken( - tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData - ); - } -} - -contract OffRamp_releaseOrMintTokens is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - } - - function test_releaseOrMintTokens_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - IERC20 dstToken1 = IERC20(s_destFeeToken); - uint256 startingBalance = dstToken1.balanceOf(OWNER); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: srcTokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, - sourcePoolData: sourceTokenAmounts[0].extraData, - offchainTokenData: offchainTokenData[0] - }) - ) - ); - - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) - ); - - assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); - } - - function test_releaseOrMintTokens_WithGasOverride_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - IERC20 dstToken1 = IERC20(s_destFeeToken); - uint256 startingBalance = dstToken1.balanceOf(OWNER); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: srcTokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, - sourcePoolData: sourceTokenAmounts[0].extraData, - offchainTokenData: offchainTokenData[0] - }) - ) - ); - - uint32[] memory gasOverrides = new uint32[](sourceTokenAmounts.length); - for (uint256 i = 0; i < gasOverrides.length; i++) { - gasOverrides[i] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; - } - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, gasOverrides - ); - - assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); - } - - function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - uint256 amount = 100; - uint256 destinationDenominationMultiplier = 1000; - srcTokenAmounts[1].amount = amount; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - address pool = s_destPoolBySourceToken[srcTokenAmounts[1].token]; - address destToken = s_destTokenBySourceToken[srcTokenAmounts[1].token]; - - MaybeRevertingBurnMintTokenPool(pool).setReleaseOrMintMultiplier(destinationDenominationMultiplier); - - Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) - ); - assertEq(destTokenAmounts[1].amount, amount * destinationDenominationMultiplier); - assertEq(destTokenAmounts[1].token, destToken); - } - - // Revert - - function test_TokenHandlingError_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes memory unknownError = bytes("unknown error"); - s_maybeRevertingPool.setShouldRevert(unknownError); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, unknownError)); - - s_offRamp.releaseOrMintTokens( - _getDefaultSourceTokenData(srcTokenAmounts), - abi.encode(OWNER), - OWNER, - SOURCE_CHAIN_SELECTOR_1, - new bytes[](srcTokenAmounts.length), - new uint32[](0) - ); - } - - function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { - uint256 amount = 100; - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - srcTokenAmounts[0].amount = amount; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.mockCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, - sourcePoolData: sourceTokenAmounts[0].extraData, - offchainTokenData: offchainTokenData[0] - }) - ), - // Includes the amount twice, this will revert due to the return data being to long - abi.encode(amount, amount) - ); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64)); - - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) - ); - } - - function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { - // The offRamp is a contract, but not a pool - address fakePoolAddress = address(s_offRamp); - - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); - sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: address(s_offRamp), - extraData: "", - amount: 1, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) - ); - } - - function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectCall( - s_destPoolBySourceToken[srcTokenAmounts[0].token], - abi.encodeWithSelector( - LockReleaseTokenPool.releaseOrMint.selector, - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: srcTokenAmounts[0].amount, - localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], - remoteChainSelector: SOURCE_CHAIN_SELECTOR_3, - sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, - sourcePoolData: sourceTokenAmounts[0].extraData, - offchainTokenData: offchainTokenData[0] - }) - ) - ); - vm.expectRevert(); - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData, new uint32[](0) - ); - } - - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 1024 - // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success( - address destPool - ) public { - // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C - // triggers some Create2Deployer and causes it to fail - vm.assume(destPool != 0x4e59b44847b379578588920cA78FbF26c0B4956C); - bytes memory unusedVar = abi.encode(makeAddr("unused")); - Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); - sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: unusedVar, - destTokenAddress: destPool, - extraData: unusedVar, - amount: 1, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - - try s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) - ) {} catch (bytes memory reason) { - // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp - assertTrue( - bytes4(reason) == OffRamp.TokenHandlingError.selector || bytes4(reason) == Internal.InvalidEVMAddress.selector - || bytes4(reason) == OffRamp.InvalidDataLength.selector - || bytes4(reason) == CallWithExactGas.NoContract.selector - || bytes4(reason) == OffRamp.NotACompatiblePool.selector, - "Expected TokenHandlingError or InvalidEVMAddress" - ); - - if (uint160(destPool) > type(uint160).max) { - assertEq(reason, abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(destPool))); - } - } - } -} - -contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { - function test_ApplyZeroUpdates_Success() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - vm.recordLogs(); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - // No logs emitted - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - - assertEq(s_offRamp.getSourceChainSelectors().length, 0); - } - - function test_AddNewChain_Success() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - OffRamp.SourceChainConfig memory expectedSourceChainConfig = - OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); - - vm.expectEmit(); - emit OffRamp.SourceChainSelectorAdded(SOURCE_CHAIN_SELECTOR_1); - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); - } - - function test_ReplaceExistingChain_Success() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - sourceChainConfigs[0].isEnabled = false; - OffRamp.SourceChainConfig memory expectedSourceChainConfig = - OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: false, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_1}); - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1, expectedSourceChainConfig); - - vm.recordLogs(); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - // No log emitted for chain selector added (only for setting the config) - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - - _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); - - uint256[] memory resultSourceChainSelectors = s_offRamp.getSourceChainSelectors(); - assertEq(resultSourceChainSelectors.length, 1); - } - - function test_AddMultipleChains_Success() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: abi.encode(ON_RAMP_ADDRESS_1, 0), - isEnabled: true - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 1, - onRamp: abi.encode(ON_RAMP_ADDRESS_1, 1), - isEnabled: false - }); - sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1 + 2, - onRamp: abi.encode(ON_RAMP_ADDRESS_1, 2), - isEnabled: true - }); - - OffRamp.SourceChainConfig[] memory expectedSourceChainConfigs = new OffRamp.SourceChainConfig[](3); - for (uint256 i = 0; i < 3; ++i) { - expectedSourceChainConfigs[i] = OffRamp.SourceChainConfig({ - router: s_destRouter, - isEnabled: sourceChainConfigs[i].isEnabled, - minSeqNr: 1, - onRamp: abi.encode(ON_RAMP_ADDRESS_1, i) - }); - - vm.expectEmit(); - emit OffRamp.SourceChainSelectorAdded(sourceChainConfigs[i].sourceChainSelector); - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(sourceChainConfigs[i].sourceChainSelector, expectedSourceChainConfigs[i]); - } - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - for (uint256 i = 0; i < 3; ++i) { - _assertSourceChainConfigEquality( - s_offRamp.getSourceChainConfig(sourceChainConfigs[i].sourceChainSelector), expectedSourceChainConfigs[i] - ); - } - } - - function test_Fuzz_applySourceChainConfigUpdate_Success( - OffRamp.SourceChainConfigArgs memory sourceChainConfigArgs - ) public { - // Skip invalid inputs - vm.assume(sourceChainConfigArgs.sourceChainSelector != 0); - vm.assume(sourceChainConfigArgs.onRamp.length != 0); - vm.assume(address(sourceChainConfigArgs.router) != address(0)); - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - sourceChainConfigs[1] = sourceChainConfigArgs; - - // Handle cases when an update occurs - bool isNewChain = sourceChainConfigs[1].sourceChainSelector != SOURCE_CHAIN_SELECTOR_1; - if (!isNewChain) { - sourceChainConfigs[1].onRamp = sourceChainConfigs[0].onRamp; - } - - OffRamp.SourceChainConfig memory expectedSourceChainConfig = OffRamp.SourceChainConfig({ - router: sourceChainConfigArgs.router, - isEnabled: sourceChainConfigArgs.isEnabled, - minSeqNr: 1, - onRamp: sourceChainConfigArgs.onRamp - }); - - if (isNewChain) { - vm.expectEmit(); - emit OffRamp.SourceChainSelectorAdded(sourceChainConfigArgs.sourceChainSelector); - } - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet(sourceChainConfigArgs.sourceChainSelector, expectedSourceChainConfig); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - _assertSourceChainConfigEquality( - s_offRamp.getSourceChainConfig(sourceChainConfigArgs.sourceChainSelector), expectedSourceChainConfig - ); - } - - function test_ReplaceExistingChainOnRamp_Success() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; - - vm.expectEmit(); - emit OffRamp.SourceChainConfigSet( - SOURCE_CHAIN_SELECTOR_1, - OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_2}) - ); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } - - // Reverts - - function test_ZeroOnRampAddress_Revert() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: new bytes(0), - isEnabled: true - }); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - sourceChainConfigs[0].onRamp = abi.encode(address(0)); - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } - - function test_RouterAddress_Revert() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: IRouter(address(0)), - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } - - function test_ZeroSourceChainSelector_Revert() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: 0, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - vm.expectRevert(OffRamp.ZeroChainSelectorNotAllowed.selector); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } - - function test_InvalidOnRampUpdate_Revert() public { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: 2, - merkleRoot: "test #2" - }); - - _commit( - OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }), - s_latestSequenceNumber - ); - - vm.stopPrank(); - vm.startPrank(OWNER); - - sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; - - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidOnRampUpdate.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - } -} - -contract OffRamp_commit is OffRampSetup { - uint64 internal s_maxInterval = 12; - - function setUp() public virtual override { - super.setUp(); - _setupMultipleOffRamps(); - - s_latestSequenceNumber = uint64(uint256(s_configDigestCommit)); - } - - function test_ReportAndPriceUpdate_Success() public { - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(s_maxInterval + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - } - - function test_ReportOnlyRootSuccess_gas() public { - uint64 max1 = 931; - bytes32 root = "Only a single root"; - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: max1, - merkleRoot: root - }); - - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(max1 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); - } - - function test_StaleReportWithRoot_Success() public { - uint64 maxSeq = 12; - uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: maxSeq, - merkleRoot: "stale report 1" - }); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - - commitReport.merkleRoots[0].minSeqNr = maxSeq + 1; - commitReport.merkleRoots[0].maxSeqNr = maxSeq * 2; - commitReport.merkleRoots[0].merkleRoot = "stale report 2"; - - vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(maxSeq * 2 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); - } - - function test_OnlyTokenPriceUpdates_Success() public { - // force RMN verification to fail - vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - } - - function test_OnlyGasPriceUpdates_Success() public { - // force RMN verification to fail - vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); - - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - } - - function test_PriceSequenceNumberCleared_Success() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - _commit(commitReport, s_latestSequenceNumber); - - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - - vm.startPrank(OWNER); - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - // Execution plugin OCR config should not clear latest epoch and round - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - - // Commit plugin config should clear latest epoch & round - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - - // The same sequence number can be reported again - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - - _commit(commitReport, s_latestSequenceNumber); - } - - function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { - uint64 maxSeq = 12; - uint224 tokenPrice1 = 4e18; - uint224 tokenPrice2 = 5e18; - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - - roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: maxSeq, - merkleRoot: "stale report" - }); - commitReport.priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); - commitReport.merkleRoots = roots; - - vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); - - vm.expectEmit(); - emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); - - _commit(commitReport, s_latestSequenceNumber); - - assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq(tokenPrice1, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); - assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - } - - // Reverts - - function test_UnauthorizedTransmitter_Revert() public { - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - bytes32[3] memory reportContext = - [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber)), s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); - - vm.expectRevert(MultiOCR3Base.UnauthorizedTransmitter.selector); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_NoConfig_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_NoConfigWithOtherConfigPresent_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); - - vm.startPrank(s_validTransmitters[0]); - vm.expectRevert(); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function test_FailedRMNVerification_Reverts() public { - // force RMN verification to fail - vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); - - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - vm.expectRevert(); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_Unhealthy_Revert() public { - _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - minSeqNr: 1, - maxSeqNr: 2, - merkleRoot: "Only a single root", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) - }); - - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_InvalidRootRevert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: 4, - merkleRoot: bytes32(0) - }); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert(OffRamp.InvalidRoot.selector); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_InvalidInterval_Revert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 2, - maxSeqNr: 2, - merkleRoot: bytes32(0) - }); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr - ) - ); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_InvalidIntervalMinLargerThanMax_Revert() public { - s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: 0, - merkleRoot: bytes32(0) - }); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert( - abi.encodeWithSelector( - OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr - ) - ); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_ZeroEpochAndRound_Revert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert(OffRamp.StaleCommitReport.selector); - _commit(commitReport, 0); - } - - function test_OnlyPriceUpdateStaleReport_Revert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); - _commit(commitReport, s_latestSequenceNumber); - - vm.expectRevert(OffRamp.StaleCommitReport.selector); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_SourceChainNotEnabled_Revert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: 0, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), - minSeqNr: 1, - maxSeqNr: 2, - merkleRoot: "Only a single root" - }); - - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, 0)); - _commit(commitReport, s_latestSequenceNumber); - } - - function test_RootAlreadyCommitted_Revert() public { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: 2, - merkleRoot: "Only a single root" - }); - OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ - priceUpdates: _getEmptyPriceUpdates(), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - - _commit(commitReport, s_latestSequenceNumber); - commitReport.merkleRoots[0].minSeqNr = 3; - commitReport.merkleRoots[0].maxSeqNr = 3; - - vm.expectRevert( - abi.encodeWithSelector(OffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot) - ); - _commit(commitReport, ++s_latestSequenceNumber); - } - - function test_CommitOnRampMismatch_Revert() public { - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; - - vm.expectRevert(abi.encodeWithSelector(OffRamp.CommitOnRampMismatch.selector, ON_RAMP_ADDRESS_2, ON_RAMP_ADDRESS_1)); - _commit(commitReport, s_latestSequenceNumber); - } - - function _constructCommitReport() internal view returns (OffRamp.CommitReport memory) { - Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); - roots[0] = Internal.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: ON_RAMP_ADDRESS_1, - minSeqNr: 1, - maxSeqNr: s_maxInterval, - merkleRoot: "test #2" - }); - - return OffRamp.CommitReport({ - priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), - merkleRoots: roots, - rmnSignatures: s_rmnSignatures, - rmnRawVs: 0 - }); - } -} - -contract OffRamp_afterOC3ConfigSet is OffRampSetup { - function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - new OffRamp.SourceChainConfigArgs[](0) - ); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - vm.expectRevert(OffRamp.SignatureVerificationDisabled.selector); - s_offRamp.setOCR3Configs(ocrConfigs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol deleted file mode 100644 index a789bc2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ /dev/null @@ -1,497 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; -import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {NonceManager} from "../../NonceManager.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; -import {OffRamp} from "../../offRamp/OffRamp.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; -import {OffRampHelper} from "../helpers/OffRampHelper.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {MultiOCR3BaseSetup} from "../ocr/MultiOCR3BaseSetup.t.sol"; -import {Vm} from "forge-std/Test.sol"; - -contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { - uint64 internal constant SOURCE_CHAIN_SELECTOR_1 = SOURCE_CHAIN_SELECTOR; - uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; - uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; - - bytes internal constant ON_RAMP_ADDRESS_1 = abi.encode(ON_RAMP_ADDRESS); - bytes internal constant ON_RAMP_ADDRESS_2 = abi.encode(0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4); - bytes internal constant ON_RAMP_ADDRESS_3 = abi.encode(0x71830C37Cb193e820de488Da111cfbFcC680a1b9); - - address internal constant BLESS_VOTE_ADDR = address(8888); - - IAny2EVMMessageReceiver internal s_receiver; - IAny2EVMMessageReceiver internal s_secondary_receiver; - MaybeRevertMessageReceiver internal s_reverting_receiver; - - MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; - - OffRampHelper internal s_offRamp; - MessageInterceptorHelper internal s_inboundMessageInterceptor; - NonceManager internal s_inboundNonceManager; - address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); - - bytes32 internal s_configDigestExec; - bytes32 internal s_configDigestCommit; - uint64 internal constant s_offchainConfigVersion = 3; - uint8 internal constant s_F = 1; - - uint64 internal s_latestSequenceNumber; - - IRMNRemote.Signature[] internal s_rmnSignatures; - - function setUp() public virtual override(FeeQuoterSetup, MultiOCR3BaseSetup) { - FeeQuoterSetup.setUp(); - MultiOCR3BaseSetup.setUp(); - - s_inboundMessageInterceptor = new MessageInterceptorHelper(); - s_receiver = new MaybeRevertMessageReceiver(false); - s_secondary_receiver = new MaybeRevertMessageReceiver(false); - s_reverting_receiver = new MaybeRevertMessageReceiver(true); - - s_maybeRevertingPool = MaybeRevertingBurnMintTokenPool(s_destPoolByToken[s_destTokens[1]]); - s_inboundNonceManager = new NonceManager(new address[](0)); - - _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); - } - - function _deployOffRamp(IRMNRemote rmnRemote, NonceManager nonceManager) internal { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); - - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: rmnRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(nonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - sourceChainConfigs - ); - - s_configDigestExec = _getBasicConfigDigest(s_F, s_emptySigners, s_validTransmitters); - s_configDigestCommit = _getBasicConfigDigest(s_F, s_validSigners, s_validTransmitters); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](2); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Execution), - configDigest: s_configDigestExec, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - ocrConfigs[1] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: true, - signers: s_validSigners, - transmitters: s_validTransmitters - }); - - s_offRamp.setDynamicConfig(_generateDynamicOffRampConfig(address(s_feeQuoter))); - s_offRamp.setOCR3Configs(ocrConfigs); - - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(s_offRamp); - NonceManager(nonceManager).applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = address(s_offRamp); - s_feeQuoter.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) - ); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: address(s_offRamp)}); - s_destRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - } - - function _setupMultipleOffRamps() internal { - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRamp: ON_RAMP_ADDRESS_1, - isEnabled: true - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, - onRamp: ON_RAMP_ADDRESS_2, - isEnabled: false - }); - sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, - onRamp: ON_RAMP_ADDRESS_3, - isEnabled: true - }); - _setupMultipleOffRampsFromConfigs(sourceChainConfigs); - } - - function _setupMultipleOffRampsFromConfigs( - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs - ) internal { - s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2 * sourceChainConfigs.length); - - for (uint256 i = 0; i < sourceChainConfigs.length; ++i) { - uint64 sourceChainSelector = sourceChainConfigs[i].sourceChainSelector; - - offRampUpdates[2 * i] = Router.OffRamp({sourceChainSelector: sourceChainSelector, offRamp: address(s_offRamp)}); - offRampUpdates[2 * i + 1] = Router.OffRamp({ - sourceChainSelector: sourceChainSelector, - offRamp: s_inboundNonceManager.getPreviousRamps(sourceChainSelector).prevOffRamp - }); - } - - s_destRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - uint32 internal constant MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS = 200_000; - uint32 internal constant MAX_TOKEN_POOL_TRANSFER_GAS = 50_000; - - function _generateDynamicOffRampConfig( - address feeQuoter - ) internal pure returns (OffRamp.DynamicConfig memory) { - return OffRamp.DynamicConfig({ - permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, - feeQuoter: feeQuoter, - messageInterceptor: address(0) - }); - } - - function _convertToGeneralMessage( - Internal.Any2EVMRampMessage memory original - ) internal view returns (Client.Any2EVMMessage memory message) { - uint256 numberOfTokens = original.tokenAmounts.length; - Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); - - for (uint256 i = 0; i < numberOfTokens; ++i) { - Internal.Any2EVMTokenTransfer memory tokenAmount = original.tokenAmounts[i]; - - address destPoolAddress = tokenAmount.destTokenAddress; - TokenPool pool = TokenPool(destPoolAddress); - destTokenAmounts[i].token = address(pool.getToken()); - destTokenAmounts[i].amount = tokenAmount.amount; - } - - return Client.Any2EVMMessage({ - messageId: original.header.messageId, - sourceChainSelector: original.header.sourceChainSelector, - sender: abi.encode(original.sender), - data: original.data, - destTokenAmounts: destTokenAmounts - }); - } - - function _generateAny2EVMMessageNoTokens( - uint64 sourceChainSelector, - bytes memory onRamp, - uint64 sequenceNumber - ) internal view returns (Internal.Any2EVMRampMessage memory) { - return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, new Client.EVMTokenAmount[](0), false); - } - - function _generateAny2EVMMessageWithTokens( - uint64 sourceChainSelector, - bytes memory onRamp, - uint64 sequenceNumber, - uint256[] memory amounts - ) internal view returns (Internal.Any2EVMRampMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - tokenAmounts[i].amount = amounts[i]; - } - return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, tokenAmounts, false); - } - - function _generateAny2EVMMessage( - uint64 sourceChainSelector, - bytes memory onRamp, - uint64 sequenceNumber, - Client.EVMTokenAmount[] memory tokenAmounts, - bool allowOutOfOrderExecution - ) internal view returns (Internal.Any2EVMRampMessage memory) { - bytes memory data = abi.encode(0); - - Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = - new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); - - // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], - extraData: "", - amount: tokenAmounts[i].amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - } - - Internal.Any2EVMRampMessage memory message = Internal.Any2EVMRampMessage({ - header: Internal.RampMessageHeader({ - messageId: "", - sourceChainSelector: sourceChainSelector, - destChainSelector: DEST_CHAIN_SELECTOR, - sequenceNumber: sequenceNumber, - nonce: allowOutOfOrderExecution ? 0 : sequenceNumber - }), - sender: abi.encode(OWNER), - data: data, - receiver: address(s_receiver), - tokenAmounts: any2EVMTokenTransfer, - gasLimit: GAS_LIMIT - }); - - message.header.messageId = _hashMessage(message, onRamp); - - return message; - } - - function _generateSingleBasicMessage( - uint64 sourceChainSelector, - bytes memory onRamp - ) internal view returns (Internal.Any2EVMRampMessage[] memory) { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); - messages[0] = _generateAny2EVMMessageNoTokens(sourceChainSelector, onRamp, 1); - return messages; - } - - function _generateMessagesWithTokens( - uint64 sourceChainSelector, - bytes memory onRamp - ) internal view returns (Internal.Any2EVMRampMessage[] memory) { - Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); - Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - tokenAmounts[0].amount = 1e18; - tokenAmounts[1].amount = 5e18; - messages[0] = _generateAny2EVMMessage(sourceChainSelector, onRamp, 1, tokenAmounts, false); - messages[1] = _generateAny2EVMMessage(sourceChainSelector, onRamp, 2, tokenAmounts, false); - - return messages; - } - - function _generateReportFromMessages( - uint64 sourceChainSelector, - Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (Internal.ExecutionReport memory) { - bytes[][] memory offchainTokenData = new bytes[][](messages.length); - - for (uint256 i = 0; i < messages.length; ++i) { - offchainTokenData[i] = new bytes[](messages[i].tokenAmounts.length); - } - - return Internal.ExecutionReport({ - sourceChainSelector: sourceChainSelector, - proofs: new bytes32[](0), - proofFlagBits: 2 ** 256 - 1, - messages: messages, - offchainTokenData: offchainTokenData - }); - } - - function _generateBatchReportFromMessages( - uint64 sourceChainSelector, - Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (Internal.ExecutionReport[] memory) { - Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](1); - reports[0] = _generateReportFromMessages(sourceChainSelector, messages); - return reports; - } - - function _getGasLimitsFromMessages( - Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (OffRamp.GasLimitOverride[] memory) { - OffRamp.GasLimitOverride[] memory gasLimits = new OffRamp.GasLimitOverride[](messages.length); - for (uint256 i = 0; i < messages.length; ++i) { - gasLimits[i].receiverExecutionGasLimit = messages[i].gasLimit; - } - - return gasLimits; - } - - function _assertSameConfig(OffRamp.DynamicConfig memory a, OffRamp.DynamicConfig memory b) public pure { - assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); - assertEq(a.messageInterceptor, b.messageInterceptor); - assertEq(a.feeQuoter, b.feeQuoter); - } - - function _assertSourceChainConfigEquality( - OffRamp.SourceChainConfig memory config1, - OffRamp.SourceChainConfig memory config2 - ) internal pure { - assertEq(config1.isEnabled, config2.isEnabled); - assertEq(config1.minSeqNr, config2.minSeqNr); - assertEq(config1.onRamp, config2.onRamp); - assertEq(address(config1.router), address(config2.router)); - } - - function _getDefaultSourceTokenData( - Client.EVMTokenAmount[] memory srcTokenAmounts - ) internal view returns (Internal.Any2EVMTokenTransfer[] memory) { - Internal.Any2EVMTokenTransfer[] memory sourceTokenData = new Internal.Any2EVMTokenTransfer[](srcTokenAmounts.length); - for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { - sourceTokenData[i] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), - destTokenAddress: s_destTokenBySourceToken[srcTokenAmounts[i].token], - extraData: "", - amount: srcTokenAmounts[i].amount, - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - } - return sourceTokenData; - } - - function _enableInboundMessageInterceptor() internal { - OffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); - dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); - s_offRamp.setDynamicConfig(dynamicConfig); - } - - function _redeployOffRampWithNoOCRConfigs() internal { - s_offRamp = new OffRampHelper( - OffRamp.StaticConfig({ - chainSelector: DEST_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - tokenAdminRegistry: address(s_tokenAdminRegistry), - nonceManager: address(s_inboundNonceManager) - }), - _generateDynamicOffRampConfig(address(s_feeQuoter)), - new OffRamp.SourceChainConfigArgs[](0) - ); - - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(s_offRamp); - s_inboundNonceManager.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - _setupMultipleOffRamps(); - - address[] memory priceUpdaters = new address[](1); - priceUpdaters[0] = address(s_offRamp); - s_feeQuoter.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) - ); - } - - function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { - bytes32[3] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber)), s_configDigestCommit]; - - (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = - _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, s_F + 1); - - vm.startPrank(s_validTransmitters[0]); - s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); - } - - function _execute( - Internal.ExecutionReport[] memory reports - ) internal { - bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - - vm.startPrank(s_validTransmitters[0]); - s_offRamp.execute(reportContext, abi.encode(reports)); - } - - function assertExecutionStateChangedEventLogs( - uint64 sourceChainSelector, - uint64 sequenceNumber, - bytes32 messageId, - bytes32 messageHash, - Internal.MessageExecutionState state, - bytes memory returnData - ) public { - Vm.Log[] memory logs = vm.getRecordedLogs(); - for (uint256 i = 0; i < logs.length; ++i) { - if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { - uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); - uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); - bytes32 logMessageId = bytes32(logs[i].topics[3]); - (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = - abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); - if (logMessageId == messageId) { - assertEq(logSourceChainSelector, sourceChainSelector); - assertEq(logSequenceNumber, sequenceNumber); - assertEq(logMessageId, messageId); - assertEq(logMessageHash, messageHash); - assertEq(logState, uint8(state)); - assertEq(logReturnData, returnData); - } - } - } - } - - function assertExecutionStateChangedEventLogs( - Vm.Log[] memory logs, - uint64 sourceChainSelector, - uint64 sequenceNumber, - bytes32 messageId, - bytes32 messageHash, - Internal.MessageExecutionState state, - bytes memory returnData - ) public pure { - for (uint256 i = 0; i < logs.length; ++i) { - if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { - uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); - uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); - bytes32 logMessageId = bytes32(logs[i].topics[3]); - (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = - abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); - if (logMessageId == messageId) { - assertEq(logSourceChainSelector, sourceChainSelector); - assertEq(logSequenceNumber, sequenceNumber); - assertEq(logMessageId, messageId); - assertEq(logMessageHash, messageHash); - assertEq(logState, uint8(state)); - assertEq(logReturnData, returnData); - } - } - } - } - - function _assertNoEmit( - bytes32 eventSelector - ) internal { - Vm.Log[] memory logs = vm.getRecordedLogs(); - - for (uint256 i = 0; i < logs.length; i++) { - assertTrue(logs[i].topics[0] != eventSelector); - } - } - - function _hashMessage( - Internal.Any2EVMRampMessage memory message, - bytes memory onRamp - ) internal pure returns (bytes32) { - return Internal._hash( - message, - keccak256( - abi.encode( - Internal.ANY_2_EVM_MESSAGE_HASH, - message.header.sourceChainSelector, - message.header.destChainSelector, - keccak256(onRamp) - ) - ) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol deleted file mode 100644 index 3562a6f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ /dev/null @@ -1,1080 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {FeeQuoter} from "../../FeeQuoter.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {OnRamp} from "../../onRamp/OnRamp.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import "./OnRampSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract OnRamp_constructor is OnRampSetup { - function test_Constructor_Success() public { - OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }); - OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); - - vm.expectEmit(); - emit OnRamp.ConfigSet(staticConfig, dynamicConfig); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); - - _deployOnRamp(SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry)); - - OnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); - _assertStaticConfigsEqual(staticConfig, gotStaticConfig); - - OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - _assertDynamicConfigsEqual(dynamicConfig, gotDynamicConfig); - - // Initial values - assertEq("OnRamp 1.6.0-dev", s_onRamp.typeAndVersion()); - assertEq(OWNER, s_onRamp.owner()); - assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); - assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); - } - - function test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() public { - OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }); - - OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); - - // Creating a DestChainConfig and setting allowListEnabled : true - OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); - destChainConfigs[0] = OnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - router: s_sourceRouter, - allowListEnabled: true - }); - - vm.expectEmit(); - emit OnRamp.ConfigSet(staticConfig, dynamicConfig); - - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, true); - - OnRampHelper tempOnRamp = new OnRampHelper(staticConfig, dynamicConfig, destChainConfigs); - - // Sending a message and expecting revert as allowList is enabled with no address in allowlist - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, OWNER)); - tempOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { - vm.expectRevert(OnRamp.InvalidConfig.selector); - new OnRampHelper( - OnRamp.StaticConfig({ - chainSelector: 0, - rmnRemote: s_mockRMNRemote, - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicOnRampConfig(address(s_feeQuoter)), - _generateDestChainConfigArgs(IRouter(address(0))) - ); - } - - function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { - vm.expectRevert(OnRamp.InvalidConfig.selector); - s_onRamp = new OnRampHelper( - OnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnRemote: IRMNRemote(address(0)), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicOnRampConfig(address(s_feeQuoter)), - _generateDestChainConfigArgs(IRouter(address(0))) - ); - } - - function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { - vm.expectRevert(OnRamp.InvalidConfig.selector); - new OnRampHelper( - OnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - nonceManager: address(0), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicOnRampConfig(address(s_feeQuoter)), - _generateDestChainConfigArgs(IRouter(address(0))) - ); - } - - function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { - vm.expectRevert(OnRamp.InvalidConfig.selector); - new OnRampHelper( - OnRamp.StaticConfig({ - chainSelector: SOURCE_CHAIN_SELECTOR, - rmnRemote: s_mockRMNRemote, - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(0) - }), - _generateDynamicOnRampConfig(address(s_feeQuoter)), - _generateDestChainConfigArgs(IRouter(address(0))) - ); - } -} - -contract OnRamp_forwardFromRouter is OnRampSetup { - struct LegacyExtraArgs { - uint256 gasLimit; - bool strict; - } - - function setUp() public virtual override { - super.setUp(); - - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - - uint64[] memory destinationChainSelectors = new uint64[](1); - destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; - address[] memory addAllowedList = new address[](1); - addAllowedList[0] = OWNER; - OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addAllowedList, - removedAllowlistedSenders: new address[](0) - }); - OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); - applyAllowListConfigArgsItems[0] = allowListConfigArgs; - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - } - - function test_ForwardFromRouterSuccessCustomExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouter_Success_ConfigurableSourceRouter() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - // Change the source router for this lane - IRouter newRouter = IRouter(makeAddr("NEW ROUTER")); - vm.stopPrank(); - vm.prank(OWNER); - s_onRamp.applyDestChainConfigUpdates(_generateDestChainConfigArgs(newRouter)); - - // forward fails from wrong router - vm.prank(address(s_sourceRouter)); - vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - // forward succeeds from correct router - vm.prank(address(newRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterSuccessLegacyExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V1_TAG, LegacyExtraArgs({gasLimit: GAS_LIMIT * 2, strict: true})); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - // We expect the message to be emitted with strict = false. - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterSuccessEmptyExtraArgs() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = ""; - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - // We expect the message to be emitted with strict = false. - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouter_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_ShouldIncrementSeqNumAndNonce_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - assertEq(nonceAfter, nonceBefore + 1); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) - ); - - for (uint64 i = 1; i < 4; ++i) { - uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, i, _messageToEvent(message, i, i, 0, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; - assertEq(nonceAfter, nonceBefore); - assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); - } - } - - function test_ShouldStoreLinkFees() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); - } - - function test_ShouldStoreNonLinkFees() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceTokens[1]; - - uint256 feeAmount = 1234567890; - IERC20(s_sourceTokens[1]).transferFrom(OWNER, address(s_onRamp), feeAmount); - - // Calculate conversion done by prices contract - uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; - uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; - uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, expectedJuels, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - - assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); - } - - // Make sure any valid sender, receiver and feeAmount can be handled. - // @TODO Temporarily setting lower fuzz run as 256 triggers snapshot gas off by 1 error. - // https://github.com/foundry-rs/foundry/issues/5689 - /// forge-dynamicConfig: default.fuzz.runs = 32 - /// forge-dynamicConfig: ccip.fuzz.runs = 32 - function test_Fuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { - // To avoid RouterMustSetOriginalSender - vm.assume(originalSender != address(0)); - vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); - feeTokenAmount = uint96(bound(feeTokenAmount, 0, MAX_MSG_FEES_JUELS)); - vm.stopPrank(); - - vm.startPrank(OWNER); - uint64[] memory destinationChainSelectors = new uint64[](1); - destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); - address[] memory addAllowedList = new address[](1); - addAllowedList[0] = originalSender; - OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addAllowedList, - removedAllowlistedSenders: new address[](0) - }); - OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); - applyAllowListConfigArgsItems[0] = allowListConfigArgs; - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - vm.stopPrank(); - - vm.startPrank(address(s_sourceRouter)); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(receiver); - - // Make sure the tokens are in the contract - deal(s_sourceFeeToken, address(s_onRamp), feeTokenAmount); - - Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent.header.sequenceNumber, expectedEvent); - - // Assert the message Id is correct - assertEq( - expectedEvent.header.messageId, - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeTokenAmount, originalSender) - ); - } - - function test_forwardFromRouter_WithInterception_Success() public { - _enableOutboundMessageInterceptor(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), false); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - // Reverts - - function test_Paused_Revert() public { - // We pause by disabling the whitelist - vm.stopPrank(); - vm.startPrank(OWNER); - s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); - vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_InvalidExtraArgsTag_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = bytes("bad args"); - - vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_Permissions_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - - function test_OriginalSender_Revert() public { - vm.expectRevert(OnRamp.RouterMustSetOriginalSender.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); - } - - function test_UnAllowedOriginalSender_Revert() public { - vm.stopPrank(); - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, STRANGER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); - } - - function test_MessageInterceptionError_Revert() public { - _enableOutboundMessageInterceptor(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); - uint256 feeAmount = 1234567890; - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1e18; - message.tokenAmounts[0].token = s_sourceTokens[0]; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), true); - - vm.expectRevert( - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - - function test_MultiCannotSendZeroTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 0; - message.tokenAmounts[0].token = s_sourceTokens[0]; - vm.expectRevert(OnRamp.CannotSendZeroTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_UnsupportedToken_Revert() public { - address wrongToken = address(1); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].token = wrongToken; - message.tokenAmounts[0].amount = 1; - - // We need to set the price of this new token to be able to reach - // the proper revert point. This must be called by the owner. - vm.stopPrank(); - vm.startPrank(OWNER); - - Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(wrongToken, 1); - s_feeQuoter.updatePrices(priceUpdates); - - // Change back to the router - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, wrongToken)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_forwardFromRouter_UnsupportedToken_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1; - message.tokenAmounts[0].token = address(1); - - vm.expectRevert(abi.encodeWithSelector(OnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_MesssageFeeTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectRevert( - abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); - } - - function test_SourceTokenDataTooLarge_Revert() public { - address sourceETH = s_sourceTokens[1]; - vm.stopPrank(); - vm.startPrank(OWNER); - - MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); - deal(address(sourceETH), address(newPool), type(uint256).max); - - // Add TokenPool to OnRamp - s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); - - // Allow chain in TokenPool - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - newPool.applyChainUpdates(chainUpdates); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); - - // No data set, should succeed - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set max data length, should succeed - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES)); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set data to max length +1, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set token config to allow larger data - vm.startPrank(OWNER); - FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, - isEnabled: true - }); - s_feeQuoter.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) - ); - - vm.startPrank(address(s_sourceRouter)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - // Set the token data larger than the configured token data, should revert - vm.startPrank(OWNER); - newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); - - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } -} - -contract OnRamp_getSupportedTokens is OnRampSetup { - function test_GetSupportedTokens_Revert() public { - vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); - s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); - } -} - -contract OnRamp_getFee is OnRampSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - assertEq(expectedFeeAmount, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - - assertEq(expectedFeeAmount, feeAmount); - } - } - - function test_GetFeeOfZeroForTokenMessage_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - assertTrue(feeAmount > 0); - - FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory tokenMults = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); - tokenMults[0] = FeeQuoter.PremiumMultiplierWeiPerEthArgs({token: message.feeToken, premiumMultiplierWeiPerEth: 0}); - s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(tokenMults); - - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; - destChainConfigArgs[0].destChainConfig.gasMultiplierWeiPerEth = 0; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - - feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - assertEq(0, feeAmount); - } - - // Reverts - - function test_Unhealthy_Revert() public { - _setMockRMNChainCurse(DEST_CHAIN_SELECTOR, true); - vm.expectRevert(abi.encodeWithSelector(OnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); - } - - function test_EnforceOutOfOrder_Revert() public { - // Update dynamic config to enforce allowOutOfOrderExecution = true. - vm.stopPrank(); - vm.startPrank(OWNER); - - FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - vm.stopPrank(); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Empty extraArgs to should revert since it enforceOutOfOrder is true. - message.extraArgs = ""; - - vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_NotAFeeTokenButPricedToken_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceTokens[1]; - - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, message.feeToken)); - - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract OnRamp_setDynamicConfig is OnRampSetup { - function test_setDynamicConfig_Success() public { - OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); - OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - feeQuoter: address(23423), - reentrancyGuardEntered: false, - messageInterceptor: makeAddr("messageInterceptor"), - feeAggregator: FEE_AGGREGATOR, - allowListAdmin: address(0) - }); - - vm.expectEmit(); - emit OnRamp.ConfigSet(staticConfig, newConfig); - - s_onRamp.setDynamicConfig(newConfig); - - OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(newConfig.feeQuoter, gotDynamicConfig.feeQuoter); - } - - // Reverts - - function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { - OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - feeQuoter: address(0), - reentrancyGuardEntered: false, - feeAggregator: FEE_AGGREGATOR, - messageInterceptor: makeAddr("messageInterceptor"), - allowListAdmin: address(0) - }); - - vm.expectRevert(OnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { - OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - feeQuoter: address(23423), - reentrancyGuardEntered: false, - messageInterceptor: address(0), - feeAggregator: FEE_AGGREGATOR, - allowListAdmin: address(0) - }); - - // Invalid price reg reverts. - newConfig.feeQuoter = address(0); - vm.expectRevert(OnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { - OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - feeQuoter: address(23423), - reentrancyGuardEntered: false, - messageInterceptor: address(0), - feeAggregator: address(0), - allowListAdmin: address(0) - }); - - vm.expectRevert(OnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } - - function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); - vm.startPrank(ADMIN); - vm.expectRevert("Only callable by owner"); - s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); - } - - function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { - OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - feeQuoter: address(23423), - reentrancyGuardEntered: true, - messageInterceptor: makeAddr("messageInterceptor"), - feeAggregator: FEE_AGGREGATOR, - allowListAdmin: address(0) - }); - - vm.expectRevert(OnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); - } -} - -contract OnRamp_withdrawFeeTokens is OnRampSetup { - mapping(address => uint256) internal s_nopFees; - - function setUp() public virtual override { - super.setUp(); - - // Since we'll mostly be testing for valid calls from the router we'll - // mock all calls to be originating from the router and re-mock in - // tests that require failure. - vm.startPrank(address(s_sourceRouter)); - - uint256 feeAmount = 1234567890; - - // Send a bunch of messages, increasing the juels in the contract - for (uint256 i = 0; i < s_sourceFeeTokens.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceFeeTokens[i % s_sourceFeeTokens.length]; - uint256 newFeeTokenBalance = IERC20(message.feeToken).balanceOf(address(s_onRamp)) + feeAmount; - deal(message.feeToken, address(s_onRamp), newFeeTokenBalance); - s_nopFees[message.feeToken] = newFeeTokenBalance; - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } - - function test_Fuzz_WithdrawFeeTokens_Success( - uint256[5] memory amounts - ) public { - vm.startPrank(OWNER); - address[] memory feeTokens = new address[](amounts.length); - for (uint256 i = 0; i < amounts.length; ++i) { - vm.assume(amounts[i] > 0); - feeTokens[i] = _deploySourceToken("", amounts[i], 18); - IERC20(feeTokens[i]).transfer(address(s_onRamp), amounts[i]); - } - - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - - for (uint256 i = 0; i < feeTokens.length; ++i) { - vm.expectEmit(); - emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, feeTokens[i], amounts[i]); - } - - s_onRamp.withdrawFeeTokens(); - - for (uint256 i = 0; i < feeTokens.length; ++i) { - assertEq(IERC20(feeTokens[i]).balanceOf(FEE_AGGREGATOR), amounts[i]); - assertEq(IERC20(feeTokens[i]).balanceOf(address(s_onRamp)), 0); - } - } - - function test_WithdrawFeeTokens_Success() public { - vm.expectEmit(); - emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); - - s_onRamp.withdrawFeeTokens(); - - assertEq(IERC20(s_sourceFeeToken).balanceOf(FEE_AGGREGATOR), s_nopFees[s_sourceFeeToken]); - assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), 0); - } -} - -contract OnRamp_getTokenPool is OnRampSetup { - function test_GetTokenPool_Success() public view { - assertEq( - s_sourcePoolByToken[s_sourceTokens[0]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) - ); - assertEq( - s_sourcePoolByToken[s_sourceTokens[1]], - address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[1]))) - ); - - address wrongToken = address(123); - address nonExistentPool = address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(wrongToken))); - - assertEq(address(0), nonExistentPool); - } -} - -contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { - function test_ApplyDestChainConfigUpdates_Success() external { - vm.stopPrank(); - vm.startPrank(OWNER); - OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); - configArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - - // supports disabling a lane by setting a router to zero - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, IRouter(address(0)), false); - s_onRamp.applyDestChainConfigUpdates(configArgs); - assertEq(address(0), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); - - // supports updating and adding lanes simultaneously - configArgs = new OnRamp.DestChainConfigArgs[](2); - configArgs[0] = OnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - router: s_sourceRouter, - allowListEnabled: false - }); - configArgs[1] = - OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); - s_onRamp.applyDestChainConfigUpdates(configArgs); - assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); - assertEq(address(9999), address(s_onRamp.getRouter(9999))); - - // handles empty list - uint256 numLogs = vm.getRecordedLogs().length; - configArgs = new OnRamp.DestChainConfigArgs[](0); - s_onRamp.applyDestChainConfigUpdates(configArgs); - assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made - } - - function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { - vm.stopPrank(); - vm.startPrank(OWNER); - OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); - configArgs[0].destChainSelector = 0; // invalid - vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidDestChainConfig.selector, 0)); - s_onRamp.applyDestChainConfigUpdates(configArgs); - } -} - -contract OnRamp_applyAllowListUpdates is OnRampSetup { - function test_applyAllowListUpdates_Success() public { - vm.stopPrank(); - vm.startPrank(OWNER); - - OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); - configArgs[0] = OnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - router: s_sourceRouter, - allowListEnabled: false - }); - configArgs[1] = - OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); - s_onRamp.applyDestChainConfigUpdates(configArgs); - - (uint64 sequenceNumber, bool allowListEnabled, address router) = s_onRamp.getDestChainConfig(9999); - assertEq(sequenceNumber, 0); - assertEq(allowListEnabled, false); - assertEq(router, address(9999)); - - uint64[] memory destinationChainSelectors = new uint64[](2); - destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; - destinationChainSelectors[1] = uint64(99999); - - address[] memory addedAllowlistedSenders = new address[](4); - addedAllowlistedSenders[0] = vm.addr(1); - addedAllowlistedSenders[1] = vm.addr(2); - addedAllowlistedSenders[2] = vm.addr(3); - addedAllowlistedSenders[3] = vm.addr(4); - - vm.expectEmit(); - emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); - - OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addedAllowlistedSenders, - removedAllowlistedSenders: new address[](0) - }); - - OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); - applyAllowListConfigArgsItems[0] = allowListConfigArgs; - - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - assertEq(4, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); - - assertEq(addedAllowlistedSenders, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR)); - - address[] memory removedAllowlistedSenders = new address[](1); - removedAllowlistedSenders[0] = vm.addr(2); - - vm.expectEmit(); - emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); - - allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: new address[](0), - removedAllowlistedSenders: removedAllowlistedSenders - }); - - OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_2 = new OnRamp.AllowListConfigArgs[](1); - allowListConfigArgsItems_2[0] = allowListConfigArgs; - - s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_2); - assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); - - addedAllowlistedSenders = new address[](2); - addedAllowlistedSenders[0] = vm.addr(5); - addedAllowlistedSenders[1] = vm.addr(6); - - removedAllowlistedSenders = new address[](2); - removedAllowlistedSenders[0] = vm.addr(1); - removedAllowlistedSenders[1] = vm.addr(3); - - vm.expectEmit(); - emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); - emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); - - allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addedAllowlistedSenders, - removedAllowlistedSenders: removedAllowlistedSenders - }); - - OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_3 = new OnRamp.AllowListConfigArgs[](1); - allowListConfigArgsItems_3[0] = allowListConfigArgs; - - s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_3); - assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); - } - - function test_applyAllowListUpdates_Revert() public { - vm.stopPrank(); - vm.startPrank(OWNER); - - OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); - configArgs[0] = OnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - router: s_sourceRouter, - allowListEnabled: false - }); - configArgs[1] = - OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999)), allowListEnabled: false}); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); - vm.expectEmit(); - emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); - s_onRamp.applyDestChainConfigUpdates(configArgs); - - uint64[] memory destinationChainSelectors = new uint64[](2); - destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; - destinationChainSelectors[1] = uint64(99999); - - address[] memory addedAllowlistedSenders = new address[](4); - addedAllowlistedSenders[0] = vm.addr(1); - addedAllowlistedSenders[1] = vm.addr(2); - addedAllowlistedSenders[2] = vm.addr(3); - addedAllowlistedSenders[3] = vm.addr(4); - - OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: true, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addedAllowlistedSenders, - removedAllowlistedSenders: new address[](0) - }); - - OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); - applyAllowListConfigArgsItems[0] = allowListConfigArgs; - - vm.startPrank(STRANGER); - vm.expectRevert(OnRamp.OnlyCallableByOwnerOrAllowlistAdmin.selector); - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - vm.stopPrank(); - - applyAllowListConfigArgsItems[0].addedAllowlistedSenders[0] = address(0); - vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); - vm.startPrank(OWNER); - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - vm.stopPrank(); - } - - function test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() public { - vm.stopPrank(); - vm.startPrank(OWNER); - - address[] memory addedAllowlistedSenders = new address[](1); - addedAllowlistedSenders[0] = vm.addr(1); - - OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ - allowListEnabled: false, - destChainSelector: DEST_CHAIN_SELECTOR, - addedAllowlistedSenders: addedAllowlistedSenders, - removedAllowlistedSenders: new address[](0) - }); - OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); - applyAllowListConfigArgsItems[0] = allowListConfigArgs; - - vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); - s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol deleted file mode 100644 index 08b213c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRouter} from "../../interfaces/IRouter.sol"; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {NonceManager} from "../../NonceManager.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {OnRamp} from "../../onRamp/OnRamp.sol"; -import {FeeQuoterFeeSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; -import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; -import {OnRampHelper} from "../helpers/OnRampHelper.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract OnRampSetup is FeeQuoterFeeSetup { - uint256 internal immutable i_tokenAmount0 = 9; - uint256 internal immutable i_tokenAmount1 = 7; - - bytes32 internal s_metadataHash; - - OnRampHelper internal s_onRamp; - MessageInterceptorHelper internal s_outboundMessageInterceptor; - address[] internal s_offRamps; - NonceManager internal s_outboundNonceManager; - - function setUp() public virtual override { - super.setUp(); - - s_outboundMessageInterceptor = new MessageInterceptorHelper(); - s_outboundNonceManager = new NonceManager(new address[](0)); - (s_onRamp, s_metadataHash) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - s_offRamps = new address[](2); - s_offRamps[0] = address(10); - s_offRamps[1] = address(11); - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](2); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp)}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[0]}); - offRampUpdates[1] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_offRamps[1]}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - - // Pre approve the first token so the gas estimates of the tests - // only cover actual gas usage from the ramps - IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 2 ** 128); - IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), 2 ** 128); - } - - function _generateTokenMessage() public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - tokenAmounts[0].amount = i_tokenAmount0; - tokenAmounts[1].amount = i_tokenAmount1; - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - /// @dev a helper function to compose EVM2AnyRampMessage messages - /// @dev it is assumed that LINK is the payment token because feeTokenAmount == feeValueJuels - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - address originalSender - ) internal view returns (Internal.EVM2AnyRampMessage memory) { - return _messageToEvent( - message, - seqNum, - nonce, - feeTokenAmount, // fee paid - feeTokenAmount, // conversion to jules is the same - originalSender - ); - } - - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - uint256 feeValueJuels, - address originalSender - ) internal view returns (Internal.EVM2AnyRampMessage memory) { - return _messageToEvent( - message, - SOURCE_CHAIN_SELECTOR, - DEST_CHAIN_SELECTOR, - seqNum, - nonce, - feeTokenAmount, - feeValueJuels, - originalSender, - s_metadataHash, - s_tokenAdminRegistry - ); - } - - function _generateDynamicOnRampConfig( - address feeQuoter - ) internal pure returns (OnRamp.DynamicConfig memory) { - return OnRamp.DynamicConfig({ - feeQuoter: feeQuoter, - reentrancyGuardEntered: false, - messageInterceptor: address(0), - feeAggregator: FEE_AGGREGATOR, - allowListAdmin: address(0) - }); - } - - // Slicing is only available for calldata. So we have to build a new bytes array. - function _removeFirst4Bytes( - bytes memory data - ) internal pure returns (bytes memory) { - bytes memory result = new bytes(data.length - 4); - for (uint256 i = 4; i < data.length; ++i) { - result[i - 4] = data[i]; - } - return result; - } - - function _generateDestChainConfigArgs( - IRouter router - ) internal pure returns (OnRamp.DestChainConfigArgs[] memory) { - OnRamp.DestChainConfigArgs[] memory destChainConfigs = new OnRamp.DestChainConfigArgs[](1); - destChainConfigs[0] = - OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: router, allowListEnabled: false}); - return destChainConfigs; - } - - function _deployOnRamp( - uint64 sourceChainSelector, - IRouter router, - address nonceManager, - address tokenAdminRegistry - ) internal returns (OnRampHelper, bytes32 metadataHash) { - OnRampHelper onRamp = new OnRampHelper( - OnRamp.StaticConfig({ - chainSelector: sourceChainSelector, - rmnRemote: s_mockRMNRemote, - nonceManager: nonceManager, - tokenAdminRegistry: tokenAdminRegistry - }), - _generateDynamicOnRampConfig(address(s_feeQuoter)), - _generateDestChainConfigArgs(router) - ); - - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(onRamp); - - NonceManager(nonceManager).applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - - return ( - onRamp, - keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, sourceChainSelector, DEST_CHAIN_SELECTOR, address(onRamp))) - ); - } - - function _enableOutboundMessageInterceptor() internal { - (, address msgSender,) = vm.readCallers(); - - bool resetPrank = false; - - if (msgSender != OWNER) { - vm.stopPrank(); - vm.startPrank(OWNER); - resetPrank = true; - } - - OnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.messageInterceptor = address(s_outboundMessageInterceptor); - s_onRamp.setDynamicConfig(dynamicConfig); - - if (resetPrank) { - vm.stopPrank(); - vm.startPrank(msgSender); - } - } - - function _assertStaticConfigsEqual(OnRamp.StaticConfig memory a, OnRamp.StaticConfig memory b) internal pure { - assertEq(a.chainSelector, b.chainSelector); - assertEq(address(a.rmnRemote), address(b.rmnRemote)); - assertEq(a.tokenAdminRegistry, b.tokenAdminRegistry); - } - - function _assertDynamicConfigsEqual(OnRamp.DynamicConfig memory a, OnRamp.DynamicConfig memory b) internal pure { - assertEq(a.feeQuoter, b.feeQuoter); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol deleted file mode 100644 index b5967e7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnFromMintTokenPool} from "../../pools/BurnFromMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnFromMintTokenPoolSetup is BurnMintSetup { - BurnFromMintTokenPool internal s_pool; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_pool = new BurnFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); - - _applyChainUpdates(address(s_pool)); - } -} - -contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); - assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); - } - - function test_PoolBurn_Success() public { - uint256 burnAmount = 20_000e18; - - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); - - vm.startPrank(s_burnMintOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(burnAmount); - - vm.expectEmit(); - emit IERC20.Transfer(address(s_pool), address(0), burnAmount); - - vm.expectEmit(); - emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); - - bytes4 expectedSignature = bytes4(keccak256("burnFrom(address,uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: burnAmount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); - } - - // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); - vm.startPrank(s_burnMintOnRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1, - localToken: address(s_burnMintERC677), - remoteChainSelector: wrongChainSelector, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol deleted file mode 100644 index 7bf0ce5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -contract BurnMintSetup is RouterSetup { - BurnMintERC677 internal s_burnMintERC677; - address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); - address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); - - address internal s_remoteBurnMintPool = makeAddr("remote_burn_mint_pool"); - address internal s_remoteToken = makeAddr("remote_token"); - - function setUp() public virtual override { - RouterSetup.setUp(); - - s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 0); - } - - function _applyChainUpdates( - address pool - ) internal { - TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); - chains[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_remoteBurnMintPool), - remoteTokenAddress: abi.encode(s_remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - BurnMintTokenPool(pool).applyChainUpdates(chains); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_burnMintOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_burnMintOffRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol deleted file mode 100644 index 8a6d047..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnMintTokenPoolSetup is BurnMintSetup { - BurnMintTokenPool internal s_pool; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_pool = new BurnMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); - - _applyChainUpdates(address(s_pool)); - } -} - -contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); - assertEq(false, s_pool.getAllowListEnabled()); - assertEq("BurnMintTokenPool 1.5.0", s_pool.typeAndVersion()); - } - - function test_PoolBurn_Success() public { - uint256 burnAmount = 20_000e18; - - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); - - vm.startPrank(s_burnMintOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(burnAmount); - - vm.expectEmit(); - emit IERC20.Transfer(address(s_pool), address(0), burnAmount); - - vm.expectEmit(); - emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); - - bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, burnAmount)); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: burnAmount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); - } - - // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); - vm.startPrank(s_burnMintOnRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1, - remoteChainSelector: wrongChainSelector, - localToken: address(s_burnMintERC677) - }) - ); - } -} - -contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { - function test_PoolMint_Success() public { - uint256 amount = 1e19; - address receiver = makeAddr("receiver_address"); - - vm.startPrank(s_burnMintOffRamp); - - vm.expectEmit(); - emit IERC20.Transfer(address(0), receiver, amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: receiver, - amount: amount, - localToken: address(s_burnMintERC677), - remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_remoteBurnMintPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - - assertEq(s_burnMintERC677.balanceOf(receiver), amount); - } - - function test_PoolMintNotHealthy_Revert() public { - // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(OWNER); - vm.startPrank(s_burnMintOffRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_burnMintERC677), - remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - - assertEq(s_burnMintERC677.balanceOf(OWNER), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1, - localToken: address(s_burnMintERC677), - remoteChainSelector: wrongChainSelector, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol deleted file mode 100644 index 92e8717..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnWithFromMintTokenPool} from "../../pools/BurnWithFromMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { - BurnWithFromMintTokenPool internal s_pool; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_pool = - new BurnWithFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); - - _applyChainUpdates(address(s_pool)); - } -} - -contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); - assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnWithFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); - } - - function test_PoolBurn_Success() public { - uint256 burnAmount = 20_000e18; - - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); - - vm.startPrank(s_burnMintOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(burnAmount); - - vm.expectEmit(); - emit IERC20.Transfer(address(s_pool), address(0), burnAmount); - - vm.expectEmit(); - emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); - - bytes4 expectedSignature = bytes4(keccak256("burn(address,uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: burnAmount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); - } - - // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); - vm.startPrank(s_burnMintOnRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1, - localToken: address(s_burnMintERC677), - remoteChainSelector: wrongChainSelector, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol deleted file mode 100644 index 7342612..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol +++ /dev/null @@ -1,886 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -import {TokenPool} from "../../pools/TokenPool.sol"; -import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; -import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract USDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; - - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; - address[] internal s_allowedList; - - function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - - s_usdcTokenPool = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - - s_usdcTokenPoolTransferLiquidity = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - } - - function setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } -} - -contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { - function test_LockOrBurn_onLockReleaseMechanism_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectEmit(); - emit TokenPool.Locked(s_routerAllowedOnRamp, amount); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); - } - - function test_MintOrRelease_OnLockReleaseMechanism_Success() public { - address recipient = address(1234); - - // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = SOURCE_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), - "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" - ); - - vm.startPrank(OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e12; - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - uint256 amount = 1e6; - - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - - // Simulate the off-ramp forwarding tokens to the recipient on destination chain - // s_token.transfer(recipient, amount); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - liquidityAmount - amount, - "Incorrect remaining liquidity in TokenPool" - ); - assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); - } - - function test_LockOrBurn_PrimaryMechanism_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - uint256 amount = 1; - - vm.startPrank(OWNER); - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - receiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - } - - // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_MintOrRelease_incomingMessageWithPrimaryMechanism() public { - bytes memory encodedUsdcMessage = - hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; - bytes memory attestation = bytes("attestation bytes"); - - uint32 nonce = 4730; - uint32 sourceDomain = 3; - uint256 amount = 100; - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - function test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() public { - // Test Enabling the LR mechanism and sending an outgoing message - test_LockOrBurn_PrimaryMechanism_Success(); - - // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message - uint64[] memory destChainRemoves = new uint64[](1); - destChainRemoves[0] = DEST_CHAIN_SELECTOR; - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); - - // Send an outgoing message - test_LockOrBurn_PrimaryMechanism_Success(); - } - - function test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() public { - test_MintOrRelease_OnLockReleaseMechanism_Success(); - - // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message - uint64[] memory destChainRemoves = new uint64[](1); - destChainRemoves[0] = SOURCE_CHAIN_SELECTOR; - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(SOURCE_CHAIN_SELECTOR); - - s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(OWNER, OWNER, SOURCE_CHAIN_SELECTOR); - - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - - // Test incoming on the primary mechanism after disable LR, simulating Circle's new support for CCTP on - // DEST_CHAIN_SELECTOR - test_MintOrRelease_incomingMessageWithPrimaryMechanism(); - } - - function test_LockOrBurn_WhileMigrationPause_Revert() public { - // Create a fake migration proposal - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); - - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) - ); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_ReleaseOrMint_WhileMigrationPause_Revert() public { - address recipient = address(1234); - - // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = SOURCE_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), - "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" - ); - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); - - // Propose the migration to CCTP - s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory sourcePoolDataLockRelease = abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()); - - uint256 amount = 1e6; - - vm.startPrank(s_routerAllowedOffRamp); - - // Expect revert because the lane is paused and no incoming messages should be allowed - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) - ); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourcePoolDataLockRelease, - offchainTokenData: "" - }) - ); - } - - function test_transferLiquidity_Success() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - vm.expectEmit(); - emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( - address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.owner(), - address(s_usdcTokenPoolTransferLiquidity), - "Ownership of the old pool should be transferred to the new pool" - ); - - assertEq( - s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - liquidityAmount, - "Tokens locked for dest chain doesn't match expected amount in storage" - ); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), - liquidityAmount, - "Liquidity amount of tokens should be new in new pool, but aren't" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - 0, - "Liquidity amount of tokens should be zero in old pool, but aren't" - ); - } - - function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - } -} - -contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { - function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectEmit(); - emit TokenPool.Locked(s_routerAllowedOnRamp, amount); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - // Ensure that the tokens are properly locked - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - amount, - "Internal locked token accounting is incorrect" - ); - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); - - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); - - // Propose the migration to CCTP - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - DEST_CHAIN_SELECTOR, - "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" - ); - - // Impersonate the set circle address and execute the proposal - vm.startPrank(CIRCLE); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); - - // Ensure the call to the burn function is properly - vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); - - s_usdcTokenPool.burnLockedUSDC(); - - // Assert that the tokens were actually burned - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); - - // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore - assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" - ); - - assertFalse( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" - ); - - test_LockOrBurn_PrimaryMechanism_Success(); - } - - function test_cancelExistingCCTPMigrationProposal() public { - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - DEST_CHAIN_SELECTOR, - "migration proposal should exist, but doesn't" - ); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - 0, - "migration proposal exists, but shouldn't after being cancelled" - ); - - vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - } - - function test_burnLockedUSDC_invalidPermissions_Revert() public { - address CIRCLE = makeAddr("CIRCLE"); - - vm.startPrank(OWNER); - - // Set the circle migrator address for later, but don't start pranking as it yet - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); - - // Should fail because only Circle can call this function - s_usdcTokenPool.burnLockedUSDC(); - - vm.startPrank(CIRCLE); - - vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.ExistingMigrationProposal.selector)); - s_usdcTokenPool.burnLockedUSDC(); - } - - function test_cannotModifyLiquidityWithoutPermissions_Revert() public { - address randomAddr = makeAddr("RANDOM"); - - vm.startPrank(randomAddr); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); - - // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); - } - - function test_cannotCancelANonExistentMigrationProposal() public { - vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); - - // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - } - - function test_unstickManualTxAfterMigration_destChain_Success() public { - address recipient = address(1234); - // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that - // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, - // which should tell it to use the lock-release mechanism with the tokens provided. - - // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as - // liquidity - uint256 amount = 1e6; - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); - - // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message - // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released - // instead of minted since there's no attestation for us to use. - - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the - // recipient - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); - assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); - - // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag - // which after a migration will mean all new messages. - - // The message should fail without an error because it failed to decode a non-existent attestation which would - // revert without an error - vm.expectRevert(); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_unstickManualTxAfterMigration_homeChain_Success() public { - address CIRCLE = makeAddr("CIRCLE"); - address recipient = address(1234); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking - // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 - - uint256 amount = 1e6; - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - // I picked 3x the amount to be stuck so that we can have enough to release with a buffer - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); - - // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens - // stuck coming back from the destination, to the home chain. This way they can be released and not minted - // since there's no corresponding attestation to use for minting. - vm.startPrank(OWNER); - - // Exclude the tokens from being burned and check for the event - vm.expectEmit(); - emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); - - s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), - (amount * 3), - "Tokens locked minus ones excluded from the burn should be 2e6" - ); - - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 1e6, - "1e6 tokens should be excluded from the burn" - ); - - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); - - vm.startPrank(CIRCLE); - - s_usdcTokenPool.burnLockedUSDC(); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" - ); - - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 1e6, - "There should still be 1e6 tokens excluded from the burn" - ); - - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); - - // Now that the burn is successful, we can release the tokens that were excluded from the burn - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); - assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 0, - "All tokens should be released from the exclusion list" - ); - - // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag - test_MintOrRelease_incomingMessageWithPrimaryMechanism(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol deleted file mode 100644 index eea7f2a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol +++ /dev/null @@ -1,438 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -contract LockReleaseTokenPoolSetup is RouterSetup { - IERC20 internal s_token; - LockReleaseTokenPool internal s_lockReleaseTokenPool; - LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; - address[] internal s_allowedList; - - address internal s_allowedOnRamp = address(123); - address internal s_allowedOffRamp = address(234); - - address internal s_destPoolAddress = address(2736782345); - address internal s_sourcePoolAddress = address(53852352095); - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - s_allowedList.push(USER_1); - s_allowedList.push(DUMMY_CONTRACT_ADDRESS); - s_lockReleaseTokenPoolWithAllowList = - new LockReleaseTokenPool(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPool.setRebalancer(OWNER); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } -} - -contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { - function test_SetRebalancer_Success() public { - assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); - s_lockReleaseTokenPool.setRebalancer(STRANGER); - assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); - } - - function test_SetRebalancer_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPool.setRebalancer(STRANGER); - } -} - -contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { - function test_Fuzz_LockOrBurnNoAllowList_Success( - uint256 amount - ) public { - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - vm.startPrank(s_allowedOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Success() public { - uint256 amount = 100; - vm.startPrank(s_allowedOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[1], - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Revert() public { - vm.startPrank(s_allowedOnRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: bytes(""), - amount: 100, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_PoolBurnRevertNotHealthy_Revert() public { - // Should not burn tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); - - vm.startPrank(s_allowedOnRamp); - vm.expectRevert(TokenPool.CursedByRMN.selector); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)), before); - } -} - -contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { - function setUp() public virtual override { - LockReleaseTokenPoolSetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_sourcePoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); - } - - function test_ReleaseOrMint_Success() public { - vm.startPrank(s_allowedOffRamp); - - uint256 amount = 100; - deal(address(s_token), address(s_lockReleaseTokenPool), amount); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Released(s_allowedOffRamp, OWNER, amount); - - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { - // Since the owner already has tokens this would break the checks - vm.assume(recipient != OWNER); - vm.assume(recipient != address(0)); - vm.assume(recipient != address(s_token)); - - // Makes sure the pool always has enough funds - deal(address(s_token), address(s_lockReleaseTokenPool), amount); - vm.startPrank(s_allowedOffRamp); - - uint256 capacity = _getInboundRateLimiterConfig().capacity; - // Determine if we hit the rate limit or the txs should succeed. - if (amount > capacity) { - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) - ); - } else { - // Only rate limit if the amount is >0 - if (amount > 0) { - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - } - - vm.expectEmit(); - emit TokenPool.Released(s_allowedOffRamp, recipient, amount); - } - - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_ChainNotAllowed_Revert() public { - address notAllowedRemotePoolAddress = address(1); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(notAllowedRemotePoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(s_allowedOffRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, SOURCE_CHAIN_SELECTOR)); - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_PoolMintNotHealthy_Revert() public { - // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_token.balanceOf(OWNER); - vm.startPrank(s_allowedOffRamp); - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - - assertEq(s_token.balanceOf(OWNER), before); - } -} - -contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { - function test_CanAcceptLiquidity_Success() public { - assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); - - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); - } -} - -contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_ProvideLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPool), amount); - - s_lockReleaseTokenPool.provideLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre - amount); - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), amount); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPool.provideLiquidity(1); - } - - function test_Fuzz_ExceedsAllowance( - uint256 amount - ) public { - vm.assume(amount > 0); - vm.expectRevert("ERC20: insufficient allowance"); - s_lockReleaseTokenPool.provideLiquidity(amount); - } - - function test_LiquidityNotAccepted_Revert() public { - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - - vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); - s_lockReleaseTokenPool.provideLiquidity(1); - } -} - -contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_WithdrawalLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPool), amount); - s_lockReleaseTokenPool.provideLiquidity(amount); - - s_lockReleaseTokenPool.withdrawLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPool.withdrawLiquidity(1); - } - - function test_InsufficientLiquidity_Revert() public { - uint256 maxUint256 = 2 ** 256 - 1; - s_token.approve(address(s_lockReleaseTokenPool), maxUint256); - s_lockReleaseTokenPool.provideLiquidity(maxUint256); - - vm.startPrank(address(s_lockReleaseTokenPool)); - s_token.transfer(OWNER, maxUint256); - vm.startPrank(OWNER); - - vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); - s_lockReleaseTokenPool.withdrawLiquidity(1); - } -} - -contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { - LockReleaseTokenPool internal s_oldLockReleaseTokenPool; - uint256 internal s_amount = 100000; - - function setUp() public virtual override { - super.setUp(); - - s_oldLockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); - } - - function test_transferLiquidity_Success() public { - uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - - s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - - vm.expectEmit(); - emit LockReleaseTokenPool.LiquidityTransferred(address(s_oldLockReleaseTokenPool), s_amount); - - s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); - } - - function test_transferLiquidity_transferTooMuch_Revert() public { - uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - - s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - - vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); - s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount + 1); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre); - } -} - -contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol deleted file mode 100644 index 766a487..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol +++ /dev/null @@ -1,785 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenPoolHelper} from "../helpers/TokenPoolHelper.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenPoolSetup is RouterSetup { - IERC20 internal s_token; - TokenPoolHelper internal s_tokenPool; - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - - s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPool_constructor is TokenPoolSetup { - function test_immutableFields_Success() public view { - assertEq(address(s_token), address(s_tokenPool.getToken())); - assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); - assertEq(false, s_tokenPool.getAllowListEnabled()); - assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); - } - - // Reverts - function test_ZeroAddressNotAllowed_Revert() public { - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - - s_tokenPool = new TokenPoolHelper(IERC20(address(0)), new address[](0), address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPool_getRemotePool is TokenPoolSetup { - function test_getRemotePool_Success() public { - uint64 chainSelector = 123124; - address remotePool = makeAddr("remotePool"); - address remoteToken = makeAddr("remoteToken"); - - // Zero indicates nothing is set - assertEq(0, s_tokenPool.getRemotePool(chainSelector).length); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(remotePool), - remoteTokenAddress: abi.encode(remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - - assertEq(remotePool, abi.decode(s_tokenPool.getRemotePool(chainSelector), (address))); - } -} - -contract TokenPool_setRemotePool is TokenPoolSetup { - function test_setRemotePool_Success() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; - address initialPool = makeAddr("remotePool"); - address remoteToken = makeAddr("remoteToken"); - // The new pool is a non-evm pool, as it doesn't fit in the normal 160 bits - bytes memory newPool = abi.encode(type(uint256).max); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(initialPool), - remoteTokenAddress: abi.encode(remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - - vm.expectEmit(); - emit TokenPool.RemotePoolSet(chainSelector, abi.encode(initialPool), newPool); - - s_tokenPool.setRemotePool(chainSelector, newPool); - - assertEq(keccak256(newPool), keccak256(s_tokenPool.getRemotePool(chainSelector))); - } - - // Reverts - - function test_setRemotePool_NonExistentChain_Reverts() public { - uint64 chainSelector = 123124; - bytes memory remotePool = abi.encode(makeAddr("remotePool")); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); - s_tokenPool.setRemotePool(chainSelector, remotePool); - } - - function test_setRemotePool_OnlyOwner_Reverts() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_tokenPool.setRemotePool(123124, abi.encode(makeAddr("remotePool"))); - } -} - -contract TokenPool_applyChainUpdates is TokenPoolSetup { - function assertState( - TokenPool.ChainUpdate[] memory chainUpdates - ) public view { - uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); - for (uint256 i = 0; i < chainUpdates.length; i++) { - assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i]); - } - - for (uint256 i = 0; i < chainUpdates.length; ++i) { - assertTrue(s_tokenPool.isSupportedChain(chainUpdates[i].remoteChainSelector)); - RateLimiter.TokenBucket memory bkt = - s_tokenPool.getCurrentOutboundRateLimiterState(chainUpdates[i].remoteChainSelector); - assertEq(bkt.capacity, chainUpdates[i].outboundRateLimiterConfig.capacity); - assertEq(bkt.rate, chainUpdates[i].outboundRateLimiterConfig.rate); - assertEq(bkt.isEnabled, chainUpdates[i].outboundRateLimiterConfig.isEnabled); - - bkt = s_tokenPool.getCurrentInboundRateLimiterState(chainUpdates[i].remoteChainSelector); - assertEq(bkt.capacity, chainUpdates[i].inboundRateLimiterConfig.capacity); - assertEq(bkt.rate, chainUpdates[i].inboundRateLimiterConfig.rate); - assertEq(bkt.isEnabled, chainUpdates[i].inboundRateLimiterConfig.isEnabled); - } - } - - function test_applyChainUpdates_Success() public { - RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); - RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); - RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); - RateLimiter.Config memory inboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e27, rate: 1e17}); - - // EVM chain, which uses the 160 bit evm address space - uint64 evmChainSelector = 1; - bytes memory evmRemotePool = abi.encode(makeAddr("evm_remote_pool")); - bytes memory evmRemoteToken = abi.encode(makeAddr("evm_remote_token")); - - // Non EVM chain, which uses the full 256 bits - uint64 nonEvmChainSelector = type(uint64).max; - bytes memory nonEvmRemotePool = abi.encode(keccak256("non_evm_remote_pool")); - bytes memory nonEvmRemoteToken = abi.encode(keccak256("non_evm_remote_token")); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: evmChainSelector, - remotePoolAddress: evmRemotePool, - remoteTokenAddress: evmRemoteToken, - allowed: true, - outboundRateLimiterConfig: outboundRateLimit1, - inboundRateLimiterConfig: inboundRateLimit1 - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: nonEvmChainSelector, - remotePoolAddress: nonEvmRemotePool, - remoteTokenAddress: nonEvmRemoteToken, - allowed: true, - outboundRateLimiterConfig: outboundRateLimit2, - inboundRateLimiterConfig: inboundRateLimit2 - }); - - // Assert configuration is applied - vm.expectEmit(); - emit TokenPool.ChainAdded( - chainUpdates[0].remoteChainSelector, - chainUpdates[0].remoteTokenAddress, - chainUpdates[0].outboundRateLimiterConfig, - chainUpdates[0].inboundRateLimiterConfig - ); - vm.expectEmit(); - emit TokenPool.ChainAdded( - chainUpdates[1].remoteChainSelector, - chainUpdates[1].remoteTokenAddress, - chainUpdates[1].outboundRateLimiterConfig, - chainUpdates[1].inboundRateLimiterConfig - ); - s_tokenPool.applyChainUpdates(chainUpdates); - // on1: rateLimit1, on2: rateLimit2, off1: rateLimit1, off2: rateLimit3 - assertState(chainUpdates); - - // Removing an non-existent chain should revert - TokenPool.ChainUpdate[] memory chainRemoves = new TokenPool.ChainUpdate[](1); - uint64 strangerChainSelector = 120938; - chainRemoves[0] = TokenPool.ChainUpdate({ - remoteChainSelector: strangerChainSelector, - remotePoolAddress: evmRemotePool, - remoteTokenAddress: evmRemoteToken, - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, strangerChainSelector)); - s_tokenPool.applyChainUpdates(chainRemoves); - // State remains - assertState(chainUpdates); - - // Can remove a chain - chainRemoves[0].remoteChainSelector = evmChainSelector; - - vm.expectEmit(); - emit TokenPool.ChainRemoved(chainRemoves[0].remoteChainSelector); - - s_tokenPool.applyChainUpdates(chainRemoves); - - // State updated, only chain 2 remains - TokenPool.ChainUpdate[] memory singleChainConfigured = new TokenPool.ChainUpdate[](1); - singleChainConfigured[0] = chainUpdates[1]; - assertState(singleChainConfigured); - - // Cannot reset already configured ramp - vm.expectRevert( - abi.encodeWithSelector(TokenPool.ChainAlreadyExists.selector, singleChainConfigured[0].remoteChainSelector) - ); - s_tokenPool.applyChainUpdates(singleChainConfigured); - } - - // Reverts - - function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_tokenPool.applyChainUpdates(new TokenPool.ChainUpdate[](0)); - } - - function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: "", - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) - }); - - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(2)), - remoteTokenAddress: "", - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) - }); - - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() public { - RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); - RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: outboundRateLimit, - inboundRateLimiterConfig: inboundRateLimit - }); - - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].allowed = false; - chainUpdates[0].outboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); - chainUpdates[0].inboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.DisabledNonZeroRateLimit.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_NonExistentChain_Revert() public { - RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); - RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: outboundRateLimit, - inboundRateLimiterConfig: inboundRateLimit - }); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainUpdates[0].remoteChainSelector)); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}) - }); - - // Outbound - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.rate = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.capacity = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.capacity = 101; - - s_tokenPool.applyChainUpdates(chainUpdates); - - // Change the chain selector as adding the same one would revert - chainUpdates[0].remoteChainSelector = 2; - - // Inbound - - chainUpdates[0].inboundRateLimiterConfig.capacity = 0; - chainUpdates[0].inboundRateLimiterConfig.rate = 0; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.rate = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.capacity = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.capacity = 101; - - s_tokenPool.applyChainUpdates(chainUpdates); - } -} - -contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { - uint64 internal s_remoteChainSelector; - - function setUp() public virtual override { - TokenPoolSetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - s_remoteChainSelector = 123124; - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: s_remoteChainSelector, - remotePoolAddress: abi.encode(address(2)), - remoteTokenAddress: abi.encode(address(3)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_Fuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { - // Cap the lower bound to 4 so 4/2 is still >= 2 - vm.assume(capacity >= 4); - // Cap the lower bound to 2 so 2/2 is still >= 1 - rate = uint128(bound(rate, 2, capacity - 2)); - // Bucket updates only work on increasing time - newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); - vm.warp(newTime); - - uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; - uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; - - RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); - RateLimiter.Config memory newInboundConfig = - RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newOutboundConfig); - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newInboundConfig); - vm.expectEmit(); - emit TokenPool.ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - s_tokenPool.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - - RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newOutboundConfig.capacity); - assertEq(bucket.rate, newOutboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - - expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); - - bucket = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newInboundConfig.capacity); - assertEq(bucket.rate, newInboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - } - - // Reverts - - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - s_tokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() - ); - } - - function test_NonExistentChain_Revert() public { - uint64 wrongChainSelector = 9084102894; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); - s_tokenPool.setChainRateLimiterConfig( - wrongChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() - ); - } -} - -contract LockRelease_setRateLimitAdmin is TokenPoolSetup { - function test_SetRateLimitAdmin_Success() public { - assertEq(address(0), s_tokenPool.getRateLimitAdmin()); - s_tokenPool.setRateLimitAdmin(OWNER); - assertEq(OWNER, s_tokenPool.getRateLimitAdmin()); - } - - // Reverts - - function test_SetRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_tokenPool.setRateLimitAdmin(STRANGER); - } -} - -contract TokenPool_onlyOnRamp is TokenPoolSetup { - function test_onlyOnRamp_Success() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - vm.startPrank(onRamp); - - s_tokenPool.onlyOnRampModifier(chainSelector); - } - - function test_ChainNotAllowed_Revert() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOnRampModifier(chainSelector); - - vm.startPrank(OWNER); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - vm.startPrank(onRamp); - // Should succeed now that we've added the chain - s_tokenPool.onlyOnRampModifier(chainSelector); - - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, onRamp)); - - s_tokenPool.onlyOnRampModifier(chainSelector); - } -} - -contract TokenPool_onlyOffRamp is TokenPoolSetup { - function test_onlyOffRamp_Success() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - - vm.startPrank(offRamp); - - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_ChainNotAllowed_Revert() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("onRamp"); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - - vm.startPrank(OWNER); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - - vm.startPrank(offRamp); - // Should succeed now that we've added the chain - s_tokenPool.onlyOffRampModifier(chainSelector); - - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("offRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, offRamp)); - - s_tokenPool.onlyOffRampModifier(chainSelector); - } -} - -contract TokenPoolWithAllowListSetup is TokenPoolSetup { - address[] internal s_allowedSenders; - - function setUp() public virtual override { - TokenPoolSetup.setUp(); - - s_allowedSenders.push(STRANGER); - s_allowedSenders.push(DUMMY_CONTRACT_ADDRESS); - - s_tokenPool = new TokenPoolHelper(s_token, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { - function test_GetAllowListEnabled_Success() public view { - assertTrue(s_tokenPool.getAllowListEnabled()); - } -} - -contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { - function test_SetRouter_Success() public { - assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); - - address newRouter = makeAddr("newRouter"); - - vm.expectEmit(); - emit TokenPool.RouterUpdated(address(s_sourceRouter), newRouter); - - s_tokenPool.setRouter(newRouter); - - assertEq(newRouter, s_tokenPool.getRouter()); - } -} - -contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { - function test_GetAllowList_Success() public view { - address[] memory setAddresses = s_tokenPool.getAllowList(); - assertEq(2, setAddresses.length); - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - } -} - -contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { - function test_SetAllowList_Success() public { - address[] memory newAddresses = new address[](2); - newAddresses[0] = address(1); - newAddresses[1] = address(2); - - for (uint256 i = 0; i < 2; ++i) { - vm.expectEmit(); - emit TokenPool.AllowListAdd(newAddresses[i]); - } - - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - address[] memory setAddresses = s_tokenPool.getAllowList(); - - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - assertEq(address(1), setAddresses[2]); - assertEq(address(2), setAddresses[3]); - - // address(2) exists noop, add address(3), remove address(1) - newAddresses = new address[](2); - newAddresses[0] = address(2); - newAddresses[1] = address(3); - - address[] memory removeAddresses = new address[](1); - removeAddresses[0] = address(1); - - vm.expectEmit(); - emit TokenPool.AllowListRemove(address(1)); - - vm.expectEmit(); - emit TokenPool.AllowListAdd(address(3)); - - s_tokenPool.applyAllowListUpdates(removeAddresses, newAddresses); - setAddresses = s_tokenPool.getAllowList(); - - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - assertEq(address(2), setAddresses[2]); - assertEq(address(3), setAddresses[3]); - - // remove all from allowList - for (uint256 i = 0; i < setAddresses.length; ++i) { - vm.expectEmit(); - emit TokenPool.AllowListRemove(setAddresses[i]); - } - - s_tokenPool.applyAllowListUpdates(setAddresses, new address[](0)); - setAddresses = s_tokenPool.getAllowList(); - - assertEq(0, setAddresses.length); - } - - function test_SetAllowListSkipsZero_Success() public { - uint256 setAddressesLength = s_tokenPool.getAllowList().length; - - address[] memory newAddresses = new address[](1); - newAddresses[0] = address(0); - - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - address[] memory setAddresses = s_tokenPool.getAllowList(); - - assertEq(setAddresses.length, setAddressesLength); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - address[] memory newAddresses = new address[](2); - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - } - - function test_AllowListNotEnabled_Revert() public { - s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - - vm.expectRevert(TokenPool.AllowListNotEnabled.selector); - - s_tokenPool.applyAllowListUpdates(new address[](0), new address[](2)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol deleted file mode 100644 index da5caba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol +++ /dev/null @@ -1,702 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; -import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -contract USDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; - - USDCTokenPoolHelper internal s_usdcTokenPool; - USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; - address[] internal s_allowedList; - - function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - _setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - - s_usdcTokenPool = - new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - - s_allowedList.push(USER_1); - s_usdcTokenPoolWithAllowList = - new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - s_usdcTokenPoolWithAllowList.applyChainUpdates(chainUpdates); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - s_usdcTokenPoolWithAllowList.setDomains(domains); - } - - function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } -} - -contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { - // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. - function test_LockOrBurn_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - uint256 amount = 1; - s_token.transfer(address(s_usdcTokenPool), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - receiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - } - - function test_Fuzz_LockOrBurn_Success(bytes32 destinationReceiver, uint256 amount) public { - vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - s_token.transfer(address(s_usdcTokenPool), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - destinationReceiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(destinationReceiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); - } - - function test_Fuzz_LockOrBurnWithAllowList_Success(bytes32 destinationReceiver, uint256 amount) public { - vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - s_token.transfer(address(s_usdcTokenPoolWithAllowList), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPoolWithAllowList.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPoolWithAllowList), - destinationReceiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: abi.encodePacked(destinationReceiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); - } - - // Reverts - function test_UnknownDomain_Revert() public { - uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; - // We need to setup the wrong chainSelector so it reaches the domain check - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: wrongDomain, onRamp: s_routerAllowedOnRamp}); - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: wrongDomain, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - - uint256 amount = 1000; - vm.startPrank(s_routerAllowedOnRamp); - deal(address(s_token), s_routerAllowedOnRamp, amount); - s_token.approve(address(s_usdcTokenPool), amount); - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.UnknownDomain.selector, wrongDomain)); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(address(0)), - amount: amount, - remoteChainSelector: wrongDomain, - localToken: address(s_token) - }) - ); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(address(0)), - amount: 0, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Revert() public { - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); - - s_usdcTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: abi.encodePacked(address(0)), - amount: 1000, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } -} - -contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { - // From https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/BurnMessage.sol#L57 - function _formatMessage( - uint32 _version, - bytes32 _burnToken, - bytes32 _mintRecipient, - uint256 _amount, - bytes32 _messageSender - ) internal pure returns (bytes memory) { - return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); - } - - function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { - vm.assume(recipient != address(0) && recipient != address(s_token)); - amount = bound(amount, 0, _getInboundRateLimiterConfig().capacity); - - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: SOURCE_DOMAIN_IDENTIFIER, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 0x060606060606, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(uint160(recipient))), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: _formatMessage( - 0, - bytes32(uint256(uint160(address(s_token)))), - bytes32(uint256(uint160(recipient))), - amount, - bytes32(uint256(uint160(OWNER))) - ) - }); - - bytes memory message = _generateUSDCMessage(usdcMessage); - bytes memory attestation = bytes("attestation bytes"); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode( - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: message, attestation: attestation})); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - vm.expectEmit(); - emit TokenPool.Minted(s_routerAllowedOffRamp, recipient, amount); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, message, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_ReleaseOrMintRealTx_Success() public { - bytes memory encodedUsdcMessage = - hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; - bytes memory attestation = bytes("attestation bytes"); - - uint32 nonce = 4730; - uint32 sourceDomain = 3; - uint256 amount = 100; - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - // Reverts - function test_UnlockingUSDCFailed_Revert() public { - vm.startPrank(s_routerAllowedOffRamp); - s_mockUSDCTransmitter.setShouldSucceed(false); - - uint256 amount = 13255235235; - - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: SOURCE_DOMAIN_IDENTIFIER, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 0x060606060606, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(uint160(address(s_mockUSDC)))), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: _formatMessage( - 0, - bytes32(uint256(uint160(address(s_token)))), - bytes32(uint256(uint160(OWNER))), - amount, - bytes32(uint256(uint160(OWNER))) - ) - }); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode( - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = abi.encode( - USDCTokenPool.MessageAndAttestation({message: _generateUSDCMessage(usdcMessage), attestation: bytes("")}) - ); - - vm.expectRevert(USDCTokenPool.UnlockingUSDCFailed.selector); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - function test_TokenMaxCapacityExceeded_Revert() public { - uint256 capacity = _getInboundRateLimiterConfig().capacity; - uint256 amount = 10 * capacity; - address recipient = address(1); - vm.startPrank(s_routerAllowedOffRamp); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: bytes(""), attestation: bytes("")})); - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) - ); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } -} - -contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); - } -} - -contract USDCTokenPool_setDomains is USDCTokenPoolSetup { - mapping(uint64 destChainSelector => USDCTokenPool.Domain domain) private s_chainToDomain; - - // Setting lower fuzz run as 256 runs was causing differing gas results in snapshot. - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 32 - function test_Fuzz_SetDomains_Success( - bytes32[5] calldata allowedCallers, - uint32[5] calldata domainIdentifiers, - uint64[5] calldata destChainSelectors - ) public { - uint256 numberOfDomains = allowedCallers.length; - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](numberOfDomains); - for (uint256 i = 0; i < numberOfDomains; ++i) { - vm.assume(allowedCallers[i] != bytes32(0) && domainIdentifiers[i] != 0 && destChainSelectors[i] != 0); - - domainUpdates[i] = USDCTokenPool.DomainUpdate({ - allowedCaller: allowedCallers[i], - domainIdentifier: domainIdentifiers[i], - destChainSelector: destChainSelectors[i], - enabled: true - }); - - s_chainToDomain[destChainSelectors[i]] = - USDCTokenPool.Domain({domainIdentifier: domainIdentifiers[i], allowedCaller: allowedCallers[i], enabled: true}); - } - - vm.expectEmit(); - emit USDCTokenPool.DomainsSet(domainUpdates); - - s_usdcTokenPool.setDomains(domainUpdates); - - for (uint256 i = 0; i < numberOfDomains; ++i) { - USDCTokenPool.Domain memory expected = s_chainToDomain[destChainSelectors[i]]; - USDCTokenPool.Domain memory got = s_usdcTokenPool.getDomain(destChainSelectors[i]); - assertEq(got.allowedCaller, expected.allowedCaller); - assertEq(got.domainIdentifier, expected.domainIdentifier); - } - } - - // Reverts - - function test_OnlyOwner_Revert() public { - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); - - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - - s_usdcTokenPool.setDomains(domainUpdates); - } - - function test_InvalidDomain_Revert() public { - bytes32 validCaller = bytes32(uint256(25)); - // Ensure valid domain works - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); - domainUpdates[0] = USDCTokenPool.DomainUpdate({ - allowedCaller: validCaller, - domainIdentifier: 0, // ensures 0 is valid, as this is eth mainnet - destChainSelector: 45690, - enabled: true - }); - - s_usdcTokenPool.setDomains(domainUpdates); - - // Make update invalid on allowedCaller - domainUpdates[0].allowedCaller = bytes32(0); - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); - - s_usdcTokenPool.setDomains(domainUpdates); - - // Make valid again - domainUpdates[0].allowedCaller = validCaller; - - // Make invalid on destChainSelector - domainUpdates[0].destChainSelector = 0; - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); - - s_usdcTokenPool.setDomains(domainUpdates); - } -} - -contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { - function test_Fuzz_ValidateMessage_Success(uint32 sourceDomain, uint64 nonce) public { - vm.pauseGasMetering(); - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: sourceDomain, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: nonce, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(299999)), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") - }); - - bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - vm.resumeGasMetering(); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain}) - ); - } - - // Reverts - - function test_ValidateInvalidMessage_Revert() public { - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: 1553252, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 387289284924, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(92398429395823)), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") - }); - - USDCTokenPool.SourceTokenDataPayload memory sourceTokenData = - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}); - - bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); - - uint32 expectedSourceDomain = usdcMessage.sourceDomain + 1; - - vm.expectRevert( - abi.encodeWithSelector(USDCTokenPool.InvalidSourceDomain.selector, expectedSourceDomain, usdcMessage.sourceDomain) - ); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: expectedSourceDomain}) - ); - - uint64 expectedNonce = usdcMessage.nonce + 1; - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidNonce.selector, expectedNonce, usdcMessage.nonce)); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, - USDCTokenPool.SourceTokenDataPayload({nonce: expectedNonce, sourceDomain: usdcMessage.sourceDomain}) - ); - - usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER + 1; - vm.expectRevert( - abi.encodeWithSelector( - USDCTokenPool.InvalidDestinationDomain.selector, DEST_DOMAIN_IDENTIFIER, usdcMessage.destinationDomain - ) - ); - - s_usdcTokenPool.validateMessage( - _generateUSDCMessage(usdcMessage), - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}) - ); - usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER; - - uint32 wrongVersion = usdcMessage.version + 1; - - usdcMessage.version = wrongVersion; - encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidMessageVersion.selector, wrongVersion)); - s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol deleted file mode 100644 index a7d73cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ /dev/null @@ -1,1196 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; -import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BaseTest} from "../BaseTest.t.sol"; - -import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; -import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; -import {stdError} from "forge-std/Test.sol"; -import {Vm} from "forge-std/Vm.sol"; - -contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { - MultiAggregateRateLimiterHelper internal s_rateLimiter; - - address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; - uint224 internal constant TOKEN_PRICE = 4e18; - - uint64 internal constant CHAIN_SELECTOR_1 = 5009297550715157269; - uint64 internal constant CHAIN_SELECTOR_2 = 4949039107694359620; - - RateLimiter.Config internal RATE_LIMITER_CONFIG_1 = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); - RateLimiter.Config internal RATE_LIMITER_CONFIG_2 = RateLimiter.Config({isEnabled: true, rate: 10, capacity: 200}); - - address internal immutable MOCK_OFFRAMP = address(1111); - address internal immutable MOCK_ONRAMP = address(1112); - - address[] internal s_authorizedCallers; - - function setUp() public virtual override(BaseTest, FeeQuoterSetup) { - BaseTest.setUp(); - FeeQuoterSetup.setUp(); - - Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); - s_feeQuoter.updatePrices(priceUpdates); - - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](4); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_2, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_2 - }); - configUpdates[2] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: true, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - configUpdates[3] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_2, - isOutboundLane: true, - rateLimiterConfig: RATE_LIMITER_CONFIG_2 - }); - - s_authorizedCallers = new address[](2); - s_authorizedCallers[0] = MOCK_OFFRAMP; - s_authorizedCallers[1] = MOCK_ONRAMP; - - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), s_authorizedCallers); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - } - - function _assertConfigWithTokenBucketEquality( - RateLimiter.Config memory config, - RateLimiter.TokenBucket memory tokenBucket - ) internal pure { - assertEq(config.rate, tokenBucket.rate); - assertEq(config.capacity, tokenBucket.capacity); - assertEq(config.capacity, tokenBucket.tokens); - assertEq(config.isEnabled, tokenBucket.isEnabled); - } - - function _assertTokenBucketEquality( - RateLimiter.TokenBucket memory tokenBucketA, - RateLimiter.TokenBucket memory tokenBucketB - ) internal pure { - assertEq(tokenBucketA.rate, tokenBucketB.rate); - assertEq(tokenBucketA.capacity, tokenBucketB.capacity); - assertEq(tokenBucketA.tokens, tokenBucketB.tokens); - assertEq(tokenBucketA.isEnabled, tokenBucketB.isEnabled); - } - - function _generateAny2EVMMessage( - uint64 sourceChainSelector, - Client.EVMTokenAmount[] memory tokenAmounts - ) internal pure returns (Client.Any2EVMMessage memory) { - return Client.Any2EVMMessage({ - messageId: keccak256(bytes("messageId")), - sourceChainSelector: sourceChainSelector, - sender: abi.encode(OWNER), - data: abi.encode(0), - destTokenAmounts: tokenAmounts - }); - } - - function _generateAny2EVMMessageNoTokens( - uint64 sourceChainSelector - ) internal pure returns (Client.Any2EVMMessage memory) { - return _generateAny2EVMMessage(sourceChainSelector, new Client.EVMTokenAmount[](0)); - } -} - -contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { - function test_ConstructorNoAuthorizedCallers_Success() public { - address[] memory authorizedCallers = new address[](0); - - vm.recordLogs(); - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); - - // FeeQuoterSet - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - - assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); - } - - function test_Constructor_Success() public { - address[] memory authorizedCallers = new address[](2); - authorizedCallers[0] = MOCK_OFFRAMP; - authorizedCallers[1] = MOCK_ONRAMP; - - vm.expectEmit(); - emit MultiAggregateRateLimiter.FeeQuoterSet(address(s_feeQuoter)); - - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); - - assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); - assertEq(s_rateLimiter.typeAndVersion(), "MultiAggregateRateLimiter 1.6.0-dev"); - } -} - -contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { - function test_Owner_Success() public { - address newAddress = address(42); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.FeeQuoterSet(newAddress); - - s_rateLimiter.setFeeQuoter(newAddress); - assertEq(newAddress, s_rateLimiter.getFeeQuoter()); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(bytes("Only callable by owner")); - - s_rateLimiter.setFeeQuoter(STRANGER); - } - - function test_ZeroAddress_Revert() public { - vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - s_rateLimiter.setFeeQuoter(address(0)); - } -} - -contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { - function test_GetTokenBucket_Success() public view { - RateLimiter.TokenBucket memory bucketInbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketInbound); - assertEq(BLOCK_TIME, bucketInbound.lastUpdated); - - RateLimiter.TokenBucket memory bucketOutbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketOutbound); - assertEq(BLOCK_TIME, bucketOutbound.lastUpdated); - } - - function test_Refill_Success() public { - RATE_LIMITER_CONFIG_1.capacity = RATE_LIMITER_CONFIG_1.capacity * 2; - - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - - assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); - assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); - assertEq(RATE_LIMITER_CONFIG_1.capacity / 2, bucket.tokens); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - - assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); - assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); - assertEq(RATE_LIMITER_CONFIG_1.capacity / 2 + warpTime * RATE_LIMITER_CONFIG_1.rate, bucket.tokens); - assertEq(BLOCK_TIME + warpTime, bucket.lastUpdated); - - vm.warp(BLOCK_TIME + warpTime * 100); - - // Bucket overflow - bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); - } - - // Reverts - - function test_TimeUnderflow_Revert() public { - vm.warp(BLOCK_TIME - 1); - - vm.expectRevert(stdError.arithmeticError); - s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - } -} - -contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { - function test_ZeroConfigs_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - } - - function test_SingleConfig_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + 1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig - ); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - - RateLimiter.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); - _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); - assertEq(BLOCK_TIME, bucket1.lastUpdated); - } - - function test_SingleConfigOutbound_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + 1, - isOutboundLane: true, - rateLimiterConfig: RATE_LIMITER_CONFIG_2 - }); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, true, configUpdates[0].rateLimiterConfig - ); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - - RateLimiter.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, true); - _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); - assertEq(BLOCK_TIME, bucket1.lastUpdated); - } - - function test_MultipleConfigs_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](5); - - for (uint64 i; i < configUpdates.length; ++i) { - configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + i + 1, - isOutboundLane: i % 2 == 0 ? false : true, - rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) - }); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane, configUpdates[i].rateLimiterConfig - ); - } - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, configUpdates.length); - - for (uint256 i; i < configUpdates.length; ++i) { - RateLimiter.TokenBucket memory bucket = - s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane); - _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } - } - - function test_MultipleConfigsBothLanes_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); - - for (uint64 i; i < configUpdates.length; ++i) { - configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + 1, - isOutboundLane: i % 2 == 0 ? false : true, - rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) - }); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane, configUpdates[i].rateLimiterConfig - ); - } - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, configUpdates.length); - - for (uint256 i; i < configUpdates.length; ++i) { - RateLimiter.TokenBucket memory bucket = - s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutboundLane); - _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } - } - - function test_UpdateExistingConfig_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_2 - }); - - RateLimiter.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); - - // Capacity equals tokens - assertEq(bucket1.capacity, bucket1.tokens); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig - ); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - vm.warp(BLOCK_TIME + 1); - bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); - assertEq(BLOCK_TIME + 1, bucket1.lastUpdated); - - // Tokens < capacity since capacity doubled - assertTrue(bucket1.capacity != bucket1.tokens); - - // Outbound lane config remains unchanged - _assertConfigWithTokenBucketEquality( - RATE_LIMITER_CONFIG_1, s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true) - ); - } - - function test_UpdateExistingConfigWithNoDifference_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - - RateLimiter.TokenBucket memory bucketPreUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig - ); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - vm.warp(BLOCK_TIME + 1); - RateLimiter.TokenBucket memory bucketPostUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); - _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); - assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); - } - - // Reverts - function test_ZeroChainSelector_Revert() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: 0, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - - vm.expectRevert(MultiAggregateRateLimiter.ZeroChainSelectorNotAllowed.selector); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - } - - function test_OnlyCallableByOwner_Revert() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + 1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - } -} - -contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSetup { - function test_GetTokenValue_Success() public view { - uint256 numberOfTokens = 10; - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); - uint256 value = s_rateLimiter.getTokenValue(tokenAmount); - assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); - } - - // Reverts - function test_NoTokenPrice_Reverts() public { - address tokenWithNoPrice = makeAddr("Token with no price"); - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); - - vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); - s_rateLimiter.getTokenValue(tokenAmount); - } -} - -contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLimiterSetup { - function setUp() public virtual override { - super.setUp(); - - // Clear rate limit tokens state - MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = - new MultiAggregateRateLimiter.LocalRateLimitToken[](s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - removes[i] = MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[i] - }); - } - s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); - } - - function test_UpdateRateLimitTokensSingleChain_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[0] - }), - remoteToken: abi.encode(s_sourceTokens[0]) - }); - adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[1] - }), - remoteToken: abi.encode(s_sourceTokens[1]) - }); - - for (uint256 i = 0; i < adds.length; ++i) { - vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( - CHAIN_SELECTOR_1, adds[i].remoteToken, adds[i].localTokenArgs.localToken - ); - } - - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - - (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); - - assertEq(localTokens.length, adds.length); - assertEq(localTokens.length, remoteTokens.length); - - for (uint256 i = 0; i < adds.length; ++i) { - assertEq(adds[i].remoteToken, remoteTokens[i]); - assertEq(adds[i].localTokenArgs.localToken, localTokens[i]); - } - } - - function test_UpdateRateLimitTokensMultipleChains_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[0] - }), - remoteToken: abi.encode(s_sourceTokens[0]) - }); - adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_2, - localToken: s_destTokens[1] - }), - remoteToken: abi.encode(s_sourceTokens[1]) - }); - - for (uint256 i = 0; i < adds.length; ++i) { - vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( - adds[i].localTokenArgs.remoteChainSelector, adds[i].remoteToken, adds[i].localTokenArgs.localToken - ); - } - - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - - (address[] memory localTokensChain1, bytes[] memory remoteTokensChain1) = - s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); - - assertEq(localTokensChain1.length, 1); - assertEq(localTokensChain1.length, remoteTokensChain1.length); - assertEq(localTokensChain1[0], adds[0].localTokenArgs.localToken); - assertEq(remoteTokensChain1[0], adds[0].remoteToken); - - (address[] memory localTokensChain2, bytes[] memory remoteTokensChain2) = - s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_2); - - assertEq(localTokensChain2.length, 1); - assertEq(localTokensChain2.length, remoteTokensChain2.length); - assertEq(localTokensChain2[0], adds[1].localTokenArgs.localToken); - assertEq(remoteTokensChain2[0], adds[1].remoteToken); - } - - function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[0] - }), - remoteToken: abi.encode(s_sourceTokens[0]) - }); - adds[1] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[1] - }), - remoteToken: abi.encode(s_sourceTokens[1]) - }); - - MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = - new MultiAggregateRateLimiter.LocalRateLimitToken[](1); - removes[0] = adds[0].localTokenArgs; - - for (uint256 i = 0; i < adds.length; ++i) { - vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded( - CHAIN_SELECTOR_1, adds[i].remoteToken, adds[i].localTokenArgs.localToken - ); - } - - s_rateLimiter.updateRateLimitTokens(removes, adds); - - for (uint256 i = 0; i < removes.length; ++i) { - vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitRemoved(CHAIN_SELECTOR_1, removes[i].localToken); - } - - s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); - - (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); - - assertEq(1, remoteTokens.length); - assertEq(adds[1].remoteToken, remoteTokens[0]); - - assertEq(1, localTokens.length); - assertEq(adds[1].localTokenArgs.localToken, localTokens[0]); - } - - function test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](0); - - MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = - new MultiAggregateRateLimiter.LocalRateLimitToken[](1); - removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[0] - }); - - vm.recordLogs(); - s_rateLimiter.updateRateLimitTokens(removes, adds); - - // No event since no remove occurred - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - - (address[] memory localTokens, bytes[] memory remoteTokens) = s_rateLimiter.getAllRateLimitTokens(CHAIN_SELECTOR_1); - - assertEq(localTokens.length, 0); - assertEq(localTokens.length, remoteTokens.length); - } - - // Reverts - - function test_ZeroSourceToken_Revert() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); - adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[0] - }), - remoteToken: new bytes(0) - }); - - vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - } - - function test_ZeroDestToken_Revert() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); - adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: address(0) - }), - remoteToken: abi.encode(s_destTokens[0]) - }); - - vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - } - - function test_NonOwner_Revert() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](4); - - vm.startPrank(STRANGER); - - vm.expectRevert(bytes("Only callable by owner")); - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); - } -} - -contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiterSetup { - address internal immutable MOCK_RECEIVER = address(1113); - - function setUp() public virtual override { - super.setUp(); - - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); - for (uint224 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[i] - }), - remoteToken: abi.encode(s_sourceTokens[i]) - }); - - Internal.PriceUpdates memory priceUpdates = - _getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); - s_feeQuoter.updatePrices(priceUpdates); - } - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - } - - function test_ValidateMessageWithNoTokens_Success() public { - vm.startPrank(MOCK_OFFRAMP); - - vm.recordLogs(); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); - - // No consumed rate limit events - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - } - - function test_ValidateMessageWithTokens_Success() public { - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 3}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); - - // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) - vm.expectEmit(); - emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - } - - function test_ValidateMessageWithDisabledRateLimitToken_Success() public { - MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = - new MultiAggregateRateLimiter.LocalRateLimitToken[](1); - removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_destTokens[1] - }); - s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 5}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); - - vm.startPrank(MOCK_OFFRAMP); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - } - - function test_ValidateMessageWithRateLimitDisabled_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: false, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - configUpdates[0].rateLimiterConfig.isEnabled = false; - - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 1000}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 50}); - - vm.startPrank(MOCK_OFFRAMP); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // No consumed rate limit events - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 0); - } - - function test_ValidateMessageWithTokensOnDifferentChains_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); - for (uint224 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_2, - localToken: s_destTokens[i] - }), - // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: abi.encode(uint256(uint160(s_sourceTokens[i])) + type(uint160).max + 1) - }); - } - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 2}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); - - // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) - uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // Chain 1 changed - RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 unchanged - RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); - assertEq(bucketChain2.capacity, bucketChain2.tokens); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(totalValue); - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); - - // Chain 1 unchanged - bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 changed - bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); - assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); - } - - function test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); - - // Only 1 rate limited token on different chain - tokensToAdd[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_2, - localToken: s_destTokens[0] - }), - // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: abi.encode(uint256(uint160(s_sourceTokens[0])) + type(uint160).max + 1) - }); - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 3}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); - - // 3 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) - uint256 totalValue = (5 * TOKEN_PRICE) / 1e18; - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // Chain 1 changed - RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 unchanged - RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); - assertEq(bucketChain2.capacity, bucketChain2.tokens); - - // 3 tokens * (TOKEN_PRICE) - uint256 totalValue2 = (3 * TOKEN_PRICE) / 1e18; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(totalValue2); - - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); - - // Chain 1 unchanged - bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 changed - bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); - assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); - } - - function test_ValidateMessageWithRateLimitReset_Success() public { - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 20}); - - // Remaining capacity: 100 -> 20 - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) - vm.warp(BLOCK_TIME + 3); - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - - // Remaining capacity: 35 -> 80 (can fit exactly 80) - vm.warp(BLOCK_TIME + 12); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - } - - // Reverts - - function test_ValidateMessageWithRateLimitExceeded_Revert() public { - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 80}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 30}); - - uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - } - - function test_ValidateMessageFromUnauthorizedCaller_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); - } -} - -contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimiterSetup { - function setUp() public virtual override { - super.setUp(); - - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); - for (uint224 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_sourceTokens[i] - }), - remoteToken: abi.encode(bytes20(s_destTokenBySourceToken[s_sourceTokens[i]])) - }); - - Internal.PriceUpdates memory priceUpdates = - _getSingleTokenPriceUpdateStruct(s_sourceTokens[i], TOKEN_PRICE * (i + 1)); - s_feeQuoter.updatePrices(priceUpdates); - } - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - } - - function test_ValidateMessageWithNoTokens_Success() public { - vm.startPrank(MOCK_ONRAMP); - - vm.recordLogs(); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); - - // No consumed rate limit events - assertEq(vm.getRecordedLogs().length, 0); - } - - function test_onOutboundMessage_ValidateMessageWithTokens_Success() public { - vm.startPrank(MOCK_ONRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 3}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); - - // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) - vm.expectEmit(); - emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - } - - function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() public { - MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = - new MultiAggregateRateLimiter.LocalRateLimitToken[](1); - removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_1, - localToken: s_sourceTokens[1] - }); - s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 5}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); - - vm.startPrank(MOCK_ONRAMP); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - } - - function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() public { - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1, - isOutboundLane: true, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - configUpdates[0].rateLimiterConfig.isEnabled = false; - - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 1000}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 50}); - - vm.startPrank(MOCK_ONRAMP); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // No consumed rate limit events - assertEq(vm.getRecordedLogs().length, 0); - } - - function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); - for (uint224 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_2, - localToken: s_sourceTokens[i] - }), - // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[i]])) + type(uint160).max + 1) - }); - } - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - - vm.startPrank(MOCK_ONRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 2}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); - - // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) - uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // Chain 1 changed - RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 unchanged - RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); - assertEq(bucketChain2.capacity, bucketChain2.tokens); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(totalValue); - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_2, _generateEVM2AnyMessage(tokenAmounts)); - - // Chain 1 unchanged - bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 changed - bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); - assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); - } - - function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { - MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = - new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); - - // Only 1 rate limited token on different chain - tokensToAdd[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ - localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ - remoteChainSelector: CHAIN_SELECTOR_2, - localToken: s_sourceTokens[0] - }), - // Create a remote token address that is different from CHAIN_SELECTOR_1 - remoteToken: abi.encode(uint256(uint160(s_destTokenBySourceToken[s_sourceTokens[0]])) + type(uint160).max + 1) - }); - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); - - vm.startPrank(MOCK_ONRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 3}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 1}); - - // 3 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) - uint256 totalValue = (5 * TOKEN_PRICE) / 1e18; - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // Chain 1 changed - RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 unchanged - RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); - assertEq(bucketChain2.capacity, bucketChain2.tokens); - - // 3 tokens * (TOKEN_PRICE) - uint256 totalValue2 = (3 * TOKEN_PRICE) / 1e18; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(totalValue2); - - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_2, _generateEVM2AnyMessage(tokenAmounts)); - - // Chain 1 unchanged - bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); - - // Chain 2 changed - bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, true); - assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); - } - - function test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() public { - vm.startPrank(MOCK_ONRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 20}); - - // Remaining capacity: 100 -> 20 - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) - vm.warp(BLOCK_TIME + 3); - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - - // Remaining capacity: 35 -> 80 (can fit exactly 80) - vm.warp(BLOCK_TIME + 12); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - } - - function test_RateLimitValueDifferentLanes_Success() public { - vm.pauseGasMetering(); - // start from blocktime that does not equal rate limiter init timestamp - vm.warp(BLOCK_TIME + 1); - - // 10 (tokens) * 4 (price) * 2 (number of times) = 80 < 100 (capacity) - uint256 numberOfTokens = 10; - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: numberOfTokens}); - uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(value); - - vm.resumeGasMetering(); - vm.startPrank(MOCK_ONRAMP); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - vm.pauseGasMetering(); - - // Get the updated bucket status - RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - - // Assert the proper value has been taken out of the bucket - assertEq(bucket1.capacity - value, bucket1.tokens); - // Inbound lane should remain unchanged - assertEq(bucket2.capacity, bucket2.tokens); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(value); - - vm.resumeGasMetering(); - s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); - vm.pauseGasMetering(); - - bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); - bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); - - // Inbound lane should remain unchanged - assertEq(bucket1.capacity - value, bucket1.tokens); - assertEq(bucket2.capacity - value, bucket2.tokens); - } - - // Reverts - - function test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() public { - vm.startPrank(MOCK_OFFRAMP); - - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); - tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: 80}); - tokenAmounts[1] = Client.EVMTokenAmount({token: s_sourceTokens[1], amount: 30}); - - uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; - vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); - } - - function test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); - } - - function _generateEVM2AnyMessage( - Client.EVMTokenAmount[] memory tokenAmounts - ) public view returns (Client.EVM2AnyMessage memory) { - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateEVM2AnyMessageNoTokens() internal view returns (Client.EVM2AnyMessage memory) { - return _generateEVM2AnyMessage(new Client.EVMTokenAmount[](0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol deleted file mode 100644 index efcdfd8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/ARMProxy.t.sol +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMN} from "../../interfaces/IRMN.sol"; - -import {ARMProxy} from "../../rmn/ARMProxy.sol"; -import {MockRMN} from "../mocks/MockRMN.sol"; -import {Test} from "forge-std/Test.sol"; - -contract ARMProxyTest is Test { - MockRMN internal s_mockRMN; - ARMProxy internal s_armProxy; - - function setUp() public virtual { - s_mockRMN = new MockRMN(); - s_armProxy = new ARMProxy(address(s_mockRMN)); - } - - function test_ARMIsCursed_Success() public { - s_armProxy.setARM(address(s_mockRMN)); - assertFalse(IRMN(address(s_armProxy)).isCursed()); - s_mockRMN.setGlobalCursed(true); - assertTrue(IRMN(address(s_armProxy)).isCursed()); - } - - function test_ARMCallRevertReasonForwarded() public { - bytes memory err = bytes("revert"); - s_mockRMN.setIsCursedRevert(err); - s_armProxy.setARM(address(s_mockRMN)); - vm.expectRevert(abi.encodeWithSelector(MockRMN.CustomError.selector, err)); - IRMN(address(s_armProxy)).isCursed(); - } -} - -contract ARMProxyStandaloneTest is Test { - address internal constant EMPTY_ADDRESS = address(0x1); - address internal constant OWNER_ADDRESS = 0xC0ffeeEeC0fFeeeEc0ffeEeEc0ffEEEEC0FfEEee; - address internal constant MOCK_RMN_ADDRESS = 0x1337133713371337133713371337133713371337; - - ARMProxy internal s_armProxy; - - function setUp() public virtual { - // needed so that the extcodesize check in ARMProxy.fallback doesn't revert - vm.etch(MOCK_RMN_ADDRESS, bytes("fake bytecode")); - - vm.prank(OWNER_ADDRESS); - s_armProxy = new ARMProxy(MOCK_RMN_ADDRESS); - } - - function test_Constructor() public { - vm.expectEmit(); - emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); - ARMProxy proxy = new ARMProxy(MOCK_RMN_ADDRESS); - assertEq(proxy.getARM(), MOCK_RMN_ADDRESS); - } - - function test_SetARM() public { - vm.expectEmit(); - emit ARMProxy.ARMSet(MOCK_RMN_ADDRESS); - vm.prank(OWNER_ADDRESS); - s_armProxy.setARM(MOCK_RMN_ADDRESS); - assertEq(s_armProxy.getARM(), MOCK_RMN_ADDRESS); - } - - function test_SetARMzero() public { - vm.expectRevert(abi.encodeWithSelector(ARMProxy.ZeroAddressNotAllowed.selector)); - vm.prank(OWNER_ADDRESS); - s_armProxy.setARM(address(0x0)); - } - - function test_ARMCallEmptyContractRevert() public { - vm.prank(OWNER_ADDRESS); - s_armProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. - vm.expectRevert(); - bytes memory b = new bytes(0); - (bool success,) = address(s_armProxy).call(b); - success; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol deleted file mode 100644 index c5226d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Internal} from "../../libraries/Internal.sol"; -import {RMNHome} from "../../rmn/RMNHome.sol"; -import {Test} from "forge-std/Test.sol"; -import {Vm} from "forge-std/Vm.sol"; - -contract RMNHomeTest is Test { - struct Config { - RMNHome.StaticConfig staticConfig; - RMNHome.DynamicConfig dynamicConfig; - } - - bytes32 internal constant ZERO_DIGEST = bytes32(uint256(0)); - RMNHome public s_rmnHome = new RMNHome(); - - function _getBaseConfig() internal pure returns (Config memory) { - RMNHome.Node[] memory nodes = new RMNHome.Node[](3); - nodes[0] = RMNHome.Node({peerId: keccak256("peerId_0"), offchainPublicKey: keccak256("offchainPublicKey_0")}); - nodes[1] = RMNHome.Node({peerId: keccak256("peerId_1"), offchainPublicKey: keccak256("offchainPublicKey_1")}); - nodes[2] = RMNHome.Node({peerId: keccak256("peerId_2"), offchainPublicKey: keccak256("offchainPublicKey_2")}); - - RMNHome.SourceChain[] memory sourceChains = new RMNHome.SourceChain[](2); - // Observer 0 for source chain 9000 - sourceChains[0] = RMNHome.SourceChain({chainSelector: 9000, minObservers: 1, observerNodesBitmap: 1 << 0}); - // Observers 1 and 2 for source chain 9001 - sourceChains[1] = RMNHome.SourceChain({chainSelector: 9001, minObservers: 2, observerNodesBitmap: 1 << 1 | 1 << 2}); - - return Config({ - staticConfig: RMNHome.StaticConfig({nodes: nodes, offchainConfig: abi.encode("static_config")}), - dynamicConfig: RMNHome.DynamicConfig({sourceChains: sourceChains, offchainConfig: abi.encode("dynamic_config")}) - }); - } - - uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 private constant PREFIX = 0x000b << (256 - 16); // 0x000b00..00 - - function _getConfigDigest(bytes memory staticConfig, uint32 version) internal view returns (bytes32) { - return bytes32( - (PREFIX & PREFIX_MASK) - | ( - uint256( - keccak256(bytes.concat(abi.encode(bytes32("EVM"), block.chainid, address(s_rmnHome), version), staticConfig)) - ) & ~PREFIX_MASK - ) - ); - } -} - -contract RMNHome_getConfigDigests is RMNHomeTest { - function test_getConfigDigests_success() public { - (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, ZERO_DIGEST); - assertEq(candidateDigest, ZERO_DIGEST); - - Config memory config = _getBaseConfig(); - bytes32 firstDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, ZERO_DIGEST); - assertEq(candidateDigest, firstDigest); - - s_rmnHome.promoteCandidateAndRevokeActive(firstDigest, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, firstDigest); - assertEq(candidateDigest, ZERO_DIGEST); - - bytes32 secondDigest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - (activeDigest, candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, firstDigest); - assertEq(candidateDigest, secondDigest); - - assertEq(activeDigest, s_rmnHome.getActiveDigest()); - assertEq(candidateDigest, s_rmnHome.getCandidateDigest()); - } -} - -contract RMNHome_setCandidate is RMNHomeTest { - function test_setCandidate_success() public { - Config memory config = _getBaseConfig(); - RMNHome.VersionedConfig memory versionedConfig = RMNHome.VersionedConfig({ - version: 1, - staticConfig: config.staticConfig, - dynamicConfig: config.dynamicConfig, - configDigest: ZERO_DIGEST - }); - - versionedConfig.configDigest = _getConfigDigest(abi.encode(versionedConfig.staticConfig), versionedConfig.version); - - vm.expectEmit(); - emit RMNHome.ConfigSet( - versionedConfig.configDigest, versionedConfig.version, versionedConfig.staticConfig, versionedConfig.dynamicConfig - ); - - s_rmnHome.setCandidate(versionedConfig.staticConfig, versionedConfig.dynamicConfig, ZERO_DIGEST); - - (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(versionedConfig.configDigest); - assertTrue(ok); - assertEq(storedVersionedConfig.version, versionedConfig.version); - RMNHome.StaticConfig memory storedStaticConfig = storedVersionedConfig.staticConfig; - RMNHome.DynamicConfig memory storedDynamicConfig = storedVersionedConfig.dynamicConfig; - - assertEq(storedStaticConfig.nodes.length, versionedConfig.staticConfig.nodes.length); - for (uint256 i = 0; i < storedStaticConfig.nodes.length; i++) { - RMNHome.Node memory storedNode = storedStaticConfig.nodes[i]; - assertEq(storedNode.peerId, versionedConfig.staticConfig.nodes[i].peerId); - assertEq(storedNode.offchainPublicKey, versionedConfig.staticConfig.nodes[i].offchainPublicKey); - } - - assertEq(storedDynamicConfig.sourceChains.length, versionedConfig.dynamicConfig.sourceChains.length); - for (uint256 i = 0; i < storedDynamicConfig.sourceChains.length; i++) { - RMNHome.SourceChain memory storedSourceChain = storedDynamicConfig.sourceChains[i]; - assertEq(storedSourceChain.chainSelector, versionedConfig.dynamicConfig.sourceChains[i].chainSelector); - assertEq(storedSourceChain.minObservers, versionedConfig.dynamicConfig.sourceChains[i].minObservers); - assertEq(storedSourceChain.observerNodesBitmap, versionedConfig.dynamicConfig.sourceChains[i].observerNodesBitmap); - } - assertEq(storedDynamicConfig.offchainConfig, versionedConfig.dynamicConfig.offchainConfig); - assertEq(storedStaticConfig.offchainConfig, versionedConfig.staticConfig.offchainConfig); - } - - function test_setCandidate_ConfigDigestMismatch_reverts() public { - Config memory config = _getBaseConfig(); - - bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, digest, ZERO_DIGEST)); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - vm.expectEmit(); - emit RMNHome.CandidateConfigRevoked(digest); - - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, digest); - } - - function test_setCandidate_OnlyOwner_reverts() public { - Config memory config = _getBaseConfig(); - - vm.startPrank(address(0)); - - vm.expectRevert("Only callable by owner"); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } -} - -contract RMNHome_revokeCandidate is RMNHomeTest { - // Sets two configs - function setUp() public { - Config memory config = _getBaseConfig(); - bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - s_rmnHome.promoteCandidateAndRevokeActive(digest, ZERO_DIGEST); - - config.dynamicConfig.sourceChains[0].minObservers--; - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_revokeCandidate_success() public { - (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); - - vm.expectEmit(); - emit RMNHome.CandidateConfigRevoked(priorCandidateDigest); - - s_rmnHome.revokeCandidate(priorCandidateDigest); - - (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(priorCandidateDigest); - assertFalse(ok); - // Ensure no old data is returned, even though it's still in storage - assertEq(storedVersionedConfig.version, 0); - assertEq(storedVersionedConfig.staticConfig.nodes.length, 0); - assertEq(storedVersionedConfig.dynamicConfig.sourceChains.length, 0); - - // Asser the active digest is unaffected but the candidate digest is set to zero - (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, priorActiveDigest); - assertEq(candidateDigest, ZERO_DIGEST); - assertTrue(candidateDigest != priorCandidateDigest); - } - - function test_revokeCandidate_ConfigDigestMismatch_reverts() public { - (, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); - - bytes32 wrongDigest = keccak256("wrong_digest"); - vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorCandidateDigest, wrongDigest)); - s_rmnHome.revokeCandidate(wrongDigest); - } - - function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { - vm.expectRevert(RMNHome.RevokingZeroDigestNotAllowed.selector); - s_rmnHome.revokeCandidate(ZERO_DIGEST); - } - - function test_revokeCandidate_OnlyOwner_reverts() public { - vm.startPrank(address(0)); - - vm.expectRevert("Only callable by owner"); - s_rmnHome.revokeCandidate(keccak256("configDigest")); - } -} - -contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTest { - function test_promoteCandidateAndRevokeActive_success() public { - Config memory config = _getBaseConfig(); - bytes32 firstConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - vm.expectEmit(); - emit RMNHome.ConfigPromoted(firstConfigToPromote); - - s_rmnHome.promoteCandidateAndRevokeActive(firstConfigToPromote, ZERO_DIGEST); - - // Assert the active digest is updated and the candidate digest is set to zero - (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, firstConfigToPromote); - assertEq(candidateDigest, ZERO_DIGEST); - - // Set a new candidate to promote over a non-zero active config. - config.staticConfig.offchainConfig = abi.encode("new_static_config"); - config.dynamicConfig.offchainConfig = abi.encode("new_dynamic_config"); - bytes32 secondConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - - vm.expectEmit(); - emit RMNHome.ActiveConfigRevoked(firstConfigToPromote); - - vm.expectEmit(); - emit RMNHome.ConfigPromoted(secondConfigToPromote); - - s_rmnHome.promoteCandidateAndRevokeActive(secondConfigToPromote, firstConfigToPromote); - - (RMNHome.VersionedConfig memory activeConfig, RMNHome.VersionedConfig memory candidateConfig) = - s_rmnHome.getAllConfigs(); - assertEq(activeConfig.configDigest, secondConfigToPromote); - assertEq(activeConfig.staticConfig.offchainConfig, config.staticConfig.offchainConfig); - assertEq(activeConfig.dynamicConfig.offchainConfig, config.dynamicConfig.offchainConfig); - - assertEq(candidateConfig.configDigest, ZERO_DIGEST); - } - - function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { - vm.expectRevert(RMNHome.NoOpStateTransitionNotAllowed.selector); - s_rmnHome.promoteCandidateAndRevokeActive(ZERO_DIGEST, ZERO_DIGEST); - } - - function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { - (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); - bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); - bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); - - vm.expectRevert( - abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongCandidateDigest) - ); - s_rmnHome.promoteCandidateAndRevokeActive(wrongCandidateDigest, wrongActiveDigest); - - vm.expectRevert(abi.encodeWithSelector(RMNHome.ConfigDigestMismatch.selector, priorActiveDigest, wrongActiveDigest)); - - s_rmnHome.promoteCandidateAndRevokeActive(priorCandidateDigest, wrongActiveDigest); - } - - function test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() public { - vm.startPrank(address(0)); - - vm.expectRevert("Only callable by owner"); - s_rmnHome.promoteCandidateAndRevokeActive(keccak256("toPromote"), keccak256("ToRevoke")); - } -} - -contract RMNHome__validateStaticAndDynamicConfig is RMNHomeTest { - function test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() public { - Config memory config = _getBaseConfig(); - config.staticConfig.nodes = new RMNHome.Node[](257); - - vm.expectRevert(RMNHome.OutOfBoundsNodesLength.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() public { - Config memory config = _getBaseConfig(); - config.staticConfig.nodes[1].peerId = config.staticConfig.nodes[0].peerId; - - vm.expectRevert(RMNHome.DuplicatePeerId.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() public { - Config memory config = _getBaseConfig(); - config.staticConfig.nodes[1].offchainPublicKey = config.staticConfig.nodes[0].offchainPublicKey; - - vm.expectRevert(RMNHome.DuplicateOffchainPublicKey.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() public { - Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[1].chainSelector = config.dynamicConfig.sourceChains[0].chainSelector; - - vm.expectRevert(RMNHome.DuplicateSourceChain.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() public { - Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].observerNodesBitmap = 1 << config.staticConfig.nodes.length; - - vm.expectRevert(RMNHome.OutOfBoundsObserverNodeIndex.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_validateStaticAndDynamicConfig_MinObserversTooHigh_reverts() public { - Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].minObservers++; - - vm.expectRevert(RMNHome.MinObserversTooHigh.selector); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } -} - -contract RMNHome_setDynamicConfig is RMNHomeTest { - function setUp() public { - Config memory config = _getBaseConfig(); - s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); - } - - function test_setDynamicConfig_success() public { - (bytes32 priorActiveDigest,) = s_rmnHome.getConfigDigests(); - - Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].minObservers--; - - (, bytes32 candidateConfigDigest) = s_rmnHome.getConfigDigests(); - - vm.expectEmit(); - emit RMNHome.DynamicConfigSet(candidateConfigDigest, config.dynamicConfig); - - s_rmnHome.setDynamicConfig(config.dynamicConfig, candidateConfigDigest); - - (RMNHome.VersionedConfig memory storedVersionedConfig, bool ok) = s_rmnHome.getConfig(candidateConfigDigest); - assertTrue(ok); - assertEq( - storedVersionedConfig.dynamicConfig.sourceChains[0].minObservers, - config.dynamicConfig.sourceChains[0].minObservers - ); - - // Asser the digests don't change when updating the dynamic config - (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); - assertEq(activeDigest, priorActiveDigest); - assertEq(candidateDigest, candidateConfigDigest); - } - - // Asserts the validation function is being called - function test_setDynamicConfig_MinObserversTooHigh_reverts() public { - Config memory config = _getBaseConfig(); - config.dynamicConfig.sourceChains[0].minObservers++; - - vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); - s_rmnHome.setDynamicConfig(config.dynamicConfig, ZERO_DIGEST); - } - - function test_setDynamicConfig_DigestNotFound_reverts() public { - // Zero always reverts - vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); - s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, ZERO_DIGEST); - - // Non-existent digest reverts - bytes32 nonExistentDigest = keccak256("nonExistentDigest"); - vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, nonExistentDigest)); - s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, nonExistentDigest); - } - - function test_setDynamicConfig_OnlyOwner_reverts() public { - Config memory config = _getBaseConfig(); - - vm.startPrank(address(0)); - - vm.expectRevert("Only callable by owner"); - s_rmnHome.setDynamicConfig(config.dynamicConfig, keccak256("configDigest")); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol deleted file mode 100644 index 5f46f85..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT, RMNRemote} from "../../rmn/RMNRemote.sol"; -import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; - -contract RMNRemote_constructor is RMNRemoteSetup { - function test_constructor_success() public view { - assertEq(s_rmnRemote.getLocalChainSelector(), 1); - } - - function test_constructor_zeroChainSelector_reverts() public { - vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); - new RMNRemote(0); - } -} - -contract RMNRemote_setConfig is RMNRemoteSetup { - function test_setConfig_minSignersIs0_success() public { - // Initially there is no config, the version is 0 - uint32 currentConfigVersion = 0; - RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectEmit(); - emit RMNRemote.ConfigSet(++currentConfigVersion, config); - - s_rmnRemote.setConfig(config); - - (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); - assertEq(gotConfig.minSigners, 0); - assertEq(version, currentConfigVersion); - - // A new config should increment the version - vm.expectEmit(); - emit RMNRemote.ConfigSet(++currentConfigVersion, config); - - s_rmnRemote.setConfig(config); - } - - function test_setConfig_addSigner_removeSigner_success() public { - uint32 currentConfigVersion = 0; - uint256 numSigners = s_signers.length; - RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectEmit(); - emit RMNRemote.ConfigSet(++currentConfigVersion, config); - - s_rmnRemote.setConfig(config); - - // add a signer - address newSigner = makeAddr("new signer"); - s_signers.push(RMNRemote.Signer({onchainPublicKey: newSigner, nodeIndex: uint64(numSigners)})); - config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectEmit(); - emit RMNRemote.ConfigSet(++currentConfigVersion, config); - - s_rmnRemote.setConfig(config); - - (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); - assertEq(gotConfig.signers.length, s_signers.length); - assertEq(gotConfig.signers[numSigners].onchainPublicKey, newSigner); - assertEq(gotConfig.signers[numSigners].nodeIndex, uint64(numSigners)); - assertEq(version, currentConfigVersion); - - // remove two signers - s_signers.pop(); - s_signers.pop(); - config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectEmit(); - emit RMNRemote.ConfigSet(++currentConfigVersion, config); - - s_rmnRemote.setConfig(config); - - (version, gotConfig) = s_rmnRemote.getVersionedConfig(); - assertEq(gotConfig.signers.length, s_signers.length); - assertEq(version, currentConfigVersion); - } - - function test_setConfig_invalidSignerOrder_reverts() public { - s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); - RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectRevert(RMNRemote.InvalidSignerOrder.selector); - s_rmnRemote.setConfig(config); - } - - function test_setConfig_minSignersTooHigh_reverts() public { - RMNRemote.Config memory config = RMNRemote.Config({ - rmnHomeContractConfigDigest: _randomBytes32(), - signers: s_signers, - minSigners: uint64(s_signers.length + 1) - }); - - vm.expectRevert(RMNRemote.MinSignersTooHigh.selector); - s_rmnRemote.setConfig(config); - } - - function test_setConfig_duplicateOnChainPublicKey_reverts() public { - s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[0].addr, nodeIndex: uint64(s_signers.length)})); - RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); - - vm.expectRevert(RMNRemote.DuplicateOnchainPublicKey.selector); - s_rmnRemote.setConfig(config); - } -} - -contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { - function test_verify_reverts() public { - Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); - IRMNRemote.Signature[] memory signatures = new IRMNRemote.Signature[](0); - - vm.expectRevert(RMNRemote.ConfigNotSet.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, merkleRoots, signatures, 0); - } -} - -contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { - function setUp() public override { - super.setUp(); - RMNRemote.Config memory config = - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 2}); - s_rmnRemote.setConfig(config); - _generatePayloadAndSigs(2, 2); - } - - function test_verify_success() public view { - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } - - function test_verify_minSignersIsZero_success() public { - vm.stopPrank(); - vm.prank(OWNER); - s_rmnRemote.setConfig( - RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}) - ); - - vm.stopPrank(); - vm.prank(OFF_RAMP_ADDRESS); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, new IRMNRemote.Signature[](0), s_v); - } - - function test_verify_InvalidSignature_reverts() public { - IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 1]; - sig.r = _randomBytes32(); - s_signatures.pop(); - s_signatures.push(sig); - - vm.expectRevert(RMNRemote.InvalidSignature.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } - - function test_verify_OutOfOrderSignatures_not_sorted_reverts() public { - IRMNRemote.Signature memory sig1 = s_signatures[s_signatures.length - 1]; - s_signatures.pop(); - IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 1]; - s_signatures.pop(); - s_signatures.push(sig1); - s_signatures.push(sig2); - - vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } - - function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { - IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 2]; - s_signatures.pop(); - s_signatures.push(sig); - - vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } - - function test_verify_UnexpectedSigner_reverts() public { - _setupSigners(2); // create 2 new signers that aren't configured on RMNRemote - _generatePayloadAndSigs(2, 2); - - vm.expectRevert(RMNRemote.UnexpectedSigner.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } - - function test_verify_ThresholdNotMet_reverts() public { - _generatePayloadAndSigs(2, 1); // 1 sig requested, but 2 required - - vm.expectRevert(RMNRemote.ThresholdNotMet.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); - } -} - -contract RMNRemote_curse is RMNRemoteSetup { - function test_curse_success() public { - vm.expectEmit(); - emit RMNRemote.Cursed(s_curseSubjects); - - s_rmnRemote.curse(s_curseSubjects); - - assertEq(abi.encode(s_rmnRemote.getCursedSubjects()), abi.encode(s_curseSubjects)); - assertTrue(s_rmnRemote.isCursed(curseSubj1)); - assertTrue(s_rmnRemote.isCursed(curseSubj2)); - // Should not have cursed a random subject - assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); - } - - function test_curse_AlreadyCursed_duplicateSubject_reverts() public { - s_curseSubjects.push(curseSubj1); - - vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, curseSubj1)); - s_rmnRemote.curse(s_curseSubjects); - } - - function test_curse_calledByNonOwner_reverts() public { - vm.expectRevert("Only callable by owner"); - vm.stopPrank(); - vm.prank(STRANGER); - s_rmnRemote.curse(s_curseSubjects); - } -} - -contract RMNRemote_uncurse is RMNRemoteSetup { - function setUp() public override { - super.setUp(); - s_rmnRemote.curse(s_curseSubjects); - } - - function test_uncurse_success() public { - vm.expectEmit(); - emit RMNRemote.Uncursed(s_curseSubjects); - - s_rmnRemote.uncurse(s_curseSubjects); - - assertEq(s_rmnRemote.getCursedSubjects().length, 0); - assertFalse(s_rmnRemote.isCursed(curseSubj1)); - assertFalse(s_rmnRemote.isCursed(curseSubj2)); - } - - function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { - s_curseSubjects.push(curseSubj1); - - vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, curseSubj1)); - s_rmnRemote.uncurse(s_curseSubjects); - } - - function test_uncurse_calledByNonOwner_reverts() public { - vm.expectRevert("Only callable by owner"); - vm.stopPrank(); - vm.prank(STRANGER); - s_rmnRemote.uncurse(s_curseSubjects); - } -} - -contract RMNRemote_global_and_legacy_curses is RMNRemoteSetup { - function test_global_and_legacy_curses_success() public { - bytes16 randSubject = bytes16(keccak256("random subject")); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); - assertTrue(s_rmnRemote.isCursed()); - assertTrue(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.curse(LEGACY_CURSE_SUBJECT); - assertTrue(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); // legacy curse doesn't affect specific subjects - - s_rmnRemote.uncurse(LEGACY_CURSE_SUBJECT); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol deleted file mode 100644 index 131dfec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {RMNRemote} from "../../rmn/RMNRemote.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {Vm} from "forge-std/Vm.sol"; - -import "forge-std/console.sol"; - -contract RMNRemoteSetup is BaseTest { - RMNRemote public s_rmnRemote; - address public OFF_RAMP_ADDRESS; - - RMNRemote.Signer[] public s_signers; - Vm.Wallet[] public s_signerWallets; - - Internal.MerkleRoot[] s_merkleRoots; - IRMNRemote.Signature[] s_signatures; - uint256 internal s_v; - - bytes16 internal constant curseSubj1 = bytes16(keccak256("subject 1")); - bytes16 internal constant curseSubj2 = bytes16(keccak256("subject 2")); - bytes16[] internal s_curseSubjects; - - function setUp() public virtual override { - super.setUp(); - s_rmnRemote = new RMNRemote(1); - OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); - s_curseSubjects = [curseSubj1, curseSubj2]; - - _setupSigners(10); - } - - /// @notice sets up a list of signers with strictly increasing onchain public keys - /// @dev signers do not have to be in order when configured, but they do when generating signatures - /// rather than sort signers every time, we do it once here and store the sorted list - function _setupSigners( - uint256 numSigners - ) internal { - // remove any existing config - while (s_signerWallets.length > 0) { - s_signerWallets.pop(); - } - while (s_signers.length > 0) { - s_signers.pop(); - } - - for (uint256 i = 0; i < numSigners; i++) { - s_signerWallets.push(vm.createWallet(_randomNum())); - } - - _sort(s_signerWallets); - - for (uint256 i = 0; i < numSigners; i++) { - s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[i].addr, nodeIndex: uint64(i)})); - } - } - - /// @notice generates n merkleRoots and matching valid signatures and populates them into - /// the shared storage vars - function _generatePayloadAndSigs(uint256 numUpdates, uint256 numSigs) internal { - require(numUpdates > 0, "need at least 1 dest lane update"); - require(numSigs <= s_signerWallets.length, "cannot generate more sigs than signers"); - - // remove any existing merkleRoots and sigs - while (s_merkleRoots.length > 0) { - s_merkleRoots.pop(); - } - while (s_signatures.length > 0) { - s_signatures.pop(); - } - s_v = 0; - - for (uint256 i = 0; i < numUpdates; i++) { - s_merkleRoots.push(_generateRandomDestLaneUpdate()); - } - - for (uint256 i = 0; i < numSigs; i++) { - (uint8 v, IRMNRemote.Signature memory sig) = _signDestLaneUpdate(s_merkleRoots, s_signerWallets[i]); - s_signatures.push(sig); - if (v == 28) { - s_v += 1 << i; - } - } - } - - /// @notice generates a random dest lane update - function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { - uint64 minSeqNum = uint32(_randomNum()); - uint64 maxSeqNum = minSeqNum + 100; - return Internal.MerkleRoot({ - sourceChainSelector: uint64(_randomNum()), - onRampAddress: abi.encode(_randomAddress()), - minSeqNr: minSeqNum, - maxSeqNr: maxSeqNum, - merkleRoot: _randomBytes32() - }); - } - - /// @notice signs the provided payload with the provided wallet - /// @return sigV v, either 27 of 28 - /// @return sig the signature - function _signDestLaneUpdate( - Internal.MerkleRoot[] memory merkleRoots, - Vm.Wallet memory wallet - ) private returns (uint8 sigV, IRMNRemote.Signature memory) { - (, RMNRemote.Config memory config) = s_rmnRemote.getVersionedConfig(); - bytes32 digest = keccak256( - abi.encode( - s_rmnRemote.getReportDigestHeader(), - RMNRemote.Report({ - destChainId: block.chainid, - destChainSelector: s_rmnRemote.getLocalChainSelector(), - rmnRemoteContractAddress: address(s_rmnRemote), - offrampAddress: OFF_RAMP_ADDRESS, - rmnHomeContractConfigDigest: config.rmnHomeContractConfigDigest, - merkleRoots: merkleRoots - }) - ) - ); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet, digest); - return (v, IRMNRemote.Signature({r: r, s: s})); - } - - /// @notice bubble sort on a storage array of wallets - function _sort( - Vm.Wallet[] storage wallets - ) private { - bool swapped; - for (uint256 i = 1; i < wallets.length; i++) { - swapped = false; - for (uint256 j = 0; j < wallets.length - i; j++) { - Vm.Wallet memory next = wallets[j + 1]; - Vm.Wallet memory actual = wallets[j]; - if (next.addr < actual.addr) { - wallets[j] = next; - wallets[j + 1] = actual; - swapped = true; - } - } - if (!swapped) { - return; - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol deleted file mode 100644 index e5e8ffd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/Router.t.sol +++ /dev/null @@ -1,819 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; -import {IRouter} from "../../interfaces/IRouter.sol"; -import {IRouterClient} from "../../interfaces/IRouterClient.sol"; -import {IWrappedNative} from "../../interfaces/IWrappedNative.sol"; - -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {OnRamp} from "../../onRamp/OnRamp.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; -import {OffRampSetup} from "../offRamp/OffRampSetup.t.sol"; -import {OnRampSetup} from "../onRamp/OnRampSetup.t.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract Router_constructor is OnRampSetup { - function test_Constructor_Success() public view { - assertEq("Router 1.2.0", s_sourceRouter.typeAndVersion()); - assertEq(OWNER, s_sourceRouter.owner()); - } -} - -contract Router_recoverTokens is OnRampSetup { - function test_RecoverTokens_Success() public { - // Assert we can recover sourceToken - IERC20 token = IERC20(s_sourceTokens[0]); - uint256 balanceBefore = token.balanceOf(OWNER); - token.transfer(address(s_sourceRouter), 1); - assertEq(token.balanceOf(address(s_sourceRouter)), 1); - s_sourceRouter.recoverTokens(address(token), OWNER, 1); - assertEq(token.balanceOf(address(s_sourceRouter)), 0); - assertEq(token.balanceOf(OWNER), balanceBefore); - - // Assert we can recover native - balanceBefore = OWNER.balance; - deal(address(s_sourceRouter), 10); - assertEq(address(s_sourceRouter).balance, 10); - s_sourceRouter.recoverTokens(address(0), OWNER, 10); - assertEq(OWNER.balance, balanceBefore + 10); - assertEq(address(s_sourceRouter).balance, 0); - } - - function test_RecoverTokensNonOwner_Revert() public { - // Reverts if not owner - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_sourceRouter.recoverTokens(address(0), STRANGER, 1); - } - - function test_RecoverTokensInvalidRecipient_Revert() public { - vm.expectRevert(abi.encodeWithSelector(Router.InvalidRecipientAddress.selector, address(0))); - s_sourceRouter.recoverTokens(address(0), address(0), 1); - } - - function test_RecoverTokensNoFunds_Revert() public { - // Reverts if no funds present - vm.expectRevert(); - s_sourceRouter.recoverTokens(address(0), OWNER, 10); - } - - function test_RecoverTokensValueReceiver_Revert() public { - MaybeRevertMessageReceiver revertingValueReceiver = new MaybeRevertMessageReceiver(true); - deal(address(s_sourceRouter), 10); - - // Value receiver reverts - vm.expectRevert(Router.FailedToSendValue.selector); - s_sourceRouter.recoverTokens(address(0), address(revertingValueReceiver), 10); - } -} - -contract Router_ccipSend is OnRampSetup { - event Burned(address indexed sender, uint256 amount); - - function test_CCIPSendLinkFeeOneTokenSuccess_gas() public { - vm.pauseGasMetering(); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - IERC20 sourceToken1 = IERC20(s_sourceTokens[1]); - sourceToken1.approve(address(s_sourceRouter), 2 ** 64); - - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 2 ** 64; - message.tokenAmounts[0].token = s_sourceTokens[1]; - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 0); - - uint256 balanceBefore = sourceToken1.balanceOf(OWNER); - - // Assert that the tokens are burned - vm.expectEmit(); - emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); - - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); - - vm.resumeGasMetering(); - bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - assertEq(msgEvent.header.messageId, messageId); - // Assert the user balance is lowered by the tokenAmounts sent and the fee amount - uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); - assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); - vm.resumeGasMetering(); - } - - function test_CCIPSendLinkFeeNoTokenSuccess_gas() public { - vm.pauseGasMetering(); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 0); - - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); - - vm.resumeGasMetering(); - bytes32 messageId = s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - assertEq(msgEvent.header.messageId, messageId); - vm.resumeGasMetering(); - } - - function test_ccipSend_nativeFeeOneTokenSuccess_gas() public { - vm.pauseGasMetering(); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - IERC20 sourceToken1 = IERC20(s_sourceTokens[1]); - sourceToken1.approve(address(s_sourceRouter), 2 ** 64); - - uint256 balanceBefore = sourceToken1.balanceOf(OWNER); - - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 2 ** 64; - message.tokenAmounts[0].token = s_sourceTokens[1]; - // Native fees will be wrapped so we need to calculate the event with - // the wrapped native feeCoin address. - message.feeToken = s_sourceRouter.getWrappedNative(); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 0); - - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; - - message.feeToken = address(0); - // Assert that the tokens are burned - vm.expectEmit(); - emit Burned(address(s_onRamp), message.tokenAmounts[0].amount); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); - - vm.resumeGasMetering(); - bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - assertEq(msgEvent.header.messageId, messageId); - // Assert the user balance is lowered by the tokenAmounts sent and the fee amount - uint256 expectedBalance = balanceBefore - (message.tokenAmounts[0].amount); - assertEq(expectedBalance, sourceToken1.balanceOf(OWNER)); - vm.resumeGasMetering(); - } - - function test_ccipSend_nativeFeeNoTokenSuccess_gas() public { - vm.pauseGasMetering(); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - // Native fees will be wrapped so we need to calculate the event with - // the wrapped native feeCoin address. - message.feeToken = s_sourceRouter.getWrappedNative(); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 0); - - Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent(message, 1, 1, expectedFee, OWNER); - msgEvent.feeValueJuels = expectedFee * s_sourceTokenPrices[1] / s_sourceTokenPrices[0]; - // Set it to address(0) to indicate native - message.feeToken = address(0); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent.header.sequenceNumber, msgEvent); - - vm.resumeGasMetering(); - bytes32 messageId = s_sourceRouter.ccipSend{value: expectedFee}(DEST_CHAIN_SELECTOR, message); - vm.pauseGasMetering(); - - assertEq(msgEvent.header.messageId, messageId); - // Assert the user balance is lowered by the tokenAmounts sent and the fee amount - vm.resumeGasMetering(); - } - - function test_NonLinkFeeToken_Success() public { - address[] memory feeTokens = new address[](1); - feeTokens[0] = s_sourceTokens[1]; - s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceTokens[1]; - IERC20(s_sourceTokens[1]).approve(address(s_sourceRouter), 2 ** 64); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_NativeFeeToken_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = address(0); // Raw native - uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - vm.stopPrank(); - hoax(address(1), 100 ether); - s_sourceRouter.ccipSend{value: nativeQuote}(DEST_CHAIN_SELECTOR, message); - } - - function test_NativeFeeTokenOverpay_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = address(0); // Raw native - uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - vm.stopPrank(); - hoax(address(1), 100 ether); - s_sourceRouter.ccipSend{value: nativeQuote + 1}(DEST_CHAIN_SELECTOR, message); - // We expect the overpayment to be taken in full. - assertEq(address(1).balance, 100 ether - (nativeQuote + 1)); - assertEq(address(s_sourceRouter).balance, 0); - } - - function test_WrappedNativeFeeToken_Success() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = s_sourceRouter.getWrappedNative(); - uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - vm.stopPrank(); - hoax(address(1), 100 ether); - // Now address(1) has nativeQuote wrapped. - IWrappedNative(s_sourceRouter.getWrappedNative()).deposit{value: nativeQuote}(); - IWrappedNative(s_sourceRouter.getWrappedNative()).approve(address(s_sourceRouter), nativeQuote); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - // Reverts - - function test_WhenNotHealthy_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(Router.BadARMSignal.selector); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_UnsupportedDestinationChain_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 wrongChain = DEST_CHAIN_SELECTOR + 1; - - vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, wrongChain)); - - s_sourceRouter.ccipSend(wrongChain, message); - } - - function test_FeeTokenAmountTooLow_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 0); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_InvalidMsgValue() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - // Non-empty feeToken but with msg.value should revert - vm.stopPrank(); - hoax(address(1), 1); - vm.expectRevert(IRouterClient.InvalidMsgValue.selector); - s_sourceRouter.ccipSend{value: 1}(DEST_CHAIN_SELECTOR, message); - } - - function test_NativeFeeTokenZeroValue() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = address(0); // Raw native - // Include no value, should revert - vm.expectRevert(); - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); - } - - function test_NativeFeeTokenInsufficientValue() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = address(0); // Raw native - // Include insufficient, should also revert - vm.stopPrank(); - - hoax(address(1), 1); - vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); - s_sourceRouter.ccipSend{value: 1}(DEST_CHAIN_SELECTOR, message); - } -} - -contract Router_getArmProxy is RouterSetup { - function test_getArmProxy() public view { - assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMN)); - } -} - -contract Router_applyRampUpdates is RouterSetup { - MaybeRevertMessageReceiver internal s_receiver; - - function setUp() public virtual override(RouterSetup) { - super.setUp(); - s_receiver = new MaybeRevertMessageReceiver(false); - } - - function _assertOffRampRouteSucceeds( - Router.OffRamp memory offRamp - ) internal { - vm.startPrank(offRamp.offRamp); - - Client.Any2EVMMessage memory message = _generateReceiverMessage(offRamp.sourceChainSelector); - vm.expectCall(address(s_receiver), abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)); - s_sourceRouter.routeMessage(message, GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver)); - } - - function _assertOffRampRouteReverts( - Router.OffRamp memory offRamp - ) internal { - vm.startPrank(offRamp.offRamp); - - vm.expectRevert(IRouter.OnlyOffRamp.selector); - s_sourceRouter.routeMessage( - _generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) - ); - } - - function test_Fuzz_OffRampUpdates( - address[20] memory offRampsInput - ) public { - Router.OffRamp[] memory offRamps = new Router.OffRamp[](20); - - for (uint256 i = 0; i < offRampsInput.length; ++i) { - offRamps[i] = Router.OffRamp({sourceChainSelector: uint64(i), offRamp: offRampsInput[i]}); - } - - // Test adding offRamps - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRamps); - - // There is no uniqueness guarantee on fuzz input, offRamps will not emit in case of a duplicate, - // hence cannot assert on number of offRamps event emissions, we need to use isOffRa - for (uint256 i = 0; i < offRamps.length; ++i) { - assertTrue(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); - } - - // Test removing offRamps - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), s_sourceRouter.getOffRamps(), new Router.OffRamp[](0)); - - assertEq(0, s_sourceRouter.getOffRamps().length); - for (uint256 i = 0; i < offRamps.length; ++i) { - assertFalse(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); - } - - // Testing removing and adding in same call - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRamps); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), offRamps, offRamps); - for (uint256 i = 0; i < offRamps.length; ++i) { - assertTrue(s_sourceRouter.isOffRamp(offRamps[i].sourceChainSelector, offRamps[i].offRamp)); - } - } - - function test_OffRampUpdatesWithRouting() public { - // Explicitly construct chain selectors and ramp addresses so we have ramp uniqueness for the various test scenarios. - uint256 numberOfSelectors = 10; - uint64[] memory sourceChainSelectors = new uint64[](numberOfSelectors); - for (uint256 i = 0; i < numberOfSelectors; ++i) { - sourceChainSelectors[i] = uint64(i); - } - - uint256 numberOfOffRamps = 5; - address[] memory offRamps = new address[](numberOfOffRamps); - for (uint256 i = 0; i < numberOfOffRamps; ++i) { - offRamps[i] = address(uint160(i * 10)); - } - - // 1st test scenario: add offramps. - // Check all the offramps are added correctly, and can route messages. - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](numberOfSelectors * numberOfOffRamps); - - // Ensure there are multi-offramp source and multi-source offramps - for (uint256 i = 0; i < numberOfSelectors; ++i) { - for (uint256 j = 0; j < numberOfOffRamps; ++j) { - offRampUpdates[(i * numberOfOffRamps) + j] = Router.OffRamp(sourceChainSelectors[i], offRamps[j]); - } - } - - for (uint256 i = 0; i < offRampUpdates.length; ++i) { - vm.expectEmit(); - emit Router.OffRampAdded(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp); - } - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - - Router.OffRamp[] memory gotOffRamps = s_sourceRouter.getOffRamps(); - assertEq(offRampUpdates.length, gotOffRamps.length); - - for (uint256 i = 0; i < offRampUpdates.length; ++i) { - assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); - assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - _assertOffRampRouteSucceeds(offRampUpdates[i]); - } - - vm.startPrank(OWNER); - - // 2nd test scenario: partially remove existing offramps, add new offramps. - // Check offramps are removed correctly. Removed offramps cannot route messages. - // Check new offramps are added correctly. New offramps can route messages. - // Check unmodified offramps remain correct, and can still route messages. - uint256 numberOfPartialUpdates = offRampUpdates.length / 2; - Router.OffRamp[] memory partialOffRampRemoves = new Router.OffRamp[](numberOfPartialUpdates); - Router.OffRamp[] memory partialOffRampAdds = new Router.OffRamp[](numberOfPartialUpdates); - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - partialOffRampRemoves[i] = offRampUpdates[i]; - partialOffRampAdds[i] = Router.OffRamp({ - sourceChainSelector: offRampUpdates[i].sourceChainSelector, - offRamp: address(uint160(offRampUpdates[i].offRamp) + 1e18) // Ensure unique new offRamps addresses - }); - } - - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - vm.expectEmit(); - emit Router.OffRampRemoved(partialOffRampRemoves[i].sourceChainSelector, partialOffRampRemoves[i].offRamp); - } - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - vm.expectEmit(); - emit Router.OffRampAdded(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp); - } - s_sourceRouter.applyRampUpdates(onRampUpdates, partialOffRampRemoves, partialOffRampAdds); - - gotOffRamps = s_sourceRouter.getOffRamps(); - assertEq(offRampUpdates.length, gotOffRamps.length); - - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - assertFalse( - s_sourceRouter.isOffRamp(partialOffRampRemoves[i].sourceChainSelector, partialOffRampRemoves[i].offRamp) - ); - _assertOffRampRouteReverts(partialOffRampRemoves[i]); - - assertTrue(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - _assertOffRampRouteSucceeds(partialOffRampAdds[i]); - } - for (uint256 i = numberOfPartialUpdates; i < offRampUpdates.length; ++i) { - assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - _assertOffRampRouteSucceeds(offRampUpdates[i]); - } - - vm.startPrank(OWNER); - - // 3rd test scenario: remove all offRamps. - // Check all offramps have been removed, no offramp is able to route messages. - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - vm.expectEmit(); - emit Router.OffRampRemoved(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp); - } - s_sourceRouter.applyRampUpdates(onRampUpdates, partialOffRampAdds, new Router.OffRamp[](0)); - - uint256 numberOfRemainingOfframps = offRampUpdates.length - numberOfPartialUpdates; - Router.OffRamp[] memory remainingOffRampRemoves = new Router.OffRamp[](numberOfRemainingOfframps); - for (uint256 i = 0; i < numberOfRemainingOfframps; ++i) { - remainingOffRampRemoves[i] = offRampUpdates[i + numberOfPartialUpdates]; - } - - for (uint256 i = 0; i < numberOfRemainingOfframps; ++i) { - vm.expectEmit(); - emit Router.OffRampRemoved(remainingOffRampRemoves[i].sourceChainSelector, remainingOffRampRemoves[i].offRamp); - } - s_sourceRouter.applyRampUpdates(onRampUpdates, remainingOffRampRemoves, new Router.OffRamp[](0)); - - // Check there are no offRamps. - assertEq(0, s_sourceRouter.getOffRamps().length); - - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - _assertOffRampRouteReverts(partialOffRampAdds[i]); - } - for (uint256 i = 0; i < offRampUpdates.length; ++i) { - assertFalse(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - _assertOffRampRouteReverts(offRampUpdates[i]); - } - - vm.startPrank(OWNER); - - // 4th test scenario: add initial onRamps back. - // Check the offramps are added correctly, and can route messages. - // Check offramps that were not added back remain unset, and cannot route messages. - for (uint256 i = 0; i < offRampUpdates.length; ++i) { - vm.expectEmit(); - emit Router.OffRampAdded(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp); - } - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - - // Check initial offRamps are added back and can route to receiver. - gotOffRamps = s_sourceRouter.getOffRamps(); - assertEq(offRampUpdates.length, gotOffRamps.length); - - for (uint256 i = 0; i < offRampUpdates.length; ++i) { - assertEq(offRampUpdates[i].offRamp, gotOffRamps[i].offRamp); - assertTrue(s_sourceRouter.isOffRamp(offRampUpdates[i].sourceChainSelector, offRampUpdates[i].offRamp)); - _assertOffRampRouteSucceeds(offRampUpdates[i]); - } - - // Check offramps that were not added back remain unset. - for (uint256 i = 0; i < numberOfPartialUpdates; ++i) { - assertFalse(s_sourceRouter.isOffRamp(partialOffRampAdds[i].sourceChainSelector, partialOffRampAdds[i].offRamp)); - _assertOffRampRouteReverts(partialOffRampAdds[i]); - } - } - - function test_Fuzz_OnRampUpdates( - Router.OnRamp[] memory onRamps - ) public { - // Test adding onRamps - for (uint256 i = 0; i < onRamps.length; ++i) { - vm.expectEmit(); - emit Router.OnRampSet(onRamps[i].destChainSelector, onRamps[i].onRamp); - } - - s_sourceRouter.applyRampUpdates(onRamps, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - // Test setting onRamps to unsupported - for (uint256 i = 0; i < onRamps.length; ++i) { - onRamps[i].onRamp = address(0); - - vm.expectEmit(); - emit Router.OnRampSet(onRamps[i].destChainSelector, onRamps[i].onRamp); - } - s_sourceRouter.applyRampUpdates(onRamps, new Router.OffRamp[](0), new Router.OffRamp[](0)); - for (uint256 i = 0; i < onRamps.length; ++i) { - assertEq(address(0), s_sourceRouter.getOnRamp(onRamps[i].destChainSelector)); - assertFalse(s_sourceRouter.isChainSupported(onRamps[i].destChainSelector)); - } - } - - function test_OnRampDisable() public { - // Add onRamp - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](0); - address onRamp = address(uint160(2)); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - assertEq(onRamp, s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); - assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); - - // Disable onRamp - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(0)}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - assertEq(address(0), s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); - assertFalse(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); - - // Re-enable onRamp - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - assertEq(onRamp, s_sourceRouter.getOnRamp(DEST_CHAIN_SELECTOR)); - assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); - } - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](0); - s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); - } - - function test_OffRampMismatch_Revert() public { - address offRamp = address(uint160(2)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp(DEST_CHAIN_SELECTOR, offRamp); - - vm.expectEmit(); - emit Router.OffRampAdded(DEST_CHAIN_SELECTOR, offRamp); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - - offRampUpdates[0] = Router.OffRamp(SOURCE_CHAIN_SELECTOR, offRamp); - - vm.expectRevert(abi.encodeWithSelector(Router.OffRampMismatch.selector, SOURCE_CHAIN_SELECTOR, offRamp)); - s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); - } -} - -contract Router_setWrappedNative is OnRampSetup { - function test_Fuzz_SetWrappedNative_Success( - address wrappedNative - ) public { - s_sourceRouter.setWrappedNative(wrappedNative); - assertEq(wrappedNative, s_sourceRouter.getWrappedNative()); - } - - // Reverts - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_sourceRouter.setWrappedNative(address(1)); - } -} - -contract Router_getSupportedTokens is OnRampSetup { - function test_GetSupportedTokens_Revert() public { - vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); - s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); - } -} - -contract Router_routeMessage is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - vm.startPrank(address(s_offRamp)); - } - - function _generateManualGasLimit( - uint256 callDataLength - ) internal view returns (uint256) { - return ((gasleft() - 2 * (16 * callDataLength + GAS_FOR_CALL_EXACT_CHECK)) * 62) / 64; - } - - function test_routeMessage_ManualExec_Success() public { - Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); - // Manuel execution cannot run out of gas - - (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), - GAS_FOR_CALL_EXACT_CHECK, - _generateManualGasLimit(message.data.length), - address(s_receiver) - ); - assertTrue(success); - assertEq("", retData); - assertGt(gasUsed, 3_000); - } - - function test_routeMessage_ExecutionEvent_Success() public { - Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); - // Should revert with reason - bytes memory realError1 = new bytes(2); - realError1[0] = 0xbe; - realError1[1] = 0xef; - s_reverting_receiver.setErr(realError1); - - vm.expectEmit(); - emit Router.MessageExecuted( - message.messageId, - message.sourceChainSelector, - address(s_offRamp), - keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) - ); - - (bool success, bytes memory retData, uint256 gasUsed) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), - GAS_FOR_CALL_EXACT_CHECK, - _generateManualGasLimit(message.data.length), - address(s_reverting_receiver) - ); - - assertFalse(success); - assertEq(abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1), retData); - assertGt(gasUsed, 3_000); - - // Reason is truncated - // Over the MAX_RET_BYTES limit (including offset and length word since we have a dynamic values), should be ignored - bytes memory realError2 = new bytes(32 * 2 + 1); - realError2[32 * 2 - 1] = 0xAA; - realError2[32 * 2] = 0xFF; - s_reverting_receiver.setErr(realError2); - - vm.expectEmit(); - emit Router.MessageExecuted( - message.messageId, - message.sourceChainSelector, - address(s_offRamp), - keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) - ); - - (success, retData, gasUsed) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), - GAS_FOR_CALL_EXACT_CHECK, - _generateManualGasLimit(message.data.length), - address(s_reverting_receiver) - ); - - assertFalse(success); - assertEq( - abi.encodeWithSelector( - MaybeRevertMessageReceiver.CustomError.selector, - uint256(32), - uint256(realError2.length), - uint256(0), - uint256(0xAA) - ), - retData - ); - assertGt(gasUsed, 3_000); - - // Should emit success - vm.expectEmit(); - emit Router.MessageExecuted( - message.messageId, - message.sourceChainSelector, - address(s_offRamp), - keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) - ); - - (success, retData, gasUsed) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), - GAS_FOR_CALL_EXACT_CHECK, - _generateManualGasLimit(message.data.length), - address(s_receiver) - ); - - assertTrue(success); - assertEq("", retData); - assertGt(gasUsed, 3_000); - } - - function testFuzz_routeMessage_ExecutionEvent_Success( - bytes calldata error - ) public { - Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); - s_reverting_receiver.setErr(error); - - bytes memory expectedRetData; - - if (error.length >= 33) { - uint256 cutOff = error.length > 64 ? 64 : error.length; - vm.expectEmit(); - emit Router.MessageExecuted( - message.messageId, - message.sourceChainSelector, - address(s_offRamp), - keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) - ); - expectedRetData = abi.encodeWithSelector( - MaybeRevertMessageReceiver.CustomError.selector, - uint256(32), - uint256(error.length), - bytes32(error[:32]), - bytes32(error[32:cutOff]) - ); - } else { - vm.expectEmit(); - emit Router.MessageExecuted( - message.messageId, - message.sourceChainSelector, - address(s_offRamp), - keccak256(abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)) - ); - expectedRetData = abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, error); - } - - (bool success, bytes memory retData,) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), - GAS_FOR_CALL_EXACT_CHECK, - _generateManualGasLimit(message.data.length), - address(s_reverting_receiver) - ); - - assertFalse(success); - assertEq(expectedRetData, retData); - } - - function test_routeMessage_AutoExec_Success() public { - (bool success,,) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) - ); - - assertTrue(success); - - (success,,) = s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 1, address(s_receiver) - ); - - // Can run out of gas, should return false - assertFalse(success); - } - - // Reverts - function test_routeMessage_OnlyOffRamp_Revert() public { - vm.stopPrank(); - vm.startPrank(STRANGER); - - vm.expectRevert(IRouter.OnlyOffRamp.selector); - s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) - ); - } - - function test_routeMessage_WhenNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(Router.BadARMSignal.selector); - s_destRouter.routeMessage( - _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) - ); - } -} - -contract Router_getFee is OnRampSetup { - function test_GetFeeSupportedChain_Success() public view { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); - assertGt(expectedFee, 10e9); - } - - // Reverts - function test_UnsupportedDestinationChain_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, 999)); - s_sourceRouter.getFee(999, message); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol deleted file mode 100644 index f4c1114..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/router/RouterSetup.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {WETH9} from "../WETH9.sol"; - -contract RouterSetup is BaseTest { - Router internal s_sourceRouter; - Router internal s_destRouter; - - function setUp() public virtual override { - BaseTest.setUp(); - - if (address(s_sourceRouter) == address(0)) { - WETH9 weth = new WETH9(); - s_sourceRouter = new Router(address(weth), address(s_mockRMN)); - vm.label(address(s_sourceRouter), "sourceRouter"); - } - if (address(s_destRouter) == address(0)) { - WETH9 weth = new WETH9(); - s_destRouter = new Router(address(weth), address(s_mockRMN)); - vm.label(address(s_destRouter), "destRouter"); - } - } - - function _generateReceiverMessage( - uint64 chainSelector - ) internal pure returns (Client.Any2EVMMessage memory) { - Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); - return Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: chainSelector, - sender: bytes("a"), - data: bytes("a"), - destTokenAmounts: ta - }); - } - - function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { - return Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(12312412312)), - destTokenAddress: abi.encode(address(9809808909)), - extraData: "", - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol deleted file mode 100644 index dfb599b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom.t.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; -import {IOwner} from "../../interfaces/IOwner.sol"; - -import {RegistryModuleOwnerCustom} from "../../tokenAdminRegistry/RegistryModuleOwnerCustom.sol"; -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {BurnMintERC677Helper} from "../helpers/BurnMintERC677Helper.sol"; - -import {Test} from "forge-std/Test.sol"; - -contract RegistryModuleOwnerCustomSetup is Test { - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - - RegistryModuleOwnerCustom internal s_registryModuleOwnerCustom; - TokenAdminRegistry internal s_tokenAdminRegistry; - address internal s_token; - - function setUp() public virtual { - vm.startPrank(OWNER); - - s_tokenAdminRegistry = new TokenAdminRegistry(); - s_token = address(new BurnMintERC677Helper("Test", "TST")); - s_registryModuleOwnerCustom = new RegistryModuleOwnerCustom(address(s_tokenAdminRegistry)); - s_tokenAdminRegistry.addRegistryModule(address(s_registryModuleOwnerCustom)); - } -} - -contract RegistryModuleOwnerCustom_constructor is RegistryModuleOwnerCustomSetup { - function test_constructor_Revert() public { - vm.expectRevert(abi.encodeWithSelector(RegistryModuleOwnerCustom.AddressZero.selector)); - - new RegistryModuleOwnerCustom(address(0)); - } -} - -contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaGetCCIPAdmin_Success() public { - assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); - - address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); - - vm.expectCall(s_token, abi.encodeWithSelector(IGetCCIPAdmin.getCCIPAdmin.selector), 1); - vm.expectCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(TokenAdminRegistry.proposeAdministrator.selector, s_token, expectedOwner), - 1 - ); - - vm.expectEmit(); - emit RegistryModuleOwnerCustom.AdministratorRegistered(s_token, expectedOwner); - - s_registryModuleOwnerCustom.registerAdminViaGetCCIPAdmin(s_token); - - assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); - } - - function test_registerAdminViaGetCCIPAdmin_Revert() public { - address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); - - vm.startPrank(makeAddr("Not_expected_owner")); - - vm.expectRevert( - abi.encodeWithSelector(RegistryModuleOwnerCustom.CanOnlySelfRegister.selector, expectedOwner, s_token) - ); - - s_registryModuleOwnerCustom.registerAdminViaGetCCIPAdmin(s_token); - } -} - -contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaOwner_Success() public { - assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); - - address expectedOwner = IOwner(s_token).owner(); - - vm.expectCall(s_token, abi.encodeWithSelector(IOwner.owner.selector), 1); - vm.expectCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(TokenAdminRegistry.proposeAdministrator.selector, s_token, expectedOwner), - 1 - ); - - vm.expectEmit(); - emit RegistryModuleOwnerCustom.AdministratorRegistered(s_token, expectedOwner); - - s_registryModuleOwnerCustom.registerAdminViaOwner(s_token); - - assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); - } - - function test_registerAdminViaOwner_Revert() public { - address expectedOwner = IOwner(s_token).owner(); - - vm.startPrank(makeAddr("Not_expected_owner")); - - vm.expectRevert( - abi.encodeWithSelector(RegistryModuleOwnerCustom.CanOnlySelfRegister.selector, expectedOwner, s_token) - ); - - s_registryModuleOwnerCustom.registerAdminViaOwner(s_token); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol deleted file mode 100644 index a5c2487..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry.t.sol +++ /dev/null @@ -1,395 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {TokenSetup} from "../TokenSetup.t.sol"; - -contract TokenAdminRegistrySetup is TokenSetup { - address internal s_registryModule = makeAddr("registryModule"); - - function setUp() public virtual override { - TokenSetup.setUp(); - - s_tokenAdminRegistry.addRegistryModule(s_registryModule); - } -} - -contract TokenAdminRegistry_getPools is TokenAdminRegistrySetup { - function test_getPools_Success() public { - address[] memory tokens = new address[](1); - tokens[0] = s_sourceTokens[0]; - - address[] memory got = s_tokenAdminRegistry.getPools(tokens); - assertEq(got.length, 1); - assertEq(got[0], s_sourcePoolByToken[tokens[0]]); - - got = s_tokenAdminRegistry.getPools(s_sourceTokens); - assertEq(got.length, s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; i++) { - assertEq(got[i], s_sourcePoolByToken[s_sourceTokens[i]]); - } - - address doesNotExist = makeAddr("doesNotExist"); - tokens[0] = doesNotExist; - got = s_tokenAdminRegistry.getPools(tokens); - assertEq(got.length, 1); - assertEq(got[0], address(0)); - } -} - -contract TokenAdminRegistry_getPool is TokenAdminRegistrySetup { - function test_getPool_Success() public view { - address got = s_tokenAdminRegistry.getPool(s_sourceTokens[0]); - assertEq(got, s_sourcePoolByToken[s_sourceTokens[0]]); - } -} - -contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { - function test_setPool_Success() public { - address pool = makeAddr("pool"); - vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); - - vm.expectEmit(); - emit TokenAdminRegistry.PoolSet(s_sourceTokens[0], s_sourcePoolByToken[s_sourceTokens[0]], pool); - - s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); - - assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), pool); - - // Assert the event is not emitted if the pool is the same as the current pool. - vm.recordLogs(); - s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); - - vm.assertEq(vm.getRecordedLogs().length, 0); - } - - function test_setPool_ZeroAddressRemovesPool_Success() public { - address pool = makeAddr("pool"); - vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); - s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); - - assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), pool); - - vm.expectEmit(); - emit TokenAdminRegistry.PoolSet(s_sourceTokens[0], pool, address(0)); - - s_tokenAdminRegistry.setPool(s_sourceTokens[0], address(0)); - - assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), address(0)); - } - - function test_setPool_InvalidTokenPoolToken_Revert() public { - address pool = makeAddr("pool"); - vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(false)); - - vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.InvalidTokenPoolToken.selector, s_sourceTokens[0])); - s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); - } - - function test_setPool_OnlyAdministrator_Revert() public { - vm.stopPrank(); - - vm.expectRevert( - abi.encodeWithSelector(TokenAdminRegistry.OnlyAdministrator.selector, address(this), s_sourceTokens[0]) - ); - s_tokenAdminRegistry.setPool(s_sourceTokens[0], makeAddr("pool")); - } -} - -contract TokenAdminRegistry_getAllConfiguredTokens is TokenAdminRegistrySetup { - function test_Fuzz_getAllConfiguredTokens_Success( - uint8 numberOfTokens - ) public { - TokenAdminRegistry cleanTokenAdminRegistry = new TokenAdminRegistry(); - for (uint160 i = 0; i < numberOfTokens; ++i) { - cleanTokenAdminRegistry.proposeAdministrator(address(i), address(i + 1000)); - } - - uint160 count = 0; - for (uint160 start = 0; start < numberOfTokens; start += count++) { - address[] memory got = cleanTokenAdminRegistry.getAllConfiguredTokens(uint64(start), uint64(count)); - if (start + count > numberOfTokens) { - assertEq(got.length, numberOfTokens - start); - } else { - assertEq(got.length, count); - } - - for (uint160 j = 0; j < got.length; ++j) { - assertEq(got[j], address(j + start)); - } - } - } - - function test_getAllConfiguredTokens_outOfBounds_Success() public view { - address[] memory tokens = s_tokenAdminRegistry.getAllConfiguredTokens(type(uint64).max, 10); - assertEq(tokens.length, 0); - } -} - -contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { - function test_transferAdminRole_Success() public { - address token = s_sourceTokens[0]; - - address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; - address newAdmin = makeAddr("newAdmin"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(token, currentAdmin, newAdmin); - - s_tokenAdminRegistry.transferAdminRole(token, newAdmin); - - TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); - - // Assert only the pending admin updates, without affecting the pending admin. - assertEq(config.pendingAdministrator, newAdmin); - assertEq(config.administrator, currentAdmin); - } - - function test_transferAdminRole_OnlyAdministrator_Revert() public { - vm.stopPrank(); - - vm.expectRevert( - abi.encodeWithSelector(TokenAdminRegistry.OnlyAdministrator.selector, address(this), s_sourceTokens[0]) - ); - s_tokenAdminRegistry.transferAdminRole(s_sourceTokens[0], makeAddr("newAdmin")); - } -} - -contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { - function test_acceptAdminRole_Success() public { - address token = s_sourceTokens[0]; - - address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; - address newAdmin = makeAddr("newAdmin"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(token, currentAdmin, newAdmin); - - s_tokenAdminRegistry.transferAdminRole(token, newAdmin); - - TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); - - // Assert only the pending admin updates, without affecting the pending admin. - assertEq(config.pendingAdministrator, newAdmin); - assertEq(config.administrator, currentAdmin); - - vm.startPrank(newAdmin); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferred(token, newAdmin); - - s_tokenAdminRegistry.acceptAdminRole(token); - - config = s_tokenAdminRegistry.getTokenConfig(token); - - // Assert only the pending admin updates, without affecting the pending admin. - assertEq(config.pendingAdministrator, address(0)); - assertEq(config.administrator, newAdmin); - } - - function test_acceptAdminRole_OnlyPendingAdministrator_Revert() public { - address token = s_sourceTokens[0]; - address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; - address newAdmin = makeAddr("newAdmin"); - - s_tokenAdminRegistry.transferAdminRole(token, newAdmin); - - TokenAdminRegistry.TokenConfig memory config = s_tokenAdminRegistry.getTokenConfig(token); - - // Assert only the pending admin updates, without affecting the pending admin. - assertEq(config.pendingAdministrator, newAdmin); - assertEq(config.administrator, currentAdmin); - - address notNewAdmin = makeAddr("notNewAdmin"); - vm.startPrank(notNewAdmin); - - vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.OnlyPendingAdministrator.selector, notNewAdmin, token)); - s_tokenAdminRegistry.acceptAdminRole(token); - } -} - -contract TokenAdminRegistry_isAdministrator is TokenAdminRegistrySetup { - function test_isAdministrator_Success() public { - address newAdmin = makeAddr("newAdmin"); - address newToken = makeAddr("newToken"); - assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); - assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, OWNER)); - - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - changePrank(newAdmin); - s_tokenAdminRegistry.acceptAdminRole(newToken); - - assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); - assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, OWNER)); - } -} - -contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { - function test_proposeAdministrator_module_Success() public { - vm.startPrank(s_registryModule); - address newAdmin = makeAddr("newAdmin"); - address newToken = makeAddr("newToken"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); - - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - - assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); - assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).administrator, address(0)); - assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).tokenPool, address(0)); - - changePrank(newAdmin); - s_tokenAdminRegistry.acceptAdminRole(newToken); - - assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); - } - - function test_proposeAdministrator_owner_Success() public { - address newAdmin = makeAddr("newAdmin"); - address newToken = makeAddr("newToken"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); - - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - - assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); - - changePrank(newAdmin); - s_tokenAdminRegistry.acceptAdminRole(newToken); - - assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); - } - - function test_proposeAdministrator_reRegisterWhileUnclaimed_Success() public { - address newAdmin = makeAddr("wrongAddress"); - address newToken = makeAddr("newToken"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); - - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - - assertEq(s_tokenAdminRegistry.getTokenConfig(newToken).pendingAdministrator, newAdmin); - - newAdmin = makeAddr("correctAddress"); - - vm.expectEmit(); - emit TokenAdminRegistry.AdministratorTransferRequested(newToken, address(0), newAdmin); - - // Ensure we can still register the correct admin while the previous admin is unclaimed. - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - - changePrank(newAdmin); - s_tokenAdminRegistry.acceptAdminRole(newToken); - - assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); - } - - mapping(address token => address admin) internal s_AdminByToken; - - function test_Fuzz_proposeAdministrator_Success(address[50] memory tokens, address[50] memory admins) public { - TokenAdminRegistry cleanTokenAdminRegistry = new TokenAdminRegistry(); - for (uint256 i = 0; i < tokens.length; i++) { - if (admins[i] == address(0)) { - continue; - } - if (cleanTokenAdminRegistry.getTokenConfig(tokens[i]).administrator != address(0)) { - continue; - } - cleanTokenAdminRegistry.proposeAdministrator(tokens[i], admins[i]); - s_AdminByToken[tokens[i]] = admins[i]; - } - - for (uint256 i = 0; i < tokens.length; i++) { - assertEq(cleanTokenAdminRegistry.getTokenConfig(tokens[i]).pendingAdministrator, s_AdminByToken[tokens[i]]); - } - } - - function test_proposeAdministrator_OnlyRegistryModule_Revert() public { - address newToken = makeAddr("newToken"); - vm.stopPrank(); - - vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.OnlyRegistryModuleOrOwner.selector, address(this))); - s_tokenAdminRegistry.proposeAdministrator(newToken, OWNER); - } - - function test_proposeAdministrator_ZeroAddress_Revert() public { - address newToken = makeAddr("newToken"); - - vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.ZeroAddress.selector)); - s_tokenAdminRegistry.proposeAdministrator(newToken, address(0)); - } - - function test_proposeAdministrator_AlreadyRegistered_Revert() public { - address newAdmin = makeAddr("newAdmin"); - address newToken = makeAddr("newToken"); - - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - changePrank(newAdmin); - s_tokenAdminRegistry.acceptAdminRole(newToken); - - changePrank(OWNER); - - vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.AlreadyRegistered.selector, newToken)); - s_tokenAdminRegistry.proposeAdministrator(newToken, newAdmin); - } -} - -contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { - function test_addRegistryModule_Success() public { - address newModule = makeAddr("newModule"); - - s_tokenAdminRegistry.addRegistryModule(newModule); - - assertTrue(s_tokenAdminRegistry.isRegistryModule(newModule)); - - // Assert the event is not emitted if the module is already added. - vm.recordLogs(); - s_tokenAdminRegistry.addRegistryModule(newModule); - - vm.assertEq(vm.getRecordedLogs().length, 0); - } - - function test_addRegistryModule_OnlyOwner_Revert() public { - address newModule = makeAddr("newModule"); - vm.stopPrank(); - - vm.expectRevert("Only callable by owner"); - s_tokenAdminRegistry.addRegistryModule(newModule); - } -} - -contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { - function test_removeRegistryModule_Success() public { - address newModule = makeAddr("newModule"); - - s_tokenAdminRegistry.addRegistryModule(newModule); - - assertTrue(s_tokenAdminRegistry.isRegistryModule(newModule)); - - vm.expectEmit(); - emit TokenAdminRegistry.RegistryModuleRemoved(newModule); - - s_tokenAdminRegistry.removeRegistryModule(newModule); - - assertFalse(s_tokenAdminRegistry.isRegistryModule(newModule)); - - // Assert the event is not emitted if the module is already removed. - vm.recordLogs(); - s_tokenAdminRegistry.removeRegistryModule(newModule); - - vm.assertEq(vm.getRecordedLogs().length, 0); - } - - function test_removeRegistryModule_OnlyOwner_Revert() public { - address newModule = makeAddr("newModule"); - vm.stopPrank(); - - vm.expectRevert("Only callable by owner"); - s_tokenAdminRegistry.removeRegistryModule(newModule); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol deleted file mode 100644 index dd2c82f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IGetCCIPAdmin} from "../interfaces/IGetCCIPAdmin.sol"; -import {IOwner} from "../interfaces/IOwner.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -contract RegistryModuleOwnerCustom is ITypeAndVersion { - error CanOnlySelfRegister(address admin, address token); - error AddressZero(); - - event AdministratorRegistered(address indexed token, address indexed administrator); - - string public constant override typeAndVersion = "RegistryModuleOwnerCustom 1.5.0"; - - // The TokenAdminRegistry contract - ITokenAdminRegistry internal immutable i_tokenAdminRegistry; - - constructor( - address tokenAdminRegistry - ) { - if (tokenAdminRegistry == address(0)) { - revert AddressZero(); - } - i_tokenAdminRegistry = ITokenAdminRegistry(tokenAdminRegistry); - } - - /// @notice Registers the admin of the token using the `getCCIPAdmin` method. - /// @param token The token to register the admin for. - /// @dev The caller must be the admin returned by the `getCCIPAdmin` method. - function registerAdminViaGetCCIPAdmin( - address token - ) external { - _registerAdmin(token, IGetCCIPAdmin(token).getCCIPAdmin()); - } - - /// @notice Registers the admin of the token using the `owner` method. - /// @param token The token to register the admin for. - /// @dev The caller must be the admin returned by the `owner` method. - function registerAdminViaOwner( - address token - ) external { - _registerAdmin(token, IOwner(token).owner()); - } - - /// @notice Registers the admin of the token to msg.sender given that the - /// admin is equal to msg.sender. - /// @param token The token to register the admin for. - /// @param admin The caller must be the admin. - function _registerAdmin(address token, address admin) internal { - if (admin != msg.sender) { - revert CanOnlySelfRegister(admin, token); - } - - i_tokenAdminRegistry.proposeAdministrator(token, admin); - - emit AdministratorRegistered(token, admin); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol deleted file mode 100644 index fbe821e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol +++ /dev/null @@ -1,237 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IPoolV1} from "../interfaces/IPool.sol"; -import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice This contract stores the token pool configuration for all CCIP enabled tokens. It works -/// on a self-serve basis, where tokens can be registered without intervention from the CCIP owner. -/// @dev This contract is not considered upgradable, as it is a customer facing contract that will store -/// significant amounts of data. -contract TokenAdminRegistry is ITokenAdminRegistry, ITypeAndVersion, OwnerIsCreator { - using EnumerableSet for EnumerableSet.AddressSet; - - error OnlyRegistryModuleOrOwner(address sender); - error OnlyAdministrator(address sender, address token); - error OnlyPendingAdministrator(address sender, address token); - error AlreadyRegistered(address token); - error ZeroAddress(); - error InvalidTokenPoolToken(address token); - - event PoolSet(address indexed token, address indexed previousPool, address indexed newPool); - event AdministratorTransferRequested(address indexed token, address indexed currentAdmin, address indexed newAdmin); - event AdministratorTransferred(address indexed token, address indexed newAdmin); - event RegistryModuleAdded(address module); - event RegistryModuleRemoved(address indexed module); - - // The struct is packed in a way that optimizes the attributes that are accessed together. - // solhint-disable-next-line gas-struct-packing - struct TokenConfig { - address administrator; // the current administrator of the token - address pendingAdministrator; // the address that is pending to become the new administrator - address tokenPool; // the token pool for this token. Can be address(0) if not deployed or not configured. - } - - string public constant override typeAndVersion = "TokenAdminRegistry 1.5.0"; - - // Mapping of token address to token configuration - mapping(address token => TokenConfig) internal s_tokenConfig; - - // All tokens that have been configured - EnumerableSet.AddressSet internal s_tokens; - - // Registry modules are allowed to register administrators for tokens - EnumerableSet.AddressSet internal s_registryModules; - - /// @notice Returns all pools for the given tokens. - /// @dev Will return address(0) for tokens that do not have a pool. - function getPools( - address[] calldata tokens - ) external view returns (address[] memory) { - address[] memory pools = new address[](tokens.length); - for (uint256 i = 0; i < tokens.length; ++i) { - pools[i] = s_tokenConfig[tokens[i]].tokenPool; - } - return pools; - } - - /// @inheritdoc ITokenAdminRegistry - function getPool( - address token - ) external view returns (address) { - return s_tokenConfig[token].tokenPool; - } - - /// @notice Returns the configuration for a token. - /// @param token The token to get the configuration for. - /// @return config The configuration for the token. - function getTokenConfig( - address token - ) external view returns (TokenConfig memory) { - return s_tokenConfig[token]; - } - - /// @notice Returns a list of tokens that are configured in the token admin registry. - /// @param startIndex Starting index in list, can be 0 if you want to start from the beginning. - /// @param maxCount Maximum number of tokens to retrieve. Since the list can be large, - /// it is recommended to use a paging mechanism to retrieve all tokens. If querying for very - /// large lists, RPCs can time out. If you want all tokens, use type(uint64).max. - /// @return tokens List of configured tokens. - /// @dev The function is paginated to avoid RPC timeouts. - /// @dev The ordering is guaranteed to remain the same as it is not possible to remove tokens - /// from s_tokens. - function getAllConfiguredTokens(uint64 startIndex, uint64 maxCount) external view returns (address[] memory tokens) { - uint256 numberOfTokens = s_tokens.length(); - if (startIndex >= numberOfTokens) { - return tokens; - } - uint256 count = maxCount; - if (count + startIndex > numberOfTokens) { - count = numberOfTokens - startIndex; - } - tokens = new address[](count); - for (uint256 i = 0; i < count; ++i) { - tokens[i] = s_tokens.at(startIndex + i); - } - - return tokens; - } - - // ================================================================ - // │ Administrator functions │ - // ================================================================ - - /// @notice Sets the pool for a token. Setting the pool to address(0) effectively delists the token - /// from CCIP. Setting the pool to any other address enables the token on CCIP. - /// @param localToken The token to set the pool for. - /// @param pool The pool to set for the token. - function setPool(address localToken, address pool) external onlyTokenAdmin(localToken) { - // The pool has to support the token, but we want to allow removing the pool, so we only check - // if the pool supports the token if it is not address(0). - if (pool != address(0) && !IPoolV1(pool).isSupportedToken(localToken)) { - revert InvalidTokenPoolToken(localToken); - } - - TokenConfig storage config = s_tokenConfig[localToken]; - - address previousPool = config.tokenPool; - config.tokenPool = pool; - - if (previousPool != pool) { - emit PoolSet(localToken, previousPool, pool); - } - } - - /// @notice Transfers the administrator role for a token to a new address with a 2-step process. - /// @param localToken The token to transfer the administrator role for. - /// @param newAdmin The address to transfer the administrator role to. Can be address(0) to cancel - /// a pending transfer. - /// @dev The new admin must call `acceptAdminRole` to accept the role. - function transferAdminRole(address localToken, address newAdmin) external onlyTokenAdmin(localToken) { - TokenConfig storage config = s_tokenConfig[localToken]; - config.pendingAdministrator = newAdmin; - - emit AdministratorTransferRequested(localToken, msg.sender, newAdmin); - } - - /// @notice Accepts the administrator role for a token. - /// @param localToken The token to accept the administrator role for. - /// @dev This function can only be called by the pending administrator. - function acceptAdminRole( - address localToken - ) external { - TokenConfig storage config = s_tokenConfig[localToken]; - if (config.pendingAdministrator != msg.sender) { - revert OnlyPendingAdministrator(msg.sender, localToken); - } - - config.administrator = msg.sender; - config.pendingAdministrator = address(0); - - emit AdministratorTransferred(localToken, msg.sender); - } - - // ================================================================ - // │ Administrator config │ - // ================================================================ - - /// @notice Public getter to check for permissions of an administrator - function isAdministrator(address localToken, address administrator) external view returns (bool) { - return s_tokenConfig[localToken].administrator == administrator; - } - - /// @inheritdoc ITokenAdminRegistry - /// @dev Can only be called by a registry module. - function proposeAdministrator(address localToken, address administrator) external { - if (!isRegistryModule(msg.sender) && msg.sender != owner()) { - revert OnlyRegistryModuleOrOwner(msg.sender); - } - if (administrator == address(0)) { - revert ZeroAddress(); - } - TokenConfig storage config = s_tokenConfig[localToken]; - - if (config.administrator != address(0)) { - revert AlreadyRegistered(localToken); - } - - config.pendingAdministrator = administrator; - - // We don't care if it's already in the set, as it's a no-op. - s_tokens.add(localToken); - - emit AdministratorTransferRequested(localToken, address(0), administrator); - } - - // ================================================================ - // │ Registry Modules │ - // ================================================================ - - /// @notice Checks if an address is a registry module. - /// @param module The address to check. - /// @return True if the address is a registry module, false otherwise. - function isRegistryModule( - address module - ) public view returns (bool) { - return s_registryModules.contains(module); - } - - /// @notice Adds a new registry module to the list of allowed modules. - /// @param module The module to add. - function addRegistryModule( - address module - ) external onlyOwner { - if (s_registryModules.add(module)) { - emit RegistryModuleAdded(module); - } - } - - /// @notice Removes a registry module from the list of allowed modules. - /// @param module The module to remove. - function removeRegistryModule( - address module - ) external onlyOwner { - if (s_registryModules.remove(module)) { - emit RegistryModuleRemoved(module); - } - } - - // ================================================================ - // │ Access │ - // ================================================================ - - /// @notice Checks if an address is the administrator of the given token. - modifier onlyTokenAdmin( - address token - ) { - if (s_tokenConfig[token].administrator != msg.sender) { - revert OnlyAdministrator(msg.sender, token); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md deleted file mode 100644 index ef0f55e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/ccip/v1.5-CCIP-License-grants.md +++ /dev/null @@ -1,8 +0,0 @@ -v1.5-CCIP-License-grants - -Additional Use Grant(s): - -You may make use of the Cross-Chain Interoperability Protocol v1.5 (which is available subject to the license here, the “Licensed Work ”) solely for purposes of - -1. importing client-side libraries or example clients to facilitate the integration of the Licensed Work into your application. -2. Developing, deploying and operating [the token pool contracts](./pools) solely for purposes of the integration and use of CCIP. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol deleted file mode 100644 index 75420fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol +++ /dev/null @@ -1,448 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {IFunctionsBilling, FunctionsBillingConfig} from "./interfaces/IFunctionsBilling.sol"; - -import {Routable} from "./Routable.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -import {ChainSpecificUtil} from "./libraries/ChainSpecificUtil.sol"; - -/// @title Functions Billing contract -/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsBilling is Routable, IFunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei - - event RequestBilled( - bytes32 indexed requestId, - uint96 juelsPerGas, - uint256 l1FeeShareWei, - uint96 callbackCostJuels, - uint72 donFeeJuels, - uint72 adminFeeJuels, - uint72 operationFeeJuels - ); - - // ================================================================ - // | Request Commitment state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; - - event CommitmentDeleted(bytes32 requestId); - - FunctionsBillingConfig private s_config; - - event ConfigUpdated(FunctionsBillingConfig config); - - error UnsupportedRequestDataVersion(); - error InsufficientBalance(); - error InvalidSubscription(); - error UnauthorizedSender(); - error MustBeSubOwner(address owner); - error InvalidLinkWeiPrice(int256 linkWei); - error InvalidUsdLinkPrice(int256 usdLink); - error PaymentTooLarge(); - error NoTransmittersSet(); - error InvalidCalldata(); - - // ================================================================ - // | Balance state | - // ================================================================ - - mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; - // Pool together collected DON fees - // Disperse them on withdrawal or change in OCR configuration - uint96 internal s_feePool; - - AggregatorV3Interface private s_linkToNativeFeed; - AggregatorV3Interface private s_linkToUsdFeed; - - // ================================================================ - // | Initialization | - // ================================================================ - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) Routable(router) { - s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); - s_linkToUsdFeed = AggregatorV3Interface(linkToUsdFeed); - - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the Chainlink Coordinator's billing configuration - /// @return config - function getConfig() external view returns (FunctionsBillingConfig memory) { - return s_config; - } - - /// @notice Sets the Chainlink Coordinator's billing configuration - /// @param config - See the contents of the FunctionsBillingConfig struct in IFunctionsBilling.sol for more information - function updateConfig(FunctionsBillingConfig memory config) public { - _onlyOwner(); - - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Fee Calculation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function getDONFeeJuels(bytes memory /* requestData */) public view override returns (uint72) { - // s_config.donFee is in cents of USD. Convert to dollars amount then get amount of Juels. - return SafeCast.toUint72(_getJuelsFromUsd(s_config.donFeeCentsUsd) / 100); - } - - /// @inheritdoc IFunctionsBilling - function getOperationFeeJuels() public view override returns (uint72) { - // s_config.donFee is in cents of USD. Convert to dollars then get amount of Juels. - return SafeCast.toUint72(_getJuelsFromUsd(s_config.operationFeeCentsUsd) / 100); - } - - /// @inheritdoc IFunctionsBilling - function getAdminFeeJuels() public view override returns (uint72) { - return _getRouter().getAdminFee(); - } - - /// @inheritdoc IFunctionsBilling - function getWeiPerUnitLink() public view returns (uint256) { - (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); - // Only fallback if feedStalenessSeconds is set - // solhint-disable-next-line not-rely-on-time - if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { - return s_config.fallbackNativePerUnitLink; - } - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - return uint256(weiPerUnitLink); - } - - function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { - // (1e18 juels/link) * wei / (wei/link) = juels - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); - } - - /// @inheritdoc IFunctionsBilling - function getUsdPerUnitLink() public view returns (uint256, uint8) { - (, int256 usdPerUnitLink, , uint256 timestamp, ) = s_linkToUsdFeed.latestRoundData(); - // Only fallback if feedStalenessSeconds is set - // solhint-disable-next-line not-rely-on-time - if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { - return (s_config.fallbackUsdPerUnitLink, s_config.fallbackUsdPerUnitLinkDecimals); - } - if (usdPerUnitLink <= 0) { - revert InvalidUsdLinkPrice(usdPerUnitLink); - } - return (uint256(usdPerUnitLink), s_linkToUsdFeed.decimals()); - } - - function _getJuelsFromUsd(uint256 amountUsd) private view returns (uint96) { - (uint256 usdPerLink, uint8 decimals) = getUsdPerUnitLink(); - // (usd) * (10**18 juels/link) * (10**decimals) / (link / usd) = juels - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((amountUsd * 10 ** (18 + decimals)) / usdPerLink); - } - - // ================================================================ - // | Cost Estimation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view override returns (uint96) { - _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - // Reasonable ceilings to prevent integer overflows - if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { - revert InvalidCalldata(); - } - uint72 adminFee = getAdminFeeJuels(); - uint72 donFee = getDONFeeJuels(data); - uint72 operationFee = getOperationFeeJuels(); - return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); - } - - /// @notice Estimate the cost in Juels of LINK - // that will be charged to a subscription to fulfill a Functions request - // Gas Price can be overestimated to account for flucuations between request and response time - function _calculateCostEstimate( - uint32 callbackGasLimit, - uint256 gasPriceWei, - uint72 donFeeJuels, - uint72 adminFeeJuels, - uint72 operationFeeJuels - ) internal view returns (uint96) { - // If gas price is less than the minimum fulfillment gas price, override to using the minimum - if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { - gasPriceWei = s_config.minimumEstimateGasPriceWei; - } - - uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit; - 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); - - return estimatedGasReimbursementJuels + feesJuels; - } - - // ================================================================ - // | Billing | - // ================================================================ - - /// @notice Initiate the billing process for an Functions request - /// @dev Only callable by the Functions Router - /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure - /// @return commitment - The parameters of the request that must be held consistent at response time - function _startBilling( - FunctionsResponse.RequestMeta memory request - ) internal returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { - // Nodes should support all past versions of the structure - if (request.dataVersion > s_config.maxSupportedRequestDataVersion) { - revert UnsupportedRequestDataVersion(); - } - - uint72 donFee = getDONFeeJuels(request.data); - operationFee = getOperationFeeJuels(); - uint96 estimatedTotalCostJuels = _calculateCostEstimate( - request.callbackGasLimit, - tx.gasprice, - donFee, - request.adminFee, - operationFee - ); - - // Check that subscription can afford the estimated cost - if ((request.availableBalance) < estimatedTotalCostJuels) { - revert InsufficientBalance(); - } - - uint32 timeoutTimestamp = uint32(block.timestamp + s_config.requestTimeoutSeconds); - bytes32 requestId = keccak256( - abi.encode( - address(this), - request.requestingContract, - request.subscriptionId, - request.initiatedRequests + 1, - keccak256(request.data), - request.dataVersion, - request.callbackGasLimit, - estimatedTotalCostJuels, - timeoutTimestamp, - // solhint-disable-next-line avoid-tx-origin - tx.origin - ) - ); - - commitment = FunctionsResponse.Commitment({ - adminFee: request.adminFee, - coordinator: address(this), - client: request.requestingContract, - subscriptionId: request.subscriptionId, - callbackGasLimit: request.callbackGasLimit, - estimatedTotalCostJuels: estimatedTotalCostJuels, - timeoutTimestamp: timeoutTimestamp, - requestId: requestId, - donFee: donFee, - gasOverheadBeforeCallback: s_config.gasOverheadBeforeCallback, - gasOverheadAfterCallback: s_config.gasOverheadAfterCallback - }); - - s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); - - return (commitment, operationFee); - } - - /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription - /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @param reportBatchSize the number of fulfillments in the transmitter's report - /// @return result fulfillment result - /// @dev Only callable by a node that has been approved on the Coordinator - /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request - function _fulfillAndBill( - bytes32 requestId, - bytes memory response, - bytes memory err, - bytes memory onchainMetadata, - bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, - uint8 reportBatchSize - ) internal returns (FunctionsResponse.FulfillResult) { - FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); - - uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; - uint256 l1FeeShareWei = ChainSpecificUtil._getL1FeeUpperLimit(msg.data.length) / reportBatchSize; - // Gas overhead without callback - uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); - uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); - - // The Functions Router will perform the callback to the client contract - (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( - response, - err, - juelsPerGas, - // The following line represents: "cost without callback or admin fee, those will be added by the Router" - // But because the _offchain_ Commitment is using operation fee in the place of the admin fee, this now adds admin fee (actually operation fee) - // Admin fee is configured to 0 in the Router - gasOverheadJuels + commitment.donFee + commitment.adminFee, - msg.sender, - FunctionsResponse.Commitment({ - adminFee: 0, // The Router should have adminFee set to 0. If it does not this will cause fulfillments to fail with INVALID_COMMITMENT instead of carrying out incorrect bookkeeping. - coordinator: commitment.coordinator, - client: commitment.client, - subscriptionId: commitment.subscriptionId, - callbackGasLimit: commitment.callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback - }) - ); - - // The router will only pay the DON on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the Coordinator should hold on to the request commitment - if ( - resultCode == FunctionsResponse.FulfillResult.FULFILLED || - resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - delete s_requestCommitments[requestId]; - // Reimburse the transmitter for the fulfillment gas cost - s_withdrawableTokens[msg.sender] += gasOverheadJuels + callbackCostJuels; - // Put donFee into the pool of fees, to be split later - // Saves on storage writes that would otherwise be charged to the user - s_feePool += commitment.donFee; - // Pay the operation fee to the Coordinator owner - s_withdrawableTokens[_owner()] += commitment.adminFee; // OperationFee is used in the slot for Admin Fee in the Offchain Commitment. Admin Fee is set to 0 in the Router (enforced by line 316 in FunctionsBilling.sol). - emit RequestBilled({ - requestId: requestId, - juelsPerGas: juelsPerGas, - l1FeeShareWei: l1FeeShareWei, - callbackCostJuels: callbackCostJuels, - donFeeJuels: commitment.donFee, - // The following two lines are because of OperationFee being used in the Offchain Commitment - adminFeeJuels: 0, - operationFeeJuels: commitment.adminFee - }); - } - return resultCode; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Router - /// @dev Used by FunctionsRouter.sol during timeout of a request - function deleteCommitment(bytes32 requestId) external override onlyRouter { - // Delete commitment - delete s_requestCommitments[requestId]; - emit CommitmentDeleted(requestId); - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function oracleWithdraw(address recipient, uint96 amount) external { - _disperseFeePool(); - - if (amount == 0) { - amount = s_withdrawableTokens[msg.sender]; - } else if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); - } - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Coordinator owner - function oracleWithdrawAll() external { - _onlyOwner(); - _disperseFeePool(); - - address[] memory transmitters = _getTransmitters(); - - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < transmitters.length; ++i) { - uint96 balance = s_withdrawableTokens[transmitters[i]]; - if (balance > 0) { - s_withdrawableTokens[transmitters[i]] = 0; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); - } - } - } - - // Overriden in FunctionsCoordinator, which has visibility into transmitters - function _getTransmitters() internal view virtual returns (address[] memory); - - // DON fees are collected into a pool s_feePool - // When OCR configuration changes, or any oracle withdraws, this must be dispersed - function _disperseFeePool() internal { - if (s_feePool == 0) { - return; - } - // All transmitters are assumed to also be observers - // Pay out the DON fee to all transmitters - address[] memory transmitters = _getTransmitters(); - uint256 numberOfTransmitters = transmitters.length; - if (numberOfTransmitters == 0) { - revert NoTransmittersSet(); - } - uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); - if (feePoolShare == 0) { - // Dust cannot be evenly distributed to all transmitters - return; - } - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < numberOfTransmitters; ++i) { - s_withdrawableTokens[transmitters[i]] += feePoolShare; - } - s_feePool -= feePoolShare * uint96(numberOfTransmitters); - } - - // Overriden in FunctionsCoordinator.sol - function _onlyOwner() internal view virtual; - - // Used in FunctionsCoordinator.sol - function _isExistingRequest(bytes32 requestId) internal view returns (bool) { - return s_requestCommitments[requestId] != bytes32(0); - } - - // Overriden in FunctionsCoordinator.sol - function _owner() internal view virtual returns (address owner); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol deleted file mode 100644 index 378714d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsClient.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; -import {IFunctionsClient} from "./interfaces/IFunctionsClient.sol"; - -import {FunctionsRequest} from "./libraries/FunctionsRequest.sol"; - -/// @title The Chainlink Functions client contract -/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests -abstract contract FunctionsClient is IFunctionsClient { - using FunctionsRequest for FunctionsRequest.Request; - - IFunctionsRouter internal immutable i_functionsRouter; - - event RequestSent(bytes32 indexed id); - event RequestFulfilled(bytes32 indexed id); - - error OnlyRouterCanFulfill(); - - constructor(address router) { - i_functionsRouter = IFunctionsRouter(router); - } - - /// @notice Sends a Chainlink Functions request - /// @param data The CBOR encoded bytes data for a Functions request - /// @param subscriptionId The subscription ID that will be charged to service the request - /// @param callbackGasLimit - The amount of gas that will be available for the fulfillment callback - /// @param donId - An identifier used to determine which route to send the request along - /// @return requestId The generated request ID for this request - function _sendRequest( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) internal returns (bytes32) { - bytes32 requestId = i_functionsRouter.sendRequest( - subscriptionId, - data, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - donId - ); - emit RequestSent(requestId); - return requestId; - } - - /// @notice User defined function to handle a response from the DON - /// @param requestId The request ID, returned by sendRequest() - /// @param response Aggregated response from the execution of the user's source code - /// @param err Aggregated error from the execution of the user code or from the execution pipeline - /// @dev Either response or error parameter will be set, but never both - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; - - /// @inheritdoc IFunctionsClient - function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { - if (msg.sender != address(i_functionsRouter)) { - revert OnlyRouterCanFulfill(); - } - _fulfillRequest(requestId, response, err); - emit RequestFulfilled(requestId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol deleted file mode 100644 index 69d6f3a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -import {FunctionsBilling, FunctionsBillingConfig} from "./FunctionsBilling.sol"; -import {OCR2Base} from "./ocr/OCR2Base.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -/// @title Functions Coordinator contract -/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with -contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Coordinator v1.3.1"; - - event OracleRequest( - bytes32 indexed requestId, - address indexed requestingContract, - address requestInitiator, - uint64 subscriptionId, - address subscriptionOwner, - bytes data, - uint16 dataVersion, - bytes32 flags, - uint64 callbackGasLimit, - FunctionsResponse.Commitment commitment - ); - event OracleResponse(bytes32 indexed requestId, address transmitter); - - error InconsistentReportData(); - error EmptyPublicKey(); - error UnauthorizedPublicKeyChange(); - - bytes private s_donPublicKey; - bytes private s_thresholdPublicKey; - - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed, linkToUsdFeed) {} - - /// @inheritdoc IFunctionsCoordinator - function getThresholdPublicKey() external view override returns (bytes memory) { - if (s_thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { - if (thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_thresholdPublicKey = thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function getDONPublicKey() external view override returns (bytes memory) { - if (s_donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_donPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { - if (donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_donPublicKey = donPublicKey; - } - - /// @dev check if node is in current transmitter list - function _isTransmitter(address node) internal view returns (bool) { - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < s_transmitters.length; ++i) { - if (s_transmitters[i] == node) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsCoordinator - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { - uint72 operationFee; - (commitment, operationFee) = _startBilling(request); - - emit OracleRequest( - commitment.requestId, - request.requestingContract, - // solhint-disable-next-line avoid-tx-origin - tx.origin, - request.subscriptionId, - request.subscriptionOwner, - request.data, - request.dataVersion, - request.flags, - request.callbackGasLimit, - FunctionsResponse.Commitment({ - coordinator: commitment.coordinator, - client: commitment.client, - subscriptionId: commitment.subscriptionId, - callbackGasLimit: commitment.callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, - // The following line is done to use the Coordinator's operationFee in place of the Router's operation fee - // With this in place the Router.adminFee must be set to 0 in the Router. - adminFee: operationFee - }) - ); - - return commitment; - } - - /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. - function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { - if (_getTransmitters().length > 0) { - _disperseFeePool(); - } - } - - /// @dev Used by FunctionsBilling.sol - function _getTransmitters() internal view override returns (address[] memory) { - return s_transmitters; - } - - function _beforeTransmit( - bytes calldata report - ) internal view override returns (bool shouldStop, DecodedReport memory decodedReport) { - ( - bytes32[] memory requestIds, - bytes[] memory results, - bytes[] memory errors, - bytes[] memory onchainMetadata, - bytes[] memory offchainMetadata - ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); - uint256 numberOfFulfillments = uint8(requestIds.length); - - if ( - numberOfFulfillments == 0 || - numberOfFulfillments != results.length || - numberOfFulfillments != errors.length || - numberOfFulfillments != onchainMetadata.length || - numberOfFulfillments != offchainMetadata.length - ) { - revert ReportInvalid("Fields must be equal length"); - } - - for (uint256 i = 0; i < numberOfFulfillments; ++i) { - if (_isExistingRequest(requestIds[i])) { - // If there is an existing request, validate report - // Leave shouldStop to default, false - break; - } - if (i == numberOfFulfillments - 1) { - // If the last fulfillment on the report does not exist, then all are duplicates - // Indicate that it's safe to stop to save on the gas of validating the report - shouldStop = true; - } - } - - return ( - shouldStop, - DecodedReport({ - requestIds: requestIds, - results: results, - errors: errors, - onchainMetadata: onchainMetadata, - offchainMetadata: offchainMetadata - }) - ); - } - - /// @dev Report hook called within OCR2Base.sol - function _report(DecodedReport memory decodedReport) internal override { - uint256 numberOfFulfillments = uint8(decodedReport.requestIds.length); - - // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig - for (uint256 i = 0; i < numberOfFulfillments; ++i) { - FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( - _fulfillAndBill( - decodedReport.requestIds[i], - decodedReport.results[i], - decodedReport.errors[i], - decodedReport.onchainMetadata[i], - decodedReport.offchainMetadata[i], - uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig - ) - ); - - // Emit on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the DON will re-try - if ( - result == FunctionsResponse.FulfillResult.FULFILLED || - result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - emit OracleResponse(decodedReport.requestIds[i], msg.sender); - } - } - } - - /// @dev Used in FunctionsBilling.sol - function _onlyOwner() internal view override { - _validateOwnership(); - } - - /// @dev Used in FunctionsBilling.sol - function _owner() internal view override returns (address owner) { - return this.owner(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol deleted file mode 100644 index ec1ccbd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsRouter.sol +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; -import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; -import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; - -import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; - -import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {Pausable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; - -contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - string public constant override typeAndVersion = "Functions Router v2.0.0"; - - // We limit return data to a selector plus 4 words. This is to avoid - // malicious contracts from returning large amounts of data and causing - // repeated out-of-gas scenarios. - uint16 public constant MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32; - uint8 private constant MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - - event RequestProcessed( - bytes32 indexed requestId, - uint64 indexed subscriptionId, - uint96 totalCostJuels, - address transmitter, - FunctionsResponse.FulfillResult resultCode, - bytes response, - bytes err, - bytes callbackReturnData - ); - - event RequestNotProcessed( - bytes32 indexed requestId, - address coordinator, - address transmitter, - FunctionsResponse.FulfillResult resultCode - ); - - error EmptyRequestData(); - error OnlyCallableFromCoordinator(); - error SenderMustAcceptTermsOfService(address sender); - error InvalidGasFlagValue(uint8 value); - error GasLimitTooBig(uint32 limit); - error DuplicateRequestId(bytes32 requestId); - - struct CallbackResult { - bool success; // ══════╸ Whether the callback succeeded or not - uint256 gasUsed; // ═══╸ The amount of gas consumed during the callback - bytes returnData; // ══╸ The return of the callback function - } - - // ================================================================ - // | Route state | - // ================================================================ - - mapping(bytes32 id => address routableContract) private s_route; - - error RouteNotFound(bytes32 id); - - // Identifier for the route to the Terms of Service Allow List - bytes32 private s_allowListId; - - // ================================================================ - // | Configuration state | - // ================================================================ - // solhint-disable-next-line gas-struct-packing - struct Config { - uint16 maxConsumersPerSubscription; // ═════════╗ Maximum number of consumers which can be added to a single subscription. This bound ensures we are able to loop over all subscription consumers as needed, without exceeding gas limits. Should a user require more consumers, they can use multiple subscriptions. - uint72 adminFee; // ║ Flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network - bytes4 handleOracleFulfillmentSelector; // ║ The function selector that is used when calling back to the Client contract - uint16 gasForCallExactCheck; // ════════════════╝ Used during calling back to the client. Ensures we have at least enough gas to be able to revert if gasAmount > 63//64*gas available. - uint32[] maxCallbackGasLimits; // ══════════════╸ List of max callback gas limits used by flag with MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX - uint16 subscriptionDepositMinimumRequests; //═══╗ Amount of requests that must be completed before the full subscription balance will be released when closing a subscription account. - uint72 subscriptionDepositJuels; // ════════════╝ Amount of subscription funds that are held as a deposit until Config.subscriptionDepositMinimumRequests are made using the subscription. - } - - Config private s_config; - - event ConfigUpdated(Config); - - // ================================================================ - // | Proposal state | - // ================================================================ - - uint8 private constant MAX_PROPOSAL_SET_LENGTH = 8; - - struct ContractProposalSet { - bytes32[] ids; // ══╸ The IDs that key into the routes that will be modified if the update is applied - address[] to; // ═══╸ The address of the contracts that the route will point to if the updated is applied - } - ContractProposalSet private s_proposedContractSet; - - event ContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ); - - event ContractUpdated(bytes32 id, address from, address to); - - error InvalidProposal(); - error IdentifierIsReserved(bytes32 id); - - // ================================================================ - // | Initialization | - // ================================================================ - - constructor( - address linkToken, - Config memory config - ) FunctionsSubscriptions(linkToken) ConfirmedOwner(msg.sender) Pausable() { - // Set the intial configuration - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice The identifier of the route to retrieve the address of the access control contract - // The access control contract controls which accounts can manage subscriptions - /// @return id - bytes32 id that can be passed to the "getContractById" of the Router - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice The router configuration - function updateConfig(Config memory config) public onlyOwner { - s_config = config; - emit ConfigUpdated(config); - } - - /// @inheritdoc IFunctionsRouter - function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) public view { - uint8 callbackGasLimitsIndexSelector = uint8(getFlags(subscriptionId)[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - if (callbackGasLimitsIndexSelector >= s_config.maxCallbackGasLimits.length) { - revert InvalidGasFlagValue(callbackGasLimitsIndexSelector); - } - uint32 maxCallbackGasLimit = s_config.maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - if (callbackGasLimit > maxCallbackGasLimit) { - revert GasLimitTooBig(maxCallbackGasLimit); - } - } - - /// @inheritdoc IFunctionsRouter - function getAdminFee() external view override returns (uint72) { - return s_config.adminFee; - } - - /// @inheritdoc IFunctionsRouter - function getAllowListId() external view override returns (bytes32) { - return s_allowListId; - } - - /// @inheritdoc IFunctionsRouter - function setAllowListId(bytes32 allowListId) external override onlyOwner { - s_allowListId = allowListId; - } - - /// @dev Used within FunctionsSubscriptions.sol - function _getMaxConsumers() internal view override returns (uint16) { - return s_config.maxConsumersPerSubscription; - } - - /// @dev Used within FunctionsSubscriptions.sol - function _getSubscriptionDepositDetails() internal view override returns (uint16, uint72) { - return (s_config.subscriptionDepositMinimumRequests, s_config.subscriptionDepositJuels); - } - - // ================================================================ - // | Requests | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function sendRequest( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external override returns (bytes32) { - IFunctionsCoordinator coordinator = IFunctionsCoordinator(getContractById(donId)); - return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); - } - - /// @inheritdoc IFunctionsRouter - function sendRequestToProposed( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external override returns (bytes32) { - IFunctionsCoordinator coordinator = IFunctionsCoordinator(getProposedContractById(donId)); - return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); - } - - function _sendRequest( - bytes32 donId, - IFunctionsCoordinator coordinator, - uint64 subscriptionId, - bytes memory data, - uint16 dataVersion, - uint32 callbackGasLimit - ) private returns (bytes32) { - _whenNotPaused(); - _isExistingSubscription(subscriptionId); - _isAllowedConsumer(msg.sender, subscriptionId); - isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - - if (data.length == 0) { - revert EmptyRequestData(); - } - - Subscription memory subscription = getSubscription(subscriptionId); - Consumer memory consumer = getConsumer(msg.sender, subscriptionId); - uint72 adminFee = s_config.adminFee; - - // Forward request to DON - FunctionsResponse.Commitment memory commitment = coordinator.startRequest( - FunctionsResponse.RequestMeta({ - requestingContract: msg.sender, - data: data, - subscriptionId: subscriptionId, - dataVersion: dataVersion, - flags: getFlags(subscriptionId), - callbackGasLimit: callbackGasLimit, - adminFee: adminFee, - initiatedRequests: consumer.initiatedRequests, - completedRequests: consumer.completedRequests, - availableBalance: subscription.balance - subscription.blockedBalance, - subscriptionOwner: subscription.owner - }) - ); - - // Do not allow setting a comittment for a requestId that already exists - if (s_requestCommitments[commitment.requestId] != bytes32(0)) { - revert DuplicateRequestId(commitment.requestId); - } - - // Store a commitment about the request - s_requestCommitments[commitment.requestId] = keccak256( - abi.encode( - FunctionsResponse.Commitment({ - adminFee: adminFee, - coordinator: address(coordinator), - client: msg.sender, - subscriptionId: subscriptionId, - callbackGasLimit: callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback - }) - ) - ); - - _markRequestInFlight(msg.sender, subscriptionId, commitment.estimatedTotalCostJuels); - - emit RequestStart({ - requestId: commitment.requestId, - donId: donId, - subscriptionId: subscriptionId, - subscriptionOwner: subscription.owner, - requestingContract: msg.sender, - // solhint-disable-next-line avoid-tx-origin - requestInitiator: tx.origin, - data: data, - dataVersion: dataVersion, - callbackGasLimit: callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels - }); - - return commitment.requestId; - } - - // ================================================================ - // | Responses | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function fulfill( - bytes memory response, - bytes memory err, - uint96 juelsPerGas, - uint96 costWithoutFulfillment, - address transmitter, - FunctionsResponse.Commitment memory commitment - ) external override returns (FunctionsResponse.FulfillResult resultCode, uint96) { - _whenNotPaused(); - - if (msg.sender != commitment.coordinator) { - revert OnlyCallableFromCoordinator(); - } - - { - bytes32 commitmentHash = s_requestCommitments[commitment.requestId]; - - if (commitmentHash == bytes32(0)) { - resultCode = FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - if (keccak256(abi.encode(commitment)) != commitmentHash) { - resultCode = FunctionsResponse.FulfillResult.INVALID_COMMITMENT; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - // Check that the transmitter has supplied enough gas for the callback to succeed - if (gasleft() < commitment.callbackGasLimit + commitment.gasOverheadAfterCallback) { - resultCode = FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - } - - { - uint96 callbackCost = juelsPerGas * SafeCast.toUint96(commitment.callbackGasLimit); - uint96 totalCostJuels = commitment.adminFee + costWithoutFulfillment + callbackCost; - - // Check that the subscription can still afford to fulfill the request - if (totalCostJuels > getSubscription(commitment.subscriptionId).balance) { - resultCode = FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - // Check that the cost has not exceeded the quoted cost - if (totalCostJuels > commitment.estimatedTotalCostJuels) { - resultCode = FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - } - - delete s_requestCommitments[commitment.requestId]; - - CallbackResult memory result = _callback( - commitment.requestId, - response, - err, - commitment.callbackGasLimit, - commitment.client - ); - - resultCode = result.success - ? FunctionsResponse.FulfillResult.FULFILLED - : FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR; - - Receipt memory receipt = _pay( - commitment.subscriptionId, - commitment.estimatedTotalCostJuels, - commitment.client, - commitment.adminFee, - juelsPerGas, - SafeCast.toUint96(result.gasUsed), - costWithoutFulfillment - ); - - emit RequestProcessed({ - requestId: commitment.requestId, - subscriptionId: commitment.subscriptionId, - totalCostJuels: receipt.totalCostJuels, - transmitter: transmitter, - resultCode: resultCode, - response: response, - err: err, - callbackReturnData: result.returnData - }); - - return (resultCode, receipt.callbackGasCostJuels); - } - - function _callback( - bytes32 requestId, - bytes memory response, - bytes memory err, - uint32 callbackGasLimit, - address client - ) private returns (CallbackResult memory) { - bool destinationNoLongerExists; - assembly { - // solidity calls check that a contract actually exists at the destination, so we do the same - destinationNoLongerExists := iszero(extcodesize(client)) - } - if (destinationNoLongerExists) { - // Return without attempting callback - // The subscription will still be charged to reimburse transmitter's gas overhead - return CallbackResult({success: false, gasUsed: 0, returnData: new bytes(0)}); - } - - bytes memory encodedCallback = abi.encodeWithSelector( - s_config.handleOracleFulfillmentSelector, - requestId, - response, - err - ); - - uint16 gasForCallExactCheck = s_config.gasForCallExactCheck; - - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid payment. - // NOTE: that callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - - bool success; - uint256 gasUsed; - // allocate return data memory ahead of time - bytes memory returnData = new bytes(MAX_CALLBACK_RETURN_BYTES); - - assembly { - let g := gas() - // Compute g -= gasForCallExactCheck and check for underflow - // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. gasForCallExactCheck ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, gasForCallExactCheck) { - revert(0, 0) - } - g := sub(g, gasForCallExactCheck) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), callbackGasLimit)) { - revert(0, 0) - } - // call and report whether we succeeded - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - let gasBeforeCall := gas() - success := call(callbackGasLimit, client, 0, add(encodedCallback, 0x20), mload(encodedCallback), 0, 0) - gasUsed := sub(gasBeforeCall, gas()) - - // limit our copy to MAX_CALLBACK_RETURN_BYTES bytes - let toCopy := returndatasize() - if gt(toCopy, MAX_CALLBACK_RETURN_BYTES) { - toCopy := MAX_CALLBACK_RETURN_BYTES - } - // Store the length of the copied bytes - mstore(returnData, toCopy) - // copy the bytes from returnData[0:_toCopy] - returndatacopy(add(returnData, 0x20), 0, toCopy) - } - - return CallbackResult({success: success, gasUsed: gasUsed, returnData: returnData}); - } - - // ================================================================ - // | Route methods | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function getContractById(bytes32 id) public view override returns (address) { - address currentImplementation = s_route[id]; - if (currentImplementation == address(0)) { - revert RouteNotFound(id); - } - return currentImplementation; - } - - /// @inheritdoc IFunctionsRouter - function getProposedContractById(bytes32 id) public view override returns (address) { - // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint8 i = 0; i < s_proposedContractSet.ids.length; ++i) { - if (id == s_proposedContractSet.ids[i]) { - return s_proposedContractSet.to[i]; - } - } - revert RouteNotFound(id); - } - - // ================================================================ - // | Contract Proposal methods | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function getProposedContractSet() external view override returns (bytes32[] memory, address[] memory) { - return (s_proposedContractSet.ids, s_proposedContractSet.to); - } - - /// @inheritdoc IFunctionsRouter - function proposeContractsUpdate( - bytes32[] memory proposedContractSetIds, - address[] memory proposedContractSetAddresses - ) external override onlyOwner { - // IDs and addresses arrays must be of equal length and must not exceed the max proposal length - uint256 idsArrayLength = proposedContractSetIds.length; - if (idsArrayLength != proposedContractSetAddresses.length || idsArrayLength > MAX_PROPOSAL_SET_LENGTH) { - revert InvalidProposal(); - } - - // NOTE: iterations of this loop will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint256 i = 0; i < idsArrayLength; ++i) { - bytes32 id = proposedContractSetIds[i]; - address proposedContract = proposedContractSetAddresses[i]; - if ( - proposedContract == address(0) || // The Proposed address must be a valid address - s_route[id] == proposedContract // The Proposed address must point to a different address than what is currently set - ) { - revert InvalidProposal(); - } - - emit ContractProposed({ - proposedContractSetId: id, - proposedContractSetFromAddress: s_route[id], - proposedContractSetToAddress: proposedContract - }); - } - - s_proposedContractSet = ContractProposalSet({ids: proposedContractSetIds, to: proposedContractSetAddresses}); - } - - /// @inheritdoc IFunctionsRouter - function updateContracts() external override onlyOwner { - // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint256 i = 0; i < s_proposedContractSet.ids.length; ++i) { - bytes32 id = s_proposedContractSet.ids[i]; - address to = s_proposedContractSet.to[i]; - emit ContractUpdated({id: id, from: s_route[id], to: to}); - s_route[id] = to; - } - - delete s_proposedContractSet; - } - - // ================================================================ - // | Modifiers | - // ================================================================ - // Favoring internal functions over actual modifiers to reduce contract size - - /// @dev Used within FunctionsSubscriptions.sol - function _whenNotPaused() internal view override { - _requireNotPaused(); - } - - /// @dev Used within FunctionsSubscriptions.sol - function _onlyRouterOwner() internal view override { - _validateOwnership(); - } - - /// @dev Used within FunctionsSubscriptions.sol - function _onlySenderThatAcceptedToS() internal view override { - address currentImplementation = s_route[s_allowListId]; - if (currentImplementation == address(0)) { - // If not set, ignore this check, allow all access - return; - } - if (!IAccessController(currentImplementation).hasAccess(msg.sender, new bytes(0))) { - revert SenderMustAcceptTermsOfService(msg.sender); - } - } - - /// @inheritdoc IFunctionsRouter - function pause() external override onlyOwner { - _pause(); - } - - /// @inheritdoc IFunctionsRouter - function unpause() external override onlyOwner { - _unpause(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol deleted file mode 100644 index bcd01c1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/FunctionsSubscriptions.sol +++ /dev/null @@ -1,552 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; -import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; -import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; - -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @title Functions Subscriptions contract -/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsSubscriptions is IFunctionsSubscriptions, IERC677Receiver { - using SafeERC20 for IERC20; - using FunctionsResponse for FunctionsResponse.Commitment; - - // ================================================================ - // | Balance state | - // ================================================================ - // link token address - IERC20 internal immutable i_linkToken; - - // s_totalLinkBalance tracks the total LINK sent to/from - // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. - // A discrepancy with this contract's LINK balance indicates that someone - // sent tokens using transfer and so we may need to use recoverFunds. - uint96 private s_totalLinkBalance; - - /// @dev NOP balances are held as a single amount. The breakdown is held by the Coordinator. - mapping(address coordinator => uint96 balanceJuelsLink) private s_withdrawableTokens; - - // ================================================================ - // | Subscription state | - // ================================================================ - // Keep a count of the number of subscriptions so that its possible to - // loop through all the current subscriptions via .getSubscription(). - uint64 private s_currentSubscriptionId; - - mapping(uint64 subscriptionId => Subscription) private s_subscriptions; - - // Maintains the list of keys in s_consumers. - // We do this for 2 reasons: - // 1. To be able to clean up all keys from s_consumers when canceling a subscription. - // 2. To be able to return the list of all consumers in getSubscription. - // Note that we need the s_consumers map to be able to directly check if a - // consumer is valid without reading all the consumers from storage. - mapping(address consumer => mapping(uint64 subscriptionId => Consumer)) private s_consumers; - - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); - - error TooManyConsumers(uint16 maximumConsumers); - error InsufficientBalance(uint96 currentBalanceJuels); - error InvalidConsumer(); - error CannotRemoveWithPendingRequests(); - error InvalidSubscription(); - error OnlyCallableFromLink(); - error InvalidCalldata(); - error MustBeSubscriptionOwner(); - error TimeoutNotExceeded(); - error MustBeProposedOwner(address proposedOwner); - event FundsRecovered(address to, uint256 amount); - - // ================================================================ - // | Request state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) internal s_requestCommitments; - - struct Receipt { - uint96 callbackGasCostJuels; - uint96 totalCostJuels; - } - - event RequestTimedOut(bytes32 indexed requestId); - - // ================================================================ - // | Initialization | - // ================================================================ - constructor(address link) { - i_linkToken = IERC20(link); - } - - // ================================================================ - // | Request/Response | - // ================================================================ - - /// @notice Sets a request as in-flight - /// @dev Only callable within the Router - function _markRequestInFlight(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) internal { - // Earmark subscription funds - s_subscriptions[subscriptionId].blockedBalance += estimatedTotalCostJuels; - - // Increment sent requests - s_consumers[client][subscriptionId].initiatedRequests += 1; - } - - /// @notice Moves funds from one subscription account to another. - /// @dev Only callable by the Coordinator contract that is saved in the request commitment - function _pay( - uint64 subscriptionId, - uint96 estimatedTotalCostJuels, - address client, - uint96 adminFee, - uint96 juelsPerGas, - uint96 gasUsed, - uint96 costWithoutCallbackJuels - ) internal returns (Receipt memory) { - uint96 callbackGasCostJuels = juelsPerGas * gasUsed; - uint96 totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels; - - if ( - s_subscriptions[subscriptionId].balance < totalCostJuels || - s_subscriptions[subscriptionId].blockedBalance < estimatedTotalCostJuels - ) { - revert InsufficientBalance(s_subscriptions[subscriptionId].balance); - } - - // Charge the subscription - s_subscriptions[subscriptionId].balance -= totalCostJuels; - - // Unblock earmarked funds - s_subscriptions[subscriptionId].blockedBalance -= estimatedTotalCostJuels; - - // Pay the DON's fees and gas reimbursement - s_withdrawableTokens[msg.sender] += costWithoutCallbackJuels + callbackGasCostJuels; - - // Pay out the administration fee - s_withdrawableTokens[address(this)] += adminFee; - - // Increment finished requests - s_consumers[client][subscriptionId].completedRequests += 1; - - return Receipt({callbackGasCostJuels: callbackGasCostJuels, totalCostJuels: totalCostJuels}); - } - - // ================================================================ - // | Owner methods | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function ownerCancelSubscription(uint64 subscriptionId) external override { - _onlyRouterOwner(); - _isExistingSubscription(subscriptionId); - _cancelSubscriptionHelper(subscriptionId, s_subscriptions[subscriptionId].owner, false); - } - - /// @inheritdoc IFunctionsSubscriptions - function recoverFunds(address to) external override { - _onlyRouterOwner(); - uint256 externalBalance = i_linkToken.balanceOf(address(this)); - uint256 internalBalance = uint256(s_totalLinkBalance); - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - i_linkToken.safeTransfer(to, amount); - emit FundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function oracleWithdraw(address recipient, uint96 amount) external override { - _whenNotPaused(); - - if (amount == 0) { - revert InvalidCalldata(); - } - uint96 currentBalance = s_withdrawableTokens[msg.sender]; - if (currentBalance < amount) { - revert InsufficientBalance(currentBalance); - } - s_withdrawableTokens[msg.sender] -= amount; - s_totalLinkBalance -= amount; - i_linkToken.safeTransfer(recipient, amount); - } - - /// @notice Owner withdraw LINK earned through admin fees - /// @notice If amount is 0 the full balance will be withdrawn - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function ownerWithdraw(address recipient, uint96 amount) external { - _onlyRouterOwner(); - if (amount == 0) { - amount = s_withdrawableTokens[address(this)]; - } - uint96 currentBalance = s_withdrawableTokens[address(this)]; - if (currentBalance < amount) { - revert InsufficientBalance(currentBalance); - } - s_withdrawableTokens[address(this)] -= amount; - s_totalLinkBalance -= amount; - - i_linkToken.safeTransfer(recipient, amount); - } - - // ================================================================ - // | TransferAndCall Deposit helper | - // ================================================================ - - // This function is to be invoked when using LINK.transferAndCall - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override { - _whenNotPaused(); - if (msg.sender != address(i_linkToken)) { - revert OnlyCallableFromLink(); - } - if (data.length != 32) { - revert InvalidCalldata(); - } - uint64 subscriptionId = abi.decode(data, (uint64)); - if (s_subscriptions[subscriptionId].owner == address(0)) { - revert InvalidSubscription(); - } - // We do not check that the msg.sender is the subscription owner, - // anyone can fund a subscription. - uint256 oldBalance = s_subscriptions[subscriptionId].balance; - s_subscriptions[subscriptionId].balance += uint96(amount); - s_totalLinkBalance += uint96(amount); - emit SubscriptionFunded(subscriptionId, oldBalance, oldBalance + amount); - } - - // ================================================================ - // | Subscription management | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function getTotalBalance() external view override returns (uint96) { - return s_totalLinkBalance; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscriptionCount() external view override returns (uint64) { - return s_currentSubscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscription(uint64 subscriptionId) public view override returns (Subscription memory) { - _isExistingSubscription(subscriptionId); - return s_subscriptions[subscriptionId]; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscriptionsInRange( - uint64 subscriptionIdStart, - uint64 subscriptionIdEnd - ) external view override returns (Subscription[] memory subscriptions) { - if ( - subscriptionIdStart > subscriptionIdEnd || - subscriptionIdEnd > s_currentSubscriptionId || - s_currentSubscriptionId == 0 - ) { - revert InvalidCalldata(); - } - - subscriptions = new Subscription[]((subscriptionIdEnd - subscriptionIdStart) + 1); - for (uint256 i = 0; i <= subscriptionIdEnd - subscriptionIdStart; ++i) { - subscriptions[i] = s_subscriptions[uint64(subscriptionIdStart + i)]; - } - - return subscriptions; - } - - /// @inheritdoc IFunctionsSubscriptions - function getConsumer(address client, uint64 subscriptionId) public view override returns (Consumer memory) { - return s_consumers[client][subscriptionId]; - } - - /// @dev Used within this file & FunctionsRouter.sol - function _isExistingSubscription(uint64 subscriptionId) internal view { - if (s_subscriptions[subscriptionId].owner == address(0)) { - revert InvalidSubscription(); - } - } - - /// @dev Used within FunctionsRouter.sol - function _isAllowedConsumer(address client, uint64 subscriptionId) internal view { - if (!s_consumers[client][subscriptionId].allowed) { - revert InvalidConsumer(); - } - } - - /// @inheritdoc IFunctionsSubscriptions - function createSubscription() external override returns (uint64 subscriptionId) { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - subscriptionId = ++s_currentSubscriptionId; - s_subscriptions[subscriptionId] = Subscription({ - balance: 0, - blockedBalance: 0, - owner: msg.sender, - proposedOwner: address(0), - consumers: new address[](0), - flags: bytes32(0) - }); - - emit SubscriptionCreated(subscriptionId, msg.sender); - - return subscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function createSubscriptionWithConsumer(address consumer) external override returns (uint64 subscriptionId) { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - subscriptionId = ++s_currentSubscriptionId; - s_subscriptions[subscriptionId] = Subscription({ - balance: 0, - blockedBalance: 0, - owner: msg.sender, - proposedOwner: address(0), - consumers: new address[](0), - flags: bytes32(0) - }); - - s_subscriptions[subscriptionId].consumers.push(consumer); - s_consumers[consumer][subscriptionId].allowed = true; - - emit SubscriptionCreated(subscriptionId, msg.sender); - emit SubscriptionConsumerAdded(subscriptionId, consumer); - - return subscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - if (newOwner == address(0) || s_subscriptions[subscriptionId].proposedOwner == newOwner) { - revert InvalidCalldata(); - } - - s_subscriptions[subscriptionId].proposedOwner = newOwner; - emit SubscriptionOwnerTransferRequested(subscriptionId, msg.sender, newOwner); - } - - /// @inheritdoc IFunctionsSubscriptions - function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external override { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - address previousOwner = s_subscriptions[subscriptionId].owner; - address proposedOwner = s_subscriptions[subscriptionId].proposedOwner; - if (proposedOwner != msg.sender) { - revert MustBeProposedOwner(proposedOwner); - } - s_subscriptions[subscriptionId].owner = msg.sender; - s_subscriptions[subscriptionId].proposedOwner = address(0); - emit SubscriptionOwnerTransferred(subscriptionId, previousOwner, msg.sender); - } - - /// @inheritdoc IFunctionsSubscriptions - function removeConsumer(uint64 subscriptionId, address consumer) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - Consumer memory consumerData = s_consumers[consumer][subscriptionId]; - _isAllowedConsumer(consumer, subscriptionId); - if (consumerData.initiatedRequests != consumerData.completedRequests) { - revert CannotRemoveWithPendingRequests(); - } - // Note bounded by config.maxConsumers - address[] memory consumers = s_subscriptions[subscriptionId].consumers; - for (uint256 i = 0; i < consumers.length; ++i) { - if (consumers[i] == consumer) { - // Storage write to preserve last element - s_subscriptions[subscriptionId].consumers[i] = consumers[consumers.length - 1]; - // Storage remove last element - s_subscriptions[subscriptionId].consumers.pop(); - break; - } - } - delete s_consumers[consumer][subscriptionId]; - emit SubscriptionConsumerRemoved(subscriptionId, consumer); - } - - /// @dev Overriden in FunctionsRouter.sol - function _getMaxConsumers() internal view virtual returns (uint16); - - /// @inheritdoc IFunctionsSubscriptions - function addConsumer(uint64 subscriptionId, address consumer) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - // Already maxed, cannot add any more consumers. - uint16 maximumConsumers = _getMaxConsumers(); - if (s_subscriptions[subscriptionId].consumers.length >= maximumConsumers) { - revert TooManyConsumers(maximumConsumers); - } - if (s_consumers[consumer][subscriptionId].allowed) { - // Idempotence - do nothing if already added. - // Ensures uniqueness in s_subscriptions[subscriptionId].consumers. - return; - } - - s_consumers[consumer][subscriptionId].allowed = true; - s_subscriptions[subscriptionId].consumers.push(consumer); - - emit SubscriptionConsumerAdded(subscriptionId, consumer); - } - - /// @dev Overriden in FunctionsRouter.sol - function _getSubscriptionDepositDetails() internal virtual returns (uint16, uint72); - - function _cancelSubscriptionHelper(uint64 subscriptionId, address toAddress, bool checkDepositRefundability) private { - Subscription memory subscription = s_subscriptions[subscriptionId]; - uint96 balance = subscription.balance; - uint64 completedRequests = 0; - - // NOTE: loop iterations are bounded by config.maxConsumers - // If no consumers, does nothing. - for (uint256 i = 0; i < subscription.consumers.length; ++i) { - address consumer = subscription.consumers[i]; - completedRequests += s_consumers[consumer][subscriptionId].completedRequests; - delete s_consumers[consumer][subscriptionId]; - } - delete s_subscriptions[subscriptionId]; - - (uint16 subscriptionDepositMinimumRequests, uint72 subscriptionDepositJuels) = _getSubscriptionDepositDetails(); - - // If subscription has not made enough requests, deposit will be forfeited - if (checkDepositRefundability && completedRequests < subscriptionDepositMinimumRequests) { - uint96 deposit = subscriptionDepositJuels > balance ? balance : subscriptionDepositJuels; - if (deposit > 0) { - s_withdrawableTokens[address(this)] += deposit; - balance -= deposit; - } - } - - if (balance > 0) { - s_totalLinkBalance -= balance; - i_linkToken.safeTransfer(toAddress, uint256(balance)); - } - emit SubscriptionCanceled(subscriptionId, toAddress, balance); - } - - /// @inheritdoc IFunctionsSubscriptions - function cancelSubscription(uint64 subscriptionId, address to) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - if (pendingRequestExists(subscriptionId)) { - revert CannotRemoveWithPendingRequests(); - } - - _cancelSubscriptionHelper(subscriptionId, to, true); - } - - /// @inheritdoc IFunctionsSubscriptions - function pendingRequestExists(uint64 subscriptionId) public view override returns (bool) { - address[] memory consumers = s_subscriptions[subscriptionId].consumers; - // NOTE: loop iterations are bounded by config.maxConsumers - for (uint256 i = 0; i < consumers.length; ++i) { - Consumer memory consumer = s_consumers[consumers[i]][subscriptionId]; - if (consumer.initiatedRequests != consumer.completedRequests) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsSubscriptions - function setFlags(uint64 subscriptionId, bytes32 flags) external override { - _onlyRouterOwner(); - _isExistingSubscription(subscriptionId); - s_subscriptions[subscriptionId].flags = flags; - } - - /// @inheritdoc IFunctionsSubscriptions - function getFlags(uint64 subscriptionId) public view returns (bytes32) { - return s_subscriptions[subscriptionId].flags; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external override { - _whenNotPaused(); - - for (uint256 i = 0; i < requestsToTimeoutByCommitment.length; ++i) { - FunctionsResponse.Commitment memory request = requestsToTimeoutByCommitment[i]; - bytes32 requestId = request.requestId; - uint64 subscriptionId = request.subscriptionId; - - // Check that request ID is valid - if (keccak256(abi.encode(request)) != s_requestCommitments[requestId]) { - revert InvalidCalldata(); - } - - // Check that request has exceeded allowed request time - if (block.timestamp < request.timeoutTimestamp) { - revert TimeoutNotExceeded(); - } - - // Notify the Coordinator that the request should no longer be fulfilled - IFunctionsBilling(request.coordinator).deleteCommitment(requestId); - // Release the subscription's balance that had been earmarked for the request - s_subscriptions[subscriptionId].blockedBalance -= request.estimatedTotalCostJuels; - s_consumers[request.client][subscriptionId].completedRequests += 1; - // Delete commitment within Router state - delete s_requestCommitments[requestId]; - - emit RequestTimedOut(requestId); - } - } - - // ================================================================ - // | Modifiers | - // ================================================================ - - function _onlySubscriptionOwner(uint64 subscriptionId) internal view { - address owner = s_subscriptions[subscriptionId].owner; - if (owner == address(0)) { - revert InvalidSubscription(); - } - if (msg.sender != owner) { - revert MustBeSubscriptionOwner(); - } - } - - /// @dev Overriden in FunctionsRouter.sol - function _onlySenderThatAcceptedToS() internal virtual; - - /// @dev Overriden in FunctionsRouter.sol - function _onlyRouterOwner() internal virtual; - - /// @dev Overriden in FunctionsRouter.sol - function _whenNotPaused() internal virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol deleted file mode 100644 index 92e2336..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/Routable.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IOwnableFunctionsRouter} from "./interfaces/IOwnableFunctionsRouter.sol"; - -/// @title This abstract should be inherited by contracts that will be used -/// as the destinations to a route (id=>contract) on the Router. -/// It provides a Router getter and modifiers. -abstract contract Routable is ITypeAndVersion { - IOwnableFunctionsRouter private immutable i_functionsRouter; - - error RouterMustBeSet(); - error OnlyCallableByRouter(); - error OnlyCallableByRouterOwner(); - - /// @dev Initializes the contract. - constructor(address router) { - if (router == address(0)) { - revert RouterMustBeSet(); - } - i_functionsRouter = IOwnableFunctionsRouter(router); - } - - /// @notice Return the Router - function _getRouter() internal view returns (IOwnableFunctionsRouter router) { - return i_functionsRouter; - } - - /// @notice Reverts if called by anyone other than the router. - modifier onlyRouter() { - if (msg.sender != address(i_functionsRouter)) { - revert OnlyCallableByRouter(); - } - _; - } - - /// @notice Reverts if called by anyone other than the router owner. - modifier onlyRouterOwner() { - if (msg.sender != i_functionsRouter.owner()) { - revert OnlyCallableByRouterOwner(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol deleted file mode 100644 index 0ba8e5d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITermsOfServiceAllowList, TermsOfServiceAllowListConfig} from "./interfaces/ITermsOfServiceAllowList.sol"; -import {IAccessController} from "../../../../shared/interfaces/IAccessController.sol"; -import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol"; - -import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; - -import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; -import {EnumerableSet} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.AddressSet; - - /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.1"; - address private s_previousToSContract; - - EnumerableSet.AddressSet private s_allowedSenders; - EnumerableSet.AddressSet private s_blockedSenders; - - event AddedAccess(address user); - event BlockedAccess(address user); - event UnblockedAccess(address user); - - error InvalidSignature(); - error InvalidUsage(); - error RecipientIsBlocked(); - error InvalidCalldata(); - error NoPreviousToSContract(); - - TermsOfServiceAllowListConfig private s_config; - - event ConfigUpdated(TermsOfServiceAllowListConfig config); - - // ================================================================ - // | Initialization | - // ================================================================ - - constructor( - TermsOfServiceAllowListConfig memory config, - address[] memory initialAllowedSenders, - address[] memory initialBlockedSenders, - address previousToSContract - ) ConfirmedOwner(msg.sender) { - updateConfig(config); - - for (uint256 i = 0; i < initialAllowedSenders.length; ++i) { - s_allowedSenders.add(initialAllowedSenders[i]); - } - - for (uint256 j = 0; j < initialBlockedSenders.length; ++j) { - if (s_allowedSenders.contains(initialBlockedSenders[j])) { - // Allowed senders cannot also be blocked - revert InvalidCalldata(); - } - s_blockedSenders.add(initialBlockedSenders[j]); - } - - s_previousToSContract = previousToSContract; - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the contracts's configuration - /// @return config - function getConfig() external view returns (TermsOfServiceAllowListConfig memory) { - return s_config; - } - - /// @notice Sets the contracts's configuration - /// @param config - See the contents of the TermsOfServiceAllowListConfig struct in ITermsOfServiceAllowList.sol for more information - function updateConfig(TermsOfServiceAllowListConfig memory config) public onlyOwner { - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Allow methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { - return keccak256(abi.encodePacked(acceptor, recipient)); - } - - /// @inheritdoc ITermsOfServiceAllowList - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { - if (s_blockedSenders.contains(recipient)) { - revert RecipientIsBlocked(); - } - - // Validate that the signature is correct and the correct data has been signed - bytes32 prefixedMessage = keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) - ); - if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { - revert InvalidSignature(); - } - - // If contract, validate that msg.sender == recipient - // This is to prevent EoAs from claiming contracts that they are not in control of - // If EoA, validate that msg.sender == acceptor == recipient - // This is to prevent EoAs from accepting for other EoAs - if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { - revert InvalidUsage(); - } - - // Add recipient to the allow list - if (s_allowedSenders.add(recipient)) { - emit AddedAccess(recipient); - } - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllAllowedSenders() external view override returns (address[] memory) { - return s_allowedSenders.values(); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllowedSendersCount() external view override returns (uint64) { - return uint64(s_allowedSenders.length()); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllowedSendersInRange( - uint64 allowedSenderIdxStart, - uint64 allowedSenderIdxEnd - ) external view override returns (address[] memory allowedSenders) { - if (allowedSenderIdxStart > allowedSenderIdxEnd || allowedSenderIdxEnd >= s_allowedSenders.length()) { - revert InvalidCalldata(); - } - - allowedSenders = new address[]((allowedSenderIdxEnd - allowedSenderIdxStart) + 1); - for (uint256 i = 0; i <= allowedSenderIdxEnd - allowedSenderIdxStart; ++i) { - allowedSenders[i] = s_allowedSenders.at(uint256(allowedSenderIdxStart + i)); - } - - return allowedSenders; - } - - /// @inheritdoc IAccessController - function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { - if (!s_config.enabled) { - return true; - } - return s_allowedSenders.contains(user); - } - - // ================================================================ - // | Block methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function isBlockedSender(address sender) external view override returns (bool) { - if (!s_config.enabled) { - return false; - } - return s_blockedSenders.contains(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function blockSender(address sender) external override onlyOwner { - s_allowedSenders.remove(sender); - s_blockedSenders.add(sender); - emit BlockedAccess(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function unblockSender(address sender) external override onlyOwner { - s_blockedSenders.remove(sender); - emit UnblockedAccess(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getBlockedSendersCount() external view override returns (uint64) { - return uint64(s_blockedSenders.length()); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getBlockedSendersInRange( - uint64 blockedSenderIdxStart, - uint64 blockedSenderIdxEnd - ) external view override returns (address[] memory blockedSenders) { - if ( - blockedSenderIdxStart > blockedSenderIdxEnd || - blockedSenderIdxEnd >= s_blockedSenders.length() || - s_blockedSenders.length() == 0 - ) { - revert InvalidCalldata(); - } - - blockedSenders = new address[]((blockedSenderIdxEnd - blockedSenderIdxStart) + 1); - for (uint256 i = 0; i <= blockedSenderIdxEnd - blockedSenderIdxStart; ++i) { - blockedSenders[i] = s_blockedSenders.at(uint256(blockedSenderIdxStart + i)); - } - - return blockedSenders; - } - - /// @inheritdoc ITermsOfServiceAllowList - function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external override onlyOwner { - if (s_previousToSContract == address(0)) { - revert NoPreviousToSContract(); - } - IAccessController previousToSContract = IAccessController(s_previousToSContract); - for (uint256 i = 0; i < previousSendersToAdd.length; ++i) { - if (previousToSContract.hasAccess(previousSendersToAdd[i], "")) { - if (!s_blockedSenders.contains(previousSendersToAdd[i])) { - s_allowedSenders.add(previousSendersToAdd[i]); - } - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol deleted file mode 100644 index 32a0ece..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -interface ITermsOfServiceAllowList { - /// @notice Return the message data for the proof given to accept the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @return Hash of the message data - function getMessage(address acceptor, address recipient) external pure returns (bytes32); - - /// @notice Check if the address is blocked for usage - /// @param sender The transaction sender's address - /// @return True or false - function isBlockedSender(address sender) external returns (bool); - - /// @notice Get a list of all allowed senders - /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - /// this function has an unbounded cost, and using it as part of a state-changing function may render the function - /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - /// @return addresses - all allowed addresses - function getAllAllowedSenders() external view returns (address[] memory); - - /// @notice Get details about the total number of allowed senders - /// @return count - total number of allowed senders in the system - function getAllowedSendersCount() external view returns (uint64); - - /// @notice Retrieve a list of allowed senders using an inclusive range - /// @dev WARNING: getAllowedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list - /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. - /// Evaluate if eventual consistency will satisfy your usecase before using it. - /// @param allowedSenderIdxStart - index of the allowed sender to start the range at - /// @param allowedSenderIdxEnd - index of the allowed sender to end the range at - /// @return allowedSenders - allowed addresses in the range provided - function getAllowedSendersInRange( - uint64 allowedSenderIdxStart, - uint64 allowedSenderIdxEnd - ) external view returns (address[] memory allowedSenders); - - /// @notice Allows access to the sender based on acceptance of the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI - /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI - /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; - - /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service - /// @param sender - Address of the sender to block - function blockSender(address sender) external; - - /// @notice Re-allows a previously blocked sender to accept the Terms of Service - /// @param sender - Address of the sender to unblock - function unblockSender(address sender) external; - - /// @notice Get details about the total number of blocked senders - /// @return count - total number of blocked senders in the system - function getBlockedSendersCount() external view returns (uint64); - - /// @notice Retrieve a list of blocked senders using an inclusive range - /// @dev WARNING: getBlockedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list - /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. - /// Evaluate if eventual consistency will satisfy your usecase before using it. - /// @param blockedSenderIdxStart - index of the blocked sender to start the range at - /// @param blockedSenderIdxEnd - index of the blocked sender to end the range at - /// @return blockedSenders - blocked addresses in the range provided - function getBlockedSendersInRange( - uint64 blockedSenderIdxStart, - uint64 blockedSenderIdxEnd - ) external view returns (address[] memory blockedSenders); - - /// @notice Enables migrating any previously allowed senders to the new contract - /// @param previousSendersToAdd - List of addresses to migrate. These address must be allowed on the previous ToS contract and not blocked - function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external; -} - -// ================================================================ -// | Configuration state | -// ================================================================ -struct TermsOfServiceAllowListConfig { - bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. - address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol deleted file mode 100644 index abb8569..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/example/FunctionsClientExample.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsClient} from "../FunctionsClient.sol"; -import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; -import {FunctionsRequest} from "../libraries/FunctionsRequest.sol"; - -/// @title Chainlink Functions example Client contract implementation -contract FunctionsClientExample is FunctionsClient, ConfirmedOwner { - using FunctionsRequest for FunctionsRequest.Request; - - uint32 public constant MAX_CALLBACK_GAS = 70_000; - - bytes32 public s_lastRequestId; - bytes32 public s_lastResponse; - bytes32 public s_lastError; - uint32 public s_lastResponseLength; - uint32 public s_lastErrorLength; - - error UnexpectedRequestID(bytes32 requestId); - - constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} - - /// @notice Send a simple request - /// @param source JavaScript source code - /// @param encryptedSecretsReferences Encrypted secrets payload - /// @param args List of arguments accessible from within the source code - /// @param subscriptionId Billing ID - function sendRequest( - string calldata source, - bytes calldata encryptedSecretsReferences, - string[] calldata args, - uint64 subscriptionId, - bytes32 jobId - ) external onlyOwner { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - if (encryptedSecretsReferences.length > 0) req._addSecretsReference(encryptedSecretsReferences); - if (args.length > 0) req._setArgs(args); - s_lastRequestId = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); - } - - /// @notice Store latest result/error - /// @param requestId The request ID, returned by sendRequest() - /// @param response Aggregated response from the user code - /// @param err Aggregated error from the user code or from the execution pipeline - /// @dev Either response or error parameter will be set, but never both - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { - if (s_lastRequestId != requestId) { - revert UnexpectedRequestID(requestId); - } - // Save only the first 32 bytes of response/error to always fit within MAX_CALLBACK_GAS - s_lastResponse = _bytesToBytes32(response); - s_lastResponseLength = uint32(response.length); - s_lastError = _bytesToBytes32(err); - s_lastErrorLength = uint32(err.length); - } - - function _bytesToBytes32(bytes memory b) private pure returns (bytes32 out) { - uint256 maxLen = 32; - if (b.length < 32) { - maxLen = b.length; - } - for (uint256 i = 0; i < maxLen; ++i) { - out |= bytes32(b[i]) >> (i * 8); - } - return out; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol deleted file mode 100644 index 0f31f7f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsBilling.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Chainlink Functions DON billing interface. -interface IFunctionsBilling { - /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed - /// @return weiPerUnitLink - The amount of WEI in one LINK - function getWeiPerUnitLink() external view returns (uint256); - - /// @notice Return the current conversion from LINK to USD from the configured Chainlink data feed - /// @return weiPerUnitLink - The amount of USD that one LINK is worth - /// @return decimals - The number of decimals that should be represented in the price feed's response - function getUsdPerUnitLink() external view returns (uint256, uint8); - - /// @notice Determine the fee that will be split between Node Operators for servicing a request - /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request - /// @return fee - Cost in Juels (1e18) of LINK - function getDONFeeJuels(bytes memory requestCBOR) external view returns (uint72); - - /// @notice Determine the fee that will be paid to the Coordinator owner for operating the network - /// @return fee - Cost in Juels (1e18) of LINK - function getOperationFeeJuels() external view returns (uint72); - - /// @notice Determine the fee that will be paid to the Router owner for operating the network - /// @return fee - Cost in Juels (1e18) of LINK - function getAdminFeeJuels() external view returns (uint72); - - /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee - /// @param - subscriptionId An identifier of the billing account - /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param - callbackGasLimit Gas limit for the fulfillment callback - /// @param - gasPriceWei The blockchain's gas price to estimate with - /// @return - billedCost Cost in Juels (1e18) of LINK - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view returns (uint96); - - /// @notice Remove a request commitment that the Router has determined to be stale - /// @param requestId - The request ID to remove - function deleteCommitment(bytes32 requestId) external; - - /// @notice Oracle withdraw LINK earned through fulfilling requests - /// @notice If amount is 0 the full balance will be withdrawn - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function oracleWithdraw(address recipient, uint96 amount) external; - - /// @notice Withdraw all LINK earned by Oracles through fulfilling requests - /// @dev transmitter addresses must support LINK tokens to avoid tokens from getting stuck as oracleWithdrawAll() calls will forward tokens directly to transmitters - function oracleWithdrawAll() external; -} - -// ================================================================ -// | Configuration state | -// ================================================================ - -struct FunctionsBillingConfig { - uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) - uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. Default of 0 means no fallback. - uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. - uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. - uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request - uint16 maxSupportedRequestDataVersion; // ║ The highest support request data version supported by the node. All lower versions should also be supported. - uint64 fallbackUsdPerUnitLink; // ║ Fallback LINK / USD conversion rate if the data feed is stale - uint8 fallbackUsdPerUnitLinkDecimals; // ════════╝ Fallback LINK / USD conversion rate decimal places if the data feed is stale - 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 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. -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol deleted file mode 100644 index f28a416..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsClient.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Chainlink Functions client interface. -interface IFunctionsClient { - /// @notice Chainlink Functions response handler called by the Functions Router - /// during fullilment from the designated transmitter node in an OCR round. - /// @param requestId The requestId returned by FunctionsClient.sendRequest(). - /// @param response Aggregated response from the request's source code. - /// @param err Aggregated error either from the request's source code or from the execution pipeline. - /// @dev Either response or error parameter will be set, but never both. - function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol deleted file mode 100644 index 4e2bd70..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsCoordinator.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions DON Coordinator interface. -interface IFunctionsCoordinator { - /// @notice Returns the DON's threshold encryption public key used to encrypt secrets - /// @dev All nodes on the DON have separate key shares of the threshold decryption key - /// and nodes must participate in a threshold decryption OCR round to decrypt secrets - /// @return thresholdPublicKey the DON's threshold encryption public key - function getThresholdPublicKey() external view returns (bytes memory); - - /// @notice Sets the DON's threshold encryption public key used to encrypt secrets - /// @dev Used to rotate the key - /// @param thresholdPublicKey The new public key - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external; - - /// @notice Returns the DON's secp256k1 public key that is used to encrypt secrets - /// @dev All nodes on the DON have the corresponding private key - /// needed to decrypt the secrets encrypted with the public key - /// @return publicKey the DON's public key - function getDONPublicKey() external view returns (bytes memory); - - /// @notice Sets DON's secp256k1 public key used to encrypt secrets - /// @dev Used to rotate the key - /// @param donPublicKey The new public key - function setDONPublicKey(bytes calldata donPublicKey) external; - - /// @notice Receives a request to be emitted to the DON for processing - /// @param request The request metadata - /// @dev see the struct for field descriptions - /// @return commitment - The parameters of the request that must be held consistent at response time - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external returns (FunctionsResponse.Commitment memory commitment); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol deleted file mode 100644 index 5f93aac..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsRouter.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions Router interface. -interface IFunctionsRouter { - /// @notice The identifier of the route to retrieve the address of the access control contract - /// The access control contract controls which accounts can manage subscriptions - /// @return id - bytes32 id that can be passed to the "getContractById" of the Router - function getAllowListId() external view returns (bytes32); - - /// @notice Set the identifier of the route to retrieve the address of the access control contract - /// The access control contract controls which accounts can manage subscriptions - function setAllowListId(bytes32 allowListId) external; - - /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network - /// @return adminFee - function getAdminFee() external view returns (uint72 adminFee); - - /// @notice Sends a request using the provided subscriptionId - /// @param subscriptionId - A unique subscription ID allocated by billing system, - /// a client can make requests from different contracts referencing the same subscription - /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param dataVersion - Gas limit for the fulfillment callback - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @param donId - An identifier used to determine which route to send the request along - /// @return requestId - A unique request identifier - function sendRequest( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external returns (bytes32); - - /// @notice Sends a request to the proposed contracts - /// @param subscriptionId - A unique subscription ID allocated by billing system, - /// a client can make requests from different contracts referencing the same subscription - /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param dataVersion - Gas limit for the fulfillment callback - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @param donId - An identifier used to determine which route to send the request along - /// @return requestId - A unique request identifier - function sendRequestToProposed( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external returns (bytes32); - - /// @notice Fulfill the request by: - /// - calling back the data that the Oracle returned to the client contract - /// - pay the DON for processing the request - /// @dev Only callable by the Coordinator contract that is saved in the commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @param juelsPerGas - current rate of juels/gas - /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment - /// @param transmitter - The Node that transmitted the OCR report - /// @param commitment - The parameters of the request that must be held consistent between request and response time - /// @return fulfillResult - - /// @return callbackGasCostJuels - - function fulfill( - bytes memory response, - bytes memory err, - uint96 juelsPerGas, - uint96 costWithoutFulfillment, - address transmitter, - FunctionsResponse.Commitment memory commitment - ) external returns (FunctionsResponse.FulfillResult, uint96); - - /// @notice Validate requested gas limit is below the subscription max. - /// @param subscriptionId subscription ID - /// @param callbackGasLimit desired callback gas limit - function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view; - - /// @notice Get the current contract given an ID - /// @param id A bytes32 identifier for the route - /// @return contract The current contract address - function getContractById(bytes32 id) external view returns (address); - - /// @notice Get the proposed next contract given an ID - /// @param id A bytes32 identifier for the route - /// @return contract The current or proposed contract address - function getProposedContractById(bytes32 id) external view returns (address); - - /// @notice Return the latest proprosal set - /// @return ids The identifiers of the contracts to update - /// @return to The addresses of the contracts that will be updated to - function getProposedContractSet() external view returns (bytes32[] memory, address[] memory); - - /// @notice Proposes one or more updates to the contract routes - /// @dev Only callable by owner - function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external; - - /// @notice Updates the current contract routes to the proposed contracts - /// @dev Only callable by owner - function updateContracts() external; - - /// @dev Puts the system into an emergency stopped state. - /// @dev Only callable by owner - function pause() external; - - /// @dev Takes the system out of an emergency stopped state. - /// @dev Only callable by owner - function unpause() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol deleted file mode 100644 index eafd6f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IFunctionsSubscriptions.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions Subscription interface. -interface IFunctionsSubscriptions { - struct Subscription { - uint96 balance; // ═════════╗ Common LINK balance that is controlled by the Router to be used for all consumer requests. - address owner; // ══════════╝ The owner can fund/withdraw/cancel the subscription. - uint96 blockedBalance; // ══╗ LINK balance that is reserved to pay for pending consumer requests. - address proposedOwner; // ══╝ For safely transferring sub ownership. - address[] consumers; // ════╸ Client contracts that can use the subscription - bytes32 flags; // ══════════╸ Per-subscription flags - } - - struct Consumer { - bool allowed; // ══════════════╗ Owner can fund/withdraw/cancel the sub. - uint64 initiatedRequests; // ║ The number of requests that have been started - uint64 completedRequests; // ══╝ The number of requests that have successfully completed or timed out - } - - /// @notice Get details about a subscription. - /// @param subscriptionId - the ID of the subscription - /// @return subscription - see IFunctionsSubscriptions.Subscription for more information on the structure - function getSubscription(uint64 subscriptionId) external view returns (Subscription memory); - - /// @notice Retrieve details about multiple subscriptions using an inclusive range - /// @param subscriptionIdStart - the ID of the subscription to start the range at - /// @param subscriptionIdEnd - the ID of the subscription to end the range at - /// @return subscriptions - see IFunctionsSubscriptions.Subscription for more information on the structure - function getSubscriptionsInRange( - uint64 subscriptionIdStart, - uint64 subscriptionIdEnd - ) external view returns (Subscription[] memory); - - /// @notice Get details about a consumer of a subscription. - /// @param client - the consumer contract address - /// @param subscriptionId - the ID of the subscription - /// @return consumer - see IFunctionsSubscriptions.Consumer for more information on the structure - function getConsumer(address client, uint64 subscriptionId) external view returns (Consumer memory); - - /// @notice Get details about the total amount of LINK within the system - /// @return totalBalance - total Juels of LINK held by the contract - function getTotalBalance() external view returns (uint96); - - /// @notice Get details about the total number of subscription accounts - /// @return count - total number of subscriptions in the system - function getSubscriptionCount() external view returns (uint64); - - /// @notice Time out all expired requests: unlocks funds and removes the ability for the request to be fulfilled - /// @param requestsToTimeoutByCommitment - A list of request commitments to time out - /// @dev The commitment can be found on the "OracleRequest" event created when sending the request. - function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external; - - /// @notice Oracle withdraw LINK earned through fulfilling requests - /// @notice If amount is 0 the full balance will be withdrawn - /// @notice Both signing and transmitting wallets will have a balance to withdraw - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function oracleWithdraw(address recipient, uint96 amount) external; - - /// @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - /// @dev Only callable by the Router Owner - /// @param subscriptionId subscription id - /// @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - function ownerCancelSubscription(uint64 subscriptionId) external; - - /// @notice Recover link sent with transfer instead of transferAndCall. - /// @dev Only callable by the Router Owner - /// @param to address to send link to - function recoverFunds(address to) external; - - /// @notice Create a new subscription. - /// @return subscriptionId - A unique subscription id. - /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function createSubscription() external returns (uint64); - - /// @notice Create a new subscription and add a consumer. - /// @return subscriptionId - A unique subscription id. - /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function createSubscriptionWithConsumer(address consumer) external returns (uint64 subscriptionId); - - /// @notice Propose a new owner for a subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param newOwner - proposed new owner of the subscription - function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external; - - /// @notice Accept an ownership transfer. - /// @param subscriptionId - ID of the subscription - /// @dev will revert if original owner of subscriptionId has not requested that msg.sender become the new owner. - function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external; - - /// @notice Remove a consumer from a Chainlink Functions subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param consumer - Consumer to remove from the subscription - function removeConsumer(uint64 subscriptionId, address consumer) external; - - /// @notice Add a consumer to a Chainlink Functions subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param consumer - New consumer which can use the subscription - function addConsumer(uint64 subscriptionId, address consumer) external; - - /// @notice Cancel a subscription - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param to - Where to send the remaining LINK to - function cancelSubscription(uint64 subscriptionId, address to) external; - - /// @notice Check to see if there exists a request commitment for all consumers for a given sub. - /// @param subscriptionId - ID of the subscription - /// @return true if there exists at least one unfulfilled request for the subscription, false otherwise. - /// @dev Looping is bounded to MAX_CONSUMERS*(number of DONs). - /// @dev Used to disable subscription canceling while outstanding request are present. - function pendingRequestExists(uint64 subscriptionId) external view returns (bool); - - /// @notice Set subscription specific flags for a subscription. - /// Each byte of the flag is used to represent a resource tier that the subscription can utilize. - /// @param subscriptionId - ID of the subscription - /// @param flags - desired flag values - function setFlags(uint64 subscriptionId, bytes32 flags) external; - - /// @notice Get flags for a given subscription. - /// @param subscriptionId - ID of the subscription - /// @return flags - current flag values - function getFlags(uint64 subscriptionId) external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol deleted file mode 100644 index f6d7880..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/interfaces/IOwnableFunctionsRouter.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsRouter} from "./IFunctionsRouter.sol"; -import {IOwnable} from "../../../../shared/interfaces/IOwnable.sol"; - -/// @title Chainlink Functions Router interface with Ownability. -interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol deleted file mode 100644 index d4c4b5f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/ChainSpecificUtil.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: MIT -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.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; - uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; - - // ------------ End Arbitrum Constants ------------ - - // ------------ Start Optimism Constants ------------ - /// @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; - uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; - - /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. - uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; - uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; - uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; - - // ------------ End Optimism Constants ------------ - - /// @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)) { - // 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 GAS_PRICE_ORACLE.getL1FeeUpperBound(calldataSizeBytes); - } - return 0; - } - - /// @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. - function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == ARB_MAINNET_CHAIN_ID || - chainId == ARB_GOERLI_TESTNET_CHAIN_ID || - chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; - } - - /// @notice Return true if and only if the provided chain ID is an Optimism (or Base) chain ID. - /// @notice Note that optimism chain id's are also OP stack chain id's. - function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == OP_MAINNET_CHAIN_ID || - chainId == OP_GOERLI_CHAIN_ID || - chainId == OP_SEPOLIA_CHAIN_ID || - chainId == BASE_MAINNET_CHAIN_ID || - chainId == BASE_GOERLI_CHAIN_ID || - chainId == BASE_SEPOLIA_CHAIN_ID; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol deleted file mode 100644 index 4e3134d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsRequest.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {CBOR} from "../../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol"; - -/// @title Library for encoding the input data of a Functions request into CBOR -library FunctionsRequest { - using CBOR for CBOR.CBORBuffer; - - uint16 public constant REQUEST_DATA_VERSION = 1; - uint256 internal constant DEFAULT_BUFFER_SIZE = 256; - - enum Location { - Inline, // Provided within the Request - Remote, // Hosted through remote location that can be accessed through a provided URL - DONHosted // Hosted on the DON's storage - } - - enum CodeLanguage { - JavaScript - // In future version we may add other languages - } - - struct Request { - Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON - Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported - CodeLanguage language; // ════════════╸ The coding language that the source code is written in - string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted - bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) - string[] args; // ════════════════════╸ String arguments that will be passed into the source code - bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code - } - - error EmptySource(); - error EmptySecrets(); - error EmptyArgs(); - error NoInlineSecrets(); - - /// @notice Encodes a Request to CBOR encoded bytes - /// @param self The request to encode - /// @return CBOR encoded bytes - function _encodeCBOR(Request memory self) internal pure returns (bytes memory) { - CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); - - buffer.writeString("codeLocation"); - buffer.writeUInt256(uint256(self.codeLocation)); - - buffer.writeString("language"); - buffer.writeUInt256(uint256(self.language)); - - buffer.writeString("source"); - buffer.writeString(self.source); - - if (self.args.length > 0) { - buffer.writeString("args"); - buffer.startArray(); - for (uint256 i = 0; i < self.args.length; ++i) { - buffer.writeString(self.args[i]); - } - buffer.endSequence(); - } - - if (self.encryptedSecretsReference.length > 0) { - if (self.secretsLocation == Location.Inline) { - revert NoInlineSecrets(); - } - buffer.writeString("secretsLocation"); - buffer.writeUInt256(uint256(self.secretsLocation)); - buffer.writeString("secrets"); - buffer.writeBytes(self.encryptedSecretsReference); - } - - if (self.bytesArgs.length > 0) { - buffer.writeString("bytesArgs"); - buffer.startArray(); - for (uint256 i = 0; i < self.bytesArgs.length; ++i) { - buffer.writeBytes(self.bytesArgs[i]); - } - buffer.endSequence(); - } - - return buffer.buf.buf; - } - - /// @notice Initializes a Chainlink Functions Request - /// @dev Sets the codeLocation and code on the request - /// @param self The uninitialized request - /// @param codeLocation The user provided source code location - /// @param language The programming language of the user code - /// @param source The user provided source code or a url - function _initializeRequest( - Request memory self, - Location codeLocation, - CodeLanguage language, - string memory source - ) internal pure { - if (bytes(source).length == 0) revert EmptySource(); - - self.codeLocation = codeLocation; - self.language = language; - self.source = source; - } - - /// @notice Initializes a Chainlink Functions Request - /// @dev Simplified version of initializeRequest for PoC - /// @param self The uninitialized request - /// @param javaScriptSource The user provided JS code (must not be empty) - function _initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure { - _initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource); - } - - /// @notice Adds Remote user encrypted secrets to a Request - /// @param self The initialized request - /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets - function _addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure { - if (encryptedSecretsReference.length == 0) revert EmptySecrets(); - - self.secretsLocation = Location.Remote; - self.encryptedSecretsReference = encryptedSecretsReference; - } - - /// @notice Adds DON-hosted secrets reference to a Request - /// @param self The initialized request - /// @param slotID Slot ID of the user's secrets hosted on DON - /// @param version User data version (for the slotID) - function _addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure { - CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); - - buffer.writeString("slotID"); - buffer.writeUInt64(slotID); - buffer.writeString("version"); - buffer.writeUInt64(version); - - self.secretsLocation = Location.DONHosted; - self.encryptedSecretsReference = buffer.buf.buf; - } - - /// @notice Sets args for the user run function - /// @param self The initialized request - /// @param args The array of string args (must not be empty) - function _setArgs(Request memory self, string[] memory args) internal pure { - if (args.length == 0) revert EmptyArgs(); - - self.args = args; - } - - /// @notice Sets bytes args for the user run function - /// @param self The initialized request - /// @param args The array of bytes args (must not be empty) - function _setBytesArgs(Request memory self, bytes[] memory args) internal pure { - if (args.length == 0) revert EmptyArgs(); - - self.bytesArgs = args; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol deleted file mode 100644 index 65fad66..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/libraries/FunctionsResponse.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Library of types that are used for fulfillment of a Functions request -library FunctionsResponse { - // Used to send request information from the Router to the Coordinator - struct RequestMeta { - bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request - bytes32 flags; // ═══════════════╸ Per-subscription flags - address requestingContract; // ══╗ The client contract that is sending the request - uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests. - uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network - uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request - uint64 initiatedRequests; // ║ The number of requests that have been started - uint32 callbackGasLimit; // ║ The amount of gas that the callback to the consuming contract will be given - uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data - uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out - address subscriptionOwner; // ═══╝ The owner of the billing subscription - } - - enum FulfillResult { - FULFILLED, // 0 - USER_CALLBACK_ERROR, // 1 - INVALID_REQUEST_ID, // 2 - COST_EXCEEDS_COMMITMENT, // 3 - INSUFFICIENT_GAS_PROVIDED, // 4 - SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5 - INVALID_COMMITMENT // 6 - } - - struct Commitment { - bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request - address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request - uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request - address client; // ════════════════════╗ The client contract that sent the request - uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request - uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given - uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network - uint72 donFee; // ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request - uint40 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. - uint40 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. - uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol deleted file mode 100644 index ac040ad..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/mocks/FunctionsV1EventsMock.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.19; - -contract FunctionsV1EventsMock { - // solhint-disable-next-line gas-struct-packing - struct Config { - uint16 maxConsumersPerSubscription; - uint72 adminFee; - bytes4 handleOracleFulfillmentSelector; - uint16 gasForCallExactCheck; - uint32[] maxCallbackGasLimits; - } - - event ConfigUpdated(Config param1); - event ContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ); - event ContractUpdated(bytes32 id, address from, address to); - event FundsRecovered(address to, uint256 amount); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event RequestNotProcessed(bytes32 indexed requestId, address coordinator, address transmitter, uint8 resultCode); - event RequestProcessed( - bytes32 indexed requestId, - uint64 indexed subscriptionId, - uint96 totalCostJuels, - address transmitter, - uint8 resultCode, - bytes response, - bytes err, - bytes callbackReturnData - ); - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - event RequestTimedOut(bytes32 indexed requestId); - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); - event Unpaused(address account); - - function emitConfigUpdated(Config memory param1) public { - emit ConfigUpdated(param1); - } - - function emitContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ) public { - emit ContractProposed(proposedContractSetId, proposedContractSetFromAddress, proposedContractSetToAddress); - } - - function emitContractUpdated(bytes32 id, address from, address to) public { - emit ContractUpdated(id, from, to); - } - - function emitFundsRecovered(address to, uint256 amount) public { - emit FundsRecovered(to, amount); - } - - function emitOwnershipTransferRequested(address from, address to) public { - emit OwnershipTransferRequested(from, to); - } - - function emitOwnershipTransferred(address from, address to) public { - emit OwnershipTransferred(from, to); - } - - function emitPaused(address account) public { - emit Paused(account); - } - - function emitRequestNotProcessed( - bytes32 requestId, - address coordinator, - address transmitter, - uint8 resultCode - ) public { - emit RequestNotProcessed(requestId, coordinator, transmitter, resultCode); - } - - function emitRequestProcessed( - bytes32 requestId, - uint64 subscriptionId, - uint96 totalCostJuels, - address transmitter, - uint8 resultCode, - bytes memory response, - bytes memory err, - bytes memory callbackReturnData - ) public { - emit RequestProcessed( - requestId, - subscriptionId, - totalCostJuels, - transmitter, - resultCode, - response, - err, - callbackReturnData - ); - } - - function emitRequestStart( - bytes32 requestId, - bytes32 donId, - uint64 subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes memory data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ) public { - emit RequestStart( - requestId, - donId, - subscriptionId, - subscriptionOwner, - requestingContract, - requestInitiator, - data, - dataVersion, - callbackGasLimit, - estimatedTotalCostJuels - ); - } - - function emitRequestTimedOut(bytes32 requestId) public { - emit RequestTimedOut(requestId); - } - - function emitSubscriptionCanceled(uint64 subscriptionId, address fundsRecipient, uint256 fundsAmount) public { - emit SubscriptionCanceled(subscriptionId, fundsRecipient, fundsAmount); - } - - function emitSubscriptionConsumerAdded(uint64 subscriptionId, address consumer) public { - emit SubscriptionConsumerAdded(subscriptionId, consumer); - } - - function emitSubscriptionConsumerRemoved(uint64 subscriptionId, address consumer) public { - emit SubscriptionConsumerRemoved(subscriptionId, consumer); - } - - function emitSubscriptionCreated(uint64 subscriptionId, address owner) public { - emit SubscriptionCreated(subscriptionId, owner); - } - - function emitSubscriptionFunded(uint64 subscriptionId, uint256 oldBalance, uint256 newBalance) public { - emit SubscriptionFunded(subscriptionId, oldBalance, newBalance); - } - - function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId, address from, address to) public { - emit SubscriptionOwnerTransferRequested(subscriptionId, from, to); - } - - function emitSubscriptionOwnerTransferred(uint64 subscriptionId, address from, address to) public { - emit SubscriptionOwnerTransferred(subscriptionId, from, to); - } - - function emitUnpaused(address account) public { - emit Unpaused(account); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol deleted file mode 100644 index 77cc950..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /** - * @notice triggers a new run of the offchain reporting protocol - * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - * @param configDigest configDigest of this configuration - * @param configCount ordinal number of this config setting among all config settings over the life of this contract - * @param signers ith element is address ith oracle uses to sign a report - * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param transmitters addresses oracles use to transmit the reports - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - /** - * @notice optionally emited to indicate the latest configDigest and epoch for - which a report was successfully transmited. Alternatively, the contract may - use latestConfigDigestAndEpoch with scanLogs set to false. - */ - event Transmitted(bytes32 configDigest, uint32 epoch); - - /** - * @notice optionally returns the latest configDigest and epoch for which a - report was successfully transmitted. Alternatively, the contract may return - scanLogs set to true and use Transmitted events to provide this information - to offchain watchers. - * @return scanLogs indicates whether to rely on the configDigest and epoch - returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol deleted file mode 100644 index 28fa670..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/dev/v1_X/ocr/OCR2Base.sol +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/** - * @notice Onchain verification of reports from the offchain reporting protocol - * @dev For details on its operation, see the offchain reporting protocol design - * doc, which refers to this contract as simply the "contract". - */ -abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { - error ReportInvalid(string message); - error InvalidConfig(string message); - - constructor() ConfirmedOwner(msg.sender) {} - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems - // to extract config from logs. - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them into two SLOADs. If any further fields are - // added, make sure that storage of the struct still takes at most 64 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // ───╮ - uint8 n; // ───╯ - } - ConfigInfo internal s_configInfo; - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - mapping(address signerOrTransmitter => Oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - struct DecodedReport { - bytes32[] requestIds; - bytes[] results; - bytes[] errors; - bytes[] onchainMetadata; - bytes[] offchainMetadata; - } - - /* - * Config logic - */ - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - // solhint-disable-next-line gas-struct-packing - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param _signers addresses with which oracles sign the reports - * @param _transmitters addresses oracles use to transmit the reports - * @param _f number of faulty oracles the system can tolerate - * @param _onchainConfig encoded on-chain contract configuration - * @param _offchainConfigVersion version number for offchainEncoding schema - * @param _offchainConfig encoded off-chain oracle configuration - */ - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < args.signers.length; i++) { - if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); - if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); - // add new signer/transmitter addresses - if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - - function _configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32(prefix | (h & ~prefixMask)); - } - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /** - * @return list of addresses permitted to transmit reports to this contract - * @dev The list will match the order used to specify the transmitter during setConfig - */ - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /** - * @dev hook called after the report has been fully validated - * for the extending contract to handle additional logic, such as oracle payment - * @param decodedReport decodedReport - */ - function _report(DecodedReport memory decodedReport) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function _requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); - } - - function _beforeTransmit( - bytes calldata report - ) internal virtual returns (bool shouldStop, DecodedReport memory decodedReport); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - (bool shouldStop, DecodedReport memory decodedReport) = _beforeTransmit(report); - - if (shouldStop) { - return; - } - - { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest - // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router - // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - _requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; - - if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); - if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); - - Oracle memory transmitter = s_oracles[msg.sender]; - if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) - revert ReportInvalid("unauthorized transmitter"); - } - - address[MAX_NUM_ORACLES] memory signed; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); - if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); - signed[o.index] = signer; - } - } - - _report(decodedReport); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/interfaces/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol deleted file mode 100644 index ffa684e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/BaseTest.t.sol +++ /dev/null @@ -1,25 +0,0 @@ -pragma solidity ^0.8.19; - -import {Test} from "forge-std/Test.sol"; - -contract BaseTest is Test { - bool private s_baseTestInitialized; - - uint256 internal OWNER_PRIVATE_KEY = 0x1; - address internal OWNER_ADDRESS = vm.addr(OWNER_PRIVATE_KEY); - - uint256 internal STRANGER_PRIVATE_KEY = 0x2; - address internal STRANGER_ADDRESS = vm.addr(STRANGER_PRIVATE_KEY); - - uint256 TX_GASPRICE_START = 3000000000; // 3 gwei - - uint72 constant JUELS_PER_LINK = 1e18; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - // Set msg.sender and tx.origin to OWNER until stopPrank is called - vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol deleted file mode 100644 index d57d511..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/ChainSpecificUtil.t.sol +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol"; -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; - -import {FunctionsFulfillmentSetup} from "./Setup.t.sol"; - -import {ArbGasInfo} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {GasPriceOracle} from "../../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; - -/// @notice #_getL1FeeUpperLimit Arbitrum -/// @dev Arbitrum gas formula = L2 Gas Price * (Gas used on L2 + Extra Buffer for L1 cost) -/// @dev where Extra Buffer for L1 cost = (L1 Estimated Cost / L2 Gas Price) -contract ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum is FunctionsFulfillmentSetup { - address private constant ARBGAS_ADDR = address(0x000000000000000000000000000000000000006C); - uint256 private constant WEI_PER_L1_CALLDATA_BYTE = 2_243_708_528; - - uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = 6_408_031_555_968; - uint256 private constant L1_FEE_WEI = 3_697_631_654_144; - - uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); - uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); - - function setUp() public virtual override { - uint256 unused = 0; - vm.mockCall( - ARBGAS_ADDR, - abi.encodeWithSelector(ArbGasInfo.getPricesInWei.selector), - abi.encode(unused, WEI_PER_L1_CALLDATA_BYTE, unused, unused, unused, unused) - ); - } - - function test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() public { - // Set the chainID - vm.chainId(42161); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Arbitrum mainnet" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum mainnet"); - } - - function test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() public { - // Set the chainID - vm.chainId(421613); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Arbitrum Goerli" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum Goerli"); - } - - function test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() public { - // Set the chainID - vm.chainId(421614); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Arbitrum Sepolia" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Arbitrum Sepolia"); - } -} - -/// @notice #_getL1FeeUpperLimit Optimism -/// @dev Optimism gas formula: https://docs.optimism.io/stack/transactions/fees#ecotone -/// @dev Note that the docs fail to mention the calculation also requires a division by 10^6 -/// @dev See here: https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/exec-engine.md#ecotone-l1-cost-fee-changes-eip-4844-da -/// @dev Also, we conservatively assume all non-zero bytes: tx_compressed_size = tx_data_size_bytes -contract ChainSpecificUtil__getL1FeeUpperLimit_Optimism is FunctionsFulfillmentSetup { - address private constant GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F); - GasPriceOracle private constant GAS_PRICE_ORACLE = GasPriceOracle(GAS_PRICE_ORACLE_ADDR); - - uint256 private constant L1_FEE_WEI = 1_648_118_885_618; - uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = (L1_FEE_WEI * (10_000 + 5_000)) / 10_000; - - uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); - uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); - - function setUp() public virtual override { - vm.mockCall( - GAS_PRICE_ORACLE_ADDR, - abi.encodeWithSelector(GAS_PRICE_ORACLE.getL1FeeUpperBound.selector), - abi.encode(L1_FEE_WEI) - ); - } - - function test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() public { - // Set the chainID - vm.chainId(10); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Optimism mainnet" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism mainnet"); - } - - function test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() public { - // Set the chainID - vm.chainId(420); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Optimism Goerli" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism Goerli"); - } - - function test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() public { - // Set the chainID - vm.chainId(11155420); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Optimism Sepolia" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Optimism Sepolia"); - } -} - -/// @notice #_getL1FeeUpperLimit Base -/// @dev Base gas formula uses Optimism formula since it is build on the OP chain stack (See comments above for Optimism tests) -contract ChainSpecificUtil__getL1FeeUpperLimit_Base is FunctionsFulfillmentSetup { - address private constant GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F); - GasPriceOracle private constant GAS_PRICE_ORACLE = GasPriceOracle(GAS_PRICE_ORACLE_ADDR); - - uint256 private constant L1_FEE_WEI = 1_648_118_885_618; - uint256 private constant L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI = (L1_FEE_WEI * (10_000 + 5_000)) / 10_000; - - uint96 l1FeeEstimateJuels = uint96((1e18 * L1_FEE_ESTIMATE_WITH_OVERESTIMATION_WEI) / uint256(LINK_ETH_RATE)); - uint96 l1FeeJuels = uint96((1e18 * L1_FEE_WEI) / uint256(LINK_ETH_RATE)); - - function setUp() public virtual override { - vm.mockCall( - GAS_PRICE_ORACLE_ADDR, - abi.encodeWithSelector(GAS_PRICE_ORACLE.getL1FeeUpperBound.selector), - abi.encode(L1_FEE_WEI) - ); - } - - function test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() public { - // Set the chainID - vm.chainId(8453); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Base mainnet" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base mainnet"); - } - - function test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() public { - // Set the chainID - vm.chainId(84531); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Base Goerli" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base Goerli"); - } - - function test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() public { - // Set the chainID - vm.chainId(84532); - - // Setup sends and fulfills request #1 - FunctionsFulfillmentSetup.setUp(); - - // Check request cost estimate - uint96 expectedEstimatedTotalCostJuels = _getExpectedCostEstimate(s_requests[1].requestData.callbackGasLimit) + - l1FeeEstimateJuels; - assertEq( - s_requests[1].commitment.estimatedTotalCostJuels, - expectedEstimatedTotalCostJuels, - "Estimated cost mismatch for Base Sepolia" - ); - - // Check response actual cost - uint96 expectedTotalCostJuels = _getExpectedCost(5416) + l1FeeJuels; - assertEq(s_responses[1].totalCostJuels, expectedTotalCostJuels, "Response cost mismatch for Base Sepolia"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol deleted file mode 100644 index b66c1e4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsBilling.t.sol +++ /dev/null @@ -1,520 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; -import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {Routable} from "../../dev/v1_X/Routable.sol"; - -import {FunctionsRouterSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup, FunctionsMultipleFulfillmentsSetup} from "./Setup.t.sol"; - -import {FunctionsBillingConfig} from "../../dev/v1_X/interfaces/IFunctionsBilling.sol"; - -/// @notice #constructor -contract FunctionsBilling_Constructor is FunctionsSubscriptionSetup { - function test_Constructor_Success() public { - assertEq(address(s_functionsRouter), s_functionsCoordinator.getRouter_HARNESS()); - assertEq(address(s_linkEthFeed), s_functionsCoordinator.getLinkToNativeFeed_HARNESS()); - } -} - -/// @notice #getConfig -contract FunctionsBilling_GetConfig is FunctionsRouterSetup { - function test_GetConfig_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - FunctionsBillingConfig memory config = s_functionsCoordinator.getConfig(); - assertEq(config.feedStalenessSeconds, getCoordinatorConfig().feedStalenessSeconds); - assertEq(config.gasOverheadBeforeCallback, getCoordinatorConfig().gasOverheadBeforeCallback); - assertEq(config.gasOverheadAfterCallback, getCoordinatorConfig().gasOverheadAfterCallback); - assertEq(config.requestTimeoutSeconds, getCoordinatorConfig().requestTimeoutSeconds); - assertEq(config.donFeeCentsUsd, getCoordinatorConfig().donFeeCentsUsd); - assertEq(config.maxSupportedRequestDataVersion, getCoordinatorConfig().maxSupportedRequestDataVersion); - assertEq(config.fulfillmentGasPriceOverEstimationBP, getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP); - assertEq(config.fallbackNativePerUnitLink, getCoordinatorConfig().fallbackNativePerUnitLink); - } -} - -/// @notice #updateConfig -contract FunctionsBilling_UpdateConfig is FunctionsRouterSetup { - FunctionsBillingConfig internal configToSet; - - function setUp() public virtual override { - FunctionsRouterSetup.setUp(); - - // Multiply all config values by 2 to confirm that they change - configToSet = FunctionsBillingConfig({ - feedStalenessSeconds: getCoordinatorConfig().feedStalenessSeconds * 2, - gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback * 2, - gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback * 2, - requestTimeoutSeconds: getCoordinatorConfig().requestTimeoutSeconds * 2, - donFeeCentsUsd: getCoordinatorConfig().donFeeCentsUsd * 2, - operationFeeCentsUsd: getCoordinatorConfig().operationFeeCentsUsd * 2, - maxSupportedRequestDataVersion: getCoordinatorConfig().maxSupportedRequestDataVersion * 2, - fulfillmentGasPriceOverEstimationBP: getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP * 2, - fallbackNativePerUnitLink: getCoordinatorConfig().fallbackNativePerUnitLink * 2, - fallbackUsdPerUnitLink: getCoordinatorConfig().fallbackUsdPerUnitLink * 2, - fallbackUsdPerUnitLinkDecimals: getCoordinatorConfig().fallbackUsdPerUnitLinkDecimals * 2, - minimumEstimateGasPriceWei: getCoordinatorConfig().minimumEstimateGasPriceWei * 2, - transmitTxSizeBytes: getCoordinatorConfig().transmitTxSizeBytes * 2 - }); - } - - function test_UpdateConfig_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsCoordinator.updateConfig(configToSet); - } - - event ConfigUpdated(FunctionsBillingConfig config); - - function test_UpdateConfig_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ConfigUpdated(configToSet); - - s_functionsCoordinator.updateConfig(configToSet); - - FunctionsBillingConfig memory config = s_functionsCoordinator.getConfig(); - assertEq(config.feedStalenessSeconds, configToSet.feedStalenessSeconds); - assertEq(config.gasOverheadAfterCallback, configToSet.gasOverheadAfterCallback); - assertEq(config.gasOverheadBeforeCallback, configToSet.gasOverheadBeforeCallback); - assertEq(config.requestTimeoutSeconds, configToSet.requestTimeoutSeconds); - assertEq(config.donFeeCentsUsd, configToSet.donFeeCentsUsd); - assertEq(config.operationFeeCentsUsd, configToSet.operationFeeCentsUsd); - assertEq(config.maxSupportedRequestDataVersion, configToSet.maxSupportedRequestDataVersion); - assertEq(config.fulfillmentGasPriceOverEstimationBP, configToSet.fulfillmentGasPriceOverEstimationBP); - assertEq(config.fallbackNativePerUnitLink, configToSet.fallbackNativePerUnitLink); - assertEq(config.minimumEstimateGasPriceWei, configToSet.minimumEstimateGasPriceWei); - assertEq(config.fallbackUsdPerUnitLink, configToSet.fallbackUsdPerUnitLink); - assertEq(config.fallbackUsdPerUnitLinkDecimals, configToSet.fallbackUsdPerUnitLinkDecimals); - } -} - -/// @notice #getDONFee -contract FunctionsBilling_GetDONFeeJuels is FunctionsRouterSetup { - function test_GetDONFeeJuels_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint72 donFee = s_functionsCoordinator.getDONFeeJuels(new bytes(0)); - uint72 expectedDonFee = uint72(((s_donFee * 10 ** (18 + LINK_USD_DECIMALS)) / uint256(LINK_USD_RATE)) / 100); - assertEq(donFee, expectedDonFee); - } -} - -/// @notice #getOperationFee -contract FunctionsBilling_GetOperationFee is FunctionsRouterSetup { - function test_GetOperationFeeJuels_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint72 operationFee = s_functionsCoordinator.getOperationFeeJuels(); - uint72 expectedOperationFee = uint72( - ((s_operationFee * 10 ** (18 + LINK_USD_DECIMALS)) / uint256(LINK_USD_RATE)) / 100 - ); - assertEq(operationFee, expectedOperationFee); - } -} - -/// @notice #getAdminFee -contract FunctionsBilling_GetAdminFeeJuels is FunctionsRouterSetup { - function test_GetAdminFeeJuels_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint72 adminFee = s_functionsCoordinator.getAdminFeeJuels(); - assertEq(adminFee, s_adminFee); - } -} - -/// @notice #getWeiPerUnitLink -contract FunctionsBilling_GetWeiPerUnitLink is FunctionsRouterSetup { - function test_GetWeiPerUnitLink_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint256 weiPerUnitLink = s_functionsCoordinator.getWeiPerUnitLink(); - assertEq(weiPerUnitLink, uint256(LINK_ETH_RATE)); - } -} - -/// @notice #estimateCost -contract FunctionsBilling_EstimateCost is FunctionsSubscriptionSetup { - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Get cost estimate as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - } - - uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei - - function test_EstimateCost_RevertsIfGasPriceAboveCeiling() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5_500; - uint256 gasPriceWei = REASONABLE_GAS_PRICE_CEILING + 1; - - vm.expectRevert(FunctionsBilling.InvalidCalldata.selector); - - s_functionsCoordinator.estimateCost(s_subscriptionId, requestData, callbackGasLimit, gasPriceWei); - } - - function test_EstimateCost_SuccessLowGasPrice() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5_500; - uint256 gasPriceWei = 1; - - uint96 costEstimate = s_functionsCoordinator.estimateCost( - s_subscriptionId, - requestData, - callbackGasLimit, - gasPriceWei - ); - uint96 expectedCostEstimate = 51110500000000000 + - s_adminFee + - s_functionsCoordinator.getDONFeeJuels(requestData) + - s_functionsCoordinator.getOperationFeeJuels(); - assertEq(costEstimate, expectedCostEstimate); - } - - function test_EstimateCost_Success() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5_500; - uint256 gasPriceWei = 5000000000; // 5 gwei - - uint96 costEstimate = s_functionsCoordinator.estimateCost( - s_subscriptionId, - requestData, - callbackGasLimit, - gasPriceWei - ); - uint96 expectedCostEstimate = 255552500000000000 + - s_adminFee + - s_functionsCoordinator.getDONFeeJuels(requestData) + - s_functionsCoordinator.getOperationFeeJuels(); - assertEq(costEstimate, expectedCostEstimate); - } -} - -/// @notice #_calculateCostEstimate -contract FunctionsBilling__CalculateCostEstimate { - // TODO: make contract internal function helper -} - -/// @notice #_startBilling -contract FunctionsBilling__StartBilling is FunctionsFulfillmentSetup { - function test__FulfillAndBill_HasUniqueGlobalRequestId() public { - // Variables that go into a requestId: - // - Coordinator address - // - Consumer contract - // - Subscription ID, - // - Consumer initiated requests - // - Request data - // - Request data version - // - Request callback gas limit - // - Estimated total cost in Juels - // - Request timeout timestamp - // - tx.origin - - // Request #1 has already been fulfilled by the test setup - - // Reset the nonce (initiatedRequests) by removing and re-adding the consumer - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers.length, 0); - s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); - assertEq(s_functionsRouter.getSubscription(s_subscriptionId).consumers[0], address(s_functionsClient)); - - // Make Request #2 - _sendAndStoreRequest( - 2, - s_requests[1].requestData.sourceCode, - s_requests[1].requestData.secrets, - s_requests[1].requestData.args, - s_requests[1].requestData.bytesArgs, - s_requests[1].requestData.callbackGasLimit - ); - - // Request #1 and #2 should have different request IDs, because the request timeout timestamp has advanced. - // A request cannot be fulfilled in the same block, which prevents removing a consumer in the same block - assertNotEq(s_requests[1].requestId, s_requests[2].requestId); - } -} - -/// @notice #_fulfillAndBill -contract FunctionsBilling__FulfillAndBill is FunctionsClientRequestSetup { - function test__FulfillAndBill_RevertIfInvalidCommitment() public { - vm.expectRevert(); - s_functionsCoordinator.fulfillAndBill_HARNESS( - s_requests[1].requestId, - new bytes(0), - new bytes(0), - new bytes(0), // malformed commitment data - new bytes(0), - 1 - ); - } - - event RequestBilled( - bytes32 indexed requestId, - uint96 juelsPerGas, - uint256 l1FeeShareWei, - uint96 callbackCostJuels, - uint72 donFee, - uint72 adminFee, - uint72 operationFee - ); - - function test__FulfillAndBill_Success() public { - uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE)); - uint96 callbackCostGas = 5072; // Taken manually - uint96 callbackCostJuels = juelsPerGas * callbackCostGas; - - // topic0 (function signature, always checked), check topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit RequestBilled( - s_requests[1].requestId, - juelsPerGas, - 0, - callbackCostJuels, - s_functionsCoordinator.getDONFeeJuels(new bytes(0)), - s_adminFee, - s_functionsCoordinator.getOperationFeeJuels() - ); - - FunctionsResponse.FulfillResult resultCode = s_functionsCoordinator.fulfillAndBill_HARNESS( - s_requests[1].requestId, - new bytes(0), - new bytes(0), - abi.encode(s_requests[1].commitment), - new bytes(0), - 1 - ); - - assertEq(uint256(resultCode), uint256(FunctionsResponse.FulfillResult.FULFILLED)); - } -} - -/// @notice #deleteCommitment -contract FunctionsBilling_DeleteCommitment is FunctionsClientRequestSetup { - function test_DeleteCommitment_RevertIfNotRouter() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(Routable.OnlyCallableByRouter.selector); - s_functionsCoordinator.deleteCommitment(s_requests[1].requestId); - } - - event CommitmentDeleted(bytes32 requestId); - - function test_DeleteCommitment_Success() public { - // Send as Router - vm.stopPrank(); - vm.startPrank(address(s_functionsRouter)); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit CommitmentDeleted(s_requests[1].requestId); - - s_functionsCoordinator.deleteCommitment(s_requests[1].requestId); - } -} - -/// @notice #oracleWithdraw -contract FunctionsBilling_OracleWithdraw is FunctionsMultipleFulfillmentsSetup { - function test_OracleWithdraw_RevertWithNoBalance() public { - uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); - _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); - - // Send as stranger, which has no balance - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - - // Attempt to withdraw with no amount, which would withdraw the full balance - s_functionsCoordinator.oracleWithdraw(STRANGER_ADDRESS, 0); - - uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); - _assertTransmittersAllHaveBalance(transmitterBalancesAfter, 0); - } - - function test_OracleWithdraw_RevertIfInsufficientBalance() public { - // Send as transmitter 1, which has transmitted 1 report - vm.stopPrank(); - vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); - - vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); - - // Attempt to withdraw more than the Coordinator has assigned - s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, s_fulfillmentCoordinatorBalance + 1); - } - - function test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() public { - uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); - _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); - - // Send as transmitter 1, which has transmitted 1 report - vm.stopPrank(); - vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); - - uint96 expectedTransmitterBalance = s_fulfillmentCoordinatorBalance / s_requestsFulfilled; - - // Attempt to withdraw half of balance - uint96 halfBalance = expectedTransmitterBalance / 2; - s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, halfBalance); - - uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); - assertEq(transmitterBalancesAfter[0], halfBalance); - assertEq(transmitterBalancesAfter[1], 0); - assertEq(transmitterBalancesAfter[2], 0); - assertEq(transmitterBalancesAfter[3], 0); - } - - function test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() public { - uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); - _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); - - // Send as transmitter 1, which has transmitted 2 reports - vm.stopPrank(); - vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); - - // Attempt to withdraw with no amount, which will withdraw the full balance - s_functionsCoordinator.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, 0); - - uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; - uint96 totalDonFees = s_functionsCoordinator.getDONFeeJuels(new bytes(0)) * s_requestsFulfilled; - uint96 donFeeShare = totalDonFees / uint8(s_transmitters.length); - uint96 expectedBalancePerFulfillment = ((s_fulfillmentCoordinatorBalance - totalOperationFees - totalDonFees) / - s_requestsFulfilled); - - uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); - // Transmitter 1 has transmitted twice - assertEq(transmitterBalancesAfter[0], (expectedBalancePerFulfillment * 2) + donFeeShare); - assertEq(transmitterBalancesAfter[1], 0); - assertEq(transmitterBalancesAfter[2], 0); - assertEq(transmitterBalancesAfter[3], 0); - } - - function test_OracleWithdraw_SuccessCoordinatorOwner() public { - // Send as Coordinator Owner - address coordinatorOwner = s_functionsCoordinator.owner(); - vm.stopPrank(); - vm.startPrank(coordinatorOwner); - - uint256 coordinatorOwnerBalanceBefore = s_linkToken.balanceOf(coordinatorOwner); - - // Attempt to withdraw with no amount, which will withdraw the full balance - s_functionsCoordinator.oracleWithdraw(coordinatorOwner, 0); - - // 4 report transmissions have been made - uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; - - uint256 coordinatorOwnerBalanceAfter = s_linkToken.balanceOf(coordinatorOwner); - assertEq(coordinatorOwnerBalanceBefore + totalOperationFees, coordinatorOwnerBalanceAfter); - } -} - -/// @notice #oracleWithdrawAll -contract FunctionsBilling_OracleWithdrawAll is FunctionsMultipleFulfillmentsSetup { - function setUp() public virtual override { - FunctionsMultipleFulfillmentsSetup.setUp(); - } - - function test_OracleWithdrawAll_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsCoordinator.oracleWithdrawAll(); - } - - function test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() public { - uint256[4] memory transmitterBalancesBefore = _getTransmitterBalances(); - _assertTransmittersAllHaveBalance(transmitterBalancesBefore, 0); - - s_functionsCoordinator.oracleWithdrawAll(); - - uint96 totalOperationFees = s_functionsCoordinator.getOperationFeeJuels() * s_requestsFulfilled; - uint96 totalDonFees = s_functionsCoordinator.getDONFeeJuels(new bytes(0)) * s_requestsFulfilled; - uint96 donFeeShare = totalDonFees / uint8(s_transmitters.length); - uint96 expectedBalancePerFulfillment = ((s_fulfillmentCoordinatorBalance - totalOperationFees - totalDonFees) / - s_requestsFulfilled); - - uint256[4] memory transmitterBalancesAfter = _getTransmitterBalances(); - // Transmitter 1 has transmitted twice - assertEq(transmitterBalancesAfter[0], (expectedBalancePerFulfillment * 2) + donFeeShare); - // Transmitter 2 and 3 have transmitted once - assertEq(transmitterBalancesAfter[1], expectedBalancePerFulfillment + donFeeShare); - assertEq(transmitterBalancesAfter[2], expectedBalancePerFulfillment + donFeeShare); - // Transmitter 4 only not transmitted, it only has its share of the DON fees - assertEq(transmitterBalancesAfter[3], donFeeShare); - } -} - -/// @notice #_disperseFeePool -contract FunctionsBilling__DisperseFeePool is FunctionsRouterSetup { - function test__DisperseFeePool_RevertIfNotSet() public { - // Manually set s_feePool (at slot 12) to 1 to get past first check in _disperseFeePool - vm.store(address(s_functionsCoordinator), bytes32(uint256(12)), bytes32(uint256(1))); - - vm.expectRevert(FunctionsBilling.NoTransmittersSet.selector); - s_functionsCoordinator.disperseFeePool_HARNESS(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol deleted file mode 100644 index 3638276..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsClient.t.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsClient} from "../../dev/v1_X/FunctionsClient.sol"; -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; - -import {FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; - -/// @notice #constructor -contract FunctionsClient_Constructor is FunctionsClientSetup { - function test_Constructor_Success() public { - assertEq(address(s_functionsRouter), s_functionsClient.getRouter_HARNESS()); - } -} - -/// @notice #_sendRequest -contract FunctionsClient__SendRequest is FunctionsSubscriptionSetup { - function test__SendRequest_RevertIfInvalidCallbackGasLimit() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); - uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; - uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); - s_functionsClient.sendRequestBytes(requestData, s_subscriptionId, 500_000, s_donId); - } -} - -/// @notice #handleOracleFulfillment -contract FunctionsClient_HandleOracleFulfillment is FunctionsClientRequestSetup { - function test_HandleOracleFulfillment_RevertIfNotRouter() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsClient.OnlyRouterCanFulfill.selector); - s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0)); - } - - event RequestFulfilled(bytes32 indexed id); - event ResponseReceived(bytes32 indexed requestId, bytes result, bytes err); - - function test_HandleOracleFulfillment_Success() public { - // Send as Router - vm.stopPrank(); - vm.startPrank(address(s_functionsRouter)); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ResponseReceived(s_requests[1].requestId, new bytes(0), new bytes(0)); - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit RequestFulfilled(s_requests[1].requestId); - - s_functionsClient.handleOracleFulfillment(s_requests[1].requestId, new bytes(0), new bytes(0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol deleted file mode 100644 index 03d9f64..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsCoordinator.t.sol +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; -import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {Routable} from "../../dev/v1_X/Routable.sol"; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsRouterSetup, FunctionsDONSetup, FunctionsSubscriptionSetup} from "./Setup.t.sol"; - -/// @notice #constructor -contract FunctionsCoordinator_Constructor is FunctionsRouterSetup { - function test_Constructor_Success() public { - assertEq(s_functionsCoordinator.typeAndVersion(), "Functions Coordinator v1.3.1"); - assertEq(s_functionsCoordinator.owner(), OWNER_ADDRESS); - } -} - -/// @notice #getThresholdPublicKey -contract FunctionsCoordinator_GetThresholdPublicKey is FunctionsDONSetup { - function test_GetThresholdPublicKey_RevertIfEmpty() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Reverts when empty - vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector); - s_functionsCoordinator.getThresholdPublicKey(); - } - - function test_GetThresholdPublicKey_Success() public { - s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey(); - assertEq(thresholdKey, s_thresholdKey); - } -} - -/// @notice #setThresholdPublicKey -contract FunctionsCoordinator_SetThresholdPublicKey is FunctionsDONSetup { - function test_SetThresholdPublicKey_RevertNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - bytes memory newThresholdKey = new bytes(0); - s_functionsCoordinator.setThresholdPublicKey(newThresholdKey); - } - - function test_SetThresholdPublicKey_Success() public { - s_functionsCoordinator.setThresholdPublicKey(s_thresholdKey); - - bytes memory thresholdKey = s_functionsCoordinator.getThresholdPublicKey(); - - assertEq(thresholdKey, s_thresholdKey); - } -} - -/// @notice #getDONPublicKey -contract FunctionsCoordinator_GetDONPublicKey is FunctionsDONSetup { - function test_GetDONPublicKey_RevertIfEmpty() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Reverts when empty - vm.expectRevert(FunctionsCoordinator.EmptyPublicKey.selector); - s_functionsCoordinator.getDONPublicKey(); - } - - function test_GetDONPublicKey_Success() public { - s_functionsCoordinator.setDONPublicKey(s_donKey); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes memory donKey = s_functionsCoordinator.getDONPublicKey(); - assertEq(donKey, s_donKey); - } -} - -/// @notice #setDONPublicKey -contract FunctionsCoordinator_SetDONPublicKey is FunctionsDONSetup { - function test_SetDONPublicKey_RevertNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsCoordinator.setDONPublicKey(s_donKey); - } - - function test_SetDONPublicKey_Success() public { - s_functionsCoordinator.setDONPublicKey(s_donKey); - - bytes memory donKey = s_functionsCoordinator.getDONPublicKey(); - assertEq(donKey, s_donKey); - } -} - -/// @notice #_isTransmitter -contract FunctionsCoordinator__IsTransmitter is FunctionsDONSetup { - function test__IsTransmitter_SuccessFound() public { - bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(NOP_TRANSMITTER_ADDRESS_1); - assertEq(isTransmitter, true); - } - - function test__IsTransmitter_SuccessNotFound() public { - bool isTransmitter = s_functionsCoordinator.isTransmitter_HARNESS(STRANGER_ADDRESS); - assertEq(isTransmitter, false); - } -} - -/// @notice #startRequest -contract FunctionsCoordinator_StartRequest is FunctionsSubscriptionSetup { - function test_StartRequest_RevertIfNotRouter() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(Routable.OnlyCallableByRouter.selector); - - s_functionsCoordinator.startRequest( - FunctionsResponse.RequestMeta({ - requestingContract: address(s_functionsClient), - data: new bytes(0), - subscriptionId: s_subscriptionId, - dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, - flags: bytes32(0), - callbackGasLimit: 5_500, - adminFee: s_adminFee, - initiatedRequests: 0, - completedRequests: 0, - availableBalance: s_subscriptionInitialFunding, - subscriptionOwner: OWNER_ADDRESS - }) - ); - } - - event OracleRequest( - bytes32 indexed requestId, - address indexed requestingContract, - address requestInitiator, - uint64 subscriptionId, - address subscriptionOwner, - bytes data, - uint16 dataVersion, - bytes32 flags, - uint64 callbackGasLimit, - FunctionsResponse.Commitment commitment - ); - - function test_StartRequest_Success() public { - // Send as Router - vm.stopPrank(); - vm.startPrank(address(s_functionsRouter)); - (, , address txOrigin) = vm.readCallers(); - - bytes memory _requestData = new bytes(0); - uint32 _callbackGasLimit = 5_500; - uint96 costEstimate = s_functionsCoordinator.estimateCost( - s_subscriptionId, - _requestData, - _callbackGasLimit, - tx.gasprice - ); - uint32 timeoutTimestamp = uint32(block.timestamp + getCoordinatorConfig().requestTimeoutSeconds); - bytes32 expectedRequestId = keccak256( - abi.encode( - address(s_functionsCoordinator), - address(s_functionsClient), - s_subscriptionId, - 1, - keccak256(_requestData), - FunctionsRequest.REQUEST_DATA_VERSION, - _callbackGasLimit, - costEstimate, - timeoutTimestamp, - txOrigin - ) - ); - - // WARNING: Kludge in place. Remove in contracts v2.0.0 - FunctionsResponse.Commitment memory expectedComittment = FunctionsResponse.Commitment({ - adminFee: s_functionsCoordinator.getOperationFeeJuels(), - coordinator: address(s_functionsCoordinator), - client: address(s_functionsClient), - subscriptionId: s_subscriptionId, - callbackGasLimit: _callbackGasLimit, - estimatedTotalCostJuels: costEstimate, - timeoutTimestamp: timeoutTimestamp, - requestId: expectedRequestId, - donFee: s_functionsCoordinator.getDONFeeJuels(_requestData), - gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback, - gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback - }); - - // topic0 (function signature, always checked), topic1 (true), topic2 (true), NOT topic3 (false), and data (true). - vm.expectEmit(true, true, false, true); - emit OracleRequest({ - requestId: expectedRequestId, - requestingContract: address(s_functionsClient), - requestInitiator: txOrigin, - subscriptionId: s_subscriptionId, - subscriptionOwner: OWNER_ADDRESS, - data: _requestData, - dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, - flags: bytes32(0), - callbackGasLimit: _callbackGasLimit, - commitment: expectedComittment - }); - - s_functionsCoordinator.startRequest( - FunctionsResponse.RequestMeta({ - requestingContract: address(s_functionsClient), - data: _requestData, - subscriptionId: s_subscriptionId, - dataVersion: FunctionsRequest.REQUEST_DATA_VERSION, - flags: bytes32(0), - callbackGasLimit: 5_500, - adminFee: s_adminFee, - initiatedRequests: 0, - completedRequests: 0, - availableBalance: s_subscriptionInitialFunding, - subscriptionOwner: OWNER_ADDRESS - }) - ); - } -} - -/// @notice #_beforeSetConfig -contract FunctionsCoordinator__BeforeSetConfig { - // TODO: make contract internal function helper -} - -/// @notice #_getTransmitters -contract FunctionsCoordinator__GetTransmitters { - // TODO: make contract internal function helper -} - -/// @notice #_report -contract FunctionsCoordinator__Report { - // TODO: make contract internal function helper -} - -/// @notice #_onlyOwner -contract FunctionsCoordinator__OnlyOwner { - // TODO: make contract internal function helper -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol deleted file mode 100644 index e9684d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRequest.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; - -import {Test} from "forge-std/Test.sol"; - -/// @notice #REQUEST_DATA_VERSION -contract FunctionsRequest_REQUEST_DATA_VERSION is Test { - function test_REQUEST_DATA_VERSION() public { - // Exposes REQUEST_DATA_VERSION - assertEq(FunctionsRequest.REQUEST_DATA_VERSION, 1); - } -} - -/// @notice #DEFAULT_BUFFER_SIZE -contract FunctionsRequest_DEFAULT_BUFFER_SIZE is Test { - function test_DEFAULT_BUFFER_SIZE() public { - // Exposes DEFAULT_BUFFER_SIZE - assertEq(FunctionsRequest.DEFAULT_BUFFER_SIZE, 256); - } -} - -/// @notice #encodeCBOR -contract FunctionsRequest_EncodeCBOR is Test { - function test_EncodeCBOR_Success() public { - // Exposes DEFAULT_BUFFER_SIZE - assertEq(FunctionsRequest.DEFAULT_BUFFER_SIZE, 256); - } -} - -/// @notice #initializeRequest -contract FunctionsRequest_InitializeRequest is Test {} - -/// @notice #initializeRequestForInlineJavaScript -contract FunctionsRequest_InitializeRequestForInlineJavaScript is Test {} - -/// @notice #addSecretsReference -contract FunctionsRequest_AddSecretsReference is Test {} - -/// @notice #addDONHostedSecrets -contract FunctionsRequest_AddDONHostedSecrets is Test {} - -/// @notice #setArgs -contract FunctionsRequest_SetArgs is Test {} - -/// @notice #setBytesArgs -contract FunctionsRequest_SetBytesArgs is Test {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol deleted file mode 100644 index 62db3e4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsRouter.t.sol +++ /dev/null @@ -1,1603 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {FunctionsCoordinator} from "../../dev/v1_X/FunctionsCoordinator.sol"; -import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {FunctionsCoordinatorTestHelper} from "./testhelpers/FunctionsCoordinatorTestHelper.sol"; -import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; - -import {FunctionsRouterSetup, FunctionsRoutesSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; - -import "forge-std/Vm.sol"; - -// ================================================================ -// | Functions Router | -// ================================================================ - -/// @notice #constructor -contract FunctionsRouter_Constructor is FunctionsRouterSetup { - function test_Constructor_Success() public { - assertEq(s_functionsRouter.typeAndVersion(), "Functions Router v2.0.0"); - assertEq(s_functionsRouter.owner(), OWNER_ADDRESS); - } -} - -/// @notice #getConfig -contract FunctionsRouter_GetConfig is FunctionsRouterSetup { - function test_GetConfig_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - assertEq(config.maxConsumersPerSubscription, getRouterConfig().maxConsumersPerSubscription); - assertEq(config.adminFee, getRouterConfig().adminFee); - assertEq(config.handleOracleFulfillmentSelector, getRouterConfig().handleOracleFulfillmentSelector); - assertEq(config.maxCallbackGasLimits[0], getRouterConfig().maxCallbackGasLimits[0]); - assertEq(config.maxCallbackGasLimits[1], getRouterConfig().maxCallbackGasLimits[1]); - assertEq(config.maxCallbackGasLimits[2], getRouterConfig().maxCallbackGasLimits[2]); - assertEq(config.gasForCallExactCheck, getRouterConfig().gasForCallExactCheck); - assertEq(config.subscriptionDepositMinimumRequests, getRouterConfig().subscriptionDepositMinimumRequests); - assertEq(config.subscriptionDepositJuels, getRouterConfig().subscriptionDepositJuels); - } -} - -/// @notice #updateConfig -contract FunctionsRouter_UpdateConfig is FunctionsRouterSetup { - FunctionsRouter.Config internal configToSet; - - function setUp() public virtual override { - FunctionsRouterSetup.setUp(); - - uint32[] memory maxCallbackGasLimits = new uint32[](4); - maxCallbackGasLimits[0] = 300_000; - maxCallbackGasLimits[1] = 500_000; - maxCallbackGasLimits[2] = 1_000_000; - maxCallbackGasLimits[3] = 3_000_000; - - configToSet = FunctionsRouter.Config({ - maxConsumersPerSubscription: s_maxConsumersPerSubscription, - adminFee: s_adminFee, - handleOracleFulfillmentSelector: s_handleOracleFulfillmentSelector, - maxCallbackGasLimits: maxCallbackGasLimits, - gasForCallExactCheck: 5000, - subscriptionDepositMinimumRequests: 10, - subscriptionDepositJuels: 5 * 1e18 - }); - } - - function test_UpdateConfig_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.updateConfig(configToSet); - } - - event ConfigUpdated(FunctionsRouter.Config config); - - function test_UpdateConfig_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ConfigUpdated(configToSet); - - s_functionsRouter.updateConfig(configToSet); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - assertEq(config.maxConsumersPerSubscription, configToSet.maxConsumersPerSubscription); - assertEq(config.adminFee, configToSet.adminFee); - assertEq(config.handleOracleFulfillmentSelector, configToSet.handleOracleFulfillmentSelector); - assertEq(config.maxCallbackGasLimits[0], configToSet.maxCallbackGasLimits[0]); - assertEq(config.maxCallbackGasLimits[1], configToSet.maxCallbackGasLimits[1]); - assertEq(config.maxCallbackGasLimits[2], configToSet.maxCallbackGasLimits[2]); - assertEq(config.maxCallbackGasLimits[3], configToSet.maxCallbackGasLimits[3]); - assertEq(config.gasForCallExactCheck, configToSet.gasForCallExactCheck); - } -} - -/// @notice #isValidCallbackGasLimit -contract FunctionsRouter_IsValidCallbackGasLimit is FunctionsSubscriptionSetup { - function test_IsValidCallbackGasLimit_RevertInvalidConfig() public { - // Set an invalid maxCallbackGasLimit flag - bytes32 flagsToSet = 0x5a00000000000000000000000000000000000000000000000000000000000000; - s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.InvalidGasFlagValue.selector, 90)); - s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, 0); - } - - function test_IsValidCallbackGasLimit_RevertGasLimitTooBig() public { - uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); - uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; - uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); - s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, maxCallbackGasLimit + 1); - } - - function test_IsValidCallbackGasLimit_Success() public view { - uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); - uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; - uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - - s_functionsRouter.isValidCallbackGasLimit(s_subscriptionId, maxCallbackGasLimit); - } -} - -/// @notice #getAdminFee -contract FunctionsRouter_GetAdminFee is FunctionsRouterSetup { - function test_GetAdminFee_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint72 adminFee = s_functionsRouter.getAdminFee(); - assertEq(adminFee, getRouterConfig().adminFee); - } -} - -/// @notice #getAllowListId -contract FunctionsRouter_GetAllowListId is FunctionsRouterSetup { - function test_GetAllowListId_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 defaultAllowListId = bytes32(0); - - bytes32 allowListId = s_functionsRouter.getAllowListId(); - assertEq(allowListId, defaultAllowListId); - } -} - -/// @notice #setAllowListId -contract FunctionsRouter_SetAllowListId is FunctionsRouterSetup { - function test_UpdateConfig_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 routeIdToSet = bytes32("allowList"); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.setAllowListId(routeIdToSet); - } - - function test_SetAllowListId_Success() public { - bytes32 routeIdToSet = bytes32("allowList"); - s_functionsRouter.setAllowListId(routeIdToSet); - bytes32 allowListId = s_functionsRouter.getAllowListId(); - assertEq(allowListId, routeIdToSet); - } -} - -/// @notice #_getMaxConsumers -contract FunctionsRouter__GetMaxConsumers is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #sendRequest -contract FunctionsRouter_SendRequest is FunctionsSubscriptionSetup { - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Add sending wallet as a subscription consumer - s_functionsRouter.addConsumer(s_subscriptionId, OWNER_ADDRESS); - } - - function test_SendRequest_RevertIfInvalidDonId() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - bytes32 invalidDonId = bytes32("this does not exist"); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidDonId)); - s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - invalidDonId - ); - } - - function test_SendRequest_RevertIfIncorrectDonId() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - bytes32 incorrectDonId = s_functionsRouter.getAllowListId(); - - // Low level revert from incorrect call - vm.expectRevert(); - s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - incorrectDonId - ); - } - - function test_SendRequest_RevertIfPaused() public { - s_functionsRouter.pause(); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.sendRequest(s_subscriptionId, requestData, FunctionsRequest.REQUEST_DATA_VERSION, 5000, s_donId); - } - - function test_SendRequest_RevertIfNoSubscription() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint64 invalidSubscriptionId = 123456789; - - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.sendRequest( - invalidSubscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5000, - s_donId - ); - } - - function test_SendRequest_RevertIfConsumerNotAllowed() public { - // Remove sending wallet as a subscription consumer - s_functionsRouter.removeConsumer(s_subscriptionId, OWNER_ADDRESS); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); - s_functionsRouter.sendRequest(s_subscriptionId, requestData, FunctionsRequest.REQUEST_DATA_VERSION, 5000, s_donId); - } - - function test_SendRequest_RevertIfInvalidCallbackGasLimit() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); - uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; - uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); - s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 500_000, - s_donId - ); - } - - function test_SendRequest_RevertIfEmptyData() public { - // Build invalid request data - bytes memory emptyRequestData = new bytes(0); - - vm.expectRevert(FunctionsRouter.EmptyRequestData.selector); - s_functionsRouter.sendRequest( - s_subscriptionId, - emptyRequestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - s_donId - ); - } - - function test_SendRequest_RevertIfInsufficientSubscriptionBalance() public { - // Create new subscription that does not have any funding - uint64 subscriptionId = s_functionsRouter.createSubscription(); - s_functionsRouter.addConsumer(subscriptionId, address(OWNER_ADDRESS)); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5000; - vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); - - s_functionsRouter.sendRequest( - subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - } - - function test_SendRequest_RevertIfDuplicateRequestId() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - uint32 callbackGasLimit = 5_000; - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - // Send a first request that will remain pending - bytes32 requestId = s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - - // Mock the Coordinator to always give back the first requestId - FunctionsResponse.Commitment memory mockCommitment = FunctionsResponse.Commitment({ - adminFee: s_adminFee, - coordinator: address(s_functionsCoordinator), - client: OWNER_ADDRESS, - subscriptionId: s_subscriptionId, - callbackGasLimit: callbackGasLimit, - estimatedTotalCostJuels: 0, - timeoutTimestamp: uint32(block.timestamp + getCoordinatorConfig().requestTimeoutSeconds), - requestId: requestId, - donFee: s_donFee, - gasOverheadBeforeCallback: getCoordinatorConfig().gasOverheadBeforeCallback, - gasOverheadAfterCallback: getCoordinatorConfig().gasOverheadAfterCallback - }); - - vm.mockCall( - address(s_functionsCoordinator), - abi.encodeWithSelector(FunctionsCoordinator.startRequest.selector), - abi.encode(mockCommitment) - ); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.DuplicateRequestId.selector, requestId)); - s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - } - - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - - function test_SendRequest_Success() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5000; - - uint96 costEstimate = s_functionsCoordinator.estimateCost( - s_subscriptionId, - requestData, - callbackGasLimit, - tx.gasprice - ); - - vm.recordLogs(); - - bytes32 requestIdFromReturn = s_functionsRouter.sendRequest( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - - // Get requestId from RequestStart event log topic 1 - Vm.Log[] memory entries = vm.getRecordedLogs(); - bytes32 requestIdFromEvent = entries[1].topics[1]; - bytes32 donIdFromEvent = entries[1].topics[2]; - bytes32 subscriptionIdFromEvent = entries[1].topics[3]; - - bytes memory expectedRequestData = abi.encode( - OWNER_ADDRESS, - OWNER_ADDRESS, - OWNER_ADDRESS, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - costEstimate - ); - - assertEq(requestIdFromReturn, requestIdFromEvent); - assertEq(donIdFromEvent, s_donId); - assertEq(subscriptionIdFromEvent, bytes32(uint256(s_subscriptionId))); - assertEq(expectedRequestData, entries[1].data); - } -} - -/// @notice #sendRequestToProposed -contract FunctionsRouter_SendRequestToProposed is FunctionsSubscriptionSetup { - FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper - - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Add sending wallet as a subscription consumer - s_functionsRouter.addConsumer(s_subscriptionId, OWNER_ADDRESS); - - // Deploy new Coordinator contract - s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - - // Propose new Coordinator contract - bytes32[] memory proposedContractSetIds = new bytes32[](1); - proposedContractSetIds[0] = s_donId; - address[] memory proposedContractSetAddresses = new address[](1); - proposedContractSetAddresses[0] = address(s_functionsCoordinator2); - - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - function test_SendRequestToProposed_RevertIfInvalidDonId() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - bytes32 invalidDonId = bytes32("this does not exist"); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidDonId)); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - invalidDonId - ); - } - - function test_SendRequestToProposed_RevertIfIncorrectDonId() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - bytes32 incorrectDonId = s_functionsRouter.getAllowListId(); - - // Low level revert from incorrect call - vm.expectRevert(); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - incorrectDonId - ); - } - - function test_SendRequestToProposed_RevertIfPaused() public { - s_functionsRouter.pause(); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5000, - s_donId - ); - } - - function test_SendRequestToProposed_RevertIfNoSubscription() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint64 invalidSubscriptionId = 123456789; - - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.sendRequestToProposed( - invalidSubscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5000, - s_donId - ); - } - - function test_SendRequestToProposed_RevertIfConsumerNotAllowed() public { - // Remove sending wallet as a subscription consumer - s_functionsRouter.removeConsumer(s_subscriptionId, OWNER_ADDRESS); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5000, - s_donId - ); - } - - function test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint8 MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - bytes32 subscriptionFlags = s_functionsRouter.getFlags(s_subscriptionId); - uint8 callbackGasLimitsIndexSelector = uint8(subscriptionFlags[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - - FunctionsRouter.Config memory config = s_functionsRouter.getConfig(); - uint32[] memory _maxCallbackGasLimits = config.maxCallbackGasLimits; - uint32 maxCallbackGasLimit = _maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.GasLimitTooBig.selector, maxCallbackGasLimit)); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 500_000, - s_donId - ); - } - - function test_SendRequestToProposed_RevertIfEmptyData() public { - // Build invalid request data - bytes memory emptyRequestData = new bytes(0); - - vm.expectRevert(FunctionsRouter.EmptyRequestData.selector); - s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - emptyRequestData, - FunctionsRequest.REQUEST_DATA_VERSION, - 5_000, - s_donId - ); - } - - function test_SendRequest_RevertIfInsufficientSubscriptionBalance() public { - // Create new subscription that does not have any funding - uint64 subscriptionId = s_functionsRouter.createSubscription(); - s_functionsRouter.addConsumer(subscriptionId, address(OWNER_ADDRESS)); - - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5000; - vm.expectRevert(FunctionsBilling.InsufficientBalance.selector); - - s_functionsRouter.sendRequestToProposed( - subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - } - - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - - function test_SendRequestToProposed_Success() public { - // Build minimal valid request data - string memory sourceCode = "return 'hello world';"; - FunctionsRequest.Request memory request; - FunctionsRequest._initializeRequest( - request, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - sourceCode - ); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - - uint32 callbackGasLimit = 5000; - - uint96 costEstimate = s_functionsCoordinator2.estimateCost( - s_subscriptionId, - requestData, - callbackGasLimit, - tx.gasprice - ); - - vm.recordLogs(); - - bytes32 requestIdFromReturn = s_functionsRouter.sendRequestToProposed( - s_subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - s_donId - ); - - // Get requestId from RequestStart event log topic 1 - Vm.Log[] memory entries = vm.getRecordedLogs(); - bytes32 requestIdFromEvent = entries[1].topics[1]; - bytes32 donIdFromEvent = entries[1].topics[2]; - bytes32 subscriptionIdFromEvent = entries[1].topics[3]; - - bytes memory expectedRequestData = abi.encode( - OWNER_ADDRESS, - OWNER_ADDRESS, - OWNER_ADDRESS, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - costEstimate - ); - - assertEq(requestIdFromReturn, requestIdFromEvent); - assertEq(donIdFromEvent, s_donId); - assertEq(subscriptionIdFromEvent, bytes32(uint256(s_subscriptionId))); - assertEq(expectedRequestData, entries[1].data); - } -} - -/// @notice #_sendRequest -contract FunctionsRouter__SendRequest is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #fulfill -contract FunctionsRouter_Fulfill is FunctionsClientRequestSetup { - function test_Fulfill_RevertIfPaused() public { - s_functionsRouter.pause(); - - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - vm.expectRevert("Pausable: paused"); - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); - } - - function test_Fulfill_RevertIfNotCommittedCoordinator() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes memory response = bytes("hello world!"); - bytes memory err = new bytes(0); - uint96 juelsPerGas = 0; - uint96 costWithoutCallback = 0; - address transmitter = NOP_TRANSMITTER_ADDRESS_1; - FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; - - vm.expectRevert(FunctionsRouter.OnlyCallableFromCoordinator.selector); - s_functionsRouter.fulfill(response, err, juelsPerGas, costWithoutCallback, transmitter, commitment); - } - - event RequestNotProcessed( - bytes32 indexed requestId, - address coordinator, - address transmitter, - FunctionsResponse.FulfillResult resultCode - ); - - function test_Fulfill_RequestNotProcessedInvalidRequestId() public { - // Send as committed Coordinator - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - bytes memory response = bytes("hello world!"); - bytes memory err = new bytes(0); - uint96 juelsPerGas = 0; - uint96 costWithoutCallback = 0; - address transmitter = NOP_TRANSMITTER_ADDRESS_1; - FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; - // Modify request commitment to have a invalid requestId - bytes32 invalidRequestId = bytes32("this does not exist"); - commitment.requestId = invalidRequestId; - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit RequestNotProcessed({ - requestId: s_requests[1].requestId, - coordinator: address(s_functionsCoordinator), - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.INVALID_REQUEST_ID - }); - - (FunctionsResponse.FulfillResult resultCode, uint96 callbackGasCostJuels) = s_functionsRouter.fulfill( - response, - err, - juelsPerGas, - costWithoutCallback, - transmitter, - commitment - ); - - assertEq(uint(resultCode), uint(FunctionsResponse.FulfillResult.INVALID_REQUEST_ID)); - assertEq(callbackGasCostJuels, 0); - } - - function test_Fulfill_RequestNotProcessedInvalidCommitment() public { - // Send as committed Coordinator - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - bytes memory response = bytes("hello world!"); - bytes memory err = new bytes(0); - uint96 juelsPerGas = 0; - uint96 costWithoutCallback = 0; - address transmitter = NOP_TRANSMITTER_ADDRESS_1; - FunctionsResponse.Commitment memory commitment = s_requests[1].commitment; - // Modify request commitment to have charge more than quoted - commitment.estimatedTotalCostJuels = 10 * JUELS_PER_LINK; // 10 LINK - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit RequestNotProcessed({ - requestId: s_requests[1].requestId, - coordinator: address(s_functionsCoordinator), - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.INVALID_COMMITMENT - }); - - (FunctionsResponse.FulfillResult resultCode, uint96 callbackGasCostJuels) = s_functionsRouter.fulfill( - response, - err, - juelsPerGas, - costWithoutCallback, - transmitter, - commitment - ); - - assertEq(uint(resultCode), uint(FunctionsResponse.FulfillResult.INVALID_COMMITMENT)); - assertEq(callbackGasCostJuels, 0); - } - - function test_Fulfill_RequestNotProcessedInsufficientGas() public { - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - uint32 callbackGasLimit = s_requests[requestToFulfill].requestData.callbackGasLimit; - // Coordinator sends enough gas that would get through callback and payment, but fail after - uint256 gasToUse = getCoordinatorConfig().gasOverheadBeforeCallback + callbackGasLimit + 10_000; - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); - emit RequestNotProcessed({ - requestId: s_requests[requestToFulfill].requestId, - coordinator: address(s_functionsCoordinator), - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false, 1, gasToUse); - } - - function test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() public { - // Find the storage slot that the Subscription is on - vm.record(); - s_functionsRouter.getSubscription(s_subscriptionId); - (bytes32[] memory reads, ) = vm.accesses(address(s_functionsRouter)); - // The first read is from '_isExistingSubscription' which checks Subscription.owner on slot 0 - // Slot 0 is shared with the Subscription.balance - uint256 slot = uint256(reads[0]); - - // The request has already been initiated, forcibly lower the subscription's balance by clearing out slot 0 - uint96 balance = 1; - address owner = address(0); - bytes32 data = bytes32(abi.encodePacked(balance, owner)); // TODO: make this more accurate - vm.store(address(s_functionsRouter), bytes32(uint256(slot)), data); - - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); - emit RequestNotProcessed({ - requestId: s_requests[requestToFulfill].requestId, - coordinator: address(s_functionsCoordinator), - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); - } - - function test_Fulfill_RequestNotProcessedCostExceedsCommitment() public { - // Use higher juelsPerGas than request time - // 10x the gas price - vm.txGasPrice(TX_GASPRICE_START * 10); - - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); - emit RequestNotProcessed({ - requestId: s_requests[requestToFulfill].requestId, - coordinator: address(s_functionsCoordinator), - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, false); - } - - event RequestProcessed( - bytes32 indexed requestId, - uint64 indexed subscriptionId, - uint96 totalCostJuels, - address transmitter, - FunctionsResponse.FulfillResult resultCode, - bytes response, - bytes err, - bytes callbackReturnData - ); - - FunctionsClientTestHelper internal s_clientWithFailingCallback; - - function test_Fulfill_SuccessUserCallbackReverts() public { - // Deploy Client with failing callback - s_clientWithFailingCallback = new FunctionsClientTestHelper(address(s_functionsRouter)); - s_clientWithFailingCallback.setRevertFulfillRequest(true); - - // Add Client as a subscription consumer - s_functionsRouter.addConsumer(s_subscriptionId, address(s_clientWithFailingCallback)); - - // Send a minimal request - uint256 requestKey = 99; - - string memory sourceCode = "return 'hello world';"; - uint32 callbackGasLimit = 5500; - - vm.recordLogs(); - bytes32 requestId = s_clientWithFailingCallback.sendSimpleRequestWithJavaScript( - sourceCode, - s_subscriptionId, - s_donId, - callbackGasLimit - ); - - // Get commitment data from OracleRequest event log - Vm.Log[] memory entries = vm.getRecordedLogs(); - (, , , , , , , FunctionsResponse.Commitment memory _commitment) = abi.decode( - entries[0].data, - (address, uint64, address, bytes, uint16, bytes32, uint64, FunctionsResponse.Commitment) - ); - - s_requests[requestKey] = Request({ - requestData: RequestData({ - sourceCode: sourceCode, - secrets: new bytes(0), - args: new string[](0), - bytesArgs: new bytes[](0), - callbackGasLimit: callbackGasLimit - }), - requestId: requestId, - commitment: _commitment, // This commitment contains the operationFee in place of adminFee - commitmentOnchain: FunctionsResponse.Commitment({ - coordinator: _commitment.coordinator, - client: _commitment.client, - subscriptionId: _commitment.subscriptionId, - callbackGasLimit: _commitment.callbackGasLimit, - estimatedTotalCostJuels: _commitment.estimatedTotalCostJuels, - timeoutTimestamp: _commitment.timeoutTimestamp, - requestId: _commitment.requestId, - donFee: _commitment.donFee, - gasOverheadBeforeCallback: _commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: _commitment.gasOverheadAfterCallback, - adminFee: s_adminFee - }) - }); - - // Fulfill - uint256 requestToFulfill = requestKey; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); - emit RequestProcessed({ - requestId: requestId, - subscriptionId: s_subscriptionId, - totalCostJuels: _getExpectedCost(1822), // gasUsed is manually taken - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, - response: bytes(response), - err: err, - callbackReturnData: vm.parseBytes( - "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000f61736b656420746f207265766572740000000000000000000000000000000000" - ) // TODO: build this programatically - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); - } - - function test_Fulfill_SuccessUserCallbackRunsOutOfGas() public { - // Send request #2 with no callback gas - string memory sourceCode = "return 'hello world';"; - bytes memory secrets = new bytes(0); - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - uint32 callbackGasLimit = 0; - _sendAndStoreRequest(2, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - - uint256 requestToFulfill = 2; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1: request ID(true), NOT topic2 (false), NOT topic3 (false), and data (true). - vm.expectEmit(true, false, false, true); - emit RequestProcessed({ - requestId: s_requests[requestToFulfill].requestId, - subscriptionId: s_subscriptionId, - totalCostJuels: _getExpectedCost(137), // gasUsed is manually taken - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, - response: bytes(response), - err: err, - callbackReturnData: new bytes(0) - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); - } - - function test_Fulfill_SuccessClientNoLongerExists() public { - // Delete the Client contract in the time between request and fulfillment - vm.etch(address(s_functionsClient), new bytes(0)); - - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1 (true), topic2 (true), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = true; - bool checkTopic2SubscriptionId = true; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2SubscriptionId, checkTopic3, checkData); - emit RequestProcessed({ - requestId: s_requests[requestToFulfill].requestId, - subscriptionId: s_subscriptionId, - totalCostJuels: _getExpectedCost(0), // gasUsed is manually taken - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR, - response: bytes(response), - err: err, - callbackReturnData: new bytes(0) - }); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true, 1); - } - - function test_Fulfill_SuccessFulfilled() public { - // Fulfill request 1 - uint256 requestToFulfill = 1; - - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestToFulfill; - string[] memory results = new string[](1); - string memory response = "hello world!"; - results[0] = response; - bytes[] memory errors = new bytes[](1); - bytes memory err = new bytes(0); - errors[0] = err; - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1RequestId = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1RequestId, checkTopic2, checkTopic3, checkData); - emit RequestProcessed({ - requestId: s_requests[requestToFulfill].requestId, - subscriptionId: s_subscriptionId, - totalCostJuels: _getExpectedCost(5416), // gasUsed is manually taken - transmitter: NOP_TRANSMITTER_ADDRESS_1, - resultCode: FunctionsResponse.FulfillResult.FULFILLED, - response: bytes(response), - err: err, - callbackReturnData: new bytes(0) - }); - _reportAndStore(requestNumberKeys, results, errors); - } -} - -/// @notice #_callback -contract FunctionsRouter__Callback is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #getContractById -contract FunctionsRouter_GetContractById is FunctionsRoutesSetup { - function test_GetContractById_RevertIfRouteDoesNotExist() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 invalidRouteId = bytes32("this does not exist"); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidRouteId)); - s_functionsRouter.getContractById(invalidRouteId); - } - - function test_GetContractById_SuccessIfRouteExists() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - address routeDestination = s_functionsRouter.getContractById(s_donId); - assertEq(routeDestination, address(s_functionsCoordinator)); - } -} - -/// @notice #getProposedContractById -contract FunctionsRouter_GetProposedContractById is FunctionsRoutesSetup { - FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper - - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - // Deploy new Coordinator contract - s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - - // Propose new Coordinator contract - bytes32[] memory proposedContractSetIds = new bytes32[](1); - proposedContractSetIds[0] = s_donId; - address[] memory proposedContractSetAddresses = new address[](1); - proposedContractSetAddresses[0] = address(s_functionsCoordinator2); - - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - function test_GetProposedContractById_RevertIfRouteDoesNotExist() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 invalidRouteId = bytes32("this does not exist"); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.RouteNotFound.selector, invalidRouteId)); - s_functionsRouter.getProposedContractById(invalidRouteId); - } - - function test_GetProposedContractById_SuccessIfRouteExists() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - address routeDestination = s_functionsRouter.getProposedContractById(s_donId); - assertEq(routeDestination, address(s_functionsCoordinator2)); - } -} - -/// @notice #getProposedContractSet -contract FunctionsRouter_GetProposedContractSet is FunctionsRoutesSetup { - FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper - bytes32[] s_proposedContractSetIds; - address[] s_proposedContractSetAddresses; - - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - // Deploy new Coordinator contract - s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - - // Propose new Coordinator contract - s_proposedContractSetIds = new bytes32[](1); - s_proposedContractSetIds[0] = s_donId; - s_proposedContractSetAddresses = new address[](1); - s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); - - s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); - } - - function test_GetProposedContractSet_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - (bytes32[] memory proposedContractSetIds, address[] memory proposedContractSetAddresses) = s_functionsRouter - .getProposedContractSet(); - - assertEq(proposedContractSetIds.length, 1); - assertEq(proposedContractSetIds[0], s_donId); - assertEq(proposedContractSetIds.length, 1); - assertEq(proposedContractSetAddresses[0], address(s_functionsCoordinator2)); - } -} - -/// @notice #proposeContractsUpdate -contract FunctionsRouter_ProposeContractsUpdate is FunctionsRoutesSetup { - FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper - bytes32[] s_proposedContractSetIds; - address[] s_proposedContractSetAddresses; - - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - // Deploy new Coordinator contract - s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - - // Propose new Coordinator contract - s_proposedContractSetIds = new bytes32[](1); - s_proposedContractSetIds[0] = s_donId; - s_proposedContractSetAddresses = new address[](1); - s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); - } - - function test_ProposeContractsUpdate_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); - } - - function test_ProposeContractsUpdate_RevertIfLengthMismatch() public { - bytes32[] memory proposedContractSetIds = new bytes32[](1); - proposedContractSetIds[0] = s_donId; - address[] memory proposedContractSetAddresses = new address[](1); - - vm.expectRevert(FunctionsRouter.InvalidProposal.selector); - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - function test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() public { - uint8 MAX_PROPOSAL_SET_LENGTH = 8; - uint8 INVALID_PROPOSAL_SET_LENGTH = MAX_PROPOSAL_SET_LENGTH + 1; - - // Generate some mock data - bytes32[] memory proposedContractSetIds = new bytes32[](INVALID_PROPOSAL_SET_LENGTH); - for (uint256 i = 0; i < INVALID_PROPOSAL_SET_LENGTH; ++i) { - proposedContractSetIds[i] = bytes32(uint256(i + 111)); - } - address[] memory proposedContractSetAddresses = new address[](INVALID_PROPOSAL_SET_LENGTH); - for (uint256 i = 0; i < INVALID_PROPOSAL_SET_LENGTH; ++i) { - proposedContractSetAddresses[i] = address(uint160(uint(keccak256(abi.encodePacked(i + 111))))); - } - - vm.expectRevert(FunctionsRouter.InvalidProposal.selector); - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - function test_ProposeContractsUpdate_RevertIfEmptyAddress() public { - bytes32[] memory proposedContractSetIds = new bytes32[](1); - proposedContractSetIds[0] = s_donId; - address[] memory proposedContractSetAddresses = new address[](1); - proposedContractSetAddresses[0] = address(0); - - vm.expectRevert(FunctionsRouter.InvalidProposal.selector); - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - function test_ProposeContractsUpdate_RevertIfNotNewContract() public { - bytes32[] memory proposedContractSetIds = new bytes32[](1); - proposedContractSetIds[0] = s_donId; - address[] memory proposedContractSetAddresses = new address[](1); - proposedContractSetAddresses[0] = address(s_functionsCoordinator); - - vm.expectRevert(FunctionsRouter.InvalidProposal.selector); - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - } - - event ContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ); - - function test_ProposeContractsUpdate_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ContractProposed({ - proposedContractSetId: s_proposedContractSetIds[0], - proposedContractSetFromAddress: address(s_functionsCoordinator), - proposedContractSetToAddress: s_proposedContractSetAddresses[0] - }); - - s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); - } -} - -/// @notice #updateContracts -contract FunctionsRouter_UpdateContracts is FunctionsRoutesSetup { - FunctionsCoordinatorTestHelper internal s_functionsCoordinator2; // TODO: use actual FunctionsCoordinator instead of helper - bytes32[] s_proposedContractSetIds; - address[] s_proposedContractSetAddresses; - - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - // Deploy new Coordinator contract - s_functionsCoordinator2 = new FunctionsCoordinatorTestHelper( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - - // Propose new Coordinator contract - s_proposedContractSetIds = new bytes32[](1); - s_proposedContractSetIds[0] = s_donId; - s_proposedContractSetAddresses = new address[](1); - s_proposedContractSetAddresses[0] = address(s_functionsCoordinator2); - - s_functionsRouter.proposeContractsUpdate(s_proposedContractSetIds, s_proposedContractSetAddresses); - } - - function test_UpdateContracts_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.updateContracts(); - } - - event ContractUpdated(bytes32 id, address from, address to); - - function test_UpdateContracts_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ContractUpdated({ - id: s_proposedContractSetIds[0], - from: address(s_functionsCoordinator), - to: s_proposedContractSetAddresses[0] - }); - - s_functionsRouter.updateContracts(); - - (bytes32[] memory proposedContractSetIds, address[] memory proposedContractSetAddresses) = s_functionsRouter - .getProposedContractSet(); - - assertEq(proposedContractSetIds.length, 0); - assertEq(proposedContractSetAddresses.length, 0); - } -} - -/// @notice #_whenNotPaused -contract FunctionsRouter__WhenNotPaused is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #_onlyRouterOwner -contract FunctionsRouter__OnlyRouterOwner is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #_onlySenderThatAcceptedToS -contract FunctionsRouter__OnlySenderThatAcceptedToS is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #pause -contract FunctionsRouter_Pause is FunctionsRouterSetup { - function setUp() public virtual override { - FunctionsRouterSetup.setUp(); - } - - event Paused(address account); - - function test_Pause_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.pause(); - } - - function test_Pause_Success() public { - // topic0 (always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - vm.expectEmit(false, false, false, true); - emit Paused(OWNER_ADDRESS); - - s_functionsRouter.pause(); - - bool isPaused = s_functionsRouter.paused(); - assertEq(isPaused, true); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.createSubscription(); - } -} - -/// @notice #unpause -contract FunctionsRouter_Unpause is FunctionsRouterSetup { - function setUp() public virtual override { - FunctionsRouterSetup.setUp(); - s_functionsRouter.pause(); - } - - event Unpaused(address account); - - function test_Unpause_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.unpause(); - } - - function test_Unpause_Success() public { - // topic0 (always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - vm.expectEmit(false, false, false, true); - emit Unpaused(OWNER_ADDRESS); - - s_functionsRouter.unpause(); - - bool isPaused = s_functionsRouter.paused(); - assertEq(isPaused, false); - - s_functionsRouter.createSubscription(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol deleted file mode 100644 index a6dda5a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsSubscriptions.t.sol +++ /dev/null @@ -1,1291 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -import {FunctionsRouterSetup, FunctionsOwnerAcceptTermsOfServiceSetup, FunctionsClientSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup, FunctionsFulfillmentSetup} from "./Setup.t.sol"; - -import "forge-std/Vm.sol"; - -// ================================================================ -// | Functions Subscriptions | -// ================================================================ - -contract FunctionsSubscriptions_Constructor_Helper is FunctionsSubscriptions { - constructor(address link) FunctionsSubscriptions(link) {} - - function getLinkToken() public view returns (IERC20) { - return IERC20(i_linkToken); - } - - // overrides - function _getMaxConsumers() internal pure override returns (uint16) { - return 0; - } - - function _getSubscriptionDepositDetails() internal pure override returns (uint16, uint72) { - return (0, 0); - } - - function _onlySenderThatAcceptedToS() internal override {} - - function _onlyRouterOwner() internal override {} - - function _whenNotPaused() internal override {} -} - -/// @notice #constructor -contract FunctionsSubscriptions_Constructor is BaseTest { - FunctionsSubscriptions_Constructor_Helper s_subscriptionsHelper; - address internal s_linkToken = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709; - - function setUp() public virtual override { - BaseTest.setUp(); - s_subscriptionsHelper = new FunctionsSubscriptions_Constructor_Helper(s_linkToken); - } - - function test_Constructor_Success() public { - assertEq(address(s_linkToken), address(s_subscriptionsHelper.getLinkToken())); - } -} - -/// @notice #_markRequestInFlight -contract FunctionsSubscriptions__MarkRequestInFlight { - // TODO: make contract internal function helper -} - -/// @notice #_pay -contract FunctionsSubscriptions__Pay { - // TODO: make contract internal function helper -} - -/// @notice #ownerCancelSubscription -contract FunctionsSubscriptions_OwnerCancelSubscription is FunctionsSubscriptionSetup { - function test_OwnerCancelSubscription_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.ownerCancelSubscription(s_subscriptionId); - } - - function test_OwnerCancelSubscription_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_functionsRouter.ownerCancelSubscription(invalidSubscriptionId); - } - - function test_OwnerCancelSubscription_SuccessSubOwnerRefunded() public { - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - s_functionsRouter.ownerCancelSubscription(s_subscriptionId); - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + s_subscriptionInitialFunding, subscriptionOwnerBalanceAfter); - } - - function test_OwnerCancelSubscription_SuccessWhenRequestInFlight() public { - // send request - string memory sourceCode = "return 'hello world';"; - bytes memory secrets; - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - - s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5500); - s_functionsRouter.ownerCancelSubscription(s_subscriptionId); - } - - function test_OwnerCancelSubscription_SuccessDeletesSubscription() public { - s_functionsRouter.ownerCancelSubscription(s_subscriptionId); - // Subscription should no longer exist - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.getSubscription(s_subscriptionId); - } - - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - - function test_OwnerCancelSubscription_Success() public { - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1SubscriptionId = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1SubscriptionId, checkTopic2, checkTopic3, checkData); - emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, s_subscriptionInitialFunding); - - s_functionsRouter.ownerCancelSubscription(s_subscriptionId); - - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + s_subscriptionInitialFunding, subscriptionOwnerBalanceAfter); - } -} - -/// @notice #recoverFunds -contract FunctionsSubscriptions_RecoverFunds is FunctionsRouterSetup { - event FundsRecovered(address to, uint256 amount); - - function test_RecoverFunds_Success() public { - uint256 fundsTransferred = 1 * 1e18; // 1 LINK - s_linkToken.transfer(address(s_functionsRouter), fundsTransferred); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit FundsRecovered(OWNER_ADDRESS, fundsTransferred); - - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - s_functionsRouter.recoverFunds(OWNER_ADDRESS); - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + fundsTransferred, subscriptionOwnerBalanceAfter); - } - - function test_OwnerCancelSubscription_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.recoverFunds(OWNER_ADDRESS); - } -} - -/// @notice #oracleWithdraw -contract FunctionsSubscriptions_OracleWithdraw is FunctionsFulfillmentSetup { - function test_OracleWithdraw_RevertIfPaused() public { - s_functionsRouter.pause(); - - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - vm.expectRevert("Pausable: paused"); - - uint96 amountToWithdraw = 1; // more than 0 - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - } - - function test_OracleWithdraw_RevertIfNoAmount() public { - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - - uint96 amountToWithdraw = 0; - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - } - - function test_OracleWithdraw_RevertIfAmountMoreThanBalance() public { - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - vm.expectRevert( - abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, s_fulfillmentCoordinatorBalance) - ); - - uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance + 1; - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - } - - function test_OracleWithdraw_RevertIfBalanceInvariant() public { - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - // vm.stopPrank(); - // vm.startPrank(address(s_functionsCoordinator)); - // TODO: Use internal function helper contract to modify s_totalLinkBalance - // uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; - // vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.TotalBalanceInvariantViolated.selector, 0, amountToWithdraw)); - // s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - } - - function test_OracleWithdraw_SuccessPaysRecipient() public { - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - uint256 transmitterBalanceBefore = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1); - - uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - - uint256 transmitterBalanceAfter = s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1); - assertEq(transmitterBalanceBefore + s_fulfillmentCoordinatorBalance, transmitterBalanceAfter); - } - - function test_OracleWithdraw_SuccessSetsBalanceToZero() public { - // Subscription payable balances are set to the Coordinator - // Send as Coordinator contract - vm.stopPrank(); - vm.startPrank(address(s_functionsCoordinator)); - - uint96 amountToWithdraw = s_fulfillmentCoordinatorBalance; - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, amountToWithdraw); - - // Attempt to withdraw 1 Juel after withdrawing full balance - vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, 0)); - s_functionsRouter.oracleWithdraw(NOP_TRANSMITTER_ADDRESS_1, 1); - } -} - -/// @notice #ownerWithdraw -contract FunctionsSubscriptions_OwnerWithdraw is FunctionsFulfillmentSetup { - function test_OwnerWithdraw_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_functionsRouter.recoverFunds(OWNER_ADDRESS); - } - - function test_OwnerWithdraw_RevertIfAmountMoreThanBalance() public { - vm.expectRevert( - abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, s_fulfillmentRouterOwnerBalance) - ); - - uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance + 1; - s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); - } - - function test_OwnerWithdraw_RevertIfBalanceInvariant() public { - // TODO: Use internal function helper contract to modify s_totalLinkBalance - // uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; - // vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.TotalBalanceInvariantViolated.selector, 0, amountToWithdraw)); - // s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); - } - - function test_OwnerWithdraw_SuccessIfRecipientAddressZero() public { - uint256 balanceBefore = s_linkToken.balanceOf(address(0)); - uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; - s_functionsRouter.ownerWithdraw(address(0), amountToWithdraw); - uint256 balanceAfter = s_linkToken.balanceOf(address(0)); - assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); - } - - function test_OwnerWithdraw_SuccessIfNoAmount() public { - uint256 balanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - uint96 amountToWithdraw = 0; - s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); - uint256 balanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); - } - - function test_OwnerWithdraw_SuccessPaysRecipient() public { - uint256 balanceBefore = s_linkToken.balanceOf(STRANGER_ADDRESS); - - uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; - s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, amountToWithdraw); - - uint256 balanceAfter = s_linkToken.balanceOf(STRANGER_ADDRESS); - assertEq(balanceBefore + s_fulfillmentRouterOwnerBalance, balanceAfter); - } - - function test_OwnerWithdraw_SuccessSetsBalanceToZero() public { - uint96 amountToWithdraw = s_fulfillmentRouterOwnerBalance; - s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, amountToWithdraw); - - // Attempt to withdraw 1 Juel after withdrawing full balance - vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.InsufficientBalance.selector, 0)); - s_functionsRouter.ownerWithdraw(OWNER_ADDRESS, 1); - } -} - -/// @notice #onTokenTransfer -contract FunctionsSubscriptions_OnTokenTransfer is FunctionsClientSetup { - uint64 s_subscriptionId; - - function setUp() public virtual override { - FunctionsClientSetup.setUp(); - - // Create subscription, but do not fund it - s_subscriptionId = s_functionsRouter.createSubscription(); - s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); - } - - function test_OnTokenTransfer_RevertIfPaused() public { - // Funding amount must be less than or equal to LINK total supply - uint256 totalSupplyJuels = 1_000_000_000 * 1e18; - s_functionsRouter.pause(); - vm.expectRevert("Pausable: paused"); - s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); - } - - function test_OnTokenTransfer_RevertIfCallerIsNotLink() public { - // Funding amount must be less than or equal to LINK total supply - uint256 totalSupplyJuels = 1_000_000_000 * 1e18; - vm.expectRevert(FunctionsSubscriptions.OnlyCallableFromLink.selector); - s_functionsRouter.onTokenTransfer(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); - } - - function test_OnTokenTransfer_RevertIfCallerIsNoCalldata() public { - // Funding amount must be less than or equal to LINK total supply - uint256 totalSupplyJuels = 1_000_000_000 * 1e18; - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, new bytes(0)); - } - - function test_OnTokenTransfer_RevertIfCallerIsNoSubscription() public { - // Funding amount must be less than or equal to LINK total supply - uint256 totalSupplyJuels = 1_000_000_000 * 1e18; - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(invalidSubscriptionId)); - } - - function test_OnTokenTransfer_Success() public { - // Funding amount must be less than LINK total supply - uint256 totalSupplyJuels = 1_000_000_000 * 1e18; - // Some of the total supply is already in the subscription account - s_linkToken.transferAndCall(address(s_functionsRouter), totalSupplyJuels, abi.encode(s_subscriptionId)); - uint96 subscriptionBalanceAfter = s_functionsRouter.getSubscription(s_subscriptionId).balance; - assertEq(totalSupplyJuels, subscriptionBalanceAfter); - } -} - -/// @notice #getTotalBalance -contract FunctionsSubscriptions_GetTotalBalance is FunctionsSubscriptionSetup { - function test_GetTotalBalance_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint96 totalBalance = s_functionsRouter.getTotalBalance(); - assertEq(totalBalance, s_subscriptionInitialFunding); - } -} - -/// @notice #getSubscriptionCount -contract FunctionsSubscriptions_GetSubscriptionCount is FunctionsSubscriptionSetup { - function test_GetSubscriptionCount_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint96 subscriptionCount = s_functionsRouter.getSubscriptionCount(); - // One subscription was made during setup - assertEq(subscriptionCount, 1); - } -} - -/// @notice #getSubscriptionsInRange -contract FunctionsSubscriptions_GetSubscriptionsInRange is FunctionsSubscriptionSetup { - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Create 2 more subscriptions - /* uint64 subscriptionId2 = */ s_functionsRouter.createSubscription(); - uint64 subscriptionId3 = s_functionsRouter.createSubscription(); - - // Give each one unique state - // #1 subscriptionId for requests, #2 empty, #3 proposedOwner of stranger - s_functionsRouter.proposeSubscriptionOwnerTransfer(subscriptionId3, STRANGER_ADDRESS); - } - - function test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - - s_functionsRouter.getSubscriptionsInRange(1, 0); - } - - function test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 lastSubscriptionId = s_functionsRouter.getSubscriptionCount(); - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - s_functionsRouter.getSubscriptionsInRange(1, lastSubscriptionId + 1); - } - - function test_GetSubscriptionsInRange_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 lastSubscriptionId = s_functionsRouter.getSubscriptionCount(); - FunctionsSubscriptions.Subscription[] memory subscriptions = s_functionsRouter.getSubscriptionsInRange( - s_subscriptionId, - lastSubscriptionId - ); - - assertEq(subscriptions.length, 3); - - // Check subscription 1 - assertEq(subscriptions[0].balance, s_subscriptionInitialFunding); - assertEq(subscriptions[0].owner, OWNER_ADDRESS); - assertEq(subscriptions[0].blockedBalance, 0); - assertEq(subscriptions[0].proposedOwner, address(0)); - assertEq(subscriptions[0].consumers[0], address(s_functionsClient)); - assertEq(subscriptions[0].flags, bytes32(0)); - - // Check subscription 2 - assertEq(subscriptions[1].balance, 0); - assertEq(subscriptions[1].owner, OWNER_ADDRESS); - assertEq(subscriptions[1].blockedBalance, 0); - assertEq(subscriptions[1].proposedOwner, address(0)); - assertEq(subscriptions[1].consumers.length, 0); - assertEq(subscriptions[1].flags, bytes32(0)); - - // Check subscription 3 - assertEq(subscriptions[2].balance, 0); - assertEq(subscriptions[2].owner, OWNER_ADDRESS); - assertEq(subscriptions[2].blockedBalance, 0); - assertEq(subscriptions[2].proposedOwner, address(STRANGER_ADDRESS)); - assertEq(subscriptions[2].consumers.length, 0); - assertEq(subscriptions[2].flags, bytes32(0)); - } -} - -/// @notice #getSubscription -contract FunctionsSubscriptions_GetSubscription is FunctionsSubscriptionSetup { - function test_GetSubscription_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); - - assertEq(subscription.balance, s_subscriptionInitialFunding); - assertEq(subscription.owner, OWNER_ADDRESS); - assertEq(subscription.blockedBalance, 0); - assertEq(subscription.proposedOwner, address(0)); - assertEq(subscription.consumers[0], address(s_functionsClient)); - assertEq(subscription.flags, bytes32(0)); - } -} - -/// @notice #getConsumer -contract FunctionsSubscriptions_GetConsumer is FunctionsSubscriptionSetup { - function test_GetConsumer_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - FunctionsSubscriptions.Consumer memory consumer = s_functionsRouter.getConsumer( - address(s_functionsClient), - s_subscriptionId - ); - - assertEq(consumer.allowed, true); - assertEq(consumer.initiatedRequests, 0); - assertEq(consumer.completedRequests, 0); - } -} - -/// @notice #_isExistingSubscription -contract FunctionsSubscriptions__IsExistingSubscription is FunctionsSubscriptionSetup { - // TODO: make contract internal function helper -} - -/// @notice #_isAllowedConsumer -contract FunctionsSubscriptions__IsAllowedConsumer { - // TODO: make contract internal function helper -} - -/// @notice #createSubscription -contract FunctionsSubscriptions_createSubscription is FunctionsOwnerAcceptTermsOfServiceSetup { - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - - function test_CreateSubscription_Success() public { - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(1, OWNER_ADDRESS); - uint64 firstCallSubscriptionId = s_functionsRouter.createSubscription(); - assertEq(firstCallSubscriptionId, 1); - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(2, OWNER_ADDRESS); - uint64 secondCallSubscriptionId = s_functionsRouter.createSubscription(); - assertEq(secondCallSubscriptionId, 2); - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(3, OWNER_ADDRESS); - uint64 thirdCallSubscriptionId = s_functionsRouter.createSubscription(); - assertEq(thirdCallSubscriptionId, 3); - } - - function test_CreateSubscription_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.createSubscription(); - } - - function test_CreateSubscription_RevertIfNotAllowedSender() public { - // Send as stranger, who has not accepted Terms of Service - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, STRANGER_ADDRESS)); - s_functionsRouter.createSubscription(); - } -} - -/// @notice #createSubscriptionWithConsumer -contract FunctionsSubscriptions_CreateSubscriptionWithConsumer is FunctionsClientSetup { - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - - function test_CreateSubscriptionWithConsumer_Success() public { - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(1, OWNER_ADDRESS); - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionConsumerAdded(1, address(s_functionsClient)); - uint64 firstCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); - assertEq(firstCallSubscriptionId, 1); - assertEq(s_functionsRouter.getSubscription(firstCallSubscriptionId).consumers[0], address(s_functionsClient)); - - // Consumer can be address(0) - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(2, OWNER_ADDRESS); - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionConsumerAdded(2, address(0)); - uint64 secondCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(0)); - assertEq(secondCallSubscriptionId, 2); - assertEq(s_functionsRouter.getSubscription(secondCallSubscriptionId).consumers[0], address(0)); - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCreated(3, OWNER_ADDRESS); - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionConsumerAdded(3, address(s_functionsClient)); - uint64 thirdCallSubscriptionId = s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); - assertEq(thirdCallSubscriptionId, 3); - assertEq(s_functionsRouter.getSubscription(thirdCallSubscriptionId).consumers[0], address(s_functionsClient)); - } - - function test_CreateSubscriptionWithConsumer_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); - } - - function test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() public { - // Send as stranger, who has not accepted Terms of Service - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, STRANGER_ADDRESS)); - s_functionsRouter.createSubscriptionWithConsumer(address(s_functionsClient)); - } -} - -/// @notice #proposeSubscriptionOwnerTransfer -contract FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer is FunctionsSubscriptionSetup { - uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS = 0x3; - address internal NEW_OWNER_ADDRESS_WITH_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS); - uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS2 = 0x4; - address internal NEW_OWNER_ADDRESS_WITH_TOS2 = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS2); - uint256 internal NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS = 0x5; - address internal NEW_OWNER_ADDRESS_WITHOUT_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS); - - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Accept ToS as new owner #1 - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - bytes32 message = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS, r, s, v); - - // Accept ToS as new owner #2 - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS2); - bytes32 message2 = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS2, NEW_OWNER_ADDRESS_WITH_TOS2); - bytes32 prefixedMessage2 = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message2)); - (uint8 v2, bytes32 r2, bytes32 s2) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage2); - s_termsOfServiceAllowList.acceptTermsOfService( - NEW_OWNER_ADDRESS_WITH_TOS2, - NEW_OWNER_ADDRESS_WITH_TOS2, - r2, - s2, - v2 - ); - - vm.stopPrank(); - vm.startPrank(OWNER_ADDRESS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_functionsRouter.proposeSubscriptionOwnerTransfer(invalidSubscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() public { - // Send as non-owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - - vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() public { - // Remove owner from Allow List - s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() public { - address EMPTY_ADDRESS = address(0); - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, EMPTY_ADDRESS); - } - - function test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() public { - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - } - - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); - - function test_ProposeSubscriptionOwnerTransfer_Success() public { - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS); - } - - function test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() public { - // topic0 (function signature, always checked), topic1 (true), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = true; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS); - - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionOwnerTransferRequested(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS2); - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS2); - assertEq(s_functionsRouter.getSubscription(s_subscriptionId).proposedOwner, NEW_OWNER_ADDRESS_WITH_TOS2); - } -} - -/// @notice #acceptSubscriptionOwnerTransfer -contract FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer is FunctionsSubscriptionSetup { - uint256 internal NEW_OWNER_PRIVATE_KEY_WITH_TOS = 0x3; - address internal NEW_OWNER_ADDRESS_WITH_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITH_TOS); - uint256 internal NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS = 0x4; - address internal NEW_OWNER_ADDRESS_WITHOUT_TOS = vm.addr(NEW_OWNER_PRIVATE_KEY_WITHOUT_TOS); - - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Accept ToS as new owner - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - bytes32 message = s_termsOfServiceAllowList.getMessage(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(NEW_OWNER_ADDRESS_WITH_TOS, NEW_OWNER_ADDRESS_WITH_TOS, r, s, v); - - vm.stopPrank(); - vm.startPrank(OWNER_ADDRESS); - } - - function test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() public { - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - s_functionsRouter.pause(); - - // Send as new owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); - } - - function test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() public { - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITHOUT_TOS); - - // Send as new owner, who has NOT accepted Terms of Service - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITHOUT_TOS); - - vm.expectRevert( - abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, NEW_OWNER_ADDRESS_WITHOUT_TOS) - ); - s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); - } - - function test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() public { - // Propose an address that is allowed to accept ownership - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - bool hasAccess = s_termsOfServiceAllowList.hasAccess(NEW_OWNER_ADDRESS_WITH_TOS, new bytes(0)); - assertEq(hasAccess, true); - - // Revoke access - s_termsOfServiceAllowList.blockSender(NEW_OWNER_ADDRESS_WITH_TOS); - - // Send as blocked address - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - - vm.expectRevert( - abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, NEW_OWNER_ADDRESS_WITH_TOS) - ); - s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); - } - - function test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() public { - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, STRANGER_ADDRESS); - - // Send as someone who is not hte proposed new owner - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsSubscriptions.MustBeProposedOwner.selector, STRANGER_ADDRESS)); - s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); - } - - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); - - function test_AcceptSubscriptionOwnerTransfer_Success() public { - // Can transfer ownership with a pending request - string memory sourceCode = "return 'hello world';"; - bytes memory secrets; - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5500); - - s_functionsRouter.proposeSubscriptionOwnerTransfer(s_subscriptionId, NEW_OWNER_ADDRESS_WITH_TOS); - - // Send as new owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(NEW_OWNER_ADDRESS_WITH_TOS); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionOwnerTransferred(s_subscriptionId, OWNER_ADDRESS, NEW_OWNER_ADDRESS_WITH_TOS); - - s_functionsRouter.acceptSubscriptionOwnerTransfer(s_subscriptionId); - - FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); - assertEq(subscription.owner, NEW_OWNER_ADDRESS_WITH_TOS); - assertEq(subscription.proposedOwner, address(0)); - } -} - -/// @notice #removeConsumer -contract FunctionsSubscriptions_RemoveConsumer is FunctionsSubscriptionSetup { - function test_RemoveConsumer_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - } - - function test_RemoveConsumer_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_functionsRouter.removeConsumer(invalidSubscriptionId, address(s_functionsClient)); - } - - function test_RemoveConsumer_RevertIfNotSubscriptionOwner() public { - // Accept ToS as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - - // Send as non-subscription owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - } - - function test_RemoveConsumer_RevertIfNotAllowedSender() public { - // Remove owner from Allow List - s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - } - - function test_RemoveConsumer_RevertIfInvalidConsumer() public { - vm.expectRevert(FunctionsSubscriptions.InvalidConsumer.selector); - s_functionsRouter.removeConsumer(s_subscriptionId, address(0)); - } - - function test_RemoveConsumer_RevertIfPendingRequests() public { - // Send a minimal request - string memory sourceCode = "return 'hello world';"; - bytes memory secrets; - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - - s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); - - vm.expectRevert(FunctionsSubscriptions.CannotRemoveWithPendingRequests.selector); - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - } - - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); - - function test_RemoveConsumer_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionConsumerRemoved(s_subscriptionId, address(s_functionsClient)); - s_functionsRouter.removeConsumer(s_subscriptionId, address(s_functionsClient)); - - FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); - assertEq(subscription.consumers, new address[](0)); - } -} - -/// @notice #_getMaxConsumers -contract FunctionsSubscriptions__GetMaxConsumers is FunctionsRouterSetup { - // TODO: make contract internal function helper -} - -/// @notice #addConsumer -contract FunctionsSubscriptions_AddConsumer is FunctionsSubscriptionSetup { - function test_AddConsumer_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - } - - function test_AddConsumer_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_functionsRouter.addConsumer(invalidSubscriptionId, address(1)); - } - - function test_AddConsumer_RevertIfNotSubscriptionOwner() public { - // Accept ToS as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - - // Send as non-subscription owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - } - - function test_AddConsumer_RevertIfNotAllowedSender() public { - // Remove owner from Allow List - s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - } - - function test_AddConsumer_RevertIfMaximumConsumers() public { - // Fill Consumers to s_maxConsumersPerSubscription - // Already has one from setup - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - s_functionsRouter.addConsumer(s_subscriptionId, address(2)); - - vm.expectRevert( - abi.encodeWithSelector(FunctionsSubscriptions.TooManyConsumers.selector, s_maxConsumersPerSubscription) - ); - s_functionsRouter.addConsumer(s_subscriptionId, address(3)); - } - - function test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() public { - // Fill Consumers to s_maxConsumersPerSubscription - // Already has one from setup - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - s_functionsRouter.addConsumer(s_subscriptionId, address(2)); - - // Lower maxConsumersPerSubscription - s_maxConsumersPerSubscription = 1; - FunctionsRouter.Config memory newRouterConfig = getRouterConfig(); - s_functionsRouter.updateConfig(newRouterConfig); - - // .AddConsumer should still revert - vm.expectRevert( - abi.encodeWithSelector(FunctionsSubscriptions.TooManyConsumers.selector, s_maxConsumersPerSubscription) - ); - s_functionsRouter.addConsumer(s_subscriptionId, address(3)); - } - - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - - function test_AddConsumer_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionConsumerAdded(s_subscriptionId, address(1)); - s_functionsRouter.addConsumer(s_subscriptionId, address(1)); - - FunctionsSubscriptions.Subscription memory subscription = s_functionsRouter.getSubscription(s_subscriptionId); - assertEq(subscription.consumers[1], address(1)); - FunctionsSubscriptions.Consumer memory consumer = s_functionsRouter.getConsumer(address(1), s_subscriptionId); - assertEq(consumer.allowed, true); - } -} - -/// @notice #cancelSubscription -contract FunctionsSubscriptions_CancelSubscription is FunctionsSubscriptionSetup { - function test_CancelSubscription_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - } - - function test_CancelSubscription_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - s_functionsRouter.cancelSubscription(invalidSubscriptionId, OWNER_ADDRESS); - } - - function test_CancelSubscription_RevertIfNotSubscriptionOwner() public { - // Accept ToS as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - - // Send as non-subscription owner, who has accepted Terms of Service - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(FunctionsSubscriptions.MustBeSubscriptionOwner.selector); - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - } - - function test_CancelSubscription_RevertIfNotAllowedSender() public { - // Remove owner from Allow List - s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); - - vm.expectRevert(abi.encodeWithSelector(FunctionsRouter.SenderMustAcceptTermsOfService.selector, OWNER_ADDRESS)); - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - } - - function test_CancelSubscription_RevertIfPendingRequests() public { - // Send a minimal request - string memory sourceCode = "return 'hello world';"; - bytes memory secrets; - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - - s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); - - vm.expectRevert(FunctionsSubscriptions.CannotRemoveWithPendingRequests.selector); - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - } - - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - - function test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() public { - // No requests have been completed - assertEq(s_functionsRouter.getConsumer(address(s_functionsClient), s_subscriptionId).completedRequests, 0); - // Subscription balance is less than deposit amount - assertLe(s_functionsRouter.getSubscription(s_subscriptionId).balance, s_subscriptionDepositJuels); - - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - - uint96 expectedRefund = 0; - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); - - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); - - // Subscription should no longer exist - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.getSubscription(s_subscriptionId); - - // Router owner should have expectedDepositWithheld to withdraw - uint96 expectedDepositWithheld = s_subscriptionInitialFunding; - uint256 balanceBeforeWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); - s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, 0); - uint256 balanceAfterWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); - assertEq(balanceBeforeWithdraw + expectedDepositWithheld, balanceAfterWithdraw); - } - - function test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() public { - // No requests have been completed - assertEq(s_functionsRouter.getConsumer(address(s_functionsClient), s_subscriptionId).completedRequests, 0); - // Subscription balance is more than deposit amount, double fund the subscription - s_linkToken.transferAndCall(address(s_functionsRouter), s_subscriptionInitialFunding, abi.encode(s_subscriptionId)); - assertGe(s_functionsRouter.getSubscription(s_subscriptionId).balance, s_subscriptionDepositJuels); - - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - - uint96 expectedRefund = (s_subscriptionInitialFunding * 2) - s_subscriptionDepositJuels; - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); - - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); - - // Subscription should no longer exist - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.getSubscription(s_subscriptionId); - - // Router owner should have expectedDepositWithheld to withdraw - uint96 expectedDepositWithheld = s_subscriptionDepositJuels; - uint256 balanceBeforeWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); - s_functionsRouter.ownerWithdraw(STRANGER_ADDRESS, 0); - uint256 balanceAfterWithdraw = s_linkToken.balanceOf(STRANGER_ADDRESS); - assertEq(balanceBeforeWithdraw + expectedDepositWithheld, balanceAfterWithdraw); - } -} - -/// @notice #cancelSubscription -contract FunctionsSubscriptions_CancelSubscription_ReceiveDeposit is FunctionsFulfillmentSetup { - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - - function test_CancelSubscription_SuccessRecieveDeposit() public { - uint96 totalCostJuels = s_fulfillmentRouterOwnerBalance + s_fulfillmentCoordinatorBalance; - - uint256 subscriptionOwnerBalanceBefore = s_linkToken.balanceOf(OWNER_ADDRESS); - - uint96 expectedRefund = s_subscriptionInitialFunding - totalCostJuels; - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit SubscriptionCanceled(s_subscriptionId, OWNER_ADDRESS, expectedRefund); - - s_functionsRouter.cancelSubscription(s_subscriptionId, OWNER_ADDRESS); - - uint256 subscriptionOwnerBalanceAfter = s_linkToken.balanceOf(OWNER_ADDRESS); - assertEq(subscriptionOwnerBalanceBefore + expectedRefund, subscriptionOwnerBalanceAfter); - - // Subscription should no longer exist - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - s_functionsRouter.getSubscription(s_subscriptionId); - } -} - -/// @notice #_cancelSubscriptionHelper -contract FunctionsSubscriptions__CancelSubscriptionHelper { - // TODO: make contract internal function helper -} - -/// @notice #pendingRequestExists -contract FunctionsSubscriptions_PendingRequestExists is FunctionsFulfillmentSetup { - function test_PendingRequestExists_SuccessFalseIfNoPendingRequests() public { - bool hasPendingRequests = s_functionsRouter.pendingRequestExists(s_subscriptionId); - assertEq(hasPendingRequests, false); - } - - function test_PendingRequestExists_SuccessTrueIfPendingRequests() public { - // Send a minimal request - string memory sourceCode = "return 'hello world';"; - bytes memory secrets; - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - - s_functionsClient.sendRequest(s_donId, sourceCode, secrets, args, bytesArgs, s_subscriptionId, 5000); - - bool hasPendingRequests = s_functionsRouter.pendingRequestExists(s_subscriptionId); - assertEq(hasPendingRequests, true); - } -} - -/// @notice #setFlags -contract FunctionsSubscriptions_SetFlags is FunctionsSubscriptionSetup { - function test_SetFlags_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - bytes32 flagsToSet = bytes32("1"); - s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); - } - - function test_SetFlags_RevertIfNoSubscription() public { - vm.expectRevert(FunctionsSubscriptions.InvalidSubscription.selector); - uint64 invalidSubscriptionId = 123456789; - bytes32 flagsToSet = bytes32("1"); - s_functionsRouter.setFlags(invalidSubscriptionId, flagsToSet); - } - - function test_SetFlags_Success() public { - bytes32 flagsToSet = bytes32("1"); - s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); - bytes32 flags = s_functionsRouter.getFlags(s_subscriptionId); - assertEq(flags, flagsToSet); - } -} - -/// @notice #getFlags -contract FunctionsSubscriptions_GetFlags is FunctionsSubscriptionSetup { - function test_GetFlags_SuccessInvalidSubscription() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 invalidSubscriptionId = 999999; - - bytes32 flags = s_functionsRouter.getFlags(invalidSubscriptionId); - assertEq(flags, bytes32(0)); - } - - function test_GetFlags_SuccessValidSubscription() public { - // Set flags - bytes32 flagsToSet = bytes32("1"); - s_functionsRouter.setFlags(s_subscriptionId, flagsToSet); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 flags = s_functionsRouter.getFlags(s_subscriptionId); - assertEq(flags, flagsToSet); - } -} - -/// @notice #timeoutRequests -contract FunctionsSubscriptions_TimeoutRequests is FunctionsClientRequestSetup { - function test_TimeoutRequests_RevertIfPaused() public { - s_functionsRouter.pause(); - - vm.expectRevert("Pausable: paused"); - FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); - commitments[0] = s_requests[1].commitmentOnchain; - s_functionsRouter.timeoutRequests(commitments); - } - - function test_TimeoutRequests_RevertInvalidRequest() public { - // Modify the commitment so that it doesn't match - s_requests[1].commitmentOnchain.donFee = 123456789; - FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); - commitments[0] = s_requests[1].commitmentOnchain; - vm.expectRevert(FunctionsSubscriptions.InvalidCalldata.selector); - s_functionsRouter.timeoutRequests(commitments); - } - - function test_TimeoutRequests_RevertIfTimeoutNotExceeded() public { - vm.expectRevert(FunctionsSubscriptions.TimeoutNotExceeded.selector); - FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); - commitments[0] = s_requests[1].commitmentOnchain; - s_functionsRouter.timeoutRequests(commitments); - } - - event RequestTimedOut(bytes32 indexed requestId); - - function test_TimeoutRequests_Success() public { - uint64 consumerCompletedRequestsBefore = s_functionsRouter - .getConsumer(address(s_functionsClient), s_subscriptionId) - .completedRequests; - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit RequestTimedOut(s_requests[1].requestId); - - // Jump ahead in time past timeout timestamp - vm.warp(s_requests[1].commitmentOnchain.timeoutTimestamp + 1); - - FunctionsResponse.Commitment[] memory commitments = new FunctionsResponse.Commitment[](1); - commitments[0] = s_requests[1].commitmentOnchain; - s_functionsRouter.timeoutRequests(commitments); - - // Releases blocked balance and increments completed requests - uint96 subscriptionBlockedBalanceAfter = s_functionsRouter.getSubscription(s_subscriptionId).blockedBalance; - assertEq(0, subscriptionBlockedBalanceAfter); - uint64 consumerCompletedRequestsAfter = s_functionsRouter - .getConsumer(address(s_functionsClient), s_subscriptionId) - .completedRequests; - assertEq(consumerCompletedRequestsBefore + 1, consumerCompletedRequestsAfter); - } -} - -// @notice #_onlySubscriptionOwner -contract FunctionsSubscriptions__OnlySubscriptionOwner { - // TODO: make contract internal function helper -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol deleted file mode 100644 index 9bf0974..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol +++ /dev/null @@ -1,557 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol"; -import {TermsOfServiceAllowListConfig} from "../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; -import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; - -import {FunctionsRoutesSetup, FunctionsOwnerAcceptTermsOfServiceSetup} from "./Setup.t.sol"; -import "forge-std/Vm.sol"; - -/// @notice #constructor -contract FunctionsTermsOfServiceAllowList_Constructor is FunctionsRoutesSetup { - function test_Constructor_Success() public { - assertEq(s_termsOfServiceAllowList.typeAndVersion(), "Functions Terms of Service Allow List v1.1.1"); - assertEq(s_termsOfServiceAllowList.owner(), OWNER_ADDRESS); - } -} - -/// @notice #getConfig -contract FunctionsTermsOfServiceAllowList_GetConfig is FunctionsRoutesSetup { - function test_GetConfig_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - TermsOfServiceAllowListConfig memory config = s_termsOfServiceAllowList.getConfig(); - assertEq(config.enabled, getTermsOfServiceConfig().enabled); - assertEq(config.signerPublicKey, getTermsOfServiceConfig().signerPublicKey); - } -} - -/// @notice #updateConfig -contract FunctionsTermsOfServiceAllowList_UpdateConfig is FunctionsRoutesSetup { - function test_UpdateConfig_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_termsOfServiceAllowList.updateConfig( - TermsOfServiceAllowListConfig({enabled: true, signerPublicKey: STRANGER_ADDRESS}) - ); - } - - event ConfigUpdated(TermsOfServiceAllowListConfig config); - - function test_UpdateConfig_Success() public { - TermsOfServiceAllowListConfig memory configToSet = TermsOfServiceAllowListConfig({ - enabled: false, - signerPublicKey: TOS_SIGNER - }); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit ConfigUpdated(configToSet); - - s_termsOfServiceAllowList.updateConfig(configToSet); - - TermsOfServiceAllowListConfig memory config = s_termsOfServiceAllowList.getConfig(); - assertEq(config.enabled, configToSet.enabled); - assertEq(config.signerPublicKey, configToSet.signerPublicKey); - } -} - -/// @notice #getMessage -contract FunctionsTermsOfServiceAllowList_GetMessage is FunctionsRoutesSetup { - function test_GetMessage_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - - assertEq(message, keccak256(abi.encodePacked(STRANGER_ADDRESS, STRANGER_ADDRESS))); - } -} - -/// @notice #acceptTermsOfService -contract FunctionsTermsOfServiceAllowList_AcceptTermsOfService is FunctionsRoutesSetup { - function test_AcceptTermsOfService_RevertIfBlockedSender() public { - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - vm.expectRevert(TermsOfServiceAllowList.RecipientIsBlocked.selector); - - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } - - function test_AcceptTermsOfService_RevertIfInvalidSigner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(STRANGER_PRIVATE_KEY, prefixedMessage); - - vm.expectRevert(TermsOfServiceAllowList.InvalidSignature.selector); - - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } - - function test_AcceptTermsOfService_RevertIfRecipientIsNotSender() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); - - s_termsOfServiceAllowList.acceptTermsOfService(OWNER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } - - function test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, OWNER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); - - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, OWNER_ADDRESS, r, s, v); - } - - function test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() public { - FunctionsClientTestHelper s_functionsClientHelper = new FunctionsClientTestHelper(address(s_functionsRouter)); - - // Send as externally owned account - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Attempt to accept for a contract account - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, address(s_functionsClientHelper)); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - vm.expectRevert(TermsOfServiceAllowList.InvalidUsage.selector); - - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, address(s_functionsClientHelper), r, s, v); - } - - function testAcceptTermsOfService_InvalidSigner_vuln() public { - // Set the signer as the zero address - TermsOfServiceAllowListConfig memory allowListConfig; - allowListConfig.enabled = true; - allowListConfig.signerPublicKey = address(0); - s_termsOfServiceAllowList.updateConfig(allowListConfig); - - // Provide garbage data (v cannot be 29) to generate an invalid signature - uint8 v = 29; - bytes32 r = 0x0101010000000000000000000000000000000000000000000000000000000000; - bytes32 s = 0x0101010000000000000000000000000000000000000000000000000000000000; - - // Expect a revert on invalid signature but the call is successful - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - // vm.expectRevert(TermsOfServiceAllowList.InvalidSignature.selector); - // TODO: Add validation to setConfig to prevent empty signer - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } - - event AddedAccess(address user); - - function test_AcceptTermsOfService_SuccessIfAcceptingForSelf() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit AddedAccess(STRANGER_ADDRESS); - - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - - assertTrue(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); - - // Check the addedAccess is not emitted, given the recipient was already in the list - vm.recordLogs(); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 0); - - assertTrue(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); - } - - function test_AcceptTermsOfService_SuccessIfAcceptingForContract() public { - FunctionsClientTestHelper s_functionsClientHelper = new FunctionsClientTestHelper(address(s_functionsRouter)); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, address(s_functionsClientHelper)); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit AddedAccess(address(s_functionsClientHelper)); - - s_functionsClientHelper.acceptTermsOfService(STRANGER_ADDRESS, address(s_functionsClientHelper), r, s, v); - - assertEq(s_termsOfServiceAllowList.hasAccess(address(s_functionsClientHelper), new bytes(0)), true); - } -} - -/// @notice #getAllAllowedSenders -contract FunctionsTermsOfServiceAllowList_GetAllAllowedSenders is FunctionsOwnerAcceptTermsOfServiceSetup { - function test_GetAllAllowedSenders_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - address[] memory expectedSenders = new address[](1); - expectedSenders[0] = OWNER_ADDRESS; - - assertEq(s_termsOfServiceAllowList.getAllAllowedSenders(), expectedSenders); - } -} - -/// @notice #getAllowedSendersCount -contract FunctionsTermsOfServiceAllowList_GetAllowedSendersCount is FunctionsOwnerAcceptTermsOfServiceSetup { - function test_GetAllowedSendersCount_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint96 allowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); - // One allowed sender was made during setup - assertEq(allowedSendersCount, 1); - } -} - -/// @notice #getAllowedSendersInRange -contract FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange is FunctionsOwnerAcceptTermsOfServiceSetup { - function test_GetAllowedSendersInRange_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - address[] memory expectedSenders = new address[](1); - expectedSenders[0] = OWNER_ADDRESS; - - assertEq(s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0), expectedSenders); - } - - function test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() public { - // setup a new empty s_termsOfServiceAllowList - FunctionsRoutesSetup.setUp(); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); - uint64 expected = 0; - assertEq(AllowedSendersCount, expected); - - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - s_termsOfServiceAllowList.getAllowedSendersInRange(0, 0); - } - - function test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - - s_termsOfServiceAllowList.getAllowedSendersInRange(1, 0); - } - - function test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 AllowedSendersCount = s_termsOfServiceAllowList.getAllowedSendersCount(); - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - s_termsOfServiceAllowList.getAllowedSendersInRange(1, AllowedSendersCount + 1); - } -} - -/// @notice #hasAccess -contract FunctionsTermsOfServiceAllowList_HasAccess is FunctionsRoutesSetup { - function test_HasAccess_FalseWhenEnabled() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Check access of account that is not on the allow list - assertEq(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0)), false); - } - - function test_HasAccess_TrueWhenDisabled() public { - // Disable allow list, which opens all access - s_termsOfServiceAllowList.updateConfig( - TermsOfServiceAllowListConfig({enabled: false, signerPublicKey: TOS_SIGNER}) - ); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Check access of account that is not on the allow list - assertEq(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0)), true); - } -} - -/// @notice #isBlockedSender -contract FunctionsTermsOfServiceAllowList_IsBlockedSender is FunctionsRoutesSetup { - function test_IsBlockedSender_SuccessFalse() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - assertEq(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS), false); - } - - function test_IsBlockedSender_SuccessTrue() public { - // Block sender - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - assertEq(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS), true); - } -} - -/// @notice #blockSender -contract FunctionsTermsOfServiceAllowList_BlockSender is FunctionsRoutesSetup { - function test_BlockSender_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_termsOfServiceAllowList.blockSender(OWNER_ADDRESS); - } - - event BlockedAccess(address user); - - function test_BlockSender_Success() public { - assertFalse(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS)); - - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit BlockedAccess(STRANGER_ADDRESS); - - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - assertFalse(s_termsOfServiceAllowList.hasAccess(STRANGER_ADDRESS, new bytes(0))); - assertTrue(s_termsOfServiceAllowList.isBlockedSender(STRANGER_ADDRESS)); - - // Account can no longer accept Terms of Service - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - vm.expectRevert(TermsOfServiceAllowList.RecipientIsBlocked.selector); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } -} - -/// @notice #unblockSender -contract FunctionsTermsOfServiceAllowList_UnblockSender is FunctionsRoutesSetup { - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - } - - function test_UnblockSender_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - s_termsOfServiceAllowList.unblockSender(STRANGER_ADDRESS); - } - - event UnblockedAccess(address user); - - function test_UnblockSender_Success() public { - // topic0 (function signature, always checked), NOT topic1 (false), NOT topic2 (false), NOT topic3 (false), and data (true). - bool checkTopic1 = false; - bool checkTopic2 = false; - bool checkTopic3 = false; - bool checkData = true; - vm.expectEmit(checkTopic1, checkTopic2, checkTopic3, checkData); - emit UnblockedAccess(STRANGER_ADDRESS); - - s_termsOfServiceAllowList.unblockSender(STRANGER_ADDRESS); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - // Account can now accept the Terms of Service - bytes32 message = s_termsOfServiceAllowList.getMessage(STRANGER_ADDRESS, STRANGER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(STRANGER_ADDRESS, STRANGER_ADDRESS, r, s, v); - } -} - -/// @notice #getBlockedSendersCount -contract FunctionsTermsOfServiceAllowList_GetBlockedSendersCount is FunctionsRoutesSetup { - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - } - - function test_GetBlockedSendersCount_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint96 blockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); - // One blocked sender was made during setup - assertEq(blockedSendersCount, 1); - } -} - -/// @notice #getBlockedSendersInRange -contract FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange is FunctionsRoutesSetup { - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - s_termsOfServiceAllowList.blockSender(STRANGER_ADDRESS); - } - - function test_GetBlockedSendersInRange_Success() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - address[] memory expectedBlockedSenders = new address[](1); - expectedBlockedSenders[0] = STRANGER_ADDRESS; - - assertEq(s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0), expectedBlockedSenders); - } - - function test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() public { - // setup a new empty s_termsOfServiceBlockList - FunctionsRoutesSetup.setUp(); - - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); - uint64 expected = 0; - assertEq(BlockedSendersCount, expected); - - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - s_termsOfServiceAllowList.getBlockedSendersInRange(0, 0); - } - - function test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - - s_termsOfServiceAllowList.getBlockedSendersInRange(1, 0); - } - - function test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - uint64 BlockedSendersCount = s_termsOfServiceAllowList.getBlockedSendersCount(); - vm.expectRevert(TermsOfServiceAllowList.InvalidCalldata.selector); - s_termsOfServiceAllowList.getBlockedSendersInRange(1, BlockedSendersCount + 1); - } -} - -/// @notice #migratePreviouslyAllowedSenders -contract FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders is FunctionsRoutesSetup { - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - } - - function test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() public { - // Send as stranger - vm.stopPrank(); - vm.startPrank(STRANGER_ADDRESS); - - vm.expectRevert("Only callable by owner"); - address[] memory empty = new address[](0); - s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(empty); - } - - function test_MigratePreviouslyAllowedSenders_Success() public { - address previouslyAllowedSender1 = 0x1000000000000000000000000000000000000000; - address previouslyAllowedSender2 = 0x2000000000000000000000000000000000000000; - address currentlyBlockedSender = 0xB000000000000000000000000000000000000000; - - address[] memory mockPreviousAllowlist = new address[](3); - mockPreviousAllowlist[0] = previouslyAllowedSender1; - mockPreviousAllowlist[1] = currentlyBlockedSender; - mockPreviousAllowlist[2] = previouslyAllowedSender2; - - s_termsOfServiceAllowList.blockSender(currentlyBlockedSender); - - vm.mockCall( - MOCK_PREVIOUS_TOS_ADDRESS, - abi.encodeWithSelector(TermsOfServiceAllowList.hasAccess.selector), - abi.encode(true) - ); - s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(mockPreviousAllowlist); - - address[] memory currentlyAllowedSenders = s_termsOfServiceAllowList.getAllAllowedSenders(); - - address[] memory expectedAllowedSenders = new address[](2); - expectedAllowedSenders[0] = previouslyAllowedSender1; - expectedAllowedSenders[1] = previouslyAllowedSender2; - assertEq(currentlyAllowedSenders, expectedAllowedSenders); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol deleted file mode 100644 index 1ecc0fb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Gas.t.sol +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsRouter} from "../../dev/v1_X/FunctionsRouter.sol"; -import {FunctionsSubscriptions} from "../../dev/v1_X/FunctionsSubscriptions.sol"; -import {FunctionsRequest} from "../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {FunctionsClientTestHelper} from "./testhelpers/FunctionsClientTestHelper.sol"; - -import {FunctionsRoutesSetup, FunctionsOwnerAcceptTermsOfServiceSetup, FunctionsSubscriptionSetup, FunctionsClientRequestSetup} from "./Setup.t.sol"; - -import "forge-std/Vm.sol"; - -/// @notice #acceptTermsOfService -contract Gas_AcceptTermsOfService is FunctionsRoutesSetup { - bytes32 s_sigR; - bytes32 s_sigS; - uint8 s_sigV; - - function setUp() public virtual override { - vm.pauseGasMetering(); - - FunctionsRoutesSetup.setUp(); - - bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, OWNER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (s_sigV, s_sigR, s_sigS) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - } - - function test_AcceptTermsOfService_Gas() public { - // Pull storage variables into memory - address ownerAddress = OWNER_ADDRESS; - bytes32 sigR = s_sigR; - bytes32 sigS = s_sigS; - uint8 sigV = s_sigV; - vm.resumeGasMetering(); - - s_termsOfServiceAllowList.acceptTermsOfService(ownerAddress, ownerAddress, sigR, sigS, sigV); - } -} - -/// @notice #createSubscription -contract Gas_CreateSubscription is FunctionsOwnerAcceptTermsOfServiceSetup { - function test_CreateSubscription_Gas() public { - s_functionsRouter.createSubscription(); - } -} - -/// @notice #addConsumer -contract Gas_AddConsumer is FunctionsSubscriptionSetup { - function setUp() public virtual override { - vm.pauseGasMetering(); - - FunctionsSubscriptionSetup.setUp(); - } - - function test_AddConsumer_Gas() public { - // Keep input data in memory - uint64 subscriptionId = s_subscriptionId; - address consumerAddress = address(s_functionsCoordinator); // use garbage address - vm.resumeGasMetering(); - - s_functionsRouter.addConsumer(subscriptionId, consumerAddress); - } -} - -/// @notice #fundSubscription -contract Gas_FundSubscription is FunctionsSubscriptionSetup { - function setUp() public virtual override { - vm.pauseGasMetering(); - - FunctionsSubscriptionSetup.setUp(); - } - - function test_FundSubscription_Gas() public { - // Keep input data in memory - address routerAddress = address(s_functionsRouter); - uint96 s_subscriptionFunding = 10 * JUELS_PER_LINK; // 10 LINK - bytes memory data = abi.encode(s_subscriptionId); - vm.resumeGasMetering(); - - s_linkToken.transferAndCall(routerAddress, s_subscriptionFunding, data); - } -} - -/// @notice #sendRequest -contract Gas_SendRequest is FunctionsSubscriptionSetup { - bytes s_minimalRequestData; - bytes s_maximalRequestData; - - function _makeStringOfBytesSize(uint16 bytesSize) internal pure returns (string memory) { - return vm.toString(new bytes((bytesSize - 2) / 2)); - } - - function setUp() public virtual override { - vm.pauseGasMetering(); - - FunctionsSubscriptionSetup.setUp(); - - { - // Create minimum viable request data - FunctionsRequest.Request memory minimalRequest; - string memory minimalSourceCode = "return Functions.encodeString('hello world');"; - FunctionsRequest._initializeRequest( - minimalRequest, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - minimalSourceCode - ); - s_minimalRequestData = FunctionsRequest._encodeCBOR(minimalRequest); - } - - { - // Create maximum viable request data - 30 KB encoded data - FunctionsRequest.Request memory maxmimalRequest; - - // Create maximum viable request data - 30 KB encoded data - string memory maximalSourceCode = _makeStringOfBytesSize(29_898); // CBOR size without source code is 102 bytes - FunctionsRequest._initializeRequest( - maxmimalRequest, - FunctionsRequest.Location.Inline, - FunctionsRequest.CodeLanguage.JavaScript, - maximalSourceCode - ); - s_maximalRequestData = FunctionsRequest._encodeCBOR(maxmimalRequest); - assertEq(s_maximalRequestData.length, 30_000); - } - } - - /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values - function test_SendRequest_MaximumGas() public { - // Pull storage variables into memory - bytes memory maximalRequestData = s_maximalRequestData; - uint64 subscriptionId = s_subscriptionId; - uint32 callbackGasLimit = 300_000; - bytes32 donId = s_donId; - vm.resumeGasMetering(); - - s_functionsClient.sendRequestBytes(maximalRequestData, subscriptionId, callbackGasLimit, donId); - } - - function test_SendRequest_MinimumGas() public { - // Pull storage variables into memory - bytes memory minimalRequestData = s_minimalRequestData; - uint64 subscriptionId = s_subscriptionId; - uint32 callbackGasLimit = 5_500; - bytes32 donId = s_donId; - vm.resumeGasMetering(); - - s_functionsClient.sendRequestBytes(minimalRequestData, subscriptionId, callbackGasLimit, donId); - } -} - -// Setup Fulfill Gas tests -contract Gas_FulfillRequest_Setup is FunctionsClientRequestSetup { - mapping(uint256 reportNumber => Report) s_reports; - - FunctionsClientTestHelper s_functionsClientWithMaximumReturnData; - - function _makeStringOfBytesSize(uint16 bytesSize) internal pure returns (string memory) { - return vm.toString(new bytes((bytesSize - 2) / 2)); - } - - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - { - // Deploy consumer that has large revert return data - s_functionsClientWithMaximumReturnData = new FunctionsClientTestHelper(address(s_functionsRouter)); - s_functionsClientWithMaximumReturnData.setRevertFulfillRequest(true); - string memory revertMessage = _makeStringOfBytesSize(30_000); // 30kb - FunctionsRouter cuts off response at MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32 = 132bytes, go well above that - s_functionsClientWithMaximumReturnData.setRevertFulfillRequestMessage(revertMessage); - s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClientWithMaximumReturnData)); - } - - // Set up maximum gas test - { - // Send request #2 for maximum gas test - uint8 requestNumber = 2; - - bytes memory secrets = new bytes(0); - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - uint32 callbackGasLimit = 300_000; - - // Create maximum viable request data - 30 KB encoded data - string memory maximalSourceCode = _makeStringOfBytesSize(29_898); // CBOR size without source code is 102 bytes - - _sendAndStoreRequest( - requestNumber, - maximalSourceCode, - secrets, - args, - bytesArgs, - callbackGasLimit, - address(s_functionsClientWithMaximumReturnData) - ); - - // Build the report transmission data - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = requestNumber; - string[] memory results = new string[](1); - // Build a 256 byte response size - results[0] = _makeStringOfBytesSize(256); - bytes[] memory errors = new bytes[](1); - errors[0] = new bytes(0); // No error - - (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); - - uint256[] memory signerPrivateKeys = new uint256[](3); - signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; - signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; - signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; - - (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( - report, - reportContext, - signerPrivateKeys - ); - - // Store the report data - s_reports[1] = Report({rs: rawRs, ss: rawSs, vs: rawVs, report: report, reportContext: reportContext}); - } - - // Set up minimum gas test - { - // Send requests minimum gas test - uint8 requestsToSend = 1; - uint8 requestNumberOffset = 3; // the setup already has request #1 sent, and the previous test case uses request #2, start from request #3 - - string memory sourceCode = "return Functions.encodeString('hello world');"; - bytes memory secrets = new bytes(0); - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - uint32 callbackGasLimit = 5_500; - - for (uint256 i = 0; i < requestsToSend; ++i) { - _sendAndStoreRequest(i + requestNumberOffset, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - } - - // Build the report transmission data - uint256[] memory requestNumberKeys = new uint256[](requestsToSend); - string[] memory results = new string[](requestsToSend); - bytes[] memory errors = new bytes[](requestsToSend); - for (uint256 i = 0; i < requestsToSend; ++i) { - requestNumberKeys[i] = i + requestNumberOffset; - results[i] = "hello world"; - errors[i] = new bytes(0); // no error - } - - (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); - - uint256[] memory signerPrivateKeys = new uint256[](3); - signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; - signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; - signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; - - (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( - report, - reportContext, - signerPrivateKeys - ); - - // Store the report data - s_reports[2] = Report({rs: rawRs, ss: rawSs, vs: rawVs, report: report, reportContext: reportContext}); - } - - vm.stopPrank(); - vm.startPrank(NOP_TRANSMITTER_ADDRESS_1); - } -} - -/// @notice #fulfillRequest -contract Gas_FulfillRequest_Success is Gas_FulfillRequest_Setup { - function setUp() public virtual override { - vm.pauseGasMetering(); - - Gas_FulfillRequest_Setup.setUp(); - } - - /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values - function test_FulfillRequest_Success_MaximumGas() public { - // Pull storage variables into memory - uint8 reportNumber = 1; - bytes32[] memory rs = s_reports[reportNumber].rs; - bytes32[] memory ss = s_reports[reportNumber].ss; - bytes32 vs = s_reports[reportNumber].vs; - bytes memory report = s_reports[reportNumber].report; - bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; - vm.resumeGasMetering(); - - // 1 fulfillment in the report, single request takes on all report validation cost - // maximum request - // maximum NOPs - // maximum return data - // first storage write to change default values - s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); - } - - function test_FulfillRequest_Success_MinimumGas() public { - // Pull storage variables into memory - uint8 reportNumber = 2; - bytes32[] memory rs = s_reports[reportNumber].rs; - bytes32[] memory ss = s_reports[reportNumber].ss; - bytes32 vs = s_reports[reportNumber].vs; - bytes memory report = s_reports[reportNumber].report; - bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; - vm.resumeGasMetering(); - - // max fulfillments in the report, cost of validation split between all - // minimal request - // minimum NOPs - // no return data - // not storage writing default values - s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); - } -} - -/// @notice #fulfillRequest -contract Gas_FulfillRequest_DuplicateRequestID is Gas_FulfillRequest_Setup { - function setUp() public virtual override { - vm.pauseGasMetering(); - - // Send requests - Gas_FulfillRequest_Setup.setUp(); - // Fulfill request #1 & #2 - for (uint256 i = 1; i < 3; i++) { - uint256 reportNumber = i; - bytes32[] memory rs = s_reports[reportNumber].rs; - bytes32[] memory ss = s_reports[reportNumber].ss; - bytes32 vs = s_reports[reportNumber].vs; - bytes memory report = s_reports[reportNumber].report; - bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; - s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); - } - - // Now tests will attempt to transmit reports with respones to requests that have already been fulfilled - } - - /// @dev The order of these test cases matters as the first test will consume more gas by writing over default values - function test_FulfillRequest_DuplicateRequestID_MaximumGas() public { - // Pull storage variables into memory - uint8 reportNumber = 1; - bytes32[] memory rs = s_reports[reportNumber].rs; - bytes32[] memory ss = s_reports[reportNumber].ss; - bytes32 vs = s_reports[reportNumber].vs; - bytes memory report = s_reports[reportNumber].report; - bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; - vm.resumeGasMetering(); - - // 1 fulfillment in the report, single request takes on all report validation cost - // maximum request - // maximum NOPs - // maximum return data - // first storage write to change default values - s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); - } - - function test_FulfillRequest_DuplicateRequestID_MinimumGas() public { - // Pull storage variables into memory - uint8 reportNumber = 2; - bytes32[] memory rs = s_reports[reportNumber].rs; - bytes32[] memory ss = s_reports[reportNumber].ss; - bytes32 vs = s_reports[reportNumber].vs; - bytes memory report = s_reports[reportNumber].report; - bytes32[3] memory reportContext = s_reports[reportNumber].reportContext; - vm.resumeGasMetering(); - - // max fulfillments in the report, cost of validation split between all - // minimal request - // minimum NOPs - // no return data - // not storage writing default values - s_functionsCoordinator.transmit(reportContext, report, rs, ss, vs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol deleted file mode 100644 index 3dc0db8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/OCR2.t.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -// ================================================================ -// | OCR2Base | -// ================================================================ - -/// @notice #constructor -contract OCR2Base_Constructor {} - -/// @notice #checkConfigValid -contract OCR2Base_CheckConfigValid {} - -/// @notice #latestConfigDigestAndEpoch -contract OCR2Base_LatestConfigDigestAndEpoch {} - -/// @notice #setConfig -contract OCR2Base_SetConfig {} - -/// @notice #configDigestFromConfigData -contract OCR2Base_ConfigDigestFromConfigData {} - -/// @notice #latestConfigDetails -contract OCR2Base_LatestConfigDetails {} - -/// @notice #transmitters -contract OCR2Base_Transmitters {} - -/// @notice #_report -contract OCR2Base__Report { - // TODO: make contract internal function helper -} - -/// @notice #requireExpectedMsgDataLength -contract OCR2Base_RequireExpectedMsgDataLength {} - -/// @notice #transmit -contract OCR2Base_Transmit {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md deleted file mode 100644 index 5f96532..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/README.md +++ /dev/null @@ -1,25 +0,0 @@ -## Usage - -First set the foundry profile to Functions: -``` -export FOUNDRY_PROFILE=functions -``` - -**To run tests use**: - -All Functions test files: -``` -forge test -vvv -``` - -To run a specific file use: -``` -forge test -vvv --mp src/v0.8/functions/tests/v1_X/[File Name].t.sol -``` - -**To see coverage**: -First ensure that the correct files are being evaluated. For example, if only v0 contracts are, then temporarily change the Functions profile in `./foundry.toml`. - -``` -forge coverage --ir-minimum -``` \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol deleted file mode 100644 index 444fc18..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol +++ /dev/null @@ -1,721 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {FunctionsClientHarness} from "./testhelpers/FunctionsClientHarness.sol"; -import {FunctionsRouterHarness, FunctionsRouter} from "./testhelpers/FunctionsRouterHarness.sol"; -import {FunctionsCoordinatorHarness} from "./testhelpers/FunctionsCoordinatorHarness.sol"; -import {FunctionsBilling} from "../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsResponse} from "../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {TermsOfServiceAllowList} from "../../dev/v1_X/accessControl/TermsOfServiceAllowList.sol"; -import {TermsOfServiceAllowListConfig} from "../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; -import {MockLinkToken} from "../../../mocks/MockLinkToken.sol"; -import {FunctionsBillingConfig} from "../../dev/v1_X/interfaces/IFunctionsBilling.sol"; - -import "forge-std/Vm.sol"; - -/// @notice Set up to deploy the following contracts: FunctionsRouter, FunctionsCoordinator, LINK/ETH Feed, ToS Allow List, and LINK token -contract FunctionsRouterSetup is BaseTest { - FunctionsRouterHarness internal s_functionsRouter; - FunctionsCoordinatorHarness internal s_functionsCoordinator; - MockV3Aggregator internal s_linkEthFeed; - MockV3Aggregator internal s_linkUsdFeed; - TermsOfServiceAllowList internal s_termsOfServiceAllowList; - MockLinkToken internal s_linkToken; - - uint16 internal s_maxConsumersPerSubscription = 3; - uint72 internal s_adminFee = 0; // Keep as 0. Setting this to anything else will cause fulfillments to fail with INVALID_COMMITMENT - uint16 internal s_donFee = 100; // $1 - uint16 internal s_operationFee = 100; // $1 - bytes4 internal s_handleOracleFulfillmentSelector = 0x0ca76175; - uint16 s_subscriptionDepositMinimumRequests = 1; - uint72 s_subscriptionDepositJuels = 11 * JUELS_PER_LINK; - - int256 internal LINK_ETH_RATE = 6_000_000_000_000_000; - uint8 internal LINK_ETH_DECIMALS = 18; - int256 internal LINK_USD_RATE = 1_500_000_000; - uint8 internal LINK_USD_DECIMALS = 8; - - address public MOCK_PREVIOUS_TOS_ADDRESS = 0x746f730000000000000000000000000000000000; - uint256 internal TOS_SIGNER_PRIVATE_KEY = 0x3; - address internal TOS_SIGNER = vm.addr(TOS_SIGNER_PRIVATE_KEY); - - function setUp() public virtual override { - BaseTest.setUp(); - s_linkToken = new MockLinkToken(); - s_functionsRouter = new FunctionsRouterHarness(address(s_linkToken), getRouterConfig()); - s_linkEthFeed = new MockV3Aggregator(LINK_ETH_DECIMALS, LINK_ETH_RATE); - s_linkUsdFeed = new MockV3Aggregator(LINK_USD_DECIMALS, LINK_USD_RATE); - s_functionsCoordinator = new FunctionsCoordinatorHarness( - address(s_functionsRouter), - getCoordinatorConfig(), - address(s_linkEthFeed), - address(s_linkUsdFeed) - ); - address[] memory initialAllowedSenders; - address[] memory initialBlockedSenders; - s_termsOfServiceAllowList = new TermsOfServiceAllowList( - getTermsOfServiceConfig(), - initialAllowedSenders, - initialBlockedSenders, - MOCK_PREVIOUS_TOS_ADDRESS - ); - } - - function getRouterConfig() public view returns (FunctionsRouter.Config memory) { - uint32[] memory maxCallbackGasLimits = new uint32[](3); - maxCallbackGasLimits[0] = 300_000; - maxCallbackGasLimits[1] = 500_000; - maxCallbackGasLimits[2] = 1_000_000; - - return - FunctionsRouter.Config({ - maxConsumersPerSubscription: s_maxConsumersPerSubscription, - adminFee: s_adminFee, - handleOracleFulfillmentSelector: s_handleOracleFulfillmentSelector, - maxCallbackGasLimits: maxCallbackGasLimits, - gasForCallExactCheck: 5000, - subscriptionDepositMinimumRequests: s_subscriptionDepositMinimumRequests, - subscriptionDepositJuels: s_subscriptionDepositJuels - }); - } - - function getCoordinatorConfig() public view returns (FunctionsBillingConfig memory) { - return - FunctionsBillingConfig({ - feedStalenessSeconds: 24 * 60 * 60, // 1 day - gasOverheadAfterCallback: 93_942, - gasOverheadBeforeCallback: 105_000, - requestTimeoutSeconds: 60 * 5, // 5 minutes - donFeeCentsUsd: s_donFee, - operationFeeCentsUsd: s_operationFee, - maxSupportedRequestDataVersion: 1, - fulfillmentGasPriceOverEstimationBP: 5000, - fallbackNativePerUnitLink: 5000000000000000, - fallbackUsdPerUnitLink: 1400000000, - fallbackUsdPerUnitLinkDecimals: 8, - minimumEstimateGasPriceWei: 1000000000, // 1 gwei - transmitTxSizeBytes: 1764 - }); - } - - function getTermsOfServiceConfig() public view returns (TermsOfServiceAllowListConfig memory) { - return TermsOfServiceAllowListConfig({enabled: true, signerPublicKey: TOS_SIGNER}); - } -} - -/// @notice Set up to set the OCR configuration of the Coordinator contract -contract FunctionsDONSetup is FunctionsRouterSetup { - uint256 internal NOP_SIGNER_PRIVATE_KEY_1 = 0x400; - address internal NOP_SIGNER_ADDRESS_1 = vm.addr(NOP_SIGNER_PRIVATE_KEY_1); - uint256 internal NOP_SIGNER_PRIVATE_KEY_2 = 0x401; - address internal NOP_SIGNER_ADDRESS_2 = vm.addr(NOP_SIGNER_PRIVATE_KEY_2); - uint256 internal NOP_SIGNER_PRIVATE_KEY_3 = 0x402; - address internal NOP_SIGNER_ADDRESS_3 = vm.addr(NOP_SIGNER_PRIVATE_KEY_3); - uint256 internal NOP_SIGNER_PRIVATE_KEY_4 = 0x403; - address internal NOP_SIGNER_ADDRESS_4 = vm.addr(NOP_SIGNER_PRIVATE_KEY_4); - - uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_1 = 0x404; - address internal NOP_TRANSMITTER_ADDRESS_1 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_1); - uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_2 = 0x405; - address internal NOP_TRANSMITTER_ADDRESS_2 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_2); - uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_3 = 0x406; - address internal NOP_TRANSMITTER_ADDRESS_3 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_3); - uint256 internal NOP_TRANSMITTER_PRIVATE_KEY_4 = 0x407; - address internal NOP_TRANSMITTER_ADDRESS_4 = vm.addr(NOP_TRANSMITTER_PRIVATE_KEY_4); - - address[] internal s_signers; - address[] internal s_transmitters; - uint8 s_f = 1; - bytes internal s_onchainConfig = new bytes(0); - uint64 internal s_offchainConfigVersion = 1; - bytes internal s_offchainConfig = new bytes(0); - - bytes s_thresholdKey = - vm.parseBytes( - "0x7b2247726f7570223a2250323536222c22475f626172223a22424f2f344358424575792f64547a436a612b614e774d666c2b645a77346d325036533246536b4966472f6633527547327337392b494e79642b4639326a346f586e67433657427561556a752b4a637a32377834484251343d222c2248223a224250532f72485065377941467232416c447a79395549466258776d46384666756632596d514177666e3342373844336f474845643247474536466e616f34552b4c6a4d4d5756792b464f7075686e77554f6a75427a64773d222c22484172726179223a5b22424d75546862414473337768316e67764e56792f6e3841316d42674b5a4b4c475259385937796a39695769337242502f316a32347571695869534531437554384c6f51446a386248466d384345477667517158494e62383d222c224248687974716d6e34314373322f4658416f43737548687151486236382f597930524b2b41354c6647654f645a78466f4e386c442b45656e4b587a544943784f6d3231636d535447364864484a6e336342645663714c673d222c22424d794e7a4534616e596258474d72694f52664c52634e7239766c347878654279316432452f4464335a744630546372386267567435582b2b42355967552b4b7875726e512f4d656b6857335845782b79506e4e4f584d3d222c22424d6a753272375a657a4a45545539413938746a6b6d547966796a79493735345742555835505174724a6578346d6766366130787373426d50325a7472412b55576d504e592b6d4664526b46674f7944694c53614e59453d225d7d" - ); - bytes s_donKey = - vm.parseBytes( - "0xf2f9c47363202d89aa9fa70baf783d70006fe493471ac8cfa82f1426fd09f16a5f6b32b7c4b5d5165cd147a6e513ba4c0efd39d969d6b20a8a21126f0411b9c6" - ); - - function setUp() public virtual override { - FunctionsRouterSetup.setUp(); - - s_signers = new address[](4); - s_signers[0] = NOP_SIGNER_ADDRESS_1; - s_signers[1] = NOP_SIGNER_ADDRESS_2; - s_signers[2] = NOP_SIGNER_ADDRESS_3; - s_signers[3] = NOP_SIGNER_ADDRESS_4; - - s_transmitters = new address[](4); - s_transmitters[0] = NOP_TRANSMITTER_ADDRESS_1; - s_transmitters[1] = NOP_TRANSMITTER_ADDRESS_2; - s_transmitters[2] = NOP_TRANSMITTER_ADDRESS_3; - s_transmitters[3] = NOP_TRANSMITTER_ADDRESS_4; - - // set OCR config - s_functionsCoordinator.setConfig( - s_signers, - s_transmitters, - s_f, - s_onchainConfig, - s_offchainConfigVersion, - s_offchainConfig - ); - } - - function _getTransmitterBalances() internal view returns (uint256[4] memory balances) { - return [ - s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_1), - s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_2), - s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_3), - s_linkToken.balanceOf(NOP_TRANSMITTER_ADDRESS_4) - ]; - } - - function _assertTransmittersAllHaveBalance(uint256[4] memory balances, uint256 expectedBalance) internal { - assertEq(balances[0], expectedBalance); - assertEq(balances[1], expectedBalance); - assertEq(balances[2], expectedBalance); - assertEq(balances[3], expectedBalance); - } -} - -/// @notice Set up to add the Coordinator and ToS Allow Contract as routes on the Router contract -contract FunctionsRoutesSetup is FunctionsDONSetup { - bytes32 s_donId = bytes32("1"); - - function setUp() public virtual override { - FunctionsDONSetup.setUp(); - - bytes32 allowListId = s_functionsRouter.getAllowListId(); - bytes32[] memory proposedContractSetIds = new bytes32[](2); - proposedContractSetIds[0] = s_donId; - proposedContractSetIds[1] = allowListId; - address[] memory proposedContractSetAddresses = new address[](2); - proposedContractSetAddresses[0] = address(s_functionsCoordinator); - proposedContractSetAddresses[1] = address(s_termsOfServiceAllowList); - - s_functionsRouter.proposeContractsUpdate(proposedContractSetIds, proposedContractSetAddresses); - s_functionsRouter.updateContracts(); - } -} - -/// @notice Set up for the OWNER_ADDRESS to accept the Terms of Service -contract FunctionsOwnerAcceptTermsOfServiceSetup is FunctionsRoutesSetup { - function setUp() public virtual override { - FunctionsRoutesSetup.setUp(); - - bytes32 message = s_termsOfServiceAllowList.getMessage(OWNER_ADDRESS, OWNER_ADDRESS); - bytes32 prefixedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", message)); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(TOS_SIGNER_PRIVATE_KEY, prefixedMessage); - s_termsOfServiceAllowList.acceptTermsOfService(OWNER_ADDRESS, OWNER_ADDRESS, r, s, v); - } -} - -/// @notice Set up to deploy a consumer contract -contract FunctionsClientSetup is FunctionsOwnerAcceptTermsOfServiceSetup { - FunctionsClientHarness internal s_functionsClient; - - function setUp() public virtual override { - FunctionsOwnerAcceptTermsOfServiceSetup.setUp(); - - s_functionsClient = new FunctionsClientHarness(address(s_functionsRouter)); - } -} - -/// @notice Set up to create a subscription, add the consumer contract as a consumer of the subscription, and fund the subscription with 's_subscriptionInitialFunding' -contract FunctionsSubscriptionSetup is FunctionsClientSetup { - uint64 s_subscriptionId; - uint96 s_subscriptionInitialFunding = 10 * JUELS_PER_LINK; // 10 LINK - - function setUp() public virtual override { - FunctionsClientSetup.setUp(); - - // Create subscription - s_subscriptionId = s_functionsRouter.createSubscription(); - s_functionsRouter.addConsumer(s_subscriptionId, address(s_functionsClient)); - - // Fund subscription - s_linkToken.transferAndCall(address(s_functionsRouter), s_subscriptionInitialFunding, abi.encode(s_subscriptionId)); - } -} - -/// @notice Set up to initate a minimal request and store it in s_requests[1] -contract FunctionsClientRequestSetup is FunctionsSubscriptionSetup { - struct Report { - bytes32[] rs; - bytes32[] ss; - bytes32 vs; - bytes report; - bytes32[3] reportContext; - } - - struct RequestData { - string sourceCode; - bytes secrets; - string[] args; - bytes[] bytesArgs; - uint32 callbackGasLimit; - } - struct Request { - RequestData requestData; - bytes32 requestId; - FunctionsResponse.Commitment commitment; // Offchain commitment that contains operation fee in the place of admin fee - FunctionsResponse.Commitment commitmentOnchain; // Commitment that is persisted as a hash in the Router - } - - mapping(uint256 requestNumber => Request) s_requests; - - struct Response { - uint96 totalCostJuels; - } - - mapping(uint256 requestNumber => Response) s_responses; - - uint96 s_fulfillmentRouterOwnerBalance = 0; - uint96 s_fulfillmentCoordinatorBalance = 0; - uint8 s_requestsSent = 0; - uint8 s_requestsFulfilled = 0; - - function setUp() public virtual override { - FunctionsSubscriptionSetup.setUp(); - - // Send request #1 - string memory sourceCode = "return 'hello world';"; - bytes memory secrets = new bytes(0); - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - uint32 callbackGasLimit = 5500; - _sendAndStoreRequest(1, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - } - - /// @notice Predicts the estimated cost (maximum cost) of a request - /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee - function _getExpectedCostEstimate(uint256 callbackGas) internal view returns (uint96) { - uint256 gasPrice = TX_GASPRICE_START < getCoordinatorConfig().minimumEstimateGasPriceWei - ? getCoordinatorConfig().minimumEstimateGasPriceWei - : TX_GASPRICE_START; - uint256 gasPriceWithOverestimation = gasPrice + - ((gasPrice * getCoordinatorConfig().fulfillmentGasPriceOverEstimationBP) / 10_000); - uint96 juelsPerGas = uint96((1e18 * gasPriceWithOverestimation) / uint256(LINK_ETH_RATE)); - uint96 gasOverheadJuels = juelsPerGas * - ((getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback)); - uint96 callbackGasCostJuels = uint96(juelsPerGas * callbackGas); - bytes memory emptyData = new bytes(0); - return - gasOverheadJuels + - s_functionsCoordinator.getDONFeeJuels(emptyData) + - s_adminFee + - s_functionsCoordinator.getOperationFeeJuels() + - callbackGasCostJuels; - } - - /// @notice Predicts the actual cost of a request - /// @dev Meant only for Ethereum, does not add L2 chains' L1 fee - function _getExpectedCost(uint256 gasUsed) internal view returns (uint96) { - uint96 juelsPerGas = uint96((1e18 * TX_GASPRICE_START) / uint256(LINK_ETH_RATE)); - uint96 gasOverheadJuels = juelsPerGas * - (getCoordinatorConfig().gasOverheadBeforeCallback + getCoordinatorConfig().gasOverheadAfterCallback); - uint96 callbackGasCostJuels = uint96(juelsPerGas * gasUsed); - bytes memory emptyData = new bytes(0); - return - gasOverheadJuels + - s_functionsCoordinator.getDONFeeJuels(emptyData) + - s_adminFee + - s_functionsCoordinator.getOperationFeeJuels() + - callbackGasCostJuels; - } - - /// @notice Send a request and store information about it in s_requests - /// @param requestNumberKey - the key that the request will be stored in `s_requests` in - /// @param sourceCode - Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted - /// @param secrets - Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) - /// @param args - String arguments that will be passed into the source code - /// @param bytesArgs - Bytes arguments that will be passed into the source code - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @param client - The consumer contract to send the request from - function _sendAndStoreRequest( - uint256 requestNumberKey, - string memory sourceCode, - bytes memory secrets, - string[] memory args, - bytes[] memory bytesArgs, - uint32 callbackGasLimit, - address client - ) internal { - if (s_requests[requestNumberKey].requestId != bytes32(0)) { - revert("Request already written"); - } - - vm.recordLogs(); - - bytes32 requestId = FunctionsClientHarness(client).sendRequest( - s_donId, - sourceCode, - secrets, - args, - bytesArgs, - s_subscriptionId, - callbackGasLimit - ); - - // Get commitment data from OracleRequest event log - Vm.Log[] memory entries = vm.getRecordedLogs(); - (, , , , , , , FunctionsResponse.Commitment memory commitment) = abi.decode( - entries[0].data, - (address, uint64, address, bytes, uint16, bytes32, uint64, FunctionsResponse.Commitment) - ); - s_requests[requestNumberKey] = Request({ - requestData: RequestData({ - sourceCode: sourceCode, - secrets: secrets, - args: args, - bytesArgs: bytesArgs, - callbackGasLimit: callbackGasLimit - }), - requestId: requestId, - commitment: commitment, // Has operationFee in place of adminFee - commitmentOnchain: FunctionsResponse.Commitment({ - coordinator: commitment.coordinator, - client: commitment.client, - subscriptionId: commitment.subscriptionId, - callbackGasLimit: commitment.callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, - adminFee: s_adminFee - }) - }); - s_requestsSent += 1; - } - - /// @notice Send a request and store information about it in s_requests - /// @param requestNumberKey - the key that the request will be stored in `s_requests` in - /// @param sourceCode - Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted - /// @param secrets - Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) - /// @param args - String arguments that will be passed into the source code - /// @param bytesArgs - Bytes arguments that will be passed into the source code - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @dev @param client - The consumer contract to send the request from (overloaded to fill client with s_functionsClient) - function _sendAndStoreRequest( - uint256 requestNumberKey, - string memory sourceCode, - bytes memory secrets, - string[] memory args, - bytes[] memory bytesArgs, - uint32 callbackGasLimit - ) internal { - _sendAndStoreRequest( - requestNumberKey, - sourceCode, - secrets, - args, - bytesArgs, - callbackGasLimit, - address(s_functionsClient) - ); - } - - function _buildReport( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors - ) internal view returns (bytes memory report, bytes32[3] memory reportContext) { - // Build report - bytes32[] memory _requestIds = new bytes32[](requestNumberKeys.length); - bytes[] memory _results = new bytes[](requestNumberKeys.length); - bytes[] memory _errors = new bytes[](requestNumberKeys.length); - bytes[] memory _onchainMetadata = new bytes[](requestNumberKeys.length); - bytes[] memory _offchainMetadata = new bytes[](requestNumberKeys.length); - for (uint256 i = 0; i < requestNumberKeys.length; ++i) { - if (keccak256(bytes(results[i])) != keccak256(new bytes(0)) && keccak256(errors[i]) != keccak256(new bytes(0))) { - revert("Report can only contain a result OR an error, one must remain empty."); - } - _requestIds[i] = s_requests[requestNumberKeys[i]].requestId; - _results[i] = bytes(results[i]); - _errors[i] = errors[i]; - _onchainMetadata[i] = abi.encode(s_requests[requestNumberKeys[i]].commitment); - _offchainMetadata[i] = new bytes(0); // No off-chain metadata - } - report = abi.encode(_requestIds, _results, _errors, _onchainMetadata, _offchainMetadata); - - // Build report context - uint256 h = uint256( - keccak256( - abi.encode( - block.chainid, - address(s_functionsCoordinator), - 1, - s_signers, - s_transmitters, - s_f, - s_onchainConfig, - s_offchainConfigVersion, - s_offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - bytes32 configDigest = bytes32((prefix & prefixMask) | (h & ~prefixMask)); - reportContext = [configDigest, configDigest, configDigest]; - - return (report, reportContext); - } - - /// @notice Gather signatures on report data - /// @param report - Report bytes generated from `_buildReport` - /// @param reportContext - Report context bytes32 generated from `_buildReport` - /// @param signerPrivateKeys - One or more addresses that will sign the report data - /// @return rawRs - Signature rs - /// @return rawSs - Signature ss - /// @return rawVs - Signature vs - function _signReport( - bytes memory report, - bytes32[3] memory reportContext, - uint256[] memory signerPrivateKeys - ) internal pure returns (bytes32[] memory, bytes32[] memory, bytes32) { - bytes32[] memory rs = new bytes32[](signerPrivateKeys.length); - bytes32[] memory ss = new bytes32[](signerPrivateKeys.length); - bytes memory vs = new bytes(signerPrivateKeys.length); - - bytes32 reportDigest = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - for (uint256 i = 0; i < signerPrivateKeys.length; i++) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPrivateKeys[i], reportDigest); - rs[i] = r; - ss[i] = s; - vs[i] = bytes1(v - 27); - } - - return (rs, ss, bytes32(vs)); - } - - function _buildAndSignReport( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors - ) internal view returns (Report memory) { - (bytes memory report, bytes32[3] memory reportContext) = _buildReport(requestNumberKeys, results, errors); - - // Sign the report - // Need at least 3 signers to fulfill minimum number of: (configInfo.n + configInfo.f) / 2 + 1 - uint256[] memory signerPrivateKeys = new uint256[](3); - signerPrivateKeys[0] = NOP_SIGNER_PRIVATE_KEY_1; - signerPrivateKeys[1] = NOP_SIGNER_PRIVATE_KEY_2; - signerPrivateKeys[2] = NOP_SIGNER_PRIVATE_KEY_3; - (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) = _signReport( - report, - reportContext, - signerPrivateKeys - ); - - return Report({report: report, reportContext: reportContext, rs: rawRs, ss: rawSs, vs: rawVs}); - } - - /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin - /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report - /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param transmitter - The address that will send the `.report` transaction - /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. - /// @param requestProcessedStartIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) - /// @param transmitterGasToUse - Override the default amount of gas that the transmitter sends the `.report` transaction with - function _reportAndStore( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors, - address transmitter, - bool expectedToSucceed, - uint8 requestProcessedStartIndex, - uint256 transmitterGasToUse - ) internal { - { - if (requestNumberKeys.length != results.length || requestNumberKeys.length != errors.length) { - revert("_reportAndStore arguments length mismatch"); - } - } - - Report memory r = _buildAndSignReport(requestNumberKeys, results, errors); - - // Send as transmitter - vm.stopPrank(); - vm.startPrank(transmitter, transmitter); - - // Send report - vm.recordLogs(); - if (transmitterGasToUse > 0) { - s_functionsCoordinator.transmit{gas: transmitterGasToUse}(r.reportContext, r.report, r.rs, r.ss, r.vs); - } else { - s_functionsCoordinator.transmit(r.reportContext, r.report, r.rs, r.ss, r.vs); - } - - if (expectedToSucceed) { - // Get actual cost from RequestProcessed event log - (uint96 totalCostJuels, , , , , ) = abi.decode( - vm.getRecordedLogs()[requestProcessedStartIndex].data, - (uint96, address, FunctionsResponse.FulfillResult, bytes, bytes, bytes) - ); - // Store response of first request - // TODO: handle multiple requests - s_responses[requestNumberKeys[0]] = Response({totalCostJuels: totalCostJuels}); - // Store profit amounts - s_fulfillmentRouterOwnerBalance += s_adminFee * uint96(requestNumberKeys.length); - // totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels - // TODO: handle multiple requests - s_fulfillmentCoordinatorBalance += totalCostJuels - s_adminFee; - } - s_requestsFulfilled += 1; - - // Return prank to Owner - vm.stopPrank(); - vm.startPrank(OWNER_ADDRESS, OWNER_ADDRESS); - } - - /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin - /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report - /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param transmitter - The address that will send the `.report` transaction - /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. - /// @param requestProcessedIndex - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) - /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas - function _reportAndStore( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors, - address transmitter, - bool expectedToSucceed, - uint8 requestProcessedIndex - ) internal { - _reportAndStore(requestNumberKeys, results, errors, transmitter, expectedToSucceed, requestProcessedIndex, 0); - } - - /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin - /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report - /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param transmitter - The address that will send the `.report` transaction - /// @param expectedToSucceed - Boolean representing if the report transmission is expected to produce a RequestProcessed event for every fulfillment. If not, we ignore retrieving the event log. - /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) - /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas - function _reportAndStore( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors, - address transmitter, - bool expectedToSucceed - ) internal { - _reportAndStore(requestNumberKeys, results, errors, transmitter, expectedToSucceed, 3); - } - - /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin - /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report - /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param transmitter - The address that will send the `.report` transaction - /// @dev @param expectedToSucceed is overloaded to give the value as true - The report transmission is expected to produce a RequestProcessed event for every fulfillment - /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) - /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas - function _reportAndStore( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors, - address transmitter - ) internal { - _reportAndStore(requestNumberKeys, results, errors, transmitter, true); - } - - /// @notice Provide a response from the DON to fulfill one or more requests and store the updated balances of the DON & Admin - /// @param requestNumberKeys - One or more requestNumberKeys that were used to store the request in `s_requests` of the requests, that will be added to the report - /// @param results - The result that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @param errors - The error that will be sent to the consumer contract's callback. For each index, e.g. result[index] or errors[index], only one of should be filled. - /// @dev @param transmitter is overloaded to give the value of transmitter #1 - The address that will send the `.report` transaction - /// @dev @param expectedToSucceed is overloaded to give the value as true - The report transmission is expected to produce a RequestProcessed event for every fulfillment - /// @dev @param requestProcessedIndex is overloaded to give requestProcessedIndex as 3 (happy path value)] - On a successful fulfillment the Router will emit a RequestProcessed event. To grab that event we must know the order at which this event was thrown in the report transmission lifecycle. This can change depending on the test setup (e.g. the Client contract gives an extra event during its callback) - /// @dev @param transmitterGasToUse is overloaded to give transmitterGasToUse as 0] - Sends the `.report` transaction with the default amount of gas - function _reportAndStore( - uint256[] memory requestNumberKeys, - string[] memory results, - bytes[] memory errors - ) internal { - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1); - } -} - -/// @notice Set up to have transmitter #1 send a report that fulfills request #1 -contract FunctionsFulfillmentSetup is FunctionsClientRequestSetup { - function setUp() public virtual override { - FunctionsClientRequestSetup.setUp(); - - // Fast forward time by 30 seconds to simulate the DON executing the computation - vm.warp(block.timestamp + 30); - - // Fulfill request 1 - uint256[] memory requestNumberKeys = new uint256[](1); - requestNumberKeys[0] = 1; - string[] memory results = new string[](1); - results[0] = "hello world!"; - bytes[] memory errors = new bytes[](1); - errors[0] = new bytes(0); - - _reportAndStore(requestNumberKeys, results, errors, NOP_TRANSMITTER_ADDRESS_1, true); - } -} - -/// @notice Set up to send and fulfill two more requests, s_request[2] reported by transmitter #2 and s_request[3] reported by transmitter #3 -contract FunctionsMultipleFulfillmentsSetup is FunctionsFulfillmentSetup { - function setUp() public virtual override { - FunctionsFulfillmentSetup.setUp(); - - // Make 3 additional requests (1 already complete) - - // *** Request #2 *** - // Send - string memory sourceCode = "return 'hello world';"; - bytes memory secrets = new bytes(0); - string[] memory args = new string[](0); - bytes[] memory bytesArgs = new bytes[](0); - uint32 callbackGasLimit = 5500; - _sendAndStoreRequest(2, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - // Fulfill as transmitter #2 - uint256[] memory requestNumberKeys1 = new uint256[](1); - requestNumberKeys1[0] = 2; - string[] memory results1 = new string[](1); - results1[0] = "hello world!"; - bytes[] memory errors1 = new bytes[](1); - errors1[0] = new bytes(0); - _reportAndStore(requestNumberKeys1, results1, errors1, NOP_TRANSMITTER_ADDRESS_2, true); - - // *** Request #3 *** - // Send - _sendAndStoreRequest(3, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - // Fulfill as transmitter #3 - uint256[] memory requestNumberKeys2 = new uint256[](1); - requestNumberKeys2[0] = 3; - string[] memory results2 = new string[](1); - results2[0] = "hello world!"; - bytes[] memory errors2 = new bytes[](1); - errors2[0] = new bytes(0); - _reportAndStore(requestNumberKeys2, results2, errors2, NOP_TRANSMITTER_ADDRESS_3, true); - - // *** Request #4 *** - // Send - _sendAndStoreRequest(4, sourceCode, secrets, args, bytesArgs, callbackGasLimit); - // Fulfill as transmitter #1 - uint256[] memory requestNumberKeys3 = new uint256[](1); - requestNumberKeys3[0] = 4; - string[] memory results3 = new string[](1); - results3[0] = "hello world!"; - bytes[] memory errors3 = new bytes[](1); - errors3[0] = new bytes(0); - _reportAndStore(requestNumberKeys3, results3, errors3, NOP_TRANSMITTER_ADDRESS_1, true); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol deleted file mode 100644 index f0cb396..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientHarness.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsClientUpgradeHelper} from "./FunctionsClientUpgradeHelper.sol"; -import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol"; - -/// @title Functions Client Test Harness -/// @notice Contract to expose internal functions for testing purposes -contract FunctionsClientHarness is FunctionsClientUpgradeHelper { - constructor(address router) FunctionsClientUpgradeHelper(router) {} - - function getRouter_HARNESS() external view returns (address) { - return address(i_functionsRouter); - } - - function sendRequest_HARNESS( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) external returns (bytes32) { - return super._sendRequest(data, subscriptionId, callbackGasLimit, donId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol deleted file mode 100644 index c300f4d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITermsOfServiceAllowList} from "../../../dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol"; -import {IFunctionsSubscriptions} from "../../../dev/v1_X/interfaces/IFunctionsSubscriptions.sol"; - -import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; - -contract FunctionsClientTestHelper is FunctionsClient { - using FunctionsRequest for FunctionsRequest.Request; - - event SendRequestInvoked(bytes32 requestId, string sourceCode, uint64 subscriptionId); - event FulfillRequestInvoked(bytes32 requestId, bytes response, bytes err); - - bool private s_revertFulfillRequest; - string private s_revertFulfillRequestMessage = "asked to revert"; - bool private s_doInvalidOperation; - bool private s_doInvalidReentrantOperation; - bool private s_doValidReentrantOperation; - - uint64 private s_subscriptionId; - bytes32 private s_donId; - - constructor(address router) FunctionsClient(router) {} - - function sendRequest( - bytes32 donId, - string calldata source, - bytes calldata secrets, - string[] calldata args, - bytes[] memory bytesArgs, - uint64 subscriptionId, - uint32 callbackGasLimit - ) public returns (bytes32 requestId) { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - if (secrets.length > 0) req._addSecretsReference(secrets); - if (args.length > 0) req._setArgs(args); - if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); - - return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); - } - - function sendSimpleRequestWithJavaScript( - string memory sourceCode, - uint64 subscriptionId, - bytes32 donId, - uint32 callbackGasLimit - ) public returns (bytes32 requestId) { - FunctionsRequest.Request memory request; - request._initializeRequestForInlineJavaScript(sourceCode); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - requestId = _sendRequest(requestData, subscriptionId, callbackGasLimit, donId); - emit SendRequestInvoked(requestId, sourceCode, subscriptionId); - } - - function sendRequestProposed( - string memory sourceCode, - uint64 subscriptionId, - bytes32 donId - ) public returns (bytes32 requestId) { - FunctionsRequest.Request memory request; - uint32 callbackGasLimit = 20_000; - request._initializeRequestForInlineJavaScript(sourceCode); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - requestId = i_functionsRouter.sendRequestToProposed( - subscriptionId, - requestData, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - donId - ); - emit RequestSent(requestId); - emit SendRequestInvoked(requestId, sourceCode, subscriptionId); - } - - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external { - bytes32 allowListId = i_functionsRouter.getAllowListId(); - ITermsOfServiceAllowList allowList = ITermsOfServiceAllowList(i_functionsRouter.getContractById(allowListId)); - allowList.acceptTermsOfService(acceptor, recipient, r, s, v); - } - - function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external { - IFunctionsSubscriptions(address(i_functionsRouter)).acceptSubscriptionOwnerTransfer(subscriptionId); - } - - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { - if (s_revertFulfillRequest) { - revert(s_revertFulfillRequestMessage); - } - if (s_doInvalidOperation) { - uint256 x = 1; - uint256 y = 0; - x = x / y; - } - if (s_doValidReentrantOperation) { - sendSimpleRequestWithJavaScript("somedata", s_subscriptionId, s_donId, 20_000); - } - if (s_doInvalidReentrantOperation) { - IFunctionsSubscriptions(address(i_functionsRouter)).cancelSubscription(s_subscriptionId, msg.sender); - } - emit FulfillRequestInvoked(requestId, response, err); - } - - function setRevertFulfillRequest(bool on) external { - s_revertFulfillRequest = on; - } - - function setRevertFulfillRequestMessage(string memory message) external { - s_revertFulfillRequestMessage = message; - } - - function setDoInvalidOperation(bool on) external { - s_doInvalidOperation = on; - } - - function setDoInvalidReentrantOperation(bool on, uint64 subscriptionId) external { - s_doInvalidReentrantOperation = on; - s_subscriptionId = subscriptionId; - } - - function setDoValidReentrantOperation(bool on, uint64 subscriptionId, bytes32 donId) external { - s_doValidReentrantOperation = on; - s_subscriptionId = subscriptionId; - s_donId = donId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol deleted file mode 100644 index e0f636e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientUpgradeHelper.sol +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; -import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; - -contract FunctionsClientUpgradeHelper is FunctionsClient, ConfirmedOwner { - using FunctionsRequest for FunctionsRequest.Request; - - constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} - - event ResponseReceived(bytes32 indexed requestId, bytes result, bytes err); - - /** - * @notice Send a simple request - * - * @param donId DON ID - * @param source JavaScript source code - * @param secrets Encrypted secrets payload - * @param args List of arguments accessible from within the source code - * @param subscriptionId Funtions billing subscription ID - * @param callbackGasLimit Maximum amount of gas used to call the client contract's `handleOracleFulfillment` function - * @return Functions request ID - */ - function sendRequest( - bytes32 donId, - string calldata source, - bytes calldata secrets, - string[] calldata args, - bytes[] memory bytesArgs, - uint64 subscriptionId, - uint32 callbackGasLimit - ) public onlyOwner returns (bytes32) { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - if (secrets.length > 0) req._addSecretsReference(secrets); - if (args.length > 0) req._setArgs(args); - if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); - - return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); - } - - function sendRequestBytes( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) public returns (bytes32 requestId) { - return _sendRequest(data, subscriptionId, callbackGasLimit, donId); - } - - /** - * @notice Same as sendRequest but for DONHosted secrets - */ - function sendRequestWithDONHostedSecrets( - bytes32 donId, - string calldata source, - uint8 slotId, - uint64 slotVersion, - string[] calldata args, - uint64 subscriptionId, - uint32 callbackGasLimit - ) public onlyOwner returns (bytes32) { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - req._addDONHostedSecrets(slotId, slotVersion); - - if (args.length > 0) req._setArgs(args); - - return _sendRequest(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); - } - - // @notice Sends a Chainlink Functions request - // @param data The CBOR encoded bytes data for a Functions request - // @param subscriptionId The subscription ID that will be charged to service the request - // @param callbackGasLimit the amount of gas that will be available for the fulfillment callback - // @return requestId The generated request ID for this request - function _sendRequestToProposed( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) internal returns (bytes32) { - bytes32 requestId = i_functionsRouter.sendRequestToProposed( - subscriptionId, - data, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - donId - ); - emit RequestSent(requestId); - return requestId; - } - - /** - * @notice Send a simple request to the proposed contract - * - * @param donId DON ID - * @param source JavaScript source code - * @param secrets Encrypted secrets payload - * @param args List of arguments accessible from within the source code - * @param subscriptionId Funtions billing subscription ID - * @param callbackGasLimit Maximum amount of gas used to call the client contract's `handleOracleFulfillment` function - * @return Functions request ID - */ - function sendRequestToProposed( - bytes32 donId, - string calldata source, - bytes calldata secrets, - string[] calldata args, - bytes[] memory bytesArgs, - uint64 subscriptionId, - uint32 callbackGasLimit - ) public onlyOwner returns (bytes32) { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - if (secrets.length > 0) req._addSecretsReference(secrets); - if (args.length > 0) req._setArgs(args); - if (bytesArgs.length > 0) req._setBytesArgs(bytesArgs); - - return _sendRequestToProposed(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); - } - - /** - * @notice Same as sendRequestToProposed but for DONHosted secrets - */ - function sendRequestToProposedWithDONHostedSecrets( - bytes32 donId, - string calldata source, - uint8 slotId, - uint64 slotVersion, - string[] calldata args, - uint64 subscriptionId, - uint32 callbackGasLimit - ) public onlyOwner returns (bytes32) { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - req._addDONHostedSecrets(slotId, slotVersion); - - if (args.length > 0) req._setArgs(args); - - return _sendRequestToProposed(FunctionsRequest._encodeCBOR(req), subscriptionId, callbackGasLimit, donId); - } - - /** - * @notice Callback that is invoked once the DON has resolved the request or hit an error - * - * @param requestId The request ID, returned by sendRequest() - * @param response Aggregated response from the user code - * @param err Aggregated error from the user code or from the execution pipeline - * Either response or error parameter will be set, but never both - */ - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { - emit ResponseReceived(requestId, response, err); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol deleted file mode 100644 index e567471..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; -import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; - -contract FunctionsClientWithEmptyCallback is FunctionsClient { - using FunctionsRequest for FunctionsRequest.Request; - - event SendRequestInvoked(bytes32 requestId, string sourceCode, uint64 subscriptionId); - event FulfillRequestInvoked(bytes32 requestId, bytes response, bytes err); - - constructor(address router) FunctionsClient(router) {} - - function sendSimpleRequestWithJavaScript( - string memory sourceCode, - uint64 subscriptionId, - bytes32 donId, - uint32 callbackGasLimit - ) public returns (bytes32 requestId) { - FunctionsRequest.Request memory request; - request._initializeRequestForInlineJavaScript(sourceCode); - bytes memory requestData = FunctionsRequest._encodeCBOR(request); - requestId = _sendRequest(requestData, subscriptionId, callbackGasLimit, donId); - emit SendRequestInvoked(requestId, sourceCode, subscriptionId); - } - - function _fulfillRequest(bytes32 /*requestId*/, bytes memory /*response*/, bytes memory /*err*/) internal override { - // Do nothing - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol deleted file mode 100644 index 0de449f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorHarness.sol +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol"; -import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsResponse} from "../../../dev/v1_X/libraries/FunctionsResponse.sol"; -import {FunctionsBillingConfig} from "../../../dev/v1_X/interfaces/IFunctionsBilling.sol"; - -/// @title Functions Coordinator Test Harness -/// @notice Contract to expose internal functions for testing purposes -contract FunctionsCoordinatorHarness is FunctionsCoordinator { - address s_linkToNativeFeed_HARNESS; - address s_linkToUsdFeed_HARNESS; - address s_router_HARNESS; - - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) FunctionsCoordinator(router, config, linkToNativeFeed, linkToUsdFeed) { - s_linkToNativeFeed_HARNESS = linkToNativeFeed; - s_linkToUsdFeed_HARNESS = linkToUsdFeed; - s_router_HARNESS = router; - } - - function isTransmitter_HARNESS(address node) external view returns (bool) { - return super._isTransmitter(node); - } - - function beforeSetConfig_HARNESS(uint8 _f, bytes memory _onchainConfig) external { - return super._beforeSetConfig(_f, _onchainConfig); - } - - /// @dev Used by FunctionsBilling.sol - function getTransmitters_HARNESS() external view returns (address[] memory) { - return super._getTransmitters(); - } - - function report_HARNESS(DecodedReport memory decodedReport) external { - return super._report(decodedReport); - } - - function onlyOwner_HARNESS() external view { - return super._onlyOwner(); - } - - // ================================================================ - // | Functions Billing | - // ================================================================ - - function getLinkToNativeFeed_HARNESS() external view returns (address) { - return s_linkToNativeFeed_HARNESS; - } - - function getLinkToUsdFeed_HARNESS() external view returns (address) { - return s_linkToUsdFeed_HARNESS; - } - - function getRouter_HARNESS() external view returns (address) { - return s_router_HARNESS; - } - - function calculateCostEstimate_HARNESS( - uint32 callbackGasLimit, - uint256 gasPriceWei, - uint72 donFee, - uint72 adminFee, - uint72 operationFee - ) external view returns (uint96) { - return super._calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); - } - - function startBilling_HARNESS( - FunctionsResponse.RequestMeta memory request - ) external returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { - return super._startBilling(request); - } - - function fulfillAndBill_HARNESS( - bytes32 requestId, - bytes memory response, - bytes memory err, - bytes memory onchainMetadata, - bytes memory offchainMetadata, - uint8 reportBatchSize - ) external returns (FunctionsResponse.FulfillResult) { - return super._fulfillAndBill(requestId, response, err, onchainMetadata, offchainMetadata, reportBatchSize); - } - - function disperseFeePool_HARNESS() external { - return super._disperseFeePool(); - } - - function owner_HARNESS() external view returns (address owner) { - return super._owner(); - } - - // ================================================================ - // | OCR2 | - // ================================================================ - - function configDigestFromConfigData_HARNESS( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - return - super._configDigestFromConfigData( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol deleted file mode 100644 index 8703d2b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsCoordinator} from "../../../dev/v1_X/FunctionsCoordinator.sol"; -import {FunctionsBilling} from "../../../dev/v1_X/FunctionsBilling.sol"; -import {FunctionsBillingConfig} from "../../../dev/v1_X/interfaces/IFunctionsBilling.sol"; - -contract FunctionsCoordinatorTestHelper is FunctionsCoordinator { - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) FunctionsCoordinator(router, config, linkToNativeFeed, linkToUsdFeed) {} - - function callReport(bytes calldata report) external { - address[MAX_NUM_ORACLES] memory signers; - signers[0] = msg.sender; - ( - bytes32[] memory requestIds, - bytes[] memory results, - bytes[] memory errors, - bytes[] memory onchainMetadata, - bytes[] memory offchainMetadata - ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); - _report( - DecodedReport({ - requestIds: requestIds, - results: results, - errors: errors, - onchainMetadata: onchainMetadata, - offchainMetadata: offchainMetadata - }) - ); - } - - function callReportMultipleSigners(bytes calldata report, address secondSigner) external { - address[MAX_NUM_ORACLES] memory signers; - signers[0] = msg.sender; - signers[1] = secondSigner; - ( - bytes32[] memory requestIds, - bytes[] memory results, - bytes[] memory errors, - bytes[] memory onchainMetadata, - bytes[] memory offchainMetadata - ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); - _report( - DecodedReport({ - requestIds: requestIds, - results: results, - errors: errors, - onchainMetadata: onchainMetadata, - offchainMetadata: offchainMetadata - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol deleted file mode 100644 index 1623fc5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsLoadTestClient.sol +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsClient} from "../../../dev/v1_X/FunctionsClient.sol"; -import {ConfirmedOwner} from "../../../../shared/access/ConfirmedOwner.sol"; -import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; - -/** - * @title Chainlink Functions load test client implementation - */ -contract FunctionsLoadTestClient is FunctionsClient, ConfirmedOwner { - using FunctionsRequest for FunctionsRequest.Request; - - uint32 public constant MAX_CALLBACK_GAS = 250_000; - - bytes32 public lastRequestID; - bytes public lastResponse; - bytes public lastError; - uint32 public totalRequests; - uint32 public totalEmptyResponses; - uint32 public totalSucceededResponses; - uint32 public totalFailedResponses; - - constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} - - /** - * @notice Send a simple request - * @param times Number of times to send the request - * @param source JavaScript source code - * @param encryptedSecretsReferences Encrypted secrets payload - * @param args List of arguments accessible from within the source code - * @param subscriptionId Billing ID - * @param donId DON ID - */ - function sendRequest( - uint32 times, - string calldata source, - bytes calldata encryptedSecretsReferences, - string[] calldata args, - uint64 subscriptionId, - bytes32 donId - ) external onlyOwner { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - if (encryptedSecretsReferences.length > 0) req._addSecretsReference(encryptedSecretsReferences); - if (args.length > 0) req._setArgs(args); - uint i = 0; - for (i = 0; i < times; i++) { - lastRequestID = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, donId); - totalRequests += 1; - } - } - - /** - * @notice Same as sendRequest but for DONHosted secrets - * @param times Number of times to send the request - * @param source JavaScript source code - * @param slotId DON hosted secrets slot ID - * @param slotVersion DON hosted secrets slot version - * @param args List of arguments accessible from within the source code - * @param subscriptionId Billing ID - * @param donId DON ID - */ - function sendRequestWithDONHostedSecrets( - uint32 times, - string calldata source, - uint8 slotId, - uint64 slotVersion, - string[] calldata args, - uint64 subscriptionId, - bytes32 donId - ) public onlyOwner { - FunctionsRequest.Request memory req; - req._initializeRequestForInlineJavaScript(source); - req._addDONHostedSecrets(slotId, slotVersion); - if (args.length > 0) req._setArgs(args); - uint i = 0; - for (i = 0; i < times; i++) { - lastRequestID = _sendRequest(req._encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, donId); - totalRequests += 1; - } - } - - /** - * @notice Sends a Chainlink Functions request that has already been CBOR encoded - * @param times Number of times to send the request - * @param cborEncodedRequest The CBOR encoded bytes data for a Functions request - * @param subscriptionId The subscription ID that will be charged to service the request - * @param donId DON ID - */ - function sendEncodedRequest( - uint32 times, - bytes memory cborEncodedRequest, - uint64 subscriptionId, - bytes32 donId - ) public onlyOwner { - uint i = 0; - for (i = 0; i < times; i++) { - lastRequestID = _sendRequest(cborEncodedRequest, subscriptionId, MAX_CALLBACK_GAS, donId); - totalRequests += 1; - } - } - - function resetStats() external onlyOwner { - lastRequestID = ""; - lastResponse = ""; - lastError = ""; - totalRequests = 0; - totalSucceededResponses = 0; - totalFailedResponses = 0; - totalEmptyResponses = 0; - } - - function getStats() - public - view - onlyOwner - returns (bytes32, bytes memory, bytes memory, uint32, uint32, uint32, uint32) - { - return ( - lastRequestID, - lastResponse, - lastError, - totalRequests, - totalSucceededResponses, - totalFailedResponses, - totalEmptyResponses - ); - } - - /** - * @notice Store latest result/error - * @param requestId The request ID, returned by sendRequest() - * @param response Aggregated response from the user code - * @param err Aggregated error from the user code or from the execution pipeline - * Either response or error parameter will be set, but never both - */ - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { - lastRequestID = requestId; - lastResponse = response; - lastError = err; - if (response.length == 0) { - totalEmptyResponses += 1; - } - if (err.length != 0) { - totalFailedResponses += 1; - } - if (response.length != 0 && err.length == 0) { - totalSucceededResponses += 1; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol deleted file mode 100644 index 7caeff4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsRouterHarness.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRouter} from "../../../dev/v1_X/FunctionsRouter.sol"; - -/// @title Functions Router Test Harness -/// @notice Contract to expose internal functions for testing purposes -contract FunctionsRouterHarness is FunctionsRouter { - constructor(address linkToken, Config memory config) FunctionsRouter(linkToken, config) {} - - function getMaxConsumers_HARNESS() external view returns (uint16) { - return super._getMaxConsumers(); - } - - function getSubscriptionDepositDetails_HARNESS() external view returns (uint16, uint72) { - return super._getSubscriptionDepositDetails(); - } - - function whenNotPaused_HARNESS() external view { - return super._whenNotPaused(); - } - - function onlyRouterOwner_HARNESS() external view { - return super._onlyRouterOwner(); - } - - function onlySenderThatAcceptedToS_HARNESS() external view { - return super._onlySenderThatAcceptedToS(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol deleted file mode 100644 index 2e2427f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsSubscriptionsHarness.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsSubscriptions} from "../../../dev/v1_X/FunctionsSubscriptions.sol"; - -/// @title Functions Subscriptions Test Harness -/// @notice Contract to expose internal functions for testing purposes -contract FunctionsSubscriptionsHarness is FunctionsSubscriptions { - constructor(address link) FunctionsSubscriptions(link) {} - - function markRequestInFlight_HARNESS(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) external { - return super._markRequestInFlight(client, subscriptionId, estimatedTotalCostJuels); - } - - function pay_HARNESS( - uint64 subscriptionId, - uint96 estimatedTotalCostJuels, - address client, - uint96 adminFee, - uint96 juelsPerGas, - uint96 gasUsed, - uint96 costWithoutCallbackJuels - ) external returns (Receipt memory) { - return - super._pay( - subscriptionId, - estimatedTotalCostJuels, - client, - adminFee, - juelsPerGas, - gasUsed, - costWithoutCallbackJuels - ); - } - - function isExistingSubscription_HARNESS(uint64 subscriptionId) external view { - return super._isExistingSubscription(subscriptionId); - } - - function isAllowedConsumer_HARNESS(address client, uint64 subscriptionId) external view { - return super._isAllowedConsumer(client, subscriptionId); - } - - // Overrides - function _getMaxConsumers() internal view override returns (uint16) {} - - function _getSubscriptionDepositDetails() internal override returns (uint16, uint72) {} - - function _onlySenderThatAcceptedToS() internal override {} - - function _onlyRouterOwner() internal override {} - - function _whenNotPaused() internal override {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol deleted file mode 100644 index 50e90c4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsRequest} from "../../../dev/v1_X/libraries/FunctionsRequest.sol"; - -contract FunctionsTestHelper { - using FunctionsRequest for FunctionsRequest.Request; - - FunctionsRequest.Request private s_req; - - event RequestData(bytes data); - - function closeEvent() public { - emit RequestData(s_req._encodeCBOR()); - } - - function initializeRequestForInlineJavaScript(string memory sourceCode) public { - FunctionsRequest.Request memory r; - r._initializeRequestForInlineJavaScript(sourceCode); - storeRequest(r); - } - - function addSecretsReference(bytes memory secrets) public { - FunctionsRequest.Request memory r = s_req; - r._addSecretsReference(secrets); - storeRequest(r); - } - - function addEmptyArgs() public pure { - FunctionsRequest.Request memory r; - string[] memory args; - r._setArgs(args); - } - - function addTwoArgs(string memory arg1, string memory arg2) public { - string[] memory args = new string[](2); - args[0] = arg1; - args[1] = arg2; - FunctionsRequest.Request memory r = s_req; - r._setArgs(args); - storeRequest(r); - } - - function storeRequest(FunctionsRequest.Request memory r) private { - s_req.codeLocation = r.codeLocation; - s_req.language = r.language; - s_req.source = r.source; - s_req.args = r.args; - s_req.secretsLocation = r.secretsLocation; - s_req.encryptedSecretsReference = r.encryptedSecretsReference; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol deleted file mode 100644 index 8de53dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsBilling.sol +++ /dev/null @@ -1,372 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; - -import {Routable} from "./Routable.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -/// @title Functions Billing contract -/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsBilling is Routable, IFunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei - // ================================================================ - // | Request Commitment state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; - - event CommitmentDeleted(bytes32 requestId); - - // ================================================================ - // | Configuration state | - // ================================================================ - - struct Config { - uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) - uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. - uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. - uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. - uint32 requestTimeoutSeconds; // ║ How many seconds it takes before we consider a request to be timed out - uint72 donFee; // ║ Additional flat fee (in Juels of LINK) that will be split between Node Operators. Max value is 2^80 - 1 == 1.2m LINK. - uint16 maxSupportedRequestDataVersion; // ═══════╝ The highest support request data version supported by the node. All lower versions should also be supported. - uint224 fallbackNativePerUnitLink; // ═══════════╸ fallback NATIVE CURRENCY / LINK conversion rate if the data feed is stale - } - - Config private s_config; - - event ConfigUpdated(Config config); - - error UnsupportedRequestDataVersion(); - error InsufficientBalance(); - error InvalidSubscription(); - error UnauthorizedSender(); - error MustBeSubOwner(address owner); - error InvalidLinkWeiPrice(int256 linkWei); - error PaymentTooLarge(); - error NoTransmittersSet(); - error InvalidCalldata(); - - // ================================================================ - // | Balance state | - // ================================================================ - - mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; - // Pool together collected DON fees - // Disperse them on withdrawal or change in OCR configuration - uint96 internal s_feePool; - - AggregatorV3Interface private s_linkToNativeFeed; - - // ================================================================ - // | Initialization | - // ================================================================ - constructor(address router, Config memory config, address linkToNativeFeed) Routable(router) { - s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); - - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the Chainlink Coordinator's billing configuration - /// @return config - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice Sets the Chainlink Coordinator's billing configuration - /// @param config - See the contents of the Config struct in IFunctionsBilling.Config for more information - function updateConfig(Config memory config) public { - _onlyOwner(); - - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Fee Calculation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function getDONFee(bytes memory /* requestData */) public view override returns (uint72) { - return s_config.donFee; - } - - /// @inheritdoc IFunctionsBilling - function getAdminFee() public view override returns (uint72) { - return _getRouter().getAdminFee(); - } - - /// @inheritdoc IFunctionsBilling - function getWeiPerUnitLink() public view returns (uint256) { - Config memory config = s_config; - (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (config.feedStalenessSeconds < block.timestamp - timestamp && config.feedStalenessSeconds > 0) { - return config.fallbackNativePerUnitLink; - } - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - return uint256(weiPerUnitLink); - } - - function _getJuelsPerGas(uint256 gasPriceWei) private view returns (uint96) { - // (1e18 juels/link) * (wei/gas) / (wei/link) = juels per gas - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((1e18 * gasPriceWei) / getWeiPerUnitLink()); - } - - // ================================================================ - // | Cost Estimation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view override returns (uint96) { - _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - // Reasonable ceilings to prevent integer overflows - if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { - revert InvalidCalldata(); - } - uint72 adminFee = getAdminFee(); - uint72 donFee = getDONFee(data); - return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee); - } - - /// @notice Estimate the cost in Juels of LINK - // that will be charged to a subscription to fulfill a Functions request - // Gas Price can be overestimated to account for flucuations between request and response time - function _calculateCostEstimate( - uint32 callbackGasLimit, - uint256 gasPriceWei, - uint72 donFee, - uint72 adminFee - ) internal view returns (uint96) { - uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit; - - 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 - - uint96 juelsPerGas = _getJuelsPerGas(gasPriceWithOverestimation); - uint256 estimatedGasReimbursement = juelsPerGas * executionGas; - uint96 fees = uint96(donFee) + uint96(adminFee); - - return SafeCast.toUint96(estimatedGasReimbursement + fees); - } - - // ================================================================ - // | Billing | - // ================================================================ - - /// @notice Initiate the billing process for an Functions request - /// @dev Only callable by the Functions Router - /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure - /// @return commitment - The parameters of the request that must be held consistent at response time - function _startBilling( - FunctionsResponse.RequestMeta memory request - ) internal returns (FunctionsResponse.Commitment memory commitment) { - Config memory config = s_config; - - // Nodes should support all past versions of the structure - if (request.dataVersion > config.maxSupportedRequestDataVersion) { - revert UnsupportedRequestDataVersion(); - } - - uint72 donFee = getDONFee(request.data); - uint96 estimatedTotalCostJuels = _calculateCostEstimate( - request.callbackGasLimit, - tx.gasprice, - donFee, - request.adminFee - ); - - // Check that subscription can afford the estimated cost - if ((request.availableBalance) < estimatedTotalCostJuels) { - revert InsufficientBalance(); - } - - bytes32 requestId = _computeRequestId( - address(this), - request.requestingContract, - request.subscriptionId, - request.initiatedRequests + 1 - ); - - commitment = FunctionsResponse.Commitment({ - adminFee: request.adminFee, - coordinator: address(this), - client: request.requestingContract, - subscriptionId: request.subscriptionId, - callbackGasLimit: request.callbackGasLimit, - estimatedTotalCostJuels: estimatedTotalCostJuels, - timeoutTimestamp: uint32(block.timestamp + config.requestTimeoutSeconds), - requestId: requestId, - donFee: donFee, - gasOverheadBeforeCallback: config.gasOverheadBeforeCallback, - gasOverheadAfterCallback: config.gasOverheadAfterCallback - }); - - s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); - - return commitment; - } - - /// @notice Generate a keccak hash request ID - /// @dev uses the number of requests that the consumer of a subscription has sent as a nonce - function _computeRequestId( - address don, - address client, - uint64 subscriptionId, - uint64 nonce - ) private pure returns (bytes32) { - return keccak256(abi.encode(don, client, subscriptionId, nonce)); - } - - /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription - /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @return result fulfillment result - /// @dev Only callable by a node that has been approved on the Coordinator - /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request - function _fulfillAndBill( - bytes32 requestId, - bytes memory response, - bytes memory err, - bytes memory onchainMetadata, - bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */ - ) internal returns (FunctionsResponse.FulfillResult) { - FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); - - if (s_requestCommitments[requestId] == bytes32(0)) { - return FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; - } - - if (s_requestCommitments[requestId] != keccak256(abi.encode(commitment))) { - return FunctionsResponse.FulfillResult.INVALID_COMMITMENT; - } - - uint96 juelsPerGas = _getJuelsPerGas(tx.gasprice); - // Gas overhead without callback - uint96 gasOverheadJuels = juelsPerGas * - (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback); - - // The Functions Router will perform the callback to the client contract - (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( - response, - err, - juelsPerGas, - gasOverheadJuels + commitment.donFee, // costWithoutFulfillment - msg.sender, - commitment - ); - - // The router will only pay the DON on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the Coordinator should hold on to the request commitment - if ( - resultCode == FunctionsResponse.FulfillResult.FULFILLED || - resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - delete s_requestCommitments[requestId]; - // Reimburse the transmitter for the fulfillment gas cost - s_withdrawableTokens[msg.sender] = gasOverheadJuels + callbackCostJuels; - // Put donFee into the pool of fees, to be split later - // Saves on storage writes that would otherwise be charged to the user - s_feePool += commitment.donFee; - } - - return resultCode; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Router - /// @dev Used by FunctionsRouter.sol during timeout of a request - function deleteCommitment(bytes32 requestId) external override onlyRouter { - // Delete commitment - delete s_requestCommitments[requestId]; - emit CommitmentDeleted(requestId); - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function oracleWithdraw(address recipient, uint96 amount) external { - _disperseFeePool(); - - if (amount == 0) { - amount = s_withdrawableTokens[msg.sender]; - } else if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); - } - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Coordinator owner - function oracleWithdrawAll() external { - _onlyOwner(); - _disperseFeePool(); - - address[] memory transmitters = _getTransmitters(); - - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < transmitters.length; ++i) { - uint96 balance = s_withdrawableTokens[transmitters[i]]; - if (balance > 0) { - s_withdrawableTokens[transmitters[i]] = 0; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); - } - } - } - - // Overriden in FunctionsCoordinator, which has visibility into transmitters - function _getTransmitters() internal view virtual returns (address[] memory); - - // DON fees are collected into a pool s_feePool - // When OCR configuration changes, or any oracle withdraws, this must be dispersed - function _disperseFeePool() internal { - if (s_feePool == 0) { - return; - } - // All transmitters are assumed to also be observers - // Pay out the DON fee to all transmitters - address[] memory transmitters = _getTransmitters(); - if (transmitters.length == 0) { - revert NoTransmittersSet(); - } - uint96 feePoolShare = s_feePool / uint96(transmitters.length); - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < transmitters.length; ++i) { - s_withdrawableTokens[transmitters[i]] += feePoolShare; - } - s_feePool -= feePoolShare * uint96(transmitters.length); - } - - // Overriden in FunctionsCoordinator.sol - function _onlyOwner() internal view virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol deleted file mode 100644 index ecbbbd9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; -import {IFunctionsClient} from "./interfaces/IFunctionsClient.sol"; - -import {FunctionsRequest} from "./libraries/FunctionsRequest.sol"; - -/// @title The Chainlink Functions client contract -/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests -abstract contract FunctionsClient is IFunctionsClient { - using FunctionsRequest for FunctionsRequest.Request; - - IFunctionsRouter internal immutable i_router; - - event RequestSent(bytes32 indexed id); - event RequestFulfilled(bytes32 indexed id); - - error OnlyRouterCanFulfill(); - - constructor(address router) { - i_router = IFunctionsRouter(router); - } - - /// @notice Sends a Chainlink Functions request - /// @param data The CBOR encoded bytes data for a Functions request - /// @param subscriptionId The subscription ID that will be charged to service the request - /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback - /// @return requestId The generated request ID for this request - function _sendRequest( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) internal returns (bytes32) { - bytes32 requestId = i_router.sendRequest( - subscriptionId, - data, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - donId - ); - emit RequestSent(requestId); - return requestId; - } - - /// @notice User defined function to handle a response from the DON - /// @param requestId The request ID, returned by sendRequest() - /// @param response Aggregated response from the execution of the user's source code - /// @param err Aggregated error from the execution of the user code or from the execution pipeline - /// @dev Either response or error parameter will be set, but never both - function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; - - /// @inheritdoc IFunctionsClient - function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { - if (msg.sender != address(i_router)) { - revert OnlyRouterCanFulfill(); - } - fulfillRequest(requestId, response, err); - emit RequestFulfilled(requestId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol deleted file mode 100644 index 1488bc4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsCoordinator.sol +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {FunctionsBilling} from "./FunctionsBilling.sol"; -import {OCR2Base} from "./ocr/OCR2Base.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -/// @title Functions Coordinator contract -/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with -contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Coordinator v1.0.0"; - - event OracleRequest( - bytes32 indexed requestId, - address indexed requestingContract, - address requestInitiator, - uint64 subscriptionId, - address subscriptionOwner, - bytes data, - uint16 dataVersion, - bytes32 flags, - uint64 callbackGasLimit, - FunctionsResponse.Commitment commitment - ); - event OracleResponse(bytes32 indexed requestId, address transmitter); - - error InconsistentReportData(); - error EmptyPublicKey(); - error UnauthorizedPublicKeyChange(); - - bytes private s_donPublicKey; - bytes private s_thresholdPublicKey; - - constructor( - address router, - Config memory config, - address linkToNativeFeed - ) OCR2Base(true) FunctionsBilling(router, config, linkToNativeFeed) {} - - /// @inheritdoc IFunctionsCoordinator - function getThresholdPublicKey() external view override returns (bytes memory) { - if (s_thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { - if (thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_thresholdPublicKey = thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function getDONPublicKey() external view override returns (bytes memory) { - if (s_donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_donPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { - if (donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_donPublicKey = donPublicKey; - } - - /// @dev check if node is in current transmitter list - function _isTransmitter(address node) internal view returns (bool) { - address[] memory nodes = s_transmitters; - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < nodes.length; ++i) { - if (nodes[i] == node) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsCoordinator - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { - commitment = _startBilling(request); - - emit OracleRequest( - commitment.requestId, - request.requestingContract, - tx.origin, - request.subscriptionId, - request.subscriptionOwner, - request.data, - request.dataVersion, - request.flags, - request.callbackGasLimit, - commitment - ); - - return commitment; - } - - /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. - function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { - if (_getTransmitters().length > 0) { - _disperseFeePool(); - } - } - - /// @dev Used by FunctionsBilling.sol - function _getTransmitters() internal view override returns (address[] memory) { - return s_transmitters; - } - - /// @dev Report hook called within OCR2Base.sol - function _report( - uint256 /*initialGas*/, - address /*transmitter*/, - uint8 /*signerCount*/, - address[MAX_NUM_ORACLES] memory /*signers*/, - bytes calldata report - ) internal override { - bytes32[] memory requestIds; - bytes[] memory results; - bytes[] memory errors; - bytes[] memory onchainMetadata; - bytes[] memory offchainMetadata; - (requestIds, results, errors, onchainMetadata, offchainMetadata) = abi.decode( - report, - (bytes32[], bytes[], bytes[], bytes[], bytes[]) - ); - - if ( - requestIds.length == 0 || - requestIds.length != results.length || - requestIds.length != errors.length || - requestIds.length != onchainMetadata.length || - requestIds.length != offchainMetadata.length - ) { - revert ReportInvalid(); - } - - // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig - for (uint256 i = 0; i < requestIds.length; ++i) { - FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( - _fulfillAndBill(requestIds[i], results[i], errors[i], onchainMetadata[i], offchainMetadata[i]) - ); - - // Emit on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the DON will re-try - if ( - result == FunctionsResponse.FulfillResult.FULFILLED || - result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - emit OracleResponse(requestIds[i], msg.sender); - } - } - } - - /// @dev Used in FunctionsBilling.sol - function _onlyOwner() internal view override { - _validateOwnership(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol deleted file mode 100644 index 9f35c4d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsRouter.sol +++ /dev/null @@ -1,585 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IFunctionsRouter} from "./interfaces/IFunctionsRouter.sol"; -import {IFunctionsCoordinator} from "./interfaces/IFunctionsCoordinator.sol"; -import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; - -import {FunctionsSubscriptions} from "./FunctionsSubscriptions.sol"; -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; -import {Pausable} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol"; - -contract FunctionsRouter is IFunctionsRouter, FunctionsSubscriptions, Pausable, ITypeAndVersion, ConfirmedOwner { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - string public constant override typeAndVersion = "Functions Router v1.0.0"; - - // We limit return data to a selector plus 4 words. This is to avoid - // malicious contracts from returning large amounts of data and causing - // repeated out-of-gas scenarios. - uint16 public constant MAX_CALLBACK_RETURN_BYTES = 4 + 4 * 32; - uint8 private constant MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX = 0; - - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - - event RequestProcessed( - bytes32 indexed requestId, - uint64 indexed subscriptionId, - uint96 totalCostJuels, - address transmitter, - FunctionsResponse.FulfillResult resultCode, - bytes response, - bytes err, - bytes callbackReturnData - ); - - event RequestNotProcessed( - bytes32 indexed requestId, - address coordinator, - address transmitter, - FunctionsResponse.FulfillResult resultCode - ); - - error EmptyRequestData(); - error OnlyCallableFromCoordinator(); - error SenderMustAcceptTermsOfService(address sender); - error InvalidGasFlagValue(uint8 value); - error GasLimitTooBig(uint32 limit); - error DuplicateRequestId(bytes32 requestId); - - struct CallbackResult { - bool success; // ══════╸ Whether the callback succeeded or not - uint256 gasUsed; // ═══╸ The amount of gas consumed during the callback - bytes returnData; // ══╸ The return of the callback function - } - - // ================================================================ - // | Route state | - // ================================================================ - - mapping(bytes32 id => address routableContract) private s_route; - - error RouteNotFound(bytes32 id); - - // Identifier for the route to the Terms of Service Allow List - bytes32 private s_allowListId; - - // ================================================================ - // | Configuration state | - // ================================================================ - struct Config { - uint16 maxConsumersPerSubscription; // ═════════╗ Maximum number of consumers which can be added to a single subscription. This bound ensures we are able to loop over all subscription consumers as needed, without exceeding gas limits. Should a user require more consumers, they can use multiple subscriptions. - uint72 adminFee; // ║ Flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network - bytes4 handleOracleFulfillmentSelector; // ║ The function selector that is used when calling back to the Client contract - uint16 gasForCallExactCheck; // ════════════════╝ Used during calling back to the client. Ensures we have at least enough gas to be able to revert if gasAmount > 63//64*gas available. - uint32[] maxCallbackGasLimits; // ══════════════╸ List of max callback gas limits used by flag with GAS_FLAG_INDEX - uint16 subscriptionDepositMinimumRequests; //═══╗ Amount of requests that must be completed before the full subscription balance will be released when closing a subscription account. - uint72 subscriptionDepositJuels; // ════════════╝ Amount of subscription funds that are held as a deposit until Config.subscriptionDepositMinimumRequests are made using the subscription. - } - - Config private s_config; - - event ConfigUpdated(Config); - - // ================================================================ - // | Proposal state | - // ================================================================ - - uint8 private constant MAX_PROPOSAL_SET_LENGTH = 8; - - struct ContractProposalSet { - bytes32[] ids; // ══╸ The IDs that key into the routes that will be modified if the update is applied - address[] to; // ═══╸ The address of the contracts that the route will point to if the updated is applied - } - ContractProposalSet private s_proposedContractSet; - - event ContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ); - - event ContractUpdated(bytes32 id, address from, address to); - - error InvalidProposal(); - error IdentifierIsReserved(bytes32 id); - - // ================================================================ - // | Initialization | - // ================================================================ - - constructor( - address linkToken, - Config memory config - ) FunctionsSubscriptions(linkToken) ConfirmedOwner(msg.sender) Pausable() { - // Set the intial configuration - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice The identifier of the route to retrieve the address of the access control contract - // The access control contract controls which accounts can manage subscriptions - /// @return id - bytes32 id that can be passed to the "getContractById" of the Router - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice The router configuration - function updateConfig(Config memory config) public onlyOwner { - s_config = config; - emit ConfigUpdated(config); - } - - /// @inheritdoc IFunctionsRouter - function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) public view { - uint8 callbackGasLimitsIndexSelector = uint8(getFlags(subscriptionId)[MAX_CALLBACK_GAS_LIMIT_FLAGS_INDEX]); - if (callbackGasLimitsIndexSelector >= s_config.maxCallbackGasLimits.length) { - revert InvalidGasFlagValue(callbackGasLimitsIndexSelector); - } - uint32 maxCallbackGasLimit = s_config.maxCallbackGasLimits[callbackGasLimitsIndexSelector]; - if (callbackGasLimit > maxCallbackGasLimit) { - revert GasLimitTooBig(maxCallbackGasLimit); - } - } - - /// @inheritdoc IFunctionsRouter - function getAdminFee() external view override returns (uint72) { - return s_config.adminFee; - } - - /// @inheritdoc IFunctionsRouter - function getAllowListId() external view override returns (bytes32) { - return s_allowListId; - } - - /// @inheritdoc IFunctionsRouter - function setAllowListId(bytes32 allowListId) external override onlyOwner { - s_allowListId = allowListId; - } - - /// @dev Used within FunctionsSubscriptions.sol - function _getMaxConsumers() internal view override returns (uint16) { - return s_config.maxConsumersPerSubscription; - } - - /// @dev Used within FunctionsSubscriptions.sol - function _getSubscriptionDepositDetails() internal view override returns (uint16, uint72) { - return (s_config.subscriptionDepositMinimumRequests, s_config.subscriptionDepositJuels); - } - - // ================================================================ - // | Requests | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function sendRequest( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external override returns (bytes32) { - IFunctionsCoordinator coordinator = IFunctionsCoordinator(getContractById(donId)); - return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); - } - - /// @inheritdoc IFunctionsRouter - function sendRequestToProposed( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external override returns (bytes32) { - IFunctionsCoordinator coordinator = IFunctionsCoordinator(getProposedContractById(donId)); - return _sendRequest(donId, coordinator, subscriptionId, data, dataVersion, callbackGasLimit); - } - - function _sendRequest( - bytes32 donId, - IFunctionsCoordinator coordinator, - uint64 subscriptionId, - bytes memory data, - uint16 dataVersion, - uint32 callbackGasLimit - ) private returns (bytes32) { - _whenNotPaused(); - _isExistingSubscription(subscriptionId); - _isAllowedConsumer(msg.sender, subscriptionId); - isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - - if (data.length == 0) { - revert EmptyRequestData(); - } - - Subscription memory subscription = getSubscription(subscriptionId); - Consumer memory consumer = getConsumer(msg.sender, subscriptionId); - uint72 adminFee = s_config.adminFee; - - // Forward request to DON - FunctionsResponse.Commitment memory commitment = coordinator.startRequest( - FunctionsResponse.RequestMeta({ - requestingContract: msg.sender, - data: data, - subscriptionId: subscriptionId, - dataVersion: dataVersion, - flags: getFlags(subscriptionId), - callbackGasLimit: callbackGasLimit, - adminFee: adminFee, - initiatedRequests: consumer.initiatedRequests, - completedRequests: consumer.completedRequests, - availableBalance: subscription.balance - subscription.blockedBalance, - subscriptionOwner: subscription.owner - }) - ); - - // Do not allow setting a comittment for a requestId that already exists - if (s_requestCommitments[commitment.requestId] != bytes32(0)) { - revert DuplicateRequestId(commitment.requestId); - } - - // Store a commitment about the request - s_requestCommitments[commitment.requestId] = keccak256( - abi.encode( - FunctionsResponse.Commitment({ - adminFee: adminFee, - coordinator: address(coordinator), - client: msg.sender, - subscriptionId: subscriptionId, - callbackGasLimit: callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback - }) - ) - ); - - _markRequestInFlight(msg.sender, subscriptionId, commitment.estimatedTotalCostJuels); - - emit RequestStart({ - requestId: commitment.requestId, - donId: donId, - subscriptionId: subscriptionId, - subscriptionOwner: subscription.owner, - requestingContract: msg.sender, - requestInitiator: tx.origin, - data: data, - dataVersion: dataVersion, - callbackGasLimit: callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels - }); - - return commitment.requestId; - } - - // ================================================================ - // | Responses | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function fulfill( - bytes memory response, - bytes memory err, - uint96 juelsPerGas, - uint96 costWithoutCallback, - address transmitter, - FunctionsResponse.Commitment memory commitment - ) external override returns (FunctionsResponse.FulfillResult resultCode, uint96) { - _whenNotPaused(); - - if (msg.sender != commitment.coordinator) { - revert OnlyCallableFromCoordinator(); - } - - { - bytes32 commitmentHash = s_requestCommitments[commitment.requestId]; - - if (commitmentHash == bytes32(0)) { - resultCode = FunctionsResponse.FulfillResult.INVALID_REQUEST_ID; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - if (keccak256(abi.encode(commitment)) != commitmentHash) { - resultCode = FunctionsResponse.FulfillResult.INVALID_COMMITMENT; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - // Check that the transmitter has supplied enough gas for the callback to succeed - if (gasleft() < commitment.callbackGasLimit + commitment.gasOverheadAfterCallback) { - resultCode = FunctionsResponse.FulfillResult.INSUFFICIENT_GAS_PROVIDED; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - } - - { - uint96 callbackCost = juelsPerGas * SafeCast.toUint96(commitment.callbackGasLimit); - uint96 totalCostJuels = commitment.adminFee + costWithoutCallback + callbackCost; - - // Check that the subscription can still afford to fulfill the request - if (totalCostJuels > getSubscription(commitment.subscriptionId).balance) { - resultCode = FunctionsResponse.FulfillResult.SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - - // Check that the cost has not exceeded the quoted cost - if (totalCostJuels > commitment.estimatedTotalCostJuels) { - resultCode = FunctionsResponse.FulfillResult.COST_EXCEEDS_COMMITMENT; - emit RequestNotProcessed(commitment.requestId, commitment.coordinator, transmitter, resultCode); - return (resultCode, 0); - } - } - - delete s_requestCommitments[commitment.requestId]; - - CallbackResult memory result = _callback( - commitment.requestId, - response, - err, - commitment.callbackGasLimit, - commitment.client - ); - - resultCode = result.success - ? FunctionsResponse.FulfillResult.FULFILLED - : FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR; - - Receipt memory receipt = _pay( - commitment.subscriptionId, - commitment.estimatedTotalCostJuels, - commitment.client, - commitment.adminFee, - juelsPerGas, - SafeCast.toUint96(result.gasUsed), - costWithoutCallback - ); - - emit RequestProcessed({ - requestId: commitment.requestId, - subscriptionId: commitment.subscriptionId, - totalCostJuels: receipt.totalCostJuels, - transmitter: transmitter, - resultCode: resultCode, - response: response, - err: err, - callbackReturnData: result.returnData - }); - - return (resultCode, receipt.callbackGasCostJuels); - } - - function _callback( - bytes32 requestId, - bytes memory response, - bytes memory err, - uint32 callbackGasLimit, - address client - ) private returns (CallbackResult memory) { - bool destinationNoLongerExists; - assembly { - // solidity calls check that a contract actually exists at the destination, so we do the same - destinationNoLongerExists := iszero(extcodesize(client)) - } - if (destinationNoLongerExists) { - // Return without attempting callback - // The subscription will still be charged to reimburse transmitter's gas overhead - return CallbackResult({success: false, gasUsed: 0, returnData: new bytes(0)}); - } - - bytes memory encodedCallback = abi.encodeWithSelector( - s_config.handleOracleFulfillmentSelector, - requestId, - response, - err - ); - - uint16 gasForCallExactCheck = s_config.gasForCallExactCheck; - - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid payment. - // NOTE: that callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - - bool success; - uint256 gasUsed; - // allocate return data memory ahead of time - bytes memory returnData = new bytes(MAX_CALLBACK_RETURN_BYTES); - - assembly { - let g := gas() - // Compute g -= gasForCallExactCheck and check for underflow - // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. gasForCallExactCheck ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, gasForCallExactCheck) { - revert(0, 0) - } - g := sub(g, gasForCallExactCheck) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), callbackGasLimit)) { - revert(0, 0) - } - // call and report whether we succeeded - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - let gasBeforeCall := gas() - success := call(callbackGasLimit, client, 0, add(encodedCallback, 0x20), mload(encodedCallback), 0, 0) - gasUsed := sub(gasBeforeCall, gas()) - - // limit our copy to MAX_CALLBACK_RETURN_BYTES bytes - let toCopy := returndatasize() - if gt(toCopy, MAX_CALLBACK_RETURN_BYTES) { - toCopy := MAX_CALLBACK_RETURN_BYTES - } - // Store the length of the copied bytes - mstore(returnData, toCopy) - // copy the bytes from returnData[0:_toCopy] - returndatacopy(add(returnData, 0x20), 0, toCopy) - } - - return CallbackResult({success: success, gasUsed: gasUsed, returnData: returnData}); - } - - // ================================================================ - // | Route methods | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function getContractById(bytes32 id) public view override returns (address) { - address currentImplementation = s_route[id]; - if (currentImplementation == address(0)) { - revert RouteNotFound(id); - } - return currentImplementation; - } - - /// @inheritdoc IFunctionsRouter - function getProposedContractById(bytes32 id) public view override returns (address) { - // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint8 i = 0; i < s_proposedContractSet.ids.length; ++i) { - if (id == s_proposedContractSet.ids[i]) { - return s_proposedContractSet.to[i]; - } - } - revert RouteNotFound(id); - } - - // ================================================================ - // | Contract Proposal methods | - // ================================================================ - - /// @inheritdoc IFunctionsRouter - function getProposedContractSet() external view override returns (bytes32[] memory, address[] memory) { - return (s_proposedContractSet.ids, s_proposedContractSet.to); - } - - /// @inheritdoc IFunctionsRouter - function proposeContractsUpdate( - bytes32[] memory proposedContractSetIds, - address[] memory proposedContractSetAddresses - ) external override onlyOwner { - // IDs and addresses arrays must be of equal length and must not exceed the max proposal length - uint256 idsArrayLength = proposedContractSetIds.length; - if (idsArrayLength != proposedContractSetAddresses.length || idsArrayLength > MAX_PROPOSAL_SET_LENGTH) { - revert InvalidProposal(); - } - - // NOTE: iterations of this loop will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint256 i = 0; i < idsArrayLength; ++i) { - bytes32 id = proposedContractSetIds[i]; - address proposedContract = proposedContractSetAddresses[i]; - if ( - proposedContract == address(0) || // The Proposed address must be a valid address - s_route[id] == proposedContract // The Proposed address must point to a different address than what is currently set - ) { - revert InvalidProposal(); - } - - emit ContractProposed({ - proposedContractSetId: id, - proposedContractSetFromAddress: s_route[id], - proposedContractSetToAddress: proposedContract - }); - } - - s_proposedContractSet = ContractProposalSet({ids: proposedContractSetIds, to: proposedContractSetAddresses}); - } - - /// @inheritdoc IFunctionsRouter - function updateContracts() external override onlyOwner { - // Iterations will not exceed MAX_PROPOSAL_SET_LENGTH - for (uint256 i = 0; i < s_proposedContractSet.ids.length; ++i) { - bytes32 id = s_proposedContractSet.ids[i]; - address to = s_proposedContractSet.to[i]; - emit ContractUpdated({id: id, from: s_route[id], to: to}); - s_route[id] = to; - } - - delete s_proposedContractSet; - } - - // ================================================================ - // | Modifiers | - // ================================================================ - // Favoring internal functions over actual modifiers to reduce contract size - - /// @dev Used within FunctionsSubscriptions.sol - function _whenNotPaused() internal view override { - _requireNotPaused(); - } - - /// @dev Used within FunctionsSubscriptions.sol - function _onlyRouterOwner() internal view override { - _validateOwnership(); - } - - /// @dev Used within FunctionsSubscriptions.sol - function _onlySenderThatAcceptedToS() internal view override { - address currentImplementation = s_route[s_allowListId]; - if (currentImplementation == address(0)) { - // If not set, ignore this check, allow all access - return; - } - if (!IAccessController(currentImplementation).hasAccess(msg.sender, new bytes(0))) { - revert SenderMustAcceptTermsOfService(msg.sender); - } - } - - /// @inheritdoc IFunctionsRouter - function pause() external override onlyOwner { - _pause(); - } - - /// @inheritdoc IFunctionsRouter - function unpause() external override onlyOwner { - _unpause(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol deleted file mode 100644 index b93d217..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsSubscriptions.sol +++ /dev/null @@ -1,552 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "./interfaces/IFunctionsSubscriptions.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {IFunctionsBilling} from "./interfaces/IFunctionsBilling.sol"; - -import {FunctionsResponse} from "./libraries/FunctionsResponse.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @title Functions Subscriptions contract -/// @notice Contract that coordinates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsSubscriptions is IFunctionsSubscriptions, IERC677Receiver { - using SafeERC20 for IERC20; - using FunctionsResponse for FunctionsResponse.Commitment; - - // ================================================================ - // | Balance state | - // ================================================================ - // link token address - IERC20 internal immutable i_linkToken; - - // s_totalLinkBalance tracks the total LINK sent to/from - // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. - // A discrepancy with this contract's LINK balance indicates that someone - // sent tokens using transfer and so we may need to use recoverFunds. - uint96 private s_totalLinkBalance; - - /// @dev NOP balances are held as a single amount. The breakdown is held by the Coordinator. - mapping(address coordinator => uint96 balanceJuelsLink) private s_withdrawableTokens; - - // ================================================================ - // | Subscription state | - // ================================================================ - // Keep a count of the number of subscriptions so that its possible to - // loop through all the current subscriptions via .getSubscription(). - uint64 private s_currentSubscriptionId; - - mapping(uint64 subscriptionId => Subscription) private s_subscriptions; - - // Maintains the list of keys in s_consumers. - // We do this for 2 reasons: - // 1. To be able to clean up all keys from s_consumers when canceling a subscription. - // 2. To be able to return the list of all consumers in getSubscription. - // Note that we need the s_consumers map to be able to directly check if a - // consumer is valid without reading all the consumers from storage. - mapping(address consumer => mapping(uint64 subscriptionId => Consumer)) private s_consumers; - - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); - - error TooManyConsumers(uint16 maximumConsumers); - error InsufficientBalance(uint96 currentBalanceJuels); - error InvalidConsumer(); - error CannotRemoveWithPendingRequests(); - error InvalidSubscription(); - error OnlyCallableFromLink(); - error InvalidCalldata(); - error MustBeSubscriptionOwner(); - error TimeoutNotExceeded(); - error MustBeProposedOwner(address proposedOwner); - event FundsRecovered(address to, uint256 amount); - - // ================================================================ - // | Request state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) internal s_requestCommitments; - - struct Receipt { - uint96 callbackGasCostJuels; - uint96 totalCostJuels; - } - - event RequestTimedOut(bytes32 indexed requestId); - - // ================================================================ - // | Initialization | - // ================================================================ - constructor(address link) { - i_linkToken = IERC20(link); - } - - // ================================================================ - // | Request/Response | - // ================================================================ - - /// @notice Sets a request as in-flight - /// @dev Only callable within the Router - function _markRequestInFlight(address client, uint64 subscriptionId, uint96 estimatedTotalCostJuels) internal { - // Earmark subscription funds - s_subscriptions[subscriptionId].blockedBalance += estimatedTotalCostJuels; - - // Increment sent requests - s_consumers[client][subscriptionId].initiatedRequests += 1; - } - - /// @notice Moves funds from one subscription account to another. - /// @dev Only callable by the Coordinator contract that is saved in the request commitment - function _pay( - uint64 subscriptionId, - uint96 estimatedTotalCostJuels, - address client, - uint96 adminFee, - uint96 juelsPerGas, - uint96 gasUsed, - uint96 costWithoutCallbackJuels - ) internal returns (Receipt memory) { - uint96 callbackGasCostJuels = juelsPerGas * gasUsed; - uint96 totalCostJuels = costWithoutCallbackJuels + adminFee + callbackGasCostJuels; - - if ( - s_subscriptions[subscriptionId].balance < totalCostJuels || - s_subscriptions[subscriptionId].blockedBalance < estimatedTotalCostJuels - ) { - revert InsufficientBalance(s_subscriptions[subscriptionId].balance); - } - - // Charge the subscription - s_subscriptions[subscriptionId].balance -= totalCostJuels; - - // Unblock earmarked funds - s_subscriptions[subscriptionId].blockedBalance -= estimatedTotalCostJuels; - - // Pay the DON's fees and gas reimbursement - s_withdrawableTokens[msg.sender] += costWithoutCallbackJuels + callbackGasCostJuels; - - // Pay out the administration fee - s_withdrawableTokens[address(this)] += adminFee; - - // Increment finished requests - s_consumers[client][subscriptionId].completedRequests += 1; - - return Receipt({callbackGasCostJuels: callbackGasCostJuels, totalCostJuels: totalCostJuels}); - } - - // ================================================================ - // | Owner methods | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function ownerCancelSubscription(uint64 subscriptionId) external override { - _onlyRouterOwner(); - _isExistingSubscription(subscriptionId); - _cancelSubscriptionHelper(subscriptionId, s_subscriptions[subscriptionId].owner, false); - } - - /// @inheritdoc IFunctionsSubscriptions - function recoverFunds(address to) external override { - _onlyRouterOwner(); - uint256 externalBalance = i_linkToken.balanceOf(address(this)); - uint256 internalBalance = uint256(s_totalLinkBalance); - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - i_linkToken.safeTransfer(to, amount); - emit FundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function oracleWithdraw(address recipient, uint96 amount) external override { - _whenNotPaused(); - - if (amount == 0) { - revert InvalidCalldata(); - } - uint96 currentBalance = s_withdrawableTokens[msg.sender]; - if (currentBalance < amount) { - revert InsufficientBalance(currentBalance); - } - s_withdrawableTokens[msg.sender] -= amount; - s_totalLinkBalance -= amount; - i_linkToken.safeTransfer(recipient, amount); - } - - /// @notice Owner withdraw LINK earned through admin fees - /// @notice If amount is 0 the full balance will be withdrawn - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function ownerWithdraw(address recipient, uint96 amount) external { - _onlyRouterOwner(); - if (amount == 0) { - amount = s_withdrawableTokens[address(this)]; - } - uint96 currentBalance = s_withdrawableTokens[address(this)]; - if (currentBalance < amount) { - revert InsufficientBalance(currentBalance); - } - s_withdrawableTokens[address(this)] -= amount; - s_totalLinkBalance -= amount; - - i_linkToken.safeTransfer(recipient, amount); - } - - // ================================================================ - // | TransferAndCall Deposit helper | - // ================================================================ - - // This function is to be invoked when using LINK.transferAndCall - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override { - _whenNotPaused(); - if (msg.sender != address(i_linkToken)) { - revert OnlyCallableFromLink(); - } - if (data.length != 32) { - revert InvalidCalldata(); - } - uint64 subscriptionId = abi.decode(data, (uint64)); - if (s_subscriptions[subscriptionId].owner == address(0)) { - revert InvalidSubscription(); - } - // We do not check that the msg.sender is the subscription owner, - // anyone can fund a subscription. - uint256 oldBalance = s_subscriptions[subscriptionId].balance; - s_subscriptions[subscriptionId].balance += uint96(amount); - s_totalLinkBalance += uint96(amount); - emit SubscriptionFunded(subscriptionId, oldBalance, oldBalance + amount); - } - - // ================================================================ - // | Subscription management | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function getTotalBalance() external view override returns (uint96) { - return s_totalLinkBalance; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscriptionCount() external view override returns (uint64) { - return s_currentSubscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscription(uint64 subscriptionId) public view override returns (Subscription memory) { - _isExistingSubscription(subscriptionId); - return s_subscriptions[subscriptionId]; - } - - /// @inheritdoc IFunctionsSubscriptions - function getSubscriptionsInRange( - uint64 subscriptionIdStart, - uint64 subscriptionIdEnd - ) external view override returns (Subscription[] memory subscriptions) { - if ( - subscriptionIdStart > subscriptionIdEnd || - subscriptionIdEnd > s_currentSubscriptionId || - s_currentSubscriptionId == 0 - ) { - revert InvalidCalldata(); - } - - subscriptions = new Subscription[]((subscriptionIdEnd - subscriptionIdStart) + 1); - for (uint256 i = 0; i <= subscriptionIdEnd - subscriptionIdStart; ++i) { - subscriptions[i] = s_subscriptions[uint64(subscriptionIdStart + i)]; - } - - return subscriptions; - } - - /// @inheritdoc IFunctionsSubscriptions - function getConsumer(address client, uint64 subscriptionId) public view override returns (Consumer memory) { - return s_consumers[client][subscriptionId]; - } - - /// @dev Used within this file & FunctionsRouter.sol - function _isExistingSubscription(uint64 subscriptionId) internal view { - if (s_subscriptions[subscriptionId].owner == address(0)) { - revert InvalidSubscription(); - } - } - - /// @dev Used within FunctionsRouter.sol - function _isAllowedConsumer(address client, uint64 subscriptionId) internal view { - if (!s_consumers[client][subscriptionId].allowed) { - revert InvalidConsumer(); - } - } - - /// @inheritdoc IFunctionsSubscriptions - function createSubscription() external override returns (uint64 subscriptionId) { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - subscriptionId = ++s_currentSubscriptionId; - s_subscriptions[subscriptionId] = Subscription({ - balance: 0, - blockedBalance: 0, - owner: msg.sender, - proposedOwner: address(0), - consumers: new address[](0), - flags: bytes32(0) - }); - - emit SubscriptionCreated(subscriptionId, msg.sender); - - return subscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function createSubscriptionWithConsumer(address consumer) external override returns (uint64 subscriptionId) { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - subscriptionId = ++s_currentSubscriptionId; - s_subscriptions[subscriptionId] = Subscription({ - balance: 0, - blockedBalance: 0, - owner: msg.sender, - proposedOwner: address(0), - consumers: new address[](0), - flags: bytes32(0) - }); - - s_subscriptions[subscriptionId].consumers.push(consumer); - s_consumers[consumer][subscriptionId].allowed = true; - - emit SubscriptionCreated(subscriptionId, msg.sender); - emit SubscriptionConsumerAdded(subscriptionId, consumer); - - return subscriptionId; - } - - /// @inheritdoc IFunctionsSubscriptions - function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - if (newOwner == address(0) || s_subscriptions[subscriptionId].proposedOwner == newOwner) { - revert InvalidCalldata(); - } - - s_subscriptions[subscriptionId].proposedOwner = newOwner; - emit SubscriptionOwnerTransferRequested(subscriptionId, msg.sender, newOwner); - } - - /// @inheritdoc IFunctionsSubscriptions - function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external override { - _whenNotPaused(); - _onlySenderThatAcceptedToS(); - - address previousOwner = s_subscriptions[subscriptionId].owner; - address proposedOwner = s_subscriptions[subscriptionId].proposedOwner; - if (proposedOwner != msg.sender) { - revert MustBeProposedOwner(proposedOwner); - } - s_subscriptions[subscriptionId].owner = msg.sender; - s_subscriptions[subscriptionId].proposedOwner = address(0); - emit SubscriptionOwnerTransferred(subscriptionId, previousOwner, msg.sender); - } - - /// @inheritdoc IFunctionsSubscriptions - function removeConsumer(uint64 subscriptionId, address consumer) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - Consumer memory consumerData = s_consumers[consumer][subscriptionId]; - _isAllowedConsumer(consumer, subscriptionId); - if (consumerData.initiatedRequests != consumerData.completedRequests) { - revert CannotRemoveWithPendingRequests(); - } - // Note bounded by config.maxConsumers - address[] memory consumers = s_subscriptions[subscriptionId].consumers; - for (uint256 i = 0; i < consumers.length; ++i) { - if (consumers[i] == consumer) { - // Storage write to preserve last element - s_subscriptions[subscriptionId].consumers[i] = consumers[consumers.length - 1]; - // Storage remove last element - s_subscriptions[subscriptionId].consumers.pop(); - break; - } - } - delete s_consumers[consumer][subscriptionId]; - emit SubscriptionConsumerRemoved(subscriptionId, consumer); - } - - /// @dev Overriden in FunctionsRouter.sol - function _getMaxConsumers() internal view virtual returns (uint16); - - /// @inheritdoc IFunctionsSubscriptions - function addConsumer(uint64 subscriptionId, address consumer) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - // Already maxed, cannot add any more consumers. - uint16 maximumConsumers = _getMaxConsumers(); - if (s_subscriptions[subscriptionId].consumers.length >= maximumConsumers) { - revert TooManyConsumers(maximumConsumers); - } - if (s_consumers[consumer][subscriptionId].allowed) { - // Idempotence - do nothing if already added. - // Ensures uniqueness in s_subscriptions[subscriptionId].consumers. - return; - } - - s_consumers[consumer][subscriptionId].allowed = true; - s_subscriptions[subscriptionId].consumers.push(consumer); - - emit SubscriptionConsumerAdded(subscriptionId, consumer); - } - - /// @dev Overriden in FunctionsRouter.sol - function _getSubscriptionDepositDetails() internal virtual returns (uint16, uint72); - - function _cancelSubscriptionHelper(uint64 subscriptionId, address toAddress, bool checkDepositRefundability) private { - Subscription memory subscription = s_subscriptions[subscriptionId]; - uint96 balance = subscription.balance; - uint64 completedRequests = 0; - - // NOTE: loop iterations are bounded by config.maxConsumers - // If no consumers, does nothing. - for (uint256 i = 0; i < subscription.consumers.length; ++i) { - address consumer = subscription.consumers[i]; - completedRequests += s_consumers[consumer][subscriptionId].completedRequests; - delete s_consumers[consumer][subscriptionId]; - } - delete s_subscriptions[subscriptionId]; - - (uint16 subscriptionDepositMinimumRequests, uint72 subscriptionDepositJuels) = _getSubscriptionDepositDetails(); - - // If subscription has not made enough requests, deposit will be forfeited - if (checkDepositRefundability && completedRequests < subscriptionDepositMinimumRequests) { - uint96 deposit = subscriptionDepositJuels > balance ? balance : subscriptionDepositJuels; - if (deposit > 0) { - s_withdrawableTokens[address(this)] += deposit; - balance -= deposit; - } - } - - if (balance > 0) { - s_totalLinkBalance -= balance; - i_linkToken.safeTransfer(toAddress, uint256(balance)); - } - emit SubscriptionCanceled(subscriptionId, toAddress, balance); - } - - /// @inheritdoc IFunctionsSubscriptions - function cancelSubscription(uint64 subscriptionId, address to) external override { - _whenNotPaused(); - _onlySubscriptionOwner(subscriptionId); - _onlySenderThatAcceptedToS(); - - if (pendingRequestExists(subscriptionId)) { - revert CannotRemoveWithPendingRequests(); - } - - _cancelSubscriptionHelper(subscriptionId, to, true); - } - - /// @inheritdoc IFunctionsSubscriptions - function pendingRequestExists(uint64 subscriptionId) public view override returns (bool) { - address[] memory consumers = s_subscriptions[subscriptionId].consumers; - // NOTE: loop iterations are bounded by config.maxConsumers - for (uint256 i = 0; i < consumers.length; ++i) { - Consumer memory consumer = s_consumers[consumers[i]][subscriptionId]; - if (consumer.initiatedRequests != consumer.completedRequests) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsSubscriptions - function setFlags(uint64 subscriptionId, bytes32 flags) external override { - _onlyRouterOwner(); - _isExistingSubscription(subscriptionId); - s_subscriptions[subscriptionId].flags = flags; - } - - /// @inheritdoc IFunctionsSubscriptions - function getFlags(uint64 subscriptionId) public view returns (bytes32) { - return s_subscriptions[subscriptionId].flags; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsSubscriptions - function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external override { - _whenNotPaused(); - - for (uint256 i = 0; i < requestsToTimeoutByCommitment.length; ++i) { - FunctionsResponse.Commitment memory request = requestsToTimeoutByCommitment[i]; - bytes32 requestId = request.requestId; - uint64 subscriptionId = request.subscriptionId; - - // Check that request ID is valid - if (keccak256(abi.encode(request)) != s_requestCommitments[requestId]) { - revert InvalidCalldata(); - } - - // Check that request has exceeded allowed request time - if (block.timestamp < request.timeoutTimestamp) { - revert TimeoutNotExceeded(); - } - - // Notify the Coordinator that the request should no longer be fulfilled - IFunctionsBilling(request.coordinator).deleteCommitment(requestId); - // Release the subscription's balance that had been earmarked for the request - s_subscriptions[subscriptionId].blockedBalance -= request.estimatedTotalCostJuels; - s_consumers[request.client][subscriptionId].completedRequests += 1; - // Delete commitment within Router state - delete s_requestCommitments[requestId]; - - emit RequestTimedOut(requestId); - } - } - - // ================================================================ - // | Modifiers | - // ================================================================ - - function _onlySubscriptionOwner(uint64 subscriptionId) internal view { - address owner = s_subscriptions[subscriptionId].owner; - if (owner == address(0)) { - revert InvalidSubscription(); - } - if (msg.sender != owner) { - revert MustBeSubscriptionOwner(); - } - } - - /// @dev Overriden in FunctionsRouter.sol - function _onlySenderThatAcceptedToS() internal virtual; - - /// @dev Overriden in FunctionsRouter.sol - function _onlyRouterOwner() internal virtual; - - /// @dev Overriden in FunctionsRouter.sol - function _whenNotPaused() internal virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol deleted file mode 100644 index 6c11d4d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/Routable.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IOwnableFunctionsRouter} from "./interfaces/IOwnableFunctionsRouter.sol"; - -/// @title This abstract should be inherited by contracts that will be used -/// as the destinations to a route (id=>contract) on the Router. -/// It provides a Router getter and modifiers. -abstract contract Routable is ITypeAndVersion { - IOwnableFunctionsRouter private immutable i_router; - - error RouterMustBeSet(); - error OnlyCallableByRouter(); - error OnlyCallableByRouterOwner(); - - /// @dev Initializes the contract. - constructor(address router) { - if (router == address(0)) { - revert RouterMustBeSet(); - } - i_router = IOwnableFunctionsRouter(router); - } - - /// @notice Return the Router - function _getRouter() internal view returns (IOwnableFunctionsRouter router) { - return i_router; - } - - /// @notice Reverts if called by anyone other than the router. - modifier onlyRouter() { - if (msg.sender != address(i_router)) { - revert OnlyCallableByRouter(); - } - _; - } - - /// @notice Reverts if called by anyone other than the router owner. - modifier onlyRouterOwner() { - if (msg.sender != i_router.owner()) { - revert OnlyCallableByRouterOwner(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol deleted file mode 100644 index 8a42e34..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/TermsOfServiceAllowList.sol +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITermsOfServiceAllowList} from "./interfaces/ITermsOfServiceAllowList.sol"; -import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; - -import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.AddressSet; - - /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.0.0"; - - EnumerableSet.AddressSet private s_allowedSenders; - mapping(address => bool) private s_blockedSenders; - - event AddedAccess(address user); - event BlockedAccess(address user); - event UnblockedAccess(address user); - - error InvalidSignature(); - error InvalidUsage(); - error RecipientIsBlocked(); - - // ================================================================ - // | Configuration state | - // ================================================================ - struct Config { - bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. - address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data - } - - Config private s_config; - - event ConfigUpdated(Config config); - - // ================================================================ - // | Initialization | - // ================================================================ - - constructor(Config memory config) ConfirmedOwner(msg.sender) { - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the contracts's configuration - /// @return config - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice Sets the contracts's configuration - /// @param config - See the contents of the TermsOfServiceAllowList.Config struct for more information - function updateConfig(Config memory config) public onlyOwner { - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Allow methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { - return keccak256(abi.encodePacked(acceptor, recipient)); - } - - /// @inheritdoc ITermsOfServiceAllowList - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { - if (s_blockedSenders[recipient]) { - revert RecipientIsBlocked(); - } - - // Validate that the signature is correct and the correct data has been signed - bytes32 prefixedMessage = keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) - ); - if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { - revert InvalidSignature(); - } - - // If contract, validate that msg.sender == recipient - // This is to prevent EoAs from claiming contracts that they are not in control of - // If EoA, validate that msg.sender == acceptor == recipient - // This is to prevent EoAs from accepting for other EoAs - if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { - revert InvalidUsage(); - } - - // Add recipient to the allow list - s_allowedSenders.add(recipient); - emit AddedAccess(recipient); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllAllowedSenders() external view override returns (address[] memory) { - return s_allowedSenders.values(); - } - - /// @inheritdoc IAccessController - function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { - if (!s_config.enabled) { - return true; - } - return s_allowedSenders.contains(user); - } - - // ================================================================ - // | Block methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function isBlockedSender(address sender) external view override returns (bool) { - if (!s_config.enabled) { - return false; - } - return s_blockedSenders[sender]; - } - - /// @inheritdoc ITermsOfServiceAllowList - function blockSender(address sender) external override onlyOwner { - s_allowedSenders.remove(sender); - s_blockedSenders[sender] = true; - emit BlockedAccess(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function unblockSender(address sender) external override onlyOwner { - s_blockedSenders[sender] = false; - emit UnblockedAccess(sender); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol deleted file mode 100644 index af4daa1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/accessControl/interfaces/ITermsOfServiceAllowList.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -interface ITermsOfServiceAllowList { - /// @notice Return the message data for the proof given to accept the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @return Hash of the message data - function getMessage(address acceptor, address recipient) external pure returns (bytes32); - - /// @notice Check if the address is blocked for usage - /// @param sender The transaction sender's address - /// @return True or false - function isBlockedSender(address sender) external returns (bool); - - /// @notice Get a list of all allowed senders - /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - /// this function has an unbounded cost, and using it as part of a state-changing function may render the function - /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - /// @return addresses - all allowed addresses - function getAllAllowedSenders() external view returns (address[] memory); - - /// @notice Allows access to the sender based on acceptance of the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI - /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI - /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; - - /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service - /// @param sender - Address of the sender to block - function blockSender(address sender) external; - - /// @notice Re-allows a previously blocked sender to accept the Terms of Service - /// @param sender - Address of the sender to unblock - function unblockSender(address sender) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol deleted file mode 100644 index 8d1cf36..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/example/FunctionsClientExample.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsClient} from "../FunctionsClient.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {FunctionsRequest} from "../libraries/FunctionsRequest.sol"; - -/// @title Chainlink Functions example Client contract implementation -contract FunctionsClientExample is FunctionsClient, ConfirmedOwner { - using FunctionsRequest for FunctionsRequest.Request; - - uint32 public constant MAX_CALLBACK_GAS = 70_000; - - bytes32 public s_lastRequestId; - bytes32 public s_lastResponse; - bytes32 public s_lastError; - uint32 public s_lastResponseLength; - uint32 public s_lastErrorLength; - - error UnexpectedRequestID(bytes32 requestId); - - constructor(address router) FunctionsClient(router) ConfirmedOwner(msg.sender) {} - - /// @notice Send a simple request - /// @param source JavaScript source code - /// @param encryptedSecretsReferences Encrypted secrets payload - /// @param args List of arguments accessible from within the source code - /// @param subscriptionId Billing ID - function sendRequest( - string calldata source, - bytes calldata encryptedSecretsReferences, - string[] calldata args, - uint64 subscriptionId, - bytes32 jobId - ) external onlyOwner { - FunctionsRequest.Request memory req; - req.initializeRequestForInlineJavaScript(source); - if (encryptedSecretsReferences.length > 0) req.addSecretsReference(encryptedSecretsReferences); - if (args.length > 0) req.setArgs(args); - s_lastRequestId = _sendRequest(req.encodeCBOR(), subscriptionId, MAX_CALLBACK_GAS, jobId); - } - - /// @notice Store latest result/error - /// @param requestId The request ID, returned by sendRequest() - /// @param response Aggregated response from the user code - /// @param err Aggregated error from the user code or from the execution pipeline - /// @dev Either response or error parameter will be set, but never both - function fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal override { - if (s_lastRequestId != requestId) { - revert UnexpectedRequestID(requestId); - } - // Save only the first 32 bytes of response/error to always fit within MAX_CALLBACK_GAS - s_lastResponse = bytesToBytes32(response); - s_lastResponseLength = uint32(response.length); - s_lastError = bytesToBytes32(err); - s_lastErrorLength = uint32(err.length); - } - - function bytesToBytes32(bytes memory b) private pure returns (bytes32 out) { - uint256 maxLen = 32; - if (b.length < 32) { - maxLen = b.length; - } - for (uint256 i = 0; i < maxLen; ++i) { - out |= bytes32(b[i]) >> (i * 8); - } - return out; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol deleted file mode 100644 index 6291d05..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsBilling.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Chainlink Functions DON billing interface. -interface IFunctionsBilling { - /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed - /// @return weiPerUnitLink - The amount of WEI in one LINK - function getWeiPerUnitLink() external view returns (uint256); - - /// @notice Determine the fee that will be split between Node Operators for servicing a request - /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request - /// @return fee - Cost in Juels (1e18) of LINK - function getDONFee(bytes memory requestCBOR) external view returns (uint72); - - /// @notice Determine the fee that will be paid to the Router owner for operating the network - /// @return fee - Cost in Juels (1e18) of LINK - function getAdminFee() external view returns (uint72); - - /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee - /// @param - subscriptionId An identifier of the billing account - /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param - callbackGasLimit Gas limit for the fulfillment callback - /// @param - gasPriceWei The blockchain's gas price to estimate with - /// @return - billedCost Cost in Juels (1e18) of LINK - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view returns (uint96); - - /// @notice Remove a request commitment that the Router has determined to be stale - /// @param requestId - The request ID to remove - function deleteCommitment(bytes32 requestId) external; - - /// @notice Oracle withdraw LINK earned through fulfilling requests - /// @notice If amount is 0 the full balance will be withdrawn - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function oracleWithdraw(address recipient, uint96 amount) external; - - /// @notice Withdraw all LINK earned by Oracles through fulfilling requests - function oracleWithdrawAll() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol deleted file mode 100644 index f28a416..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsClient.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Chainlink Functions client interface. -interface IFunctionsClient { - /// @notice Chainlink Functions response handler called by the Functions Router - /// during fullilment from the designated transmitter node in an OCR round. - /// @param requestId The requestId returned by FunctionsClient.sendRequest(). - /// @param response Aggregated response from the request's source code. - /// @param err Aggregated error either from the request's source code or from the execution pipeline. - /// @dev Either response or error parameter will be set, but never both. - function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol deleted file mode 100644 index 4e2bd70..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsCoordinator.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions DON Coordinator interface. -interface IFunctionsCoordinator { - /// @notice Returns the DON's threshold encryption public key used to encrypt secrets - /// @dev All nodes on the DON have separate key shares of the threshold decryption key - /// and nodes must participate in a threshold decryption OCR round to decrypt secrets - /// @return thresholdPublicKey the DON's threshold encryption public key - function getThresholdPublicKey() external view returns (bytes memory); - - /// @notice Sets the DON's threshold encryption public key used to encrypt secrets - /// @dev Used to rotate the key - /// @param thresholdPublicKey The new public key - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external; - - /// @notice Returns the DON's secp256k1 public key that is used to encrypt secrets - /// @dev All nodes on the DON have the corresponding private key - /// needed to decrypt the secrets encrypted with the public key - /// @return publicKey the DON's public key - function getDONPublicKey() external view returns (bytes memory); - - /// @notice Sets DON's secp256k1 public key used to encrypt secrets - /// @dev Used to rotate the key - /// @param donPublicKey The new public key - function setDONPublicKey(bytes calldata donPublicKey) external; - - /// @notice Receives a request to be emitted to the DON for processing - /// @param request The request metadata - /// @dev see the struct for field descriptions - /// @return commitment - The parameters of the request that must be held consistent at response time - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external returns (FunctionsResponse.Commitment memory commitment); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol deleted file mode 100644 index 5f93aac..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsRouter.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions Router interface. -interface IFunctionsRouter { - /// @notice The identifier of the route to retrieve the address of the access control contract - /// The access control contract controls which accounts can manage subscriptions - /// @return id - bytes32 id that can be passed to the "getContractById" of the Router - function getAllowListId() external view returns (bytes32); - - /// @notice Set the identifier of the route to retrieve the address of the access control contract - /// The access control contract controls which accounts can manage subscriptions - function setAllowListId(bytes32 allowListId) external; - - /// @notice Get the flat fee (in Juels of LINK) that will be paid to the Router owner for operation of the network - /// @return adminFee - function getAdminFee() external view returns (uint72 adminFee); - - /// @notice Sends a request using the provided subscriptionId - /// @param subscriptionId - A unique subscription ID allocated by billing system, - /// a client can make requests from different contracts referencing the same subscription - /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param dataVersion - Gas limit for the fulfillment callback - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @param donId - An identifier used to determine which route to send the request along - /// @return requestId - A unique request identifier - function sendRequest( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external returns (bytes32); - - /// @notice Sends a request to the proposed contracts - /// @param subscriptionId - A unique subscription ID allocated by billing system, - /// a client can make requests from different contracts referencing the same subscription - /// @param data - CBOR encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param dataVersion - Gas limit for the fulfillment callback - /// @param callbackGasLimit - Gas limit for the fulfillment callback - /// @param donId - An identifier used to determine which route to send the request along - /// @return requestId - A unique request identifier - function sendRequestToProposed( - uint64 subscriptionId, - bytes calldata data, - uint16 dataVersion, - uint32 callbackGasLimit, - bytes32 donId - ) external returns (bytes32); - - /// @notice Fulfill the request by: - /// - calling back the data that the Oracle returned to the client contract - /// - pay the DON for processing the request - /// @dev Only callable by the Coordinator contract that is saved in the commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @param juelsPerGas - current rate of juels/gas - /// @param costWithoutFulfillment - The cost of processing the request (in Juels of LINK ), without fulfillment - /// @param transmitter - The Node that transmitted the OCR report - /// @param commitment - The parameters of the request that must be held consistent between request and response time - /// @return fulfillResult - - /// @return callbackGasCostJuels - - function fulfill( - bytes memory response, - bytes memory err, - uint96 juelsPerGas, - uint96 costWithoutFulfillment, - address transmitter, - FunctionsResponse.Commitment memory commitment - ) external returns (FunctionsResponse.FulfillResult, uint96); - - /// @notice Validate requested gas limit is below the subscription max. - /// @param subscriptionId subscription ID - /// @param callbackGasLimit desired callback gas limit - function isValidCallbackGasLimit(uint64 subscriptionId, uint32 callbackGasLimit) external view; - - /// @notice Get the current contract given an ID - /// @param id A bytes32 identifier for the route - /// @return contract The current contract address - function getContractById(bytes32 id) external view returns (address); - - /// @notice Get the proposed next contract given an ID - /// @param id A bytes32 identifier for the route - /// @return contract The current or proposed contract address - function getProposedContractById(bytes32 id) external view returns (address); - - /// @notice Return the latest proprosal set - /// @return ids The identifiers of the contracts to update - /// @return to The addresses of the contracts that will be updated to - function getProposedContractSet() external view returns (bytes32[] memory, address[] memory); - - /// @notice Proposes one or more updates to the contract routes - /// @dev Only callable by owner - function proposeContractsUpdate(bytes32[] memory proposalSetIds, address[] memory proposalSetAddresses) external; - - /// @notice Updates the current contract routes to the proposed contracts - /// @dev Only callable by owner - function updateContracts() external; - - /// @dev Puts the system into an emergency stopped state. - /// @dev Only callable by owner - function pause() external; - - /// @dev Takes the system out of an emergency stopped state. - /// @dev Only callable by owner - function unpause() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol deleted file mode 100644 index eafd6f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IFunctionsSubscriptions.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {FunctionsResponse} from "../libraries/FunctionsResponse.sol"; - -/// @title Chainlink Functions Subscription interface. -interface IFunctionsSubscriptions { - struct Subscription { - uint96 balance; // ═════════╗ Common LINK balance that is controlled by the Router to be used for all consumer requests. - address owner; // ══════════╝ The owner can fund/withdraw/cancel the subscription. - uint96 blockedBalance; // ══╗ LINK balance that is reserved to pay for pending consumer requests. - address proposedOwner; // ══╝ For safely transferring sub ownership. - address[] consumers; // ════╸ Client contracts that can use the subscription - bytes32 flags; // ══════════╸ Per-subscription flags - } - - struct Consumer { - bool allowed; // ══════════════╗ Owner can fund/withdraw/cancel the sub. - uint64 initiatedRequests; // ║ The number of requests that have been started - uint64 completedRequests; // ══╝ The number of requests that have successfully completed or timed out - } - - /// @notice Get details about a subscription. - /// @param subscriptionId - the ID of the subscription - /// @return subscription - see IFunctionsSubscriptions.Subscription for more information on the structure - function getSubscription(uint64 subscriptionId) external view returns (Subscription memory); - - /// @notice Retrieve details about multiple subscriptions using an inclusive range - /// @param subscriptionIdStart - the ID of the subscription to start the range at - /// @param subscriptionIdEnd - the ID of the subscription to end the range at - /// @return subscriptions - see IFunctionsSubscriptions.Subscription for more information on the structure - function getSubscriptionsInRange( - uint64 subscriptionIdStart, - uint64 subscriptionIdEnd - ) external view returns (Subscription[] memory); - - /// @notice Get details about a consumer of a subscription. - /// @param client - the consumer contract address - /// @param subscriptionId - the ID of the subscription - /// @return consumer - see IFunctionsSubscriptions.Consumer for more information on the structure - function getConsumer(address client, uint64 subscriptionId) external view returns (Consumer memory); - - /// @notice Get details about the total amount of LINK within the system - /// @return totalBalance - total Juels of LINK held by the contract - function getTotalBalance() external view returns (uint96); - - /// @notice Get details about the total number of subscription accounts - /// @return count - total number of subscriptions in the system - function getSubscriptionCount() external view returns (uint64); - - /// @notice Time out all expired requests: unlocks funds and removes the ability for the request to be fulfilled - /// @param requestsToTimeoutByCommitment - A list of request commitments to time out - /// @dev The commitment can be found on the "OracleRequest" event created when sending the request. - function timeoutRequests(FunctionsResponse.Commitment[] calldata requestsToTimeoutByCommitment) external; - - /// @notice Oracle withdraw LINK earned through fulfilling requests - /// @notice If amount is 0 the full balance will be withdrawn - /// @notice Both signing and transmitting wallets will have a balance to withdraw - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function oracleWithdraw(address recipient, uint96 amount) external; - - /// @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - /// @dev Only callable by the Router Owner - /// @param subscriptionId subscription id - /// @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - function ownerCancelSubscription(uint64 subscriptionId) external; - - /// @notice Recover link sent with transfer instead of transferAndCall. - /// @dev Only callable by the Router Owner - /// @param to address to send link to - function recoverFunds(address to) external; - - /// @notice Create a new subscription. - /// @return subscriptionId - A unique subscription id. - /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function createSubscription() external returns (uint64); - - /// @notice Create a new subscription and add a consumer. - /// @return subscriptionId - A unique subscription id. - /// @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - /// @dev Note to fund the subscription, use transferAndCall. For example - /// @dev LINKTOKEN.transferAndCall( - /// @dev address(ROUTER), - /// @dev amount, - /// @dev abi.encode(subscriptionId)); - function createSubscriptionWithConsumer(address consumer) external returns (uint64 subscriptionId); - - /// @notice Propose a new owner for a subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param newOwner - proposed new owner of the subscription - function proposeSubscriptionOwnerTransfer(uint64 subscriptionId, address newOwner) external; - - /// @notice Accept an ownership transfer. - /// @param subscriptionId - ID of the subscription - /// @dev will revert if original owner of subscriptionId has not requested that msg.sender become the new owner. - function acceptSubscriptionOwnerTransfer(uint64 subscriptionId) external; - - /// @notice Remove a consumer from a Chainlink Functions subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param consumer - Consumer to remove from the subscription - function removeConsumer(uint64 subscriptionId, address consumer) external; - - /// @notice Add a consumer to a Chainlink Functions subscription. - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param consumer - New consumer which can use the subscription - function addConsumer(uint64 subscriptionId, address consumer) external; - - /// @notice Cancel a subscription - /// @dev Only callable by the Subscription's owner - /// @param subscriptionId - ID of the subscription - /// @param to - Where to send the remaining LINK to - function cancelSubscription(uint64 subscriptionId, address to) external; - - /// @notice Check to see if there exists a request commitment for all consumers for a given sub. - /// @param subscriptionId - ID of the subscription - /// @return true if there exists at least one unfulfilled request for the subscription, false otherwise. - /// @dev Looping is bounded to MAX_CONSUMERS*(number of DONs). - /// @dev Used to disable subscription canceling while outstanding request are present. - function pendingRequestExists(uint64 subscriptionId) external view returns (bool); - - /// @notice Set subscription specific flags for a subscription. - /// Each byte of the flag is used to represent a resource tier that the subscription can utilize. - /// @param subscriptionId - ID of the subscription - /// @param flags - desired flag values - function setFlags(uint64 subscriptionId, bytes32 flags) external; - - /// @notice Get flags for a given subscription. - /// @param subscriptionId - ID of the subscription - /// @return flags - current flag values - function getFlags(uint64 subscriptionId) external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol deleted file mode 100644 index c5f3d82..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/interfaces/IOwnableFunctionsRouter.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsRouter} from "./IFunctionsRouter.sol"; -import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; - -/// @title Chainlink Functions Router interface with Ownability. -interface IOwnableFunctionsRouter is IOwnable, IFunctionsRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol deleted file mode 100644 index ef697b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {CBOR} from "../../../vendor/solidity-cborutils/v2.0.0/CBOR.sol"; - -/// @title Library for encoding the input data of a Functions request into CBOR -library FunctionsRequest { - using CBOR for CBOR.CBORBuffer; - - uint16 public constant REQUEST_DATA_VERSION = 1; - uint256 internal constant DEFAULT_BUFFER_SIZE = 256; - - enum Location { - Inline, // Provided within the Request - Remote, // Hosted through remote location that can be accessed through a provided URL - DONHosted // Hosted on the DON's storage - } - - enum CodeLanguage { - JavaScript - // In future version we may add other languages - } - - struct Request { - Location codeLocation; // ════════════╸ The location of the source code that will be executed on each node in the DON - Location secretsLocation; // ═════════╸ The location of secrets that will be passed into the source code. *Only Remote secrets are supported - CodeLanguage language; // ════════════╸ The coding language that the source code is written in - string source; // ════════════════════╸ Raw source code for Request.codeLocation of Location.Inline, URL for Request.codeLocation of Location.Remote, or slot decimal number for Request.codeLocation of Location.DONHosted - bytes encryptedSecretsReference; // ══╸ Encrypted URLs for Request.secretsLocation of Location.Remote (use addSecretsReference()), or CBOR encoded slotid+version for Request.secretsLocation of Location.DONHosted (use addDONHostedSecrets()) - string[] args; // ════════════════════╸ String arguments that will be passed into the source code - bytes[] bytesArgs; // ════════════════╸ Bytes arguments that will be passed into the source code - } - - error EmptySource(); - error EmptySecrets(); - error EmptyArgs(); - error NoInlineSecrets(); - - /// @notice Encodes a Request to CBOR encoded bytes - /// @param self The request to encode - /// @return CBOR encoded bytes - function encodeCBOR(Request memory self) internal pure returns (bytes memory) { - CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); - - buffer.writeString("codeLocation"); - buffer.writeUInt256(uint256(self.codeLocation)); - - buffer.writeString("language"); - buffer.writeUInt256(uint256(self.language)); - - buffer.writeString("source"); - buffer.writeString(self.source); - - if (self.args.length > 0) { - buffer.writeString("args"); - buffer.startArray(); - for (uint256 i = 0; i < self.args.length; ++i) { - buffer.writeString(self.args[i]); - } - buffer.endSequence(); - } - - if (self.encryptedSecretsReference.length > 0) { - if (self.secretsLocation == Location.Inline) { - revert NoInlineSecrets(); - } - buffer.writeString("secretsLocation"); - buffer.writeUInt256(uint256(self.secretsLocation)); - buffer.writeString("secrets"); - buffer.writeBytes(self.encryptedSecretsReference); - } - - if (self.bytesArgs.length > 0) { - buffer.writeString("bytesArgs"); - buffer.startArray(); - for (uint256 i = 0; i < self.bytesArgs.length; ++i) { - buffer.writeBytes(self.bytesArgs[i]); - } - buffer.endSequence(); - } - - return buffer.buf.buf; - } - - /// @notice Initializes a Chainlink Functions Request - /// @dev Sets the codeLocation and code on the request - /// @param self The uninitialized request - /// @param codeLocation The user provided source code location - /// @param language The programming language of the user code - /// @param source The user provided source code or a url - function initializeRequest( - Request memory self, - Location codeLocation, - CodeLanguage language, - string memory source - ) internal pure { - if (bytes(source).length == 0) revert EmptySource(); - - self.codeLocation = codeLocation; - self.language = language; - self.source = source; - } - - /// @notice Initializes a Chainlink Functions Request - /// @dev Simplified version of initializeRequest for PoC - /// @param self The uninitialized request - /// @param javaScriptSource The user provided JS code (must not be empty) - function initializeRequestForInlineJavaScript(Request memory self, string memory javaScriptSource) internal pure { - initializeRequest(self, Location.Inline, CodeLanguage.JavaScript, javaScriptSource); - } - - /// @notice Adds Remote user encrypted secrets to a Request - /// @param self The initialized request - /// @param encryptedSecretsReference Encrypted comma-separated string of URLs pointing to off-chain secrets - function addSecretsReference(Request memory self, bytes memory encryptedSecretsReference) internal pure { - if (encryptedSecretsReference.length == 0) revert EmptySecrets(); - - self.secretsLocation = Location.Remote; - self.encryptedSecretsReference = encryptedSecretsReference; - } - - /// @notice Adds DON-hosted secrets reference to a Request - /// @param self The initialized request - /// @param slotID Slot ID of the user's secrets hosted on DON - /// @param version User data version (for the slotID) - function addDONHostedSecrets(Request memory self, uint8 slotID, uint64 version) internal pure { - CBOR.CBORBuffer memory buffer = CBOR.create(DEFAULT_BUFFER_SIZE); - - buffer.writeString("slotID"); - buffer.writeUInt64(slotID); - buffer.writeString("version"); - buffer.writeUInt64(version); - - self.secretsLocation = Location.DONHosted; - self.encryptedSecretsReference = buffer.buf.buf; - } - - /// @notice Sets args for the user run function - /// @param self The initialized request - /// @param args The array of string args (must not be empty) - function setArgs(Request memory self, string[] memory args) internal pure { - if (args.length == 0) revert EmptyArgs(); - - self.args = args; - } - - /// @notice Sets bytes args for the user run function - /// @param self The initialized request - /// @param args The array of bytes args (must not be empty) - function setBytesArgs(Request memory self, bytes[] memory args) internal pure { - if (args.length == 0) revert EmptyArgs(); - - self.bytesArgs = args; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol deleted file mode 100644 index 65fad66..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsResponse.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Library of types that are used for fulfillment of a Functions request -library FunctionsResponse { - // Used to send request information from the Router to the Coordinator - struct RequestMeta { - bytes data; // ══════════════════╸ CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request - bytes32 flags; // ═══════════════╸ Per-subscription flags - address requestingContract; // ══╗ The client contract that is sending the request - uint96 availableBalance; // ═════╝ Common LINK balance of the subscription that is controlled by the Router to be used for all consumer requests. - uint72 adminFee; // ═════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network - uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request - uint64 initiatedRequests; // ║ The number of requests that have been started - uint32 callbackGasLimit; // ║ The amount of gas that the callback to the consuming contract will be given - uint16 dataVersion; // ══════════╝ The version of the structure of the CBOR encoded request data - uint64 completedRequests; // ════╗ The number of requests that have successfully completed or timed out - address subscriptionOwner; // ═══╝ The owner of the billing subscription - } - - enum FulfillResult { - FULFILLED, // 0 - USER_CALLBACK_ERROR, // 1 - INVALID_REQUEST_ID, // 2 - COST_EXCEEDS_COMMITMENT, // 3 - INSUFFICIENT_GAS_PROVIDED, // 4 - SUBSCRIPTION_BALANCE_INVARIANT_VIOLATION, // 5 - INVALID_COMMITMENT // 6 - } - - struct Commitment { - bytes32 requestId; // ═════════════════╸ A unique identifier for a Chainlink Functions request - address coordinator; // ═══════════════╗ The Coordinator contract that manages the DON that is servicing a request - uint96 estimatedTotalCostJuels; // ════╝ The maximum cost in Juels (1e18) of LINK that will be charged to fulfill a request - address client; // ════════════════════╗ The client contract that sent the request - uint64 subscriptionId; // ║ Identifier of the billing subscription that will be charged for the request - uint32 callbackGasLimit; // ═══════════╝ The amount of gas that the callback to the consuming contract will be given - uint72 adminFee; // ═══════════════════╗ Flat fee (in Juels of LINK) that will be paid to the Router Owner for operation of the network - uint72 donFee; // ║ Fee (in Juels of LINK) that will be split between Node Operators for servicing a request - uint40 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. - uint40 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. - uint32 timeoutTimestamp; // ═══════════╝ The timestamp at which a request will be eligible to be timed out - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol deleted file mode 100644 index 68b51f8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/mocks/FunctionsV1EventsMock.sol +++ /dev/null @@ -1,181 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.19; - -contract FunctionsV1EventsMock { - struct Config { - uint16 maxConsumersPerSubscription; - uint72 adminFee; - bytes4 handleOracleFulfillmentSelector; - uint16 gasForCallExactCheck; - uint32[] maxCallbackGasLimits; - } - event ConfigUpdated(Config param1); - event ContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ); - event ContractUpdated(bytes32 id, address from, address to); - event FundsRecovered(address to, uint256 amount); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event RequestNotProcessed(bytes32 indexed requestId, address coordinator, address transmitter, uint8 resultCode); - event RequestProcessed( - bytes32 indexed requestId, - uint64 indexed subscriptionId, - uint96 totalCostJuels, - address transmitter, - uint8 resultCode, - bytes response, - bytes err, - bytes callbackReturnData - ); - event RequestStart( - bytes32 indexed requestId, - bytes32 indexed donId, - uint64 indexed subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ); - event RequestTimedOut(bytes32 indexed requestId); - event SubscriptionCanceled(uint64 indexed subscriptionId, address fundsRecipient, uint256 fundsAmount); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId, address consumer); - event SubscriptionCreated(uint64 indexed subscriptionId, address owner); - event SubscriptionFunded(uint64 indexed subscriptionId, uint256 oldBalance, uint256 newBalance); - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId, address from, address to); - event Unpaused(address account); - - function emitConfigUpdated(Config memory param1) public { - emit ConfigUpdated(param1); - } - - function emitContractProposed( - bytes32 proposedContractSetId, - address proposedContractSetFromAddress, - address proposedContractSetToAddress - ) public { - emit ContractProposed(proposedContractSetId, proposedContractSetFromAddress, proposedContractSetToAddress); - } - - function emitContractUpdated(bytes32 id, address from, address to) public { - emit ContractUpdated(id, from, to); - } - - function emitFundsRecovered(address to, uint256 amount) public { - emit FundsRecovered(to, amount); - } - - function emitOwnershipTransferRequested(address from, address to) public { - emit OwnershipTransferRequested(from, to); - } - - function emitOwnershipTransferred(address from, address to) public { - emit OwnershipTransferred(from, to); - } - - function emitPaused(address account) public { - emit Paused(account); - } - - function emitRequestNotProcessed( - bytes32 requestId, - address coordinator, - address transmitter, - uint8 resultCode - ) public { - emit RequestNotProcessed(requestId, coordinator, transmitter, resultCode); - } - - function emitRequestProcessed( - bytes32 requestId, - uint64 subscriptionId, - uint96 totalCostJuels, - address transmitter, - uint8 resultCode, - bytes memory response, - bytes memory err, - bytes memory callbackReturnData - ) public { - emit RequestProcessed( - requestId, - subscriptionId, - totalCostJuels, - transmitter, - resultCode, - response, - err, - callbackReturnData - ); - } - - function emitRequestStart( - bytes32 requestId, - bytes32 donId, - uint64 subscriptionId, - address subscriptionOwner, - address requestingContract, - address requestInitiator, - bytes memory data, - uint16 dataVersion, - uint32 callbackGasLimit, - uint96 estimatedTotalCostJuels - ) public { - emit RequestStart( - requestId, - donId, - subscriptionId, - subscriptionOwner, - requestingContract, - requestInitiator, - data, - dataVersion, - callbackGasLimit, - estimatedTotalCostJuels - ); - } - - function emitRequestTimedOut(bytes32 requestId) public { - emit RequestTimedOut(requestId); - } - - function emitSubscriptionCanceled(uint64 subscriptionId, address fundsRecipient, uint256 fundsAmount) public { - emit SubscriptionCanceled(subscriptionId, fundsRecipient, fundsAmount); - } - - function emitSubscriptionConsumerAdded(uint64 subscriptionId, address consumer) public { - emit SubscriptionConsumerAdded(subscriptionId, consumer); - } - - function emitSubscriptionConsumerRemoved(uint64 subscriptionId, address consumer) public { - emit SubscriptionConsumerRemoved(subscriptionId, consumer); - } - - function emitSubscriptionCreated(uint64 subscriptionId, address owner) public { - emit SubscriptionCreated(subscriptionId, owner); - } - - function emitSubscriptionFunded(uint64 subscriptionId, uint256 oldBalance, uint256 newBalance) public { - emit SubscriptionFunded(subscriptionId, oldBalance, newBalance); - } - - function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId, address from, address to) public { - emit SubscriptionOwnerTransferRequested(subscriptionId, from, to); - } - - function emitSubscriptionOwnerTransferred(uint64 subscriptionId, address from, address to) public { - emit SubscriptionOwnerTransferred(subscriptionId, from, to); - } - - function emitUnpaused(address account) public { - emit Unpaused(account); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol deleted file mode 100644 index 09c4a82..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /** - * @notice triggers a new run of the offchain reporting protocol - * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - * @param configDigest configDigest of this configuration - * @param configCount ordinal number of this config setting among all config settings over the life of this contract - * @param signers ith element is address ith oracle uses to sign a report - * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param transmitters addresses oracles use to transmit the reports - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /** - * @notice optionally emited to indicate the latest configDigest and epoch for - which a report was successfully transmited. Alternatively, the contract may - use latestConfigDigestAndEpoch with scanLogs set to false. - */ - event Transmitted(bytes32 configDigest, uint32 epoch); - - /** - * @notice optionally returns the latest configDigest and epoch for which a - report was successfully transmitted. Alternatively, the contract may return - scanLogs set to true and use Transmitted events to provide this information - to offchain watchers. - * @return scanLogs indicates whether to rely on the configDigest and epoch - returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol deleted file mode 100644 index b7c3f03..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_0_0/ocr/OCR2Base.sol +++ /dev/null @@ -1,357 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/** - * @notice Onchain verification of reports from the offchain reporting protocol - * @dev For details on its operation, see the offchain reporting protocol design - * doc, which refers to this contract as simply the "contract". - */ -abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { - error ReportInvalid(); - error InvalidConfig(string message); - - bool internal immutable i_uniqueReports; - - constructor(bool uniqueReports) ConfirmedOwner(msg.sender) { - i_uniqueReports = uniqueReports; - } - - uint256 private constant maxUint32 = (1 << 32) - 1; - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems - // to extract config from logs. - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a single SLOAD. If any further fields are - // added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // TODO: could be optimized by squeezing into one slot - uint8 n; - } - ConfigInfo internal s_configInfo; - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - mapping(address signerOrTransmitter => Oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - /* - * Config logic - */ - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param _signers addresses with which oracles sign the reports - * @param _transmitters addresses oracles use to transmit the reports - * @param _f number of faulty oracles the system can tolerate - * @param _onchainConfig encoded on-chain contract configuration - * @param _offchainConfigVersion version number for offchainEncoding schema - * @param _offchainConfig encoded off-chain oracle configuration - */ - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < args.signers.length; i++) { - // add new signer/transmitter addresses - require(s_oracles[args.signers[i]].role == Role.Unset, "repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - require(s_oracles[args.transmitters[i]].role == Role.Unset, "repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - - function configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /** - * @return list of addresses permitted to transmit reports to this contract - * @dev The list will match the order used to specify the transmitter during setConfig - */ - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /** - * @dev hook called after the report has been fully validated - * for the extending contract to handle additional logic, such as oracle payment - * @param initialGas the amount of gas before validation - * @param transmitter the address of the account that submitted the report - * @param signers the addresses of all signing accounts - * @param report serialized report - */ - function _report( - uint256 initialGas, - address transmitter, - uint8 signerCount, - address[MAX_NUM_ORACLES] memory signers, - bytes calldata report - ) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - require(msg.data.length == expected, "calldata length mismatch"); - } - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - uint256 initialGas = gasleft(); // This line must come first - - { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - ConfigInfo memory configInfo = s_configInfo; - require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures; - if (i_uniqueReports) { - expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1; - } else { - expectedNumSignatures = configInfo.f + 1; - } - - require(rs.length == expectedNumSignatures, "wrong number of signatures"); - require(rs.length == ss.length, "signatures out of registration"); - - Oracle memory transmitter = s_oracles[msg.sender]; - require( // Check that sender is authorized to report - transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index], - "unauthorized transmitter" - ); - } - - address[MAX_NUM_ORACLES] memory signed; - uint8 signerCount = 0; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - require(o.role == Role.Signer, "address not authorized to sign"); - require(signed[o.index] == address(0), "non-unique signature"); - signed[o.index] = signer; - signerCount += 1; - } - } - - _report(initialGas, msg.sender, signerCount, signed, report); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol deleted file mode 100644 index ff34500..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsBilling.sol +++ /dev/null @@ -1,391 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "../v1_0_0/interfaces/IFunctionsSubscriptions.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {IFunctionsBilling} from "../v1_0_0/interfaces/IFunctionsBilling.sol"; - -import {Routable} from "../v1_0_0/Routable.sol"; -import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; - -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -import {ChainSpecificUtil} from "./libraries/ChainSpecificUtil.sol"; - -/// @title Functions Billing contract -/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsBilling is Routable, IFunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei - - event RequestBilled( - bytes32 indexed requestId, - uint96 juelsPerGas, - uint256 l1FeeShareWei, - uint96 callbackCostJuels, - uint96 totalCostJuels - ); - - // ================================================================ - // | Request Commitment state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; - - event CommitmentDeleted(bytes32 requestId); - - // ================================================================ - // | Configuration state | - // ================================================================ - - struct Config { - uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) - uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. - uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. - uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. - uint72 donFee; // ║ Additional flat fee (in Juels of LINK) that will be split between Node Operators. Max value is 2^80 - 1 == 1.2m LINK. - uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request - uint16 maxSupportedRequestDataVersion; // ═══════╝ The highest support request data version supported by the node. All lower versions should also be supported. - 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 - } - - Config private s_config; - - event ConfigUpdated(Config config); - - error UnsupportedRequestDataVersion(); - error InsufficientBalance(); - error InvalidSubscription(); - error UnauthorizedSender(); - error MustBeSubOwner(address owner); - error InvalidLinkWeiPrice(int256 linkWei); - error PaymentTooLarge(); - error NoTransmittersSet(); - error InvalidCalldata(); - - // ================================================================ - // | Balance state | - // ================================================================ - - mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; - // Pool together collected DON fees - // Disperse them on withdrawal or change in OCR configuration - uint96 internal s_feePool; - - AggregatorV3Interface private s_linkToNativeFeed; - - // ================================================================ - // | Initialization | - // ================================================================ - constructor(address router, Config memory config, address linkToNativeFeed) Routable(router) { - s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); - - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the Chainlink Coordinator's billing configuration - /// @return config - function getConfig() external view returns (Config memory) { - return s_config; - } - - /// @notice Sets the Chainlink Coordinator's billing configuration - /// @param config - See the contents of the Config struct in IFunctionsBilling.Config for more information - function updateConfig(Config memory config) public { - _onlyOwner(); - - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Fee Calculation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function getDONFee(bytes memory /* requestData */) public view override returns (uint72) { - return s_config.donFee; - } - - /// @inheritdoc IFunctionsBilling - function getAdminFee() public view override returns (uint72) { - return _getRouter().getAdminFee(); - } - - /// @inheritdoc IFunctionsBilling - function getWeiPerUnitLink() public view returns (uint256) { - Config memory config = s_config; - (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (config.feedStalenessSeconds < block.timestamp - timestamp && config.feedStalenessSeconds > 0) { - return config.fallbackNativePerUnitLink; - } - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - return uint256(weiPerUnitLink); - } - - function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { - // (1e18 juels/link) * wei / (wei/link) = juels - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); - } - - // ================================================================ - // | Cost Estimation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view override returns (uint96) { - _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - // Reasonable ceilings to prevent integer overflows - if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { - revert InvalidCalldata(); - } - uint72 adminFee = getAdminFee(); - uint72 donFee = getDONFee(data); - return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee); - } - - /// @notice Estimate the cost in Juels of LINK - // that will be charged to a subscription to fulfill a Functions request - // Gas Price can be overestimated to account for flucuations between request and response time - function _calculateCostEstimate( - uint32 callbackGasLimit, - uint256 gasPriceWei, - uint72 donFee, - uint72 adminFee - ) internal view returns (uint96) { - // If gas price is less than the minimum fulfillment gas price, override to using the minimum - if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { - 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); - - uint96 feesJuels = uint96(donFee) + uint96(adminFee); - - return estimatedGasReimbursementJuels + feesJuels; - } - - // ================================================================ - // | Billing | - // ================================================================ - - /// @notice Initiate the billing process for an Functions request - /// @dev Only callable by the Functions Router - /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure - /// @return commitment - The parameters of the request that must be held consistent at response time - function _startBilling( - FunctionsResponse.RequestMeta memory request - ) internal returns (FunctionsResponse.Commitment memory commitment) { - Config memory config = s_config; - - // Nodes should support all past versions of the structure - if (request.dataVersion > config.maxSupportedRequestDataVersion) { - revert UnsupportedRequestDataVersion(); - } - - uint72 donFee = getDONFee(request.data); - uint96 estimatedTotalCostJuels = _calculateCostEstimate( - request.callbackGasLimit, - tx.gasprice, - donFee, - request.adminFee - ); - - // Check that subscription can afford the estimated cost - if ((request.availableBalance) < estimatedTotalCostJuels) { - revert InsufficientBalance(); - } - - uint32 timeoutTimestamp = uint32(block.timestamp + config.requestTimeoutSeconds); - bytes32 requestId = keccak256( - abi.encode( - address(this), - request.requestingContract, - request.subscriptionId, - request.initiatedRequests + 1, - keccak256(request.data), - request.dataVersion, - request.callbackGasLimit, - estimatedTotalCostJuels, - timeoutTimestamp, - // solhint-disable-next-line avoid-tx-origin - tx.origin - ) - ); - - commitment = FunctionsResponse.Commitment({ - adminFee: request.adminFee, - coordinator: address(this), - client: request.requestingContract, - subscriptionId: request.subscriptionId, - callbackGasLimit: request.callbackGasLimit, - estimatedTotalCostJuels: estimatedTotalCostJuels, - timeoutTimestamp: timeoutTimestamp, - requestId: requestId, - donFee: donFee, - gasOverheadBeforeCallback: config.gasOverheadBeforeCallback, - gasOverheadAfterCallback: config.gasOverheadAfterCallback - }); - - s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); - - return commitment; - } - - /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription - /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @param reportBatchSize the number of fulfillments in the transmitter's report - /// @return result fulfillment result - /// @dev Only callable by a node that has been approved on the Coordinator - /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request - function _fulfillAndBill( - bytes32 requestId, - bytes memory response, - bytes memory err, - bytes memory onchainMetadata, - bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, - uint8 reportBatchSize - ) internal returns (FunctionsResponse.FulfillResult) { - FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); - - uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; - uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize; - // Gas overhead without callback - uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); - uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); - - // The Functions Router will perform the callback to the client contract - (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( - response, - err, - juelsPerGas, - gasOverheadJuels + commitment.donFee, // cost without callback or admin fee, those will be added by the Router - msg.sender, - commitment - ); - - // The router will only pay the DON on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the Coordinator should hold on to the request commitment - if ( - resultCode == FunctionsResponse.FulfillResult.FULFILLED || - resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - delete s_requestCommitments[requestId]; - // Reimburse the transmitter for the fulfillment gas cost - s_withdrawableTokens[msg.sender] = gasOverheadJuels + callbackCostJuels; - // Put donFee into the pool of fees, to be split later - // Saves on storage writes that would otherwise be charged to the user - s_feePool += commitment.donFee; - emit RequestBilled({ - requestId: requestId, - juelsPerGas: juelsPerGas, - l1FeeShareWei: l1FeeShareWei, - callbackCostJuels: callbackCostJuels, - totalCostJuels: gasOverheadJuels + callbackCostJuels + commitment.donFee + commitment.adminFee - }); - } - - return resultCode; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Router - /// @dev Used by FunctionsRouter.sol during timeout of a request - function deleteCommitment(bytes32 requestId) external override onlyRouter { - // Delete commitment - delete s_requestCommitments[requestId]; - emit CommitmentDeleted(requestId); - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function oracleWithdraw(address recipient, uint96 amount) external { - _disperseFeePool(); - - if (amount == 0) { - amount = s_withdrawableTokens[msg.sender]; - } else if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); - } - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Coordinator owner - function oracleWithdrawAll() external { - _onlyOwner(); - _disperseFeePool(); - - address[] memory transmitters = _getTransmitters(); - - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < transmitters.length; ++i) { - uint96 balance = s_withdrawableTokens[transmitters[i]]; - if (balance > 0) { - s_withdrawableTokens[transmitters[i]] = 0; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); - } - } - } - - // Overriden in FunctionsCoordinator, which has visibility into transmitters - function _getTransmitters() internal view virtual returns (address[] memory); - - // DON fees are collected into a pool s_feePool - // When OCR configuration changes, or any oracle withdraws, this must be dispersed - function _disperseFeePool() internal { - if (s_feePool == 0) { - return; - } - // All transmitters are assumed to also be observers - // Pay out the DON fee to all transmitters - address[] memory transmitters = _getTransmitters(); - uint256 numberOfTransmitters = transmitters.length; - if (numberOfTransmitters == 0) { - revert NoTransmittersSet(); - } - uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < numberOfTransmitters; ++i) { - s_withdrawableTokens[transmitters[i]] += feePoolShare; - } - s_feePool -= feePoolShare * uint96(numberOfTransmitters); - } - - // Overriden in FunctionsCoordinator.sol - function _onlyOwner() internal view virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol deleted file mode 100644 index 188e217..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/FunctionsCoordinator.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsCoordinator} from "../v1_0_0/interfaces/IFunctionsCoordinator.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {FunctionsBilling} from "./FunctionsBilling.sol"; -import {OCR2Base} from "./ocr/OCR2Base.sol"; -import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; - -/// @title Functions Coordinator contract -/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with -contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Coordinator v1.1.0"; - - event OracleRequest( - bytes32 indexed requestId, - address indexed requestingContract, - address requestInitiator, - uint64 subscriptionId, - address subscriptionOwner, - bytes data, - uint16 dataVersion, - bytes32 flags, - uint64 callbackGasLimit, - FunctionsResponse.Commitment commitment - ); - event OracleResponse(bytes32 indexed requestId, address transmitter); - - error InconsistentReportData(); - error EmptyPublicKey(); - error UnauthorizedPublicKeyChange(); - - bytes private s_donPublicKey; - bytes private s_thresholdPublicKey; - - constructor( - address router, - Config memory config, - address linkToNativeFeed - ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed) {} - - /// @inheritdoc IFunctionsCoordinator - function getThresholdPublicKey() external view override returns (bytes memory) { - if (s_thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { - if (thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_thresholdPublicKey = thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function getDONPublicKey() external view override returns (bytes memory) { - if (s_donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_donPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { - if (donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_donPublicKey = donPublicKey; - } - - /// @dev check if node is in current transmitter list - function _isTransmitter(address node) internal view returns (bool) { - address[] memory nodes = s_transmitters; - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < nodes.length; ++i) { - if (nodes[i] == node) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsCoordinator - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { - commitment = _startBilling(request); - - emit OracleRequest( - commitment.requestId, - request.requestingContract, - // solhint-disable-next-line avoid-tx-origin - tx.origin, - request.subscriptionId, - request.subscriptionOwner, - request.data, - request.dataVersion, - request.flags, - request.callbackGasLimit, - commitment - ); - - return commitment; - } - - /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. - function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { - if (_getTransmitters().length > 0) { - _disperseFeePool(); - } - } - - /// @dev Used by FunctionsBilling.sol - function _getTransmitters() internal view override returns (address[] memory) { - return s_transmitters; - } - - /// @dev Report hook called within OCR2Base.sol - function _report( - uint256 /*initialGas*/, - address /*transmitter*/, - uint8 /*signerCount*/, - address[MAX_NUM_ORACLES] memory /*signers*/, - bytes calldata report - ) internal override { - ( - bytes32[] memory requestIds, - bytes[] memory results, - bytes[] memory errors, - bytes[] memory onchainMetadata, - bytes[] memory offchainMetadata - ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); - uint256 numberOfFulfillments = uint8(requestIds.length); - - if ( - numberOfFulfillments == 0 || - numberOfFulfillments != results.length || - numberOfFulfillments != errors.length || - numberOfFulfillments != onchainMetadata.length || - numberOfFulfillments != offchainMetadata.length - ) { - revert ReportInvalid("Fields must be equal length"); - } - - // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig - for (uint256 i = 0; i < numberOfFulfillments; ++i) { - FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( - _fulfillAndBill( - requestIds[i], - results[i], - errors[i], - onchainMetadata[i], - offchainMetadata[i], - uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig - ) - ); - - // Emit on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the DON will re-try - if ( - result == FunctionsResponse.FulfillResult.FULFILLED || - result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - emit OracleResponse(requestIds[i], msg.sender); - } - } - } - - /// @dev Used in FunctionsBilling.sol - function _onlyOwner() internal view override { - _validateOwnership(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol deleted file mode 100644 index 68d346e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/libraries/ChainSpecificUtil.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -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"; - -/// @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); - - uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; - uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; - uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; - - // ------------ 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); - - uint256 private constant OP_MAINNET_CHAIN_ID = 10; - uint256 private constant OP_GOERLI_CHAIN_ID = 420; - uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; - - /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. - uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; - uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; - uint256 private constant BASE_SEPOLIA_CHAIN_ID = 84532; - - // ------------ 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) { - uint256 chainid = block.chainid; - if (_isArbitrumChainId(chainid)) { - return ARBGAS.getCurrentTxL1GasFees(); - } else if (_isOptimismChainId(chainid)) { - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING)); - } - return 0; - } - - /// @notice Return true if and only if the provided chain ID is an Arbitrum chain ID. - function _isArbitrumChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == ARB_MAINNET_CHAIN_ID || - chainId == ARB_GOERLI_TESTNET_CHAIN_ID || - chainId == ARB_SEPOLIA_TESTNET_CHAIN_ID; - } - - /// @notice Return true if and only if the provided chain ID is an Optimism (or Base) chain ID. - /// @notice Note that optimism chain id's are also OP stack chain id's. - function _isOptimismChainId(uint256 chainId) internal pure returns (bool) { - return - chainId == OP_MAINNET_CHAIN_ID || - chainId == OP_GOERLI_CHAIN_ID || - chainId == OP_SEPOLIA_CHAIN_ID || - chainId == BASE_MAINNET_CHAIN_ID || - chainId == BASE_GOERLI_CHAIN_ID || - chainId == BASE_SEPOLIA_CHAIN_ID; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol deleted file mode 100644 index 4182227..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /** - * @notice triggers a new run of the offchain reporting protocol - * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - * @param configDigest configDigest of this configuration - * @param configCount ordinal number of this config setting among all config settings over the life of this contract - * @param signers ith element is address ith oracle uses to sign a report - * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param transmitters addresses oracles use to transmit the reports - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - /** - * @notice optionally emited to indicate the latest configDigest and epoch for - which a report was successfully transmited. Alternatively, the contract may - use latestConfigDigestAndEpoch with scanLogs set to false. - */ - event Transmitted(bytes32 configDigest, uint32 epoch); - - /** - * @notice optionally returns the latest configDigest and epoch for which a - report was successfully transmitted. Alternatively, the contract may return - scanLogs set to true and use Transmitted events to provide this information - to offchain watchers. - * @return scanLogs indicates whether to rely on the configDigest and epoch - returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol deleted file mode 100644 index a4fd2bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_1_0/ocr/OCR2Base.sol +++ /dev/null @@ -1,348 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/** - * @notice Onchain verification of reports from the offchain reporting protocol - * @dev For details on its operation, see the offchain reporting protocol design - * doc, which refers to this contract as simply the "contract". - */ -abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { - error ReportInvalid(string message); - error InvalidConfig(string message); - - constructor() ConfirmedOwner(msg.sender) {} - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems - // to extract config from logs. - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a single SLOAD. If any further fields are - // added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // TODO: could be optimized by squeezing into one slot - uint8 n; - } - ConfigInfo internal s_configInfo; - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - mapping(address signerOrTransmitter => Oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - /* - * Config logic - */ - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - // solhint-disable-next-line gas-struct-packing - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param _signers addresses with which oracles sign the reports - * @param _transmitters addresses oracles use to transmit the reports - * @param _f number of faulty oracles the system can tolerate - * @param _onchainConfig encoded on-chain contract configuration - * @param _offchainConfigVersion version number for offchainEncoding schema - * @param _offchainConfig encoded off-chain oracle configuration - */ - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < args.signers.length; i++) { - if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); - if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); - // add new signer/transmitter addresses - if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - - function _configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /** - * @return list of addresses permitted to transmit reports to this contract - * @dev The list will match the order used to specify the transmitter during setConfig - */ - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /** - * @dev hook called after the report has been fully validated - * for the extending contract to handle additional logic, such as oracle payment - * @param initialGas the amount of gas before validation - * @param transmitter the address of the account that submitted the report - * @param signers the addresses of all signing accounts - * @param report serialized report - */ - function _report( - uint256 initialGas, - address transmitter, - uint8 signerCount, - address[MAX_NUM_ORACLES] memory signers, - bytes calldata report - ) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function _requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); - } - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - uint256 initialGas = gasleft(); // This line must come first - - { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest - // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router - // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - _requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; - - if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); - if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); - - Oracle memory transmitter = s_oracles[msg.sender]; - if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) - revert ReportInvalid("unauthorized transmitter"); - } - - address[MAX_NUM_ORACLES] memory signed; - uint8 signerCount = 0; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); - if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); - signed[o.index] = signer; - signerCount += 1; - } - } - - _report(initialGas, msg.sender, signerCount, signed, report); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol deleted file mode 100644 index 49ecf3d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsBilling.sol +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsSubscriptions} from "../v1_0_0/interfaces/IFunctionsSubscriptions.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {IFunctionsBilling, FunctionsBillingConfig} from "./interfaces/IFunctionsBilling.sol"; - -import {Routable} from "../v1_0_0/Routable.sol"; -import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; - -import {SafeCast} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -import {ChainSpecificUtil} from "../v1_1_0/libraries/ChainSpecificUtil.sol"; - -/// @title Functions Billing contract -/// @notice Contract that calculates payment from users to the nodes of the Decentralized Oracle Network (DON). -abstract contract FunctionsBilling is Routable, IFunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - uint256 private constant REASONABLE_GAS_PRICE_CEILING = 1_000_000_000_000_000; // 1 million gwei - - event RequestBilled( - bytes32 indexed requestId, - uint96 juelsPerGas, - uint256 l1FeeShareWei, - uint96 callbackCostJuels, - uint72 donFeeJuels, - uint72 adminFeeJuels, - uint72 operationFeeJuels - ); - - // ================================================================ - // | Request Commitment state | - // ================================================================ - - mapping(bytes32 requestId => bytes32 commitmentHash) private s_requestCommitments; - - event CommitmentDeleted(bytes32 requestId); - - FunctionsBillingConfig private s_config; - - event ConfigUpdated(FunctionsBillingConfig config); - - error UnsupportedRequestDataVersion(); - error InsufficientBalance(); - error InvalidSubscription(); - error UnauthorizedSender(); - error MustBeSubOwner(address owner); - error InvalidLinkWeiPrice(int256 linkWei); - error InvalidUsdLinkPrice(int256 usdLink); - error PaymentTooLarge(); - error NoTransmittersSet(); - error InvalidCalldata(); - - // ================================================================ - // | Balance state | - // ================================================================ - - mapping(address transmitter => uint96 balanceJuelsLink) private s_withdrawableTokens; - // Pool together collected DON fees - // Disperse them on withdrawal or change in OCR configuration - uint96 internal s_feePool; - - AggregatorV3Interface private s_linkToNativeFeed; - AggregatorV3Interface private s_linkToUsdFeed; - - // ================================================================ - // | Initialization | - // ================================================================ - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) Routable(router) { - s_linkToNativeFeed = AggregatorV3Interface(linkToNativeFeed); - s_linkToUsdFeed = AggregatorV3Interface(linkToUsdFeed); - - updateConfig(config); - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the Chainlink Coordinator's billing configuration - /// @return config - function getConfig() external view returns (FunctionsBillingConfig memory) { - return s_config; - } - - /// @notice Sets the Chainlink Coordinator's billing configuration - /// @param config - See the contents of the FunctionsBillingConfig struct in IFunctionsBilling.sol for more information - function updateConfig(FunctionsBillingConfig memory config) public { - _onlyOwner(); - - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Fee Calculation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function getDONFeeJuels(bytes memory /* requestData */) public view override returns (uint72) { - // s_config.donFee is in cents of USD. Get Juel amount then convert to dollars. - return SafeCast.toUint72(_getJuelsFromUsd(s_config.donFeeCentsUsd) / 100); - } - - /// @inheritdoc IFunctionsBilling - function getOperationFeeJuels() public view override returns (uint72) { - // s_config.donFee is in cents of USD. Get Juel amount then convert to dollars. - return SafeCast.toUint72(_getJuelsFromUsd(s_config.operationFeeCentsUsd) / 100); - } - - /// @inheritdoc IFunctionsBilling - function getAdminFeeJuels() public view override returns (uint72) { - return _getRouter().getAdminFee(); - } - - /// @inheritdoc IFunctionsBilling - function getWeiPerUnitLink() public view returns (uint256) { - (, int256 weiPerUnitLink, , uint256 timestamp, ) = s_linkToNativeFeed.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { - return s_config.fallbackNativePerUnitLink; - } - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - return uint256(weiPerUnitLink); - } - - function _getJuelsFromWei(uint256 amountWei) private view returns (uint96) { - // (1e18 juels/link) * wei / (wei/link) = juels - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((1e18 * amountWei) / getWeiPerUnitLink()); - } - - /// @inheritdoc IFunctionsBilling - function getUsdPerUnitLink() public view returns (uint256, uint8) { - (, int256 usdPerUnitLink, , uint256 timestamp, ) = s_linkToUsdFeed.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (s_config.feedStalenessSeconds < block.timestamp - timestamp && s_config.feedStalenessSeconds > 0) { - return (s_config.fallbackUsdPerUnitLink, s_config.fallbackUsdPerUnitLinkDecimals); - } - if (usdPerUnitLink <= 0) { - revert InvalidUsdLinkPrice(usdPerUnitLink); - } - return (uint256(usdPerUnitLink), s_linkToUsdFeed.decimals()); - } - - function _getJuelsFromUsd(uint256 amountUsd) private view returns (uint96) { - (uint256 usdPerLink, uint8 decimals) = getUsdPerUnitLink(); - // (usd) * (10**18 juels/link) * (10**decimals) / (link / usd) = juels - // There are only 1e9*1e18 = 1e27 juels in existence, should not exceed uint96 (2^96 ~ 7e28) - return SafeCast.toUint96((amountUsd * 10 ** (18 + decimals)) / usdPerLink); - } - - // ================================================================ - // | Cost Estimation | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view override returns (uint96) { - _getRouter().isValidCallbackGasLimit(subscriptionId, callbackGasLimit); - // Reasonable ceilings to prevent integer overflows - if (gasPriceWei > REASONABLE_GAS_PRICE_CEILING) { - revert InvalidCalldata(); - } - uint72 adminFee = getAdminFeeJuels(); - uint72 donFee = getDONFeeJuels(data); - uint72 operationFee = getOperationFeeJuels(); - return _calculateCostEstimate(callbackGasLimit, gasPriceWei, donFee, adminFee, operationFee); - } - - /// @notice Estimate the cost in Juels of LINK - // that will be charged to a subscription to fulfill a Functions request - // Gas Price can be overestimated to account for flucuations between request and response time - function _calculateCostEstimate( - uint32 callbackGasLimit, - uint256 gasPriceWei, - uint72 donFeeJuels, - uint72 adminFeeJuels, - uint72 operationFeeJuels - ) internal view returns (uint96) { - // If gas price is less than the minimum fulfillment gas price, override to using the minimum - if (gasPriceWei < s_config.minimumEstimateGasPriceWei) { - 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); - - uint96 feesJuels = uint96(donFeeJuels) + uint96(adminFeeJuels) + uint96(operationFeeJuels); - - return estimatedGasReimbursementJuels + feesJuels; - } - - // ================================================================ - // | Billing | - // ================================================================ - - /// @notice Initiate the billing process for an Functions request - /// @dev Only callable by the Functions Router - /// @param request - Chainlink Functions request data, see FunctionsResponse.RequestMeta for the structure - /// @return commitment - The parameters of the request that must be held consistent at response time - function _startBilling( - FunctionsResponse.RequestMeta memory request - ) internal returns (FunctionsResponse.Commitment memory commitment, uint72 operationFee) { - // Nodes should support all past versions of the structure - if (request.dataVersion > s_config.maxSupportedRequestDataVersion) { - revert UnsupportedRequestDataVersion(); - } - - uint72 donFee = getDONFeeJuels(request.data); - operationFee = getOperationFeeJuels(); - uint96 estimatedTotalCostJuels = _calculateCostEstimate( - request.callbackGasLimit, - tx.gasprice, - donFee, - request.adminFee, - operationFee - ); - - // Check that subscription can afford the estimated cost - if ((request.availableBalance) < estimatedTotalCostJuels) { - revert InsufficientBalance(); - } - - uint32 timeoutTimestamp = uint32(block.timestamp + s_config.requestTimeoutSeconds); - bytes32 requestId = keccak256( - abi.encode( - address(this), - request.requestingContract, - request.subscriptionId, - request.initiatedRequests + 1, - keccak256(request.data), - request.dataVersion, - request.callbackGasLimit, - estimatedTotalCostJuels, - timeoutTimestamp, - // solhint-disable-next-line avoid-tx-origin - tx.origin - ) - ); - - commitment = FunctionsResponse.Commitment({ - adminFee: request.adminFee, - coordinator: address(this), - client: request.requestingContract, - subscriptionId: request.subscriptionId, - callbackGasLimit: request.callbackGasLimit, - estimatedTotalCostJuels: estimatedTotalCostJuels, - timeoutTimestamp: timeoutTimestamp, - requestId: requestId, - donFee: donFee, - gasOverheadBeforeCallback: s_config.gasOverheadBeforeCallback, - gasOverheadAfterCallback: s_config.gasOverheadAfterCallback - }); - - s_requestCommitments[requestId] = keccak256(abi.encode(commitment)); - - return (commitment, operationFee); - } - - /// @notice Finalize billing process for an Functions request by sending a callback to the Client contract and then charging the subscription - /// @param requestId identifier for the request that was generated by the Registry in the beginBilling commitment - /// @param response response data from DON consensus - /// @param err error from DON consensus - /// @param reportBatchSize the number of fulfillments in the transmitter's report - /// @return result fulfillment result - /// @dev Only callable by a node that has been approved on the Coordinator - /// @dev simulated offchain to determine if sufficient balance is present to fulfill the request - function _fulfillAndBill( - bytes32 requestId, - bytes memory response, - bytes memory err, - bytes memory onchainMetadata, - bytes memory /* offchainMetadata TODO: use in getDonFee() for dynamic billing */, - uint8 reportBatchSize - ) internal returns (FunctionsResponse.FulfillResult) { - FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment)); - - uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice; - uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize; - // Gas overhead without callback - uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei); - uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice); - - // The Functions Router will perform the callback to the client contract - (FunctionsResponse.FulfillResult resultCode, uint96 callbackCostJuels) = _getRouter().fulfill( - response, - err, - juelsPerGas, - // The following line represents: "cost without callback or admin fee, those will be added by the Router" - // But because the _offchain_ Commitment is using operation fee in the place of the admin fee, this now adds admin fee (actually operation fee) - // Admin fee is configured to 0 in the Router - gasOverheadJuels + commitment.donFee + commitment.adminFee, - msg.sender, - FunctionsResponse.Commitment({ - adminFee: 0, // The Router should have adminFee set to 0. If it does not this will cause fulfillments to fail with INVALID_COMMITMENT instead of carrying out incorrect bookkeeping. - coordinator: commitment.coordinator, - client: commitment.client, - subscriptionId: commitment.subscriptionId, - callbackGasLimit: commitment.callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback - }) - ); - - // The router will only pay the DON on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the Coordinator should hold on to the request commitment - if ( - resultCode == FunctionsResponse.FulfillResult.FULFILLED || - resultCode == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - delete s_requestCommitments[requestId]; - // Reimburse the transmitter for the fulfillment gas cost - s_withdrawableTokens[msg.sender] += gasOverheadJuels + callbackCostJuels; - // Put donFee into the pool of fees, to be split later - // Saves on storage writes that would otherwise be charged to the user - s_feePool += commitment.donFee; - // Pay the operation fee to the Coordinator owner - s_withdrawableTokens[_owner()] += commitment.adminFee; // OperationFee is used in the slot for Admin Fee in the Offchain Commitment. Admin Fee is set to 0 in the Router (enforced by line 316 in FunctionsBilling.sol). - emit RequestBilled({ - requestId: requestId, - juelsPerGas: juelsPerGas, - l1FeeShareWei: l1FeeShareWei, - callbackCostJuels: callbackCostJuels, - donFeeJuels: commitment.donFee, - // The following two lines are because of OperationFee being used in the Offchain Commitment - adminFeeJuels: 0, - operationFeeJuels: commitment.adminFee - }); - } - return resultCode; - } - - // ================================================================ - // | Request Timeout | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Router - /// @dev Used by FunctionsRouter.sol during timeout of a request - function deleteCommitment(bytes32 requestId) external override onlyRouter { - // Delete commitment - delete s_requestCommitments[requestId]; - emit CommitmentDeleted(requestId); - } - - // ================================================================ - // | Fund withdrawal | - // ================================================================ - - /// @inheritdoc IFunctionsBilling - function oracleWithdraw(address recipient, uint96 amount) external { - _disperseFeePool(); - - if (amount == 0) { - amount = s_withdrawableTokens[msg.sender]; - } else if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(recipient, amount); - } - - /// @inheritdoc IFunctionsBilling - /// @dev Only callable by the Coordinator owner - function oracleWithdrawAll() external { - _onlyOwner(); - _disperseFeePool(); - - address[] memory transmitters = _getTransmitters(); - - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < transmitters.length; ++i) { - uint96 balance = s_withdrawableTokens[transmitters[i]]; - if (balance > 0) { - s_withdrawableTokens[transmitters[i]] = 0; - IFunctionsSubscriptions(address(_getRouter())).oracleWithdraw(transmitters[i], balance); - } - } - } - - // Overriden in FunctionsCoordinator, which has visibility into transmitters - function _getTransmitters() internal view virtual returns (address[] memory); - - // DON fees are collected into a pool s_feePool - // When OCR configuration changes, or any oracle withdraws, this must be dispersed - function _disperseFeePool() internal { - if (s_feePool == 0) { - return; - } - // All transmitters are assumed to also be observers - // Pay out the DON fee to all transmitters - address[] memory transmitters = _getTransmitters(); - uint256 numberOfTransmitters = transmitters.length; - if (numberOfTransmitters == 0) { - revert NoTransmittersSet(); - } - uint96 feePoolShare = s_feePool / uint96(numberOfTransmitters); - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < numberOfTransmitters; ++i) { - s_withdrawableTokens[transmitters[i]] += feePoolShare; - } - s_feePool -= feePoolShare * uint96(numberOfTransmitters); - } - - // Overriden in FunctionsCoordinator.sol - function _onlyOwner() internal view virtual; - - // Used in FunctionsCoordinator.sol - function _isExistingRequest(bytes32 requestId) internal view returns (bool) { - return s_requestCommitments[requestId] != bytes32(0); - } - - // Overriden in FunctionsCoordinator.sol - function _owner() internal view virtual returns (address owner); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol deleted file mode 100644 index 84b6414..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsClient.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsRouter} from "../v1_0_0/interfaces/IFunctionsRouter.sol"; -import {IFunctionsClient} from "../v1_0_0/interfaces/IFunctionsClient.sol"; - -import {FunctionsRequest} from "../v1_0_0/libraries/FunctionsRequest.sol"; - -/// @title The Chainlink Functions client contract -/// @notice Contract developers can inherit this contract in order to make Chainlink Functions requests -abstract contract FunctionsClient is IFunctionsClient { - using FunctionsRequest for FunctionsRequest.Request; - - IFunctionsRouter internal immutable i_functionsRouter; - - event RequestSent(bytes32 indexed id); - event RequestFulfilled(bytes32 indexed id); - - error OnlyRouterCanFulfill(); - - constructor(address router) { - i_functionsRouter = IFunctionsRouter(router); - } - - /// @notice Sends a Chainlink Functions request - /// @param data The CBOR encoded bytes data for a Functions request - /// @param subscriptionId The subscription ID that will be charged to service the request - /// @param callbackGasLimit the amount of gas that will be available for the fulfillment callback - /// @return requestId The generated request ID for this request - function _sendRequest( - bytes memory data, - uint64 subscriptionId, - uint32 callbackGasLimit, - bytes32 donId - ) internal returns (bytes32) { - bytes32 requestId = i_functionsRouter.sendRequest( - subscriptionId, - data, - FunctionsRequest.REQUEST_DATA_VERSION, - callbackGasLimit, - donId - ); - emit RequestSent(requestId); - return requestId; - } - - /// @notice User defined function to handle a response from the DON - /// @param requestId The request ID, returned by sendRequest() - /// @param response Aggregated response from the execution of the user's source code - /// @param err Aggregated error from the execution of the user code or from the execution pipeline - /// @dev Either response or error parameter will be set, but never both - function _fulfillRequest(bytes32 requestId, bytes memory response, bytes memory err) internal virtual; - - /// @inheritdoc IFunctionsClient - function handleOracleFulfillment(bytes32 requestId, bytes memory response, bytes memory err) external override { - if (msg.sender != address(i_functionsRouter)) { - revert OnlyRouterCanFulfill(); - } - _fulfillRequest(requestId, response, err); - emit RequestFulfilled(requestId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol deleted file mode 100644 index 9c7f359..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/FunctionsCoordinator.sol +++ /dev/null @@ -1,228 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IFunctionsCoordinator} from "../v1_0_0/interfaces/IFunctionsCoordinator.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {FunctionsBilling, FunctionsBillingConfig} from "./FunctionsBilling.sol"; -import {OCR2Base} from "./ocr/OCR2Base.sol"; -import {FunctionsResponse} from "../v1_0_0/libraries/FunctionsResponse.sol"; - -/// @title Functions Coordinator contract -/// @notice Contract that nodes of a Decentralized Oracle Network (DON) interact with -contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilling { - using FunctionsResponse for FunctionsResponse.RequestMeta; - using FunctionsResponse for FunctionsResponse.Commitment; - using FunctionsResponse for FunctionsResponse.FulfillResult; - - /// @inheritdoc ITypeAndVersion - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override typeAndVersion = "Functions Coordinator v1.3.0"; - - event OracleRequest( - bytes32 indexed requestId, - address indexed requestingContract, - address requestInitiator, - uint64 subscriptionId, - address subscriptionOwner, - bytes data, - uint16 dataVersion, - bytes32 flags, - uint64 callbackGasLimit, - FunctionsResponse.Commitment commitment - ); - event OracleResponse(bytes32 indexed requestId, address transmitter); - - error InconsistentReportData(); - error EmptyPublicKey(); - error UnauthorizedPublicKeyChange(); - - bytes private s_donPublicKey; - bytes private s_thresholdPublicKey; - - constructor( - address router, - FunctionsBillingConfig memory config, - address linkToNativeFeed, - address linkToUsdFeed - ) OCR2Base() FunctionsBilling(router, config, linkToNativeFeed, linkToUsdFeed) {} - - /// @inheritdoc IFunctionsCoordinator - function getThresholdPublicKey() external view override returns (bytes memory) { - if (s_thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setThresholdPublicKey(bytes calldata thresholdPublicKey) external override onlyOwner { - if (thresholdPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_thresholdPublicKey = thresholdPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function getDONPublicKey() external view override returns (bytes memory) { - if (s_donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - return s_donPublicKey; - } - - /// @inheritdoc IFunctionsCoordinator - function setDONPublicKey(bytes calldata donPublicKey) external override onlyOwner { - if (donPublicKey.length == 0) { - revert EmptyPublicKey(); - } - s_donPublicKey = donPublicKey; - } - - /// @dev check if node is in current transmitter list - function _isTransmitter(address node) internal view returns (bool) { - // Bounded by "maxNumOracles" on OCR2Abstract.sol - for (uint256 i = 0; i < s_transmitters.length; ++i) { - if (s_transmitters[i] == node) { - return true; - } - } - return false; - } - - /// @inheritdoc IFunctionsCoordinator - function startRequest( - FunctionsResponse.RequestMeta calldata request - ) external override onlyRouter returns (FunctionsResponse.Commitment memory commitment) { - uint72 operationFee; - (commitment, operationFee) = _startBilling(request); - - emit OracleRequest( - commitment.requestId, - request.requestingContract, - // solhint-disable-next-line avoid-tx-origin - tx.origin, - request.subscriptionId, - request.subscriptionOwner, - request.data, - request.dataVersion, - request.flags, - request.callbackGasLimit, - FunctionsResponse.Commitment({ - coordinator: commitment.coordinator, - client: commitment.client, - subscriptionId: commitment.subscriptionId, - callbackGasLimit: commitment.callbackGasLimit, - estimatedTotalCostJuels: commitment.estimatedTotalCostJuels, - timeoutTimestamp: commitment.timeoutTimestamp, - requestId: commitment.requestId, - donFee: commitment.donFee, - gasOverheadBeforeCallback: commitment.gasOverheadBeforeCallback, - gasOverheadAfterCallback: commitment.gasOverheadAfterCallback, - // The following line is done to use the Coordinator's operationFee in place of the Router's operation fee - // With this in place the Router.adminFee must be set to 0 in the Router. - adminFee: operationFee - }) - ); - - return commitment; - } - - /// @dev DON fees are pooled together. If the OCR configuration is going to change, these need to be distributed. - function _beforeSetConfig(uint8 /* _f */, bytes memory /* _onchainConfig */) internal override { - if (_getTransmitters().length > 0) { - _disperseFeePool(); - } - } - - /// @dev Used by FunctionsBilling.sol - function _getTransmitters() internal view override returns (address[] memory) { - return s_transmitters; - } - - function _beforeTransmit( - bytes calldata report - ) internal view override returns (bool shouldStop, DecodedReport memory decodedReport) { - ( - bytes32[] memory requestIds, - bytes[] memory results, - bytes[] memory errors, - bytes[] memory onchainMetadata, - bytes[] memory offchainMetadata - ) = abi.decode(report, (bytes32[], bytes[], bytes[], bytes[], bytes[])); - uint256 numberOfFulfillments = uint8(requestIds.length); - - if ( - numberOfFulfillments == 0 || - numberOfFulfillments != results.length || - numberOfFulfillments != errors.length || - numberOfFulfillments != onchainMetadata.length || - numberOfFulfillments != offchainMetadata.length - ) { - revert ReportInvalid("Fields must be equal length"); - } - - for (uint256 i = 0; i < numberOfFulfillments; ++i) { - if (_isExistingRequest(requestIds[i])) { - // If there is an existing request, validate report - // Leave shouldStop to default, false - break; - } - if (i == numberOfFulfillments - 1) { - // If the last fulfillment on the report does not exist, then all are duplicates - // Indicate that it's safe to stop to save on the gas of validating the report - shouldStop = true; - } - } - - return ( - shouldStop, - DecodedReport({ - requestIds: requestIds, - results: results, - errors: errors, - onchainMetadata: onchainMetadata, - offchainMetadata: offchainMetadata - }) - ); - } - - /// @dev Report hook called within OCR2Base.sol - function _report(DecodedReport memory decodedReport) internal override { - uint256 numberOfFulfillments = uint8(decodedReport.requestIds.length); - - // Bounded by "MaxRequestBatchSize" on the Job's ReportingPluginConfig - for (uint256 i = 0; i < numberOfFulfillments; ++i) { - FunctionsResponse.FulfillResult result = FunctionsResponse.FulfillResult( - _fulfillAndBill( - decodedReport.requestIds[i], - decodedReport.results[i], - decodedReport.errors[i], - decodedReport.onchainMetadata[i], - decodedReport.offchainMetadata[i], - uint8(numberOfFulfillments) // will not exceed "MaxRequestBatchSize" on the Job's ReportingPluginConfig - ) - ); - - // Emit on successfully processing the fulfillment - // In these two fulfillment results the user has been charged - // Otherwise, the DON will re-try - if ( - result == FunctionsResponse.FulfillResult.FULFILLED || - result == FunctionsResponse.FulfillResult.USER_CALLBACK_ERROR - ) { - emit OracleResponse(decodedReport.requestIds[i], msg.sender); - } - } - } - - /// @dev Used in FunctionsBilling.sol - function _onlyOwner() internal view override { - _validateOwnership(); - } - - /// @dev Used in FunctionsBilling.sol - function _owner() internal view override returns (address owner) { - return this.owner(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol deleted file mode 100644 index 1d9a3b9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/TermsOfServiceAllowList.sol +++ /dev/null @@ -1,205 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITermsOfServiceAllowList, TermsOfServiceAllowListConfig} from "./interfaces/ITermsOfServiceAllowList.sol"; -import {IAccessController} from "../../../shared/interfaces/IAccessController.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; - -import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, ITypeAndVersion, ConfirmedOwner { - using Address for address; - using EnumerableSet for EnumerableSet.AddressSet; - - /// @inheritdoc ITypeAndVersion - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.0"; - - EnumerableSet.AddressSet private s_allowedSenders; - EnumerableSet.AddressSet private s_blockedSenders; - - event AddedAccess(address user); - event BlockedAccess(address user); - event UnblockedAccess(address user); - - error InvalidSignature(); - error InvalidUsage(); - error RecipientIsBlocked(); - error InvalidCalldata(); - - TermsOfServiceAllowListConfig private s_config; - - event ConfigUpdated(TermsOfServiceAllowListConfig config); - - // ================================================================ - // | Initialization | - // ================================================================ - - constructor( - TermsOfServiceAllowListConfig memory config, - address[] memory initialAllowedSenders, - address[] memory initialBlockedSenders - ) ConfirmedOwner(msg.sender) { - updateConfig(config); - - for (uint256 i = 0; i < initialAllowedSenders.length; ++i) { - s_allowedSenders.add(initialAllowedSenders[i]); - } - - for (uint256 j = 0; j < initialBlockedSenders.length; ++j) { - if (s_allowedSenders.contains(initialBlockedSenders[j])) { - // Allowed senders cannot also be blocked - revert InvalidCalldata(); - } - s_blockedSenders.add(initialBlockedSenders[j]); - } - } - - // ================================================================ - // | Configuration | - // ================================================================ - - /// @notice Gets the contracts's configuration - /// @return config - function getConfig() external view returns (TermsOfServiceAllowListConfig memory) { - return s_config; - } - - /// @notice Sets the contracts's configuration - /// @param config - See the contents of the TermsOfServiceAllowListConfig struct in ITermsOfServiceAllowList.sol for more information - function updateConfig(TermsOfServiceAllowListConfig memory config) public onlyOwner { - s_config = config; - emit ConfigUpdated(config); - } - - // ================================================================ - // | Allow methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function getMessage(address acceptor, address recipient) public pure override returns (bytes32) { - return keccak256(abi.encodePacked(acceptor, recipient)); - } - - /// @inheritdoc ITermsOfServiceAllowList - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external override { - if (s_blockedSenders.contains(recipient)) { - revert RecipientIsBlocked(); - } - - // Validate that the signature is correct and the correct data has been signed - bytes32 prefixedMessage = keccak256( - abi.encodePacked("\x19Ethereum Signed Message:\n32", getMessage(acceptor, recipient)) - ); - if (ecrecover(prefixedMessage, v, r, s) != s_config.signerPublicKey) { - revert InvalidSignature(); - } - - // If contract, validate that msg.sender == recipient - // This is to prevent EoAs from claiming contracts that they are not in control of - // If EoA, validate that msg.sender == acceptor == recipient - // This is to prevent EoAs from accepting for other EoAs - if (msg.sender != recipient || (msg.sender != acceptor && !msg.sender.isContract())) { - revert InvalidUsage(); - } - - // Add recipient to the allow list - if (s_allowedSenders.add(recipient)) { - emit AddedAccess(recipient); - } - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllAllowedSenders() external view override returns (address[] memory) { - return s_allowedSenders.values(); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllowedSendersCount() external view override returns (uint64) { - return uint64(s_allowedSenders.length()); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getAllowedSendersInRange( - uint64 allowedSenderIdxStart, - uint64 allowedSenderIdxEnd - ) external view override returns (address[] memory allowedSenders) { - if ( - allowedSenderIdxStart > allowedSenderIdxEnd || - allowedSenderIdxEnd >= s_allowedSenders.length() || - s_allowedSenders.length() == 0 - ) { - revert InvalidCalldata(); - } - - allowedSenders = new address[]((allowedSenderIdxEnd - allowedSenderIdxStart) + 1); - for (uint256 i = 0; i <= allowedSenderIdxEnd - allowedSenderIdxStart; ++i) { - allowedSenders[i] = s_allowedSenders.at(uint256(allowedSenderIdxStart + i)); - } - - return allowedSenders; - } - - /// @inheritdoc IAccessController - function hasAccess(address user, bytes calldata /* data */) external view override returns (bool) { - if (!s_config.enabled) { - return true; - } - return s_allowedSenders.contains(user); - } - - // ================================================================ - // | Block methods | - // ================================================================ - - /// @inheritdoc ITermsOfServiceAllowList - function isBlockedSender(address sender) external view override returns (bool) { - if (!s_config.enabled) { - return false; - } - return s_blockedSenders.contains(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function blockSender(address sender) external override onlyOwner { - s_allowedSenders.remove(sender); - s_blockedSenders.add(sender); - emit BlockedAccess(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function unblockSender(address sender) external override onlyOwner { - s_blockedSenders.remove(sender); - emit UnblockedAccess(sender); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getBlockedSendersCount() external view override returns (uint64) { - return uint64(s_blockedSenders.length()); - } - - /// @inheritdoc ITermsOfServiceAllowList - function getBlockedSendersInRange( - uint64 blockedSenderIdxStart, - uint64 blockedSenderIdxEnd - ) external view override returns (address[] memory blockedSenders) { - if ( - blockedSenderIdxStart > blockedSenderIdxEnd || - blockedSenderIdxEnd >= s_blockedSenders.length() || - s_blockedSenders.length() == 0 - ) { - revert InvalidCalldata(); - } - - blockedSenders = new address[]((blockedSenderIdxEnd - blockedSenderIdxStart) + 1); - for (uint256 i = 0; i <= blockedSenderIdxEnd - blockedSenderIdxStart; ++i) { - blockedSenders[i] = s_blockedSenders.at(uint256(blockedSenderIdxStart + i)); - } - - return blockedSenders; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol deleted file mode 100644 index 65db9c4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/accessControl/interfaces/ITermsOfServiceAllowList.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @notice A contract to handle access control of subscription management dependent on signing a Terms of Service -interface ITermsOfServiceAllowList { - /// @notice Return the message data for the proof given to accept the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @return Hash of the message data - function getMessage(address acceptor, address recipient) external pure returns (bytes32); - - /// @notice Check if the address is blocked for usage - /// @param sender The transaction sender's address - /// @return True or false - function isBlockedSender(address sender) external returns (bool); - - /// @notice Get a list of all allowed senders - /// @dev WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - /// to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - /// this function has an unbounded cost, and using it as part of a state-changing function may render the function - /// uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - /// @return addresses - all allowed addresses - function getAllAllowedSenders() external view returns (address[] memory); - - /// @notice Get details about the total number of allowed senders - /// @return count - total number of allowed senders in the system - function getAllowedSendersCount() external view returns (uint64); - - /// @notice Retrieve a list of allowed senders using an inclusive range - /// @dev WARNING: getAllowedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list - /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. - /// Evaluate if eventual consistency will satisfy your usecase before using it. - /// @param allowedSenderIdxStart - index of the allowed sender to start the range at - /// @param allowedSenderIdxEnd - index of the allowed sender to end the range at - /// @return allowedSenders - allowed addresses in the range provided - function getAllowedSendersInRange( - uint64 allowedSenderIdxStart, - uint64 allowedSenderIdxEnd - ) external view returns (address[] memory allowedSenders); - - /// @notice Allows access to the sender based on acceptance of the Terms of Service - /// @param acceptor - The wallet address that has accepted the Terms of Service on the UI - /// @param recipient - The recipient address that the acceptor is taking responsibility for - /// @param r - ECDSA signature r data produced by the Chainlink Functions Subscription UI - /// @param s - ECDSA signature s produced by the Chainlink Functions Subscription UI - /// @param v - ECDSA signature v produced by the Chainlink Functions Subscription UI - function acceptTermsOfService(address acceptor, address recipient, bytes32 r, bytes32 s, uint8 v) external; - - /// @notice Removes a sender's access if already authorized, and disallows re-accepting the Terms of Service - /// @param sender - Address of the sender to block - function blockSender(address sender) external; - - /// @notice Re-allows a previously blocked sender to accept the Terms of Service - /// @param sender - Address of the sender to unblock - function unblockSender(address sender) external; - - /// @notice Get details about the total number of blocked senders - /// @return count - total number of blocked senders in the system - function getBlockedSendersCount() external view returns (uint64); - - /// @notice Retrieve a list of blocked senders using an inclusive range - /// @dev WARNING: getBlockedSendersInRange uses EnumerableSet .length() and .at() methods to iterate over the list - /// without the need for an extra mapping. These method can not guarantee the ordering when new elements are added. - /// Evaluate if eventual consistency will satisfy your usecase before using it. - /// @param blockedSenderIdxStart - index of the blocked sender to start the range at - /// @param blockedSenderIdxEnd - index of the blocked sender to end the range at - /// @return blockedSenders - blocked addresses in the range provided - function getBlockedSendersInRange( - uint64 blockedSenderIdxStart, - uint64 blockedSenderIdxEnd - ) external view returns (address[] memory blockedSenders); -} - -// ================================================================ -// | Configuration state | -// ================================================================ -struct TermsOfServiceAllowListConfig { - bool enabled; // ═════════════╗ When enabled, access will be checked against s_allowedSenders. When disabled, all access will be allowed. - address signerPublicKey; // ══╝ The key pair that needs to sign the acceptance data -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol deleted file mode 100644 index 79806f1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/interfaces/IFunctionsBilling.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @title Chainlink Functions DON billing interface. -interface IFunctionsBilling { - /// @notice Return the current conversion from WEI of ETH to LINK from the configured Chainlink data feed - /// @return weiPerUnitLink - The amount of WEI in one LINK - function getWeiPerUnitLink() external view returns (uint256); - - /// @notice Return the current conversion from LINK to USD from the configured Chainlink data feed - /// @return weiPerUnitLink - The amount of USD that one LINK is worth - /// @return decimals - The number of decimals that should be represented in the price feed's response - function getUsdPerUnitLink() external view returns (uint256, uint8); - - /// @notice Determine the fee that will be split between Node Operators for servicing a request - /// @param requestCBOR - CBOR encoded Chainlink Functions request data, use FunctionsRequest library to encode a request - /// @return fee - Cost in Juels (1e18) of LINK - function getDONFeeJuels(bytes memory requestCBOR) external view returns (uint72); - - /// @notice Determine the fee that will be paid to the Coordinator owner for operating the network - /// @return fee - Cost in Juels (1e18) of LINK - function getOperationFeeJuels() external view returns (uint72); - - /// @notice Determine the fee that will be paid to the Router owner for operating the network - /// @return fee - Cost in Juels (1e18) of LINK - function getAdminFeeJuels() external view returns (uint72); - - /// @notice Estimate the total cost that will be charged to a subscription to make a request: transmitter gas re-reimbursement, plus DON fee, plus Registry fee - /// @param - subscriptionId An identifier of the billing account - /// @param - data Encoded Chainlink Functions request data, use FunctionsClient API to encode a request - /// @param - callbackGasLimit Gas limit for the fulfillment callback - /// @param - gasPriceWei The blockchain's gas price to estimate with - /// @return - billedCost Cost in Juels (1e18) of LINK - function estimateCost( - uint64 subscriptionId, - bytes calldata data, - uint32 callbackGasLimit, - uint256 gasPriceWei - ) external view returns (uint96); - - /// @notice Remove a request commitment that the Router has determined to be stale - /// @param requestId - The request ID to remove - function deleteCommitment(bytes32 requestId) external; - - /// @notice Oracle withdraw LINK earned through fulfilling requests - /// @notice If amount is 0 the full balance will be withdrawn - /// @param recipient where to send the funds - /// @param amount amount to withdraw - function oracleWithdraw(address recipient, uint96 amount) external; - - /// @notice Withdraw all LINK earned by Oracles through fulfilling requests - /// @dev transmitter addresses must support LINK tokens to avoid tokens from getting stuck as oracleWithdrawAll() calls will forward tokens directly to transmitters - function oracleWithdrawAll() external; -} - -// ================================================================ -// | Configuration state | -// ================================================================ - -struct FunctionsBillingConfig { - uint32 fulfillmentGasPriceOverEstimationBP; // ══╗ Percentage of gas price overestimation to account for changes in gas price between request and response. Held as basis points (one hundredth of 1 percentage point) - uint32 feedStalenessSeconds; // ║ How long before we consider the feed price to be stale and fallback to fallbackNativePerUnitLink. - uint32 gasOverheadBeforeCallback; // ║ Represents the average gas execution cost before the fulfillment callback. This amount is always billed for every request. - uint32 gasOverheadAfterCallback; // ║ Represents the average gas execution cost after the fulfillment callback. This amount is always billed for every request. - uint40 minimumEstimateGasPriceWei; // ║ The lowest amount of wei that will be used as the tx.gasprice when estimating the cost to fulfill the request - uint16 maxSupportedRequestDataVersion; // ║ The highest support request data version supported by the node. All lower versions should also be supported. - uint64 fallbackUsdPerUnitLink; // ║ Fallback LINK / USD conversion rate if the data feed is stale - uint8 fallbackUsdPerUnitLinkDecimals; // ════════╝ Fallback LINK / USD conversion rate decimal places if the data feed is stale - 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. -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol deleted file mode 100644 index 4182227..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /** - * @notice triggers a new run of the offchain reporting protocol - * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - * @param configDigest configDigest of this configuration - * @param configCount ordinal number of this config setting among all config settings over the life of this contract - * @param signers ith element is address ith oracle uses to sign a report - * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param transmitters addresses oracles use to transmit the reports - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - /** - * @notice optionally emited to indicate the latest configDigest and epoch for - which a report was successfully transmited. Alternatively, the contract may - use latestConfigDigestAndEpoch with scanLogs set to false. - */ - event Transmitted(bytes32 configDigest, uint32 epoch); - - /** - * @notice optionally returns the latest configDigest and epoch for which a - report was successfully transmitted. Alternatively, the contract may return - scanLogs set to true and use Transmitted events to provide this information - to offchain watchers. - * @return scanLogs indicates whether to rely on the configDigest and epoch - returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol deleted file mode 100644 index 565e7d8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/functions/v1_3_0/ocr/OCR2Base.sol +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/** - * @notice Onchain verification of reports from the offchain reporting protocol - * @dev For details on its operation, see the offchain reporting protocol design - * doc, which refers to this contract as simply the "contract". - */ -abstract contract OCR2Base is ConfirmedOwner, OCR2Abstract { - error ReportInvalid(string message); - error InvalidConfig(string message); - - constructor() ConfirmedOwner(msg.sender) {} - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - uint32 internal s_latestConfigBlockNumber; // makes it easier for offchain systems - // to extract config from logs. - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a single SLOAD. If any further fields are - // added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // TODO: could be optimized by squeezing into one slot - uint8 n; - } - ConfigInfo internal s_configInfo; - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - mapping(address signerOrTransmitter => Oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - struct DecodedReport { - bytes32[] requestIds; - bytes[] results; - bytes[] errors; - bytes[] onchainMetadata; - bytes[] offchainMetadata; - } - - /* - * Config logic - */ - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - // solhint-disable-next-line gas-struct-packing - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param _signers addresses with which oracles sign the reports - * @param _transmitters addresses oracles use to transmit the reports - * @param _f number of faulty oracles the system can tolerate - * @param _onchainConfig encoded on-chain contract configuration - * @param _offchainConfigVersion version number for offchainEncoding schema - * @param _offchainConfig encoded off-chain oracle configuration - */ - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < args.signers.length; i++) { - if (args.signers[i] == address(0)) revert InvalidConfig("signer must not be empty"); - if (args.transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); - // add new signer/transmitter addresses - if (s_oracles[args.signers[i]].role != Role.Unset) revert InvalidConfig("repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - if (s_oracles[args.transmitters[i]].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - - function _configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /** - * @return list of addresses permitted to transmit reports to this contract - * @dev The list will match the order used to specify the transmitter during setConfig - */ - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /** - * @dev hook called after the report has been fully validated - * for the extending contract to handle additional logic, such as oracle payment - * @param decodedReport decodedReport - */ - function _report(DecodedReport memory decodedReport) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function _requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - if (msg.data.length != expected) revert ReportInvalid("calldata length mismatch"); - } - - function _beforeTransmit( - bytes calldata report - ) internal virtual returns (bool shouldStop, DecodedReport memory decodedReport); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - (bool shouldStop, DecodedReport memory decodedReport) = _beforeTransmit(report); - - if (shouldStop) { - return; - } - - { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - // The following check is disabled to allow both current and proposed routes to submit reports using the same OCR config digest - // Chainlink Functions uses globally unique request IDs. Metadata about the request is stored and checked in the Coordinator and Router - // require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - _requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures = (s_configInfo.n + s_configInfo.f) / 2 + 1; - - if (rs.length != expectedNumSignatures) revert ReportInvalid("wrong number of signatures"); - if (rs.length != ss.length) revert ReportInvalid("report rs and ss must be of equal length"); - - Oracle memory transmitter = s_oracles[msg.sender]; - if (transmitter.role != Role.Transmitter && msg.sender != s_transmitters[transmitter.index]) - revert ReportInvalid("unauthorized transmitter"); - } - - address[MAX_NUM_ORACLES] memory signed; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - if (o.role != Role.Signer) revert ReportInvalid("address not authorized to sign"); - if (signed[o.index] != address(0)) revert ReportInvalid("non-unique signature"); - signed[o.index] = signer; - } - } - - _report(decodedReport); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol deleted file mode 100644 index 5ee9cbb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface ChainlinkRequestInterface { - function oracleRequest( - address sender, - uint256 requestPrice, - bytes32 serviceAgreementID, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunctionId, - uint256 expiration - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol deleted file mode 100644 index 2592b69..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface ENSInterface { - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed node, address owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed node, address resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed node, uint64 ttl); - - function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external; - - function setResolver(bytes32 node, address resolver) external; - - function setOwner(bytes32 node, address owner) external; - - function setTTL(bytes32 node, uint64 ttl) external; - - function owner(bytes32 node) external view returns (address); - - function resolver(bytes32 node) external view returns (address); - - function ttl(bytes32 node) external view returns (uint64); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol deleted file mode 100644 index 6e353a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FeedRegistryInterface.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; -pragma abicoder v2; - -import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; - -// solhint-disable-next-line interface-starts-with-i -interface FeedRegistryInterface { - struct Phase { - uint16 phaseId; - uint80 startingAggregatorRoundId; - uint80 endingAggregatorRoundId; - } - - event FeedProposed( - address indexed asset, - address indexed denomination, - address indexed proposedAggregator, - address currentAggregator, - address sender - ); - event FeedConfirmed( - address indexed asset, - address indexed denomination, - address indexed latestAggregator, - address previousAggregator, - uint16 nextPhaseId, - address sender - ); - - // V3 AggregatorV3Interface - - function decimals(address base, address quote) external view returns (uint8); - - function description(address base, address quote) external view returns (string memory); - - function version(address base, address quote) external view returns (uint256); - - function latestRoundData( - address base, - address quote - ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - function getRoundData( - address base, - address quote, - uint80 _roundId - ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - // V2 AggregatorInterface - - function latestAnswer(address base, address quote) external view returns (int256 answer); - - function latestTimestamp(address base, address quote) external view returns (uint256 timestamp); - - function latestRound(address base, address quote) external view returns (uint256 roundId); - - function getAnswer(address base, address quote, uint256 roundId) external view returns (int256 answer); - - function getTimestamp(address base, address quote, uint256 roundId) external view returns (uint256 timestamp); - - // Registry getters - - function getFeed(address base, address quote) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseFeed( - address base, - address quote, - uint16 phaseId - ) external view returns (AggregatorV2V3Interface aggregator); - - function isFeedEnabled(address aggregator) external view returns (bool); - - function getPhase(address base, address quote, uint16 phaseId) external view returns (Phase memory phase); - - // Round helpers - - function getRoundFeed( - address base, - address quote, - uint80 roundId - ) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseRange( - address base, - address quote, - uint16 phaseId - ) external view returns (uint80 startingRoundId, uint80 endingRoundId); - - function getPreviousRoundId( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 previousRoundId); - - function getNextRoundId(address base, address quote, uint80 roundId) external view returns (uint80 nextRoundId); - - // Feed management - - function proposeFeed(address base, address quote, address aggregator) external; - - function confirmFeed(address base, address quote, address aggregator) external; - - // Proposed aggregator - - function getProposedFeed( - address base, - address quote - ) external view returns (AggregatorV2V3Interface proposedAggregator); - - function proposedGetRoundData( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - function proposedLatestRoundData( - address base, - address quote - ) external view returns (uint80 id, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - // Phases - function getCurrentPhaseId(address base, address quote) external view returns (uint16 currentPhaseId); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol deleted file mode 100644 index beb2b58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/FlagsInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface FlagsInterface { - function getFlag(address) external view returns (bool); - - function getFlags(address[] calldata) external view returns (bool[] memory); - - function raiseFlag(address) external; - - function raiseFlags(address[] calldata) external; - - function lowerFlags(address[] calldata) external; - - function setRaisingAccessController(address) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol deleted file mode 100644 index b457a50..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {OracleInterface} from "./OracleInterface.sol"; -import {ChainlinkRequestInterface} from "./ChainlinkRequestInterface.sol"; - -// solhint-disable-next-line interface-starts-with-i -interface OperatorInterface is OracleInterface, ChainlinkRequestInterface { - function operatorRequest( - address sender, - uint256 payment, - bytes32 specId, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function fulfillOracleRequest2( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes calldata data - ) external returns (bool); - - function ownerTransferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); - - function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol deleted file mode 100644 index 6e7aa29..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface OracleInterface { - function fulfillOracleRequest( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes32 data - ) external returns (bool); - - function withdraw(address recipient, uint256 amount) external; - - function withdrawable() external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol deleted file mode 100644 index af06e29..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PoRAddressList.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @title Chainlink Proof-of-Reserve address list interface. - * @notice This interface enables Chainlink nodes to get the list addresses to be used in a PoR feed. A single - * contract that implements this interface can only store an address list for a single PoR feed. - * @dev All functions in this interface are expected to be called off-chain, so gas usage is not a big concern. - * This makes it possible to store addresses in optimized data types and convert them to human-readable strings - * in `getPoRAddressList()`. - */ -// solhint-disable-next-line interface-starts-with-i -interface PoRAddressList { - /// @notice Get total number of addresses in the list. - function getPoRAddressListLength() external view returns (uint256); - - /** - * @notice Get a batch of human-readable addresses from the address list. The requested batch size can be greater - * than the actual address list size, in which the full address list will be returned. - * @dev Due to limitations of gas usage in off-chain calls, we need to support fetching the addresses in batches. - * EVM addresses need to be converted to human-readable strings. The address strings need to be in the same format - * that would be used when querying the balance of that address. - * @param startIndex The index of the first address in the batch. - * @param endIndex The index of the last address in the batch. If `endIndex > getPoRAddressListLength()-1`, - * endIndex need to default to `getPoRAddressListLength()-1`. - * @return Array of addresses as strings. - */ - function getPoRAddressList(uint256 startIndex, uint256 endIndex) external view returns (string[] memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol deleted file mode 100644 index ca0b1de..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface PointerInterface { - function getAddress() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol deleted file mode 100644 index 786f275..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/interfaces/TypeAndVersionInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -abstract contract TypeAndVersionInterface { - function typeAndVersion() external pure virtual returns (string memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol deleted file mode 100644 index 2e9211f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol +++ /dev/null @@ -1,1055 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; -import {ICapabilityConfiguration} from "./interfaces/ICapabilityConfiguration.sol"; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; - -import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; -import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; - -/// @notice CapabilitiesRegistry is used to manage Nodes (including their links to Node Operators), Capabilities, -/// and DONs (Decentralized Oracle Networks) which are sets of nodes that support those Capabilities. -/// @dev The contract currently stores the entire state of Node Operators, Nodes, Capabilities and DONs in the -/// contract and requires a full state migration if an upgrade is ever required. The team acknowledges this and is -/// fine reconfiguring the upgraded contract in the future so as to not add extra complexity to this current version. -contract CapabilitiesRegistry is OwnerIsCreator, ITypeAndVersion { - // Add the library methods - using EnumerableSet for EnumerableSet.Bytes32Set; - using EnumerableSet for EnumerableSet.UintSet; - - struct NodeOperator { - /// @notice The address of the admin that can manage a node operator - address admin; - /// @notice Human readable name of a Node Operator managing the node - /// @dev The contract does not validate the length or characters of the node operator name because - /// a trusted admin will supply these names. We reduce gas costs by omitting these checks on-chain. - string name; - } - - struct NodeParams { - /// @notice The id of the node operator that manages this node - uint32 nodeOperatorId; - /// @notice The signer address for application-layer message verification. - bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed to - /// be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. - bytes32 p2pId; - /// @notice Public key used to encrypt secrets for this node - bytes32 encryptionPublicKey; - /// @notice The list of hashed capability IDs supported by the node - bytes32[] hashedCapabilityIds; - } - - struct NodeInfo { - /// @notice The id of the node operator that manages this node - uint32 nodeOperatorId; - /// @notice The number of times the node's configuration has been updated - uint32 configCount; - /// @notice The ID of the Workflow DON that the node belongs to. A node can - /// only belong to one DON that accepts Workflows. - uint32 workflowDONId; - /// @notice The signer address for application-layer message verification. - bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed - /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. - bytes32 p2pId; - /// @notice Public key used to encrypt secrets for this node - bytes32 encryptionPublicKey; - /// @notice The list of hashed capability IDs supported by the node - bytes32[] hashedCapabilityIds; - /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple - /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one. - uint256[] capabilitiesDONIds; - } - - struct Node { - /// @notice The node's parameters - /// @notice The id of the node operator that manages this node - uint32 nodeOperatorId; - /// @notice The number of times the node's configuration has been updated - uint32 configCount; - /// @notice The ID of the Workflow DON that the node belongs to. A node can - /// only belong to one DON that accepts Workflows. - uint32 workflowDONId; - /// @notice The signer address for application-layer message verification. - /// @dev This key is guaranteed to be unique in the CapabilitiesRegistry as a signer - /// address can only belong to one node. - /// @dev This should be the ABI encoded version of the node's address. I.e 0x0000address. The Capability Registry - /// does not store it as an address so that non EVM chains with addresses greater than 20 bytes can be supported - /// in the future. - bytes32 signer; - /// @notice This is an Ed25519 public key that is used to identify a node. This key is guaranteed - /// to be unique in the CapabilitiesRegistry. It is used to identify a node in the the P2P network. - bytes32 p2pId; - /// @notice Public key used to encrypt secrets for this node - bytes32 encryptionPublicKey; - /// @notice The node's supported capabilities - /// @dev This is stored as a map so that we can easily update to a set of new capabilities by - /// incrementing the configCount and creating a new set of supported capability IDs - mapping(uint32 configCount => EnumerableSet.Bytes32Set capabilityId) supportedHashedCapabilityIds; - /// @notice The list of capabilities DON Ids supported by the node. A node can belong to multiple - /// capabilities DONs. This list does not include a Workflow DON id if the node belongs to one. - EnumerableSet.UintSet capabilitiesDONIds; - } - - /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is - /// an already aggregated report. There are multiple possible ways to aggregate. - /// @dev REPORT response type receives signatures together with the response that is used to verify the data. - /// OBSERVATION_IDENTICAL just receives data without signatures and waits for some number of observations before - /// proceeding to the next step - enum CapabilityResponseType { - // No additional aggregation is needed on the remote response. - REPORT, - // A number of identical observations need to be aggregated. - OBSERVATION_IDENTICAL - } - - /// @notice CapabilityType indicates the type of capability which determines - /// where the capability can be used in a Workflow Spec. - enum CapabilityType { - TRIGGER, - ACTION, - CONSENSUS, - TARGET - } - - struct Capability { - /// @notice The partially qualified ID for the capability. - /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} - /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` - /// portion of the ID. - /// - /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" - /// labelledName = "data-streams-reports:chain:ethereum" - string labelledName; - /// @notice Semver, e.g., "1.2.3" - /// @dev must be valid Semver + max 32 characters. - string version; - /// @notice CapabilityType indicates the type of capability which determines - /// where the capability can be used in a Workflow Spec. - CapabilityType capabilityType; - /// @notice CapabilityResponseType indicates whether remote response requires aggregation or is an - /// already aggregated report. There are multiple possible ways to aggregate. - CapabilityResponseType responseType; - /// @notice An address to the capability configuration contract. Having this defined on a capability enforces - /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement - /// CapabilityConfigurationContractInterface. - /// - /// @dev The main use cases are: - /// 1) Sharing capability configuration across DON instances - /// 2) Inspect and modify on-chain configuration without off-chain capability code. - /// - /// It is not recommended to store configuration which requires knowledge of the DON membership. - address configurationContract; - } - - struct CapabilityInfo { - /// @notice A hashed ID created by the `getHashedCapabilityId` function. - bytes32 hashedId; - /// @notice The partially qualified ID for the capability. - /// @dev Given the following capability ID: {name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}@{version} - /// Then we denote the `labelledName` as the `{name}:{label1_key}_{label1_value}:{label2_key}_{label2_value}` - /// portion of the ID. - /// - /// Ex. id = "data-streams-reports:chain:ethereum@1.0.0" - /// labelledName = "data-streams-reports:chain:ethereum" - string labelledName; - /// @notice Semver, e.g., "1.2.3" - /// @dev must be valid Semver + max 32 characters. - string version; - /// @notice CapabilityType indicates the type of capability which determines - /// where the capability can be used in a Workflow Spec. - CapabilityType capabilityType; - /// @notice CapabilityResponseType indicates whether remote response requires aggregation - /// or is an already aggregated report. There are multiple possible ways to aggregate. - CapabilityResponseType responseType; - /// @notice An address to the capability configuration contract. Having this defined on a capability enforces - /// consistent configuration across DON instances serving the same capability. Configuration contract MUST implement - /// CapabilityConfigurationContractInterface. - /// - /// @dev The main use cases are: - /// 1) Sharing capability configuration across DON instances - /// 2) Inspect and modify on-chain configuration without off-chain capability code. - /// - /// It is not recommended to store configuration which requires knowledge of the DON membership. - address configurationContract; - /// @notice True if the capability is deprecated - bool isDeprecated; - } - - /// @notice CapabilityConfiguration is a struct that holds the capability configuration - /// for a specific DON - struct CapabilityConfiguration { - /// @notice The capability Id - bytes32 capabilityId; - /// @notice The capability config specific to a DON. This will be decoded offchain - bytes config; - } - - struct DONCapabilityConfig { - /// @notice The set of p2pIds of nodes that belong to this DON. A node (the same p2pId) can belong to multiple DONs. - EnumerableSet.Bytes32Set nodes; - /// @notice The set of capabilityIds - bytes32[] capabilityIds; - /// @notice Mapping from hashed capability IDs to configs - mapping(bytes32 capabilityId => bytes config) capabilityConfigs; - } - - /// @notice DON (Decentralized Oracle Network) is a grouping of nodes that support - // the same capabilities. - struct DON { - /// @notice Computed. Auto-increment. - uint32 id; - /// @notice The number of times the DON was configured - uint32 configCount; - /// @notice The f value for the DON. This is the number of faulty nodes - /// that the DON can tolerate. This can be different from the f value of - /// the OCR instances that capabilities spawn. - uint8 f; - /// @notice True if the DON is public. A public DON means that it accepts - /// external capability requests - bool isPublic; - /// @notice True if the DON accepts Workflows. A DON that accepts Workflows - /// is called Workflow DON and it can process Workflow Specs. A Workflow - /// DON also support one or more capabilities as well. - bool acceptsWorkflows; - /// @notice Mapping of config counts to configurations - mapping(uint32 configCount => DONCapabilityConfig donConfig) config; - } - - struct DONInfo { - /// @notice Computed. Auto-increment. - uint32 id; - /// @notice The number of times the DON was configured - uint32 configCount; - /// @notice The f value for the DON. This is the number of faulty nodes - /// that the DON can tolerate. This can be different from the f value of - /// the OCR instances that capabilities spawn. - uint8 f; - /// @notice True if the DON is public. A public DON means that it accepts - /// external capability requests - bool isPublic; - /// @notice True if the DON accepts Workflows. - bool acceptsWorkflows; - /// @notice List of member node P2P Ids - bytes32[] nodeP2PIds; - /// @notice List of capability configurations - CapabilityConfiguration[] capabilityConfigurations; - } - - /// @notice DONParams is a struct that holds the parameters for a DON. - /// @dev This is needed to avoid "stack too deep" errors in _setDONConfig. - struct DONParams { - uint32 id; - uint32 configCount; - bool isPublic; - bool acceptsWorkflows; - uint8 f; - } - - /// @notice This error is thrown when a caller is not allowed - /// to execute the transaction - /// @param sender The address that tried to execute the transaction - error AccessForbidden(address sender); - - /// @notice This error is thrown when there is a mismatch between - /// array arguments - /// @param lengthOne The length of the first array argument - /// @param lengthTwo The length of the second array argument - error LengthMismatch(uint256 lengthOne, uint256 lengthTwo); - - /// @notice This error is thrown when trying to set a node operator's - /// admin address to the zero address - error InvalidNodeOperatorAdmin(); - - /// @notice This error is thrown when trying to add a node with P2P ID that - /// is empty bytes - /// @param p2pId The provided P2P ID - error InvalidNodeP2PId(bytes32 p2pId); - - /// @notice This error is thrown when trying to add a node without - /// including the encryption public key bytes. - /// @param encryptionPublicKey The encryption public key bytes - error InvalidNodeEncryptionPublicKey(bytes32 encryptionPublicKey); - - /// @notice This error is thrown when trying to add a node without - /// capabilities or with capabilities that do not exist. - /// @param hashedCapabilityIds The IDs of the capabilities that are being added. - error InvalidNodeCapabilities(bytes32[] hashedCapabilityIds); - - /// @notice This error is emitted when a DON does not exist - /// @param donId The ID of the nonexistent DON - error DONDoesNotExist(uint32 donId); - - /// @notice This error is thrown when trying to set the node's - /// signer address to zero or if the signer address has already - /// been used by another node - error InvalidNodeSigner(); - - /// @notice This error is thrown when trying to add a capability that already - /// exists. - /// @param hashedCapabilityId The hashed capability ID of the capability - /// that already exists - error CapabilityAlreadyExists(bytes32 hashedCapabilityId); - - /// @notice This error is thrown when trying to add a node that already - /// exists. - /// @param nodeP2PId The P2P ID of the node that already exists - error NodeAlreadyExists(bytes32 nodeP2PId); - - /// @notice This error is thrown when trying to add a node to a DON where - /// the node does not support the capability - /// @param nodeP2PId The P2P ID of the node - /// @param capabilityId The ID of the capability - error NodeDoesNotSupportCapability(bytes32 nodeP2PId, bytes32 capabilityId); - - /// @notice This error is thrown when trying to add a capability configuration - /// for a capability that was already configured on a DON - /// @param donId The ID of the DON that the capability was configured for - /// @param capabilityId The ID of the capability that was configured - error DuplicateDONCapability(uint32 donId, bytes32 capabilityId); - - /// @notice This error is thrown when trying to add a duplicate node to a DON - /// @param donId The ID of the DON that the node was added for - /// @param nodeP2PId The P2P ID of the node - error DuplicateDONNode(uint32 donId, bytes32 nodeP2PId); - - /// @notice This error is thrown when trying to configure a DON with invalid - /// fault tolerance value. - /// @param f The proposed fault tolerance value - /// @param nodeCount The proposed number of nodes in the DON - error InvalidFaultTolerance(uint8 f, uint256 nodeCount); - - /// @notice This error is thrown when a capability with the provided hashed ID is - /// not found. - /// @param hashedCapabilityId The hashed ID used for the lookup. - error CapabilityDoesNotExist(bytes32 hashedCapabilityId); - - /// @notice This error is thrown when trying to deprecate a capability that - /// is deprecated. - /// @param hashedCapabilityId The hashed ID of the capability that is deprecated. - error CapabilityIsDeprecated(bytes32 hashedCapabilityId); - - /// @notice This error is thrown when a node with the provided P2P ID is - /// not found. - /// @param nodeP2PId The node P2P ID used for the lookup. - error NodeDoesNotExist(bytes32 nodeP2PId); - - /// @notice This error is thrown when a node operator does not exist - /// @param nodeOperatorId The ID of the node operator that does not exist - error NodeOperatorDoesNotExist(uint32 nodeOperatorId); - - /// @notice This error is thrown when trying to remove a node that is still - /// part of a capabilities DON - /// @param donId The Id of the DON the node belongs to - /// @param nodeP2PId The P2P Id of the node being removed - error NodePartOfCapabilitiesDON(uint32 donId, bytes32 nodeP2PId); - - /// @notice This error is thrown when attempting to add a node to a second - /// Workflow DON or when trying to remove a node that belongs to a Workflow - /// DON - /// @param donId The Id of the DON the node belongs to - /// @param nodeP2PId The P2P Id of the node - error NodePartOfWorkflowDON(uint32 donId, bytes32 nodeP2PId); - - /// @notice This error is thrown when removing a capability from the node - /// when that capability is still required by one of the DONs the node - /// belongs to. - /// @param hashedCapabilityId The hashed ID of the capability - /// @param donId The ID of the DON that requires the capability - error CapabilityRequiredByDON(bytes32 hashedCapabilityId, uint32 donId); - - /// @notice This error is thrown when trying to add a capability with a - /// configuration contract that does not implement the required interface. - /// @param proposedConfigurationContract The address of the proposed - /// configuration contract. - error InvalidCapabilityConfigurationContractInterface(address proposedConfigurationContract); - - /// @notice This event is emitted when a new node is added - /// @param p2pId The P2P ID of the node - /// @param nodeOperatorId The ID of the node operator that manages this node - /// @param signer The encoded node's signer address - event NodeAdded(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); - - /// @notice This event is emitted when a node is removed - /// @param p2pId The P2P ID of the node that was removed - event NodeRemoved(bytes32 p2pId); - - /// @notice This event is emitted when a node is updated - /// @param p2pId The P2P ID of the node - /// @param nodeOperatorId The ID of the node operator that manages this node - /// @param signer The node's signer address - event NodeUpdated(bytes32 p2pId, uint32 indexed nodeOperatorId, bytes32 signer); - - /// @notice This event is emitted when a DON's config is set - /// @param donId The ID of the DON the config was set for - /// @param configCount The number of times the DON has been - /// configured - event ConfigSet(uint32 indexed donId, uint32 configCount); - - /// @notice This event is emitted when a new node operator is added - /// @param nodeOperatorId The ID of the newly added node operator - /// @param admin The address of the admin that can manage the node - /// operator - /// @param name The human readable name of the node operator - event NodeOperatorAdded(uint32 indexed nodeOperatorId, address indexed admin, string name); - - /// @notice This event is emitted when a node operator is removed - /// @param nodeOperatorId The ID of the node operator that was removed - event NodeOperatorRemoved(uint32 indexed nodeOperatorId); - - /// @notice This event is emitted when a node operator is updated - /// @param nodeOperatorId The ID of the node operator that was updated - /// @param admin The address of the node operator's admin - /// @param name The node operator's human readable name - event NodeOperatorUpdated(uint32 indexed nodeOperatorId, address indexed admin, string name); - - /// @notice This event is emitted when a new capability is added - /// @param hashedCapabilityId The hashed ID of the newly added capability - event CapabilityConfigured(bytes32 indexed hashedCapabilityId); - - /// @notice This event is emitted when a capability is deprecated - /// @param hashedCapabilityId The hashed ID of the deprecated capability - event CapabilityDeprecated(bytes32 indexed hashedCapabilityId); - - string public constant override typeAndVersion = "CapabilitiesRegistry 1.0.0"; - - /// @notice Mapping of capabilities - mapping(bytes32 hashedCapabilityId => Capability capability) private s_capabilities; - - /// @notice Set of hashed capability IDs. - /// A hashed ID is created by the function `getHashedCapabilityId`. - EnumerableSet.Bytes32Set private s_hashedCapabilityIds; - - /// @notice Set of deprecated hashed capability IDs, - /// A hashed ID is created by the function `getHashedCapabilityId`. - EnumerableSet.Bytes32Set private s_deprecatedHashedCapabilityIds; - - /// @notice Encoded node signer addresses - EnumerableSet.Bytes32Set private s_nodeSigners; - - /// @notice Set of node P2P IDs - EnumerableSet.Bytes32Set private s_nodeP2PIds; - - /// @notice Mapping of node operators - mapping(uint32 nodeOperatorId => NodeOperator nodeOperator) private s_nodeOperators; - - /// @notice Mapping of nodes - mapping(bytes32 p2pId => Node node) private s_nodes; - - /// @notice Mapping of DON IDs to DONs - mapping(uint32 donId => DON don) private s_dons; - - /// @notice The next ID to assign a new node operator to - /// @dev Starting with 1 to avoid confusion with the zero value - /// @dev No getter for this as this is an implementation detail - uint32 private s_nextNodeOperatorId = 1; - - /// @notice The next ID to assign a new DON to - /// @dev Starting with 1 to avoid confusion with the zero value - /// @dev No getter for this as this is an implementation detail - uint32 private s_nextDONId = 1; - - /// @notice Adds a list of node operators - /// @param nodeOperators List of node operators to add - function addNodeOperators(NodeOperator[] calldata nodeOperators) external onlyOwner { - for (uint256 i; i < nodeOperators.length; ++i) { - NodeOperator memory nodeOperator = nodeOperators[i]; - if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); - uint32 nodeOperatorId = s_nextNodeOperatorId; - s_nodeOperators[nodeOperatorId] = NodeOperator({admin: nodeOperator.admin, name: nodeOperator.name}); - ++s_nextNodeOperatorId; - emit NodeOperatorAdded(nodeOperatorId, nodeOperator.admin, nodeOperator.name); - } - } - - /// @notice Removes a node operator - /// @param nodeOperatorIds The IDs of the node operators to remove - function removeNodeOperators(uint32[] calldata nodeOperatorIds) external onlyOwner { - for (uint32 i; i < nodeOperatorIds.length; ++i) { - uint32 nodeOperatorId = nodeOperatorIds[i]; - delete s_nodeOperators[nodeOperatorId]; - emit NodeOperatorRemoved(nodeOperatorId); - } - } - - /// @notice Updates a node operator - /// @param nodeOperatorIds The ID of the node operator being updated - /// @param nodeOperators The updated node operator params - function updateNodeOperators(uint32[] calldata nodeOperatorIds, NodeOperator[] calldata nodeOperators) external { - if (nodeOperatorIds.length != nodeOperators.length) - revert LengthMismatch(nodeOperatorIds.length, nodeOperators.length); - - address owner = owner(); - for (uint256 i; i < nodeOperatorIds.length; ++i) { - uint32 nodeOperatorId = nodeOperatorIds[i]; - - NodeOperator storage currentNodeOperator = s_nodeOperators[nodeOperatorId]; - if (currentNodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(nodeOperatorId); - - NodeOperator memory nodeOperator = nodeOperators[i]; - if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); - if (msg.sender != currentNodeOperator.admin && msg.sender != owner) revert AccessForbidden(msg.sender); - - if ( - currentNodeOperator.admin != nodeOperator.admin || - keccak256(abi.encode(currentNodeOperator.name)) != keccak256(abi.encode(nodeOperator.name)) - ) { - currentNodeOperator.admin = nodeOperator.admin; - currentNodeOperator.name = nodeOperator.name; - emit NodeOperatorUpdated(nodeOperatorId, nodeOperator.admin, nodeOperator.name); - } - } - } - - /// @notice Gets a node operator's data - /// @param nodeOperatorId The ID of the node operator to query for - /// @return NodeOperator The node operator data - function getNodeOperator(uint32 nodeOperatorId) external view returns (NodeOperator memory) { - return s_nodeOperators[nodeOperatorId]; - } - - /// @notice Gets all node operators - /// @return NodeOperator[] All node operators - function getNodeOperators() external view returns (NodeOperator[] memory) { - uint32 nodeOperatorId = s_nextNodeOperatorId; - /// Minus one to account for s_nextNodeOperatorId starting at index 1 - NodeOperator[] memory nodeOperators = new NodeOperator[](s_nextNodeOperatorId - 1); - uint256 idx; - for (uint32 i = 1; i < nodeOperatorId; ++i) { - if (s_nodeOperators[i].admin != address(0)) { - nodeOperators[idx] = s_nodeOperators[i]; - ++idx; - } - } - if (idx != s_nextNodeOperatorId - 1) { - assembly { - mstore(nodeOperators, idx) - } - } - return nodeOperators; - } - - /// @notice Adds nodes. Nodes can be added with deprecated capabilities to - /// avoid breaking changes when deprecating capabilities. - /// @param nodes The nodes to add - function addNodes(NodeParams[] calldata nodes) external { - bool isOwner = msg.sender == owner(); - for (uint256 i; i < nodes.length; ++i) { - NodeParams memory node = nodes[i]; - - NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; - if (nodeOperator.admin == address(0)) revert NodeOperatorDoesNotExist(node.nodeOperatorId); - if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); - - Node storage storedNode = s_nodes[node.p2pId]; - if (storedNode.signer != bytes32("")) revert NodeAlreadyExists(node.p2pId); - if (node.p2pId == bytes32("")) revert InvalidNodeP2PId(node.p2pId); - - if (node.signer == bytes32("") || s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); - - if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); - - bytes32[] memory capabilityIds = node.hashedCapabilityIds; - if (capabilityIds.length == 0) revert InvalidNodeCapabilities(capabilityIds); - - ++storedNode.configCount; - - uint32 capabilityConfigCount = storedNode.configCount; - for (uint256 j; j < capabilityIds.length; ++j) { - if (!s_hashedCapabilityIds.contains(capabilityIds[j])) revert InvalidNodeCapabilities(capabilityIds); - storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(capabilityIds[j]); - } - - storedNode.encryptionPublicKey = node.encryptionPublicKey; - storedNode.nodeOperatorId = node.nodeOperatorId; - storedNode.p2pId = node.p2pId; - storedNode.signer = node.signer; - s_nodeSigners.add(node.signer); - s_nodeP2PIds.add(node.p2pId); - emit NodeAdded(node.p2pId, node.nodeOperatorId, node.signer); - } - } - - /// @notice Removes nodes. The node operator admin or contract owner - /// can remove nodes - /// @param removedNodeP2PIds The P2P Ids of the nodes to remove - function removeNodes(bytes32[] calldata removedNodeP2PIds) external { - bool isOwner = msg.sender == owner(); - for (uint256 i; i < removedNodeP2PIds.length; ++i) { - bytes32 p2pId = removedNodeP2PIds[i]; - - Node storage node = s_nodes[p2pId]; - - if (node.signer == bytes32("")) revert NodeDoesNotExist(p2pId); - if (node.capabilitiesDONIds.length() > 0) - revert NodePartOfCapabilitiesDON(uint32(node.capabilitiesDONIds.at(i)), p2pId); - if (node.workflowDONId != 0) revert NodePartOfWorkflowDON(node.workflowDONId, p2pId); - - if (!isOwner && msg.sender != s_nodeOperators[node.nodeOperatorId].admin) revert AccessForbidden(msg.sender); - s_nodeSigners.remove(node.signer); - s_nodeP2PIds.remove(node.p2pId); - delete s_nodes[p2pId]; - emit NodeRemoved(p2pId); - } - } - - /// @notice Updates nodes. The node admin can update the node's signer address - /// and reconfigure its supported capabilities - /// @param nodes The nodes to update - function updateNodes(NodeParams[] calldata nodes) external { - bool isOwner = msg.sender == owner(); - for (uint256 i; i < nodes.length; ++i) { - NodeParams memory node = nodes[i]; - Node storage storedNode = s_nodes[node.p2pId]; - NodeOperator memory nodeOperator = s_nodeOperators[storedNode.nodeOperatorId]; - - if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId); - if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); - - if (node.signer == bytes32("")) revert InvalidNodeSigner(); - - bytes32 previousSigner = storedNode.signer; - if (previousSigner != node.signer) { - if (s_nodeSigners.contains(node.signer)) revert InvalidNodeSigner(); - storedNode.signer = node.signer; - s_nodeSigners.remove(previousSigner); - s_nodeSigners.add(node.signer); - } - - if (node.encryptionPublicKey == bytes32("")) revert InvalidNodeEncryptionPublicKey(node.encryptionPublicKey); - - bytes32[] memory supportedHashedCapabilityIds = node.hashedCapabilityIds; - if (supportedHashedCapabilityIds.length == 0) revert InvalidNodeCapabilities(supportedHashedCapabilityIds); - - uint32 capabilityConfigCount = ++storedNode.configCount; - for (uint256 j; j < supportedHashedCapabilityIds.length; ++j) { - if (!s_hashedCapabilityIds.contains(supportedHashedCapabilityIds[j])) - revert InvalidNodeCapabilities(supportedHashedCapabilityIds); - storedNode.supportedHashedCapabilityIds[capabilityConfigCount].add(supportedHashedCapabilityIds[j]); - } - - // Validate that capabilities required by a Workflow DON are still supported - uint32 nodeWorkflowDONId = storedNode.workflowDONId; - if (nodeWorkflowDONId != 0) { - bytes32[] memory workflowDonCapabilityIds = s_dons[nodeWorkflowDONId] - .config[s_dons[nodeWorkflowDONId].configCount] - .capabilityIds; - - for (uint256 j; j < workflowDonCapabilityIds.length; ++j) { - if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(workflowDonCapabilityIds[j])) - revert CapabilityRequiredByDON(workflowDonCapabilityIds[j], nodeWorkflowDONId); - } - } - - // Validate that capabilities required by capabilities DONs are still supported - uint256[] memory capabilitiesDONIds = storedNode.capabilitiesDONIds.values(); - for (uint32 j; j < capabilitiesDONIds.length; ++j) { - uint32 donId = uint32(capabilitiesDONIds[j]); - bytes32[] memory donCapabilityIds = s_dons[donId].config[s_dons[donId].configCount].capabilityIds; - - for (uint256 k; k < donCapabilityIds.length; ++k) { - if (!storedNode.supportedHashedCapabilityIds[capabilityConfigCount].contains(donCapabilityIds[k])) - revert CapabilityRequiredByDON(donCapabilityIds[k], donId); - } - } - - storedNode.nodeOperatorId = node.nodeOperatorId; - storedNode.p2pId = node.p2pId; - storedNode.encryptionPublicKey = node.encryptionPublicKey; - - emit NodeUpdated(node.p2pId, node.nodeOperatorId, node.signer); - } - } - - /// @notice Gets a node's data - /// @param p2pId The P2P ID of the node to query for - /// @return nodeInfo NodeInfo The node data - function getNode(bytes32 p2pId) public view returns (NodeInfo memory nodeInfo) { - return ( - NodeInfo({ - nodeOperatorId: s_nodes[p2pId].nodeOperatorId, - p2pId: s_nodes[p2pId].p2pId, - signer: s_nodes[p2pId].signer, - encryptionPublicKey: s_nodes[p2pId].encryptionPublicKey, - hashedCapabilityIds: s_nodes[p2pId].supportedHashedCapabilityIds[s_nodes[p2pId].configCount].values(), - configCount: s_nodes[p2pId].configCount, - workflowDONId: s_nodes[p2pId].workflowDONId, - capabilitiesDONIds: s_nodes[p2pId].capabilitiesDONIds.values() - }) - ); - } - - /// @notice Gets all nodes - /// @return NodeInfo[] All nodes in the capability registry - function getNodes() external view returns (NodeInfo[] memory) { - bytes32[] memory p2pIds = s_nodeP2PIds.values(); - NodeInfo[] memory nodesInfo = new NodeInfo[](p2pIds.length); - - for (uint256 i; i < p2pIds.length; ++i) { - nodesInfo[i] = getNode(p2pIds[i]); - } - return nodesInfo; - } - - /// @notice Adds a new capability to the capability registry - /// @param capabilities The capabilities being added - /// @dev There is no function to update capabilities as this would require - /// nodes to trust that the capabilities they support are not updated by the - /// admin - function addCapabilities(Capability[] calldata capabilities) external onlyOwner { - for (uint256 i; i < capabilities.length; ++i) { - Capability memory capability = capabilities[i]; - bytes32 hashedCapabilityId = getHashedCapabilityId(capability.labelledName, capability.version); - if (!s_hashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityAlreadyExists(hashedCapabilityId); - _setCapability(hashedCapabilityId, capability); - } - } - - /// @notice Deprecates a capability - /// @param hashedCapabilityIds[] The IDs of the capabilities to deprecate - function deprecateCapabilities(bytes32[] calldata hashedCapabilityIds) external onlyOwner { - for (uint256 i; i < hashedCapabilityIds.length; ++i) { - bytes32 hashedCapabilityId = hashedCapabilityIds[i]; - if (!s_hashedCapabilityIds.contains(hashedCapabilityId)) revert CapabilityDoesNotExist(hashedCapabilityId); - if (!s_deprecatedHashedCapabilityIds.add(hashedCapabilityId)) revert CapabilityIsDeprecated(hashedCapabilityId); - - emit CapabilityDeprecated(hashedCapabilityId); - } - } - - /// @notice Returns a Capability by its hashed ID. - /// @dev Use `getHashedCapabilityId` to get the hashed ID. - function getCapability(bytes32 hashedId) public view returns (CapabilityInfo memory) { - return ( - CapabilityInfo({ - hashedId: hashedId, - labelledName: s_capabilities[hashedId].labelledName, - version: s_capabilities[hashedId].version, - capabilityType: s_capabilities[hashedId].capabilityType, - responseType: s_capabilities[hashedId].responseType, - configurationContract: s_capabilities[hashedId].configurationContract, - isDeprecated: s_deprecatedHashedCapabilityIds.contains(hashedId) - }) - ); - } - - /// @notice Returns all capabilities. This operation will copy capabilities - /// to memory, which can be quite expensive. This is designed to mostly be - /// used by view accessors that are queried without any gas fees. - /// @return CapabilityInfo[] List of capabilities - function getCapabilities() external view returns (CapabilityInfo[] memory) { - bytes32[] memory hashedCapabilityIds = s_hashedCapabilityIds.values(); - CapabilityInfo[] memory capabilitiesInfo = new CapabilityInfo[](hashedCapabilityIds.length); - - for (uint256 i; i < hashedCapabilityIds.length; ++i) { - capabilitiesInfo[i] = getCapability(hashedCapabilityIds[i]); - } - return capabilitiesInfo; - } - - /// @notice This functions returns a capability id that has been hashed to fit into a bytes32 for cheaper access - /// @param labelledName The name of the capability - /// @param version The capability's version number - /// @return bytes32 A unique identifier for the capability - /// @dev The hash of the encoded labelledName and version - function getHashedCapabilityId(string memory labelledName, string memory version) public pure returns (bytes32) { - return keccak256(abi.encode(labelledName, version)); - } - - /// @notice Returns whether a capability is deprecated - /// @param hashedCapabilityId The hashed ID of the capability to check - /// @return bool True if the capability is deprecated, false otherwise - function isCapabilityDeprecated(bytes32 hashedCapabilityId) external view returns (bool) { - return s_deprecatedHashedCapabilityIds.contains(hashedCapabilityId); - } - - /// @notice Adds a DON made up by a group of nodes that support a list - /// of capability configurations - /// @param nodes The nodes making up the DON - /// @param capabilityConfigurations The list of configurations for the - /// capabilities supported by the DON - /// @param isPublic True if the DON is can accept external capability requests - /// @param acceptsWorkflows True if the DON can accept workflows - /// @param f The maximum number of faulty nodes the DON can tolerate - function addDON( - bytes32[] calldata nodes, - CapabilityConfiguration[] calldata capabilityConfigurations, - bool isPublic, - bool acceptsWorkflows, - uint8 f - ) external onlyOwner { - uint32 id = s_nextDONId++; - s_dons[id].id = id; - - _setDONConfig( - nodes, - capabilityConfigurations, - DONParams({id: id, configCount: 1, isPublic: isPublic, acceptsWorkflows: acceptsWorkflows, f: f}) - ); - } - - /// @notice Updates a DON's configuration. This allows - /// the admin to reconfigure the list of capabilities supported - /// by the DON, the list of nodes that make up the DON as well - /// as whether or not the DON can accept external workflows - /// @param donId The ID of the DON to update - /// @param nodes The nodes making up the DON - /// @param capabilityConfigurations The list of configurations for the - /// capabilities supported by the DON - /// @param isPublic True if the DON is can accept external capability requests - /// @param f The maximum number of nodes that can fail - function updateDON( - uint32 donId, - bytes32[] calldata nodes, - CapabilityConfiguration[] calldata capabilityConfigurations, - bool isPublic, - uint8 f - ) external onlyOwner { - DON storage don = s_dons[donId]; - uint32 configCount = don.configCount; - if (configCount == 0) revert DONDoesNotExist(donId); - _setDONConfig( - nodes, - capabilityConfigurations, - DONParams({ - id: donId, - configCount: ++configCount, - isPublic: isPublic, - acceptsWorkflows: don.acceptsWorkflows, - f: f - }) - ); - } - - /// @notice Removes DONs from the Capability Registry - /// @param donIds The IDs of the DON to be removed - function removeDONs(uint32[] calldata donIds) external onlyOwner { - for (uint256 i; i < donIds.length; ++i) { - uint32 donId = donIds[i]; - DON storage don = s_dons[donId]; - - uint32 configCount = don.configCount; - EnumerableSet.Bytes32Set storage nodeP2PIds = don.config[configCount].nodes; - - bool isWorkflowDON = don.acceptsWorkflows; - for (uint256 j; j < nodeP2PIds.length(); ++j) { - if (isWorkflowDON) { - delete s_nodes[nodeP2PIds.at(j)].workflowDONId; - } else { - s_nodes[nodeP2PIds.at(j)].capabilitiesDONIds.remove(donId); - } - } - - // DON config count starts at index 1 - if (don.configCount == 0) revert DONDoesNotExist(donId); - delete s_dons[donId]; - emit ConfigSet(donId, 0); - } - } - - /// @notice Gets DON's data - /// @param donId The DON ID - /// @return DONInfo The DON's parameters - function getDON(uint32 donId) external view returns (DONInfo memory) { - return _getDON(donId); - } - - /// @notice Returns the list of configured DONs - /// @return DONInfo[] The list of configured DONs - function getDONs() external view returns (DONInfo[] memory) { - /// Minus one to account for s_nextDONId starting at index 1 - uint32 donId = s_nextDONId; - DONInfo[] memory dons = new DONInfo[](donId - 1); - uint256 idx; - /// - for (uint32 i = 1; i < donId; ++i) { - if (s_dons[i].id != 0) { - dons[idx] = _getDON(i); - ++idx; - } - } - if (idx != donId - 1) { - assembly { - mstore(dons, idx) - } - } - return dons; - } - - /// @notice Returns the DON specific configuration for a capability - /// @param donId The DON's ID - /// @param capabilityId The Capability ID - /// @return bytes The DON specific configuration for the capability stored on the capability registry - /// @return bytes The DON specific configuration stored on the capability's configuration contract - function getCapabilityConfigs(uint32 donId, bytes32 capabilityId) external view returns (bytes memory, bytes memory) { - uint32 configCount = s_dons[donId].configCount; - - bytes memory donCapabilityConfig = s_dons[donId].config[configCount].capabilityConfigs[capabilityId]; - bytes memory globalCapabilityConfig; - - if (s_capabilities[capabilityId].configurationContract != address(0)) { - globalCapabilityConfig = ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract) - .getCapabilityConfiguration(donId); - } - - return (donCapabilityConfig, globalCapabilityConfig); - } - - /// @notice Sets the configuration for a DON - /// @param nodes The nodes making up the DON - /// @param capabilityConfigurations The list of configurations for the capabilities supported by the DON - /// @param donParams The DON's parameters - function _setDONConfig( - bytes32[] calldata nodes, - CapabilityConfiguration[] calldata capabilityConfigurations, - DONParams memory donParams - ) internal { - DONCapabilityConfig storage donCapabilityConfig = s_dons[donParams.id].config[donParams.configCount]; - - // Validate the f value. We are intentionally relaxing the 3f+1 requirement - // as not all DONs will run OCR instances. - if (donParams.f == 0 || donParams.f + 1 > nodes.length) revert InvalidFaultTolerance(donParams.f, nodes.length); - - // Skip removing supported DON Ids from previously configured nodes in DON if - // we are adding the DON for the first time - if (donParams.configCount > 1) { - DONCapabilityConfig storage prevDONCapabilityConfig = s_dons[donParams.id].config[donParams.configCount - 1]; - - // We acknowledge that this may result in an out of gas error if the number of configured - // nodes is large. This is mitigated by ensuring that there will not be a large number - // of nodes configured to a DON. - // We also do not remove the nodes from the previous DON capability config. This is not - // needed as the previous config will be overwritten by storing the latest config - // at configCount - for (uint256 i; i < prevDONCapabilityConfig.nodes.length(); ++i) { - s_nodes[prevDONCapabilityConfig.nodes.at(i)].capabilitiesDONIds.remove(donParams.id); - delete s_nodes[prevDONCapabilityConfig.nodes.at(i)].workflowDONId; - } - } - - for (uint256 i; i < nodes.length; ++i) { - if (!donCapabilityConfig.nodes.add(nodes[i])) revert DuplicateDONNode(donParams.id, nodes[i]); - - if (donParams.acceptsWorkflows) { - if (s_nodes[nodes[i]].workflowDONId != donParams.id && s_nodes[nodes[i]].workflowDONId != 0) - revert NodePartOfWorkflowDON(donParams.id, nodes[i]); - s_nodes[nodes[i]].workflowDONId = donParams.id; - } else { - /// Fine to add a duplicate DON ID to the set of supported DON IDs again as the set - /// will only store unique DON IDs - s_nodes[nodes[i]].capabilitiesDONIds.add(donParams.id); - } - } - - for (uint256 i; i < capabilityConfigurations.length; ++i) { - CapabilityConfiguration calldata configuration = capabilityConfigurations[i]; - - if (!s_hashedCapabilityIds.contains(configuration.capabilityId)) - revert CapabilityDoesNotExist(configuration.capabilityId); - if (s_deprecatedHashedCapabilityIds.contains(configuration.capabilityId)) - revert CapabilityIsDeprecated(configuration.capabilityId); - - if (donCapabilityConfig.capabilityConfigs[configuration.capabilityId].length > 0) - revert DuplicateDONCapability(donParams.id, configuration.capabilityId); - - for (uint256 j; j < nodes.length; ++j) { - if ( - !s_nodes[nodes[j]].supportedHashedCapabilityIds[s_nodes[nodes[j]].configCount].contains( - configuration.capabilityId - ) - ) revert NodeDoesNotSupportCapability(nodes[j], configuration.capabilityId); - } - - donCapabilityConfig.capabilityIds.push(configuration.capabilityId); - donCapabilityConfig.capabilityConfigs[configuration.capabilityId] = configuration.config; - - s_dons[donParams.id].isPublic = donParams.isPublic; - s_dons[donParams.id].acceptsWorkflows = donParams.acceptsWorkflows; - s_dons[donParams.id].f = donParams.f; - s_dons[donParams.id].configCount = donParams.configCount; - - _setDONCapabilityConfig( - donParams.id, - donParams.configCount, - configuration.capabilityId, - nodes, - configuration.config - ); - } - emit ConfigSet(donParams.id, donParams.configCount); - } - - /// @notice Sets the capability's config on the config contract - /// @param donId The ID of the DON the capability is being configured for - /// @param configCount The number of times the DON has been configured - /// @param capabilityId The capability's ID - /// @param nodes The nodes in the DON - /// @param config The DON's capability config - /// @dev Helper function used to resolve stack too deep errors in _setDONConfig - function _setDONCapabilityConfig( - uint32 donId, - uint32 configCount, - bytes32 capabilityId, - bytes32[] calldata nodes, - bytes memory config - ) internal { - if (s_capabilities[capabilityId].configurationContract != address(0)) { - ICapabilityConfiguration(s_capabilities[capabilityId].configurationContract).beforeCapabilityConfigSet( - nodes, - config, - configCount, - donId - ); - } - } - - /// @notice Sets a capability's data - /// @param hashedCapabilityId The ID of the capability being set - /// @param capability The capability's data - function _setCapability(bytes32 hashedCapabilityId, Capability memory capability) internal { - if (capability.configurationContract != address(0)) { - /// Check that the configuration contract being assigned - /// correctly supports the ICapabilityConfiguration interface - /// by implementing both getCapabilityConfiguration and - /// beforeCapabilityConfigSet - if ( - !ERC165Checker.supportsInterface(capability.configurationContract, type(ICapabilityConfiguration).interfaceId) - ) revert InvalidCapabilityConfigurationContractInterface(capability.configurationContract); - } - s_capabilities[hashedCapabilityId] = capability; - emit CapabilityConfigured(hashedCapabilityId); - } - - /// @notice Gets DON's data - /// @param donId The DON ID - /// @return DONInfo The DON's parameters - function _getDON(uint32 donId) internal view returns (DONInfo memory) { - uint32 configCount = s_dons[donId].configCount; - - DONCapabilityConfig storage donCapabilityConfig = s_dons[donId].config[configCount]; - - bytes32[] memory capabilityIds = donCapabilityConfig.capabilityIds; - CapabilityConfiguration[] memory capabilityConfigurations = new CapabilityConfiguration[](capabilityIds.length); - - for (uint256 i; i < capabilityConfigurations.length; ++i) { - capabilityConfigurations[i] = CapabilityConfiguration({ - capabilityId: capabilityIds[i], - config: donCapabilityConfig.capabilityConfigs[capabilityIds[i]] - }); - } - - return - DONInfo({ - id: s_dons[donId].id, - configCount: configCount, - f: s_dons[donId].f, - isPublic: s_dons[donId].isPublic, - acceptsWorkflows: s_dons[donId].acceptsWorkflows, - nodeP2PIds: donCapabilityConfig.nodes.values(), - capabilityConfigurations: capabilityConfigurations - }); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol deleted file mode 100644 index 447c979..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IReceiver} from "./interfaces/IReceiver.sol"; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; - -import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { - event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); - - error UnauthorizedSender(address sender); - error UnauthorizedWorkflowOwner(address workflowOwner); - error UnauthorizedWorkflowName(bytes10 workflowName); - - struct ReceivedFeedReport { - bytes32 FeedId; - uint224 Price; - uint32 Timestamp; - } - - struct StoredFeedReport { - uint224 Price; - uint32 Timestamp; - } - - mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports; - address[] internal s_allowedSendersList; - mapping(address sender => bool) internal s_allowedSenders; - address[] internal s_allowedWorkflowOwnersList; - mapping(address owner => bool) internal s_allowedWorkflowOwners; - bytes10[] internal s_allowedWorkflowNamesList; - mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames; - - function setConfig( - address[] calldata _allowedSendersList, - address[] calldata _allowedWorkflowOwnersList, - bytes10[] calldata _allowedWorkflowNamesList - ) external onlyOwner { - for (uint32 i = 0; i < s_allowedSendersList.length; ++i) { - s_allowedSenders[s_allowedSendersList[i]] = false; - } - for (uint32 i = 0; i < _allowedSendersList.length; ++i) { - s_allowedSenders[_allowedSendersList[i]] = true; - } - s_allowedSendersList = _allowedSendersList; - for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) { - s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false; - } - for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) { - s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true; - } - s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList; - for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) { - s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false; - } - for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) { - s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true; - } - s_allowedWorkflowNamesList = _allowedWorkflowNamesList; - } - - function onReport(bytes calldata metadata, bytes calldata rawReport) external { - if (!s_allowedSenders[msg.sender]) { - revert UnauthorizedSender(msg.sender); - } - - (bytes10 workflowName, address workflowOwner) = _getInfo(metadata); - if (!s_allowedWorkflowNames[workflowName]) { - revert UnauthorizedWorkflowName(workflowName); - } - if (!s_allowedWorkflowOwners[workflowOwner]) { - revert UnauthorizedWorkflowOwner(workflowOwner); - } - - ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[])); - for (uint256 i = 0; i < feeds.length; ++i) { - s_feedReports[feeds[i].FeedId] = StoredFeedReport(feeds[i].Price, feeds[i].Timestamp); - emit FeedReceived(feeds[i].FeedId, feeds[i].Price, feeds[i].Timestamp); - } - } - - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _getInfo(bytes memory metadata) internal pure returns (bytes10 workflowName, address workflowOwner) { - // (first 32 bytes contain length of the byte array) - // workflow_cid // offset 32, size 32 - // workflow_name // offset 64, size 10 - // workflow_owner // offset 74, size 20 - // report_name // offset 94, size 2 - assembly { - // no shifting needed for bytes10 type - workflowName := mload(add(metadata, 64)) - // shift right by 12 bytes to get the actual value - workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) - } - } - - function getPrice(bytes32 feedId) external view returns (uint224, uint32) { - StoredFeedReport memory report = s_feedReports[feedId]; - return (report.Price, report.Timestamp); - } - - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { - return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol deleted file mode 100644 index 5a28aa5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; - -/// @title Keystone Feeds Permission Handler -/// @notice This contract is designed to manage and validate permissions for accessing specific reports within a decentralized system. -/// @dev The contract uses mappings to keep track of report permissions associated with a unique report ID. -abstract contract KeystoneFeedsPermissionHandler is OwnerIsCreator { - /// @notice Holds the details for permissions of a report - /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. - struct Permission { - address forwarder; // ──────╮ The address of the forwarder (20 bytes) - bytes10 workflowName; // │ The name of the workflow in bytes10 - bytes2 reportName; // ──────╯ The name of the report in bytes2 - address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) - bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) - } - - /// @notice Event emitted when report permissions are set - event ReportPermissionSet(bytes32 indexed reportId, Permission permission); - - /// @notice Error to be thrown when an unauthorized access attempt is made - error ReportForwarderUnauthorized(address forwarder, address workflowOwner, bytes10 workflowName, bytes2 reportName); - - /// @dev Mapping from a report ID to a boolean indicating whether the report is allowed or not - mapping(bytes32 reportId => bool isAllowed) internal s_allowedReports; - - /// @notice Sets permissions for multiple reports - /// @param permissions An array of Permission structs for which to set permissions - /// @dev Emits a ReportPermissionSet event for each permission set - function setReportPermissions(Permission[] memory permissions) external onlyOwner { - for (uint256 i; i < permissions.length; ++i) { - _setReportPermission(permissions[i]); - } - } - - /// @dev Internal function to set a single report permission - /// @param permission The Permission struct containing details about the permission to set - /// @dev Emits a ReportPermissionSet event - function _setReportPermission(Permission memory permission) internal { - bytes32 reportId = _createReportId( - permission.forwarder, - permission.workflowOwner, - permission.workflowName, - permission.reportName - ); - s_allowedReports[reportId] = permission.isAllowed; - emit ReportPermissionSet(reportId, permission); - } - - /// @dev Internal view function to validate if a report is allowed for a given set of details - /// @param forwarder The address of the forwarder - /// @param workflowOwner The address of the workflow owner - /// @param workflowName The name of the workflow in bytes10 - /// @param reportName The name of the report in bytes2 - /// @dev Reverts with Unauthorized if the report is not allowed - function _validateReportPermission( - address forwarder, - address workflowOwner, - bytes10 workflowName, - bytes2 reportName - ) internal view { - bytes32 reportId = _createReportId(forwarder, workflowOwner, workflowName, reportName); - if (!s_allowedReports[reportId]) { - revert ReportForwarderUnauthorized(forwarder, workflowOwner, workflowName, reportName); - } - } - - /// @notice Generates a unique report ID based on the provided parameters. - /// @dev The report ID is computed using the Keccak-256 hash function over the encoded parameters. - /// @param forwarder The address of the forwarder associated with the report. - /// @param workflowOwner The address of the owner of the workflow. - /// @param workflowName The name of the workflow, represented as a 10-byte value. - /// @param reportName The name of the report, represented as a 2-byte value. - /// @return reportId The computed unique report ID as a bytes32 value. - function _createReportId( - address forwarder, - address workflowOwner, - bytes10 workflowName, - bytes2 reportName - ) internal pure returns (bytes32 reportId) { - return keccak256(abi.encode(forwarder, workflowOwner, workflowName, reportName)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol deleted file mode 100644 index 3616667..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ /dev/null @@ -1,335 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IReceiver} from "./interfaces/IReceiver.sol"; -import {IRouter} from "./interfaces/IRouter.sol"; -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; - -import {ERC165Checker} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; - -/// @notice This is an entry point for `write_${chain}` Target capability. It allows nodes to -/// determine if reports have been processed (successfully or not) in a decentralized and -/// product-agnostic way by recording processed reports. -contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { - /// @notice This error is returned when the report is shorter than REPORT_METADATA_LENGTH, - /// which is the minimum length of a report. - error InvalidReport(); - - /// @notice This error is thrown whenever trying to set a config with a fault tolerance of 0. - error FaultToleranceMustBePositive(); - - /// @notice This error is thrown whenever configuration provides more signers than the maximum allowed number. - /// @param numSigners The number of signers who have signed the report - /// @param maxSigners The maximum number of signers that can sign a report - error ExcessSigners(uint256 numSigners, uint256 maxSigners); - - /// @notice This error is thrown whenever a configuration is provided with less than the minimum number of signers. - /// @param numSigners The number of signers provided - /// @param minSigners The minimum number of signers expected - error InsufficientSigners(uint256 numSigners, uint256 minSigners); - - /// @notice This error is thrown whenever a duplicate signer address is provided in the configuration. - /// @param signer The signer address that was duplicated. - error DuplicateSigner(address signer); - - /// @notice This error is thrown whenever a report has an incorrect number of signatures. - /// @param expected The number of signatures expected, F + 1 - /// @param received The number of signatures received - error InvalidSignatureCount(uint256 expected, uint256 received); - - /// @notice This error is thrown whenever a report specifies a configuration that does not exist. - /// @param configId (uint64(donId) << 32) | configVersion - error InvalidConfig(uint64 configId); - - /// @notice This error is thrown whenever a signer address is not in the configuration or - /// when trying to set a zero address as a signer. - /// @param signer The signer address that was not in the configuration - error InvalidSigner(address signer); - - /// @notice This error is thrown whenever a signature is invalid. - /// @param signature The signature that was invalid - error InvalidSignature(bytes signature); - - /// @notice Contains the signing address of each oracle - struct OracleSet { - uint8 f; // Number of faulty nodes allowed - address[] signers; - mapping(address signer => uint256 position) _positions; // 1-indexed to detect unset values - } - - struct Transmission { - address transmitter; - // This is true if the receiver is not a contract or does not implement the `IReceiver` interface. - bool invalidReceiver; - // Whether the transmission attempt was successful. If `false`, the transmission can be retried - // with an increased gas limit. - bool success; - // The amount of gas allocated for the `IReceiver.onReport` call. uint80 allows storing gas for known EVM block - // gas limits. Ensures that the minimum gas requested by the user is available during the transmission attempt. - // If the transmission fails (indicated by a `false` success state), it can be retried with an increased gas limit. - uint80 gasLimit; - } - - /// @notice Emitted when a report is processed - /// @param result The result of the attempted delivery. True if successful. - event ReportProcessed( - address indexed receiver, - bytes32 indexed workflowExecutionId, - bytes2 indexed reportId, - bool result - ); - - /// @notice Contains the configuration for each DON ID - /// configId (uint64(donId) << 32) | configVersion - mapping(uint64 configId => OracleSet oracleSet) internal s_configs; - - event ConfigSet(uint32 indexed donId, uint32 indexed configVersion, uint8 f, address[] signers); - - string public constant override typeAndVersion = "Forwarder and Router 1.0.0"; - - constructor() OwnerIsCreator() { - s_forwarders[address(this)] = true; - } - - uint256 internal constant MAX_ORACLES = 31; - uint256 internal constant METADATA_LENGTH = 109; - uint256 internal constant FORWARDER_METADATA_LENGTH = 45; - uint256 internal constant SIGNATURE_LENGTH = 65; - - /// @dev This is the gas required to store `success` after the report is processed. - /// It is a warm storage write because of the packed struct. In practice it will cost less. - uint256 internal constant INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT = 5_000; - /// @dev This is the gas required to store the transmission struct and perform other checks. - uint256 internal constant INTERNAL_GAS_REQUIREMENTS = 25_000 + INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; - /// @dev This is the minimum gas required to route a report. This includes internal gas requirements - /// as well as the minimum gas that the user contract will receive. 30k * 3 gas is to account for - /// cases where consumers need close to the 30k limit provided in the supportsInterface check. - uint256 internal constant MINIMUM_GAS_LIMIT = INTERNAL_GAS_REQUIREMENTS + 30_000 * 3 + 10_000; - - // ================================================================ - // │ Router │ - // ================================================================ - - mapping(address forwarder => bool isForwarder) internal s_forwarders; - mapping(bytes32 transmissionId => Transmission transmission) internal s_transmissions; - - function addForwarder(address forwarder) external onlyOwner { - s_forwarders[forwarder] = true; - emit ForwarderAdded(forwarder); - } - - function removeForwarder(address forwarder) external onlyOwner { - s_forwarders[forwarder] = false; - emit ForwarderRemoved(forwarder); - } - - function route( - bytes32 transmissionId, - address transmitter, - address receiver, - bytes calldata metadata, - bytes calldata validatedReport - ) public returns (bool) { - if (!s_forwarders[msg.sender]) revert UnauthorizedForwarder(); - - uint256 gasLimit = gasleft() - INTERNAL_GAS_REQUIREMENTS; - if (gasLimit < MINIMUM_GAS_LIMIT) revert InsufficientGasForRouting(transmissionId); - - Transmission memory transmission = s_transmissions[transmissionId]; - if (transmission.success || transmission.invalidReceiver) revert AlreadyAttempted(transmissionId); - - s_transmissions[transmissionId].transmitter = transmitter; - s_transmissions[transmissionId].gasLimit = uint80(gasLimit); - - // This call can consume up to 90k gas. - if (!ERC165Checker.supportsInterface(receiver, type(IReceiver).interfaceId)) { - s_transmissions[transmissionId].invalidReceiver = true; - return false; - } - - bool success; - bytes memory payload = abi.encodeCall(IReceiver.onReport, (metadata, validatedReport)); - - uint256 remainingGas = gasleft() - INTERNAL_GAS_REQUIREMENTS_AFTER_REPORT; - assembly { - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(remainingGas, receiver, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) - } - - if (success) { - s_transmissions[transmissionId].success = true; - } - return success; - } - - function getTransmissionId( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) public pure returns (bytes32) { - // This is slightly cheaper compared to `keccak256(abi.encode(receiver, workflowExecutionId, reportId));` - return keccak256(bytes.concat(bytes20(uint160(receiver)), workflowExecutionId, reportId)); - } - - function getTransmissionInfo( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external view returns (TransmissionInfo memory) { - bytes32 transmissionId = getTransmissionId(receiver, workflowExecutionId, reportId); - - Transmission memory transmission = s_transmissions[transmissionId]; - - TransmissionState state; - - if (transmission.transmitter == address(0)) { - state = IRouter.TransmissionState.NOT_ATTEMPTED; - } else if (transmission.invalidReceiver) { - state = IRouter.TransmissionState.INVALID_RECEIVER; - } else { - state = transmission.success ? IRouter.TransmissionState.SUCCEEDED : IRouter.TransmissionState.FAILED; - } - - return - TransmissionInfo({ - gasLimit: transmission.gasLimit, - invalidReceiver: transmission.invalidReceiver, - state: state, - success: transmission.success, - transmissionId: transmissionId, - transmitter: transmission.transmitter - }); - } - - /// @notice Get transmitter of a given report or 0x0 if it wasn't transmitted yet - function getTransmitter( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external view returns (address) { - return s_transmissions[getTransmissionId(receiver, workflowExecutionId, reportId)].transmitter; - } - - function isForwarder(address forwarder) external view returns (bool) { - return s_forwarders[forwarder]; - } - - // ================================================================ - // │ Forwarder │ - // ================================================================ - - function setConfig(uint32 donId, uint32 configVersion, uint8 f, address[] calldata signers) external onlyOwner { - if (f == 0) revert FaultToleranceMustBePositive(); - if (signers.length > MAX_ORACLES) revert ExcessSigners(signers.length, MAX_ORACLES); - if (signers.length <= 3 * f) revert InsufficientSigners(signers.length, 3 * f + 1); - - uint64 configId = (uint64(donId) << 32) | configVersion; - - // remove any old signer addresses - for (uint256 i = 0; i < s_configs[configId].signers.length; ++i) { - delete s_configs[configId]._positions[s_configs[configId].signers[i]]; - } - - // add new signer addresses - for (uint256 i = 0; i < signers.length; ++i) { - // assign indices, detect duplicates - address signer = signers[i]; - if (signer == address(0)) revert InvalidSigner(signer); - if (s_configs[configId]._positions[signer] != 0) revert DuplicateSigner(signer); - s_configs[configId]._positions[signer] = i + 1; - } - s_configs[configId].signers = signers; - s_configs[configId].f = f; - - emit ConfigSet(donId, configVersion, f, signers); - } - - function clearConfig(uint32 donId, uint32 configVersion) external onlyOwner { - // We are not removing old signer positions, because it is sufficient to - // clear the f value for `report` function. If we decide to restore - // the configId in the future, the setConfig function clears the positions. - s_configs[(uint64(donId) << 32) | configVersion].f = 0; - - emit ConfigSet(donId, configVersion, 0, new address[](0)); - } - - // send a report to receiver - function report( - address receiver, - bytes calldata rawReport, - bytes calldata reportContext, - bytes[] calldata signatures - ) external { - if (rawReport.length < METADATA_LENGTH) { - revert InvalidReport(); - } - - bytes32 workflowExecutionId; - bytes2 reportId; - { - uint64 configId; - (workflowExecutionId, configId, reportId) = _getMetadata(rawReport); - OracleSet storage config = s_configs[configId]; - - uint8 f = config.f; - // f can never be 0, so this means the config doesn't actually exist - if (f == 0) revert InvalidConfig(configId); - if (f + 1 != signatures.length) revert InvalidSignatureCount(f + 1, signatures.length); - - // validate signatures - bytes32 completeHash = keccak256(abi.encodePacked(keccak256(rawReport), reportContext)); - address[MAX_ORACLES + 1] memory signed; - for (uint256 i = 0; i < signatures.length; ++i) { - bytes calldata signature = signatures[i]; - if (signature.length != SIGNATURE_LENGTH) revert InvalidSignature(signature); - address signer = ecrecover( - completeHash, - uint8(signature[64]) + 27, - bytes32(signature[0:32]), - bytes32(signature[32:64]) - ); - - // validate signer is trusted and signature is unique - uint256 index = config._positions[signer]; - if (index == 0) revert InvalidSigner(signer); // index is 1-indexed so we can detect unset signers - if (signed[index] != address(0)) revert DuplicateSigner(signer); - signed[index] = signer; - } - } - - bool success = this.route( - getTransmissionId(receiver, workflowExecutionId, reportId), - msg.sender, - receiver, - rawReport[FORWARDER_METADATA_LENGTH:METADATA_LENGTH], - rawReport[METADATA_LENGTH:] - ); - - emit ReportProcessed(receiver, workflowExecutionId, reportId, success); - } - - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _getMetadata( - bytes memory rawReport - ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { - // (first 32 bytes of memory contain length of the report) - // version // offset 32, size 1 - // workflow_execution_id // offset 33, size 32 - // timestamp // offset 65, size 4 - // don_id // offset 69, size 4 - // don_config_version, // offset 73, size 4 - // workflow_cid // offset 77, size 32 - // workflow_name // offset 109, size 10 - // workflow_owner // offset 119, size 20 - // report_id // offset 139, size 2 - assembly { - workflowExecutionId := mload(add(rawReport, 33)) - // shift right by 24 bytes to get the combined don_id and don_config_version - configId := shr(mul(24, 8), mload(add(rawReport, 69))) - reportId := mload(add(rawReport, 139)) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol deleted file mode 100644 index d054434..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/OCR3Capability.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; -import {OCR2Abstract} from "./ocr/OCR2Abstract.sol"; - -/// @notice OCR2Base provides config management compatible with OCR3 -contract OCR3Capability is OwnerIsCreator, OCR2Abstract { - error InvalidConfig(string message); - error ReportingUnsupported(); - - string public constant override typeAndVersion = "Keystone 1.0.0"; - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - // makes it easier for offchain systems to extract config from logs. - uint32 internal s_latestConfigBlockNumber; - - // Storing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a single SLOAD. If any further fields are - // added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // TODO: could be optimized by squeezing into one slot - uint8 n; - } - ConfigInfo internal s_configInfo; - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param _signers addresses with which oracles sign the reports - /// @param _transmitters addresses oracles use to transmit the reports - /// @param _f number of faulty oracles the system can tolerate - /// @param _onchainConfig encoded on-chain contract configuration - /// @param _offchainConfigVersion version number for offchainEncoding schema - /// @param _offchainConfig encoded off-chain oracle configuration - /// @dev signer = [ 1 byte type | 2 byte len | n byte value ]... - function setConfig( - bytes[] calldata _signers, - address[] calldata _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - // Bounded by MAX_NUM_ORACLES in OCR2Abstract.sol - for (uint256 i = 0; i < _signers.length; ++i) { - if (_transmitters[i] == address(0)) revert InvalidConfig("transmitter must not be empty"); - // add new signers - bytes calldata publicKeys = _signers[i]; - uint256 offset = 0; - uint256 publicKeysLength = uint16(publicKeys.length); - // scan through public keys to validate encoded format - while (offset < publicKeysLength) { - if (offset + 3 > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); - uint256 keyLen = uint256(uint8(publicKeys[offset + 1])) + (uint256(uint8(publicKeys[offset + 2])) << 8); - if (offset + 3 + keyLen > publicKeysLength) revert InvalidConfig("invalid signer pubKey encoding"); - offset += 3 + keyLen; - } - } - s_configInfo.f = _f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _offchainConfigVersion, - _offchainConfig - ); - } - s_configInfo.n = uint8(_signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _offchainConfigVersion, - _offchainConfig - ); - } - - function _configDigestFromConfigData( - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - bytes[] calldata _signers, - address[] calldata _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - _chainId, - _contractAddress, - _configCount, - _signers, - _transmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x000e << (256 - 16); // 0x000e00..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see __configDigestFromConfigData) - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata /* reportContext */, - bytes calldata /* report */, - bytes32[] calldata /* rs */, - bytes32[] calldata /* ss */, - bytes32 /* rawVs */ // signatures - ) external pure override { - revert ReportingUnsupported(); - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol deleted file mode 100644 index 6c14447..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/ICapabilityConfiguration.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice Interface for capability configuration contract. It MUST be -/// implemented for a contract to be used as a capability configuration. -/// The contract MAY store configuration that is shared across multiple -/// DON instances and capability versions. -/// @dev This interface does not guarantee the configuration contract's -/// correctness. It is the responsibility of the contract owner to ensure -/// that the configuration contract emits the CapabilityConfigurationSet -/// event when the configuration is set. -interface ICapabilityConfiguration { - /// @notice Emitted when a capability configuration is set. - event CapabilityConfigurationSet(); - - /// @notice Returns the capability configuration for a particular DON instance. - /// @dev donId is required to get DON-specific configuration. It avoids a - /// situation where configuration size grows too large. - /// @param donId The DON instance ID. These are stored in the CapabilitiesRegistry. - /// @return configuration DON's configuration for the capability. - function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration); - - /// @notice Called by the registry prior to the config being set for a particular DON. - /// @param nodes The nodes that the configuration is being set for. - /// @param donCapabilityConfig The configuration being set on the capability registry. - /// @param donCapabilityConfigCount The number of times the DON has been configured, tracked on the capability registry. - /// @param donId The DON ID on the capability registry. - function beforeCapabilityConfigSet( - bytes32[] calldata nodes, - bytes calldata donCapabilityConfig, - uint64 donCapabilityConfigCount, - uint32 donId - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol deleted file mode 100644 index 9afa1d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IReceiver.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title IReceiver - receives keystone reports -interface IReceiver { - /// @notice Handles incoming keystone reports. - /// @dev If this function call reverts, it can be retried with a higher gas - /// limit. The receiver is responsible for discarding stale reports. - /// @param metadata Report's metadata. - /// @param report Workflow report. - function onReport(bytes calldata metadata, bytes calldata report) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol deleted file mode 100644 index 3d2e24f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/interfaces/IRouter.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/// @title IRouter - delivers keystone reports to receiver -interface IRouter { - error UnauthorizedForwarder(); - /// @dev Thrown when the gas limit is insufficient for handling state after - /// calling the receiver function. - error InsufficientGasForRouting(bytes32 transmissionId); - error AlreadyAttempted(bytes32 transmissionId); - - event ForwarderAdded(address indexed forwarder); - event ForwarderRemoved(address indexed forwarder); - - enum TransmissionState { - NOT_ATTEMPTED, - SUCCEEDED, - INVALID_RECEIVER, - FAILED - } - - struct TransmissionInfo { - bytes32 transmissionId; - TransmissionState state; - address transmitter; - // This is true if the receiver is not a contract or does not implement the - // `IReceiver` interface. - bool invalidReceiver; - // Whether the transmission attempt was successful. If `false`, the - // transmission can be retried with an increased gas limit. - bool success; - // The amount of gas allocated for the `IReceiver.onReport` call. uint80 - // allows storing gas for known EVM block gas limits. - // Ensures that the minimum gas requested by the user is available during - // the transmission attempt. If the transmission fails (indicated by a - // `false` success state), it can be retried with an increased gas limit. - uint80 gasLimit; - } - - function addForwarder(address forwarder) external; - function removeForwarder(address forwarder) external; - - function route( - bytes32 transmissionId, - address transmitter, - address receiver, - bytes calldata metadata, - bytes calldata report - ) external returns (bool); - - function getTransmissionId( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external pure returns (bytes32); - function getTransmissionInfo( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external view returns (TransmissionInfo memory); - function getTransmitter( - address receiver, - bytes32 workflowExecutionId, - bytes2 reportId - ) external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol deleted file mode 100644 index 2eb9b55..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/lib/KeystoneFeedDefaultMetadataLib.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -library KeystoneFeedDefaultMetadataLib { - /** - * Metadata Layout: - * - * +-------------------------------+--------------------+---------------------+---------------+ - * | 32 bytes (length prefix) | 32 bytes | 10 bytes | 20 bytes | 2 bytes | - * | (Not used in function) | workflow_cid | workflow_name | workflow_owner| report_name | - * +-------------------------------+--------------------+---------------------+---------------+----------------+ - * | | | | | | - * | (Offset 0) | (Offset 32) | (Offset 64) | (Offset 74) | (Offset 94) | - * +-------------------------------+--------------------+---------------------+---------------+----------------+ - * @dev used to slice metadata bytes into workflowName, workflowOwner and report name - */ - function _extractMetadataInfo( - bytes memory metadata - ) internal pure returns (bytes10 workflowName, address workflowOwner, bytes2 reportName) { - // (first 32 bytes contain length of the byte array) - // workflow_cid // offset 32, size 32 - // workflow_name // offset 64, size 10 - // workflow_owner // offset 74, size 20 - // report_name // offset 94, size 2 - assembly { - // no shifting needed for bytes10 type - workflowName := mload(add(metadata, 64)) - // shift right by 12 bytes to get the actual value - workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) - // no shifting needed for bytes2 type - reportName := mload(add(metadata, 94)) - } - return (workflowName, workflowOwner, reportName); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol deleted file mode 100644 index af822a6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/ocr/OCR2Abstract.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /** - * @notice triggers a new run of the offchain reporting protocol - * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - * @param configDigest configDigest of this configuration - * @param configCount ordinal number of this config setting among all config settings over the life of this contract - * @param signers ith element is address ith oracle uses to sign a report - * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - bytes[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param transmitters addresses oracles use to transmit the reports - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - */ - function setConfig( - bytes[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /** - * @notice information about current offchain reporting protocol configuration - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - */ - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - /** - * @notice optionally emitted to indicate the latest configDigest and epoch for - which a report was successfully transmitted. Alternatively, the contract may - use latestConfigDigestAndEpoch with scanLogs set to false. - */ - event Transmitted(bytes32 configDigest, uint32 epoch); - - /** - * @notice optionally returns the latest configDigest and epoch for which a - report was successfully transmitted. Alternatively, the contract may return - scanLogs set to true and use Transmitted events to provide this information - to offchain watchers. - * @return scanLogs indicates whether to rely on the configDigest and epoch - returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice transmit is called to post a new report to the contract - * @param report serialized report, which the signatures are signing. - * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - * @param rawVs ith element is the the V component of the ith signature - */ - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol deleted file mode 100644 index 64dc018..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/BaseTest.t.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; -import {Constants} from "./Constants.t.sol"; -import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract BaseTest is Test, Constants { - CapabilitiesRegistry internal s_CapabilitiesRegistry; - CapabilityConfigurationContract internal s_capabilityConfigurationContract; - CapabilitiesRegistry.Capability internal s_basicCapability; - CapabilitiesRegistry.Capability internal s_capabilityWithConfigurationContract; - bytes32 internal s_basicHashedCapabilityId; - bytes32 internal s_capabilityWithConfigurationContractId; - bytes32 internal s_nonExistentHashedCapabilityId; - - function setUp() public virtual { - vm.startPrank(ADMIN); - s_CapabilitiesRegistry = new CapabilitiesRegistry(); - s_capabilityConfigurationContract = new CapabilityConfigurationContract(); - - s_basicCapability = CapabilitiesRegistry.Capability({ - labelledName: "data-streams-reports", - version: "1.0.0", - responseType: CapabilitiesRegistry.CapabilityResponseType.REPORT, - configurationContract: address(0), - capabilityType: CapabilitiesRegistry.CapabilityType.TRIGGER - }); - s_capabilityWithConfigurationContract = CapabilitiesRegistry.Capability({ - labelledName: "read-ethereum-mainnet-gas-price", - version: "1.0.2", - responseType: CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL, - configurationContract: address(s_capabilityConfigurationContract), - capabilityType: CapabilitiesRegistry.CapabilityType.ACTION - }); - - s_basicHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - s_capabilityWithConfigurationContractId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_capabilityWithConfigurationContract.labelledName, - s_capabilityWithConfigurationContract.version - ); - s_nonExistentHashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("non-existent-capability", "1.0.0"); - } - - function _getNodeOperators() internal pure returns (CapabilitiesRegistry.NodeOperator[] memory) { - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](3); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ - admin: NODE_OPERATOR_ONE_ADMIN, - name: NODE_OPERATOR_ONE_NAME - }); - nodeOperators[1] = CapabilitiesRegistry.NodeOperator({ - admin: NODE_OPERATOR_TWO_ADMIN, - name: NODE_OPERATOR_TWO_NAME - }); - nodeOperators[2] = CapabilitiesRegistry.NodeOperator({admin: NODE_OPERATOR_THREE, name: NODE_OPERATOR_THREE_NAME}); - return nodeOperators; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol deleted file mode 100644 index 7bee2b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddCapabilitiesTest.t.sol +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; -import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -contract CapabilitiesRegistry_AddCapabilitiesTest is BaseTest { - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_basicCapability; - - vm.expectRevert("Only callable by owner"); - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_RevertWhen_CapabilityExists() public { - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_basicCapability; - - // Successfully add the capability the first time - s_CapabilitiesRegistry.addCapabilities(capabilities); - - // Try to add the same capability again - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.CapabilityAlreadyExists.selector, s_basicHashedCapabilityId) - ); - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_RevertWhen_ConfigurationContractNotDeployed() public { - address nonExistentContract = address(1); - s_capabilityWithConfigurationContract.configurationContract = nonExistentContract; - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_capabilityWithConfigurationContract; - - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, - nonExistentContract - ) - ); - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_RevertWhen_ConfigurationContractDoesNotMatchInterface() public { - address contractWithoutERC165 = address(9999); - vm.mockCall( - contractWithoutERC165, - abi.encodeWithSelector( - IERC165.supportsInterface.selector, - ICapabilityConfiguration.getCapabilityConfiguration.selector ^ - ICapabilityConfiguration.beforeCapabilityConfigSet.selector - ), - abi.encode(false) - ); - s_capabilityWithConfigurationContract.configurationContract = contractWithoutERC165; - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_capabilityWithConfigurationContract; - - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.InvalidCapabilityConfigurationContractInterface.selector, - contractWithoutERC165 - ) - ); - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_AddCapability_NoConfigurationContract() public { - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_basicCapability; - - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId("data-streams-reports", "1.0.0"); - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); - s_CapabilitiesRegistry.addCapabilities(capabilities); - CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( - hashedCapabilityId - ); - - assertEq(storedCapability.labelledName, s_basicCapability.labelledName); - assertEq(storedCapability.version, s_basicCapability.version); - assertEq(uint256(storedCapability.responseType), uint256(s_basicCapability.responseType)); - assertEq(storedCapability.configurationContract, s_basicCapability.configurationContract); - } - - function test_AddCapability_WithConfiguration() public { - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](1); - capabilities[0] = s_capabilityWithConfigurationContract; - - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_capabilityWithConfigurationContract.labelledName, - s_capabilityWithConfigurationContract.version - ); - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.CapabilityConfigured(hashedCapabilityId); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.CapabilityInfo memory storedCapability = s_CapabilitiesRegistry.getCapability( - hashedCapabilityId - ); - - assertEq(storedCapability.labelledName, s_capabilityWithConfigurationContract.labelledName); - assertEq(storedCapability.version, s_capabilityWithConfigurationContract.version); - assertEq(uint256(storedCapability.responseType), uint256(s_capabilityWithConfigurationContract.responseType)); - assertEq(storedCapability.configurationContract, s_capabilityWithConfigurationContract.configurationContract); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol deleted file mode 100644 index 4e8725a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddDONTest.t.sol +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; -import {MaliciousConfigurationContract} from "./mocks/MaliciousConfigurationContract.sol"; - -contract CapabilitiesRegistry_AddDONTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicHashedCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - nodes[2] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, - hashedCapabilityIds: capabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodes); - - changePrank(ADMIN); - } - - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - bytes32[] memory nodes = new bytes32[](1); - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_NodeDoesNotSupportCapability() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, - P2P_ID_TWO, - s_capabilityWithConfigurationContractId - ) - ); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_CapabilityDoesNotExist() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_nonExistentHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) - ); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_FaultToleranceIsZero() public { - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidFaultTolerance.selector, 0, 1)); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, 0); - } - - function test_RevertWhen_DuplicateCapabilityAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) - ); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_DeprecatedCapabilityAdded() public { - bytes32 capabilityId = s_basicHashedCapabilityId; - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = capabilityId; - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: capabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_DuplicateNodeAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 2, P2P_ID)); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_AddDON() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_THREE; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.ConfigSet(DON_ID, 1); - vm.expectCall( - address(s_capabilityConfigurationContract), - abi.encodeWithSelector( - ICapabilityConfiguration.beforeCapabilityConfigSet.selector, - nodes, - CONFIG_CAPABILITY_CONFIG, - 1, - DON_ID - ), - 1 - ); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - - CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); - assertEq(donInfo.id, DON_ID); - assertEq(donInfo.configCount, 1); - assertEq(donInfo.isPublic, true); - assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); - assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - - (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry - .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); - assertEq(capabilityConfigContractConfig, bytes("")); - - ( - bytes memory CapabilitiesRegistryDONConfigTwo, - bytes memory capabilityConfigContractConfigTwo - ) = s_CapabilitiesRegistry.getCapabilityConfigs(DON_ID, s_capabilityWithConfigurationContractId); - assertEq(CapabilitiesRegistryDONConfigTwo, CONFIG_CAPABILITY_CONFIG); - assertEq(capabilityConfigContractConfigTwo, CONFIG_CAPABILITY_CONFIG); - - assertEq(donInfo.nodeP2PIds.length, nodes.length); - assertEq(donInfo.nodeP2PIds[0], P2P_ID); - assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); - } -} - -contract CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationConfigured is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - - address maliciousConfigContractAddr = address( - new MaliciousConfigurationContract(s_capabilityWithConfigurationContractId) - ); - s_basicCapability.configurationContract = maliciousConfigContractAddr; - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); - nodeOperators[0].admin = maliciousConfigContractAddr; - nodeOperators[1].admin = maliciousConfigContractAddr; - nodeOperators[2].admin = maliciousConfigContractAddr; - - s_CapabilitiesRegistry.addNodeOperators(nodeOperators); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); - bytes32[] memory capabilityIds = new bytes32[](1); - capabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - nodes[2] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, - hashedCapabilityIds: capabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodes); - - changePrank(ADMIN); - } - - function test_RevertWhen_MaliciousCapabilitiesConfigContractTriesToRemoveCapabilitiesFromDONNodes() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_THREE; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.CapabilityRequiredByDON.selector, s_basicHashedCapabilityId, DON_ID) - ); - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol deleted file mode 100644 index b4f7be9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodeOperatorsTest.t.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_AddNodeOperatorsTest is BaseTest { - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_RevertWhen_NodeOperatorAdminAddressZero() public { - changePrank(ADMIN); - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = _getNodeOperators(); - nodeOperators[0].admin = address(0); - vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); - s_CapabilitiesRegistry.addNodeOperators(nodeOperators); - } - - function test_AddNodeOperators() public { - changePrank(ADMIN); - - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeOperatorAdded( - TEST_NODE_OPERATOR_ONE_ID, - NODE_OPERATOR_ONE_ADMIN, - NODE_OPERATOR_ONE_NAME - ); - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeOperatorAdded( - TEST_NODE_OPERATOR_TWO_ID, - NODE_OPERATOR_TWO_ADMIN, - NODE_OPERATOR_TWO_NAME - ); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - - CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( - TEST_NODE_OPERATOR_ONE_ID - ); - assertEq(nodeOperatorOne.admin, NODE_OPERATOR_ONE_ADMIN); - assertEq(nodeOperatorOne.name, NODE_OPERATOR_ONE_NAME); - - CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( - TEST_NODE_OPERATOR_TWO_ID - ); - assertEq(nodeOperatorTwo.admin, NODE_OPERATOR_TWO_ADMIN); - assertEq(nodeOperatorTwo.name, NODE_OPERATOR_TWO_NAME); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol deleted file mode 100644 index aa6cca4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_AddNodesTest.t.sol +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_AddNodesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - changePrank(ADMIN); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { - changePrank(STRANGER); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_AddingNodeWithInvalidNodeOperator() public { - changePrank(ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - uint32 invalidNodeOperatorId = 10000; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: invalidNodeOperatorId, // Invalid NOP - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) - ); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_SignerAddressEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: bytes32(""), - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_EncryptionPublicKeyEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: bytes32(""), - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_SignerAddressNotUnique() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodes); - - changePrank(NODE_OPERATOR_TWO_ADMIN); - - // Try adding another node with the same signer address - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_AddingDuplicateP2PId() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodes); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeAlreadyExists.selector, P2P_ID)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_P2PIDEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: bytes32(""), - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeP2PId.selector, bytes32(""))); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_AddingNodeWithoutCapabilities() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](0); - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_AddingNodeWithInvalidCapability() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_AddsNodeParams() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - s_CapabilitiesRegistry.addNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.hashedCapabilityIds.length, 2); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(node.configCount, 1); - } - - function test_OwnerCanAddNodes() public { - changePrank(ADMIN); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - s_CapabilitiesRegistry.addNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.hashedCapabilityIds.length, 2); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(node.configCount, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol deleted file mode 100644 index e06fa4a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_DeprecateCapabilitiesTest.t.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_DeprecateCapabilitiesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - - vm.expectRevert("Only callable by owner"); - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - } - - function test_RevertWhen_CapabilityDoesNotExist() public { - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = s_nonExistentHashedCapabilityId; - - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) - ); - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - } - - function test_RevertWhen_CapabilityIsDeprecated() public { - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, hashedCapabilityId)); - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - } - - function test_DeprecatesCapability() public { - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - assertEq(s_CapabilitiesRegistry.isCapabilityDeprecated(hashedCapabilityId), true); - } - - function test_EmitsEvent() public { - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.CapabilityDeprecated(hashedCapabilityId); - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol deleted file mode 100644 index 8f39183..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetCapabilitiesTest.t.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_GetCapabilitiesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - s_CapabilitiesRegistry.addCapabilities(capabilities); - } - - function test_ReturnsCapabilities() public { - bytes32 hashedCapabilityId = s_CapabilitiesRegistry.getHashedCapabilityId( - s_basicCapability.labelledName, - s_basicCapability.version - ); - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = hashedCapabilityId; - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - - CapabilitiesRegistry.CapabilityInfo[] memory capabilities = s_CapabilitiesRegistry.getCapabilities(); - - assertEq(capabilities.length, 2); - - assertEq(capabilities[0].labelledName, "data-streams-reports"); - assertEq(capabilities[0].version, "1.0.0"); - assertEq(uint256(capabilities[0].responseType), uint256(CapabilitiesRegistry.CapabilityResponseType.REPORT)); - assertEq(uint256(capabilities[0].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.TRIGGER)); - assertEq(capabilities[0].configurationContract, address(0)); - assertEq(capabilities[0].hashedId, keccak256(abi.encode(capabilities[0].labelledName, capabilities[0].version))); - assertEq(capabilities[0].isDeprecated, true); - - assertEq(capabilities[1].labelledName, "read-ethereum-mainnet-gas-price"); - assertEq(capabilities[1].version, "1.0.2"); - assertEq( - uint256(capabilities[1].responseType), - uint256(CapabilitiesRegistry.CapabilityResponseType.OBSERVATION_IDENTICAL) - ); - assertEq(uint256(capabilities[1].capabilityType), uint256(CapabilitiesRegistry.CapabilityType.ACTION)); - assertEq(capabilities[1].configurationContract, address(s_capabilityConfigurationContract)); - assertEq(capabilities[1].hashedId, keccak256(abi.encode(capabilities[1].labelledName, capabilities[1].version))); - assertEq(capabilities[1].isDeprecated, false); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol deleted file mode 100644 index 6d8dd13..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetDONsTest.t.sol +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; - -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_GetDONsTest is BaseTest { - CapabilitiesRegistry.CapabilityConfiguration[] private s_capabilityConfigs; - - function setUp() public override { - BaseTest.setUp(); - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicHashedCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - changePrank(NODE_OPERATOR_ONE_ADMIN); - s_CapabilitiesRegistry.addNodes(nodes); - - s_capabilityConfigs.push( - CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }) - ); - - bytes32[] memory nodeIds = new bytes32[](2); - nodeIds[0] = P2P_ID; - nodeIds[1] = P2P_ID_TWO; - - changePrank(ADMIN); - s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, true, true, 1); - s_CapabilitiesRegistry.addDON(nodeIds, s_capabilityConfigs, false, false, 1); - } - - function test_CorrectlyFetchesDONs() public view { - CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); - assertEq(dons.length, 2); - assertEq(dons[0].id, DON_ID); - assertEq(dons[0].configCount, 1); - assertEq(dons[0].isPublic, true); - assertEq(dons[0].acceptsWorkflows, true); - assertEq(dons[0].f, 1); - assertEq(dons[0].capabilityConfigurations.length, s_capabilityConfigs.length); - assertEq(dons[0].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - - assertEq(dons[1].id, DON_ID_TWO); - assertEq(dons[1].configCount, 1); - assertEq(dons[1].isPublic, false); - assertEq(dons[1].capabilityConfigurations.length, s_capabilityConfigs.length); - assertEq(dons[1].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - } - - function test_DoesNotIncludeRemovedDONs() public { - uint32[] memory removedDONIDs = new uint32[](1); - removedDONIDs[0] = DON_ID; - s_CapabilitiesRegistry.removeDONs(removedDONIDs); - - CapabilitiesRegistry.DONInfo[] memory dons = s_CapabilitiesRegistry.getDONs(); - assertEq(dons.length, 1); - assertEq(dons[0].id, DON_ID_TWO); - assertEq(dons[0].configCount, 1); - assertEq(dons[0].isPublic, false); - assertEq(dons[0].acceptsWorkflows, false); - assertEq(dons[0].f, 1); - assertEq(dons[0].capabilityConfigurations.length, s_capabilityConfigs.length); - assertEq(dons[0].capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol deleted file mode 100644 index cdfb0eb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetHashedCapabilityIdTest.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilityConfigurationContract} from "./mocks/CapabilityConfigurationContract.sol"; - -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_GetHashedCapabilityTest is BaseTest { - string constant CAPABILITY_LABELLED_NAME = "ccip1"; - string constant CAPABILITY_VERSION = "1.0.0"; - - function test_CorrectlyGeneratesHashedCapabilityId() public view { - bytes32 expectedHashedCapabilityId = keccak256(abi.encode(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION)); - - assertEq( - s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), - expectedHashedCapabilityId - ); - } - - function test_DoesNotCauseIncorrectClashes() public view { - assertNotEq( - s_CapabilitiesRegistry.getHashedCapabilityId(CAPABILITY_LABELLED_NAME, CAPABILITY_VERSION), - s_CapabilitiesRegistry.getHashedCapabilityId("ccip", "11.0.0") - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol deleted file mode 100644 index 471f4a8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodeOperatorsTest.t.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_GetNodeOperatorsTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_CorrectlyFetchesNodeOperators() public view { - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); - assertEq(nodeOperators.length, 3); - - assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); - assertEq(nodeOperators[0].name, NODE_OPERATOR_ONE_NAME); - - assertEq(nodeOperators[1].admin, NODE_OPERATOR_TWO_ADMIN); - assertEq(nodeOperators[1].name, NODE_OPERATOR_TWO_NAME); - - assertEq(nodeOperators[2].admin, NODE_OPERATOR_THREE); - assertEq(nodeOperators[2].name, NODE_OPERATOR_THREE_NAME); - } - - function test_DoesNotIncludeRemovedNodeOperators() public { - changePrank(ADMIN); - uint32[] memory nodeOperatorsToRemove = new uint32[](1); - nodeOperatorsToRemove[0] = 2; - s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); - - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = s_CapabilitiesRegistry.getNodeOperators(); - assertEq(nodeOperators.length, 2); - - assertEq(nodeOperators[0].admin, NODE_OPERATOR_ONE_ADMIN); - assertEq(nodeOperators[0].name, NODE_OPERATOR_ONE_NAME); - assertEq(nodeOperators[1].admin, NODE_OPERATOR_THREE); - assertEq(nodeOperators[1].name, NODE_OPERATOR_THREE_NAME); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol deleted file mode 100644 index 4fc150e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_GetNodesTest.t.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_GetNodesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(NODE_OPERATOR_ONE_ADMIN); - - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_CorrectlyFetchesNodes() public view { - CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); - assertEq(nodes.length, 2); - - assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(nodes[0].signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - assertEq(nodes[0].p2pId, P2P_ID); - assertEq(nodes[0].hashedCapabilityIds.length, 2); - assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(nodes[0].configCount, 1); - - assertEq(nodes[1].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(nodes[1].signer, NODE_OPERATOR_TWO_SIGNER_ADDRESS); - assertEq(nodes[1].p2pId, P2P_ID_TWO); - assertEq(nodes[1].hashedCapabilityIds.length, 2); - assertEq(nodes[1].hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(nodes[1].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(nodes[1].configCount, 1); - } - - function test_DoesNotIncludeRemovedNodes() public { - changePrank(ADMIN); - bytes32[] memory nodesToRemove = new bytes32[](1); - nodesToRemove[0] = P2P_ID_TWO; - s_CapabilitiesRegistry.removeNodes(nodesToRemove); - - CapabilitiesRegistry.NodeInfo[] memory nodes = s_CapabilitiesRegistry.getNodes(); - assertEq(nodes.length, 1); - - assertEq(nodes[0].nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(nodes[0].signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - assertEq(nodes[0].p2pId, P2P_ID); - assertEq(nodes[0].hashedCapabilityIds.length, 2); - assertEq(nodes[0].hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(nodes[0].hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(nodes[0].configCount, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol deleted file mode 100644 index c3a8dc1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveDONsTest.t.sol +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; - -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_RemoveDONsTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicHashedCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - changePrank(NODE_OPERATOR_ONE_ADMIN); - s_CapabilitiesRegistry.addNodes(nodes); - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - bytes32[] memory nodeIds = new bytes32[](2); - nodeIds[0] = P2P_ID; - nodeIds[1] = P2P_ID_TWO; - - changePrank(ADMIN); - s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); - } - - function test_RevertWhen_CalledByNonAdmin() public { - uint32[] memory donIDs = new uint32[](1); - donIDs[0] = 1; - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_CapabilitiesRegistry.removeDONs(donIDs); - } - - function test_RevertWhen_DONDoesNotExist() public { - uint32 invalidDONId = 10; - uint32[] memory donIDs = new uint32[](1); - donIDs[0] = invalidDONId; - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, invalidDONId)); - s_CapabilitiesRegistry.removeDONs(donIDs); - } - - function test_RemovesDON() public { - uint32[] memory donIDs = new uint32[](1); - donIDs[0] = DON_ID; - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.ConfigSet(DON_ID, 0); - s_CapabilitiesRegistry.removeDONs(donIDs); - - CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); - assertEq(donInfo.id, 0); - assertEq(donInfo.configCount, 0); - assertEq(donInfo.isPublic, false); - assertEq(donInfo.capabilityConfigurations.length, 0); - - (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry - .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - - assertEq(CapabilitiesRegistryDONConfig, bytes("")); - assertEq(capabilityConfigContractConfig, bytes("")); - assertEq(donInfo.nodeP2PIds.length, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol deleted file mode 100644 index 1f70bc8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodeOperatorsTest.t.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_RemoveNodeOperatorsTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_RevertWhen_CalledByNonOwner() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - uint32[] memory nodeOperatorsToRemove = new uint32[](2); - nodeOperatorsToRemove[1] = 1; - s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); - } - - function test_RemovesNodeOperator() public { - changePrank(ADMIN); - - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_ONE_ID); - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeOperatorRemoved(TEST_NODE_OPERATOR_TWO_ID); - uint32[] memory nodeOperatorsToRemove = new uint32[](2); - nodeOperatorsToRemove[0] = TEST_NODE_OPERATOR_ONE_ID; - nodeOperatorsToRemove[1] = TEST_NODE_OPERATOR_TWO_ID; - s_CapabilitiesRegistry.removeNodeOperators(nodeOperatorsToRemove); - - CapabilitiesRegistry.NodeOperator memory nodeOperatorOne = s_CapabilitiesRegistry.getNodeOperator( - TEST_NODE_OPERATOR_ONE_ID - ); - assertEq(nodeOperatorOne.admin, address(0)); - assertEq(nodeOperatorOne.name, ""); - - CapabilitiesRegistry.NodeOperator memory nodeOperatorTwo = s_CapabilitiesRegistry.getNodeOperator( - TEST_NODE_OPERATOR_TWO_ID - ); - assertEq(nodeOperatorTwo.admin, address(0)); - assertEq(nodeOperatorTwo.name, ""); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol deleted file mode 100644 index dfe63e2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_RemoveNodesTest.t.sol +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_RemoveNodesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - nodes[2] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(ADMIN); - - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { - changePrank(STRANGER); - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); - s_CapabilitiesRegistry.removeNodes(nodes); - } - - function test_RevertWhen_NodeDoesNotExist() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = INVALID_P2P_ID; - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); - s_CapabilitiesRegistry.removeNodes(nodes); - } - - function test_RevertWhen_P2PIDEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = bytes32(""); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); - s_CapabilitiesRegistry.removeNodes(nodes); - } - - function test_RevertWhen_NodePartOfCapabilitiesDON() public { - changePrank(ADMIN); - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, false, F_VALUE); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfCapabilitiesDON.selector, 1, P2P_ID)); - s_CapabilitiesRegistry.removeNodes(nodes); - } - - function test_CanRemoveWhenDONDeleted() public { - changePrank(ADMIN); - - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - // Add DON - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - - // Try remove nodes - bytes32[] memory removedNodes = new bytes32[](1); - removedNodes[0] = P2P_ID; - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID)); - s_CapabilitiesRegistry.removeNodes(removedNodes); - - // Remove DON - uint32[] memory donIds = new uint32[](1); - donIds[0] = DON_ID; - s_CapabilitiesRegistry.removeDONs(donIds); - - // Remove node - s_CapabilitiesRegistry.removeNodes(removedNodes); - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, 0); - assertEq(node.p2pId, bytes32("")); - assertEq(node.signer, bytes32("")); - assertEq(node.hashedCapabilityIds.length, 0); - assertEq(node.configCount, 0); - } - - function test_CanRemoveWhenNodeNoLongerPartOfDON() public { - changePrank(ADMIN); - - bytes32[] memory nodes = new bytes32[](3); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - nodes[2] = P2P_ID_THREE; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - // Add DON - s_CapabilitiesRegistry.addDON(nodes, capabilityConfigs, true, true, F_VALUE); - - // Try remove nodes - bytes32[] memory removedNodes = new bytes32[](1); - removedNodes[0] = P2P_ID_TWO; - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodePartOfWorkflowDON.selector, 1, P2P_ID_TWO)); - s_CapabilitiesRegistry.removeNodes(removedNodes); - - // Update nodes in DON - bytes32[] memory updatedNodes = new bytes32[](2); - updatedNodes[0] = P2P_ID; - updatedNodes[1] = P2P_ID_THREE; - s_CapabilitiesRegistry.updateDON(DON_ID, updatedNodes, capabilityConfigs, true, F_VALUE); - - // Remove node - s_CapabilitiesRegistry.removeNodes(removedNodes); - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); - assertEq(node.nodeOperatorId, 0); - assertEq(node.p2pId, bytes32("")); - assertEq(node.signer, bytes32("")); - assertEq(node.hashedCapabilityIds.length, 0); - assertEq(node.configCount, 0); - } - - function test_RemovesNode() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeRemoved(P2P_ID); - s_CapabilitiesRegistry.removeNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, 0); - assertEq(node.p2pId, bytes32("")); - assertEq(node.signer, bytes32("")); - assertEq(node.hashedCapabilityIds.length, 0); - assertEq(node.configCount, 0); - } - - function test_CanAddNodeWithSameSignerAddressAfterRemoving() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - s_CapabilitiesRegistry.removeNodes(nodes); - - CapabilitiesRegistry.NodeParams[] memory nodeParams = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodeParams[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodeParams); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.hashedCapabilityIds.length, 2); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); - assertEq(node.configCount, 1); - } - - function test_OwnerCanRemoveNodes() public { - changePrank(ADMIN); - - bytes32[] memory nodes = new bytes32[](1); - nodes[0] = P2P_ID; - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeRemoved(P2P_ID); - s_CapabilitiesRegistry.removeNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, 0); - assertEq(node.p2pId, bytes32("")); - assertEq(node.signer, bytes32("")); - assertEq(node.hashedCapabilityIds.length, 0); - assertEq(node.configCount, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol deleted file mode 100644 index 00ce88f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_TypeAndVersionTest.t.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; - -contract CapabilitiesRegistry_TypeAndVersionTest is BaseTest { - function test_TypeAndVersion() public view { - assertEq(s_CapabilitiesRegistry.typeAndVersion(), "CapabilitiesRegistry 1.0.0"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol deleted file mode 100644 index 52b496d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateDONTest.t.sol +++ /dev/null @@ -1,241 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {ICapabilityConfiguration} from "../interfaces/ICapabilityConfiguration.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_UpdateDONTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](3); - bytes32[] memory capabilityIds = new bytes32[](2); - capabilityIds[0] = s_basicHashedCapabilityId; - capabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: capabilityIds - }); - - bytes32[] memory nodeTwoCapabilityIds = new bytes32[](1); - nodeTwoCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: nodeTwoCapabilityIds - }); - - nodes[2] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_THREE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, - hashedCapabilityIds: capabilityIds - }); - - s_CapabilitiesRegistry.addNodes(nodes); - - bytes32[] memory donNodes = new bytes32[](2); - donNodes[0] = P2P_ID; - donNodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - s_CapabilitiesRegistry.addDON(donNodes, capabilityConfigs, true, true, F_VALUE); - } - - function test_RevertWhen_CalledByNonAdmin() public { - changePrank(STRANGER); - vm.expectRevert("Only callable by owner"); - bytes32[] memory nodes = new bytes32[](1); - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_NodeDoesNotSupportCapability() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.NodeDoesNotSupportCapability.selector, - P2P_ID_TWO, - s_capabilityWithConfigurationContractId - ) - ); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_DONDoesNotExist() public { - uint32 nonExistentDONId = 10; - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DONDoesNotExist.selector, nonExistentDONId)); - s_CapabilitiesRegistry.updateDON(nonExistentDONId, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_CapabilityDoesNotExist() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_nonExistentHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.CapabilityDoesNotExist.selector, s_nonExistentHashedCapabilityId) - ); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_DuplicateCapabilityAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONCapability.selector, 1, s_basicHashedCapabilityId) - ); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_DeprecatedCapabilityAdded() public { - bytes32 capabilityId = s_basicHashedCapabilityId; - bytes32[] memory deprecatedCapabilities = new bytes32[](1); - deprecatedCapabilities[0] = capabilityId; - s_CapabilitiesRegistry.deprecateCapabilities(deprecatedCapabilities); - - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_TWO; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: capabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.CapabilityIsDeprecated.selector, capabilityId)); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_RevertWhen_DuplicateNodeAdded() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.DuplicateDONNode.selector, 1, P2P_ID)); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, true, F_VALUE); - } - - function test_UpdatesDON() public { - bytes32[] memory nodes = new bytes32[](2); - nodes[0] = P2P_ID; - nodes[1] = P2P_ID_THREE; - - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](2); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - capabilityConfigs[1] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_capabilityWithConfigurationContractId, - config: CONFIG_CAPABILITY_CONFIG - }); - - CapabilitiesRegistry.DONInfo memory oldDONInfo = s_CapabilitiesRegistry.getDON(DON_ID); - - bool expectedDONIsPublic = false; - uint32 expectedConfigCount = oldDONInfo.configCount + 1; - - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.ConfigSet(DON_ID, expectedConfigCount); - vm.expectCall( - address(s_capabilityConfigurationContract), - abi.encodeWithSelector( - ICapabilityConfiguration.beforeCapabilityConfigSet.selector, - nodes, - CONFIG_CAPABILITY_CONFIG, - expectedConfigCount, - DON_ID - ), - 1 - ); - s_CapabilitiesRegistry.updateDON(DON_ID, nodes, capabilityConfigs, expectedDONIsPublic, F_VALUE); - - CapabilitiesRegistry.DONInfo memory donInfo = s_CapabilitiesRegistry.getDON(DON_ID); - assertEq(donInfo.id, DON_ID); - assertEq(donInfo.configCount, expectedConfigCount); - assertEq(donInfo.isPublic, false); - assertEq(donInfo.capabilityConfigurations.length, capabilityConfigs.length); - assertEq(donInfo.capabilityConfigurations[0].capabilityId, s_basicHashedCapabilityId); - - (bytes memory CapabilitiesRegistryDONConfig, bytes memory capabilityConfigContractConfig) = s_CapabilitiesRegistry - .getCapabilityConfigs(DON_ID, s_basicHashedCapabilityId); - assertEq(CapabilitiesRegistryDONConfig, BASIC_CAPABILITY_CONFIG); - assertEq(capabilityConfigContractConfig, bytes("")); - - assertEq(donInfo.nodeP2PIds.length, nodes.length); - assertEq(donInfo.nodeP2PIds[0], P2P_ID); - assertEq(donInfo.nodeP2PIds[1], P2P_ID_THREE); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol deleted file mode 100644 index 8f6be58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_UpdateNodeOperatorTest is BaseTest { - uint32 private constant TEST_NODE_OPERATOR_ID = 1; - address private constant NEW_NODE_OPERATOR_ADMIN = address(3); - string private constant NEW_NODE_OPERATOR_NAME = "new-node-operator"; - - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - } - - function test_RevertWhen_CalledByNonAdminAndNonOwner() public { - changePrank(STRANGER); - - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: ADMIN, name: NEW_NODE_OPERATOR_NAME}); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); - s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorAdminIsZeroAddress() public { - changePrank(ADMIN); - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: address(0), name: NEW_NODE_OPERATOR_NAME}); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectRevert(CapabilitiesRegistry.InvalidNodeOperatorAdmin.selector); - s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() public { - changePrank(ADMIN); - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ - admin: NEW_NODE_OPERATOR_ADMIN, - name: NEW_NODE_OPERATOR_NAME - }); - - uint32 invalidNodeOperatorId = 10000; - uint32[] memory nodeOperatorIds = new uint32[](2); - nodeOperatorIds[0] = invalidNodeOperatorId; - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.LengthMismatch.selector, nodeOperatorIds.length, nodeOperators.length) - ); - s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_RevertWhen_NodeOperatorDoesNotExist() public { - changePrank(ADMIN); - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ - admin: NEW_NODE_OPERATOR_ADMIN, - name: NEW_NODE_OPERATOR_NAME - }); - - uint32 invalidNodeOperatorId = 10000; - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = invalidNodeOperatorId; - vm.expectRevert( - abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) - ); - s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - } - - function test_UpdatesNodeOperator() public { - changePrank(ADMIN); - - CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ - admin: NEW_NODE_OPERATOR_ADMIN, - name: NEW_NODE_OPERATOR_NAME - }); - - uint32[] memory nodeOperatorIds = new uint32[](1); - nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; - - vm.expectEmit(true, true, true, true, address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeOperatorUpdated( - TEST_NODE_OPERATOR_ID, - NEW_NODE_OPERATOR_ADMIN, - NEW_NODE_OPERATOR_NAME - ); - s_CapabilitiesRegistry.updateNodeOperators(nodeOperatorIds, nodeOperators); - - CapabilitiesRegistry.NodeOperator memory nodeOperator = s_CapabilitiesRegistry.getNodeOperator( - TEST_NODE_OPERATOR_ID - ); - assertEq(nodeOperator.admin, NEW_NODE_OPERATOR_ADMIN); - assertEq(nodeOperator.name, NEW_NODE_OPERATOR_NAME); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol deleted file mode 100644 index 218161f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol +++ /dev/null @@ -1,386 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./BaseTest.t.sol"; -import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; - -contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { - function setUp() public override { - BaseTest.setUp(); - changePrank(ADMIN); - CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); - capabilities[0] = s_basicCapability; - capabilities[1] = s_capabilityWithConfigurationContract; - - s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); - s_CapabilitiesRegistry.addCapabilities(capabilities); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](2); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(NODE_OPERATOR_ONE_ADMIN); - s_CapabilitiesRegistry.addNodes(nodes); - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - changePrank(NODE_OPERATOR_TWO_ADMIN); - s_CapabilitiesRegistry.addNodes(nodes); - } - - function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { - changePrank(STRANGER); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_CalledByAnotherNodeOperatorAdmin() public { - changePrank(NODE_OPERATOR_TWO_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID, - signer: NEW_NODE_SIGNER, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, NODE_OPERATOR_TWO_ADMIN)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_NodeDoesNotExist() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: INVALID_P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, INVALID_P2P_ID)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_P2PIDEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: bytes32(""), - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeDoesNotExist.selector, bytes32(""))); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_SignerAddressEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: bytes32(""), - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_EncryptionPublicKeyEmpty() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: bytes32(""), - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_TWO_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(CapabilitiesRegistry.InvalidNodeSigner.selector); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_UpdatingNodeWithoutCapabilities() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](0); - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_AddingNodeWithInvalidCapability() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() public { - // SETUP: addDON - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - bytes32[] memory nodeIds = new bytes32[](2); - nodeIds[0] = P2P_ID; - nodeIds[1] = P2P_ID_TWO; - - // SETUP: updateNodes - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - // DON requires s_basicHashedCapabilityId but we are swapping for - // s_capabilityWithConfigurationContractId - hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - uint32 workflowDonId = 1; - - // Operations - changePrank(ADMIN); - s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, true, 1); - - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.CapabilityRequiredByDON.selector, - s_basicHashedCapabilityId, - workflowDonId - ) - ); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() public { - // SETUP: addDON - CapabilitiesRegistry.CapabilityConfiguration[] - memory capabilityConfigs = new CapabilitiesRegistry.CapabilityConfiguration[](1); - capabilityConfigs[0] = CapabilitiesRegistry.CapabilityConfiguration({ - capabilityId: s_basicHashedCapabilityId, - config: BASIC_CAPABILITY_CONFIG - }); - bytes32[] memory nodeIds = new bytes32[](2); - nodeIds[0] = P2P_ID; - nodeIds[1] = P2P_ID_TWO; - - // SETUP: updateNodes - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - // DON requires s_basicHashedCapabilityId but we are swapping for - // s_capabilityWithConfigurationContractId - hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - uint32 capabilitiesDonId = 1; - - // Operations - changePrank(ADMIN); - s_CapabilitiesRegistry.addDON(nodeIds, capabilityConfigs, true, false, 1); - - vm.expectRevert( - abi.encodeWithSelector( - CapabilitiesRegistry.CapabilityRequiredByDON.selector, - s_basicHashedCapabilityId, - capabilitiesDonId - ) - ); - s_CapabilitiesRegistry.updateNodes(nodes); - } - - function test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - // Set node one's signer to another address - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: bytes32(abi.encodePacked(address(6666))), - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - s_CapabilitiesRegistry.updateNodes(nodes); - - // Set node two's signer to node one's signer - changePrank(NODE_OPERATOR_TWO_ADMIN); - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, - p2pId: P2P_ID_TWO, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_TWO, - hashedCapabilityIds: hashedCapabilityIds - }); - s_CapabilitiesRegistry.updateNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID_TWO); - assertEq(node.signer, NODE_OPERATOR_ONE_SIGNER_ADDRESS); - } - - function test_UpdatesNodeParams() public { - changePrank(NODE_OPERATOR_ONE_ADMIN); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NEW_NODE_SIGNER, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); - s_CapabilitiesRegistry.updateNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.signer, NEW_NODE_SIGNER); - assertEq(node.hashedCapabilityIds.length, 1); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(node.configCount, 2); - } - - function test_OwnerCanUpdateNodes() public { - changePrank(ADMIN); - - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - hashedCapabilityIds[0] = s_basicHashedCapabilityId; - - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NEW_NODE_SIGNER, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - vm.expectEmit(address(s_CapabilitiesRegistry)); - emit CapabilitiesRegistry.NodeUpdated(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NEW_NODE_SIGNER); - s_CapabilitiesRegistry.updateNodes(nodes); - - CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); - assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); - assertEq(node.p2pId, P2P_ID); - assertEq(node.signer, NEW_NODE_SIGNER); - assertEq(node.hashedCapabilityIds.length, 1); - assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); - assertEq(node.configCount, 2); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol deleted file mode 100644 index a0501a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/Constants.t.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -contract Constants { - address internal constant ADMIN = address(1); - address internal constant STRANGER = address(2); - - uint32 internal constant TEST_NODE_OPERATOR_ONE_ID = 1; - address internal constant NODE_OPERATOR_ONE_ADMIN = address(3); - string internal constant NODE_OPERATOR_ONE_NAME = "node-operator-one"; - bytes32 internal constant NODE_OPERATOR_ONE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(3333))); - bytes32 internal constant P2P_ID = hex"e42415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; - bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY = bytes32("test-encryption-public-key"); - - uint32 internal constant TEST_NODE_OPERATOR_TWO_ID = 2; - address internal constant NODE_OPERATOR_TWO_ADMIN = address(4); - string internal constant NODE_OPERATOR_TWO_NAME = "node-operator-two"; - bytes32 internal constant NODE_OPERATOR_TWO_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(4444))); - bytes32 internal constant P2P_ID_TWO = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a05"; - bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_TWO = bytes32("test-encryption-public-key-2"); - - uint32 internal constant TEST_NODE_OPERATOR_THREE_ID = 3; - address internal constant NODE_OPERATOR_THREE = address(4); - string internal constant NODE_OPERATOR_THREE_NAME = "node-operator-three"; - bytes32 internal constant NODE_OPERATOR_THREE_SIGNER_ADDRESS = bytes32(abi.encodePacked(address(5555))); - bytes32 internal constant P2P_ID_THREE = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a06"; - bytes32 internal constant TEST_ENCRYPTION_PUBLIC_KEY_THREE = bytes32("test-encryption-public-key-3"); - - uint8 internal constant F_VALUE = 1; - uint32 internal constant DON_ID = 1; - uint32 internal constant DON_ID_TWO = 2; - - bytes32 internal constant INVALID_P2P_ID = bytes32("fake-p2p"); - bytes32 internal constant NEW_NODE_SIGNER = hex"f53415859707d90ed4dc534ad730f187a17b0c368e1beec2e9b995587c4b0a07"; - - bytes internal constant BASIC_CAPABILITY_CONFIG = bytes("basic-capability-config"); - bytes internal constant CONFIG_CAPABILITY_CONFIG = bytes("config-capability-config"); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol deleted file mode 100644 index 0dd480a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarderBaseTest.t.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; -import {Receiver} from "./mocks/Receiver.sol"; -import {KeystoneForwarder} from "../KeystoneForwarder.sol"; - -contract BaseTest is Test { - address internal ADMIN = address(1); - address internal constant TRANSMITTER = address(50); - uint256 internal constant MAX_ORACLES = 31; - uint32 internal DON_ID = 0x01020304; - uint8 internal F = 1; - uint32 internal CONFIG_VERSION = 1; - - struct Signer { - uint256 mockPrivateKey; - address signerAddress; - } - - Signer[MAX_ORACLES] internal s_signers; - KeystoneForwarder internal s_forwarder; - KeystoneForwarder internal s_router; - Receiver internal s_receiver; - - function setUp() public virtual { - vm.startPrank(ADMIN); - s_router = new KeystoneForwarder(); - s_forwarder = new KeystoneForwarder(); - s_router.addForwarder(address(s_forwarder)); - s_receiver = new Receiver(); - - uint256 seed = 0; - - for (uint256 i; i < MAX_ORACLES; ++i) { - uint256 mockPK = seed + i + 1; - s_signers[i].mockPrivateKey = mockPK; - s_signers[i].signerAddress = vm.addr(mockPK); - } - } - - function _getSignerAddresses() internal view returns (address[] memory) { - address[] memory signerAddrs = new address[](s_signers.length); - for (uint256 i = 0; i < signerAddrs.length; ++i) { - signerAddrs[i] = s_signers[i].signerAddress; - } - return signerAddrs; - } - - function _getSignerAddresses(uint256 limit) internal view returns (address[] memory) { - address[] memory signerAddrs = new address[](limit); - for (uint256 i = 0; i < limit; ++i) { - signerAddrs[i] = s_signers[i].signerAddress; - } - return signerAddrs; - } - - function _signReport( - bytes memory report, - bytes memory reportContext, - uint256 requiredSignatures - ) internal view returns (bytes[] memory signatures) { - signatures = new bytes[](requiredSignatures); - for (uint256 i = 0; i < requiredSignatures; ++i) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign( - s_signers[i].mockPrivateKey, - keccak256(abi.encodePacked(keccak256(report), reportContext)) - ); - signatures[i] = bytes.concat(r, s, bytes1(v - 27)); - } - return signatures; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol deleted file mode 100644 index c6dc7fc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_ReportTest.t.sol +++ /dev/null @@ -1,326 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; -import {MaliciousReportReceiver} from "./mocks/MaliciousReportReceiver.sol"; -import {MaliciousRevertingReceiver} from "./mocks/MaliciousRevertingReceiver.sol"; -import {KeystoneForwarder} from "../KeystoneForwarder.sol"; - -contract KeystoneForwarder_ReportTest is BaseTest { - event MessageReceived(bytes metadata, bytes[] mercuryReports); - event ReportProcessed( - address indexed receiver, - bytes32 indexed workflowExecutionId, - bytes2 indexed reportId, - bool result - ); - - uint8 internal version = 1; - uint32 internal timestamp = 0; - bytes32 internal workflowId = hex"6d795f6964000000000000000000000000000000000000000000000000000000"; - bytes10 internal workflowName = hex"000000000000DEADBEEF"; - address internal workflowOwner = address(51); - bytes32 internal executionId = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; - bytes2 internal reportId = hex"0001"; - bytes[] internal mercuryReports = new bytes[](2); - bytes internal rawReports; - bytes internal header; - bytes internal metadata; - bytes internal report; - bytes internal reportContext = new bytes(96); - uint256 internal requiredSignaturesNum = F + 1; - bytes[] internal signatures = new bytes[](2); - - function setUp() public override { - BaseTest.setUp(); - - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); - s_router.addForwarder(address(s_forwarder)); - - mercuryReports[0] = hex"010203"; - mercuryReports[1] = hex"aabbccdd"; - - rawReports = abi.encode(mercuryReports); - metadata = abi.encodePacked(workflowId, workflowName, workflowOwner, reportId); - header = abi.encodePacked(version, executionId, timestamp, DON_ID, CONFIG_VERSION, metadata); - report = abi.encodePacked(header, rawReports); - - signatures = _signReport(report, reportContext, requiredSignaturesNum); - - vm.startPrank(TRANSMITTER); - } - - function test_RevertWhen_ReportHasIncorrectDON() public { - uint32 invalidDONId = 111; - bytes memory reportWithInvalidDONId = abi.encodePacked( - version, - executionId, - timestamp, - invalidDONId, - CONFIG_VERSION, - workflowId, - workflowName, - workflowOwner, - reportId, - rawReports - ); - - uint64 configId = (uint64(invalidDONId) << 32) | CONFIG_VERSION; - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); - s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); - } - - function test_RevertWhen_ReportHasInexistentConfigVersion() public { - bytes memory reportWithInvalidDONId = abi.encodePacked( - version, - executionId, - timestamp, - DON_ID, - CONFIG_VERSION + 1, - workflowId, - workflowName, - workflowOwner, - reportId, - rawReports - ); - - uint64 configId = (uint64(DON_ID) << 32) | (CONFIG_VERSION + 1); - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); - s_forwarder.report(address(s_receiver), reportWithInvalidDONId, reportContext, signatures); - } - - function test_RevertWhen_ReportIsMalformed() public { - bytes memory shortenedReport = abi.encode(bytes32(report)); - - vm.expectRevert(KeystoneForwarder.InvalidReport.selector); - s_forwarder.report(address(s_receiver), shortenedReport, reportContext, signatures); - } - - function test_RevertWhen_TooFewSignatures() public { - bytes[] memory fewerSignatures = new bytes[](F); - - vm.expectRevert( - abi.encodeWithSelector(KeystoneForwarder.InvalidSignatureCount.selector, F + 1, fewerSignatures.length) - ); - s_forwarder.report(address(s_receiver), report, reportContext, fewerSignatures); - } - - function test_RevertWhen_TooManySignatures() public { - bytes[] memory moreSignatures = new bytes[](F + 2); - - vm.expectRevert( - abi.encodeWithSelector(KeystoneForwarder.InvalidSignatureCount.selector, F + 1, moreSignatures.length) - ); - s_forwarder.report(address(s_receiver), report, reportContext, moreSignatures); - } - - function test_RevertWhen_AnySignatureIsInvalid() public { - signatures[1] = abi.encode(1234); // invalid signature - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSignature.selector, signatures[1])); - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - } - - function test_RevertWhen_AnySignerIsInvalid() public { - uint256 mockPK = 999; - - Signer memory maliciousSigner = Signer({mockPrivateKey: mockPK, signerAddress: vm.addr(mockPK)}); - (uint8 v, bytes32 r, bytes32 s) = vm.sign( - maliciousSigner.mockPrivateKey, - keccak256(abi.encodePacked(keccak256(report), reportContext)) - ); - signatures[1] = bytes.concat(r, s, bytes1(v - 27)); - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSigner.selector, maliciousSigner.signerAddress)); - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - } - - function test_RevertWhen_ReportHasDuplicateSignatures() public { - signatures[1] = signatures[0]; // repeat a signature - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.DuplicateSigner.selector, s_signers[0].signerAddress)); - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - } - - function test_RevertWhen_RetryingSuccessfulTransmission() public { - s_forwarder.report{gas: 400_000}(address(s_receiver), report, reportContext, signatures); - - bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); - vm.expectRevert(abi.encodeWithSelector(IRouter.AlreadyAttempted.selector, transmissionId)); - // Retyring with more gas - s_forwarder.report{gas: 450_000}(address(s_receiver), report, reportContext, signatures); - } - - function test_RevertWhen_RetryingInvalidContractTransmission() public { - // Receiver is not a contract - address receiver = address(404); - s_forwarder.report{gas: 400_000}(receiver, report, reportContext, signatures); - - bytes32 transmissionId = s_forwarder.getTransmissionId(receiver, executionId, reportId); - vm.expectRevert(abi.encodeWithSelector(IRouter.AlreadyAttempted.selector, transmissionId)); - // Retyring with more gas - s_forwarder.report{gas: 450_000}(receiver, report, reportContext, signatures); - } - - function test_RevertWhen_AttemptingTransmissionWithInsufficientGas() public { - bytes32 transmissionId = s_forwarder.getTransmissionId(address(s_receiver), executionId, reportId); - vm.expectRevert(abi.encodeWithSelector(IRouter.InsufficientGasForRouting.selector, transmissionId)); - s_forwarder.report{gas: 150_000}(address(s_receiver), report, reportContext, signatures); - } - - function test_Report_SuccessfulDelivery() public { - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( - address(s_receiver), - executionId, - reportId - ); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.NOT_ATTEMPTED), "state mismatch"); - - vm.expectEmit(address(s_receiver)); - emit MessageReceived(metadata, mercuryReports); - - vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, reportId, true); - - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - - transmissionInfo = s_forwarder.getTransmissionInfo(address(s_receiver), executionId, reportId); - - assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); - assertGt(transmissionInfo.gasLimit, 100_000, "gas limit mismatch"); - } - - function test_Report_SuccessfulRetryWithMoreGas() public { - s_forwarder.report{gas: 200_000}(address(s_receiver), report, reportContext, signatures); - - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( - address(s_receiver), - executionId, - reportId - ); - // Expect to fail with the receiver running out of gas - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.FAILED), "state mismatch"); - assertGt(transmissionInfo.gasLimit, 100_000, "gas limit mismatch"); - - // Should succeed with more gas - s_forwarder.report{gas: 300_000}(address(s_receiver), report, reportContext, signatures); - - transmissionInfo = s_forwarder.getTransmissionInfo(address(s_receiver), executionId, reportId); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); - assertGt(transmissionInfo.gasLimit, 200_000, "gas limit mismatch"); - } - - function test_Report_FailedDeliveryWhenReceiverNotContract() public { - // Receiver is not a contract - address receiver = address(404); - - vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(receiver, executionId, reportId, false); - - s_forwarder.report(receiver, report, reportContext, signatures); - - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo(receiver, executionId, reportId); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.INVALID_RECEIVER), "state mismatch"); - } - - function test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() public { - // Receiver is a contract but doesn't implement the required interface - address receiver = address(s_forwarder); - - vm.expectEmit(true, true, true, false); - emit ReportProcessed(receiver, executionId, reportId, false); - - s_forwarder.report(receiver, report, reportContext, signatures); - - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo(receiver, executionId, reportId); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.INVALID_RECEIVER), "state mismatch"); - } - - function test_Report_FailedDeliveryWhenReportReceiverConsumesAllGasAndInterfaceCheckUsesMax() public { - MaliciousRevertingReceiver maliciousReceiver = new MaliciousRevertingReceiver(); - // This should not revert if gas tracking is effective - // It may revert if it fails to reserve sufficient gas for routing - // This POC requires pretty specific initial gas, so that 1/64 of gas passed to `onReport()` is insufficient to store the success - s_forwarder.report{gas: 200_000}(address(maliciousReceiver), report, reportContext, signatures); - - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( - address(maliciousReceiver), - executionId, - reportId - ); - - assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.SUCCEEDED), "state mismatch"); - } - - function test_Report_FailedDelieryWhenReportReceiverConsumesAllGas() public { - MaliciousReportReceiver s_maliciousReceiver = new MaliciousReportReceiver(); - s_forwarder.report{gas: 500_000}(address(s_maliciousReceiver), report, reportContext, signatures); - - IRouter.TransmissionInfo memory transmissionInfo = s_forwarder.getTransmissionInfo( - address(s_maliciousReceiver), - executionId, - reportId - ); - - assertEq(transmissionInfo.transmitter, TRANSMITTER, "transmitter mismatch"); - assertEq(uint8(transmissionInfo.state), uint8(IRouter.TransmissionState.FAILED), "state mismatch"); - assertGt(transmissionInfo.gasLimit, 410_000, "gas limit mismatch"); - } - - function test_Report_ConfigVersion() public { - vm.stopPrank(); - // configure a new configVersion - vm.prank(ADMIN); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION + 1, F, _getSignerAddresses()); - - // old version still works - vm.expectEmit(address(s_receiver)); - emit MessageReceived(metadata, mercuryReports); - - vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), executionId, reportId, true); - - vm.prank(TRANSMITTER); - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - - // after clear the old version doesn't work anymore - vm.prank(ADMIN); - s_forwarder.clearConfig(DON_ID, CONFIG_VERSION); - - uint64 configId = (uint64(DON_ID) << 32) | CONFIG_VERSION; - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidConfig.selector, configId)); - vm.prank(TRANSMITTER); - s_forwarder.report(address(s_receiver), report, reportContext, signatures); - - // but new config does - bytes32 newExecutionId = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000001"; - bytes memory newMetadata = abi.encodePacked(workflowId, workflowName, workflowOwner, reportId); - bytes memory newHeader = abi.encodePacked( - version, - newExecutionId, - timestamp, - DON_ID, - CONFIG_VERSION + 1, - newMetadata - ); - bytes memory newReport = abi.encodePacked(newHeader, rawReports); - // resign the new report - bytes[] memory newSignatures = _signReport(newReport, reportContext, requiredSignaturesNum); - - vm.expectEmit(address(s_receiver)); - emit MessageReceived(newMetadata, mercuryReports); - - vm.expectEmit(address(s_forwarder)); - emit ReportProcessed(address(s_receiver), newExecutionId, reportId, true); - - vm.prank(TRANSMITTER); - s_forwarder.report(address(s_receiver), newReport, reportContext, newSignatures); - - // validate transmitter was recorded - address transmitter = s_forwarder.getTransmitter(address(s_receiver), newExecutionId, reportId); - assertEq(transmitter, TRANSMITTER, "transmitter mismatch"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol deleted file mode 100644 index 5dcf79b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_SetConfigTest.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; -import {KeystoneForwarder} from "../KeystoneForwarder.sol"; - -contract KeystoneForwarder_SetConfigTest is BaseTest { - address internal constant STRANGER = address(2); - - function test_RevertWhen_NotOwner() public { - vm.stopPrank(); // BaseTest sets ADMIN - vm.prank(STRANGER); - vm.expectRevert(); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); - } - - function test_RevertWhen_FaultToleranceIsZero() public { - vm.expectRevert(KeystoneForwarder.FaultToleranceMustBePositive.selector); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, 0, _getSignerAddresses()); - } - - function test_RevertWhen_InsufficientSigners() public { - address[] memory signers = new address[](1); - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InsufficientSigners.selector, 1, 4)); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); - } - - function test_RevertWhen_ExcessSigners() public { - address[] memory signers = new address[](64); - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.ExcessSigners.selector, 64, 31)); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); - } - - function test_RevertWhen_ProvidingDuplicateSigners() public { - address[] memory signers = _getSignerAddresses(); - signers[1] = signers[0]; - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.DuplicateSigner.selector, signers[0])); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); - } - - function test_RevertWhen_ProvidingZeroAddressSigner() public { - address[] memory signers = _getSignerAddresses(); - signers[1] = address(0); - - vm.expectRevert(abi.encodeWithSelector(KeystoneForwarder.InvalidSigner.selector, signers[1])); - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, signers); - } - - function test_SetConfig_FirstTime() public { - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); - } - - function test_SetConfig_WhenSignersAreRemoved() public { - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses()); - - s_forwarder.setConfig(DON_ID, CONFIG_VERSION, F, _getSignerAddresses(16)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol deleted file mode 100644 index 5a5cc70..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneForwarder_TypeAndVersionTest.t.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseTest} from "./KeystoneForwarderBaseTest.t.sol"; - -contract KeystoneForwarder_TypeAndVersionTest is BaseTest { - function test_TypeAndVersion() public view { - assertEq(s_forwarder.typeAndVersion(), "Forwarder and Router 1.0.0"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol deleted file mode 100644 index 0e43b72..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/KeystoneRouter_AccessTest.t.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; -import {IReceiver} from "../interfaces/IReceiver.sol"; -import {IRouter} from "../interfaces/IRouter.sol"; -import {KeystoneForwarder} from "../KeystoneForwarder.sol"; -import {Receiver} from "./mocks/Receiver.sol"; - -contract KeystoneRouter_SetConfigTest is Test { - address internal ADMIN = address(1); - address internal constant STRANGER = address(2); - address internal constant FORWARDER = address(99); - address internal constant TRANSMITTER = address(50); - address internal constant RECEIVER = address(51); - - bytes internal metadata = hex"01020304"; - bytes internal report = hex"9998"; - bytes32 internal id = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; - - KeystoneForwarder internal s_router; - Receiver internal s_receiver; - - function setUp() public virtual { - vm.prank(ADMIN); - s_router = new KeystoneForwarder(); - s_receiver = new Receiver(); - } - - function test_AddForwarder_RevertWhen_NotOwner() public { - vm.prank(STRANGER); - vm.expectRevert(); - s_router.addForwarder(FORWARDER); - } - - function test_RemoveForwarder_RevertWhen_NotOwner() public { - vm.prank(STRANGER); - vm.expectRevert(); - s_router.removeForwarder(FORWARDER); - } - - function test_RemoveForwarder_Success() public { - vm.prank(ADMIN); - vm.expectEmit(true, false, false, false); - emit IRouter.ForwarderRemoved(FORWARDER); - s_router.removeForwarder(FORWARDER); - } - - function test_Route_RevertWhen_UnauthorizedForwarder() public { - vm.prank(STRANGER); - vm.expectRevert(IRouter.UnauthorizedForwarder.selector); - s_router.route(id, TRANSMITTER, RECEIVER, metadata, report); - } - - function test_Route_Success() public { - assertEq(s_router.isForwarder(FORWARDER), false); - - vm.prank(ADMIN); - s_router.addForwarder(FORWARDER); - assertEq(s_router.isForwarder(FORWARDER), true); - - vm.prank(FORWARDER); - vm.mockCall(address(s_receiver), abi.encodeCall(IReceiver.onReport, (metadata, report)), abi.encode()); - vm.expectCall(address(s_receiver), abi.encodeCall(IReceiver.onReport, (metadata, report))); - s_router.route(id, TRANSMITTER, address(s_receiver), metadata, report); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol deleted file mode 100644 index 105c890..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/CapabilityConfigurationContract.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -contract CapabilityConfigurationContract is ICapabilityConfiguration, IERC165 { - mapping(uint256 => bytes) private s_donConfiguration; - - function getCapabilityConfiguration(uint32 donId) external view returns (bytes memory configuration) { - return s_donConfiguration[donId]; - } - - function beforeCapabilityConfigSet(bytes32[] calldata, bytes calldata config, uint64, uint32 donId) external { - // In practice a real capability configuration contract will do more than just store - // the config for a DON - s_donConfiguration[donId] = config; - } - - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { - return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol deleted file mode 100644 index 9325014..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousConfigurationContract.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ICapabilityConfiguration} from "../../interfaces/ICapabilityConfiguration.sol"; -import {CapabilitiesRegistry} from "../../CapabilitiesRegistry.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Constants} from "../Constants.t.sol"; - -contract MaliciousConfigurationContract is ICapabilityConfiguration, IERC165, Constants { - bytes32 internal s_capabilityWithConfigurationContractId; - - constructor(bytes32 capabilityWithConfigContractId) { - s_capabilityWithConfigurationContractId = capabilityWithConfigContractId; - } - - function getCapabilityConfiguration(uint32) external pure returns (bytes memory configuration) { - return bytes(""); - } - - function beforeCapabilityConfigSet(bytes32[] calldata, bytes calldata, uint64, uint32) external { - CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](2); - bytes32[] memory hashedCapabilityIds = new bytes32[](1); - - hashedCapabilityIds[0] = s_capabilityWithConfigurationContractId; - - // Set node one's signer to another address - nodes[0] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID, - signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, - hashedCapabilityIds: hashedCapabilityIds - }); - - nodes[1] = CapabilitiesRegistry.NodeParams({ - nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, - p2pId: P2P_ID_THREE, - signer: NODE_OPERATOR_THREE_SIGNER_ADDRESS, - encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY_THREE, - hashedCapabilityIds: hashedCapabilityIds - }); - - CapabilitiesRegistry(msg.sender).updateNodes(nodes); - } - - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { - return interfaceId == type(ICapabilityConfiguration).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol deleted file mode 100644 index 8f039b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IReceiver} from "../../interfaces/IReceiver.sol"; - -contract MaliciousReportReceiver is IReceiver, IERC165 { - event MessageReceived(bytes metadata, bytes[] mercuryReports); - bytes public latestReport; - - function onReport(bytes calldata metadata, bytes calldata rawReport) external { - // Exhaust all gas that was provided - for (uint256 i = 0; i < 1_000_000_000; ++i) { - bytes[] memory mercuryReports = abi.decode(rawReport, (bytes[])); - latestReport = rawReport; - emit MessageReceived(metadata, mercuryReports); - } - } - - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol deleted file mode 100644 index f45e95a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IReceiver} from "../../interfaces/IReceiver.sol"; - -/// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` -/// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately -contract MaliciousRevertingReceiver is IReceiver, IERC165 { - function onReport(bytes calldata, bytes calldata) external view override { - // consumes about 63/64 of all gas available - uint256 targetGasRemaining = 200; - for (uint256 i = 0; gasleft() > targetGasRemaining; ++i) {} - } - - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - // Consume up to the maximum amount of gas that can be consumed in this check - for (uint256 i = 0; i < 500; ++i) {} - - return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol deleted file mode 100644 index d400595..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/keystone/test/mocks/Receiver.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IReceiver} from "../../interfaces/IReceiver.sol"; - -contract Receiver is IReceiver, IERC165 { - event MessageReceived(bytes metadata, bytes[] mercuryReports); - bytes public latestReport; - - constructor() {} - - function onReport(bytes calldata metadata, bytes calldata rawReport) external { - latestReport = rawReport; - - // parse actual report - bytes[] memory mercuryReports = abi.decode(rawReport, (bytes[])); - emit MessageReceived(metadata, mercuryReports); - } - - function supportsInterface(bytes4 interfaceId) public pure returns (bool) { - return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md deleted file mode 100644 index 21a537c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/README.md +++ /dev/null @@ -1,148 +0,0 @@ -# Overview - -This folder contains the source code and tests for the Layer 2 -Emergency Protocol (L2EP) contracts. It is organized as follows: - -```text -. -├─/dev (stores the latest source code for L2EP) -├─/test (stores the Foundry tests for L2EP) -``` - -## The `/dev` Folder - -The `/dev` folder contains subfolders for each chain that -has an L2EP solution implemented for it (e.g. `/scroll`, `/arbitrum`, -`/optimism`). It also contains a subfolder named `/interfaces`, -which stores shared interface types between all the supported -contracts. The top-level contracts (e.g. `CrossDomainOwnable.sol`) -serve as either abstract or parent contracts that are meant -to be reused for each indiviudal chain. - -## The `/test` Folder - -This folder is arranged as follows: - -- `/mocks`: used for both Foundry test cases and Hardhat test cases (NOTE: -Hardhat test cases should be considered deprecated at this point) - -- `/[version]`: test cases for a specific version of the L2EP contracts - -### Testing Conventions and Methodology - -By convention, each testing file should end in `.t.sol` (this is a standard -that other projects have also adopted). Each testing file in this folder -follows a similar structure. - -```text -TestFile.t.sol - | - |--- Base Contract (inherits L2EPTest contract) - | - |--- Child Contract 1 (inherits base contract) - | | - | |--- Test Function - | | - | |--- ... - | - | - |--- Child Contract 2 (inherits base contract) - | | - | |--- Test Function - | | - | |--- ... - | - | - ... -``` - -All test files contain a base contract defined at the top of the file. This -base contract inherits from a contract called `L2EPTest`. The `L2EPTest` -contract and base contracts have no test cases. Instead, the `L2EPTest` -contract is meant to store data/functions that will be reused among all -the base contracts. Similarly, the base contract is meant to store data -and/or functions that will be reused by any contracts that inherit it. -As such, each test file will define separate child contracts, and each -will inherit from the base contract + define its own set of tests. - -The base contract defines a `setUp` function which is automatically called -exactly once before ***each*** of the tests are run in an inheriting contract. -The `setUp` function typically deploys a fresh set of test contracts so that -tests can run independently of each other. Alongside the `setUp` function, -the base contract can also define variables, constants, events, etc. that -are meant to be reused per test. - -The name of the base contract follows the following convention: - -```text -Test -``` - -The child contract names follow a similar convention: - -```text -_ -``` - -Each test function within the child contract complies -with the following naming pattern: - -```text -test_ -``` - -### Running Foundry Tests - -#### Usage - -First make sure you are in the contracts directory: - -```sh -# Assuming you are currently in the /chainlink directory -cd ./contracts -``` - -If you already have foundry installed, you can use the following command -to run all L2EP tests: - -```sh -FOUNDRY_PROFILE=l2ep forge test -vvv -``` - -To run a specific L2EP test, you can use a variation of the following command: - -```sh -FOUNDRY_PROFILE=l2ep forge test -vvv --match-path ./src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol -``` - -Or alternatively: - -```sh -FOUNDRY_PROFILE=l2ep forge test -vvv --match-contract ScrollSequencerUptimeFeed -``` - -If you prefer, you can also export `FOUNDRY_PROFILE` so that it doesn't need -to be provided before every command: - -```sh -# Export foundry profile -export FOUNDRY_PROFILE=l2ep - -# Run all tests -forge test -vvv - -# Run all tests and generate a gas snapshot -make snapshot -``` - -A full list of flags for `forge test` can be found [here](https://book.getfoundry.sh/reference/forge/forge-test). - -#### Coverage - -First ensure that the correct files are being evaluated. For example, if only -v1 contracts are, being evaluated then temporarily change the L2EP profile in -`./foundry.toml`. - -```sh -forge coverage -``` diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol deleted file mode 100644 index 859c6f0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; -import {IDelegateForwarder} from "./interfaces/IDelegateForwarder.sol"; - -/** - * @title CrossDomainDelegateForwarder - L1 xDomain account representation (with delegatecall support) - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can consider that position to be held by the `l1Owner` - */ -abstract contract CrossDomainDelegateForwarder is IDelegateForwarder, CrossDomainOwnable {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol deleted file mode 100644 index c097057..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {CrossDomainOwnable} from "./CrossDomainOwnable.sol"; -import {IForwarder} from "./interfaces/IForwarder.sol"; - -/** - * @title CrossDomainForwarder - L1 xDomain account representation - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can consider that position to be held by the `l1Owner` - */ -abstract contract CrossDomainForwarder is IForwarder, CrossDomainOwnable {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol deleted file mode 100644 index c85762b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {ICrossDomainOwnable} from "./interfaces/ICrossDomainOwnable.sol"; - -/** - * @title The CrossDomainOwnable contract - * @notice A contract with helpers for cross-domain contract ownership. - */ -contract CrossDomainOwnable is ICrossDomainOwnable, ConfirmedOwner { - address internal s_l1Owner; - address internal s_l1PendingOwner; - - constructor(address newl1Owner) ConfirmedOwner(msg.sender) { - _setL1Owner(newl1Owner); - } - - /** - * @notice transfer ownership of this account to a new L1 owner - * @param to new L1 owner that will be allowed to call the forward fn - */ - function transferL1Ownership(address to) public virtual override onlyL1Owner { - _transferL1Ownership(to); - } - - /** - * @notice accept ownership of this account to a new L1 owner - */ - function acceptL1Ownership() public virtual override onlyProposedL1Owner { - _setL1Owner(s_l1PendingOwner); - } - - /** - * @notice Get the current owner - */ - function l1Owner() public view override returns (address) { - return s_l1Owner; - } - - /** - * @notice validate, transfer ownership, and emit relevant events - */ - function _transferL1Ownership(address to) internal { - // solhint-disable-next-line gas-custom-errors - require(to != msg.sender, "Cannot transfer to self"); - - s_l1PendingOwner = to; - - emit L1OwnershipTransferRequested(s_l1Owner, to); - } - - /** - * @notice set ownership, emit relevant events. Used in acceptOwnership() - */ - function _setL1Owner(address to) internal { - address oldOwner = s_l1Owner; - s_l1Owner = to; - s_l1PendingOwner = address(0); - - emit L1OwnershipTransferred(oldOwner, to); - } - - /** - * @notice Reverts if called by anyone other than the L1 owner. - */ - modifier onlyL1Owner() virtual { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == s_l1Owner, "Only callable by L1 owner"); - _; - } - - /** - * @notice Reverts if called by anyone other than the L1 owner. - */ - modifier onlyProposedL1Owner() virtual { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == s_l1PendingOwner, "Only callable by proposed L1 owner"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol deleted file mode 100644 index 2dc030d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/Flags.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; -import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -/* dev dependencies - to be re/moved after audit */ -import {IFlags} from "./interfaces/IFlags.sol"; - -/** - * @title The Flags contract - * @notice Allows flags to signal to any reader on the access control list. - * The owner can set flags, or designate other addresses to set flags. - * Raise flag actions are controlled by its own access controller. - * Lower flag actions are controlled by its own access controller. - * An expected pattern is to allow addresses to raise flags on themselves, so if you are subscribing to - * FlagOn events you should filter for addresses you care about. - */ -// solhint-disable gas-custom-errors -contract Flags is ITypeAndVersion, IFlags, SimpleReadAccessController { - AccessControllerInterface public raisingAccessController; - AccessControllerInterface public loweringAccessController; - - mapping(address => bool) private s_flags; - - event FlagRaised(address indexed subject); - event FlagLowered(address indexed subject); - event RaisingAccessControllerUpdated(address indexed previous, address indexed current); - event LoweringAccessControllerUpdated(address indexed previous, address indexed current); - - /** - * @param racAddress address for the raising access controller. - * @param lacAddress address for the lowering access controller. - */ - constructor(address racAddress, address lacAddress) { - setRaisingAccessController(racAddress); - setLoweringAccessController(lacAddress); - } - - /** - * @notice versions: - * - * - Flags 1.1.0: upgraded to solc 0.8, added lowering access controller - * - Flags 1.0.0: initial release - * - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "Flags 1.1.0"; - } - - /** - * @notice read the warning flag status of a contract address. - * @param subject The contract address being checked for a flag. - * @return A true value indicates that a flag was raised and a - * false value indicates that no flag was raised. - */ - function getFlag(address subject) external view override checkAccess returns (bool) { - return s_flags[subject]; - } - - /** - * @notice read the warning flag status of a contract address. - * @param subjects An array of addresses being checked for a flag. - * @return An array of bools where a true value for any flag indicates that - * a flag was raised and a false value indicates that no flag was raised. - */ - function getFlags(address[] calldata subjects) external view override checkAccess returns (bool[] memory) { - bool[] memory responses = new bool[](subjects.length); - for (uint256 i = 0; i < subjects.length; i++) { - responses[i] = s_flags[subjects[i]]; - } - return responses; - } - - /** - * @notice enable the warning flag for an address. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subject The contract address whose flag is being raised - */ - function raiseFlag(address subject) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - _tryToRaiseFlag(subject); - } - - /** - * @notice enable the warning flags for multiple addresses. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subjects List of the contract addresses whose flag is being raised - */ - function raiseFlags(address[] calldata subjects) external override { - require(_allowedToRaiseFlags(), "Not allowed to raise flags"); - - for (uint256 i = 0; i < subjects.length; i++) { - _tryToRaiseFlag(subjects[i]); - } - } - - /** - * @notice allows owner to disable the warning flags for an addresses. - * Access is controlled by loweringAccessController, except for owner - * who always has access. - * @param subject The contract address whose flag is being lowered - */ - function lowerFlag(address subject) external override { - require(_allowedToLowerFlags(), "Not allowed to lower flags"); - - _tryToLowerFlag(subject); - } - - /** - * @notice allows owner to disable the warning flags for multiple addresses. - * Access is controlled by loweringAccessController, except for owner - * who always has access. - * @param subjects List of the contract addresses whose flag is being lowered - */ - function lowerFlags(address[] calldata subjects) external override { - require(_allowedToLowerFlags(), "Not allowed to lower flags"); - - for (uint256 i = 0; i < subjects.length; i++) { - address subject = subjects[i]; - - _tryToLowerFlag(subject); - } - } - - /** - * @notice allows owner to change the access controller for raising flags. - * @param racAddress new address for the raising access controller. - */ - function setRaisingAccessController(address racAddress) public override onlyOwner { - address previous = address(raisingAccessController); - - if (previous != racAddress) { - raisingAccessController = AccessControllerInterface(racAddress); - - emit RaisingAccessControllerUpdated(previous, racAddress); - } - } - - function setLoweringAccessController(address lacAddress) public override onlyOwner { - address previous = address(loweringAccessController); - - if (previous != lacAddress) { - loweringAccessController = AccessControllerInterface(lacAddress); - - emit LoweringAccessControllerUpdated(previous, lacAddress); - } - } - - // PRIVATE - function _allowedToRaiseFlags() private view returns (bool) { - return msg.sender == owner() || raisingAccessController.hasAccess(msg.sender, msg.data); - } - - function _allowedToLowerFlags() private view returns (bool) { - return msg.sender == owner() || loweringAccessController.hasAccess(msg.sender, msg.data); - } - - function _tryToRaiseFlag(address subject) private { - if (!s_flags[subject]) { - s_flags[subject] = true; - emit FlagRaised(subject); - } - } - - function _tryToLowerFlag(address subject) private { - if (s_flags[subject]) { - s_flags[subject] = false; - emit FlagLowered(subject); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol deleted file mode 100644 index 0db657e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -// solhint-disable-next-line no-unused-import -import {IForwarder} from "../interfaces/IForwarder.sol"; - -import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; -import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; - -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/** - * @title ArbitrumCrossDomainForwarder - L1 xDomain account representation - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can be considered to be owned by the `l1Owner` - */ -contract ArbitrumCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { - /** - * @notice creates a new Arbitrum xDomain Forwarder contract - * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder - */ - constructor(address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) {} - - /** - * @notice versions: - * - * - ArbitrumCrossDomainForwarder 0.1.0: initial release - * - ArbitrumCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable - * - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ArbitrumCrossDomainForwarder 1.0.0"; - } - - /** - * @notice The L2 xDomain `msg.sender`, generated from L1 sender address - */ - function crossDomainMessenger() public view returns (address) { - return AddressAliasHelper.applyL1ToL2Alias(l1Owner()); - } - - /** - * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - * @inheritdoc IForwarder - */ - function forward(address target, bytes memory data) external virtual override onlyL1Owner { - Address.functionCall(target, data, "Forwarder call reverted"); - } - - /** - * @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. - */ - modifier onlyL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == crossDomainMessenger(), "Sender is not the L2 messenger"); - _; - } - - /** - * @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. - */ - modifier onlyProposedL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == AddressAliasHelper.applyL1ToL2Alias(s_l1PendingOwner), "Must be proposed L1 owner"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol deleted file mode 100644 index 60d9cc5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line no-unused-import -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -// solhint-disable-next-line no-unused-import -import {IForwarder} from "../interfaces/IForwarder.sol"; -import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; - -import {ArbitrumCrossDomainForwarder} from "./ArbitrumCrossDomainForwarder.sol"; - -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/** - * @title ArbitrumCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Arbitrum - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` - */ -contract ArbitrumCrossDomainGovernor is IDelegateForwarder, ArbitrumCrossDomainForwarder { - /** - * @notice creates a new Arbitrum xDomain Forwarder contract - * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder - */ - constructor(address l1OwnerAddr) ArbitrumCrossDomainForwarder(l1OwnerAddr) {} - - /** - * @notice versions: - * - * - ArbitrumCrossDomainGovernor 1.0.0: initial release - * - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ArbitrumCrossDomainGovernor 1.0.0"; - } - - /** - * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc IForwarder - */ - function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionCall(target, data, "Governor call reverted"); - } - - /** - * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc IDelegateForwarder - */ - function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); - } - - /** - * @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. - */ - modifier onlyLocalOrCrossDomainOwner() { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == crossDomainMessenger() || msg.sender == owner(), "Sender is not the L2 messenger or owner"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol deleted file mode 100644 index 678bef3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol +++ /dev/null @@ -1,313 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IFlags} from "../interfaces/IFlags.sol"; -import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; - -/** - * @title ArbitrumSequencerUptimeFeed - L2 sequencer uptime status aggregator - * @notice L2 contract that receives status updates from a specific L1 address, - * records a new answer if the status changed, and raises or lowers the flag on the - * stored Flags contract. - */ -contract ArbitrumSequencerUptimeFeed is - AggregatorV2V3Interface, - ISequencerUptimeFeed, - ITypeAndVersion, - SimpleReadAccessController -{ - /// @dev Round info (for uptime history) - struct Round { - bool status; - uint64 timestamp; - } - - /// @dev Packed state struct to save sloads - struct FeedState { - uint80 latestRoundId; - bool latestStatus; - uint64 latestTimestamp; - } - - /// @notice Contract is not yet initialized - error Uninitialized(); - /// @notice Contract is already initialized - error AlreadyInitialized(); - /// @notice Sender is not the L2 messenger - error InvalidSender(); - /// @notice Replacement for AggregatorV3Interface "No data present" - error NoDataPresent(); - - event Initialized(); - event L1SenderTransferred(address indexed from, address indexed to); - /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - - /// @dev Follows: https://eips.ethereum.org/EIPS/eip-1967 - address public constant FLAG_L2_SEQ_OFFLINE = - address(bytes20(bytes32(uint256(keccak256("chainlink.flags.arbitrum-seq-offline")) - 1))); - - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint8 public constant override decimals = 0; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override description = "L2 Sequencer Uptime Status Feed"; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint256 public constant override version = 1; - - /// @dev Flags contract to raise/lower flags on, during status transitions - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - IFlags public immutable FLAGS; - /// @dev L1 address - address private s_l1Sender; - /// @dev s_latestRoundId == 0 means this contract is uninitialized. - FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, latestTimestamp: 0}); - mapping(uint80 => Round) private s_rounds; - - /** - * @param flagsAddress Address of the Flags contract on L2 - * @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract - */ - constructor(address flagsAddress, address l1SenderAddress) { - _setL1Sender(l1SenderAddress); - - FLAGS = IFlags(flagsAddress); - } - - /** - * @notice Check if a roundId is valid in this current contract state - * @dev Mainly used for AggregatorV2V3Interface functions - * @param roundId Round ID to check - */ - function _isValidRound(uint256 roundId) private view returns (bool) { - return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; - } - - /// @notice Check that this contract is initialised, otherwise throw - function _requireInitialized(uint80 latestRoundId) private pure { - if (latestRoundId == 0) { - revert Uninitialized(); - } - } - - /** - * @notice Initialise the first round. Can't be done in the constructor, - * because this contract's address must be permissioned by the the Flags contract - * (The Flags contract itself is a SimpleReadAccessController). - */ - function initialize() external onlyOwner { - FeedState memory feedState = s_feedState; - if (feedState.latestRoundId != 0) { - revert AlreadyInitialized(); - } - - uint64 timestamp = uint64(block.timestamp); - bool currentStatus = FLAGS.getFlag(FLAG_L2_SEQ_OFFLINE); - - // Initialise roundId == 1 as the first round - _recordRound(1, currentStatus, timestamp); - - emit Initialized(); - } - - /** - * @notice versions: - * - * - ArbitrumSequencerUptimeFeed 1.0.0: initial release - * - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ArbitrumSequencerUptimeFeed 1.0.0"; - } - - /// @return L1 sender address - function l1Sender() public view virtual returns (address) { - return s_l1Sender; - } - - /** - * @notice Set the allowed L1 sender for this contract to a new L1 sender - * @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - * @param to new L1 sender that will be allowed to call `updateStatus` on this contract - */ - function transferL1Sender(address to) external virtual onlyOwner { - _setL1Sender(to); - } - - /// @notice internal method that stores the L1 sender - function _setL1Sender(address to) private { - address from = s_l1Sender; - if (from != to) { - s_l1Sender = to; - emit L1SenderTransferred(from, to); - } - } - - /** - * @notice Messages sent by the stored L1 sender will arrive on L2 with this - * address as the `msg.sender` - * @return L2-aliased form of the L1 sender address - */ - function aliasedL1MessageSender() public view returns (address) { - return AddressAliasHelper.applyL1ToL2Alias(l1Sender()); - } - - /** - * @dev Returns an AggregatorV2V3Interface compatible answer from status flag - * - * @param status The status flag to convert to an aggregator-compatible answer - */ - function _getStatusAnswer(bool status) private pure returns (int256) { - return status ? int256(1) : int256(0); - } - - /** - * @notice Raise or lower the flag on the stored Flags contract. - */ - function _forwardStatusToFlags(bool status) private { - if (status) { - FLAGS.raiseFlag(FLAG_L2_SEQ_OFFLINE); - } else { - FLAGS.lowerFlag(FLAG_L2_SEQ_OFFLINE); - } - } - - /** - * @notice Helper function to record a round and set the latest feed state. - * - * @param roundId The round ID to record - * @param status Sequencer status - * @param timestamp Block timestamp of status update - */ - function _recordRound(uint80 roundId, bool status, uint64 timestamp) private { - Round memory nextRound = Round(status, timestamp); - FeedState memory feedState = FeedState(roundId, status, timestamp); - - s_rounds[roundId] = nextRound; - s_feedState = feedState; - - emit NewRound(roundId, msg.sender, timestamp); - emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); - } - - /** - * @notice Record a new status and timestamp if it has changed since the last round. - * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - * - * @param status Sequencer status - * @param timestamp Block timestamp of status update - */ - function updateStatus(bool status, uint64 timestamp) external override { - FeedState memory feedState = s_feedState; - _requireInitialized(feedState.latestRoundId); - if (msg.sender != aliasedL1MessageSender()) { - revert InvalidSender(); - } - - // Ignore if status did not change or latest recorded timestamp is newer - if (feedState.latestStatus == status || feedState.latestTimestamp > timestamp) { - emit UpdateIgnored(feedState.latestStatus, feedState.latestTimestamp, status, timestamp); - return; - } - - // Prepare a new round with updated status - feedState.latestRoundId += 1; - _recordRound(feedState.latestRoundId, status, timestamp); - - _forwardStatusToFlags(status); - } - - /// @inheritdoc AggregatorInterface - function latestAnswer() external view override checkAccess returns (int256) { - FeedState memory feedState = s_feedState; - _requireInitialized(feedState.latestRoundId); - return _getStatusAnswer(feedState.latestStatus); - } - - /// @inheritdoc AggregatorInterface - function latestTimestamp() external view override checkAccess returns (uint256) { - FeedState memory feedState = s_feedState; - _requireInitialized(feedState.latestRoundId); - return feedState.latestTimestamp; - } - - /// @inheritdoc AggregatorInterface - function latestRound() external view override checkAccess returns (uint256) { - FeedState memory feedState = s_feedState; - _requireInitialized(feedState.latestRoundId); - return feedState.latestRoundId; - } - - /// @inheritdoc AggregatorInterface - function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { - _requireInitialized(s_feedState.latestRoundId); - if (_isValidRound(roundId)) { - return _getStatusAnswer(s_rounds[uint80(roundId)].status); - } - - return 0; - } - - /// @inheritdoc AggregatorInterface - function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { - _requireInitialized(s_feedState.latestRoundId); - if (_isValidRound(roundId)) { - return s_rounds[uint80(roundId)].timestamp; - } - - return 0; - } - - /// @inheritdoc AggregatorV3Interface - function getRoundData( - uint80 _roundId - ) - public - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - _requireInitialized(s_feedState.latestRoundId); - - if (_isValidRound(_roundId)) { - Round memory round = s_rounds[_roundId]; - answer = _getStatusAnswer(round.status); - startedAt = uint256(round.timestamp); - } else { - answer = 0; - startedAt = 0; - } - roundId = _roundId; - updatedAt = startedAt; - answeredInRound = roundId; - - return (roundId, answer, startedAt, updatedAt, answeredInRound); - } - - /// @inheritdoc AggregatorV3Interface - function latestRoundData() - external - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - FeedState memory feedState = s_feedState; - _requireInitialized(feedState.latestRoundId); - - roundId = feedState.latestRoundId; - answer = _getStatusAnswer(feedState.latestStatus); - startedAt = feedState.latestTimestamp; - updatedAt = startedAt; - answeredInRound = roundId; - - return (roundId, answer, startedAt, updatedAt, answeredInRound); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol deleted file mode 100644 index 05f9349..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol +++ /dev/null @@ -1,355 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; - -/* ./dev dependencies - to be moved from ./dev after audit */ -import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {IArbitrumDelayedInbox} from "../interfaces/IArbitrumDelayedInbox.sol"; -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/** - * @title ArbitrumValidator - makes xDomain L2 Flags contract call (using L2 xDomain Forwarder contract) - * @notice Allows to raise and lower Flags on the Arbitrum L2 network through L1 bridge - * - The internal AccessController controls the access of the validate method - * - Gas configuration is controlled by a configurable external SimpleWriteAccessController - * - Funds on the contract are managed by the owner - */ -contract ArbitrumValidator is ITypeAndVersion, AggregatorValidatorInterface, SimpleWriteAccessController { - enum PaymentStrategy { - L1, - L2 - } - // Config for L1 -> L2 Arbitrum retryable ticket message - struct GasConfig { - uint256 maxGas; - uint256 gasPriceBid; - uint256 baseFee; // Will use block.baseFee if set to 0 - address gasPriceL1FeedAddr; - } - - /// @dev Precompiled contract that exists in every Arbitrum chain at address(100). Exposes a variety of system-level functionality. - address internal constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - - int256 private constant ANSWER_SEQ_OFFLINE = 1; - - /// @notice The address of Arbitrum's DelayedInbox - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable CROSS_DOMAIN_MESSENGER; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L2_SEQ_STATUS_RECORDER; - // L2 xDomain alias address of this contract - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L2_ALIAS = AddressAliasHelper.applyL1ToL2Alias(address(this)); - - PaymentStrategy private s_paymentStrategy; - GasConfig private s_gasConfig; - AccessControllerInterface private s_configAC; - - /** - * @notice emitted when a new payment strategy is set - * @param paymentStrategy strategy describing how the contract pays for xDomain calls - */ - event PaymentStrategySet(PaymentStrategy indexed paymentStrategy); - - /** - * @notice emitted when a new gas configuration is set - * @param maxGas gas limit for immediate L2 execution attempt. - * @param gasPriceBid maximum L2 gas price to pay - * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) - */ - event GasConfigSet(uint256 maxGas, uint256 gasPriceBid, address indexed gasPriceL1FeedAddr); - - /** - * @notice emitted when a new gas access-control contract is set - * @param previous the address prior to the current setting - * @param current the address of the new access-control contract - */ - event ConfigACSet(address indexed previous, address indexed current); - - /** - * @notice emitted when a new ETH withdrawal from L2 was requested - * @param id unique id of the published retryable transaction (keccak256(requestID, uint(0)) - * @param amount of funds to withdraw - */ - event L2WithdrawalRequested(uint256 indexed id, uint256 amount, address indexed refundAddr); - - /** - * @param crossDomainMessengerAddr address the xDomain bridge messenger (Arbitrum Inbox L1) contract address - * @param l2ArbitrumSequencerUptimeFeedAddr the L2 Flags contract address - * @param configACAddr address of the access controller for managing gas price on Arbitrum - * @param maxGas gas limit for immediate L2 execution attempt. A value around 1M should be sufficient - * @param gasPriceBid maximum L2 gas price to pay - * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) - * @param _paymentStrategy strategy describing how the contract pays for xDomain calls - */ - constructor( - address crossDomainMessengerAddr, - address l2ArbitrumSequencerUptimeFeedAddr, - address configACAddr, - uint256 maxGas, - uint256 gasPriceBid, - uint256 baseFee, - address gasPriceL1FeedAddr, - PaymentStrategy _paymentStrategy - ) { - // solhint-disable-next-line gas-custom-errors - require(crossDomainMessengerAddr != address(0), "Invalid xDomain Messenger address"); - // solhint-disable-next-line gas-custom-errors - require(l2ArbitrumSequencerUptimeFeedAddr != address(0), "Invalid ArbitrumSequencerUptimeFeed contract address"); - CROSS_DOMAIN_MESSENGER = crossDomainMessengerAddr; - L2_SEQ_STATUS_RECORDER = l2ArbitrumSequencerUptimeFeedAddr; - // Additional L2 payment configuration - _setConfigAC(configACAddr); - _setGasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); - _setPaymentStrategy(_paymentStrategy); - } - - /** - * @notice versions: - * - * - ArbitrumValidator 0.1.0: initial release - * - ArbitrumValidator 0.2.0: critical Arbitrum network update - * - xDomain `msg.sender` backwards incompatible change (now an alias address) - * - new `withdrawFundsFromL2` fn that withdraws from L2 xDomain alias address - * - approximation of `maxSubmissionCost` using a L1 gas price feed - * - ArbitrumValidator 1.0.0: change target of L2 sequencer status update - * - now calls `updateStatus` on an L2 ArbitrumSequencerUptimeFeed contract instead of - * directly calling the Flags contract - * - ArbitrumValidator 2.0.0: change how maxSubmissionCost is calculated when sending cross chain messages - * - now calls `calculateRetryableSubmissionFee` instead of inlining equation to estimate - * the maxSubmissionCost required to send the message to L2 - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "ArbitrumValidator 2.0.0"; - } - - /// @return stored PaymentStrategy - function paymentStrategy() external view virtual returns (PaymentStrategy) { - return s_paymentStrategy; - } - - /// @return stored GasConfig - function gasConfig() external view virtual returns (GasConfig memory) { - return s_gasConfig; - } - - /// @return config AccessControllerInterface contract address - function configAC() external view virtual returns (address) { - return address(s_configAC); - } - - /** - * @notice makes this contract payable - * @dev receives funds: - * - to use them (if configured) to pay for L2 execution on L1 - * - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) - */ - receive() external payable {} - - /** - * @notice withdraws all funds available in this contract to the msg.sender - * @dev only owner can call this - */ - function withdrawFunds() external onlyOwner { - address payable recipient = payable(msg.sender); - uint256 amount = address(this).balance; - Address.sendValue(recipient, amount); - } - - /** - * @notice withdraws all funds available in this contract to the address specified - * @dev only owner can call this - * @param recipient address where to send the funds - */ - function withdrawFundsTo(address payable recipient) external onlyOwner { - uint256 amount = address(this).balance; - Address.sendValue(recipient, amount); - } - - /** - * @notice withdraws funds from L2 xDomain alias address (representing this L1 contract) - * @dev only owner can call this - * @param amount of funds to withdraws - * @param refundAddr address where gas excess on L2 will be sent - * WARNING: `refundAddr` is not aliased! Make sure you can recover the refunded funds on L2. - * @return id unique id of the published retryable transaction (keccak256(requestID, uint(0)) - */ - function withdrawFundsFromL2(uint256 amount, address refundAddr) external onlyOwner returns (uint256 id) { - // Build an xDomain message to trigger the ArbSys precompile, which will create a L2 -> L1 tx transferring `amount` - bytes memory message = abi.encodeWithSelector(ArbSys.withdrawEth.selector, address(this)); - // Make the xDomain call - // NOTICE: We approximate the max submission cost of sending a retryable tx with specific calldata length. - uint256 maxSubmissionCost = _approximateMaxSubmissionCost(message.length); - uint256 maxGas = 120_000; // static `maxGas` for L2 -> L1 transfer - uint256 gasPriceBid = s_gasConfig.gasPriceBid; - uint256 l1PaymentValue = s_paymentStrategy == PaymentStrategy.L1 - ? _maxRetryableTicketCost(maxSubmissionCost, maxGas, gasPriceBid) - : 0; - // NOTICE: In the case of PaymentStrategy.L2 the L2 xDomain alias address needs to be funded, as it will be paying the fee. - id = IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).createRetryableTicketNoRefundAliasRewrite{value: l1PaymentValue}( - ARBSYS_ADDR, // target - amount, // L2 call value (requested) - maxSubmissionCost, - refundAddr, // excessFeeRefundAddress - refundAddr, // callValueRefundAddress - maxGas, - gasPriceBid, - message - ); - emit L2WithdrawalRequested(id, amount, refundAddr); - - return id; - } - - /** - * @notice sets config AccessControllerInterface contract - * @dev only owner can call this - * @param accessController new AccessControllerInterface contract address - */ - function setConfigAC(address accessController) external onlyOwner { - _setConfigAC(accessController); - } - - /** - * @notice sets Arbitrum gas configuration - * @dev access control provided by `configAC` - * @param maxGas gas limit for immediate L2 execution attempt. A value around 1M should be sufficient - * @param gasPriceBid maximum L2 gas price to pay - * @param gasPriceL1FeedAddr address of the L1 gas price feed (used to approximate Arbitrum retryable ticket submission cost) - */ - function setGasConfig( - uint256 maxGas, - uint256 gasPriceBid, - uint256 baseFee, - address gasPriceL1FeedAddr - ) external onlyOwnerOrConfigAccess { - _setGasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); - } - - /** - * @notice sets the payment strategy - * @dev access control provided by `configAC` - * @param _paymentStrategy strategy describing how the contract pays for xDomain calls - */ - function setPaymentStrategy(PaymentStrategy _paymentStrategy) external onlyOwnerOrConfigAccess { - _setPaymentStrategy(_paymentStrategy); - } - - /** - * @notice validate method sends an xDomain L2 tx to update Flags contract, in case of change from `previousAnswer`. - * @dev A retryable ticket is created on the Arbitrum L1 Inbox contract. The tx gas fee can be paid from this - * contract providing a value, or if no L1 value is sent with the xDomain message the gas will be paid by - * the L2 xDomain alias account (generated from `address(this)`). This method is accessed controlled. - * @param previousAnswer previous aggregator answer - * @param currentAnswer new aggregator answer - value of 1 considers the service offline. - */ - function validate( - uint256 /* previousRoundId */, - int256 previousAnswer, - uint256 /* currentRoundId */, - int256 currentAnswer - ) external override checkAccess returns (bool) { - // Avoids resending to L2 the same tx on every call - if (previousAnswer == currentAnswer) { - return true; - } - - // Excess gas on L2 will be sent to the L2 xDomain alias address of this contract - address refundAddr = L2_ALIAS; - // Encode the ArbitrumSequencerUptimeFeed call - bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; - bool status = currentAnswer == ANSWER_SEQ_OFFLINE; - uint64 timestamp = uint64(block.timestamp); - // Encode `status` and `timestamp` - bytes memory message = abi.encodeWithSelector(selector, status, timestamp); - // Make the xDomain call - // NOTICE: We approximate the max submission cost of sending a retryable tx with specific calldata length. - uint256 maxSubmissionCost = _approximateMaxSubmissionCost(message.length); - uint256 maxGas = s_gasConfig.maxGas; - uint256 gasPriceBid = s_gasConfig.gasPriceBid; - uint256 l1PaymentValue = s_paymentStrategy == PaymentStrategy.L1 - ? _maxRetryableTicketCost(maxSubmissionCost, maxGas, gasPriceBid) - : 0; - // NOTICE: In the case of PaymentStrategy.L2 the L2 xDomain alias address needs to be funded, as it will be paying the fee. - // We also ignore the returned msg number, that can be queried via the `InboxMessageDelivered` event. - IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).createRetryableTicketNoRefundAliasRewrite{value: l1PaymentValue}( - L2_SEQ_STATUS_RECORDER, // target - 0, // L2 call value - maxSubmissionCost, - refundAddr, // excessFeeRefundAddress - refundAddr, // callValueRefundAddress - maxGas, - gasPriceBid, - message - ); - // return success - return true; - } - - /// @notice internal method that stores the payment strategy - function _setPaymentStrategy(PaymentStrategy _paymentStrategy) internal { - s_paymentStrategy = _paymentStrategy; - emit PaymentStrategySet(_paymentStrategy); - } - - /// @notice internal method that stores the gas configuration - function _setGasConfig(uint256 maxGas, uint256 gasPriceBid, uint256 baseFee, address gasPriceL1FeedAddr) internal { - // solhint-disable-next-line gas-custom-errors - require(maxGas > 0, "Max gas is zero"); - // solhint-disable-next-line gas-custom-errors - require(gasPriceBid > 0, "Gas price bid is zero"); - // solhint-disable-next-line gas-custom-errors - require(gasPriceL1FeedAddr != address(0), "Gas price Aggregator is zero address"); - s_gasConfig = GasConfig(maxGas, gasPriceBid, baseFee, gasPriceL1FeedAddr); - emit GasConfigSet(maxGas, gasPriceBid, gasPriceL1FeedAddr); - } - - /// @notice Internal method that stores the configuration access controller - function _setConfigAC(address accessController) internal { - address previousAccessController = address(s_configAC); - if (accessController != previousAccessController) { - s_configAC = AccessControllerInterface(accessController); - emit ConfigACSet(previousAccessController, accessController); - } - } - - /** - * @notice Internal method that approximates the `maxSubmissionCost` - * @dev This function estimates the max submission cost using the formula - * implemented in Arbitrum DelayedInbox's calculateRetryableSubmissionFee function - * @param calldataSizeInBytes xDomain message size in bytes - */ - function _approximateMaxSubmissionCost(uint256 calldataSizeInBytes) internal view returns (uint256) { - return - IArbitrumDelayedInbox(CROSS_DOMAIN_MESSENGER).calculateRetryableSubmissionFee( - calldataSizeInBytes, - s_gasConfig.baseFee - ); - } - - /// @notice Internal helper method that calculates the total cost of the xDomain retryable ticket call - function _maxRetryableTicketCost( - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal pure returns (uint256) { - return maxSubmissionCost + maxGas * gasPriceBid; - } - - /// @dev reverts if the caller does not have access to change the configuration - modifier onlyOwnerOrConfigAccess() { - // solhint-disable-next-line gas-custom-errors - require( - msg.sender == owner() || (address(s_configAC) != address(0) && s_configAC.hasAccess(msg.sender, msg.data)), - "No access" - ); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol deleted file mode 100644 index e18efd6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IInbox} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; - -/** - * @notice This interface extends Arbitrum's IInbox interface to include - * the calculateRetryableSubmissionFee. This new function was added as part - * of Arbitrum's Nitro migration but was excluded from the IInbox interface. This setup - * works for us as the team has added it as a public function to the IInbox proxy - * contract's implementation - */ -interface IArbitrumDelayedInbox is IInbox { - function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol deleted file mode 100644 index d5a0138..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title A contract with helpers for cross-domain contract ownership -interface ICrossDomainOwnable { - event L1OwnershipTransferRequested(address indexed from, address indexed to); - - event L1OwnershipTransferred(address indexed from, address indexed to); - - function l1Owner() external returns (address); - - function transferL1Ownership(address recipient) external; - - function acceptL1Ownership() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol deleted file mode 100644 index 3df532b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title Forwards a delegatecall to a target, under some conditions -interface IDelegateForwarder { - /// @notice forward delegatecalls the `target` with `data` - /// @param target contract address to be delegatecalled - /// @param data to send to target contract - function forwardDelegate(address target, bytes memory data) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol deleted file mode 100644 index 6ae5a3a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IFlags { - function getFlag(address) external view returns (bool); - - function getFlags(address[] calldata) external view returns (bool[] memory); - - function raiseFlag(address) external; - - function raiseFlags(address[] calldata) external; - - function lowerFlag(address) external; - - function lowerFlags(address[] calldata) external; - - function setRaisingAccessController(address) external; - - function setLoweringAccessController(address) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol deleted file mode 100644 index 374e381..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title Forwards a call to a target, under some conditions -interface IForwarder { - /// @notice forward calls the `target` with `data` - /// @param target contract address to be called - /// @param data to send to target contract - function forward(address target, bytes memory data) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol deleted file mode 100644 index 879dc06..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface ISequencerUptimeFeed { - function updateStatus(bool status, uint64 timestamp) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol deleted file mode 100644 index 1d03788..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -// solhint-disable-next-line no-unused-import -import {IForwarder} from "../interfaces/IForwarder.sol"; - -/* ./dev dependencies - to be moved from ./dev after audit */ -import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; -import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; - -import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/** - * @title OptimismCrossDomainForwarder - L1 xDomain account representation - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can be considered to be owned by the `l1Owner` - */ -contract OptimismCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { - // OVM_L2CrossDomainMessenger is a precompile usually deployed to 0x4200000000000000000000000000000000000007 - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - iOVM_CrossDomainMessenger private immutable OVM_CROSS_DOMAIN_MESSENGER; - - /** - * @notice creates a new Optimism xDomain Forwarder contract - * @param crossDomainMessengerAddr the xDomain bridge messenger (Optimism bridge L2) contract address - * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - */ - constructor(iOVM_CrossDomainMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { - // solhint-disable-next-line gas-custom-errors - require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); - OVM_CROSS_DOMAIN_MESSENGER = crossDomainMessengerAddr; - } - - /** - * @notice versions: - * - * - OptimismCrossDomainForwarder 0.1.0: initial release - * - OptimismCrossDomainForwarder 1.0.0: Use OZ Address, CrossDomainOwnable - * - * @inheritdoc ITypeAndVersion - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "OptimismCrossDomainForwarder 1.0.0"; - } - - /** - * @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - * @inheritdoc IForwarder - */ - function forward(address target, bytes memory data) external virtual override onlyL1Owner { - Address.functionCall(target, data, "Forwarder call reverted"); - } - - /** - * @notice This is always the address of the OVM_L2CrossDomainMessenger contract - */ - function crossDomainMessenger() public view returns (address) { - return address(OVM_CROSS_DOMAIN_MESSENGER); - } - - /** - * @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. - */ - modifier onlyL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == crossDomainMessenger(), "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - iOVM_CrossDomainMessenger(crossDomainMessenger()).xDomainMessageSender() == l1Owner(), - "xDomain sender is not the L1 owner" - ); - _; - } - - /** - * @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. - */ - modifier onlyProposedL1Owner() override { - address messenger = crossDomainMessenger(); - // solhint-disable-next-line gas-custom-errors - require(msg.sender == messenger, "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - iOVM_CrossDomainMessenger(messenger).xDomainMessageSender() == s_l1PendingOwner, - "Must be proposed L1 owner" - ); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol deleted file mode 100644 index 6a41bd9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; -// solhint-disable-next-line no-unused-import -import {IForwarder} from "../interfaces/IForwarder.sol"; - -import {OptimismCrossDomainForwarder} from "./OptimismCrossDomainForwarder.sol"; - -import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/** - * @title OptimismCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Optimism - * @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. - * @dev Any other L2 contract which uses this contract's address as a privileged position, - * can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` - */ -contract OptimismCrossDomainGovernor is IDelegateForwarder, OptimismCrossDomainForwarder { - /** - * @notice creates a new Optimism xDomain Forwarder contract - * @param crossDomainMessengerAddr the xDomain bridge messenger (Optimism bridge L2) contract address - * @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - * @dev Empty constructor required due to inheriting from abstract contract CrossDomainForwarder - */ - constructor( - iOVM_CrossDomainMessenger crossDomainMessengerAddr, - address l1OwnerAddr - ) OptimismCrossDomainForwarder(crossDomainMessengerAddr, l1OwnerAddr) {} - - /** - * @notice versions: - * - * - OptimismCrossDomainForwarder 1.0.0: initial release - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "OptimismCrossDomainGovernor 1.0.0"; - } - - /** - * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc IForwarder - */ - function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionCall(target, data, "Governor call reverted"); - } - - /** - * @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - * @inheritdoc IDelegateForwarder - */ - function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); - } - - /** - * @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. - */ - modifier onlyLocalOrCrossDomainOwner() { - address messenger = crossDomainMessenger(); - // 1. The delegatecall MUST come from either the L1 owner (via cross-chain message) or the L2 owner - // solhint-disable-next-line gas-custom-errors - require(msg.sender == messenger || msg.sender == owner(), "Sender is not the L2 messenger or owner"); - // 2. The L2 Messenger's caller MUST be the L1 Owner - if (msg.sender == messenger) { - // solhint-disable-next-line gas-custom-errors - require( - iOVM_CrossDomainMessenger(messenger).xDomainMessageSender() == l1Owner(), - "xDomain sender is not the L1 owner" - ); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol deleted file mode 100644 index 0e6f9c5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; - -import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; - -/** - * @title OptimismSequencerUptimeFeed - L2 sequencer uptime status aggregator - * @notice L2 contract that receives status updates from a specific L1 address, - * records a new answer if the status changed - */ -contract OptimismSequencerUptimeFeed is BaseSequencerUptimeFeed { - string public constant override typeAndVersion = "OptimismSequencerUptimeFeed 1.1.0-dev"; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - IL2CrossDomainMessenger private immutable s_l2CrossDomainMessenger; - - /** - * @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract - * @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract - * @param initialStatus The initial status of the feed - */ - constructor( - address l1SenderAddress, - address l2CrossDomainMessengerAddr, - bool initialStatus - ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { - s_l2CrossDomainMessenger = IL2CrossDomainMessenger(l2CrossDomainMessengerAddr); - } - - function _validateSender(address l1Sender) internal view override { - if ( - msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender - ) { - revert InvalidSender(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol deleted file mode 100644 index cf5222f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; - -import {BaseValidator} from "../shared/BaseValidator.sol"; - -import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; - -/// @title OptimismValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 -contract OptimismValidator is BaseValidator { - string public constant override typeAndVersion = "OptimismValidator 1.1.0-dev"; - - /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - /// @param l2UptimeFeedAddr the address of the OptimismSequencerUptimeFeed contract address - /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 - constructor( - address l1CrossDomainMessengerAddress, - address l2UptimeFeedAddr, - uint32 gasLimit - ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {} - - /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. - /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. - /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. - function validate( - uint256 /* previousRoundId */, - int256 /* previousAnswer */, - uint256 /* currentRoundId */, - int256 currentAnswer - ) external override checkAccess returns (bool) { - // Encode the OptimismSequencerUptimeFeed call - bytes4 selector = ISequencerUptimeFeed.updateStatus.selector; - bool status = currentAnswer == ANSWER_SEQ_OFFLINE; - uint64 timestamp = uint64(block.timestamp); - // Encode `status` and `timestamp` - bytes memory message = abi.encodeWithSelector(selector, status, timestamp); - // Make the xDomain call - IL1CrossDomainMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage( - L2_UPTIME_FEED_ADDR, // target - message, - s_gasLimit - ); - // return success - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol deleted file mode 100644 index c70bc79..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IForwarder} from "../interfaces/IForwarder.sol"; - -import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; -import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; - -import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/// @title ScrollCrossDomainForwarder - L1 xDomain account representation -/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. -/// @dev Any other L2 contract which uses this contract's address as a privileged position, -/// can be considered to be owned by the `l1Owner` -contract ScrollCrossDomainForwarder is ITypeAndVersion, CrossDomainForwarder { - string public constant override typeAndVersion = "ScrollCrossDomainForwarder 1.0.0"; - - address internal immutable i_scrollCrossDomainMessenger; - - /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address - /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { - // solhint-disable-next-line gas-custom-errors - require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); - i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); - } - - /// @dev forwarded only if L2 Messenger calls with `xDomainMessageSender` being the L1 owner address - /// @inheritdoc IForwarder - function forward(address target, bytes memory data) external override onlyL1Owner { - Address.functionCall(target, data, "Forwarder call reverted"); - } - - /// @notice This is always the address of the Scroll Cross Domain Messenger contract - function crossDomainMessenger() external view returns (address) { - return address(i_scrollCrossDomainMessenger); - } - - /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. - modifier onlyL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), - "xDomain sender is not the L1 owner" - ); - _; - } - - /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. - modifier onlyProposedL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, - "Must be proposed L1 owner" - ); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol deleted file mode 100644 index dae621e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; -// solhint-disable-next-line no-unused-import -import {IForwarder} from "../interfaces/IForwarder.sol"; - -import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; -import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; - -import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; - -/// @title ScrollCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Scroll -/// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. -/// @dev Any other L2 contract which uses this contract's address as a privileged position, -/// can be considered to be simultaneously owned by the `l1Owner` and L2 `owner` -contract ScrollCrossDomainGovernor is IDelegateForwarder, ITypeAndVersion, CrossDomainForwarder { - string public constant override typeAndVersion = "ScrollCrossDomainGovernor 1.0.0"; - - address internal immutable i_scrollCrossDomainMessenger; - - /// @param crossDomainMessengerAddr the xDomain bridge messenger (Scroll bridge L2) contract address - /// @param l1OwnerAddr the L1 owner address that will be allowed to call the forward fn - constructor(IScrollMessenger crossDomainMessengerAddr, address l1OwnerAddr) CrossDomainOwnable(l1OwnerAddr) { - // solhint-disable-next-line gas-custom-errors - require(address(crossDomainMessengerAddr) != address(0), "Invalid xDomain Messenger address"); - i_scrollCrossDomainMessenger = address(crossDomainMessengerAddr); - } - - /// @inheritdoc IForwarder - /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - function forward(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionCall(target, data, "Governor call reverted"); - } - - /// @inheritdoc IDelegateForwarder - /// @dev forwarded only if L2 Messenger calls with `msg.sender` being the L1 owner address, or called by the L2 owner - function forwardDelegate(address target, bytes memory data) external override onlyLocalOrCrossDomainOwner { - Address.functionDelegateCall(target, data, "Governor delegatecall reverted"); - } - - /// @notice The address of the Scroll Cross Domain Messenger contract - function crossDomainMessenger() external view returns (address) { - return address(i_scrollCrossDomainMessenger); - } - - /// @notice The call MUST come from the L1 owner (via cross-chain message.) Reverts otherwise. - modifier onlyL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), - "xDomain sender is not the L1 owner" - ); - _; - } - - /// @notice The call MUST come from either the L1 owner (via cross-chain message) or the L2 owner. Reverts otherwise. - modifier onlyLocalOrCrossDomainOwner() { - // 1. The delegatecall MUST come from either the L1 owner (via cross-chain message) or the L2 owner - // solhint-disable-next-line gas-custom-errors - require( - msg.sender == i_scrollCrossDomainMessenger || msg.sender == owner(), - "Sender is not the L2 messenger or owner" - ); - // 2. The L2 Messenger's caller MUST be the L1 Owner - if (msg.sender == i_scrollCrossDomainMessenger) { - // solhint-disable-next-line gas-custom-errors - require( - IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == l1Owner(), - "xDomain sender is not the L1 owner" - ); - } - _; - } - - /// @notice The call MUST come from the proposed L1 owner (via cross-chain message.) Reverts otherwise. - modifier onlyProposedL1Owner() override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == i_scrollCrossDomainMessenger, "Sender is not the L2 messenger"); - // solhint-disable-next-line gas-custom-errors - require( - IScrollMessenger(i_scrollCrossDomainMessenger).xDomainMessageSender() == s_l1PendingOwner, - "Must be proposed L1 owner" - ); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol deleted file mode 100644 index 40f2941..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; - -import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; - -/// @title ScrollSequencerUptimeFeed - L2 sequencer uptime status aggregator -/// @notice L2 contract that receives status updates, and records a new answer if the status changed -contract ScrollSequencerUptimeFeed is BaseSequencerUptimeFeed { - error ZeroAddress(); - - string public constant override typeAndVersion = "ScrollSequencerUptimeFeed 1.1.0-dev"; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - IL2ScrollMessenger private immutable s_l2CrossDomainMessenger; - - /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract - /// @param l2CrossDomainMessengerAddr Address of the L2CrossDomainMessenger contract - /// @param initialStatus The initial status of the feed - constructor( - address l1SenderAddress, - address l2CrossDomainMessengerAddr, - bool initialStatus - ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { - if (l2CrossDomainMessengerAddr == address(0)) { - revert ZeroAddress(); - } - - s_l2CrossDomainMessenger = IL2ScrollMessenger(l2CrossDomainMessengerAddr); - } - - function _validateSender(address l1Sender) internal view override { - if ( - msg.sender != address(s_l2CrossDomainMessenger) || s_l2CrossDomainMessenger.xDomainMessageSender() != l1Sender - ) { - revert InvalidSender(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol deleted file mode 100644 index b009c80..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; - -import {BaseValidator} from "../shared/BaseValidator.sol"; - -import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; -import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; - -/// @title ScrollValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 -contract ScrollValidator is BaseValidator { - string public constant override typeAndVersion = "ScrollValidator 1.1.0-dev"; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L1_MSG_QUEUE_ADDR; - - constructor( - address l1CrossDomainMessengerAddress, - address l2UptimeFeedAddr, - address l1MessageQueueAddr, - uint32 gasLimit - ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { - // solhint-disable-next-line gas-custom-errors - require(l1MessageQueueAddr != address(0), "Invalid L1 message queue address"); - L1_MSG_QUEUE_ADDR = l1MessageQueueAddr; - } - - /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. - /// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled. - /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. - function validate( - uint256 /* previousRoundId */, - int256 /* previousAnswer */, - uint256 /* currentRoundId */, - int256 currentAnswer - ) external override checkAccess returns (bool) { - // Make the xDomain call - IL1ScrollMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage{ - value: IL1MessageQueue(L1_MSG_QUEUE_ADDR).estimateCrossDomainMessageFee(s_gasLimit) - }( - L2_UPTIME_FEED_ADDR, - 0, - abi.encodeWithSelector( - ISequencerUptimeFeed.updateStatus.selector, - currentAnswer == ANSWER_SEQ_OFFLINE, - uint64(block.timestamp) - ), - s_gasLimit - ); - - // return success - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol deleted file mode 100644 index 15c2050..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol +++ /dev/null @@ -1,231 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; - -import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; - -/// @title L2 sequencer uptime status aggregator -/// @notice L2 contract that receives status updates from a specific L1 address, -/// records a new answer if the status changed -abstract contract BaseSequencerUptimeFeed is - ITypeAndVersion, - AggregatorV2V3Interface, - ISequencerUptimeFeed, - SimpleReadAccessController -{ - /// @dev Round info for uptime history - struct Round { - uint64 startedAt; // ─╮ The timestamp at which the round started - uint64 updatedAt; // │ The timestamp at which the round was updated - bool status; // ──────╯ The sequencer status for the round - } - - struct FeedState { - uint80 latestRoundId; // ─╮ The ID of the latest round - uint64 startedAt; // │ The date at which the latest round started - uint64 updatedAt; // │ The date at which the latest round was updated - bool latestStatus; // ────╯ The status of the latest round - } - - /// @notice Sender is not the L2 messenger - error InvalidSender(); - /// @notice Replacement for AggregatorV3Interface "No data present" - error NoDataPresent(); - - event L1SenderTransferred(address indexed from, address indexed to); - /// @dev Emitted when an `updateStatus` call is ignored due to unchanged status or stale timestamp - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - /// @dev Emitted when a updateStatus is called without the status changing - event RoundUpdated(int256 status, uint64 updatedAt); - - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint8 public constant override decimals = 0; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override description = "L2 Sequencer Uptime Status Feed"; - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - uint256 public constant override version = 1; - - /// @dev L1 address - address private s_l1Sender; - /// @dev s_latestRoundId == 0 means this contract is uninitialized. - FeedState private s_feedState = FeedState({latestRoundId: 0, latestStatus: false, startedAt: 0, updatedAt: 0}); - mapping(uint80 roundId => Round round) private s_rounds; - - /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract - /// @param initialStatus The initial status of the feed - constructor(address l1SenderAddress, bool initialStatus) { - // We neet to allow l1SenderAddress to be zero because this contract is deployed first - // After deploying the validator contract, this contract will be updated with the correct L1 sender address - _setL1Sender(l1SenderAddress); - - // Initialise roundId == 1 as the first round - _recordRound(1, initialStatus, uint64(block.timestamp)); - } - - /// @notice Check if a roundId is valid in this current contract state - /// @dev Mainly used for AggregatorV2V3Interface functions - /// @param roundId Round ID to check - function _isValidRound(uint256 roundId) private view returns (bool) { - return roundId > 0 && roundId <= type(uint80).max && s_feedState.latestRoundId >= roundId; - } - - /// @return L1 sender address - function l1Sender() public view virtual returns (address) { - return s_l1Sender; - } - - /// @notice Set the allowed L1 sender for this contract to a new L1 sender - /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract - function transferL1Sender(address to) external virtual onlyOwner { - _setL1Sender(to); - } - - /// @notice internal method that stores the L1 sender - function _setL1Sender(address newSender) internal { - address oldSender = s_l1Sender; - if (oldSender != newSender) { - s_l1Sender = newSender; - emit L1SenderTransferred(oldSender, newSender); - } - } - - /// @dev Returns an AggregatorV2V3Interface compatible answer from status flag - /// @param status The status flag to convert to an aggregator-compatible answer - function _getStatusAnswer(bool status) internal pure returns (int256) { - return status ? int256(1) : int256(0); - } - - /// @notice Helper function to record a round and set the latest feed state. - /// @param roundId The round ID to record - /// @param status Sequencer status - /// @param timestamp The L1 block timestamp of status update - function _recordRound(uint80 roundId, bool status, uint64 timestamp) internal { - s_rounds[roundId] = Round({status: status, startedAt: timestamp, updatedAt: uint64(block.timestamp)}); - s_feedState = FeedState({ - latestRoundId: roundId, - latestStatus: status, - startedAt: timestamp, - updatedAt: uint64(block.timestamp) - }); - - emit NewRound(roundId, msg.sender, timestamp); - emit AnswerUpdated(_getStatusAnswer(status), roundId, timestamp); - } - - /// @notice Helper function to update when a round was last updated - /// @param roundId The round ID to update - /// @param status Sequencer status - function _updateRound(uint80 roundId, bool status) internal { - s_rounds[roundId].updatedAt = uint64(block.timestamp); - s_feedState.updatedAt = uint64(block.timestamp); - emit RoundUpdated(_getStatusAnswer(status), uint64(block.timestamp)); - } - - function _getFeedState() internal view returns (FeedState memory) { - return s_feedState; - } - - /// @inheritdoc AggregatorInterface - function latestAnswer() external view override checkAccess returns (int256) { - return _getStatusAnswer(s_feedState.latestStatus); - } - - /// @inheritdoc AggregatorInterface - function latestTimestamp() external view override checkAccess returns (uint256) { - return s_feedState.startedAt; - } - - /// @inheritdoc AggregatorInterface - function latestRound() external view override checkAccess returns (uint256) { - return s_feedState.latestRoundId; - } - - /// @inheritdoc AggregatorInterface - function getAnswer(uint256 roundId) external view override checkAccess returns (int256) { - if (!_isValidRound(roundId)) { - revert NoDataPresent(); - } - - return _getStatusAnswer(s_rounds[uint80(roundId)].status); - } - - /// @inheritdoc AggregatorInterface - function getTimestamp(uint256 roundId) external view override checkAccess returns (uint256) { - if (!_isValidRound(roundId)) { - revert NoDataPresent(); - } - - return s_rounds[uint80(roundId)].startedAt; - } - - /** - * @notice Record a new status and timestamp if it has changed since the last round. - * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - * - * @param status Sequencer status - * @param timestamp Block timestamp of status update - */ - function updateStatus(bool status, uint64 timestamp) external override { - _validateSender(s_l1Sender); - - FeedState memory feedState = _getFeedState(); - // Ignore if latest recorded timestamp is newer - if (feedState.startedAt > timestamp) { - emit UpdateIgnored(feedState.latestStatus, feedState.startedAt, status, timestamp); - return; - } - - if (feedState.latestStatus == status) { - _updateRound(feedState.latestRoundId, status); - } else { - feedState.latestRoundId += 1; - _recordRound(feedState.latestRoundId, status, timestamp); - } - } - - function _validateSender(address l1Sender) internal virtual; - - /// @inheritdoc AggregatorV3Interface - function getRoundData( - uint80 _roundId - ) - public - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - if (!_isValidRound(_roundId)) { - revert NoDataPresent(); - } - - Round storage round = s_rounds[_roundId]; - - return (_roundId, _getStatusAnswer(round.status), uint256(round.startedAt), uint256(round.updatedAt), _roundId); - } - - /// @inheritdoc AggregatorV3Interface - function latestRoundData() - external - view - override - checkAccess - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - FeedState storage feedState = s_feedState; - - return ( - feedState.latestRoundId, - _getStatusAnswer(feedState.latestStatus), - feedState.startedAt, - feedState.updatedAt, - feedState.latestRoundId - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol deleted file mode 100644 index 33df388..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; - -abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValidatorInterface, ITypeAndVersion { - /// @notice emitted when gas cost to spend on L2 is updated - /// @param gasLimit updated gas cost - event GasLimitUpdated(uint32 gasLimit); - - error L1CrossDomainMessengerAddressZero(); - error L2UptimeFeedAddrZero(); - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L1_CROSS_DOMAIN_MESSENGER_ADDRESS; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable L2_UPTIME_FEED_ADDR; - - int256 internal constant ANSWER_SEQ_OFFLINE = 1; - - uint32 internal s_gasLimit; - - /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address - /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 - constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { - if (l1CrossDomainMessengerAddress == address(0)) { - revert L1CrossDomainMessengerAddressZero(); - } - if (l2UptimeFeedAddr == address(0)) { - revert L2UptimeFeedAddrZero(); - } - - L1_CROSS_DOMAIN_MESSENGER_ADDRESS = l1CrossDomainMessengerAddress; - L2_UPTIME_FEED_ADDR = l2UptimeFeedAddr; - s_gasLimit = gasLimit; - } - - /// @notice fetches the gas cost of sending a cross chain message - function getGasLimit() external view returns (uint32) { - return s_gasLimit; - } - - /// @notice sets the new gas cost to spend when sending cross chain message - /// @param gasLimit the updated gas cost - function setGasLimit(uint32 gasLimit) external onlyOwner { - s_gasLimit = gasLimit; - emit GasLimitUpdated(gasLimit); - } - - /// @notice makes this contract payable - /// @dev receives funds: - /// - to use them (if configured) to pay for L2 execution on L1 - /// - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2) - receive() external payable {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol deleted file mode 100644 index 0074a02..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; - -import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; - -/// @title ZKSyncSequencerUptimeFeed - L2 sequencer uptime status aggregator -/// @notice L2 contract that receives status updates from a specific L1 address, -/// records a new answer if the status changed -contract ZKSyncSequencerUptimeFeed is BaseSequencerUptimeFeed { - string public constant override typeAndVersion = "ZKSyncSequencerUptimeFeed 1.1.0-dev"; - - /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract - /// @param initialStatus The initial status of the feed - constructor(address l1SenderAddress, bool initialStatus) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) {} - - function _validateSender(address l1Sender) internal view override { - address aliasedL1Sender = AddressAliasHelper.applyL1ToL2Alias(l1Sender); - - if (msg.sender != aliasedL1Sender) { - revert InvalidSender(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol deleted file mode 100644 index 10f68ce..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; - -import {BaseValidator} from "../shared/BaseValidator.sol"; - -import {IBridgehub, L2TransactionRequestDirect} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; - -/// @title ZKSyncValidator - makes cross chain call to update the Sequencer Uptime Feed on L2 -contract ZKSyncValidator is BaseValidator { - /// Contract state variables - string public constant override typeAndVersion = "ZKSyncValidator 1.1.0-dev"; - uint32 private constant ZKSYNC_TEST_NET_CHAIN_ID = 300; - uint32 private constant ZKSYNC_MAIN_NET_CHAIN_ID = 324; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - uint32 private immutable CHAIN_ID; - /// @dev how much l2 gas each byte of pubdata costs - uint32 private s_l2GasPerPubdataByteLimit; - - /// @notice emitted when the gas per pubdata byte limit is updated - /// @param l2GasPerPubdataByteLimit updated gas per pubdata byte limit - event GasPerPubdataByteLimitUpdated(uint32 l2GasPerPubdataByteLimit); - - /// @notice ChainID is not a valid value - error InvalidChainID(); - - /// @param l1CrossDomainMessengerAddress address the Bridgehub contract address - /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeedInterface contract address - /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 - constructor( - address l1CrossDomainMessengerAddress, - address l2UptimeFeedAddr, - uint32 gasLimit, - uint32 chainId, - uint32 l2GasPerPubdataByteLimit - ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) { - if (chainId != ZKSYNC_TEST_NET_CHAIN_ID && chainId != ZKSYNC_MAIN_NET_CHAIN_ID) { - revert InvalidChainID(); - } - - s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; - CHAIN_ID = chainId; - } - - /// @notice sets the l2GasPerPubdataByteLimit for the L2 transaction request - /// @param l2GasPerPubdataByteLimit the updated l2GasPerPubdataByteLimit - function setL2GasPerPubdataByteLimit(uint32 l2GasPerPubdataByteLimit) external onlyOwner { - if (s_l2GasPerPubdataByteLimit != l2GasPerPubdataByteLimit) { - s_l2GasPerPubdataByteLimit = l2GasPerPubdataByteLimit; - emit GasPerPubdataByteLimitUpdated(l2GasPerPubdataByteLimit); - } - } - - /// @notice fetches the l2GasPerPubdataByteLimit for the L2 transaction request - function getL2GasPerPubdataByteLimit() external view returns (uint32) { - return s_l2GasPerPubdataByteLimit; - } - - /// @notice fetches the chain id - function getChainId() external view returns (uint32) { - return CHAIN_ID; - } - - /// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2. - /// @dev A message is sent using the Bridgehub. This method is accessed controlled. - /// @param currentAnswer new aggregator answer - value of 1 considers the sequencer offline. - function validate( - uint256 /* previousRoundId */, - int256 /* previousAnswer */, - uint256 /* currentRoundId */, - int256 currentAnswer - ) external override checkAccess returns (bool) { - IBridgehub bridgeHub = IBridgehub(L1_CROSS_DOMAIN_MESSENGER_ADDRESS); - - uint256 transactionBaseCostEstimate = bridgeHub.l2TransactionBaseCost( - CHAIN_ID, - tx.gasprice, - s_gasLimit, - s_l2GasPerPubdataByteLimit - ); - - L2TransactionRequestDirect memory l2TransactionRequestDirect = L2TransactionRequestDirect({ - chainId: CHAIN_ID, - mintValue: transactionBaseCostEstimate, - l2Contract: L2_UPTIME_FEED_ADDR, - l2Value: 0, - l2Calldata: abi.encodeWithSelector( - ISequencerUptimeFeed.updateStatus.selector, - currentAnswer == ANSWER_SEQ_OFFLINE, - uint64(block.timestamp) - ), - l2GasLimit: s_gasLimit, - l2GasPerPubdataByteLimit: s_l2GasPerPubdataByteLimit, - factoryDeps: new bytes[](0), - refundRecipient: msg.sender - }); - - // Make the xDomain call - bridgeHub.requestL2TransactionDirect{value: transactionBaseCostEstimate}(l2TransactionRequestDirect); - - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol deleted file mode 100644 index 5201932..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/MockAggregatorV2V3.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; - -contract MockAggregatorV2V3 is AggregatorV2V3Interface { - function latestAnswer() external pure returns (int256) { - return 0; - } - - function latestTimestamp() external pure returns (uint256) { - return 0; - } - - function latestRound() external pure returns (uint256) { - return 0; - } - - function getAnswer(uint256) external pure returns (int256) { - return 0; - } - - function getTimestamp(uint256 roundId) external pure returns (uint256) { - return roundId; - } - - function decimals() external pure returns (uint8) { - return 0; - } - - function description() external pure returns (string memory) { - return ""; - } - - function version() external pure returns (uint256) { - return 0; - } - - function getRoundData( - uint80 - ) - external - pure - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (0, 0, 0, 0, 0); - } - - function latestRoundData() - external - pure - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (73786976294838220258, 96800000000, 163826896, 1638268960, 73786976294838220258); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol deleted file mode 100644 index 0c4193a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/optimism/MockOVMCrossDomainMessenger.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {iOVM_CrossDomainMessenger} from "../../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; - -import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; - -contract MockOVMCrossDomainMessenger is iOVM_CrossDomainMessenger { - address internal s_mockMessageSender; - - constructor(address sender) { - s_mockMessageSender = sender; - } - - function xDomainMessageSender() external view override returns (address) { - return s_mockMessageSender; - } - - function _setMockMessageSender(address sender) external { - s_mockMessageSender = sender; - } - - /** - * Sends a cross domain message to the target messenger. - * @param _target Target contract address. - * @param _message Message to send to the target. - */ - function sendMessage(address _target, bytes calldata _message, uint32) external override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol deleted file mode 100644 index 3724491..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollCrossDomainMessenger.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; - -import {Address} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; - -contract MockScrollCrossDomainMessenger is IScrollMessenger { - address internal s_mockMessageSender; - - constructor(address sender) { - s_mockMessageSender = sender; - } - - function xDomainMessageSender() external view override returns (address) { - return s_mockMessageSender; - } - - function _setMockMessageSender(address sender) external { - s_mockMessageSender = sender; - } - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param _target The address of account who receive the message. - /// @param _message The content of the message. - function sendMessage(address _target, uint256, bytes calldata _message, uint256) external payable override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param _target The address of account who receive the message. - /// @param _message The content of the message. - function sendMessage(address _target, uint256, bytes calldata _message, uint256, address) external payable override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol deleted file mode 100644 index 42147fb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1CrossDomainMessenger.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; - -contract MockScrollL1CrossDomainMessenger is IL1ScrollMessenger { - uint256 private s_nonce; - - function xDomainMessageSender() public pure returns (address) { - return address(0); - } - - function sendMessage( - address _target, - uint256 _value, - bytes calldata _message, - uint256 _gasLimit - ) external payable override { - emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); - s_nonce++; - } - - function sendMessage( - address _target, - uint256 _value, - bytes calldata _message, - uint256 _gasLimit, - address - ) external payable override { - emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); - s_nonce++; - } - - function relayMessageWithProof( - address from, - address to, - uint256 value, - uint256 nonce, - bytes memory message, - L2MessageProof memory proof - ) external override {} - - function replayMessage( - address from, - address to, - uint256 value, - uint256 messageNonce, - bytes memory message, - uint32 newGasLimit, - address refundAddress - ) external payable override {} - - function dropMessage( - address from, - address to, - uint256 value, - uint256 messageNonce, - bytes memory message - ) external override {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol deleted file mode 100644 index e43f1bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; - -contract MockScrollL1MessageQueue is IL1MessageQueue { - /// @notice The start index of all pending inclusion messages. - function pendingQueueIndex() external pure returns (uint256) { - return 0; - } - - /// @notice Return the index of next appended message. - function nextCrossDomainMessageIndex() external pure returns (uint256) { - return 0; - } - - /// @notice Return the message of in `queueIndex`. - function getCrossDomainMessage(uint256 /* queueIndex */) external pure returns (bytes32) { - return ""; - } - - /// @notice Return the amount of ETH should pay for cross domain message. - function estimateCrossDomainMessageFee(uint256 /* gasLimit */) external pure returns (uint256) { - return 0; - } - - /// @notice Return the amount of intrinsic gas fee should pay for cross domain message. - function calculateIntrinsicGasFee(bytes memory /* _calldata */) external pure returns (uint256) { - return 0; - } - - /// @notice Return the hash of a L1 message. - function computeTransactionHash( - address /* sender */, - uint256 /* queueIndex */, - uint256 /* value */, - address /* target */, - uint256 /* gasLimit */, - bytes calldata /* data */ - ) external pure returns (bytes32) { - return 0; - } - - /// @notice Append a L1 to L2 message into this contract. - /// @param target The address of target contract to call in L2. - /// @param gasLimit The maximum gas should be used for relay this message in L2. - /// @param data The calldata passed to target contract. - function appendCrossDomainMessage(address target, uint256 gasLimit, bytes calldata data) external {} - - /// @notice Append an enforced transaction to this contract. - /// @dev The address of sender should be an EOA. - /// @param sender The address of sender who will initiate this transaction in L2. - /// @param target The address of target contract to call in L2. - /// @param value The value passed - /// @param gasLimit The maximum gas should be used for this transaction in L2. - /// @param data The calldata passed to target contract. - function appendEnforcedTransaction( - address sender, - address target, - uint256 value, - uint256 gasLimit, - bytes calldata data - ) external {} - - /// @notice Pop finalized messages from queue. - /// - /// @dev We can pop at most 256 messages each time. And if the message is not skipped, - /// the corresponding entry will be cleared. - /// - /// @param startIndex The start index to pop. - /// @param count The number of messages to pop. - /// @param skippedBitmap A bitmap indicates whether a message is skipped. - function popCrossDomainMessage(uint256 startIndex, uint256 count, uint256 skippedBitmap) external {} - - /// @notice Drop a skipped message from the queue. - function dropCrossDomainMessage(uint256 index) external {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol deleted file mode 100644 index af0e0b5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/scroll/MockScrollL2CrossDomainMessenger.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; - -contract MockScrollL2CrossDomainMessenger is IL2ScrollMessenger { - uint256 private s_nonce; - address private s_sender; - - function xDomainMessageSender() public view returns (address) { - return s_sender; - } - - function sendMessage( - address _target, - uint256 _value, - bytes calldata _message, - uint256 _gasLimit - ) external payable override { - emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); - s_nonce++; - } - - function sendMessage( - address _target, - uint256 _value, - bytes calldata _message, - uint256 _gasLimit, - address - ) external payable override { - emit SentMessage(msg.sender, _target, _value, s_nonce, _gasLimit, _message); - s_nonce++; - } - - function relayMessage( - address from, - address to, - uint256 value, - uint256 nonce, - bytes calldata message - ) external override {} - - /// Needed for backwards compatibility in Hardhat tests - function setSender(address newSender) external { - s_sender = newSender; - } - - /// Needed for backwards compatibility in Hardhat tests - receive() external payable {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol deleted file mode 100644 index b46b9d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/mocks/zksync/MockZKSyncL1Bridge.sol +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {IBridgehub, L2TransactionRequestDirect, L2TransactionRequestTwoBridgesOuter} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; -import {IL1SharedBridge} from "@zksync/contracts/l1-contracts/contracts/bridge/interfaces/IL1SharedBridge.sol"; -import {L2Message, L2Log, TxStatus} from "@zksync/contracts/l1-contracts/contracts/common/Messaging.sol"; - -contract MockBridgehub is IBridgehub { - address public pendingAdmin; - address public admin; - address public sharedBridgeAddr; - - mapping(address stateTransitionManager => bool stateTransitionManagerIsRegistered) - public registeredStateTransitionManagers; - mapping(uint256 chainId => address stateTransitionManagerAddress) public stateTransitionManagers; - mapping(address baseToken => bool tokenIsRegistered) public registeredTokens; - mapping(uint256 chainId => address baseToken) public baseTokens; - mapping(uint256 chainId => address hyperChain) public hyperchains; - - /// Generic error for unauthorized actions - error NotAuthorized(string msg); - - /// Fake event that will get emitted when `requestL2TransactionDirect` is called - event SentMessage(address indexed sender, bytes message); - - /// Admin functions - function setPendingAdmin(address _newPendingAdmin) external override { - emit NewPendingAdmin(pendingAdmin, _newPendingAdmin); - pendingAdmin = _newPendingAdmin; - } - - function acceptAdmin() external override { - if (msg.sender != pendingAdmin) { - revert NotAuthorized("Only pending admin can accept"); - } - - emit NewAdmin(admin, pendingAdmin); - admin = pendingAdmin; - pendingAdmin = address(0); - } - - /// Getters - function stateTransitionManagerIsRegistered(address _stateTransitionManager) external view override returns (bool) { - return registeredStateTransitionManagers[_stateTransitionManager]; - } - - function stateTransitionManager(uint256 _chainId) external view override returns (address) { - return stateTransitionManagers[_chainId]; - } - - function tokenIsRegistered(address _baseToken) external view override returns (bool) { - return registeredTokens[_baseToken]; - } - - function baseToken(uint256 _chainId) external view override returns (address) { - return baseTokens[_chainId]; - } - - function sharedBridge() external view override returns (IL1SharedBridge) { - return IL1SharedBridge(sharedBridgeAddr); - } - - function getHyperchain(uint256 _chainId) external view override returns (address) { - return hyperchains[_chainId]; - } - - /// Mailbox forwarder - function proveL2MessageInclusion( - uint256, - uint256, - uint256, - L2Message calldata, - bytes32[] calldata - ) external pure override returns (bool) { - return true; - } - - function proveL2LogInclusion( - uint256, - uint256, - uint256, - L2Log memory, - bytes32[] calldata - ) external pure override returns (bool) { - return true; - } - - function proveL1ToL2TransactionStatus( - uint256, - bytes32, - uint256, - uint256, - uint16, - bytes32[] calldata, - TxStatus - ) external pure override returns (bool) { - return true; - } - - function requestL2TransactionDirect( - L2TransactionRequestDirect calldata txRequest - ) external payable override returns (bytes32) { - emit SentMessage(msg.sender, txRequest.l2Calldata); - return keccak256(abi.encodePacked("L2TransactionDirect")); - } - - function requestL2TransactionTwoBridges( - L2TransactionRequestTwoBridgesOuter calldata - ) external payable override returns (bytes32) { - return keccak256(abi.encodePacked("L2TransactionTwoBridges")); - } - - function l2TransactionBaseCost(uint256, uint256, uint256, uint256) external pure override returns (uint256) { - return 0; - } - - /// Registry - function createNewChain( - uint256 _chainId, - address _stateTransitionManager, - address _baseToken, - uint256, - address, - bytes calldata - ) external override returns (uint256 chainId) { - hyperchains[_chainId] = _stateTransitionManager; - baseTokens[_chainId] = _baseToken; - emit NewChain(_chainId, _stateTransitionManager, address(this)); - return _chainId; - } - - function addStateTransitionManager(address _stateTransitionManager) external override { - registeredStateTransitionManagers[_stateTransitionManager] = true; - } - - function removeStateTransitionManager(address _stateTransitionManager) external override { - registeredStateTransitionManagers[_stateTransitionManager] = false; - } - - function addToken(address _token) external override { - registeredTokens[_token] = true; - } - - function setSharedBridge(address _sharedBridgeAddr) external override { - sharedBridgeAddr = _sharedBridgeAddr; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol deleted file mode 100644 index 93640f4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/L2EPTest.t.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {Greeter} from "../../../tests/Greeter.sol"; - -import {MultiSend} from "../../../vendor/MultiSend.sol"; -import {Test} from "forge-std/Test.sol"; - -contract L2EPTest is Test { - /// Helper variable(s) - address internal s_strangerAddr = vm.addr(0x1); - address internal s_l1OwnerAddr = vm.addr(0x2); - address internal s_eoaValidator = vm.addr(0x3); - address internal s_deployerAddr = vm.addr(0x4); - - /// @param selector - the function selector - /// @param greeterAddr - the address of the Greeter contract - /// @param message - the new greeting message, which will be passed as an argument to Greeter#setGreeting - /// @return a 2-layer encoding such that decoding the first layer provides the CrossDomainForwarder#forward - /// function selector and the corresponding arguments to the forward function, and decoding the - /// second layer provides the Greeter#setGreeting function selector and the corresponding - /// arguments to the set greeting function (which in this case is the input message) - function encodeCrossDomainSetGreetingMsg( - bytes4 selector, - address greeterAddr, - string memory message - ) public pure returns (bytes memory) { - return abi.encodeWithSelector(selector, greeterAddr, abi.encodeWithSelector(Greeter.setGreeting.selector, message)); - } - - /// @param selector - the function selector - /// @param multiSendAddr - the address of the MultiSend contract - /// @param encodedTxs - an encoded list of transactions (e.g. abi.encodePacked(encodeMultiSendTx("some data"), ...)) - /// @return a 2-layer encoding such that decoding the first layer provides the CrossDomainGoverner#forwardDelegate - /// function selector and the corresponding arguments to the forwardDelegate function, and decoding the - /// second layer provides the MultiSend#multiSend function selector and the corresponding - /// arguments to the multiSend function (which in this case is the input encodedTxs) - function encodeCrossDomainMultiSendMsg( - bytes4 selector, - address multiSendAddr, - bytes memory encodedTxs - ) public pure returns (bytes memory) { - return - abi.encodeWithSelector(selector, multiSendAddr, abi.encodeWithSelector(MultiSend.multiSend.selector, encodedTxs)); - } - - /// @param greeterAddr - the address of the greeter contract - /// @param data - the transaction data string - /// @return an encoded transaction structured as specified in the MultiSend#multiSend comments - function encodeMultiSendTx(address greeterAddr, bytes memory data) public pure returns (bytes memory) { - bytes memory txData = abi.encodeWithSelector(Greeter.setGreeting.selector, data); - return - abi.encodePacked( - uint8(0), // operation - greeterAddr, // to - uint256(0), // value - uint256(txData.length), // data length - txData // data as bytes - ); - } - - /// @param l1Address - Address on L1 - /// @return an Arbitrum L2 address - function toArbitrumL2AliasAddress(address l1Address) public pure returns (address) { - return address(uint160(l1Address) + uint160(0x1111000000000000000000000000000000001111)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol deleted file mode 100644 index cff9b95..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ArbitrumCrossDomainForwarder} from "../../../dev/arbitrum/ArbitrumCrossDomainForwarder.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ArbitrumCrossDomainForwarderTest is L2EPTest { - /// Helper variable(s) - address internal s_crossDomainMessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); - address internal s_newOwnerCrossDomainMessengerAddr = toArbitrumL2AliasAddress(s_strangerAddr); - - /// Contracts - ArbitrumCrossDomainForwarder internal s_arbitrumCrossDomainForwarder; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_arbitrumCrossDomainForwarder = new ArbitrumCrossDomainForwarder(s_l1OwnerAddr); - s_greeter = new Greeter(address(s_arbitrumCrossDomainForwarder)); - vm.stopPrank(); - } -} - -contract ArbitrumCrossDomainForwarder_Constructor is ArbitrumCrossDomainForwarderTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_arbitrumCrossDomainForwarder.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_arbitrumCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_arbitrumCrossDomainForwarder.crossDomainMessenger(), s_crossDomainMessengerAddr); - - // it should set the typeAndVersion correctly - assertEq(s_arbitrumCrossDomainForwarder.typeAndVersion(), "ArbitrumCrossDomainForwarder 1.0.0"); - } -} - -contract ArbitrumCrossDomainForwarder_Forward is ArbitrumCrossDomainForwarderTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_arbitrumCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_arbitrumCrossDomainForwarder.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_arbitrumCrossDomainForwarder.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, "") - ); - } -} - -contract ArbitrumCrossDomainForwarder_TransferL1Ownership is ArbitrumCrossDomainForwarderTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_arbitrumCrossDomainForwarder.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_arbitrumCrossDomainForwarder.l1Owner(), s_strangerAddr); - - // Sends the message - s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_arbitrumCrossDomainForwarder.l1Owner(), address(0)); - - // Sends the message - s_arbitrumCrossDomainForwarder.transferL1Ownership(address(0)); - } -} - -contract ArbitrumCrossDomainForwarder_AcceptL1Ownership is ArbitrumCrossDomainForwarderTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_arbitrumCrossDomainForwarder.acceptL1Ownership(); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Request ownership transfer - vm.startPrank(s_crossDomainMessengerAddr); - s_arbitrumCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - vm.startPrank(s_newOwnerCrossDomainMessengerAddr); - s_arbitrumCrossDomainForwarder.acceptL1Ownership(); - - // Asserts that the ownership was actually transferred - assertEq(s_arbitrumCrossDomainForwarder.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol deleted file mode 100644 index 610f49f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol +++ /dev/null @@ -1,258 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ArbitrumCrossDomainGovernor} from "../../../dev/arbitrum/ArbitrumCrossDomainGovernor.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -import {MultiSend} from "../../../../vendor/MultiSend.sol"; - -contract ArbitrumCrossDomainGovernorTest is L2EPTest { - /// Helper variable(s) - address internal s_crossDomainMessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); - address internal s_newOwnerCrossDomainMessengerAddr = toArbitrumL2AliasAddress(s_strangerAddr); - - /// Contracts - ArbitrumCrossDomainGovernor internal s_arbitrumCrossDomainGovernor; - MultiSend internal s_multiSend; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_arbitrumCrossDomainGovernor = new ArbitrumCrossDomainGovernor(s_l1OwnerAddr); - s_greeter = new Greeter(address(s_arbitrumCrossDomainGovernor)); - s_multiSend = new MultiSend(); - vm.stopPrank(); - } -} - -contract ArbitrumCrossDomainGovernor_Constructor is ArbitrumCrossDomainGovernorTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_arbitrumCrossDomainGovernor.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_arbitrumCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_arbitrumCrossDomainGovernor.crossDomainMessenger(), s_crossDomainMessengerAddr); - - // it should set the typeAndVersion correctly - assertEq(s_arbitrumCrossDomainGovernor.typeAndVersion(), "ArbitrumCrossDomainGovernor 1.0.0"); - } -} - -contract ArbitrumCrossDomainGovernor_Forward is ArbitrumCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_arbitrumCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_arbitrumCrossDomainGovernor.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_arbitrumCrossDomainGovernor.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_arbitrumCrossDomainGovernor.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, "") - ); - } -} - -contract ArbitrumCrossDomainGovernor_ForwardDelegate is ArbitrumCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_arbitrumCrossDomainGovernor.forwardDelegate(address(s_multiSend), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends the message - s_arbitrumCrossDomainGovernor.forwardDelegate( - address(s_multiSend), - abi.encodeWithSelector( - MultiSend.multiSend.selector, - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ) - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Sends the message - s_arbitrumCrossDomainGovernor.forwardDelegate( - address(s_multiSend), - abi.encodeWithSelector( - MultiSend.multiSend.selector, - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ) - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should revert batch when one call fails - function test_RevertsBatchWhenOneCallFails() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Governor delegatecall reverted"); - s_arbitrumCrossDomainGovernor.forwardDelegate( - address(s_multiSend), - abi.encodeWithSelector( - MultiSend.multiSend.selector, - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) - ) - ); - - // Checks that the greeter message is unchanged - assertEq(s_greeter.greeting(), ""); - } - - /// @notice it should bubble up revert when contract call reverts - function test_BubbleUpRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Greeter: revert triggered"); - s_arbitrumCrossDomainGovernor.forwardDelegate( - address(s_greeter), - abi.encodeWithSelector(Greeter.triggerRevert.selector) - ); - } -} - -contract ArbitrumCrossDomainGovernor_TransferL1Ownership is ArbitrumCrossDomainGovernorTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_arbitrumCrossDomainGovernor.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_arbitrumCrossDomainGovernor.l1Owner(), s_strangerAddr); - - // Sends the message - s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_arbitrumCrossDomainGovernor.l1Owner(), address(0)); - - // Sends the message - s_arbitrumCrossDomainGovernor.transferL1Ownership(address(0)); - } -} - -contract ArbitrumCrossDomainGovernor_AcceptL1Ownership is ArbitrumCrossDomainGovernorTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_crossDomainMessengerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_arbitrumCrossDomainGovernor.acceptL1Ownership(); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Request ownership transfer - vm.startPrank(s_crossDomainMessengerAddr); - s_arbitrumCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - vm.startPrank(s_newOwnerCrossDomainMessengerAddr); - s_arbitrumCrossDomainGovernor.acceptL1Ownership(); - - // Asserts that the ownership was actually transferred - assertEq(s_arbitrumCrossDomainGovernor.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol deleted file mode 100644 index e308ead..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol +++ /dev/null @@ -1,248 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; -import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {Flags} from "../../../dev/Flags.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ArbitrumSequencerUptimeFeedTest is L2EPTest { - /// Constants - uint256 internal constant GAS_USED_DEVIATION = 100; - - /// Helper variable(s) - address internal s_l2MessengerAddr = toArbitrumL2AliasAddress(s_l1OwnerAddr); - - /// L2EP contracts - ArbitrumSequencerUptimeFeed internal s_arbitrumSequencerUptimeFeed; - SimpleWriteAccessController internal s_accessController; - MockAggregatorV2V3 internal s_l1GasFeed; - Flags internal s_flags; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); - event Initialized(); - - /// Setup - function setUp() public { - vm.startPrank(s_deployerAddr, s_deployerAddr); - - s_accessController = new SimpleWriteAccessController(); - s_flags = new Flags(address(s_accessController), address(s_accessController)); - s_arbitrumSequencerUptimeFeed = new ArbitrumSequencerUptimeFeed(address(s_flags), s_l1OwnerAddr); - - s_accessController.addAccess(address(s_arbitrumSequencerUptimeFeed)); - s_accessController.addAccess(address(s_flags)); - s_accessController.addAccess(s_deployerAddr); - s_flags.addAccess(address(s_arbitrumSequencerUptimeFeed)); - - vm.expectEmit(); - emit Initialized(); - s_arbitrumSequencerUptimeFeed.initialize(); - - vm.stopPrank(); - } -} - -contract ArbitrumSequencerUptimeFeed_Constants is ArbitrumSequencerUptimeFeedTest { - /// @notice it should have the correct value for FLAG_L2_SEQ_OFFLINE' - function test_InitialState() public { - assertEq(s_arbitrumSequencerUptimeFeed.FLAG_L2_SEQ_OFFLINE(), 0xa438451D6458044c3c8CD2f6f31c91ac882A6d91); - } -} - -contract ArbitrumSequencerUptimeFeed_UpdateStatus is ArbitrumSequencerUptimeFeedTest { - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(ArbitrumSequencerUptimeFeed.InvalidSender.selector); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_arbitrumSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract ArbitrumSequencerUptimeFeed_AggregatorV3Interface is ArbitrumSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_arbitrumSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_Return0WhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) = s_arbitrumSequencerUptimeFeed.getRoundData(2); - - // Validates round data - assertEq(roundId, 2); - assertEq(answer, 0); - assertEq(startedAt, 0); - assertEq(updatedAt, 0); - assertEq(answeredInRound, 2); - } -} - -contract ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ArbitrumSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_arbitrumSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_arbitrumSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_arbitrumSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_arbitrumSequencerUptimeFeed)); - - // Whitelist consumer - vm.startPrank(s_deployerAddr, s_deployerAddr); - s_arbitrumSequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_arbitrumSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_arbitrumSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol deleted file mode 100644 index ab87299..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; - -import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; -import {ArbitrumValidator} from "../../../dev/arbitrum/ArbitrumValidator.sol"; -import {MockArbitrumInbox} from "../../../../tests/MockArbitrumInbox.sol"; -import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ArbitrumValidatorTest is L2EPTest { - /// Helper constants - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; - uint256 internal constant GAS_PRICE_BID = 1000000; - uint256 internal constant BASE_FEE = 14000000000; - uint256 internal constant MAX_GAS = 1000000; - - /// L2EP contracts - AccessControllerInterface internal s_accessController; - MockArbitrumInbox internal s_mockArbitrumInbox; - ArbitrumValidator internal s_arbitrumValidator; - MockAggregatorV2V3 internal s_l1GasFeed; - - /// Events - event RetryableTicketNoRefundAliasRewriteCreated( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes data - ); - - /// Setup - function setUp() public { - s_accessController = new SimpleWriteAccessController(); - s_mockArbitrumInbox = new MockArbitrumInbox(); - s_l1GasFeed = new MockAggregatorV2V3(); - s_arbitrumValidator = new ArbitrumValidator( - address(s_mockArbitrumInbox), - L2_SEQ_STATUS_RECORDER_ADDRESS, - address(s_accessController), - MAX_GAS, - GAS_PRICE_BID, - BASE_FEE, - address(s_l1GasFeed), - ArbitrumValidator.PaymentStrategy.L1 - ); - } -} - -contract ArbitrumValidator_Validate is ArbitrumValidatorTest { - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { - // Gives access to the s_eoaValidator - s_arbitrumValidator.addAccess(s_eoaValidator); - - // Gets the ArbitrumValidator L2 address - address arbitrumValidatorL2Addr = toArbitrumL2AliasAddress(address(s_arbitrumValidator)); - - // Sets block.timestamp to a later date, funds the ArbitrumValidator contract, and sets msg.sender and tx.origin - uint256 futureTimestampInSeconds = block.timestamp + 5000; - vm.warp(futureTimestampInSeconds); - vm.deal(address(s_arbitrumValidator), 1 ether); - vm.startPrank(s_eoaValidator); - - // Sets up the expected event data - vm.expectEmit(); - emit RetryableTicketNoRefundAliasRewriteCreated( - L2_SEQ_STATUS_RECORDER_ADDRESS, // destAddr - 0, // arbTxCallValue - 25312000000000, // maxSubmissionCost - arbitrumValidatorL2Addr, // submissionRefundAddress - arbitrumValidatorL2Addr, // valueRefundAddress - MAX_GAS, // maxGas - GAS_PRICE_BID, // gasPriceBid - abi.encodeWithSelector(ArbitrumSequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // data - ); - - // Runs the function (which produces the event to test) - s_arbitrumValidator.validate(0, 0, 1, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol deleted file mode 100644 index c0e82ab..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {OptimismCrossDomainForwarder} from "../../../dev/optimism/OptimismCrossDomainForwarder.sol"; -import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract OptimismCrossDomainForwarderTest is L2EPTest { - /// Contracts - MockOVMCrossDomainMessenger internal s_mockOptimismCrossDomainMessenger; - OptimismCrossDomainForwarder internal s_optimismCrossDomainForwarder; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_mockOptimismCrossDomainMessenger = new MockOVMCrossDomainMessenger(s_l1OwnerAddr); - s_optimismCrossDomainForwarder = new OptimismCrossDomainForwarder( - s_mockOptimismCrossDomainMessenger, - s_l1OwnerAddr - ); - s_greeter = new Greeter(address(s_optimismCrossDomainForwarder)); - vm.stopPrank(); - } -} - -contract OptimismCrossDomainForwarder_Constructor is OptimismCrossDomainForwarderTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_optimismCrossDomainForwarder.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_optimismCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_optimismCrossDomainForwarder.crossDomainMessenger(), address(s_mockOptimismCrossDomainMessenger)); - - // it should set the typeAndVersion correctly - assertEq(s_optimismCrossDomainForwarder.typeAndVersion(), "OptimismCrossDomainForwarder 1.0.0"); - } -} - -contract OptimismCrossDomainForwarder_Forward is OptimismCrossDomainForwarderTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_optimismCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainForwarder.forward.selector, address(s_greeter), greeting), // message - 0 // gas limit - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainForwarder.forward.selector, address(s_greeter), ""), // message - 0 // gas limit - ); - } -} - -contract OptimismCrossDomainForwarder_TransferL1Ownership is OptimismCrossDomainForwarderTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_optimismCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_optimismCrossDomainForwarder.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_optimismCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_optimismCrossDomainForwarder.l1Owner(), s_strangerAddr); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_optimismCrossDomainForwarder.l1Owner(), address(0)); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, address(0)), // message - 0 // gas limit - ); - } -} - -contract OptimismCrossDomainForwarder_AcceptL1Ownership is OptimismCrossDomainForwarderTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - abi.encodeWithSelector(s_optimismCrossDomainForwarder.acceptL1Ownership.selector), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Request ownership transfer - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - abi.encodeWithSelector(s_optimismCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Sets a mock message sender - s_mockOptimismCrossDomainMessenger._setMockMessageSender(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainForwarder), // target - abi.encodeWithSelector(s_optimismCrossDomainForwarder.acceptL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Asserts that the ownership was actually transferred - assertEq(s_optimismCrossDomainForwarder.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol deleted file mode 100644 index 8f8fb9d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol +++ /dev/null @@ -1,294 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {OptimismCrossDomainGovernor} from "../../../dev/optimism/OptimismCrossDomainGovernor.sol"; -import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -import {MultiSend} from "../../../../vendor/MultiSend.sol"; - -contract OptimismCrossDomainGovernorTest is L2EPTest { - /// Contracts - MockOVMCrossDomainMessenger internal s_mockOptimismCrossDomainMessenger; - OptimismCrossDomainGovernor internal s_optimismCrossDomainGovernor; - MultiSend internal s_multiSend; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_mockOptimismCrossDomainMessenger = new MockOVMCrossDomainMessenger(s_l1OwnerAddr); - s_optimismCrossDomainGovernor = new OptimismCrossDomainGovernor(s_mockOptimismCrossDomainMessenger, s_l1OwnerAddr); - s_greeter = new Greeter(address(s_optimismCrossDomainGovernor)); - s_multiSend = new MultiSend(); - vm.stopPrank(); - } -} - -contract OptimismCrossDomainGovernor_Constructor is OptimismCrossDomainGovernorTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_optimismCrossDomainGovernor.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_optimismCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_optimismCrossDomainGovernor.crossDomainMessenger(), address(s_mockOptimismCrossDomainMessenger)); - - // it should set the typeAndVersion correctly - assertEq(s_optimismCrossDomainGovernor.typeAndVersion(), "OptimismCrossDomainGovernor 1.0.0"); - } -} - -contract OptimismCrossDomainGovernor_Forward is OptimismCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_optimismCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainGovernor.forward.selector, address(s_greeter), greeting), // message - 0 // gas limit - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - encodeCrossDomainSetGreetingMsg(s_optimismCrossDomainGovernor.forward.selector, address(s_greeter), ""), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_optimismCrossDomainGovernor.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), greeting); - } -} - -contract OptimismCrossDomainGovernor_ForwardDelegate is OptimismCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_optimismCrossDomainGovernor.forwardDelegate(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - encodeCrossDomainMultiSendMsg( - s_optimismCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - encodeCrossDomainMultiSendMsg( - s_optimismCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should revert batch when one call fails - function test_RevertsBatchWhenOneCallFails() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Governor delegatecall reverted"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - encodeCrossDomainMultiSendMsg( - s_optimismCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message is unchanged - assertEq(s_greeter.greeting(), ""); - } - - /// @notice it should bubble up revert when contract call reverts - function test_BubbleUpRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Greeter: revert triggered"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector( - OptimismCrossDomainGovernor.forwardDelegate.selector, - address(s_greeter), - abi.encodeWithSelector(Greeter.triggerRevert.selector) - ), // message - 0 // gas limit - ); - } -} - -contract OptimismCrossDomainGovernor_TransferL1Ownership is OptimismCrossDomainGovernorTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_optimismCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_optimismCrossDomainGovernor.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_optimismCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_optimismCrossDomainGovernor.l1Owner(), s_strangerAddr); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_optimismCrossDomainGovernor.l1Owner(), address(0)); - - // Sends the message - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, address(0)), // message - 0 // gas limit - ); - } -} - -contract OptimismCrossDomainGovernor_AcceptL1Ownership is OptimismCrossDomainGovernorTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector(s_optimismCrossDomainGovernor.acceptL1Ownership.selector), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Request ownership transfer - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector(s_optimismCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Sets a mock message sender - s_mockOptimismCrossDomainMessenger._setMockMessageSender(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - s_mockOptimismCrossDomainMessenger.sendMessage( - address(s_optimismCrossDomainGovernor), // target - abi.encodeWithSelector(s_optimismCrossDomainGovernor.acceptL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Asserts that the ownership was actually transferred - assertEq(s_optimismCrossDomainGovernor.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol deleted file mode 100644 index eec9657..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; -import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract OptimismSequencerUptimeFeedTest is L2EPTest { - /// Constants - uint256 internal constant GAS_USED_DEVIATION = 100; - - /// L2EP contracts - MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; - MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; - OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); - - /// Setup - function setUp() public { - // Deploys contracts - s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); - s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); - s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( - s_l1OwnerAddr, - address(s_mockOptimismL2CrossDomainMessenger), - false - ); - - // Sets mock sender in mock L2 messenger contract - s_mockOptimismL2CrossDomainMessenger.setSender(s_l1OwnerAddr); - } -} - -contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Checks L1 sender - address actualL1Addr = s_optimismSequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); - - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = s_optimismSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} - -contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeedTest { - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender - function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Sets mock sender in mock L2 messenger contract - s_mockOptimismL2CrossDomainMessenger.setSender(s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_optimismSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_optimismSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_optimismSequencerUptimeFeed.getTimestamp(2); - } -} - -contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is OptimismSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); - - // Whitelist consumer - s_optimismSequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol deleted file mode 100644 index 59395bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; - -import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; -import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; -import {OptimismValidator} from "../../../dev/optimism/OptimismValidator.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract OptimismValidatorTest is L2EPTest { - /// Helper constants - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; - uint32 internal constant INIT_GAS_LIMIT = 1900000; - - /// L2EP contracts - MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; - MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; - OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; - OptimismValidator internal s_optimismValidator; - - /// Events - event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); - - /// Setup - function setUp() public { - s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); - s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); - - s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( - address(s_mockOptimismL1CrossDomainMessenger), - address(s_mockOptimismL2CrossDomainMessenger), - true - ); - - s_optimismValidator = new OptimismValidator( - address(s_mockOptimismL1CrossDomainMessenger), - address(s_optimismSequencerUptimeFeed), - INIT_GAS_LIMIT - ); - } -} - -contract OptimismValidator_SetGasLimit is OptimismValidatorTest { - /// @notice it correctly updates the gas limit - function test_CorrectlyUpdatesTheGasLimit() public { - uint32 newGasLimit = 2000000; - assertEq(s_optimismValidator.getGasLimit(), INIT_GAS_LIMIT); - s_optimismValidator.setGasLimit(newGasLimit); - assertEq(s_optimismValidator.getGasLimit(), newGasLimit); - } -} - -contract OptimismValidator_Validate is OptimismValidatorTest { - /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("No access"); - s_optimismValidator.validate(0, 0, 1, 1); - } - - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { - // Gives access to the s_eoaValidator - s_optimismValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 5000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - vm.expectEmit(false, false, false, true); - emit SentMessage( - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - address(s_optimismValidator), // sender - abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds), // message - 0, // nonce - INIT_GAS_LIMIT // gas limit - ); - - // Runs the function (which produces the event to test) - s_optimismValidator.validate(0, 0, 0, 0); - } - - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { - // Gives access to the s_eoaValidator - s_optimismValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 10000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - vm.expectEmit(false, false, false, true); - emit SentMessage( - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - address(s_optimismValidator), // sender - abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds), // message - 0, // nonce - INIT_GAS_LIMIT // gas limit - ); - - // Runs the function (which produces the event to test) - s_optimismValidator.validate(0, 0, 1, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol deleted file mode 100644 index e34e84f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainForwarder} from "../../../dev/scroll/ScrollCrossDomainForwarder.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ScrollCrossDomainForwarderTest is L2EPTest { - /// Contracts - MockScrollCrossDomainMessenger internal s_mockScrollCrossDomainMessenger; - ScrollCrossDomainForwarder internal s_scrollCrossDomainForwarder; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_mockScrollCrossDomainMessenger = new MockScrollCrossDomainMessenger(s_l1OwnerAddr); - s_scrollCrossDomainForwarder = new ScrollCrossDomainForwarder(s_mockScrollCrossDomainMessenger, s_l1OwnerAddr); - s_greeter = new Greeter(address(s_scrollCrossDomainForwarder)); - vm.stopPrank(); - } -} - -contract ScrollCrossDomainForwarder_Constructor is ScrollCrossDomainForwarderTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_scrollCrossDomainForwarder.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_scrollCrossDomainForwarder.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_scrollCrossDomainForwarder.crossDomainMessenger(), address(s_mockScrollCrossDomainMessenger)); - - // it should set the typeAndVersion correctly - assertEq(s_scrollCrossDomainForwarder.typeAndVersion(), "ScrollCrossDomainForwarder 1.0.0"); - } -} - -contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_scrollCrossDomainForwarder.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainForwarder.forward.selector, address(s_greeter), greeting), // message - 0 // gas limit - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainForwarder.forward.selector, address(s_greeter), ""), // message - 0 // gas limit - ); - } -} - -contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForwarderTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_scrollCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_scrollCrossDomainForwarder.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_scrollCrossDomainForwarder.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_scrollCrossDomainForwarder.l1Owner(), s_strangerAddr); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_scrollCrossDomainForwarder.l1Owner(), address(0)); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, address(0)), // message - 0 // gas limit - ); - } -} - -contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwarderTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainForwarder.acceptL1Ownership.selector), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Request ownership transfer - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainForwarder.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Sets a mock message sender - s_mockScrollCrossDomainMessenger._setMockMessageSender(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainForwarder), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainForwarder.acceptL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Asserts that the ownership was actually transferred - assertEq(s_scrollCrossDomainForwarder.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol deleted file mode 100644 index 8c3d56d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol +++ /dev/null @@ -1,305 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainGovernor} from "../../../dev/scroll/ScrollCrossDomainGovernor.sol"; -import {Greeter} from "../../../../tests/Greeter.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -import {MultiSend} from "../../../../vendor/MultiSend.sol"; - -contract ScrollCrossDomainGovernorTest is L2EPTest { - /// Contracts - MockScrollCrossDomainMessenger internal s_mockScrollCrossDomainMessenger; - ScrollCrossDomainGovernor internal s_scrollCrossDomainGovernor; - MultiSend internal s_multiSend; - Greeter internal s_greeter; - - /// Events - event L1OwnershipTransferRequested(address indexed from, address indexed to); - event L1OwnershipTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - vm.startPrank(s_l1OwnerAddr); - s_mockScrollCrossDomainMessenger = new MockScrollCrossDomainMessenger(s_l1OwnerAddr); - s_scrollCrossDomainGovernor = new ScrollCrossDomainGovernor(s_mockScrollCrossDomainMessenger, s_l1OwnerAddr); - s_greeter = new Greeter(address(s_scrollCrossDomainGovernor)); - s_multiSend = new MultiSend(); - vm.stopPrank(); - } -} - -contract ScrollCrossDomainGovernor_Constructor is ScrollCrossDomainGovernorTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // it should set the owner correctly - assertEq(s_scrollCrossDomainGovernor.owner(), s_l1OwnerAddr); - - // it should set the l1Owner correctly - assertEq(s_scrollCrossDomainGovernor.l1Owner(), s_l1OwnerAddr); - - // it should set the crossdomain messenger correctly - assertEq(s_scrollCrossDomainGovernor.crossDomainMessenger(), address(s_mockScrollCrossDomainMessenger)); - - // it should set the typeAndVersion correctly - assertEq(s_scrollCrossDomainGovernor.typeAndVersion(), "ScrollCrossDomainGovernor 1.0.0"); - } -} - -contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_scrollCrossDomainGovernor.forward(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_Forward() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainGovernor.forward.selector, address(s_greeter), greeting), // message - 0 // gas limit - ); - - // Checks that the greeter got the message - assertEq(s_greeter.greeting(), greeting); - } - - /// @notice it should revert when contract call reverts - function test_ForwardRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message - vm.expectRevert("Invalid greeting length"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - encodeCrossDomainSetGreetingMsg(s_scrollCrossDomainGovernor.forward.selector, address(s_greeter), ""), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Defines the cross domain message to send - string memory greeting = "hello"; - - // Sends the message - s_scrollCrossDomainGovernor.forward( - address(s_greeter), - abi.encodeWithSelector(s_greeter.setGreeting.selector, greeting) - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), greeting); - } -} - -contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorTest { - /// @notice it should not be callable by unknown address - function test_NotCallableByUnknownAddress() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger or owner"); - s_scrollCrossDomainGovernor.forwardDelegate(address(s_greeter), abi.encode("")); - } - - /// @notice it should be callable by crossdomain messenger address / L1 owner - function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - encodeCrossDomainMultiSendMsg( - s_scrollCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should be callable by L2 owner - function test_CallableByL2Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_l1OwnerAddr); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - encodeCrossDomainMultiSendMsg( - s_scrollCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "bar")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message was updated - assertEq(s_greeter.greeting(), "bar"); - } - - /// @notice it should revert batch when one call fails - function test_RevertsBatchWhenOneCallFails() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Governor delegatecall reverted"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - encodeCrossDomainMultiSendMsg( - s_scrollCrossDomainGovernor.forwardDelegate.selector, - address(s_multiSend), - abi.encodePacked(encodeMultiSendTx(address(s_greeter), "foo"), encodeMultiSendTx(address(s_greeter), "")) - ), // message - 0 // gas limit - ); - - // Checks that the greeter message is unchanged - assertEq(s_greeter.greeting(), ""); - } - - /// @notice it should bubble up revert when contract call reverts - function test_BubbleUpRevert() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends an invalid message (empty transaction data is not allowed) - vm.expectRevert("Greeter: revert triggered"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector( - ScrollCrossDomainGovernor.forwardDelegate.selector, - address(s_greeter), - abi.encodeWithSelector(Greeter.triggerRevert.selector) - ), // message - 0 // gas limit - ); - } -} - -contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGovernorTest { - /// @notice it should not be callable by non-owners - function test_NotCallableByNonOwners() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_scrollCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should not be callable by L2 owner - function test_NotCallableByL2Owner() public { - vm.startPrank(s_l1OwnerAddr); - assertEq(s_scrollCrossDomainGovernor.owner(), s_l1OwnerAddr); - vm.expectRevert("Sender is not the L2 messenger"); - s_scrollCrossDomainGovernor.transferL1Ownership(s_strangerAddr); - } - - /// @notice it should be callable by current L1 owner - function test_CallableByL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_scrollCrossDomainGovernor.l1Owner(), s_strangerAddr); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by current L1 owner to zero address - function test_CallableByL1OwnerOrZeroAddress() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Defines the cross domain message to send - vm.expectEmit(); - emit L1OwnershipTransferRequested(s_scrollCrossDomainGovernor.l1Owner(), address(0)); - - // Sends the message - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, address(0)), // message - 0 // gas limit - ); - } -} - -contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGovernorTest { - /// @notice it should not be callable by non pending-owners - function test_NotCallableByNonPendingOwners() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Sends the message - vm.expectRevert("Must be proposed L1 owner"); - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainGovernor.acceptL1Ownership.selector), // message - 0 // gas limit - ); - } - - /// @notice it should be callable by pending L1 owner - function test_CallableByPendingL1Owner() public { - // Sets msg.sender and tx.origin - vm.startPrank(s_strangerAddr); - - // Request ownership transfer - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainGovernor.transferL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Sets a mock message sender - s_mockScrollCrossDomainMessenger._setMockMessageSender(s_strangerAddr); - - // Prepares expected event payload - vm.expectEmit(); - emit L1OwnershipTransferred(s_l1OwnerAddr, s_strangerAddr); - - // Accepts ownership transfer request - s_mockScrollCrossDomainMessenger.sendMessage( - address(s_scrollCrossDomainGovernor), // target - 0, // value - abi.encodeWithSelector(s_scrollCrossDomainGovernor.acceptL1Ownership.selector, s_strangerAddr), // message - 0 // gas limit - ); - - // Asserts that the ownership was actually transferred - assertEq(s_scrollCrossDomainGovernor.l1Owner(), s_strangerAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol deleted file mode 100644 index 0968c69..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ /dev/null @@ -1,325 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; -import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; -import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ScrollSequencerUptimeFeedTest is L2EPTest { - /// Constants - uint256 internal constant GAS_USED_DEVIATION = 100; - - /// L2EP contracts - MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; - MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; - ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); - - /// Setup - function setUp() public { - // Deploys contracts - s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); - s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); - s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( - s_l1OwnerAddr, - address(s_mockScrollL2CrossDomainMessenger), - false - ); - - // Sets mock sender in mock L2 messenger contract - s_mockScrollL2CrossDomainMessenger.setSender(s_l1OwnerAddr); - } -} - -contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // L2 cross domain messenger address must not be the zero address - vm.expectRevert(ScrollSequencerUptimeFeed.ZeroAddress.selector); - new ScrollSequencerUptimeFeed(s_l1OwnerAddr, address(0), false); - - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Checks L1 sender - address actualL1Addr = s_scrollSequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); - - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = s_scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} - -contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest { - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender - function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Sets mock sender in mock L2 messenger contract - s_mockScrollL2CrossDomainMessenger.setSender(s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_scrollSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_scrollSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Fetches the latest timestamp - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Submits a status update - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_scrollSequencerUptimeFeed.getTimestamp(2); - } -} - -contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ScrollSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); - - // Whitelist consumer - s_scrollSequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol deleted file mode 100644 index 3d5298d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; - -import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; -import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; -import {MockScrollL1MessageQueue} from "../../mocks/scroll/MockScrollL1MessageQueue.sol"; -import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; -import {ScrollValidator} from "../../../dev/scroll/ScrollValidator.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ScrollValidatorTest is L2EPTest { - /// Helper constants - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; - uint32 internal constant INIT_GAS_LIMIT = 1900000; - - /// L2EP contracts - MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; - MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; - MockScrollL1MessageQueue internal s_mockScrollL1MessageQueue; - ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; - ScrollValidator internal s_scrollValidator; - - /// https://github.com/scroll-tech/scroll/blob/03089eaeee1193ff44c532c7038611ae123e7ef3/contracts/src/libraries/IScrollMessenger.sol#L22 - event SentMessage( - address indexed sender, - address indexed target, - uint256 value, - uint256 messageNonce, - uint256 gasLimit, - bytes message - ); - - /// Setup - function setUp() public { - s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); - s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); - s_mockScrollL1MessageQueue = new MockScrollL1MessageQueue(); - - s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( - address(s_mockScrollL1CrossDomainMessenger), - address(s_mockScrollL2CrossDomainMessenger), - true - ); - - s_scrollValidator = new ScrollValidator( - address(s_mockScrollL1CrossDomainMessenger), - address(s_scrollSequencerUptimeFeed), - address(s_mockScrollL1MessageQueue), - INIT_GAS_LIMIT - ); - } -} - -contract ScrollValidator_SetGasLimit is ScrollValidatorTest { - /// @notice it correctly updates the gas limit - function test_CorrectlyUpdatesTheGasLimit() public { - uint32 newGasLimit = 2000000; - assertEq(s_scrollValidator.getGasLimit(), INIT_GAS_LIMIT); - s_scrollValidator.setGasLimit(newGasLimit); - assertEq(s_scrollValidator.getGasLimit(), newGasLimit); - } -} - -contract ScrollValidator_Validate is ScrollValidatorTest { - /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("No access"); - s_scrollValidator.validate(0, 0, 1, 1); - } - - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { - // Gives access to the s_eoaValidator - s_scrollValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 5000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - vm.expectEmit(false, false, false, true); - emit SentMessage( - address(s_scrollValidator), // sender - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - 0, // value - 0, // nonce - INIT_GAS_LIMIT, // gas limit - abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, false, futureTimestampInSeconds) // message - ); - - // Runs the function (which produces the event to test) - s_scrollValidator.validate(0, 0, 0, 0); - } - - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { - // Gives access to the s_eoaValidator - s_scrollValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 10000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - vm.expectEmit(false, false, false, true); - emit SentMessage( - address(s_scrollValidator), // sender - L2_SEQ_STATUS_RECORDER_ADDRESS, // target - 0, // value - 0, // nonce - INIT_GAS_LIMIT, // gas limit - abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) // message - ); - - // Runs the function (which produces the event to test) - s_scrollValidator.validate(0, 0, 1, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol deleted file mode 100644 index 6d90b39..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol +++ /dev/null @@ -1,291 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ZKSyncSequencerUptimeFeed} from "../../../dev/zksync/ZKSyncSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ZKSyncSequencerUptimeFeedTest is L2EPTest { - /// Helper Variables - address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); - - /// L2EP contracts - ZKSyncSequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); - - /// Setup - function setUp() public { - // Deploys contracts - s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed(s_l1OwnerAddr, false); - } -} - -contract ZKSyncSequencerUptimeFeed_Constructor is ZKSyncSequencerUptimeFeedTest { - /// @notice it should have been deployed with the correct initial state - function test_InitialState() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Checks L1 sender - address actualL1Addr = s_zksyncSequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); - - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} - -contract ZKSyncSequencerUptimeFeed_UpdateStatus is ZKSyncSequencerUptimeFeedTest { - /// @notice it should revert if called by an unauthorized account - function test_RevertIfNotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(1)); - } - - /// @notice it should update status when status has not changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenNoChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_zksyncSequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice it should update status when status has changed and incoming timestamp is newer than the latest - function test_UpdateStatusWhenStatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should update status when status has changed and incoming timestamp is the same as latest - function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice it should ignore out-of-order updates - function test_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - // TODO: how can we check that an AnswerUpdated event was NOT emitted - s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - } -} - -contract ZKSyncSequencerUptimeFeed_AggregatorV3Interface is ZKSyncSequencerUptimeFeedTest { - /// @notice it should return valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) - function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getRoundData(2); - } - - /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) - function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getAnswer(2); - } - - /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) - function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_zksyncSequencerUptimeFeed.getTimestamp(2); - } -} - -contract ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ZKSyncSequencerUptimeFeedTest { - /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); - - // Whitelist consumer - s_zksyncSequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); - assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol deleted file mode 100644 index 0bea147..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; -import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; -import {ZKSyncValidator} from "../../../dev/zksync/ZKSyncValidator.sol"; -import {BaseValidator} from "../../../dev/shared/BaseValidator.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract ZKSyncValidatorTest is L2EPTest { - address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = address(0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b); - address internal constant DUMMY_L1_XDOMAIN_MSNGR_ADDR = address(0xa04Fc18f012B1a5A8231c7Ee4b916Dd6dbd271b6); - address internal constant DUMMY_L2_UPTIME_FEED_ADDR = address(0xFe31891940A2e5f04B76eD8bD1038E44127d1512); - uint32 internal constant INIT_GAS_PER_PUBDATA_BYTE_LIMIT = 800; - uint32 internal constant INIT_GAS_LIMIT = 1900000; - uint32 internal constant MAIN_NET_CHAIN_ID = 300; - uint32 internal constant BAD_CHAIN_ID = 0; - - ISequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; - MockBridgehub internal s_mockZKSyncL1Bridge; - ZKSyncValidator internal s_zksyncValidator; - - /// Fake event that will get emitted when `requestL2TransactionDirect` is called - /// Definition is taken from MockZKSyncL1Bridge - event SentMessage(address indexed sender, bytes message); - - /// Setup - function setUp() public { - s_mockZKSyncL1Bridge = new MockBridgehub(); - - s_zksyncValidator = new ZKSyncValidator( - address(s_mockZKSyncL1Bridge), - DUMMY_L2_UPTIME_FEED_ADDR, - INIT_GAS_LIMIT, - MAIN_NET_CHAIN_ID, - INIT_GAS_PER_PUBDATA_BYTE_LIMIT - ); - } -} - -contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { - /// @notice it correctly validates that the chain id is valid - function test_ConstructingRevertedWithInvalidChainId() public { - vm.expectRevert(ZKSyncValidator.InvalidChainID.selector); - new ZKSyncValidator( - DUMMY_L1_XDOMAIN_MSNGR_ADDR, - DUMMY_L2_UPTIME_FEED_ADDR, - INIT_GAS_LIMIT, - BAD_CHAIN_ID, - INIT_GAS_PER_PUBDATA_BYTE_LIMIT - ); - } - - /// @notice it correctly validates that the L1 bridge address is not zero - function test_ConstructingRevertedWithZeroL1BridgeAddress() public { - vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); - new ZKSyncValidator( - address(0), - DUMMY_L2_UPTIME_FEED_ADDR, - INIT_GAS_LIMIT, - MAIN_NET_CHAIN_ID, - INIT_GAS_PER_PUBDATA_BYTE_LIMIT - ); - } - - /// @notice it correctly validates that the L2 Uptime feed address is not zero - function test_ConstructingRevertedWithZeroL2UpdateFeedAddress() public { - vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); - new ZKSyncValidator( - DUMMY_L1_XDOMAIN_MSNGR_ADDR, - address(0), - INIT_GAS_LIMIT, - MAIN_NET_CHAIN_ID, - INIT_GAS_PER_PUBDATA_BYTE_LIMIT - ); - } -} - -contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { - /// @notice it correctly updates the gas limit per pubdata byte - function test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() public { - assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), INIT_GAS_PER_PUBDATA_BYTE_LIMIT); - - uint32 newGasPerPubDataByteLimit = 2000000; - s_zksyncValidator.setL2GasPerPubdataByteLimit(newGasPerPubDataByteLimit); - assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), newGasPerPubDataByteLimit); - } -} - -contract ZKSyncValidator_GetChainId is ZKSyncValidatorTest { - /// @notice it correctly gets the chain id - function test_CorrectlyGetsTheChainId() public { - assertEq(s_zksyncValidator.getChainId(), MAIN_NET_CHAIN_ID); - } -} - -contract ZKSyncValidator_Validate is ZKSyncValidatorTest { - /// @notice it reverts if called by account with no access - function test_RevertsIfCalledByAnAccountWithNoAccess() public { - vm.startPrank(s_strangerAddr); - vm.expectRevert("No access"); - s_zksyncValidator.validate(0, 0, 1, 1); - } - - /// @notice it posts sequencer status when there is not status change - function test_PostSequencerStatusWhenThereIsNotStatusChange() public { - // Gives access to the s_eoaValidator - s_zksyncValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 5000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - bytes memory message = abi.encodeWithSelector( - ISequencerUptimeFeed.updateStatus.selector, - false, - futureTimestampInSeconds - ); - - vm.expectEmit(false, false, false, true); - emit SentMessage(address(s_zksyncValidator), message); - - // Runs the function (which produces the event to test) - s_zksyncValidator.validate(0, 0, 0, 0); - } - - /// @notice it post sequencer offline - function test_PostSequencerOffline() public { - // Gives access to the s_eoaValidator - s_zksyncValidator.addAccess(s_eoaValidator); - - // Sets block.timestamp to a later date - uint256 futureTimestampInSeconds = block.timestamp + 10000; - vm.startPrank(s_eoaValidator); - vm.warp(futureTimestampInSeconds); - - // Sets up the expected event data - vm.expectEmit(false, false, false, true); - emit SentMessage( - address(s_zksyncValidator), - abi.encodeWithSelector(ISequencerUptimeFeed.updateStatus.selector, true, futureTimestampInSeconds) - ); - - // Runs the function (which produces the event to test) - s_zksyncValidator.validate(0, 0, 1, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol deleted file mode 100644 index 070930b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/LiquidityManager.sol +++ /dev/null @@ -1,575 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBridgeAdapter} from "./interfaces/IBridge.sol"; -import {ILiquidityManager} from "./interfaces/ILiquidityManager.sol"; -import {ILiquidityContainer} from "./interfaces/ILiquidityContainer.sol"; -import {IWrappedNative} from "../ccip/interfaces/IWrappedNative.sol"; - -import {OCR3Base} from "./ocr/OCR3Base.sol"; - -import {IERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice LiquidityManager for a single token over multiple chains. -/// @dev This contract is designed to be used with the LockReleaseTokenPool contract but -/// isn't constrained to it. It can be used with any contract that implements the ILiquidityContainer -/// interface. -/// @dev The OCR3 DON should only be able to transfer funds to other pre-approved contracts -/// on other chains. Under no circumstances should it be able to transfer funds to arbitrary -/// addresses. The owner is therefore in full control of the funds in this contract, not the DON. -/// This is a security feature. The worst that can happen is that the DON can lock up funds in -/// bridges, but it can't steal them. -/// @dev References to local mean logic on the same chain as this contract is deployed on. -/// References to remote mean logic on other chains. -contract LiquidityManager is ILiquidityManager, OCR3Base { - using SafeERC20 for IERC20; - - error ZeroAddress(); - error InvalidRemoteChain(uint64 chainSelector); - error ZeroChainSelector(); - error InsufficientLiquidity(uint256 requested, uint256 available, uint256 reserve); - error EmptyReport(); - error TransferFailed(); - error OnlyFinanceRole(); - - /// @notice Emitted when a finalization step is completed without funds being available. - /// @param ocrSeqNum The OCR sequence number of the report. - /// @param remoteChainSelector The chain selector of the remote chain funds are coming from. - /// @param bridgeSpecificData The bridge specific data that was used to finalize the transfer. - event FinalizationStepCompleted( - uint64 indexed ocrSeqNum, - uint64 indexed remoteChainSelector, - bytes bridgeSpecificData - ); - - /// @notice Emitted when the CLL finance role is set. - /// @param financeRole The address of the new finance role. - event FinanceRoleSet(address financeRole); - - /// @notice Emitted when liquidity is transferred to another chain, or received from another chain. - /// @param ocrSeqNum The OCR sequence number of the report. - /// @param fromChainSelector The chain selector of the chain the funds are coming from. - /// In the event fromChainSelector == i_localChainSelector, this is an outgoing transfer. - /// Otherwise, it is an incoming transfer. - /// @param toChainSelector The chain selector of the chain the funds are going to. - /// In the event toChainSelector == i_localChainSelector, this is an incoming transfer. - /// Otherwise, it is an outgoing transfer. - /// @param to The address the funds are going to. - /// If this is address(this), the funds are arriving in this contract. - /// @param amount The amount of tokens being transferred. - /// @param bridgeSpecificData The bridge specific data that was passed to the local bridge adapter - /// when transferring the funds. - /// @param bridgeReturnData The return data from the local bridge adapter when transferring the funds. - event LiquidityTransferred( - uint64 indexed ocrSeqNum, - uint64 indexed fromChainSelector, - uint64 indexed toChainSelector, - address to, - uint256 amount, - bytes bridgeSpecificData, - bytes bridgeReturnData - ); - - /// @notice Emitted when liquidity is added to the local liquidity container. - /// @param provider The address of the provider that added the liquidity. - /// @param amount The amount of liquidity that was added. - event LiquidityAddedToContainer(address indexed provider, uint256 indexed amount); - - /// @notice Emitted when liquidity is removed from the local liquidity container. - /// @param remover The address of the remover that removed the liquidity. - /// @param amount The amount of liquidity that was removed. - event LiquidityRemovedFromContainer(address indexed remover, uint256 indexed amount); - - /// @notice Emitted when the local liquidity container is set. - /// @param newLiquidityContainer The address of the new liquidity container. - event LiquidityContainerSet(address indexed newLiquidityContainer); - - /// @notice Emitted when the minimum liquidity is set. - /// @param oldBalance The old minimum liquidity. - /// @param newBalance The new minimum liquidity. - event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); - - /// @notice Emitted when someone sends native to this contract - /// @param amount The amount of native deposited - /// @param depositor The address that deposited the native - event NativeDeposited(uint256 amount, address depositor); - - /// @notice Emitted when native balance is withdrawn by contract owner - /// @param amount The amount of native withdrawn - /// @param destination The address the native is sent to - event NativeWithdrawn(uint256 amount, address destination); - - /// @notice Emitted when a cross chain rebalancer is set. - /// @param remoteChainSelector The chain selector of the remote chain. - /// @param localBridge The local bridge adapter that will be used to transfer funds. - /// @param remoteToken The address of the token on the remote chain. - /// @param remoteRebalancer The address of the remote rebalancer contract. - /// @param enabled Whether the rebalancer is enabled. - event CrossChainRebalancerSet( - uint64 indexed remoteChainSelector, - IBridgeAdapter localBridge, - address remoteToken, - address remoteRebalancer, - bool enabled - ); - - /// @notice Emitted when a finalization step fails. - /// @param ocrSeqNum The OCR sequence number of the report. - /// @param remoteChainSelector The chain selector of the remote chain funds are coming from. - /// @param bridgeSpecificData The bridge specific data that was used to finalize the transfer. - /// @param reason The reason the finalization failed. - event FinalizationFailed( - uint64 indexed ocrSeqNum, - uint64 indexed remoteChainSelector, - bytes bridgeSpecificData, - bytes reason - ); - - struct CrossChainRebalancer { - address remoteRebalancer; - IBridgeAdapter localBridge; - address remoteToken; - bool enabled; - } - - string public constant override typeAndVersion = "LiquidityManager 1.0.0-dev"; - - /// @notice The token that this pool manages liquidity for. - IERC20 public immutable i_localToken; - - /// @notice The chain selector belonging to the chain this pool is deployed on. - uint64 internal immutable i_localChainSelector; - - /// @notice The target balance defines the expected amount of tokens for this network. - /// Setting the balance to 0 will disable any automated rebalancing operations. - uint256 internal s_minimumLiquidity; - - /// @notice Mapping of chain selector to liquidity container on other chains - mapping(uint64 chainSelector => CrossChainRebalancer) private s_crossChainRebalancer; - - uint64[] private s_supportedDestChains; - - /// @notice The liquidity container on the local chain - /// @dev In the case of CCIP, this would be the token pool. - ILiquidityContainer private s_localLiquidityContainer; - - /// @notice The CLL finance team multisig - address private s_finance; - - constructor( - IERC20 token, - uint64 localChainSelector, - ILiquidityContainer localLiquidityContainer, - uint256 minimumLiquidity, - address finance - ) OCR3Base() { - if (localChainSelector == 0) { - revert ZeroChainSelector(); - } - - if (address(token) == address(0) || address(localLiquidityContainer) == address(0)) { - revert ZeroAddress(); - } - i_localToken = token; - i_localChainSelector = localChainSelector; - s_localLiquidityContainer = localLiquidityContainer; - s_minimumLiquidity = minimumLiquidity; - s_finance = finance; - } - - // ================================================================ - // │ Native Management │ - // ================================================================ - - receive() external payable { - emit NativeDeposited(msg.value, msg.sender); - } - - /// @notice withdraw native balance - function withdrawNative(uint256 amount, address payable destination) external onlyFinance { - (bool success, ) = destination.call{value: amount}(""); - if (!success) revert TransferFailed(); - - emit NativeWithdrawn(amount, destination); - } - - // ================================================================ - // │ Liquidity Management │ - // ================================================================ - - /// @inheritdoc ILiquidityManager - function getLiquidity() public view returns (uint256 currentLiquidity) { - return i_localToken.balanceOf(address(s_localLiquidityContainer)); - } - - /// @notice Adds liquidity to the multi-chain system. - /// @dev Anyone can call this function, but anyone other than the owner should regard - /// adding liquidity as a donation to the system, as there is no way to get it out. - /// This function is open to anyone to be able to quickly add funds to the system - /// without having to go through potentially complicated multisig schemes to do it from - /// the owner address. - function addLiquidity(uint256 amount) external { - i_localToken.safeTransferFrom(msg.sender, address(this), amount); - - // Make sure this is tether compatible, as they have strange approval requirements - // Should be good since all approvals are always immediately used. - i_localToken.safeApprove(address(s_localLiquidityContainer), amount); - s_localLiquidityContainer.provideLiquidity(amount); - - emit LiquidityAddedToContainer(msg.sender, amount); - } - - /// @notice Removes liquidity from the system and sends it to the caller, so the owner. - /// @dev Only the owner can call this function. - function removeLiquidity(uint256 amount) external onlyFinance { - uint256 currentBalance = getLiquidity(); - if (currentBalance < amount) { - revert InsufficientLiquidity(amount, currentBalance, 0); - } - - s_localLiquidityContainer.withdrawLiquidity(amount); - i_localToken.safeTransfer(msg.sender, amount); - - emit LiquidityRemovedFromContainer(msg.sender, amount); - } - - /// @notice escape hatch to manually withdraw any ERC20 token from the LM contract - /// @param token The address of the token to withdraw - /// @param amount The amount of tokens to withdraw - /// @param destination The address to send the tokens to - function withdrawERC20(address token, uint256 amount, address destination) external onlyFinance { - IERC20(token).safeTransfer(destination, amount); - } - - /// @notice Transfers liquidity to another chain. - /// @dev This function is a public version of the internal _rebalanceLiquidity function. - /// to allow the owner to also initiate a rebalancing when needed. - function rebalanceLiquidity( - uint64 chainSelector, - uint256 amount, - uint256 nativeBridgeFee, - bytes calldata bridgeSpecificPayload - ) external onlyFinance { - _rebalanceLiquidity(chainSelector, amount, nativeBridgeFee, type(uint64).max, bridgeSpecificPayload); - } - - /// @notice Finalizes liquidity from another chain. - /// @dev This function is a public version of the internal _receiveLiquidity function. - /// to allow the owner to also initiate a finalization when needed. - function receiveLiquidity( - uint64 remoteChainSelector, - uint256 amount, - bool shouldWrapNative, - bytes calldata bridgeSpecificPayload - ) external onlyFinance { - _receiveLiquidity(remoteChainSelector, amount, bridgeSpecificPayload, shouldWrapNative, type(uint64).max); - } - - /// @notice Transfers liquidity to another chain. - /// @dev Called by both the owner and the DON. - /// @param chainSelector The chain selector of the chain to transfer liquidity to. - /// @param tokenAmount The amount of tokens to transfer. - /// @param nativeBridgeFee The fee to pay to the bridge. - /// @param ocrSeqNum The OCR sequence number of the report. - /// @param bridgeSpecificPayload The bridge specific data to pass to the bridge adapter. - function _rebalanceLiquidity( - uint64 chainSelector, - uint256 tokenAmount, - uint256 nativeBridgeFee, - uint64 ocrSeqNum, - bytes memory bridgeSpecificPayload - ) internal { - uint256 currentBalance = getLiquidity(); - uint256 minBalance = s_minimumLiquidity; - if (currentBalance < minBalance || currentBalance - minBalance < tokenAmount) { - revert InsufficientLiquidity(tokenAmount, currentBalance, minBalance); - } - - CrossChainRebalancer memory remoteLiqManager = s_crossChainRebalancer[chainSelector]; - - if (!remoteLiqManager.enabled) { - revert InvalidRemoteChain(chainSelector); - } - - // XXX: Could be optimized by withdrawing once and then sending to all destinations - s_localLiquidityContainer.withdrawLiquidity(tokenAmount); - i_localToken.safeApprove(address(remoteLiqManager.localBridge), tokenAmount); - - bytes memory bridgeReturnData = remoteLiqManager.localBridge.sendERC20{value: nativeBridgeFee}( - address(i_localToken), - remoteLiqManager.remoteToken, - remoteLiqManager.remoteRebalancer, - tokenAmount, - bridgeSpecificPayload - ); - - emit LiquidityTransferred( - ocrSeqNum, - i_localChainSelector, - chainSelector, - remoteLiqManager.remoteRebalancer, - tokenAmount, - bridgeSpecificPayload, - bridgeReturnData - ); - } - - /// @notice Receives liquidity from another chain. - /// @dev Called by both the owner and the DON. - /// @param remoteChainSelector The chain selector of the chain to receive liquidity from. - /// @param amount The amount of tokens to receive. - /// @param bridgeSpecificPayload The bridge specific data to pass to the bridge adapter finalizeWithdrawERC20 call. - /// @param shouldWrapNative Whether the token should be wrapped before injecting it into the liquidity container. - /// This only applies to native tokens wrapper contracts, e.g WETH. - /// @param ocrSeqNum The OCR sequence number of the report. - function _receiveLiquidity( - uint64 remoteChainSelector, - uint256 amount, - bytes memory bridgeSpecificPayload, - bool shouldWrapNative, - uint64 ocrSeqNum - ) internal { - // check if the remote chain is supported - CrossChainRebalancer memory remoteRebalancer = s_crossChainRebalancer[remoteChainSelector]; - if (!remoteRebalancer.enabled) { - revert InvalidRemoteChain(remoteChainSelector); - } - - // finalize the withdrawal through the bridge adapter - try - remoteRebalancer.localBridge.finalizeWithdrawERC20( - remoteRebalancer.remoteRebalancer, // remoteSender: the remote rebalancer - address(this), // localReceiver: this contract - bridgeSpecificPayload - ) - returns (bool fundsAvailable) { - if (fundsAvailable) { - // finalization was successful and we can inject the liquidity into the container. - // approve and liquidity container should transferFrom. - _injectLiquidity(amount, ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, shouldWrapNative); - } else { - // a finalization step was completed, but funds are not available. - // hence, we cannot inject any liquidity yet. - emit FinalizationStepCompleted(ocrSeqNum, remoteChainSelector, bridgeSpecificPayload); - } - - // return here on the happy path. - // sad path is when finalizeWithdrawERC20 reverts, which is handled after the catch block. - return; - } catch (bytes memory lowLevelData) { - // failed to finalize the withdrawal. - // this could mean that the withdrawal was already finalized - // or that the withdrawal failed. - // we assume the former and continue - emit FinalizationFailed(ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, lowLevelData); - } - - // if we reach this point, the finalization failed. - // since we don't have enough information to know why it failed, - // we assume that it failed because the withdrawal was already finalized, - // and that the funds are available. - _injectLiquidity(amount, ocrSeqNum, remoteChainSelector, bridgeSpecificPayload, shouldWrapNative); - } - - /// @notice Injects liquidity into the local liquidity container. - /// @param amount The amount of tokens to inject. - /// @param ocrSeqNum The OCR sequence number of the report. - /// @param remoteChainSelector The chain selector of the remote chain. - /// @param bridgeSpecificPayload The bridge specific data passed to the bridge adapter finalizeWithdrawERC20 call. - /// @param shouldWrapNative Whether the token should be wrapped before injecting it into the liquidity container. - function _injectLiquidity( - uint256 amount, - uint64 ocrSeqNum, - uint64 remoteChainSelector, - bytes memory bridgeSpecificPayload, - bool shouldWrapNative - ) private { - // We trust the DON or the owner (the only two actors who can end up calling this function) - // to correctly set the shouldWrapNative flag. - // Some bridges only bridge native and not wrapped native. - // In such a case we need to re-wrap the native in order to inject it into the liquidity container. - // TODO: escape hatch in case of bug? - if (shouldWrapNative) { - IWrappedNative(address(i_localToken)).deposit{value: amount}(); - } - - i_localToken.safeIncreaseAllowance(address(s_localLiquidityContainer), amount); - s_localLiquidityContainer.provideLiquidity(amount); - - emit LiquidityTransferred( - ocrSeqNum, - remoteChainSelector, - i_localChainSelector, - address(this), - amount, - bridgeSpecificPayload, - bytes("") // no bridge return data when receiving - ); - } - - /// @notice Process the OCR report. - /// @dev Called by OCR3Base's transmit() function. - function _report(bytes calldata report, uint64 ocrSeqNum) internal override { - ILiquidityManager.LiquidityInstructions memory instructions = abi.decode( - report, - (ILiquidityManager.LiquidityInstructions) - ); - - uint256 sendInstructions = instructions.sendLiquidityParams.length; - uint256 receiveInstructions = instructions.receiveLiquidityParams.length; - - // There should always be instructions to send or receive, if not, the report is invalid - // and we revert to save the gas of the signature validation of OCR. - if (sendInstructions == 0 && receiveInstructions == 0) { - revert EmptyReport(); - } - - for (uint256 i = 0; i < sendInstructions; ++i) { - _rebalanceLiquidity( - instructions.sendLiquidityParams[i].remoteChainSelector, - instructions.sendLiquidityParams[i].amount, - instructions.sendLiquidityParams[i].nativeBridgeFee, - ocrSeqNum, - instructions.sendLiquidityParams[i].bridgeData - ); - } - - for (uint256 i = 0; i < receiveInstructions; ++i) { - _receiveLiquidity( - instructions.receiveLiquidityParams[i].remoteChainSelector, - instructions.receiveLiquidityParams[i].amount, - instructions.receiveLiquidityParams[i].bridgeData, - instructions.receiveLiquidityParams[i].shouldWrapNative, - ocrSeqNum - ); - } - } - - // ================================================================ - // │ Config │ - // ================================================================ - - function getSupportedDestChains() external view returns (uint64[] memory) { - return s_supportedDestChains; - } - - /// @notice Gets the cross chain liquidity manager - function getCrossChainRebalancer(uint64 chainSelector) external view returns (CrossChainRebalancer memory) { - return s_crossChainRebalancer[chainSelector]; - } - - /// @notice Gets all cross chain liquidity managers - /// @dev We don't care too much about gas since this function is intended for offchain usage. - function getAllCrossChainRebalancers() external view returns (CrossChainRebalancerArgs[] memory) { - uint256 numChains = s_supportedDestChains.length; - CrossChainRebalancerArgs[] memory managers = new CrossChainRebalancerArgs[](numChains); - for (uint256 i = 0; i < numChains; ++i) { - uint64 chainSelector = s_supportedDestChains[i]; - CrossChainRebalancer memory currentManager = s_crossChainRebalancer[chainSelector]; - managers[i] = CrossChainRebalancerArgs({ - remoteRebalancer: currentManager.remoteRebalancer, - localBridge: currentManager.localBridge, - remoteToken: currentManager.remoteToken, - remoteChainSelector: chainSelector, - enabled: currentManager.enabled - }); - } - - return managers; - } - - /// @notice Sets a list of cross chain liquidity managers. - /// @dev Will update the list of supported dest chains if the chain is new. - function setCrossChainRebalancers(CrossChainRebalancerArgs[] calldata crossChainRebalancers) external onlyOwner { - for (uint256 i = 0; i < crossChainRebalancers.length; ++i) { - _setCrossChainRebalancer(crossChainRebalancers[i]); - } - } - - function setCrossChainRebalancer(CrossChainRebalancerArgs calldata crossChainLiqManager) external onlyOwner { - _setCrossChainRebalancer(crossChainLiqManager); - } - - /// @notice Sets a single cross chain liquidity manager. - /// @dev Will update the list of supported dest chains if the chain is new. - function _setCrossChainRebalancer(CrossChainRebalancerArgs calldata crossChainLiqManager) internal { - if (crossChainLiqManager.remoteChainSelector == 0) { - revert ZeroChainSelector(); - } - - if ( - crossChainLiqManager.remoteRebalancer == address(0) || - address(crossChainLiqManager.localBridge) == address(0) || - crossChainLiqManager.remoteToken == address(0) - ) { - revert ZeroAddress(); - } - - // If the destination chain is new, add it to the list of supported chains - if (s_crossChainRebalancer[crossChainLiqManager.remoteChainSelector].remoteToken == address(0)) { - s_supportedDestChains.push(crossChainLiqManager.remoteChainSelector); - } - - s_crossChainRebalancer[crossChainLiqManager.remoteChainSelector] = CrossChainRebalancer({ - remoteRebalancer: crossChainLiqManager.remoteRebalancer, - localBridge: crossChainLiqManager.localBridge, - remoteToken: crossChainLiqManager.remoteToken, - enabled: crossChainLiqManager.enabled - }); - - emit CrossChainRebalancerSet( - crossChainLiqManager.remoteChainSelector, - crossChainLiqManager.localBridge, - crossChainLiqManager.remoteToken, - crossChainLiqManager.remoteRebalancer, - crossChainLiqManager.enabled - ); - } - - /// @notice Gets the local liquidity container. - function getLocalLiquidityContainer() external view returns (address) { - return address(s_localLiquidityContainer); - } - - /// @notice Sets the local liquidity container. - /// @dev Only the owner can call this function. - function setLocalLiquidityContainer(ILiquidityContainer localLiquidityContainer) external onlyOwner { - if (address(localLiquidityContainer) == address(0)) { - revert ZeroAddress(); - } - s_localLiquidityContainer = localLiquidityContainer; - - emit LiquidityContainerSet(address(localLiquidityContainer)); - } - - /// @notice Gets the target tokens balance. - function getMinimumLiquidity() external view returns (uint256) { - return s_minimumLiquidity; - } - - /// @notice Sets the target tokens balance. - /// @dev Only the owner can call this function. - function setMinimumLiquidity(uint256 minimumLiquidity) external onlyOwner { - uint256 oldLiquidity = s_minimumLiquidity; - s_minimumLiquidity = minimumLiquidity; - emit MinimumLiquiditySet(oldLiquidity, s_minimumLiquidity); - } - - /// @notice Gets the CLL finance team multisig address - function getFinanceRole() external view returns (address) { - return s_finance; - } - - /// @notice Sets the finance team multisig address - /// @dev Only the owner can call this function. - function setFinanceRole(address finance) external onlyOwner { - s_finance = finance; - emit FinanceRoleSet(finance); - } - - modifier onlyFinance() { - if (msg.sender != s_finance) revert OnlyFinanceRole(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol deleted file mode 100644 index 9ab7376..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL1BridgeAdapter.sol +++ /dev/null @@ -1,175 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBridgeAdapter} from "../interfaces/IBridge.sol"; - -import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; -import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -interface IOutbox { - /** - * @notice Executes a messages in an Outbox entry. - * @dev Reverts if dispute period hasn't expired, since the outbox entry - * is only created once the rollup confirms the respective assertion. - * @dev it is not possible to execute any L2-to-L1 transaction which contains data - * to a contract address without any code (as enforced by the Bridge contract). - * @param proof Merkle proof of message inclusion in send root - * @param index Merkle path to message - * @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) - * @param to destination address for L1 contract call - * @param l2Block l2 block number at which sendTxToL1 call was made - * @param l1Block l1 block number at which sendTxToL1 call was made - * @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made - * @param value wei in L1 message - * @param data abi-encoded L1 message data - */ - function executeTransaction( - bytes32[] calldata proof, - uint256 index, - address l2Sender, - address to, - uint256 l2Block, - uint256 l1Block, - uint256 l2Timestamp, - uint256 value, - bytes calldata data - ) external; -} - -/// @notice Arbitrum L1 Bridge adapter -/// @dev Auto unwraps and re-wraps wrapped eth in the bridge. -contract ArbitrumL1BridgeAdapter is IBridgeAdapter { - using SafeERC20 for IERC20; - - IL1GatewayRouter internal immutable i_l1GatewayRouter; - IOutbox internal immutable i_l1Outbox; - - error NoGatewayForToken(address token); - error Unimplemented(); - - constructor(IL1GatewayRouter l1GatewayRouter, IOutbox l1Outbox) { - if (address(l1GatewayRouter) == address(0) || address(l1Outbox) == address(0)) { - revert BridgeAddressCannotBeZero(); - } - i_l1GatewayRouter = l1GatewayRouter; - i_l1Outbox = l1Outbox; - } - - /// @dev these are parameters provided by the caller of the sendERC20 function - /// and must be determined offchain. - struct SendERC20Params { - uint256 gasLimit; - uint256 maxSubmissionCost; - uint256 maxFeePerGas; - } - - /// @inheritdoc IBridgeAdapter - function sendERC20( - address localToken, - address /* remoteToken */, - address recipient, - uint256 amount, - bytes calldata bridgeSpecificPayload - ) external payable override returns (bytes memory) { - // receive the token transfer from the msg.sender - IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); - - // Note: the gateway router could return 0x0 for the gateway address - // if that token is not yet registered - address gateway = IGatewayRouter(address(i_l1GatewayRouter)).getGateway(localToken); - if (gateway == address(0)) { - revert NoGatewayForToken(localToken); - } - - // approve the gateway to transfer the token amount sent to the adapter - IERC20(localToken).safeApprove(gateway, amount); - - SendERC20Params memory params = abi.decode(bridgeSpecificPayload, (SendERC20Params)); - - uint256 expectedMsgValue = (params.gasLimit * params.maxFeePerGas) + params.maxSubmissionCost; - if (msg.value < expectedMsgValue) { - revert MsgValueDoesNotMatchAmount(msg.value, expectedMsgValue); - } - - // The router will route the call to the gateway that we approved - // above. The gateway will then transfer the tokens to the L2. - // outboundTransferCustomRefund will return the abi encoded inbox sequence number - // which is 256 bits, so we can cap the return data to 256 bits. - bytes memory inboxSequenceNumber = i_l1GatewayRouter.outboundTransferCustomRefund{value: msg.value}( - localToken, - recipient, - recipient, - amount, - params.gasLimit, - params.maxFeePerGas, - abi.encode(params.maxSubmissionCost, bytes("")) - ); - - return inboxSequenceNumber; - } - - /// @dev This function is so that we can easily abi-encode the arbitrum-specific payload for the sendERC20 function. - function exposeSendERC20Params(SendERC20Params memory params) public pure {} - - /// @dev fees have to be determined offchain for arbitrum, therefore revert here to discourage usage. - function getBridgeFeeInNative() public pure override returns (uint256) { - revert Unimplemented(); - } - - /// @param proof Merkle proof of message inclusion in send root - /// @param index Merkle path to message - /// @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1) - /// @param to destination address for L1 contract call - /// @param l2Block l2 block number at which sendTxToL1 call was made - /// @param l1Block l1 block number at which sendTxToL1 call was made - /// @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made - /// @param value wei in L1 message - /// @param data abi-encoded L1 message data - struct ArbitrumFinalizationPayload { - bytes32[] proof; - uint256 index; - address l2Sender; - address to; - uint256 l2Block; - uint256 l1Block; - uint256 l2Timestamp; - uint256 value; - bytes data; - } - - /// @dev This function is so that we can easily abi-encode the arbitrum-specific payload for the finalizeWithdrawERC20 function. - function exposeArbitrumFinalizationPayload(ArbitrumFinalizationPayload memory payload) public pure {} - - /// @notice Finalize an L2 -> L1 transfer. - /// Arbitrum finalizations are single-step, so we always return true. - /// Calls to this function will revert in two cases, 1) if the finalization payload is wrong, - /// i.e incorrect merkle proof, or index and 2) if the withdrawal was already finalized. - /// @return true iff the finalization does not revert. - function finalizeWithdrawERC20( - address /* remoteSender */, - address /* localReceiver */, - bytes calldata arbitrumFinalizationPayload - ) external override returns (bool) { - ArbitrumFinalizationPayload memory payload = abi.decode(arbitrumFinalizationPayload, (ArbitrumFinalizationPayload)); - i_l1Outbox.executeTransaction( - payload.proof, - payload.index, - payload.l2Sender, - payload.to, - payload.l2Block, - payload.l1Block, - payload.l2Timestamp, - payload.value, - payload.data - ); - return true; - } - - /// @notice Convenience function to get the L2 token address from the L1 token address. - /// @return The L2 token address for the given L1 token address. - function getL2Token(address l1Token) external view returns (address) { - return i_l1GatewayRouter.calculateL2TokenAddress(l1Token); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol deleted file mode 100644 index 6ee9716..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/ArbitrumL2BridgeAdapter.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBridgeAdapter} from "../interfaces/IBridge.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -interface IArbSys { - function withdrawEth(address destination) external payable returns (uint256); -} - -interface IL2GatewayRouter { - function outboundTransfer( - address l1Token, - address to, - uint256 amount, - bytes calldata data - ) external payable returns (bytes memory); -} - -/// @notice Arbitrum L2 Bridge adapter -/// @dev Auto unwraps and re-wraps wrapped eth in the bridge. -contract ArbitrumL2BridgeAdapter is IBridgeAdapter { - using SafeERC20 for IERC20; - - IL2GatewayRouter internal immutable i_l2GatewayRouter; - // address internal immutable i_l1ERC20Gateway; - IArbSys internal constant ARB_SYS = IArbSys(address(0x64)); - - constructor(IL2GatewayRouter l2GatewayRouter) { - if (address(l2GatewayRouter) == address(0)) { - revert BridgeAddressCannotBeZero(); - } - i_l2GatewayRouter = l2GatewayRouter; - } - - /// @inheritdoc IBridgeAdapter - function sendERC20( - address localToken, - address remoteToken, - address recipient, - uint256 amount, - bytes calldata /* bridgeSpecificPayload */ - ) external payable override returns (bytes memory) { - if (msg.value != 0) { - revert MsgShouldNotContainValue(msg.value); - } - - IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); - - // the data returned is the unique id of the L2 to L1 transfer - // see https://github.com/OffchainLabs/token-bridge-contracts/blob/bf9ad3d7f25c0eaf0a5f89eec7a0a370833cea16/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol#L169-L191 - // No approval needed, the bridge will burn the tokens from this contract. - bytes memory l2ToL1TxId = i_l2GatewayRouter.outboundTransfer(remoteToken, recipient, amount, bytes("")); - - return l2ToL1TxId; - } - - /// @notice No-op since L1 -> L2 transfers do not need finalization. - /// @return true always. - function finalizeWithdrawERC20( - address /* remoteSender */, - address /* localReceiver */, - bytes calldata /* bridgeSpecificPayload */ - ) external pure override returns (bool) { - return true; - } - - /// @notice There are no fees to bridge back to L1 - function getBridgeFeeInNative() external pure returns (uint256) { - return 0; - } - - function depositNativeToL1(address recipient) external payable { - ARB_SYS.withdrawEth{value: msg.value}(recipient); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol deleted file mode 100644 index 6734c74..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL1BridgeAdapter.sol +++ /dev/null @@ -1,196 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBridgeAdapter} from "../interfaces/IBridge.sol"; -import {IWrappedNative} from "../../ccip/interfaces/IWrappedNative.sol"; -import {Types} from "../interfaces/optimism/Types.sol"; -import {IOptimismPortal} from "../interfaces/optimism/IOptimismPortal.sol"; - -import {IL1StandardBridge} from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice OptimismL1BridgeAdapter implements IBridgeAdapter for the Optimism L1<=>L2 bridge. -/// @dev L1 -> L2 deposits are done via the depositERC20To and depositETHTo functions on the L1StandardBridge. -/// The amount of gas provided for the transaction must be buffered - the Optimism SDK recommends a 20% buffer. -/// The Optimism Bridge implements 2-step withdrawals from L2 to L1. Once a withdrawal transaction is included -/// in the L2 chain, it must be proven on L1 before it can be finalized. There is a buffer between the transaction -/// being posted on L2 before it can be proven, and similarly, there is a buffer in the time it takes to prove -/// the transaction before it can be finalized. -/// See https://blog.oplabs.co/two-step-withdrawals/ for more details on this mechanism. -/// @dev We have to unwrap WETH into ether before depositing it to L2. Therefore this bridge adapter bridges -/// WETH to ether. The receiver on L2 must wrap the ether back into WETH. -contract OptimismL1BridgeAdapter is IBridgeAdapter { - using SafeERC20 for IERC20; - - /// @notice used when the action in the payload is invalid. - error InvalidFinalizationAction(); - - /// @notice Payload for proving a withdrawal from L2 on L1 via finalizeWithdrawERC20. - /// @param withdrawalTransaction The withdrawal transaction, see its docstring for more details. - /// @param l2OutputIndex The index of the output in the L2 block, or the dispute game index post fault proof upgrade. - /// @param outputRootProof The inclusion proof of the L2ToL1MessagePasser contract's storage root. - /// @param withdrawalProof The Merkle proof of the withdrawal key presence in the L2ToL1MessagePasser contract's state trie. - struct OptimismProveWithdrawalPayload { - Types.WithdrawalTransaction withdrawalTransaction; - uint256 l2OutputIndex; - Types.OutputRootProof outputRootProof; - bytes[] withdrawalProof; - } - - /// @notice Payload for finalizing a withdrawal from L2 on L1. - /// Note that the withdrawal must be proven first before it can be finalized. - /// @param withdrawalTransaction The withdrawal transaction, see its docstring for more details. - struct OptimismFinalizationPayload { - Types.WithdrawalTransaction withdrawalTransaction; - } - - /// @notice The action to take when finalizing a withdrawal. - /// Optimism implements two-step withdrawals, so we need to specify the action to take - /// each time the finalizeWithdrawERC20 function is called. - enum FinalizationAction { - ProveWithdrawal, - FinalizeWithdrawal - } - - /// @notice Payload for interacting with the finalizeWithdrawERC20 function. - /// Since Optimism has 2-step withdrawals, we cannot finalize and get the funds on L1 in the same transaction. - /// @param action The action to take; either ProveWithdrawal or FinalizeWithdrawal. - /// @param data The payload for the action. If ProveWithdrawal, it must be an abi-encoded OptimismProveWithdrawalPayload. - /// If FinalizeWithdrawal, it must be an abi-encoded OptimismFinalizationPayload. - struct FinalizeWithdrawERC20Payload { - FinalizationAction action; - bytes data; - } - - /// @dev Reference to the L1StandardBridge contract. Deposits to L2 go through this contract. - IL1StandardBridge internal immutable i_L1Bridge; - - /// @dev Reference to the WrappedNative contract. Optimism bridges ether directly rather than WETH, - /// so we need to unwrap WETH into ether before depositing it to L2. - IWrappedNative internal immutable i_wrappedNative; - - /// @dev Reference to the OptimismPortal contract, which is used to prove and finalize withdrawals. - IOptimismPortal internal immutable i_optimismPortal; - - /// @dev Nonce to use for L2 deposits to allow for better tracking offchain. - uint64 private s_nonce = 0; - - constructor(IL1StandardBridge l1Bridge, IWrappedNative wrappedNative, IOptimismPortal optimismPortal) { - if ( - address(l1Bridge) == address(0) || address(wrappedNative) == address(0) || address(optimismPortal) == address(0) - ) { - revert BridgeAddressCannotBeZero(); - } - i_L1Bridge = l1Bridge; - i_wrappedNative = wrappedNative; - i_optimismPortal = optimismPortal; - } - - /// @notice The WETH withdraw requires this be present otherwise withdraws will fail. - receive() external payable {} - - /// @inheritdoc IBridgeAdapter - function sendERC20( - address localToken, - address remoteToken, - address recipient, - uint256 amount, - bytes calldata /* bridgeSpecificPayload */ - ) external payable override returns (bytes memory) { - IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); - - if (msg.value != 0) { - revert MsgShouldNotContainValue(msg.value); - } - - // Extra data for the L2 deposit. - // We encode the nonce in the extra data so that we can track the L2 deposit offchain. - bytes memory extraData = abi.encode(s_nonce++); - - // If the token is the wrapped native, we unwrap it and deposit native - if (localToken == address(i_wrappedNative)) { - i_wrappedNative.withdraw(amount); - i_L1Bridge.depositETHTo{value: amount}(recipient, 0, extraData); - return extraData; - } - - // Token is a normal ERC20. - IERC20(localToken).safeApprove(address(i_L1Bridge), amount); - i_L1Bridge.depositERC20To(localToken, remoteToken, recipient, amount, 0, extraData); - - return extraData; - } - - /// @notice Bridging to Optimism is paid for with gas - /// @dev Since the gas amount charged is dynamic, the gas burn can change from block to block. - /// You should always add a buffer of at least 20% to the gas limit for your L1 to L2 transaction - /// to avoid running out of gas. - function getBridgeFeeInNative() public pure returns (uint256) { - return 0; - } - - /// @notice Prove or finalize an ERC20 withdrawal from L2. - /// The action to take is specified in the payload. See the docstring of FinalizeWithdrawERC20Payload for more details. - /// @param data The payload for the action. This is an abi.encode'd FinalizeWithdrawERC20Payload with the appropriate data. - /// @return true iff finalization is successful, and false for proving a withdrawal. If either of these fail, - /// the call to this function will revert. - function finalizeWithdrawERC20( - address /* remoteSender */, - address /* localReceiver */, - bytes calldata data - ) external override returns (bool) { - // decode the data into FinalizeWithdrawERC20Payload first and extract the action. - FinalizeWithdrawERC20Payload memory payload = abi.decode(data, (FinalizeWithdrawERC20Payload)); - if (payload.action == FinalizationAction.ProveWithdrawal) { - // The action being ProveWithdrawal indicates that this is a withdrawal proof payload. - // Decode the data into OptimismProveWithdrawalPayload and call the proveWithdrawal function. - OptimismProveWithdrawalPayload memory provePayload = abi.decode(payload.data, (OptimismProveWithdrawalPayload)); - _proveWithdrawal(provePayload); - return false; - } else if (payload.action == FinalizationAction.FinalizeWithdrawal) { - // decode the data into OptimismFinalizationPayload and call the finalizeWithdrawal function. - OptimismFinalizationPayload memory finalizePayload = abi.decode(payload.data, (OptimismFinalizationPayload)); - // NOTE: finalizing ether withdrawals will currently send ether to the receiver address as indicated by the - // withdrawal tx. However, this is problematic because we need to re-wrap it into WETH. - // However, we can't do that from within this adapter because it doesn't actually have the ether. - // So its up to the caller to rectify this by re-wrapping the ether. - _finalizeWithdrawal(finalizePayload); - return true; - } else { - revert InvalidFinalizationAction(); - } - } - - function _proveWithdrawal(OptimismProveWithdrawalPayload memory payload) internal { - // will revert if the proof is invalid or the output index is not yet included on L1. - i_optimismPortal.proveWithdrawalTransaction( - payload.withdrawalTransaction, - payload.l2OutputIndex, - payload.outputRootProof, - payload.withdrawalProof - ); - } - - function _finalizeWithdrawal(OptimismFinalizationPayload memory payload) internal { - i_optimismPortal.finalizeWithdrawalTransaction(payload.withdrawalTransaction); - } - - /// @notice returns the address of the WETH token used by this adapter. - /// @return the address of the WETH token used by this adapter. - function getWrappedNative() external view returns (address) { - return address(i_wrappedNative); - } - - /// @notice returns the address of the Optimism portal contract. - /// @return the address of the Optimism portal contract. - function getOptimismPortal() external view returns (address) { - return address(i_optimismPortal); - } - - /// @notice returns the address of the Optimism L1StandardBridge bridge contract. - /// @return the address of the Optimism L1StandardBridge bridge contract. - function getL1Bridge() external view returns (address) { - return address(i_L1Bridge); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol deleted file mode 100644 index fd1218f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/bridge-adapters/OptimismL2BridgeAdapter.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBridgeAdapter} from "../interfaces/IBridge.sol"; -import {IWrappedNative} from "../../ccip/interfaces/IWrappedNative.sol"; - -import {Lib_PredeployAddresses} from "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @dev copy/pasted from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L2/L2StandardBridge.sol#L114-L122. -/// We can't import it because of hard pin solidity version in the pragma (0.8.15). -interface IL2StandardBridge { - /// @custom:legacy - /// @notice Initiates a withdrawal from L2 to L1 to a target account on L1. - /// Note that if ETH is sent to a contract on L1 and the call fails, then that ETH will - /// be locked in the L1StandardBridge. ETH may be recoverable if the call can be - /// successfully replayed by increasing the amount of gas supplied to the call. If the - /// call will fail for any amount of gas, then the ETH will be locked permanently. - /// This function only works with OptimismMintableERC20 tokens or ether. Use the - /// `bridgeERC20To` function to bridge native L2 tokens to L1. - /// @param _l2Token Address of the L2 token to withdraw. - /// @param _to Recipient account on L1. - /// @param _amount Amount of the L2 token to withdraw. - /// @param _minGasLimit Minimum gas limit to use for the transaction. - /// @param _extraData Extra data attached to the withdrawal. - function withdrawTo( - address _l2Token, - address _to, - uint256 _amount, - uint32 _minGasLimit, - bytes calldata _extraData - ) external payable; -} - -/// @notice OptimismL2BridgeAdapter implements IBridgeAdapter for the Optimism L2<=>L1 bridge. -/// @dev We have to unwrap WETH into ether before withdrawing it to L1. Therefore this bridge adapter bridges -/// WETH to ether. The receiver on L1 must wrap the ether back into WETH. -contract OptimismL2BridgeAdapter is IBridgeAdapter { - using SafeERC20 for IERC20; - - IL2StandardBridge internal immutable i_L2Bridge = IL2StandardBridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE); - IWrappedNative internal immutable i_wrappedNative; - - // Nonce to use for L1 withdrawals to allow for better tracking offchain. - uint64 private s_nonce = 0; - - constructor(IWrappedNative wrappedNative) { - // Wrapped native can be address zero, this means that auto-wrapping is disabled. - i_wrappedNative = wrappedNative; - } - - /// @notice The WETH withdraw requires this be present otherwise withdraws will fail. - receive() external payable {} - - /// @inheritdoc IBridgeAdapter - function sendERC20( - address localToken, - address /* remoteToken */, - address recipient, - uint256 amount, - bytes calldata /* bridgeSpecificPayload */ - ) external payable override returns (bytes memory) { - if (msg.value != 0) { - revert MsgShouldNotContainValue(msg.value); - } - - IERC20(localToken).safeTransferFrom(msg.sender, address(this), amount); - - // Extra data for the L2 withdraw. - // We encode the nonce in the extra data so that we can track the L2 withdraw offchain. - bytes memory extraData = abi.encode(s_nonce++); - - // If the token is the wrapped native, we unwrap it and withdraw native - if (localToken == address(i_wrappedNative)) { - i_wrappedNative.withdraw(amount); - // XXX: Lib_PredeployAddresses.OVM_ETH is actually 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000. - // This code path still works because the L2 bridge is hardcoded to handle this specific address. - // The better approach might be to use the bridgeEthTo function, which is on the StandardBridge - // abstract contract, inherited by both L1StandardBridge and L2StandardBridge. - // This is also marked as legacy, so it might mean that this will be deprecated soon. - i_L2Bridge.withdrawTo{value: amount}(Lib_PredeployAddresses.OVM_ETH, recipient, amount, 0, extraData); - return extraData; - } - - // Token is normal ERC20 - IERC20(localToken).approve(address(i_L2Bridge), amount); - i_L2Bridge.withdrawTo(localToken, recipient, amount, 0, extraData); - return extraData; - } - - /// @notice No-op since L1 -> L2 transfers do not need finalization. - /// @return true always. - function finalizeWithdrawERC20( - address /* remoteSender */, - address /* localReceiver */, - bytes calldata /* bridgeSpecificPayload */ - ) external pure override returns (bool) { - return true; - } - - /// @notice There are no fees to bridge back to L1 - function getBridgeFeeInNative() external pure returns (uint256) { - return 0; - } - - /// @notice returns the address of the WETH token used by this adapter. - /// @return the address of the WETH token used by this adapter. - function getWrappedNative() external view returns (address) { - return address(i_wrappedNative); - } - - /// @notice returns the address of the L2 bridge used by this adapter. - /// @return the address of the L2 bridge used by this adapter. - function getL2Bridge() external view returns (address) { - return address(i_L2Bridge); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol deleted file mode 100644 index 888b487..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/encoders/OptimismL1BridgeAdapterEncoder.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OptimismL1BridgeAdapter} from "../bridge-adapters/OptimismL1BridgeAdapter.sol"; - -/// @dev to generate abi's for the OptimismL1BridgeAdapter's various payload types. -/// @dev for usage examples see core/scripts/ccip/liquiditymanager/opstack/prove_withdrawal.go -/// @dev or core/scripts/ccip/liquiditymanager/opstack/finalize.go. -abstract contract OptimismL1BridgeAdapterEncoder { - function encodeFinalizeWithdrawalERC20Payload( - OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload - ) public pure {} - - function encodeOptimismProveWithdrawalPayload( - OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload memory payload - ) public pure {} - - function encodeOptimismFinalizationPayload( - OptimismL1BridgeAdapter.OptimismFinalizationPayload memory payload - ) public pure {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol deleted file mode 100644 index 83e64ed..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/IBridge.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -/// @dev IBridgeAdapter provides a common interface to interact with the native bridge. -interface IBridgeAdapter { - error BridgeAddressCannotBeZero(); - error MsgValueDoesNotMatchAmount(uint256 msgValue, uint256 amount); - error InsufficientEthValue(uint256 wanted, uint256 got); - error MsgShouldNotContainValue(uint256 value); - - /// @notice Send the specified amount of the local token cross-chain to the remote chain. - /// The tokens on the remote chain will then be sourced from the remoteToken address. - /// The amount to be sent must be approved by the caller beforehand on the localToken contract. - /// The caller must provide the bridging fee in native currency, i.e msg.value. - /// @param localToken The address of the local ERC-20 token. - /// @param remoteToken The address of the remote ERC-20 token. - /// @param recipient The address of the recipient on the remote chain. - /// @param amount The amount of the local token to send. - /// @param bridgeSpecificPayload The payload of the cross-chain transfer. Bridge-specific. - function sendERC20( - address localToken, - address remoteToken, - address recipient, - uint256 amount, - bytes calldata bridgeSpecificPayload - ) external payable returns (bytes memory); - - /// @notice Get the bridging fee in native currency. This fee must be provided upon sending tokens via - /// the sendERC20 function. - /// @return The bridging fee in native currency. - function getBridgeFeeInNative() external view returns (uint256); - - /// @notice Finalize the withdrawal of a cross-chain transfer. - /// Not all implementations will finalize a transfer in a single call to this function. - /// Optimism, for example, requires a two-step process to finalize a transfer. The first - /// step requires proving the withdrawal that occurred on L2 on L1. The second step is then - /// the finalization, whereby funds become available to the recipient. So, in that particular - /// scenario, `false` is returned from `finalizeWithdrawERC20` when the first step is completed, - /// and `true` is returned when the second step is completed. - /// @param remoteSender The address of the sender on the remote chain. - /// @param localReceiver The address of the receiver on the local chain. - /// @param bridgeSpecificPayload The payload of the cross-chain transfer, bridge-specific, i.e a proof of some kind. - /// @return true iff the funds are available, false otherwise. - function finalizeWithdrawERC20( - address remoteSender, - address localReceiver, - bytes calldata bridgeSpecificPayload - ) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol deleted file mode 100644 index 062325d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityContainer.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -/// @notice Interface for a liquidity container, this can be a CCIP token pool. -interface ILiquidityContainer { - event LiquidityAdded(address indexed provider, uint256 indexed amount); - event LiquidityRemoved(address indexed provider, uint256 indexed amount); - - /// @notice Provide additional liquidity to the container. - /// @dev Should emit LiquidityAdded - function provideLiquidity(uint256 amount) external; - - /// @notice Withdraws liquidity from the container to the msg sender - /// @dev Should emit LiquidityRemoved - function withdrawLiquidity(uint256 amount) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol deleted file mode 100644 index 19fd101..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/ILiquidityManager.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IBridgeAdapter} from "./IBridge.sol"; - -interface ILiquidityManager { - /// @notice Parameters for sending liquidity to a remote chain. - /// @param amount The amount of tokens to be sent to the remote chain. - /// @param nativeBridgeFee The amount of native that should be sent by the liquiditymanager in the sendERC20 call. - /// Used to pay for the bridge fees. - /// @param remoteChainSelector The selector of the remote chain. - /// @param bridgeData The bridge data that should be passed to the sendERC20 call. - struct SendLiquidityParams { - uint256 amount; - uint256 nativeBridgeFee; - uint64 remoteChainSelector; - bytes bridgeData; - } - - /// @notice Parameters for receiving liquidity from a remote chain. - /// @param amount The amount of tokens to be received from the remote chain. - /// @param remoteChainSelector The selector of the remote chain. - /// @param bridgeData The bridge data that should be passed to the finalizeWithdrawERC20 call. - /// @param shouldWrapNative Whether the received native token should be wrapped into wrapped native. - /// This is needed for when the bridge being used doesn't bridge wrapped native but native directly. - struct ReceiveLiquidityParams { - uint256 amount; - uint64 remoteChainSelector; - bool shouldWrapNative; - bytes bridgeData; - } - - /// @notice Instructions for the rebalancer on what to do with the available liquidity. - /// @param sendLiquidityParams The parameters for sending liquidity to a remote chain. - /// @param receiveLiquidityParams The parameters for receiving liquidity from a remote chain. - struct LiquidityInstructions { - SendLiquidityParams[] sendLiquidityParams; - ReceiveLiquidityParams[] receiveLiquidityParams; - } - - /// @notice Parameters for adding a cross-chain rebalancer. - /// @param remoteRebalancer The address of the remote rebalancer. - /// @param localBridge The local bridge adapter address. - /// @param remoteToken The address of the remote token. - /// @param remoteChainSelector The selector of the remote chain. - /// @param enabled Whether the rebalancer is enabled. - struct CrossChainRebalancerArgs { - address remoteRebalancer; - IBridgeAdapter localBridge; - address remoteToken; - uint64 remoteChainSelector; - bool enabled; - } - - /// @notice Returns the current liquidity in the liquidity container. - /// @return currentLiquidity The current liquidity in the liquidity container. - function getLiquidity() external view returns (uint256 currentLiquidity); - - /// @notice Returns all the cross-chain rebalancers. - /// @return All the cross-chain rebalancers. - function getAllCrossChainRebalancers() external view returns (CrossChainRebalancerArgs[] memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol deleted file mode 100644 index c695729..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IAbstractArbitrumTokenGateway.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {TokenGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/TokenGateway.sol"; - -/// @dev to generate gethwrappers -abstract contract IAbstractArbitrumTokenGateway is TokenGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol deleted file mode 100644 index a5d0e5e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbRollupCore.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IRollupCore} from "@arbitrum/nitro-contracts/src/rollup/IRollupCore.sol"; - -/// @dev to generate gethwrappers -interface IArbRollupCore is IRollupCore {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol deleted file mode 100644 index 7d6afbc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbSys.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; - -/// @dev to generate gethwrappers -interface IArbSys is ArbSys {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol deleted file mode 100644 index 81fc2cb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumGatewayRouter.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; - -/// @dev to generate gethwrappers -interface IArbitrumGatewayRouter is IGatewayRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol deleted file mode 100644 index a306ef2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumInbox.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IInboxBase} from "@arbitrum/nitro-contracts/src/bridge/IInboxBase.sol"; - -/// @dev to generate gethwrappers -interface IArbitrumInbox is IInboxBase {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol deleted file mode 100644 index 49e7e45..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumL1GatewayRouter.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; - -/// @dev to generate gethwrappers -interface IArbitrumL1GatewayRouter is IL1GatewayRouter {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol deleted file mode 100644 index 0c1f228..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IArbitrumTokenGateway.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ITokenGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/ITokenGateway.sol"; - -/// @dev to generate gethwrappers -interface IArbitrumTokenGateway is ITokenGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol deleted file mode 100644 index 96a63a0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumGateway.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {L2ArbitrumGateway} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol"; - -/// @dev to generate gethwrappers -abstract contract IL2ArbitrumGateway is L2ArbitrumGateway {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol deleted file mode 100644 index 115882a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/IL2ArbitrumMessenger.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {L2ArbitrumMessenger} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol"; - -/// @dev to generate gethwrappers -abstract contract IL2ArbitrumMessenger is L2ArbitrumMessenger {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol deleted file mode 100644 index 79475cd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/arbitrum/INodeInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {NodeInterface} from "@arbitrum/nitro-contracts/src/node-interface/NodeInterface.sol"; - -/// @dev to generate gethwrappers -interface INodeInterface is NodeInterface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol deleted file mode 100644 index f0bd99f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/DisputeTypes.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/libraries/DisputeTypes.sol -pragma solidity ^0.8.0; - -/// @notice A `GameType` represents the type of game being played. -type GameType is uint32; - -/// @notice A `GameId` represents a packed 1 byte game ID, an 11 byte timestamp, and a 20 byte address. -/// @dev The packed layout of this type is as follows: -/// ┌───────────┬───────────┐ -/// │ Bits │ Value │ -/// ├───────────┼───────────┤ -/// │ [0, 8) │ Game Type │ -/// │ [8, 96) │ Timestamp │ -/// │ [96, 256) │ Address │ -/// └───────────┴───────────┘ -type GameId is bytes32; - -/// @notice A dedicated timestamp type. -type Timestamp is uint64; - -/// @notice A claim represents an MPT root representing the state of the fault proof program. -type Claim is bytes32; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol deleted file mode 100644 index 2b5cc65..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismCrossDomainMessenger.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/universal/CrossDomainMessenger.sol#L153 -pragma solidity ^0.8.0; - -interface IOptimismCrossDomainMessenger { - /// @notice Emitted whenever a message is sent to the other chain. - /// @param target Address of the recipient of the message. - /// @param sender Address of the sender of the message. - /// @param message Message to trigger the recipient address with. - /// @param messageNonce Unique nonce attached to the message. - /// @param gasLimit Minimum gas limit that the message can be executed with. - event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); - - /// @notice Relays a message that was sent by the other CrossDomainMessenger contract. Can only - /// be executed via cross-chain call from the other messenger OR if the message was - /// already received once and is currently being replayed. - /// @param _nonce Nonce of the message being relayed. - /// @param _sender Address of the user who sent the message. - /// @param _target Address that the message is targeted at. - /// @param _value ETH value to send with the message. - /// @param _minGasLimit Minimum amount of gas that the message can be executed with. - /// @param _message Message to send to the target. - function relayMessage( - uint256 _nonce, - address _sender, - address _target, - uint256 _value, - uint256 _minGasLimit, - bytes calldata _message - ) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol deleted file mode 100644 index f72e645..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismDisputeGameFactory.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol -pragma solidity ^0.8.0; - -import {GameType, GameId, Timestamp, Claim} from "./DisputeTypes.sol"; - -interface IOptimismDisputeGameFactory { - /// @notice Information about a dispute game found in a `findLatestGames` search. - struct GameSearchResult { - uint256 index; - GameId metadata; - Timestamp timestamp; - Claim rootClaim; - bytes extraData; - } - - /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than - /// `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`. - /// @param _gameType The type of game to find. - /// @param _start The index to start the reverse search from. - /// @param _n The number of games to find. - function findLatestGames( - GameType _gameType, - uint256 _start, - uint256 _n - ) external view returns (GameSearchResult[] memory games_); - - /// @notice The total number of dispute games created by this factory. - /// @return gameCount_ The total number of dispute games created by this factory. - function gameCount() external view returns (uint256 gameCount_); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol deleted file mode 100644 index 3a518fc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL1StandardBridge.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L1/L1StandardBridge.sol -pragma solidity ^0.8.0; - -interface IOptimismL1StandardBridge { - /// @custom:legacy - /// @notice Deposits some amount of ETH into a target account on L2. - /// Note that if ETH is sent to a contract on L2 and the call fails, then that ETH will - /// be locked in the L2StandardBridge. ETH may be recoverable if the call can be - /// successfully replayed by increasing the amount of gas supplied to the call. If the - /// call will fail for any amount of gas, then the ETH will be locked permanently. - /// @param _to Address of the recipient on L2. - /// @param _minGasLimit Minimum gas limit for the deposit message on L2. - /// @param _extraData Optional data to forward to L2. - /// Data supplied here will not be used to execute any code on L2 and is - /// only emitted as extra data for the convenience of off-chain tooling. - function depositETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol deleted file mode 100644 index fa36863..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2OutputOracle.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/L2OutputOracle.sol -pragma solidity ^0.8.0; - -import {Types} from "./Types.sol"; - -interface IOptimismL2OutputOracle { - /// @notice Returns the index of the L2 output that checkpoints a given L2 block number. - /// Uses a binary search to find the first output greater than or equal to the given - /// block. - /// @param _l2BlockNumber L2 block number to find a checkpoint for. - /// @return Index of the first checkpoint that commits to the given L2 block number. - function getL2OutputIndexAfter(uint256 _l2BlockNumber) external view returns (uint256); - - /// @notice Returns an output by index. Needed to return a struct instead of a tuple. - /// @param _l2OutputIndex Index of the output to return. - /// @return The output at the given index. - function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol deleted file mode 100644 index 9ac6aeb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismL2ToL1MessagePasser.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol -pragma solidity ^0.8.0; - -interface IOptimismL2ToL1MessagePasser { - /// @notice Emitted any time a withdrawal is initiated. - /// @param nonce Unique value corresponding to each withdrawal. - /// @param sender The L2 account address which initiated the withdrawal. - /// @param target The L1 account address the call will be send to. - /// @param value The ETH value submitted for withdrawal, to be forwarded to the target. - /// @param gasLimit The minimum amount of gas that must be provided when withdrawing. - /// @param data The data to be forwarded to the target on L1. - /// @param withdrawalHash The hash of the withdrawal. - event MessagePassed( - uint256 indexed nonce, - address indexed sender, - address indexed target, - uint256 value, - uint256 gasLimit, - bytes data, - bytes32 withdrawalHash - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol deleted file mode 100644 index 887025b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/OptimismPortal.sol -pragma solidity ^0.8.0; - -import {Types} from "./Types.sol"; - -interface IOptimismPortal { - /// @notice Semantic version. - function version() external view returns (string memory); - - /// @notice Proves a withdrawal transaction. - /// @param _tx Withdrawal transaction to finalize. - /// @param _l2OutputIndex L2 output index to prove against. - /// @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. - /// @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. - function proveWithdrawalTransaction( - Types.WithdrawalTransaction memory _tx, - uint256 _l2OutputIndex, - Types.OutputRootProof calldata _outputRootProof, - bytes[] calldata _withdrawalProof - ) external; - - /// @notice Finalizes a withdrawal transaction. - /// @param _tx Withdrawal transaction to finalize. - function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol deleted file mode 100644 index 165922b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismPortal2.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/L1/OptimismPortal2.sol -pragma solidity ^0.8.0; -import {GameType} from "./DisputeTypes.sol"; - -interface IOptimismPortal2 { - /// @notice The dispute game factory address. - /// @dev See https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/L1/OptimismPortal2.sol#L79. - function disputeGameFactory() external view returns (address); - /// @notice The game type that the OptimismPortal consults for output proposals. - function respectedGameType() external view returns (GameType); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol deleted file mode 100644 index 2f9ef91..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/IOptimismStandardBridge.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/f707883038d527cbf1e9f8ea513fe33255deadbc/packages/contracts-bedrock/src/universal/StandardBridge.sol#L88 -pragma solidity ^0.8.0; - -interface IOptimismStandardBridge { - /// @notice Emitted when an ERC20 bridge is finalized on this chain. - /// @param localToken Address of the ERC20 on this chain. - /// @param remoteToken Address of the ERC20 on the remote chain. - /// @param from Address of the sender. - /// @param to Address of the receiver. - /// @param amount Amount of the ERC20 sent. - /// @param extraData Extra data sent with the transaction. - event ERC20BridgeFinalized( - address indexed localToken, - address indexed remoteToken, - address indexed from, - address to, - uint256 amount, - bytes extraData - ); - - /// @notice Finalizes an ERC20 bridge on this chain. Can only be triggered by the other - /// StandardBridge contract on the remote chain. - /// @param _localToken Address of the ERC20 on this chain. - /// @param _remoteToken Address of the corresponding token on the remote chain. - /// @param _from Address of the sender. - /// @param _to Address of the receiver. - /// @param _amount Amount of the ERC20 being bridged. - /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will - /// not be triggered with this data, but it will be emitted and can be used - /// to identify the transaction. - function finalizeBridgeERC20( - address _localToken, - address _remoteToken, - address _from, - address _to, - uint256 _amount, - bytes calldata _extraData - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol deleted file mode 100644 index bd8d5d3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/interfaces/optimism/Types.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -// Copied from https://github.com/ethereum-optimism/optimism/blob/v1.7.0/packages/contracts-bedrock/src/libraries/Types.sol -pragma solidity ^0.8.0; - -/// @title Types -/// @notice Contains various types used throughout the Optimism contract system. -library Types { - /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1 - /// timestamp that the output root is posted. This timestamp is used to verify that the - /// finalization period has passed since the output root was submitted. - /// @custom:field outputRoot Hash of the L2 output. - /// @custom:field timestamp Timestamp of the L1 block that the output root was submitted in. - /// @custom:field l2BlockNumber L2 block number that the output corresponds to. - struct OutputProposal { - bytes32 outputRoot; - uint128 timestamp; - uint128 l2BlockNumber; - } - - /// @notice Struct representing the elements that are hashed together to generate an output root - /// which itself represents a snapshot of the L2 state. - /// @custom:field version Version of the output root. - /// @custom:field stateRoot Root of the state trie at the block of this output. - /// @custom:field messagePasserStorageRoot Root of the message passer storage trie. - /// @custom:field latestBlockhash Hash of the block this output was generated from. - struct OutputRootProof { - bytes32 version; - bytes32 stateRoot; - bytes32 messagePasserStorageRoot; - bytes32 latestBlockhash; - } - - /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end - /// user (as opposed to a system deposit transaction generated by the system). - /// @custom:field from Address of the sender of the transaction. - /// @custom:field to Address of the recipient of the transaction. - /// @custom:field isCreation True if the transaction is a contract creation. - /// @custom:field value Value to send to the recipient. - /// @custom:field mint Amount of ETH to mint. - /// @custom:field gasLimit Gas limit of the transaction. - /// @custom:field data Data of the transaction. - /// @custom:field l1BlockHash Hash of the block the transaction was submitted in. - /// @custom:field logIndex Index of the log in the block the transaction was submitted in. - //solhint-disable gas-struct-packing - struct UserDepositTransaction { - address from; - address to; - bool isCreation; - uint256 value; - uint256 mint; - uint64 gasLimit; - bytes data; - bytes32 l1BlockHash; - uint256 logIndex; - } - - /// @notice Struct representing a withdrawal transaction. - /// @custom:field nonce Nonce of the withdrawal transaction - /// @custom:field sender Address of the sender of the transaction. - /// @custom:field target Address of the recipient of the transaction. - /// @custom:field value Value to send to the recipient. - /// @custom:field gasLimit Gas limit of the transaction. - /// @custom:field data Data of the transaction. - struct WithdrawalTransaction { - uint256 nonce; - address sender; - address target; - uint256 value; - uint256 gasLimit; - bytes data; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol deleted file mode 100644 index 44e5d89..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Abstract.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -abstract contract OCR3Abstract is ITypeAndVersion { - // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; - - /// @notice triggers a new run of the offchain reporting protocol - /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - /// @param configDigest configDigest of this configuration - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - function setOCR3Config( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0001 << (256 - 16); // 0x000100..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @notice optionally emitted to indicate the latest configDigest and sequence number - /// for which a report was successfully transmitted. Alternatively, the contract may - /// use latestConfigDigestAndEpoch with scanLogs set to false. - event Transmitted(bytes32 configDigest, uint64 sequenceNumber); - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param rawVs ith element is the the V component of the ith signature - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol deleted file mode 100644 index 8c31ba5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/ocr/OCR3Base.sol +++ /dev/null @@ -1,280 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {OCR3Abstract} from "./OCR3Abstract.sol"; - -/// @notice Onchain verification of reports from the offchain reporting protocol -/// @dev For details on its operation, see the offchain reporting protocol design -/// doc, which refers to this contract as simply the "contract". -abstract contract OCR3Base is OwnerIsCreator, OCR3Abstract { - error InvalidConfig(string message); - error WrongMessageLength(uint256 expected, uint256 actual); - error ConfigDigestMismatch(bytes32 expected, bytes32 actual); - error ForkedChain(uint256 expected, uint256 actual); - error WrongNumberOfSignatures(); - error SignaturesOutOfRegistration(); - error UnauthorizedTransmitter(); - error UnauthorizedSigner(); - error NonUniqueSignatures(); - error OracleCannotBeZeroAddress(); - error NonIncreasingSequenceNumber(uint64 sequenceNumber, uint64 latestSequenceNumber); - - // Packing these fields used on the hot path in a ConfigInfo variable reduces the - // retrieval of all of them to a minimum number of SLOADs. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; - uint8 n; - } - - // Used for s_oracles[a].role, where a is an address, to track the purpose - // of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR3Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // Index of oracle in s_signers/s_transmitters - Role role; // Role of the address which mapped to this struct - } - - // The current config - ConfigInfo internal s_configInfo; - - // incremented each time a new config is posted. This count is incorporated - // into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - // makes it easier for offchain systems to extract config from logs. - uint32 internal s_latestConfigBlockNumber; - - uint64 internal s_latestSequenceNumber; - - // signer OR transmitter address - mapping(address signerOrTransmitter => Oracle oracle) internal s_oracles; - - // s_signers contains the signing address of each oracle - address[] internal s_signers; - - // s_transmitters contains the transmission address of each oracle, - // i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32; // word containing length of ss - - uint256 internal immutable i_chainID; - - constructor() { - i_chainID = block.chainid; - } - - // Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 numSigners, uint256 numTransmitters, uint256 f) { - if (numSigners > MAX_NUM_ORACLES) revert InvalidConfig("too many signers"); - if (f == 0) revert InvalidConfig("f must be positive"); - if (numSigners != numTransmitters) revert InvalidConfig("oracle addresses out of registration"); - if (numSigners <= 3 * f) revert InvalidConfig("faulty-oracle f too high"); - _; - } - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig encoded on-chain contract configuration - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig encoded off-chain oracle configuration - function setOCR3Config( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override checkConfigValid(signers.length, transmitters.length, f) onlyOwner { - _beforeSetConfig(onchainConfig); - uint256 oldSignerLength = s_signers.length; - for (uint256 i = 0; i < oldSignerLength; ++i) { - delete s_oracles[s_signers[i]]; - delete s_oracles[s_transmitters[i]]; - } - - uint256 newSignersLength = signers.length; - for (uint256 i = 0; i < newSignersLength; ++i) { - // add new signer/transmitter addresses - address signer = signers[i]; - if (s_oracles[signer].role != Role.Unset) revert InvalidConfig("repeated signer address"); - if (signer == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[signer] = Oracle(uint8(i), Role.Signer); - - address transmitter = transmitters[i]; - if (s_oracles[transmitter].role != Role.Unset) revert InvalidConfig("repeated transmitter address"); - if (transmitter == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[transmitter] = Oracle(uint8(i), Role.Transmitter); - } - - s_signers = signers; - s_transmitters = transmitters; - - s_configInfo.f = f; - s_configInfo.n = uint8(newSignersLength); - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - ++s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_latestSequenceNumber = 0; - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - /// @dev Hook that is run from setOCR3Config() right after validating configuration. - /// Empty by default, please provide an implementation in a child contract if you need additional configuration processing - function _beforeSetConfig(bytes memory _onchainConfig) internal virtual {} - - /// @return list of addresses permitted to transmit reports to this contract - /// @dev The list will match the order used to specify the transmitter during setConfig - function getTransmitters() external view returns (address[] memory) { - return s_transmitters; - } - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param rawVs ith element is the the V component of the ith signature - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - uint64 sequenceNumber = uint64(uint256(reportContext[1])); - if (sequenceNumber <= s_latestSequenceNumber) { - revert NonIncreasingSequenceNumber(sequenceNumber, s_latestSequenceNumber); - } - - // Scoping this reduces stack pressure and gas usage - { - _report(report, sequenceNumber); - } - - s_latestSequenceNumber = sequenceNumber; - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 24 byte padding, 8 byte sequence number - bytes32 configDigest = reportContext[0]; - ConfigInfo memory configInfo = s_configInfo; - - if (configInfo.latestConfigDigest != configDigest) { - revert ConfigDigestMismatch(configInfo.latestConfigDigest, configDigest); - } - // If the cached chainID at time of deployment doesn't match the current chainID, we reject all signed reports. - // This avoids a (rare) scenario where chain A forks into chain A and A', A' still has configDigest - // calculated from chain A and so OCR reports will be valid on both forks. - if (i_chainID != block.chainid) revert ForkedChain(i_chainID, block.chainid); - - emit Transmitted(configDigest, sequenceNumber); - - if (rs.length != configInfo.f + 1) revert WrongNumberOfSignatures(); - if (rs.length != ss.length) revert SignaturesOutOfRegistration(); - - // Scoping this reduces stack pressure and gas usage - { - Oracle memory transmitter = s_oracles[msg.sender]; - // Check that sender is authorized to report - if (!(transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index])) - revert UnauthorizedTransmitter(); - } - // Scoping this reduces stack pressure and gas usage - { - uint256 expectedDataLength = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32; // 32 bytes per entry in _ss) - if (msg.data.length != expectedDataLength) revert WrongMessageLength(expectedDataLength, msg.data.length); - } - - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - bool[MAX_NUM_ORACLES] memory signed; - - uint256 numberOfSignatures = rs.length; - for (uint256 i = 0; i < numberOfSignatures; ++i) { - // Safe from ECDSA malleability here since we check for duplicate signers. - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - // Since we disallow address(0) as a valid signer address, it can - // never have a signer role. - Oracle memory oracle = s_oracles[signer]; - if (oracle.role != Role.Signer) revert UnauthorizedSigner(); - if (signed[oracle.index]) revert NonUniqueSignatures(); - signed[oracle.index] = true; - } - } - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /// @notice gets the latest sequence number accepted by the contract - /// @return sequenceNumber the monotomically incremenenting number associated with OCR reports - function latestSequenceNumber() external view virtual returns (uint64 sequenceNumber) { - return s_latestSequenceNumber; - } - - function _report(bytes calldata report, uint64 sequenceNumber) internal virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol deleted file mode 100644 index 73c9ba7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol +++ /dev/null @@ -1,945 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityManager} from "../interfaces/ILiquidityManager.sol"; -import {IBridgeAdapter} from "../interfaces/IBridge.sol"; - -import {LockReleaseTokenPool} from "../../ccip/pools/LockReleaseTokenPool.sol"; -import {LiquidityManager} from "../LiquidityManager.sol"; -import {MockL1BridgeAdapter} from "./mocks/MockBridgeAdapter.sol"; -import {LiquidityManagerBaseTest} from "./LiquidityManagerBaseTest.t.sol"; -import {LiquidityManagerHelper} from "./helpers/LiquidityManagerHelper.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -// FOUNDRY_PROFILE=liquiditymanager forge test --match-path src/v0.8/liquiditymanager/test/LiquidityManager.t.sol - -contract LiquidityManagerSetup is LiquidityManagerBaseTest { - event FinalizationStepCompleted( - uint64 indexed ocrSeqNum, - uint64 indexed remoteChainSelector, - bytes bridgeSpecificData - ); - event LiquidityTransferred( - uint64 indexed ocrSeqNum, - uint64 indexed fromChainSelector, - uint64 indexed toChainSelector, - address to, - uint256 amount, - bytes bridgeSpecificPayload, - bytes bridgeReturnData - ); - event FinalizationFailed( - uint64 indexed ocrSeqNum, - uint64 indexed remoteChainSelector, - bytes bridgeSpecificData, - bytes reason - ); - event FinanceRoleSet(address financeRole); - event LiquidityAddedToContainer(address indexed provider, uint256 indexed amount); - event LiquidityRemovedFromContainer(address indexed remover, uint256 indexed amount); - // Liquidity container event - event LiquidityAdded(address indexed provider, uint256 indexed amount); - event LiquidityRemoved(address indexed remover, uint256 indexed amount); - - error NonceAlreadyUsed(uint256 nonce); - - LiquidityManagerHelper internal s_liquidityManager; - LockReleaseTokenPool internal s_lockReleaseTokenPool; - MockL1BridgeAdapter internal s_bridgeAdapter; - - // LiquidityManager that rebalances weth. - LiquidityManagerHelper internal s_wethRebalancer; - LockReleaseTokenPool internal s_wethLockReleaseTokenPool; - MockL1BridgeAdapter internal s_wethBridgeAdapter; - - function setUp() public virtual override { - LiquidityManagerBaseTest.setUp(); - - s_bridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); - s_lockReleaseTokenPool = new LockReleaseTokenPool(s_l1Token, new address[](0), address(1), true, address(123)); - s_liquidityManager = new LiquidityManagerHelper( - s_l1Token, - i_localChainSelector, - s_lockReleaseTokenPool, - 0, - FINANCE - ); - - s_lockReleaseTokenPool.setRebalancer(address(s_liquidityManager)); - - s_wethBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l1Weth)), true); - s_wethLockReleaseTokenPool = new LockReleaseTokenPool( - IERC20(address(s_l1Weth)), - new address[](0), - address(1), - true, - address(123) - ); - s_wethRebalancer = new LiquidityManagerHelper( - IERC20(address(s_l1Weth)), - i_localChainSelector, - s_wethLockReleaseTokenPool, - 0, - FINANCE - ); - - s_wethLockReleaseTokenPool.setRebalancer(address(s_wethRebalancer)); - } -} - -contract LiquidityManager_addLiquidity is LiquidityManagerSetup { - function test_addLiquiditySuccess() external { - address caller = STRANGER; - vm.startPrank(caller); - - uint256 amount = 12345679; - deal(address(s_l1Token), caller, amount); - - s_l1Token.approve(address(s_liquidityManager), amount); - - vm.expectEmit(); - emit LiquidityAddedToContainer(caller, amount); - - s_liquidityManager.addLiquidity(amount); - - assertEq(s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), amount); - } -} - -contract LiquidityManager_removeLiquidity is LiquidityManagerSetup { - function test_removeLiquiditySuccess() external { - uint256 amount = 12345679; - deal(address(s_l1Token), address(s_lockReleaseTokenPool), amount); - - vm.expectEmit(); - emit LiquidityRemovedFromContainer(FINANCE, amount); - - vm.startPrank(FINANCE); - s_liquidityManager.removeLiquidity(amount); - - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0); - } - - function test_InsufficientLiquidityReverts() external { - uint256 balance = 923; - uint256 requested = balance + 1; - - deal(address(s_l1Token), address(s_lockReleaseTokenPool), balance); - - vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InsufficientLiquidity.selector, requested, balance, 0)); - - vm.startPrank(FINANCE); - s_liquidityManager.removeLiquidity(requested); - } - - function test_OnlyFinanceRoleReverts() external { - vm.stopPrank(); - - vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); - - s_liquidityManager.removeLiquidity(123); - } -} - -contract LiquidityManager__report is LiquidityManagerSetup { - function test_EmptyReportReverts() external { - ILiquidityManager.LiquidityInstructions memory instructions = ILiquidityManager.LiquidityInstructions({ - sendLiquidityParams: new ILiquidityManager.SendLiquidityParams[](0), - receiveLiquidityParams: new ILiquidityManager.ReceiveLiquidityParams[](0) - }); - - vm.expectRevert(LiquidityManager.EmptyReport.selector); - - s_liquidityManager.report(abi.encode(instructions), 123); - } -} - -contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { - uint256 internal constant AMOUNT = 12345679; - - function test_rebalanceLiquiditySuccess() external { - deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); - - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(s_liquidityManager), - localBridge: s_bridgeAdapter, - remoteToken: address(s_l2Token), - remoteChainSelector: i_remoteChainSelector, - enabled: true - }); - s_liquidityManager.setCrossChainRebalancers(args); - - vm.expectEmit(); - emit Transfer(address(s_lockReleaseTokenPool), address(s_liquidityManager), AMOUNT); - - vm.expectEmit(); - emit Approval(address(s_liquidityManager), address(s_bridgeAdapter), AMOUNT); - - vm.expectEmit(); - emit Transfer(address(s_liquidityManager), address(s_bridgeAdapter), AMOUNT); - - vm.expectEmit(); - bytes memory encodedNonce = abi.encode(uint256(1)); - emit LiquidityTransferred( - type(uint64).max, - i_localChainSelector, - i_remoteChainSelector, - address(s_liquidityManager), - AMOUNT, - bytes(""), - encodedNonce - ); - - vm.startPrank(FINANCE); - s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, AMOUNT, 0, bytes("")); - - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0); - assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), AMOUNT); - assertEq(s_l1Token.allowance(address(s_liquidityManager), address(s_bridgeAdapter)), 0); - } - - /// @notice this test sets up a circular system where the liquidity container of - /// the local Liquidity manager is the bridge adapter of the remote liquidity manager - /// and the other way around for the remote liquidity manager. This allows us to - /// rebalance funds between the two liquidity managers on the same chain. - function test_rebalanceBetweenPoolsSuccess() external { - uint256 amount = 12345670; - - s_liquidityManager = new LiquidityManagerHelper(s_l1Token, i_localChainSelector, s_bridgeAdapter, 0, FINANCE); - - MockL1BridgeAdapter mockRemoteBridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); - LiquidityManager mockRemoteRebalancer = new LiquidityManager( - s_l1Token, - i_remoteChainSelector, - mockRemoteBridgeAdapter, - 0, - FINANCE - ); - - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(mockRemoteRebalancer), - localBridge: mockRemoteBridgeAdapter, - remoteToken: address(s_l1Token), - remoteChainSelector: i_remoteChainSelector, - enabled: true - }); - - s_liquidityManager.setCrossChainRebalancers(args); - - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(s_liquidityManager), - localBridge: s_bridgeAdapter, - remoteToken: address(s_l1Token), - remoteChainSelector: i_localChainSelector, - enabled: true - }); - - mockRemoteRebalancer.setCrossChainRebalancers(args); - - deal(address(s_l1Token), address(s_bridgeAdapter), amount); - - vm.startPrank(FINANCE); - s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, amount, 0, bytes("")); - - assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), 0); - assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), amount); - assertEq(s_l1Token.allowance(address(s_liquidityManager), address(s_bridgeAdapter)), 0); - - // attach a bridge fee and see the relevant adapter's ether balance change. - // the bridge fee is sent along with the sendERC20 call. - uint256 bridgeFee = 123; - vm.deal(address(mockRemoteRebalancer), bridgeFee); - mockRemoteRebalancer.rebalanceLiquidity(i_localChainSelector, amount, bridgeFee, bytes("")); - - assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), amount); - assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), 0); - assertEq(address(s_bridgeAdapter).balance, bridgeFee); - - // Assert partial rebalancing works correctly - s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, amount / 2, 0, bytes("")); - - assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), amount / 2); - assertEq(s_l1Token.balanceOf(address(mockRemoteBridgeAdapter)), amount / 2); - } - - function test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() external { - // set up a rebalancer on another chain, an "L2". - // note we use the L1 bridge adapter because it has the reverting logic - // when finalization is already done. - MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); - LockReleaseTokenPool remotePool = new LockReleaseTokenPool( - s_l2Token, - new address[](0), - address(1), - true, - address(123) - ); - LiquidityManager remoteRebalancer = new LiquidityManager(s_l2Token, i_remoteChainSelector, remotePool, 0, FINANCE); - - // set rebalancer role on the pool. - remotePool.setRebalancer(address(remoteRebalancer)); - - // set up the cross chain rebalancer on "L1". - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(remoteRebalancer), - localBridge: s_bridgeAdapter, - remoteToken: address(s_l2Token), - remoteChainSelector: i_remoteChainSelector, - enabled: true - }); - - s_liquidityManager.setCrossChainRebalancers(args); - - // set up the cross chain rebalancer on "L2". - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(s_liquidityManager), - localBridge: remoteBridgeAdapter, - remoteToken: address(s_l1Token), - remoteChainSelector: i_localChainSelector, - enabled: true - }); - - remoteRebalancer.setCrossChainRebalancers(args); - - // deal some L1 tokens to the L1 bridge adapter so that it can send them to the rebalancer - // when the withdrawal gets finalized. - deal(address(s_l1Token), address(s_bridgeAdapter), AMOUNT); - // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. - deal(address(s_l2Token), address(remotePool), AMOUNT); - - uint256 nonce = 1; - uint64 maxSeqNum = type(uint64).max; - bytes memory bridgeSendReturnData = abi.encode(nonce); - bytes memory bridgeSpecificPayload = bytes(""); - vm.expectEmit(); - emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_liquidityManager), - AMOUNT, - bridgeSpecificPayload, - bridgeSendReturnData - ); - vm.startPrank(FINANCE); - remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); - - // available liquidity has been moved to the remote bridge adapter from the token pool. - assertEq(s_l2Token.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); - assertEq(s_l2Token.balanceOf(address(remotePool)), 0, "remotePool balance"); - - // prove and finalize manually on the L1 bridge adapter. - // this should transfer the funds to the rebalancer. - MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); - MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, - data: abi.encode(provePayload) - }); - bool fundsAvailable = s_bridgeAdapter.finalizeWithdrawERC20( - address(0), - address(s_liquidityManager), - abi.encode(payload) - ); - assertFalse(fundsAvailable, "fundsAvailable must be false"); - MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ - nonce: nonce, - amount: AMOUNT - }); - payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, - data: abi.encode(finalizePayload) - }); - fundsAvailable = s_bridgeAdapter.finalizeWithdrawERC20( - address(0), - address(s_liquidityManager), - abi.encode(payload) - ); - assertTrue(fundsAvailable, "fundsAvailable must be true"); - - // available balance on the L1 bridge adapter has been moved to the rebalancer. - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), AMOUNT, "rebalancer balance 1"); - assertEq(s_l1Token.balanceOf(address(s_bridgeAdapter)), 0, "bridgeAdapter balance"); - - // try to finalize on L1 again - // bytes memory revertData = abi.encodeWithSelector(NonceAlreadyUsed.selector, nonce); - vm.expectEmit(); - emit FinalizationFailed( - maxSeqNum, - i_remoteChainSelector, - abi.encode(payload), - abi.encodeWithSelector(NonceAlreadyUsed.selector, nonce) - ); - vm.expectEmit(); - emit LiquidityAdded(address(s_liquidityManager), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_liquidityManager), - AMOUNT, - abi.encode(payload), - bytes("") - ); - s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); - - // available balance on the rebalancer has been injected into the token pool. - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 2"); - assertEq(s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), AMOUNT, "lockReleaseTokenPool balance"); - } - - function test_rebalanceBetweenPools_MultiStageFinalization() external { - // set up a rebalancer on another chain, an "L2". - // note we use the L1 bridge adapter because it has the reverting logic - // when finalization is already done. - MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); - LockReleaseTokenPool remotePool = new LockReleaseTokenPool( - s_l2Token, - new address[](0), - address(1), - true, - address(123) - ); - LiquidityManager remoteRebalancer = new LiquidityManager(s_l2Token, i_remoteChainSelector, remotePool, 0, FINANCE); - - // set rebalancer role on the pool. - remotePool.setRebalancer(address(remoteRebalancer)); - - // set up the cross chain rebalancer on "L1". - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(remoteRebalancer), - localBridge: s_bridgeAdapter, - remoteToken: address(s_l2Token), - remoteChainSelector: i_remoteChainSelector, - enabled: true - }); - - s_liquidityManager.setCrossChainRebalancers(args); - - // set up the cross chain rebalancer on "L2". - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(s_liquidityManager), - localBridge: remoteBridgeAdapter, - remoteToken: address(s_l1Token), - remoteChainSelector: i_localChainSelector, - enabled: true - }); - - remoteRebalancer.setCrossChainRebalancers(args); - - // deal some L1 tokens to the L1 bridge adapter so that it can send them to the rebalancer - // when the withdrawal gets finalized. - deal(address(s_l1Token), address(s_bridgeAdapter), AMOUNT); - // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. - deal(address(s_l2Token), address(remotePool), AMOUNT); - - // initiate a send from remote rebalancer to s_liquidityManager. - uint256 nonce = 1; - uint64 maxSeqNum = type(uint64).max; - bytes memory bridgeSendReturnData = abi.encode(nonce); - bytes memory bridgeSpecificPayload = bytes(""); - vm.expectEmit(); - emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_liquidityManager), - AMOUNT, - bridgeSpecificPayload, - bridgeSendReturnData - ); - vm.startPrank(FINANCE); - remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); - - // available liquidity has been moved to the remote bridge adapter from the token pool. - assertEq(s_l2Token.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); - assertEq(s_l2Token.balanceOf(address(remotePool)), 0, "remotePool balance"); - - // prove withdrawal on the L1 bridge adapter, through the rebalancer. - uint256 balanceBeforeProve = s_l1Token.balanceOf(address(s_lockReleaseTokenPool)); - MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); - MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, - data: abi.encode(provePayload) - }); - vm.expectEmit(); - emit FinalizationStepCompleted(maxSeqNum, i_remoteChainSelector, abi.encode(payload)); - s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); - - // s_liquidityManager should have no tokens. - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 1"); - // balance of s_lockReleaseTokenPool should be unchanged since no liquidity got added yet. - assertEq( - s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), - balanceBeforeProve, - "s_lockReleaseTokenPool balance should be unchanged" - ); - - // finalize withdrawal on the L1 bridge adapter, through the rebalancer. - MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ - nonce: nonce, - amount: AMOUNT - }); - payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, - data: abi.encode(finalizePayload) - }); - vm.expectEmit(); - emit LiquidityAdded(address(s_liquidityManager), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_liquidityManager), - AMOUNT, - abi.encode(payload), - bytes("") - ); - s_liquidityManager.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); - - // s_liquidityManager should have no tokens. - assertEq(s_l1Token.balanceOf(address(s_liquidityManager)), 0, "rebalancer balance 2"); - // balance of s_lockReleaseTokenPool should be updated - assertEq( - s_l1Token.balanceOf(address(s_lockReleaseTokenPool)), - balanceBeforeProve + AMOUNT, - "s_lockReleaseTokenPool balance should be updated" - ); - } - - function test_rebalanceBetweenPools_NativeRewrap() external { - // set up a rebalancer similar to the above on another chain, an "L2". - MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l2Weth)), true); - LockReleaseTokenPool remotePool = new LockReleaseTokenPool( - IERC20(address(s_l2Weth)), - new address[](0), - address(1), - true, - address(123) - ); - LiquidityManager remoteRebalancer = new LiquidityManager( - IERC20(address(s_l2Weth)), - i_remoteChainSelector, - remotePool, - 0, - FINANCE - ); - - // set rebalancer role on the pool. - remotePool.setRebalancer(address(remoteRebalancer)); - - // set up the cross chain rebalancer on "L1". - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(remoteRebalancer), - localBridge: s_wethBridgeAdapter, - remoteToken: address(s_l2Weth), - remoteChainSelector: i_remoteChainSelector, - enabled: true - }); - - s_wethRebalancer.setCrossChainRebalancers(args); - - // set up the cross chain rebalancer on "L2". - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(s_wethRebalancer), - localBridge: remoteBridgeAdapter, - remoteToken: address(s_l1Weth), - remoteChainSelector: i_localChainSelector, - enabled: true - }); - - remoteRebalancer.setCrossChainRebalancers(args); - - // deal some ether to the L1 bridge adapter so that it can send them to the rebalancer - // when the withdrawal gets finalized. - vm.deal(address(s_wethBridgeAdapter), AMOUNT); - // deal some L2 tokens to the remote token pool so that we can withdraw it when we rebalance. - deal(address(s_l2Weth), address(remotePool), AMOUNT); - // deposit some eth to the weth contract on L2 from the remote bridge adapter - // so that the withdraw() call succeeds. - vm.deal(address(remoteBridgeAdapter), AMOUNT); - vm.startPrank(address(remoteBridgeAdapter)); - s_l2Weth.deposit{value: AMOUNT}(); - vm.stopPrank(); - - // switch to finance for the rest of the test to avoid reverts. - vm.startPrank(FINANCE); - - // initiate a send from remote rebalancer to s_wethRebalancer. - uint256 nonce = 1; - uint64 maxSeqNum = type(uint64).max; - bytes memory bridgeSendReturnData = abi.encode(nonce); - bytes memory bridgeSpecificPayload = bytes(""); - vm.expectEmit(); - emit LiquidityRemoved(address(remoteRebalancer), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_wethRebalancer), - AMOUNT, - bridgeSpecificPayload, - bridgeSendReturnData - ); - remoteRebalancer.rebalanceLiquidity(i_localChainSelector, AMOUNT, 0, bridgeSpecificPayload); - - // available liquidity has been moved to the remote bridge adapter from the token pool. - assertEq(s_l2Weth.balanceOf(address(remoteBridgeAdapter)), AMOUNT, "remoteBridgeAdapter balance"); - assertEq(s_l2Weth.balanceOf(address(remotePool)), 0, "remotePool balance"); - - // prove withdrawal on the L1 bridge adapter, through the rebalancer. - uint256 balanceBeforeProve = s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)); - MockL1BridgeAdapter.ProvePayload memory provePayload = MockL1BridgeAdapter.ProvePayload({nonce: nonce}); - MockL1BridgeAdapter.Payload memory payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.ProveWithdrawal, - data: abi.encode(provePayload) - }); - vm.expectEmit(); - emit FinalizationStepCompleted(maxSeqNum, i_remoteChainSelector, abi.encode(payload)); - s_wethRebalancer.receiveLiquidity(i_remoteChainSelector, AMOUNT, false, abi.encode(payload)); - - // s_wethRebalancer should have no tokens. - assertEq(s_l1Weth.balanceOf(address(s_wethRebalancer)), 0, "rebalancer balance 1"); - // balance of s_wethLockReleaseTokenPool should be unchanged since no liquidity got added yet. - assertEq( - s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)), - balanceBeforeProve, - "s_wethLockReleaseTokenPool balance should be unchanged" - ); - - // finalize withdrawal on the L1 bridge adapter, through the rebalancer. - MockL1BridgeAdapter.FinalizePayload memory finalizePayload = MockL1BridgeAdapter.FinalizePayload({ - nonce: nonce, - amount: AMOUNT - }); - payload = MockL1BridgeAdapter.Payload({ - action: MockL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal, - data: abi.encode(finalizePayload) - }); - vm.expectEmit(); - emit LiquidityAdded(address(s_wethRebalancer), AMOUNT); - vm.expectEmit(); - emit LiquidityTransferred( - maxSeqNum, - i_remoteChainSelector, - i_localChainSelector, - address(s_wethRebalancer), - AMOUNT, - abi.encode(payload), - bytes("") - ); - s_wethRebalancer.receiveLiquidity(i_remoteChainSelector, AMOUNT, true, abi.encode(payload)); - - // s_wethRebalancer should have no tokens. - assertEq(s_l1Weth.balanceOf(address(s_wethRebalancer)), 0, "rebalancer balance 2"); - // s_wethRebalancer should have no native tokens. - assertEq(address(s_wethRebalancer).balance, 0, "rebalancer native balance should be zero"); - // balance of s_wethLockReleaseTokenPool should be updated - assertEq( - s_l1Weth.balanceOf(address(s_wethLockReleaseTokenPool)), - balanceBeforeProve + AMOUNT, - "s_wethLockReleaseTokenPool balance should be updated" - ); - } - - // Reverts - - function test_InsufficientLiquidityReverts() external { - s_liquidityManager.setMinimumLiquidity(3); - deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); - vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InsufficientLiquidity.selector, AMOUNT, AMOUNT, 3)); - - vm.startPrank(FINANCE); - s_liquidityManager.rebalanceLiquidity(0, AMOUNT, 0, bytes("")); - } - - function test_InvalidRemoteChainReverts() external { - deal(address(s_l1Token), address(s_lockReleaseTokenPool), AMOUNT); - - vm.expectRevert(abi.encodeWithSelector(LiquidityManager.InvalidRemoteChain.selector, i_remoteChainSelector)); - - vm.startPrank(FINANCE); - s_liquidityManager.rebalanceLiquidity(i_remoteChainSelector, AMOUNT, 0, bytes("")); - } -} - -contract LiquidityManager_setCrossChainRebalancer is LiquidityManagerSetup { - event CrossChainRebalancerSet( - uint64 indexed remoteChainSelector, - IBridgeAdapter localBridge, - address remoteToken, - address remoteRebalancer, - bool enabled - ); - - function test_setCrossChainRebalancerSuccess() external { - address newRebalancer = address(23892423); - uint64 remoteChainSelector = 12301293; - - uint64[] memory supportedChains = s_liquidityManager.getSupportedDestChains(); - assertEq(supportedChains.length, 0); - - LiquidityManager.CrossChainRebalancerArgs[] memory args = new LiquidityManager.CrossChainRebalancerArgs[](1); - args[0] = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: newRebalancer, - localBridge: s_bridgeAdapter, - remoteToken: address(190490124908), - remoteChainSelector: remoteChainSelector, - enabled: true - }); - - vm.expectEmit(); - emit CrossChainRebalancerSet( - remoteChainSelector, - args[0].localBridge, - args[0].remoteToken, - newRebalancer, - args[0].enabled - ); - - s_liquidityManager.setCrossChainRebalancers(args); - - assertEq(s_liquidityManager.getCrossChainRebalancer(remoteChainSelector).remoteRebalancer, newRebalancer); - - LiquidityManager.CrossChainRebalancerArgs[] memory got = s_liquidityManager.getAllCrossChainRebalancers(); - assertEq(got.length, 1); - assertEq(got[0].remoteRebalancer, args[0].remoteRebalancer); - assertEq(address(got[0].localBridge), address(args[0].localBridge)); - assertEq(got[0].remoteToken, args[0].remoteToken); - assertEq(got[0].remoteChainSelector, args[0].remoteChainSelector); - assertEq(got[0].enabled, args[0].enabled); - - supportedChains = s_liquidityManager.getSupportedDestChains(); - assertEq(supportedChains.length, 1); - assertEq(supportedChains[0], remoteChainSelector); - - address anotherRebalancer = address(123); - args[0].remoteRebalancer = anotherRebalancer; - - vm.expectEmit(); - emit CrossChainRebalancerSet( - remoteChainSelector, - args[0].localBridge, - args[0].remoteToken, - anotherRebalancer, - args[0].enabled - ); - - s_liquidityManager.setCrossChainRebalancer(args[0]); - - assertEq(s_liquidityManager.getCrossChainRebalancer(remoteChainSelector).remoteRebalancer, anotherRebalancer); - - supportedChains = s_liquidityManager.getSupportedDestChains(); - assertEq(supportedChains.length, 1); - assertEq(supportedChains[0], remoteChainSelector); - } - - function test_ZeroChainSelectorReverts() external { - LiquidityManager.CrossChainRebalancerArgs memory arg = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(9), - localBridge: s_bridgeAdapter, - remoteToken: address(190490124908), - remoteChainSelector: 0, - enabled: true - }); - - vm.expectRevert(LiquidityManager.ZeroChainSelector.selector); - - s_liquidityManager.setCrossChainRebalancer(arg); - } - - function test_ZeroAddressReverts() external { - LiquidityManager.CrossChainRebalancerArgs memory arg = ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(0), - localBridge: s_bridgeAdapter, - remoteToken: address(190490124908), - remoteChainSelector: 123, - enabled: true - }); - - vm.expectRevert(LiquidityManager.ZeroAddress.selector); - - s_liquidityManager.setCrossChainRebalancer(arg); - - arg.remoteRebalancer = address(9); - arg.localBridge = IBridgeAdapter(address(0)); - - vm.expectRevert(LiquidityManager.ZeroAddress.selector); - - s_liquidityManager.setCrossChainRebalancer(arg); - - arg.localBridge = s_bridgeAdapter; - arg.remoteToken = address(0); - - vm.expectRevert(LiquidityManager.ZeroAddress.selector); - - s_liquidityManager.setCrossChainRebalancer(arg); - } - - function test_OnlyOwnerReverts() external { - vm.stopPrank(); - - vm.expectRevert("Only callable by owner"); - - // Test the entrypoint that takes a list - s_liquidityManager.setCrossChainRebalancers(new LiquidityManager.CrossChainRebalancerArgs[](0)); - - vm.expectRevert("Only callable by owner"); - - // Test the entrypoint that takes a single item - s_liquidityManager.setCrossChainRebalancer( - ILiquidityManager.CrossChainRebalancerArgs({ - remoteRebalancer: address(9), - localBridge: s_bridgeAdapter, - remoteToken: address(190490124908), - remoteChainSelector: 124, - enabled: true - }) - ); - } -} - -contract LiquidityManager_setLocalLiquidityContainer is LiquidityManagerSetup { - event LiquidityContainerSet(address indexed newLiquidityContainer); - - function test_setLocalLiquidityContainerSuccess() external { - LockReleaseTokenPool newPool = new LockReleaseTokenPool( - s_l1Token, - new address[](0), - address(1), - true, - address(123) - ); - - vm.expectEmit(); - emit LiquidityContainerSet(address(newPool)); - - s_liquidityManager.setLocalLiquidityContainer(newPool); - - assertEq(s_liquidityManager.getLocalLiquidityContainer(), address(newPool)); - } - - function test_OnlyOwnerReverts() external { - vm.stopPrank(); - - vm.expectRevert("Only callable by owner"); - - s_liquidityManager.setLocalLiquidityContainer(LockReleaseTokenPool(address(1))); - } - - function test_ReverstWhen_CalledWithTheZeroAddress() external { - vm.expectRevert(LiquidityManager.ZeroAddress.selector); - s_liquidityManager.setLocalLiquidityContainer(LockReleaseTokenPool(address(0))); - } -} - -contract LiquidityManager_setMinimumLiquidity is LiquidityManagerSetup { - event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); - - function test_setMinimumLiquiditySuccess() external { - vm.expectEmit(); - emit MinimumLiquiditySet(uint256(0), uint256(1000)); - s_liquidityManager.setMinimumLiquidity(1000); - assertEq(s_liquidityManager.getMinimumLiquidity(), uint256(1000)); - } - - function test_OnlyOwnerReverts() external { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_liquidityManager.setMinimumLiquidity(uint256(1000)); - } -} - -contract LiquidityManager_setFinanceRole is LiquidityManagerSetup { - event MinimumLiquiditySet(uint256 oldBalance, uint256 newBalance); - - function test_setFinanceRoleSuccess() external { - vm.expectEmit(); - address newFinanceRole = makeAddr("newFinanceRole"); - assertEq(s_liquidityManager.getFinanceRole(), FINANCE); - emit FinanceRoleSet(newFinanceRole); - s_liquidityManager.setFinanceRole(newFinanceRole); - assertEq(s_liquidityManager.getFinanceRole(), newFinanceRole); - } - - function test_OnlyOwnerReverts() external { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - s_liquidityManager.setFinanceRole(address(1)); - } -} - -contract LiquidityManager_withdrawNative is LiquidityManagerSetup { - event NativeWithdrawn(uint256 amount, address destination); - - address private receiver = makeAddr("receiver"); - - function setUp() public override { - super.setUp(); - vm.deal(address(s_liquidityManager), 1); - } - - function test_withdrawNative_success() external { - assertEq(receiver.balance, 0); - vm.expectEmit(); - emit NativeWithdrawn(1, receiver); - vm.startPrank(FINANCE); - s_liquidityManager.withdrawNative(1, payable(receiver)); - assertEq(receiver.balance, 1); - } - - function test_OnlyFinanceRoleReverts() external { - vm.stopPrank(); - vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); - s_liquidityManager.withdrawNative(1, payable(receiver)); - } -} - -contract LiquidityManager_receive is LiquidityManagerSetup { - event NativeDeposited(uint256 amount, address depositor); - - address private depositor = makeAddr("depositor"); - - function test_receive_success() external { - vm.deal(depositor, 100); - uint256 before = address(s_liquidityManager).balance; - vm.expectEmit(); - emit NativeDeposited(100, depositor); - vm.startPrank(depositor); - payable(address(s_liquidityManager)).transfer(100); - assertEq(address(s_liquidityManager).balance, before + 100); - } -} - -contract LiquidityManager_withdrawERC20 is LiquidityManagerSetup { - function test_withdrawERC20Success() external { - uint256 amount = 100; - deal(address(s_otherToken), address(s_liquidityManager), amount); - assertEq(s_otherToken.balanceOf(address(1)), 0); - assertEq(s_otherToken.balanceOf(address(s_liquidityManager)), amount); - vm.startPrank(FINANCE); - s_liquidityManager.withdrawERC20(address(s_otherToken), amount, address(1)); - assertEq(s_otherToken.balanceOf(address(1)), amount); - assertEq(s_otherToken.balanceOf(address(s_liquidityManager)), 0); - } - - function test_withdrawERC20Reverts() external { - uint256 amount = 100; - deal(address(s_otherToken), address(s_liquidityManager), amount); - vm.startPrank(STRANGER); - vm.expectRevert(LiquidityManager.OnlyFinanceRole.selector); - s_liquidityManager.withdrawERC20(address(s_otherToken), amount, address(1)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol deleted file mode 100644 index 128a03f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Test} from "forge-std/Test.sol"; - -import {WETH9} from "../../ccip/test/WETH9.sol"; - -import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract LiquidityManagerBaseTest is Test { - // ERC20 events - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); - - IERC20 internal s_l1Token; - IERC20 internal s_l2Token; - IERC20 internal s_otherToken; - WETH9 internal s_l1Weth; - WETH9 internal s_l2Weth; - - uint64 internal immutable i_localChainSelector = 1234; - uint64 internal immutable i_remoteChainSelector = 9876; - - address internal constant FINANCE = address(0x00000fffffffffffffffffffff); - address internal constant OWNER = address(0x00000078772732723782873283); - address internal constant STRANGER = address(0x00000999999911111111222222); - - function setUp() public virtual { - s_l1Token = new ERC20("l1", "L1"); - s_l2Token = new ERC20("l2", "L2"); - s_otherToken = new ERC20("other", "OTHER"); - - s_l1Weth = new WETH9(); - s_l2Weth = new WETH9(); - - vm.startPrank(OWNER); - - vm.label(FINANCE, "FINANCE"); - vm.label(OWNER, "OWNER"); - vm.label(STRANGER, "STRANGER"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol deleted file mode 100644 index 8afea2d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL1BridgeAdapter.t.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; - -import {ArbitrumL1BridgeAdapter, IOutbox} from "../../bridge-adapters/ArbitrumL1BridgeAdapter.sol"; -import "forge-std/Test.sol"; - -import {IL1GatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/ethereum/gateway/IL1GatewayRouter.sol"; -import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -//contract ArbitrumL1BridgeAdapterSetup is Test { -// uint256 internal mainnetFork; -// uint256 internal arbitrumFork; -// -// string internal constant MAINNET_RPC_URL = ""; -// -// address internal constant L1_GATEWAY_ROUTER = 0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef; -// address internal constant L1_ERC20_GATEWAY = 0xa3A7B6F88361F48403514059F1F16C8E78d60EeC; -// address internal constant L1_INBOX = 0x4Dbd4fc535Ac27206064B68FfCf827b0A60BAB3f; -// // inbox 0x5aED5f8A1e3607476F1f81c3d8fe126deB0aFE94? -// address internal constant L1_OUTBOX = 0x0B9857ae2D4A3DBe74ffE1d7DF045bb7F96E4840; -// -// IERC20 internal constant L1_LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); -// IWrappedNative internal constant L1_WRAPPED_NATIVE = IWrappedNative(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); -// -// address internal constant L2_GATEWAY_ROUTER = 0x5288c571Fd7aD117beA99bF60FE0846C4E84F933; -// address internal constant L2_ETH_WITHDRAWAL_PRECOMPILE = 0x0000000000000000000000000000000000000064; -// -// IERC20 internal constant L2_LINK = IERC20(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4); -// IWrappedNative internal constant L2_WRAPPED_NATIVE = IWrappedNative(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); -// -// ArbitrumL1BridgeAdapter internal s_l1BridgeAdapter; -// -// uint256 internal constant TOKEN_BALANCE = 10e18; -// address internal constant OWNER = address(0xdead); -// -// function setUp() public { -// vm.startPrank(OWNER); -// -// mainnetFork = vm.createFork(MAINNET_RPC_URL); -// vm.selectFork(mainnetFork); -// -// s_l1BridgeAdapter = new ArbitrumL1BridgeAdapter( -// IL1GatewayRouter(L1_GATEWAY_ROUTER), -// IOutbox(L1_OUTBOX), -// L1_ERC20_GATEWAY -// ); -// -// deal(address(L1_LINK), OWNER, TOKEN_BALANCE); -// deal(address(L1_WRAPPED_NATIVE), OWNER, TOKEN_BALANCE); -// -// vm.label(OWNER, "Owner"); -// vm.label(L1_GATEWAY_ROUTER, "L1GatewayRouter"); -// vm.label(L1_ERC20_GATEWAY, "L1 ERC20 Gateway"); -// } -//} -// -//contract ArbitrumL1BridgeAdapter_sendERC20 is ArbitrumL1BridgeAdapterSetup { -// event TransferRouted(address indexed token, address indexed _userFrom, address indexed _userTo, address gateway); -// -// function test_sendERC20Success() public { -// L1_LINK.approve(address(s_l1BridgeAdapter), TOKEN_BALANCE); -// -// vm.expectEmit(); -// emit TransferRouted(address(L1_LINK), address(s_l1BridgeAdapter), OWNER, L1_ERC20_GATEWAY); -// -// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * -// s_l1BridgeAdapter.GAS_PRICE_BID() + -// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); -// -// s_l1BridgeAdapter.sendERC20{value: expectedCost}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); -// } -// -// function test_BridgeFeeTooLowReverts() public { -// L1_LINK.approve(address(s_l1BridgeAdapter), TOKEN_BALANCE); -// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * -// s_l1BridgeAdapter.GAS_PRICE_BID() + -// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); -// -// vm.expectRevert( -// abi.encodeWithSelector(ArbitrumL1BridgeAdapter.InsufficientEthValue.selector, expectedCost, expectedCost - 1) -// ); -// -// s_l1BridgeAdapter.sendERC20{value: expectedCost - 1}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); -// } -// -// function test_noApprovalReverts() public { -// uint256 expectedCost = s_l1BridgeAdapter.MAX_GAS() * -// s_l1BridgeAdapter.GAS_PRICE_BID() + -// s_l1BridgeAdapter.MAX_SUBMISSION_COST(); -// -// vm.expectRevert("SafeERC20: low-level call failed"); -// -// s_l1BridgeAdapter.sendERC20{value: expectedCost}(address(L1_LINK), OWNER, OWNER, TOKEN_BALANCE); -// } -//} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol deleted file mode 100644 index e34ff04..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/ArbitrumL2BridgeAdapter.t.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; - -import {ArbitrumL2BridgeAdapter, IL2GatewayRouter} from "../../bridge-adapters/ArbitrumL2BridgeAdapter.sol"; -import "forge-std/Test.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -//contract ArbitrumL2BridgeAdapterSetup is Test { -// uint256 internal arbitrumFork; -// -// string internal constant ARBITRUM_RPC_URL = ""; -// -// address internal constant L2_GATEWAY_ROUTER = 0x5288c571Fd7aD117beA99bF60FE0846C4E84F933; -// address internal constant L2_ETH_WITHDRAWAL_PRECOMPILE = 0x0000000000000000000000000000000000000064; -// -// IERC20 internal constant L1_LINK = IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); -// IERC20 internal constant L2_LINK = IERC20(0xf97f4df75117a78c1A5a0DBb814Af92458539FB4); -// IWrappedNative internal constant L2_WRAPPED_NATIVE = IWrappedNative(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); -// -// uint256 internal constant TOKEN_BALANCE = 10e18; -// address internal constant OWNER = address(0xdead); -// -// ArbitrumL2BridgeAdapter internal s_l2BridgeAdapter; -// -// function setUp() public { -// vm.startPrank(OWNER); -// -// arbitrumFork = vm.createFork(ARBITRUM_RPC_URL); -// -// vm.selectFork(arbitrumFork); -// s_l2BridgeAdapter = new ArbitrumL2BridgeAdapter(IL2GatewayRouter(L2_GATEWAY_ROUTER)); -// deal(address(L2_LINK), OWNER, TOKEN_BALANCE); -// deal(address(L2_WRAPPED_NATIVE), OWNER, TOKEN_BALANCE); -// -// vm.label(OWNER, "Owner"); -// vm.label(L2_GATEWAY_ROUTER, "L2GatewayRouterProxy"); -// vm.label(0xe80eb0238029333e368e0bDDB7acDf1b9cb28278, "L2GatewayRouter"); -// vm.label(L2_ETH_WITHDRAWAL_PRECOMPILE, "Precompile: ArbSys"); -// } -//} -// -//contract ArbitrumL2BridgeAdapter_sendERC20 is ArbitrumL2BridgeAdapterSetup { -// function test_sendERC20Success() public { -// L2_LINK.approve(address(s_l2BridgeAdapter), TOKEN_BALANCE); -// -// s_l2BridgeAdapter.sendERC20(address(L1_LINK), address(L2_LINK), OWNER, TOKEN_BALANCE); -// } -//} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol deleted file mode 100644 index cface1d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/bridge-adapters/OptimismL1BridgeAdapter.t.sol +++ /dev/null @@ -1,129 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import "forge-std/Test.sol"; - -import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; -import {WETH9} from "../../../ccip/test/WETH9.sol"; -import {OptimismL1BridgeAdapter} from "../../bridge-adapters/OptimismL1BridgeAdapter.sol"; -import {Types} from "../../interfaces/optimism/Types.sol"; -import {IOptimismPortal} from "../../interfaces/optimism/IOptimismPortal.sol"; - -import {IL1StandardBridge} from "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract OptimismL1BridgeAdapterSetup is Test { - // addresses below are fake - address internal constant L1_STANDARD_BRIDGE = address(1234); - address internal constant OP_PORTAL = address(4567); - address internal constant OWNER = address(0xdead); - - OptimismL1BridgeAdapter internal s_adapter; - - function setUp() public { - vm.startPrank(OWNER); - - // deploy wrapped native - WETH9 weth = new WETH9(); - - // deploy bridge adapter - s_adapter = new OptimismL1BridgeAdapter( - IL1StandardBridge(L1_STANDARD_BRIDGE), - IWrappedNative(address(weth)), - IOptimismPortal(OP_PORTAL) - ); - } -} - -contract OptimismL1BridgeAdapter_finalizeWithdrawERC20 is OptimismL1BridgeAdapterSetup { - function testfinalizeWithdrawERC20proveWithdrawalSuccess() public { - // prepare payload - OptimismL1BridgeAdapter.OptimismProveWithdrawalPayload memory provePayload = OptimismL1BridgeAdapter - .OptimismProveWithdrawalPayload({ - withdrawalTransaction: Types.WithdrawalTransaction({ - nonce: 1, - sender: address(0xdead), - target: address(0xbeef), - value: 1234, - gasLimit: 4567, - data: hex"deadbeef" - }), - l2OutputIndex: 1234, - outputRootProof: Types.OutputRootProof({ - version: bytes32(0), - stateRoot: bytes32(uint256(500)), - messagePasserStorageRoot: bytes32(uint256(600)), - latestBlockhash: bytes32(uint256(700)) - }), - withdrawalProof: new bytes[](0) - }); - OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload; - payload.action = OptimismL1BridgeAdapter.FinalizationAction.ProveWithdrawal; - payload.data = abi.encode(provePayload); - - bytes memory encodedPayload = abi.encode(payload); - - // mock out call to optimism portal - vm.mockCall( - OP_PORTAL, - abi.encodeWithSelector( - IOptimismPortal.proveWithdrawalTransaction.selector, - provePayload.withdrawalTransaction, - provePayload.l2OutputIndex, - provePayload.outputRootProof, - provePayload.withdrawalProof - ), - "" - ); - - // call finalizeWithdrawERC20 - s_adapter.finalizeWithdrawERC20(address(0), address(0), encodedPayload); - } - - function testfinalizeWithdrawERC20FinalizeSuccess() public { - // prepare payload - OptimismL1BridgeAdapter.OptimismFinalizationPayload memory finalizePayload = OptimismL1BridgeAdapter - .OptimismFinalizationPayload({ - withdrawalTransaction: Types.WithdrawalTransaction({ - nonce: 1, - sender: address(0xdead), - target: address(0xbeef), - value: 1234, - gasLimit: 4567, - data: hex"deadbeef" - }) - }); - OptimismL1BridgeAdapter.FinalizeWithdrawERC20Payload memory payload; - payload.action = OptimismL1BridgeAdapter.FinalizationAction.FinalizeWithdrawal; - payload.data = abi.encode(finalizePayload); - - bytes memory encodedPayload = abi.encode(payload); - - // mock out call to optimism portal - vm.mockCall( - OP_PORTAL, - abi.encodeWithSelector( - IOptimismPortal.finalizeWithdrawalTransaction.selector, - finalizePayload.withdrawalTransaction - ), - "" - ); - - // call finalizeWithdrawERC20 - s_adapter.finalizeWithdrawERC20(address(0), address(0), encodedPayload); - } - - function testFinalizeWithdrawERC20Reverts() public { - // case 1: badly encoded payload - bytes memory payload = abi.encode(1, 2, 3); - vm.expectRevert(); - s_adapter.finalizeWithdrawERC20(address(0), address(0), payload); - - // case 2: invalid action - // can't prepare the payload in solidity - payload = hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"; - vm.expectRevert(); - s_adapter.finalizeWithdrawERC20(address(0), address(0), payload); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol deleted file mode 100644 index 9b4654a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/LiquidityManagerHelper.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ILiquidityContainer} from "../../interfaces/ILiquidityContainer.sol"; - -import {LiquidityManager} from "../../LiquidityManager.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract LiquidityManagerHelper is LiquidityManager { - constructor( - IERC20 token, - uint64 localChainSelector, - ILiquidityContainer localLiquidityContainer, - uint256 targetTokens, - address finance - ) LiquidityManager(token, localChainSelector, localLiquidityContainer, targetTokens, finance) {} - - function report(bytes calldata rep, uint64 ocrSeqNum) external { - _report(rep, ocrSeqNum); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol deleted file mode 100644 index b2cd2ef..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/OCR3Helper.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR3Base} from "../../ocr/OCR3Base.sol"; - -contract OCR3Helper is OCR3Base { - function configDigestFromConfigData( - uint256 chainSelector, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) public pure returns (bytes32) { - return - _configDigestFromConfigData( - chainSelector, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - function _report(bytes calldata report, uint64 sequenceNumber) internal override {} - - function typeAndVersion() public pure override returns (string memory) { - return "OCR3BaseHelper 1.0.0"; - } - - function setLatestSeqNum(uint64 newSeqNum) external { - s_latestSequenceNumber = newSeqNum; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol deleted file mode 100644 index ff5e21f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/helpers/ReportEncoder.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {ILiquidityManager} from "../../interfaces/ILiquidityManager.sol"; - -/// @dev this is needed to generate the types to help encode the report offchain -abstract contract ReportEncoder is ILiquidityManager { - /// @dev exposed so that we can encode the report for OCR offchain - function exposeForEncoding(ILiquidityManager.LiquidityInstructions memory instructions) public pure {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol deleted file mode 100644 index f51c60f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/MockBridgeAdapter.sol +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -// solhint-disable one-contract-per-file -pragma solidity ^0.8.0; - -import {IBridgeAdapter} from "../../interfaces/IBridge.sol"; -import {ILiquidityContainer} from "../../interfaces/ILiquidityContainer.sol"; -import {IWrappedNative} from "../../../ccip/interfaces/IWrappedNative.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice Mock multiple-stage finalization bridge adapter implementation. -/// @dev Funds are only made available after both the prove and finalization steps are completed. -/// Sends the L1 tokens from the msg sender to address(this). -contract MockL1BridgeAdapter is IBridgeAdapter, ILiquidityContainer { - using SafeERC20 for IERC20; - - error InsufficientLiquidity(); - error NonceAlreadyUsed(uint256 nonce); - error InvalidFinalizationAction(); - error NonceNotProven(uint256 nonce); - error NativeSendFailed(); - - /// @notice Payload to "prove" the withdrawal. - /// @dev This is just a mock setup, there's no real proving. This is so that - /// we can test the multi-step finalization code path. - /// @param nonce the nonce emitted on the remote chain. - struct ProvePayload { - uint256 nonce; - } - - /// @notice Payload to "finalize" the withdrawal. - /// @dev This is just a mock setup, there's no real finalization. This is so that - /// we can test the multi-step finalization code path. - /// @param nonce the nonce emitted on the remote chain. - struct FinalizePayload { - uint256 nonce; - uint256 amount; - } - - /// @notice The finalization action to take. - /// @dev This emulates Optimism's two-step withdrawal process. - enum FinalizationAction { - ProveWithdrawal, - FinalizeWithdrawal - } - - /// @notice The payload to use for the bridgeSpecificPayload in the finalizeWithdrawERC20 function. - struct Payload { - FinalizationAction action; - bytes data; - } - - IERC20 internal immutable i_token; - uint256 internal s_nonce = 1; - mapping(uint256 => bool) internal s_nonceProven; - mapping(uint256 => bool) internal s_nonceFinalized; - - /// @dev For test cases where we want to send pure native upon finalizeWithdrawERC20 being called. - /// This is to emulate the behavior of bridges that do not bridge wrapped native. - bool internal immutable i_holdNative; - - constructor(IERC20 token, bool holdNative) { - i_token = token; - i_holdNative = holdNative; - } - - /// @dev The receive function is needed for IWrappedNative.withdraw() to work. - receive() external payable {} - - /// @notice Simply transferFrom msg.sender the tokens that are to be bridged to address(this). - function sendERC20( - address localToken, - address /* remoteToken */, - address /* remoteReceiver */, - uint256 amount, - bytes calldata /* bridgeSpecificPayload */ - ) external payable override returns (bytes memory) { - IERC20(localToken).transferFrom(msg.sender, address(this), amount); - - // If the flag to hold native is set we assume that i_token points to a WETH contract - // and withdraw native. - // This way we can transfer the raw native back to the sender upon finalization. - if (i_holdNative) { - IWrappedNative(address(i_token)).withdraw(amount); - } - - bytes memory encodedNonce = abi.encode(s_nonce++); - return encodedNonce; - } - - function getBridgeFeeInNative() external pure returns (uint256) { - return 0; - } - - function provideLiquidity(uint256 amount) external { - i_token.safeTransferFrom(msg.sender, address(this), amount); - emit LiquidityAdded(msg.sender, amount); - } - - function withdrawLiquidity(uint256 amount) external { - if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); - i_token.safeTransfer(msg.sender, amount); - emit LiquidityRemoved(msg.sender, amount); - } - - /// @dev for easy encoding offchain - function encodeProvePayload(ProvePayload memory payload) external pure {} - - function encodeFinalizePayload(FinalizePayload memory payload) external pure {} - - function encodePayload(Payload memory payload) external pure {} - - /// @dev Test setup is trusted, so just transfer the tokens to the localReceiver, - /// which should be the local rebalancer. Infer the amount from the bridgeSpecificPayload. - /// Note that this means that this bridge adapter will need to have some tokens, - /// however this is ok in a test environment since we will have infinite tokens. - /// @param localReceiver the address to transfer the tokens to. - /// @param bridgeSpecificPayload the payload to use for the finalization or proving. - /// @return true if the transfer was successful, revert otherwise. - function finalizeWithdrawERC20( - address /* remoteSender */, - address localReceiver, - bytes calldata bridgeSpecificPayload - ) external override returns (bool) { - Payload memory payload = abi.decode(bridgeSpecificPayload, (Payload)); - if (payload.action == FinalizationAction.ProveWithdrawal) { - return _proveWithdrawal(payload); - } else if (payload.action == FinalizationAction.FinalizeWithdrawal) { - return _finalizeWithdrawal(payload, localReceiver); - } - revert InvalidFinalizationAction(); - } - - function _proveWithdrawal(Payload memory payload) internal returns (bool) { - ProvePayload memory provePayload = abi.decode(payload.data, (ProvePayload)); - if (s_nonceProven[provePayload.nonce]) revert NonceAlreadyUsed(provePayload.nonce); - s_nonceProven[provePayload.nonce] = true; - return false; - } - - function _finalizeWithdrawal(Payload memory payload, address localReceiver) internal returns (bool) { - FinalizePayload memory finalizePayload = abi.decode(payload.data, (FinalizePayload)); - if (!s_nonceProven[finalizePayload.nonce]) revert NonceNotProven(finalizePayload.nonce); - if (s_nonceFinalized[finalizePayload.nonce]) revert NonceAlreadyUsed(finalizePayload.nonce); - s_nonceFinalized[finalizePayload.nonce] = true; - // re-entrancy prevented by nonce checks above. - _transferTokens(finalizePayload.amount, localReceiver); - return true; - } - - function _transferTokens(uint256 amount, address localReceiver) internal { - if (i_holdNative) { - (bool success, ) = payable(localReceiver).call{value: amount}(""); - if (!success) { - revert NativeSendFailed(); - } - } else { - i_token.safeTransfer(localReceiver, amount); - } - } -} - -/// @notice Mock L2 Bridge adapter -/// @dev Sends the L2 tokens from the msg sender to address(this) -contract MockL2BridgeAdapter is IBridgeAdapter { - /// @notice Simply transferFrom msg.sender the tokens that are to be bridged. - function sendERC20( - address localToken, - address /* remoteToken */, - address /* recipient */, - uint256 amount, - bytes calldata /* bridgeSpecificPayload */ - ) external payable override returns (bytes memory) { - IERC20(localToken).transferFrom(msg.sender, address(this), amount); - return ""; - } - - function getBridgeFeeInNative() external pure returns (uint256) { - return 0; - } - - // No-op - function finalizeWithdrawERC20( - address /* remoteSender */, - address /* localReceiver */, - bytes calldata /* bridgeSpecificData */ - ) external pure override returns (bool) { - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol deleted file mode 100644 index 5e771f0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/mocks/NoOpOCR3.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {OCR3Base} from "../../ocr/OCR3Base.sol"; - -// NoOpOCR3 is a mock implementation of the OCR3Base contract that does nothing -// This is so that we can generate gethwrappers for the contract and use the OCR3 ABI in -// Go code. -contract NoOpOCR3 is OCR3Base { - // solhint-disable-next-line chainlink-solidity/all-caps-constant-storage-variables - string public constant override typeAndVersion = "NoOpOCR3 1.0.0"; - - constructor() OCR3Base() {} - - function _report(bytes calldata, uint64) internal override { - // do nothing - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol deleted file mode 100644 index 840e90f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Base.t.sol +++ /dev/null @@ -1,337 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {OCR3Setup} from "./OCR3Setup.t.sol"; -import {OCR3Base} from "../../ocr/OCR3Base.sol"; -import {OCR3Helper} from "../helpers/OCR3Helper.sol"; - -contract OCR3BaseSetup is OCR3Setup { - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - OCR3Helper internal s_OCR3Base; - - bytes32[] internal s_rs; - bytes32[] internal s_ss; - bytes32 internal s_rawVs; - - uint40 internal s_latestEpochAndRound; - - function setUp() public virtual override { - OCR3Setup.setUp(); - s_OCR3Base = new OCR3Helper(); - - bytes32 testReportDigest = getTestReportDigest(); - - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - uint8[] memory vs = new uint8[](2); - - // Calculate signatures - (vs[0], rs[0], ss[0]) = vm.sign(PRIVATE0, testReportDigest); - (vs[1], rs[1], ss[1]) = vm.sign(PRIVATE1, testReportDigest); - - s_rs = rs; - s_ss = ss; - s_rawVs = bytes32(bytes1(vs[0] - 27)) | (bytes32(bytes1(vs[1] - 27)) >> 8); - } - - function getBasicConfigDigest(uint8 f, uint64 currentConfigCount) internal view returns (bytes32) { - bytes memory configBytes = abi.encode(""); - return - s_OCR3Base.configDigestFromConfigData( - block.chainid, - address(s_OCR3Base), - currentConfigCount + 1, - s_valid_signers, - s_valid_transmitters, - f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - } - - function getTestReportDigest() internal view returns (bytes32) { - bytes32 configDigest = getBasicConfigDigest(s_f, 0); - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - return keccak256(abi.encodePacked(keccak256(REPORT), reportContext)); - } - - function getBasicConfigDigest( - address contractAddress, - uint8 f, - uint64 currentConfigCount, - bytes memory onchainConfig - ) internal view returns (bytes32) { - return - s_OCR3Base.configDigestFromConfigData( - block.chainid, - contractAddress, - currentConfigCount + 1, - s_valid_signers, - s_valid_transmitters, - f, - onchainConfig, - s_offchainConfigVersion, - abi.encode("") - ); - } -} - -contract OCR3Base_transmit is OCR3BaseSetup { - bytes32 internal s_configDigest; - - function setUp() public virtual override { - OCR3BaseSetup.setUp(); - bytes memory configBytes = abi.encode(""); - - s_configDigest = getBasicConfigDigest(s_f, 0); - s_OCR3Base.setOCR3Config( - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - } - - function testTransmit2SignersSuccess_gas() public { - vm.pauseGasMetering(); - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - vm.startPrank(s_valid_transmitters[0]); - vm.resumeGasMetering(); - s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - // Reverts - - function testNonIncreasingSequenceNumberReverts() public { - bytes32[3] memory reportContext = [s_configDigest, bytes32(uint256(0)) /* sequence number */, s_configDigest]; - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.NonIncreasingSequenceNumber.selector, 0, 0)); - s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - function testForkedChainReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - uint256 chain1 = block.chainid; - uint256 chain2 = chain1 + 1; - vm.chainId(chain2); - vm.expectRevert(abi.encodeWithSelector(OCR3Base.ForkedChain.selector, chain1, chain2)); - vm.startPrank(s_valid_transmitters[0]); - s_OCR3Base.transmit(reportContext, REPORT, s_rs, s_ss, s_rawVs); - } - - function testWrongNumberOfSignaturesReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - vm.expectRevert(OCR3Base.WrongNumberOfSignatures.selector); - s_OCR3Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); - } - - function testConfigDigestMismatchReverts() public { - bytes32 configDigest; - bytes32[3] memory reportContext = [configDigest, bytes32(uint256(1)) /* sequence number */, configDigest]; - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.ConfigDigestMismatch.selector, s_configDigest, configDigest)); - s_OCR3Base.transmit(reportContext, REPORT, new bytes32[](0), new bytes32[](0), s_rawVs); - } - - function testSignatureOutOfRegistrationReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](1); - - vm.expectRevert(OCR3Base.SignaturesOutOfRegistration.selector); - s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } - - function testUnAuthorizedTransmitterReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = new bytes32[](2); - bytes32[] memory ss = new bytes32[](2); - - vm.expectRevert(OCR3Base.UnauthorizedTransmitter.selector); - s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } - - function testNonUniqueSignatureReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = s_rs; - bytes32[] memory ss = s_ss; - - rs[1] = rs[0]; - ss[1] = ss[0]; - // Need to reset the rawVs to be valid - bytes32 rawVs = bytes32(bytes1(uint8(28) - 27)) | (bytes32(bytes1(uint8(28) - 27)) >> 8); - - vm.startPrank(s_valid_transmitters[0]); - vm.expectRevert(OCR3Base.NonUniqueSignatures.selector); - s_OCR3Base.transmit(reportContext, REPORT, rs, ss, rawVs); - } - - function testUnauthorizedSignerReverts() public { - bytes32[3] memory reportContext = [s_configDigest, s_configDigest, s_configDigest]; - bytes32[] memory rs = new bytes32[](2); - rs[0] = s_configDigest; - bytes32[] memory ss = rs; - - vm.startPrank(s_valid_transmitters[0]); - vm.expectRevert(OCR3Base.UnauthorizedSigner.selector); - s_OCR3Base.transmit(reportContext, REPORT, rs, ss, s_rawVs); - } -} - -contract OCR3Base_setOCR3Config is OCR3BaseSetup { - function testSetConfigSuccess() public { - vm.pauseGasMetering(); - bytes memory configBytes = abi.encode(""); - uint32 configCount = 0; - - bytes32 configDigest = getBasicConfigDigest(s_f, configCount++); - - address[] memory transmitters = s_OCR3Base.getTransmitters(); - assertEq(0, transmitters.length); - - s_OCR3Base.setLatestSeqNum(3); - uint64 seqNum = s_OCR3Base.latestSequenceNumber(); - assertEq(seqNum, 3); - - vm.expectEmit(); - emit ConfigSet( - 0, - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - - s_OCR3Base.setOCR3Config( - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - - transmitters = s_OCR3Base.getTransmitters(); - assertEq(s_valid_transmitters, transmitters); - - configDigest = getBasicConfigDigest(s_f, configCount++); - - seqNum = s_OCR3Base.latestSequenceNumber(); - assertEq(seqNum, 0); - - vm.expectEmit(); - emit ConfigSet( - uint32(block.number), - configDigest, - configCount, - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - vm.resumeGasMetering(); - s_OCR3Base.setOCR3Config( - s_valid_signers, - s_valid_transmitters, - s_f, - configBytes, - s_offchainConfigVersion, - configBytes - ); - } - - // Reverts - function testRepeatAddressReverts() public { - address[] memory signers = new address[](10); - signers[0] = address(1245678); - address[] memory transmitters = new address[](10); - transmitters[0] = signers[0]; - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "repeated transmitter address")); - s_OCR3Base.setOCR3Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); - } - - function testSignerCannotBeZeroAddressReverts() public { - uint256 f = 1; - address[] memory signers = new address[](3 * f + 1); - address[] memory transmitters = new address[](3 * f + 1); - for (uint160 i = 0; i < 3 * f + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - signers[0] = address(0); - - vm.expectRevert(OCR3Base.OracleCannotBeZeroAddress.selector); - s_OCR3Base.setOCR3Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); - } - - function testTransmitterCannotBeZeroAddressReverts() public { - uint256 f = 1; - address[] memory signers = new address[](3 * f + 1); - address[] memory transmitters = new address[](3 * f + 1); - for (uint160 i = 0; i < 3 * f + 1; ++i) { - signers[i] = address(i + 1); - transmitters[i] = address(i + 1000); - } - - transmitters[0] = address(0); - - vm.expectRevert(OCR3Base.OracleCannotBeZeroAddress.selector); - s_OCR3Base.setOCR3Config(signers, transmitters, uint8(f), abi.encode(""), 100, abi.encode("")); - } - - function testOracleOutOfRegisterReverts() public { - address[] memory signers = new address[](10); - address[] memory transmitters = new address[](0); - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "oracle addresses out of registration")); - s_OCR3Base.setOCR3Config(signers, transmitters, 2, abi.encode(""), 100, abi.encode("")); - } - - function testFTooHighReverts() public { - address[] memory signers = new address[](0); - uint8 f = 1; - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "faulty-oracle f too high")); - s_OCR3Base.setOCR3Config(signers, new address[](0), f, abi.encode(""), 100, abi.encode("")); - } - - function testFMustBePositiveReverts() public { - uint8 f = 0; - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "f must be positive")); - s_OCR3Base.setOCR3Config(new address[](0), new address[](0), f, abi.encode(""), 100, abi.encode("")); - } - - function testTooManySignersReverts() public { - address[] memory signers = new address[](32); - - vm.expectRevert(abi.encodeWithSelector(OCR3Base.InvalidConfig.selector, "too many signers")); - s_OCR3Base.setOCR3Config(signers, new address[](0), 0, abi.encode(""), 100, abi.encode("")); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol deleted file mode 100644 index ee60c58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/liquiditymanager/test/ocr/OCR3Setup.t.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {LiquidityManagerBaseTest} from "../LiquidityManagerBaseTest.t.sol"; - -contract OCR3Setup is LiquidityManagerBaseTest { - // Signer private keys used for these test - uint256 internal constant PRIVATE0 = 0x7b2e97fe057e6de99d6872a2ef2abf52c9b4469bc848c2465ac3fcd8d336e81d; - uint256 internal constant PRIVATE1 = 0xab56160806b05ef1796789248e1d7f34a6465c5280899159d645218cd216cee6; - uint256 internal constant PRIVATE2 = 0x6ec7caa8406a49b76736602810e0a2871959fbbb675e23a8590839e4717f1f7f; - uint256 internal constant PRIVATE3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; - - address[] internal s_valid_signers; - address[] internal s_valid_transmitters; - - uint64 internal constant s_offchainConfigVersion = 3; - uint8 internal constant s_f = 1; - bytes internal constant REPORT = abi.encode("testReport"); - - function setUp() public virtual override { - LiquidityManagerBaseTest.setUp(); - - s_valid_transmitters = new address[](4); - for (uint160 i = 0; i < 4; ++i) { - s_valid_transmitters[i] = address(4 + i); - } - - s_valid_signers = new address[](4); - s_valid_signers[0] = vm.addr(PRIVATE0); //0xc110458BE52CaA6bB68E66969C3218A4D9Db0211 - s_valid_signers[1] = vm.addr(PRIVATE1); //0xc110a19c08f1da7F5FfB281dc93630923F8E3719 - s_valid_signers[2] = vm.addr(PRIVATE2); //0xc110fdF6e8fD679C7Cc11602d1cd829211A18e9b - s_valid_signers[3] = vm.addr(PRIVATE3); //0xc11028017c9b445B6bF8aE7da951B5cC28B326C0 - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol deleted file mode 100644 index 478afa9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/interfaces/IConfigurator.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -interface IConfigurator { - /// @notice This event is emitted whenever a new configuration is set for a feed. It triggers a new run of the offchain reporting protocol. - event ConfigSet( - bytes32 indexed configId, - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - bytes32[] offchainTransmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - function setConfig( - bytes32 configId, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol deleted file mode 100644 index c1b59a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/ByteUtil.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -/* - * @title ByteUtil - * @author Michael Fletcher - * @notice Byte utility functions for efficiently parsing and manipulating packed byte data - */ -library ByteUtil { - // Error message when an offset is out of bounds - error MalformedData(); - - /** - * @dev Reads a uint256 from a position within a byte array. - * @param data Byte array to read from. - * @param offset Position to start reading from. - * @return result The uint256 read from the byte array. - */ - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _readUint256(bytes memory data, uint256 offset) internal pure returns (uint256 result) { - //bounds check - if (offset + 32 > data.length) revert MalformedData(); - - assembly { - //load 32 byte word accounting for 32 bit length and offset - result := mload(add(add(data, 32), offset)) - } - } - - /** - * @dev Reads a uint192 from a position within a byte array. - * @param data Byte array to read from. - * @param offset Position to start reading from. - * @return result The uint192 read from the byte array. - */ - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _readUint192(bytes memory data, uint256 offset) internal pure returns (uint256 result) { - //bounds check - if (offset + 24 > data.length) revert MalformedData(); - - assembly { - //load 32 byte word accounting for 32 bit length and offset - result := mload(add(add(data, 32), offset)) - //shift the result right 64 bits - result := shr(64, result) - } - } - - /** - * @dev Reads a uint32 from a position within a byte array. - * @param data Byte array to read from. - * @param offset Position to start reading from. - * @return result The uint32 read from the byte array. - */ - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _readUint32(bytes memory data, uint256 offset) internal pure returns (uint256 result) { - //bounds check - if (offset + 4 > data.length) revert MalformedData(); - - assembly { - //load 32 byte word accounting for 32 bit length and offset - result := mload(add(add(data, 32), offset)) - //shift the result right 224 bits - result := shr(224, result) - } - } - - /** - * @dev Reads an address from a position within a byte array. - * @param data Byte array to read from. - * @param offset Position to start reading from. - * @return result The uint32 read from the byte array. - */ - // solhint-disable-next-line chainlink-solidity/explicit-returns - function _readAddress(bytes memory data, uint256 offset) internal pure returns (address result) { - //bounds check - if (offset + 20 > data.length) revert MalformedData(); - - assembly { - //load 32 byte word accounting for 32 bit length and offset - let word := mload(add(add(data, 32), offset)) - //address is the last 20 bytes of the word, so shift right - result := shr(96, word) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol deleted file mode 100644 index 23418bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/Common.sol +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -/* - * @title Common - * @author Michael Fletcher - * @notice Common functions and structs - */ -library Common { - // @notice The asset struct to hold the address of an asset and amount - struct Asset { - address assetAddress; - uint256 amount; - } - - // @notice Struct to hold the address and its associated weight - struct AddressAndWeight { - address addr; - uint64 weight; - } - - /** - * @notice Checks if an array of AddressAndWeight has duplicate addresses - * @param recipients The array of AddressAndWeight to check - * @return bool True if there are duplicates, false otherwise - */ - function _hasDuplicateAddresses(address[] memory recipients) internal pure returns (bool) { - for (uint256 i = 0; i < recipients.length; ) { - for (uint256 j = i + 1; j < recipients.length; ) { - if (recipients[i] == recipients[j]) { - return true; - } - unchecked { - ++j; - } - } - unchecked { - ++i; - } - } - return false; - } - - /** - * @notice Checks if an array of AddressAndWeight has duplicate addresses - * @param recipients The array of AddressAndWeight to check - * @return bool True if there are duplicates, false otherwise - */ - function _hasDuplicateAddresses(Common.AddressAndWeight[] memory recipients) internal pure returns (bool) { - for (uint256 i = 0; i < recipients.length; ) { - for (uint256 j = i + 1; j < recipients.length; ) { - if (recipients[i].addr == recipients[j].addr) { - return true; - } - unchecked { - ++j; - } - } - unchecked { - ++i; - } - } - return false; - } - - /** - * @notice sorts a list of addresses numerically - * @param arr The array of addresses to sort - * @param left the start index - * @param right the end index - */ - function _quickSort(address[] memory arr, int256 left, int256 right) internal pure { - int256 i = left; - int256 j = right; - if (i == j) return; - address pivot = arr[uint256(left + (right - left) / 2)]; - while (i <= j) { - while (uint160(arr[uint256(i)]) < uint160(pivot)) i++; - while (uint160(pivot) < uint160(arr[uint256(j)])) j--; - if (i <= j) { - (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); - i++; - j--; - } - } - if (left < j) _quickSort(arr, left, j); - if (i < right) _quickSort(arr, i, right); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol deleted file mode 100644 index 8f11dab..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/libraries/test/ByteUtilTest.t.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {ByteUtil} from "../ByteUtil.sol"; - -contract ByteUtilTest is Test { - using ByteUtil for bytes; - - bytes internal constant B_512 = - hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"; - bytes internal constant B_128 = hex"ffffffffffffffffffffffffffffffff"; - bytes internal constant B_16 = hex"ffff"; - bytes internal constant B_EMPTY = new bytes(0); - - bytes4 internal constant MALFORMED_ERROR_SELECTOR = bytes4(keccak256("MalformedData()")); - - function test_readUint256Max() public pure { - //read the first 32 bytes - uint256 result = B_512._readUint256(0); - - //the result should be the max value of a uint256 - assertEq(result, type(uint256).max); - } - - function test_readUint192Max() public pure { - //read the first 24 bytes - uint256 result = B_512._readUint192(0); - - //the result should be the max value of a uint192 - assertEq(result, type(uint192).max); - } - - function test_readUint32Max() public pure { - //read the first 4 bytes - uint256 result = B_512._readUint32(0); - - //the result should be the max value of a uint32 - assertEq(result, type(uint32).max); - } - - function test_readUint256Min() public pure { - //read the second 32 bytes - uint256 result = B_512._readUint256(32); - - //the result should be the min value of a uint256 - assertEq(result, type(uint256).min); - } - - function test_readUint192Min() public pure { - //read the second 24 bytes - uint256 result = B_512._readUint192(32); - - //the result should be the min value of a uint192 - assertEq(result, type(uint192).min); - } - - function test_readUint32Min() public pure { - //read the second 4 bytes - uint256 result = B_512._readUint32(32); - - //the result should be the min value of a uint32 - assertEq(result, type(uint32).min); - } - - function test_readUint256MultiWord() public pure { - //read the first 32 bytes - uint256 result = B_512._readUint256(31); - - //the result should be the last byte from the first word (ff), and 31 bytes from the second word (0000) (0xFF...0000) - assertEq(result, type(uint256).max << 248); - } - - function test_readUint192MultiWord() public pure { - //read the first 24 bytes - uint256 result = B_512._readUint192(31); - - //the result should be the last byte from the first word (ff), and 23 bytes from the second word (0000) (0xFF...0000) - assertEq(result, type(uint192).max << 184); - } - - function test_readUint32MultiWord() public pure { - //read the first 4 bytes - uint256 result = B_512._readUint32(31); - - //the result should be the last byte from the first word (ff), and 3 bytes from the second word (0000) (0xFF...0000) - assertEq(result, type(uint32).max << 24); - } - - function test_readUint256WithNotEnoughBytes() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //try and read 32 bytes from a 16 byte number - B_128._readUint256(0); - } - - function test_readUint192WithNotEnoughBytes() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //try and read 24 bytes from a 16 byte number - B_128._readUint192(0); - } - - function test_readUint32WithNotEnoughBytes() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //try and read 4 bytes from a 2 byte number - B_16._readUint32(0); - } - - function test_readUint256WithEmptyArray() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //read 20 bytes from an empty array - B_EMPTY._readUint256(0); - } - - function test_readUint192WithEmptyArray() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //read 20 bytes from an empty array - B_EMPTY._readUint192(0); - } - - function test_readUint32WithEmptyArray() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //read 20 bytes from an empty array - B_EMPTY._readUint32(0); - } - - function test_readAddress() public pure { - //read the first 20 bytes - address result = B_512._readAddress(0); - - //the result should be the max value of a uint256 - assertEq(result, address(type(uint160).max)); - } - - function test_readZeroAddress() public pure { - //read the first 32 bytes after the first word - address result = B_512._readAddress(32); - - //the result should be 0x00...0 - assertEq(result, address(type(uint160).min)); - } - - function test_readAddressMultiWord() public pure { - //read the first 20 bytes after byte 13 - address result = B_512._readAddress(13); - - //the result should be the value last 19 bytes of the first word (ffff..) and the first byte of the second word (00) (0xFFFF..00) - assertEq(result, address(type(uint160).max << 8)); - } - - function test_readAddressWithNotEnoughBytes() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //read 20 bytes from a 16 byte array - B_128._readAddress(0); - } - - function test_readAddressWithEmptyArray() public { - //should revert if there's not enough bytes - vm.expectRevert(MALFORMED_ERROR_SELECTOR); - - //read the first 20 bytes of an empty array - B_EMPTY._readAddress(0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol deleted file mode 100644 index 44f550e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/FeeManager.sol +++ /dev/null @@ -1,507 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IFeeManager} from "./interfaces/IFeeManager.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; -import {IRewardManager} from "./interfaces/IRewardManager.sol"; -import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; - -/** - * @title FeeManager - * @author Michael Fletcher - * @author Austin Born - * @notice This contract is used for the handling of fees required for users verifying reports. - */ -contract FeeManager is IFeeManager, ConfirmedOwner, TypeAndVersionInterface { - using SafeERC20 for IERC20; - - /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] - mapping(address => mapping(bytes32 => mapping(address => uint256))) public s_subscriberDiscounts; - - /// @notice keep track of any subsidised link that is owed to the reward manager. - mapping(bytes32 => uint256) public s_linkDeficit; - - /// @notice the total discount that can be applied to a fee, 1e18 = 100% discount - uint64 private constant PERCENTAGE_SCALAR = 1e18; - - /// @notice the LINK token address - address public immutable i_linkAddress; - - /// @notice the native token address - address public immutable i_nativeAddress; - - /// @notice the proxy address - address public immutable i_proxyAddress; - - /// @notice the reward manager address - IRewardManager public immutable i_rewardManager; - - // @notice the mask to apply to get the report version - bytes32 private constant REPORT_VERSION_MASK = 0xffff000000000000000000000000000000000000000000000000000000000000; - - // @notice the different report versions - bytes32 private constant REPORT_V1 = 0x0001000000000000000000000000000000000000000000000000000000000000; - - /// @notice the surcharge fee to be paid if paying in native - uint256 public s_nativeSurcharge; - - /// @notice the error thrown if the discount or surcharge is invalid - error InvalidSurcharge(); - - /// @notice the error thrown if the discount is invalid - error InvalidDiscount(); - - /// @notice the error thrown if the address is invalid - error InvalidAddress(); - - /// @notice thrown if msg.value is supplied with a bad quote - error InvalidDeposit(); - - /// @notice thrown if a report has expired - error ExpiredReport(); - - /// @notice thrown if a report has no quote - error InvalidQuote(); - - // @notice thrown when the caller is not authorized - error Unauthorized(); - - // @notice thrown when trying to clear a zero deficit - error ZeroDeficit(); - - /// @notice thrown when trying to pay an address that cannot except funds - error InvalidReceivingAddress(); - - /// @notice Emitted whenever a subscriber's discount is updated - /// @param subscriber address of the subscriber to update discounts for - /// @param feedId Feed ID for the discount - /// @param token Token address for the discount - /// @param discount Discount to apply, in relation to the PERCENTAGE_SCALAR - event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); - - /// @notice Emitted when updating the native surcharge - /// @param newSurcharge Surcharge amount to apply relative to PERCENTAGE_SCALAR - event NativeSurchargeUpdated(uint64 newSurcharge); - - /// @notice Emits when this contract does not have enough LINK to send to the reward manager when paying in native - /// @param rewards Config digest and link fees which could not be subsidised - event InsufficientLink(IRewardManager.FeePayment[] rewards); - - /// @notice Emitted when funds are withdrawn - /// @param adminAddress Address of the admin - /// @param recipient Address of the recipient - /// @param assetAddress Address of the asset withdrawn - /// @param quantity Amount of the asset withdrawn - event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); - - /// @notice Emits when a deficit has been cleared for a particular config digest - /// @param configDigest Config digest of the deficit cleared - /// @param linkQuantity Amount of LINK required to pay the deficit - event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); - - /// @notice Emits when a fee has been processed - /// @param configDigest Config digest of the fee processed - /// @param subscriber Address of the subscriber who paid the fee - /// @param fee Fee paid - /// @param reward Reward paid - /// @param appliedDiscount Discount applied to the fee - event DiscountApplied( - bytes32 indexed configDigest, - address indexed subscriber, - Common.Asset fee, - Common.Asset reward, - uint256 appliedDiscount - ); - - /** - * @notice Construct the FeeManager contract - * @param _linkAddress The address of the LINK token - * @param _nativeAddress The address of the wrapped ERC-20 version of the native token (represents fee in native or wrapped) - * @param _proxyAddress The address of the proxy contract - * @param _rewardManagerAddress The address of the reward manager contract - */ - constructor( - address _linkAddress, - address _nativeAddress, - address _proxyAddress, - address _rewardManagerAddress - ) ConfirmedOwner(msg.sender) { - if ( - _linkAddress == address(0) || - _nativeAddress == address(0) || - _proxyAddress == address(0) || - _rewardManagerAddress == address(0) - ) revert InvalidAddress(); - - i_linkAddress = _linkAddress; - i_nativeAddress = _nativeAddress; - i_proxyAddress = _proxyAddress; - i_rewardManager = IRewardManager(_rewardManagerAddress); - - IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); - } - - modifier onlyOwnerOrProxy() { - if (msg.sender != i_proxyAddress && msg.sender != owner()) revert Unauthorized(); - _; - } - - modifier onlyProxy() { - if (msg.sender != i_proxyAddress) revert Unauthorized(); - _; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "FeeManager 2.0.0"; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return interfaceId == this.processFee.selector || interfaceId == this.processFeeBulk.selector; - } - - /// @inheritdoc IVerifierFeeManager - function processFee( - bytes calldata payload, - bytes calldata parameterPayload, - address subscriber - ) external payable override onlyProxy { - (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( - payload, - parameterPayload, - subscriber - ); - - if (fee.amount == 0) { - _tryReturnChange(subscriber, msg.value); - return; - } - - IFeeManager.FeeAndReward[] memory feeAndReward = new IFeeManager.FeeAndReward[](1); - feeAndReward[0] = IFeeManager.FeeAndReward(bytes32(payload), fee, reward, appliedDiscount); - - if (fee.assetAddress == i_linkAddress) { - _handleFeesAndRewards(subscriber, feeAndReward, 1, 0); - } else { - _handleFeesAndRewards(subscriber, feeAndReward, 0, 1); - } - } - - /// @inheritdoc IVerifierFeeManager - function processFeeBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload, - address subscriber - ) external payable override onlyProxy { - FeeAndReward[] memory feesAndRewards = new IFeeManager.FeeAndReward[](payloads.length); - - //keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees - uint256 numberOfLinkFees; - uint256 numberOfNativeFees; - - uint256 feesAndRewardsIndex; - for (uint256 i; i < payloads.length; ++i) { - (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _processFee( - payloads[i], - parameterPayload, - subscriber - ); - - if (fee.amount != 0) { - feesAndRewards[feesAndRewardsIndex++] = IFeeManager.FeeAndReward( - bytes32(payloads[i]), - fee, - reward, - appliedDiscount - ); - - unchecked { - //keep track of some tallys to make downstream calculations more efficient - if (fee.assetAddress == i_linkAddress) { - ++numberOfLinkFees; - } else { - ++numberOfNativeFees; - } - } - } - } - - if (numberOfLinkFees != 0 || numberOfNativeFees != 0) { - _handleFeesAndRewards(subscriber, feesAndRewards, numberOfLinkFees, numberOfNativeFees); - } else { - _tryReturnChange(subscriber, msg.value); - } - } - - /// @inheritdoc IFeeManager - function getFeeAndReward( - address subscriber, - bytes memory report, - address quoteAddress - ) public view returns (Common.Asset memory, Common.Asset memory, uint256) { - Common.Asset memory fee; - Common.Asset memory reward; - - //get the feedId from the report - bytes32 feedId = bytes32(report); - - //the report needs to be a support version - bytes32 reportVersion = _getReportVersion(feedId); - - //version 1 of the reports don't require quotes, so the fee will be 0 - if (reportVersion == REPORT_V1) { - fee.assetAddress = i_nativeAddress; - reward.assetAddress = i_linkAddress; - return (fee, reward, 0); - } - - //verify the quote payload is a supported token - if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) { - revert InvalidQuote(); - } - - //decode the report depending on the version - uint256 linkQuantity; - uint256 nativeQuantity; - uint256 expiresAt; - (, , , nativeQuantity, linkQuantity, expiresAt) = abi.decode( - report, - (bytes32, uint32, uint32, uint192, uint192, uint32) - ); - - //read the timestamp bytes from the report data and verify it has not expired - if (expiresAt < block.timestamp) { - revert ExpiredReport(); - } - - //get the discount being applied - uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress]; - - //the reward is always set in LINK - reward.assetAddress = i_linkAddress; - reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); - - //calculate either the LINK fee or native fee if it's within the report - if (quoteAddress == i_linkAddress) { - fee.assetAddress = i_linkAddress; - fee.amount = reward.amount; - } else { - uint256 surchargedFee = Math.ceilDiv(nativeQuantity * (PERCENTAGE_SCALAR + s_nativeSurcharge), PERCENTAGE_SCALAR); - - fee.assetAddress = i_nativeAddress; - fee.amount = Math.ceilDiv(surchargedFee * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); - } - - //return the fee - return (fee, reward, discount); - } - - /// @inheritdoc IVerifierFeeManager - function setFeeRecipients( - bytes32 configDigest, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external onlyOwnerOrProxy { - i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); - } - - /// @inheritdoc IFeeManager - function setNativeSurcharge(uint64 surcharge) external onlyOwner { - if (surcharge > PERCENTAGE_SCALAR) revert InvalidSurcharge(); - - s_nativeSurcharge = surcharge; - - emit NativeSurchargeUpdated(surcharge); - } - - /// @inheritdoc IFeeManager - function updateSubscriberDiscount( - address subscriber, - bytes32 feedId, - address token, - uint64 discount - ) external onlyOwner { - //make sure the discount is not greater than the total discount that can be applied - if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); - //make sure the token is either LINK or native - if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); - - s_subscriberDiscounts[subscriber][feedId][token] = discount; - - emit SubscriberDiscountUpdated(subscriber, feedId, token, discount); - } - - /// @inheritdoc IFeeManager - function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { - //address 0 is used to withdraw native in the context of withdrawing - if (assetAddress == address(0)) { - (bool success, ) = payable(recipient).call{value: quantity}(""); - - if (!success) revert InvalidReceivingAddress(); - return; - } - - //withdraw the requested asset - IERC20(assetAddress).safeTransfer(recipient, quantity); - - //emit event when funds are withdrawn - emit Withdraw(msg.sender, recipient, assetAddress, uint192(quantity)); - } - - /// @inheritdoc IFeeManager - function linkAvailableForPayment() external view returns (uint256) { - //return the amount of LINK this contact has available to pay rewards - return IERC20(i_linkAddress).balanceOf(address(this)); - } - - /** - * @notice Gets the current version of the report that is encoded as the last two bytes of the feed - * @param feedId feed id to get the report version for - */ - function _getReportVersion(bytes32 feedId) internal pure returns (bytes32) { - return REPORT_VERSION_MASK & feedId; - } - - function _processFee( - bytes calldata payload, - bytes calldata parameterPayload, - address subscriber - ) internal view returns (Common.Asset memory, Common.Asset memory, uint256) { - if (subscriber == address(this)) revert InvalidAddress(); - - //decode the report from the payload - (, bytes memory report) = abi.decode(payload, (bytes32[3], bytes)); - - //get the feedId from the report - bytes32 feedId = bytes32(report); - - //v1 doesn't need a quote payload, so skip the decoding - address quote; - if (_getReportVersion(feedId) != REPORT_V1) { - //decode the quote from the bytes - (quote) = abi.decode(parameterPayload, (address)); - } - - //decode the fee, it will always be native or LINK - return getFeeAndReward(subscriber, report, quote); - } - - function _handleFeesAndRewards( - address subscriber, - FeeAndReward[] memory feesAndRewards, - uint256 numberOfLinkFees, - uint256 numberOfNativeFees - ) internal { - IRewardManager.FeePayment[] memory linkRewards = new IRewardManager.FeePayment[](numberOfLinkFees); - IRewardManager.FeePayment[] memory nativeFeeLinkRewards = new IRewardManager.FeePayment[](numberOfNativeFees); - - uint256 totalNativeFee; - uint256 totalNativeFeeLinkValue; - - uint256 linkRewardsIndex; - uint256 nativeFeeLinkRewardsIndex; - - uint256 totalNumberOfFees = numberOfLinkFees + numberOfNativeFees; - for (uint256 i; i < totalNumberOfFees; ++i) { - if (feesAndRewards[i].fee.assetAddress == i_linkAddress) { - linkRewards[linkRewardsIndex++] = IRewardManager.FeePayment( - feesAndRewards[i].configDigest, - uint192(feesAndRewards[i].reward.amount) - ); - } else { - nativeFeeLinkRewards[nativeFeeLinkRewardsIndex++] = IRewardManager.FeePayment( - feesAndRewards[i].configDigest, - uint192(feesAndRewards[i].reward.amount) - ); - totalNativeFee += feesAndRewards[i].fee.amount; - totalNativeFeeLinkValue += feesAndRewards[i].reward.amount; - } - - if (feesAndRewards[i].appliedDiscount != 0) { - emit DiscountApplied( - feesAndRewards[i].configDigest, - subscriber, - feesAndRewards[i].fee, - feesAndRewards[i].reward, - feesAndRewards[i].appliedDiscount - ); - } - } - - //keep track of change in case of any over payment - uint256 change; - - if (msg.value != 0) { - //there must be enough to cover the fee - if (totalNativeFee > msg.value) revert InvalidDeposit(); - - //wrap the amount required to pay the fee & approve as the subscriber paid in wrapped native - IWERC20(i_nativeAddress).deposit{value: totalNativeFee}(); - - unchecked { - //msg.value is always >= to fee.amount - change = msg.value - totalNativeFee; - } - } else { - if (totalNativeFee != 0) { - //subscriber has paid in wrapped native, so transfer the native to this contract - IERC20(i_nativeAddress).safeTransferFrom(subscriber, address(this), totalNativeFee); - } - } - - if (linkRewards.length != 0) { - i_rewardManager.onFeePaid(linkRewards, subscriber); - } - - if (nativeFeeLinkRewards.length != 0) { - //distribute subsidised fees paid in Native - if (totalNativeFeeLinkValue > IERC20(i_linkAddress).balanceOf(address(this))) { - // If not enough LINK on this contract to forward for rewards, tally the deficit to be paid by out-of-band LINK - for (uint256 i; i < nativeFeeLinkRewards.length; ++i) { - unchecked { - //we have previously tallied the fees, any overflows would have already reverted - s_linkDeficit[nativeFeeLinkRewards[i].poolId] += nativeFeeLinkRewards[i].amount; - } - } - - emit InsufficientLink(nativeFeeLinkRewards); - } else { - //distribute the fees - i_rewardManager.onFeePaid(nativeFeeLinkRewards, address(this)); - } - } - - // a refund may be needed if the payee has paid in excess of the fee - _tryReturnChange(subscriber, change); - } - - function _tryReturnChange(address subscriber, uint256 quantity) internal { - if (quantity != 0) { - payable(subscriber).transfer(quantity); - } - } - - /// @inheritdoc IFeeManager - function payLinkDeficit(bytes32 configDigest) external onlyOwner { - uint256 deficit = s_linkDeficit[configDigest]; - - if (deficit == 0) revert ZeroDeficit(); - - delete s_linkDeficit[configDigest]; - - IRewardManager.FeePayment[] memory deficitFeePayment = new IRewardManager.FeePayment[](1); - - deficitFeePayment[0] = IRewardManager.FeePayment(configDigest, uint192(deficit)); - - i_rewardManager.onFeePaid(deficitFeePayment, address(this)); - - emit LinkDeficitCleared(configDigest, deficit); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol deleted file mode 100644 index 49fef51..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/RewardManager.sol +++ /dev/null @@ -1,321 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IRewardManager} from "./interfaces/IRewardManager.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {Common} from "../libraries/Common.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/** - * @title RewardManager - * @author Michael Fletcher - * @author Austin Born - * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. - */ -contract RewardManager is IRewardManager, ConfirmedOwner, TypeAndVersionInterface { - using SafeERC20 for IERC20; - - // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] - mapping(bytes32 => uint256) public s_totalRewardRecipientFees; - - // @dev The mapping of fee balances for each pot last time the recipient claimed: s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] - mapping(bytes32 => mapping(address => uint256)) public s_totalRewardRecipientFeesLastClaimedAmounts; - - // @dev The mapping of RewardRecipient weights for a particular poolId: s_rewardRecipientWeights[poolId][rewardRecipient]. - mapping(bytes32 => mapping(address => uint256)) public s_rewardRecipientWeights; - - // @dev Keep track of the reward recipient weights that have been set to prevent duplicates - mapping(bytes32 => bool) public s_rewardRecipientWeightsSet; - - // @dev Store a list of pool ids that have been registered, to make off chain lookups easier - bytes32[] public s_registeredPoolIds; - - // @dev The address for the LINK contract - address public immutable i_linkAddress; - - // The total weight of all RewardRecipients. 1e18 = 100% of the pool fees - uint64 private constant PERCENTAGE_SCALAR = 1e18; - - // The fee manager address - address public s_feeManagerAddress; - - // @notice Thrown whenever the RewardRecipient weights are invalid - error InvalidWeights(); - - // @notice Thrown when any given address is invalid - error InvalidAddress(); - - // @notice Thrown when the pool id is invalid - error InvalidPoolId(); - - // @notice Thrown when the calling contract is not within the authorized contracts - error Unauthorized(); - - // @notice Thrown when getAvailableRewardPoolIds parameters are incorrectly set - error InvalidPoolLength(); - - // Events emitted upon state change - event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); - event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); - event FeeManagerUpdated(address newFeeManagerAddress); - event FeePaid(FeePayment[] payments, address payer); - - /** - * @notice Constructor - * @param linkAddress address of the wrapped LINK token - */ - constructor(address linkAddress) ConfirmedOwner(msg.sender) { - //ensure that the address ia not zero - if (linkAddress == address(0)) revert InvalidAddress(); - - i_linkAddress = linkAddress; - } - - // @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "RewardManager 1.1.0"; - } - - // @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return interfaceId == this.onFeePaid.selector; - } - - modifier onlyOwnerOrFeeManager() { - if (msg.sender != owner() && msg.sender != s_feeManagerAddress) revert Unauthorized(); - _; - } - - modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { - if (msg.sender != owner() && s_rewardRecipientWeights[poolId][msg.sender] == 0) revert Unauthorized(); - _; - } - - modifier onlyFeeManager() { - if (msg.sender != s_feeManagerAddress) revert Unauthorized(); - _; - } - - /// @inheritdoc IRewardManager - function onFeePaid(FeePayment[] calldata payments, address payer) external override onlyFeeManager { - uint256 totalFeeAmount; - for (uint256 i; i < payments.length; ++i) { - unchecked { - //the total amount for any ERC-20 asset cannot exceed 2^256 - 1 - //see https://github.com/OpenZeppelin/openzeppelin-contracts/blob/36bf1e46fa811f0f07d38eb9cfbc69a955f300ce/contracts/token/ERC20/ERC20.sol#L266 - //for example implementation. - s_totalRewardRecipientFees[payments[i].poolId] += payments[i].amount; - - //tally the total payable fees - totalFeeAmount += payments[i].amount; - } - } - - //transfer the fees to this contract - IERC20(i_linkAddress).safeTransferFrom(payer, address(this), totalFeeAmount); - - emit FeePaid(payments, payer); - } - - /// @inheritdoc IRewardManager - function claimRewards(bytes32[] memory poolIds) external override { - _claimRewards(msg.sender, poolIds); - } - - // wrapper impl for claimRewards - function _claimRewards(address recipient, bytes32[] memory poolIds) internal returns (uint256) { - //get the total amount claimable for this recipient - uint256 claimAmount; - - //loop and claim all the rewards in the poolId pot - for (uint256 i; i < poolIds.length; ++i) { - //get the poolId to be claimed - bytes32 poolId = poolIds[i]; - - //get the total fees for the pot - uint256 totalFeesInPot = s_totalRewardRecipientFees[poolId]; - - unchecked { - //avoid unnecessary storage reads if there's no fees in the pot - if (totalFeesInPot == 0) continue; - - //get the claimable amount for this recipient, this calculation will never exceed the amount in the pot - uint256 claimableAmount = totalFeesInPot - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient]; - - //calculate the recipients share of the fees, which is their weighted share of the difference between the last amount they claimed and the current amount in the pot. This can never be more than the total amount in existence - uint256 recipientShare = (claimableAmount * s_rewardRecipientWeights[poolId][recipient]) / PERCENTAGE_SCALAR; - - //if there's no fees to claim, continue as there's nothing to update - if (recipientShare == 0) continue; - - //keep track of the total amount claimable, this can never be more than the total amount in existence - claimAmount += recipientShare; - - //set the current total amount of fees in the pot as it's used to calculate future claims - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] = totalFeesInPot; - - //emit event if the recipient has rewards to claim - emit RewardsClaimed(poolIds[i], recipient, uint192(recipientShare)); - } - } - - //check if there's any rewards to claim in the given poolId - if (claimAmount != 0) { - //transfer the reward to the recipient - IERC20(i_linkAddress).safeTransfer(recipient, claimAmount); - } - - return claimAmount; - } - - /// @inheritdoc IRewardManager - function setRewardRecipients( - bytes32 poolId, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external override onlyOwnerOrFeeManager { - //revert if there are no recipients to set - if (rewardRecipientAndWeights.length == 0) revert InvalidAddress(); - - //check that the weights have not been previously set - if (s_rewardRecipientWeightsSet[poolId]) revert InvalidPoolId(); - - //keep track of the registered poolIds to make off chain lookups easier - s_registeredPoolIds.push(poolId); - - //keep track of which pools have had their reward recipients set - s_rewardRecipientWeightsSet[poolId] = true; - - //set the reward recipients, this will only be called once and contain the full set of RewardRecipients with a total weight of 100% - _setRewardRecipientWeights(poolId, rewardRecipientAndWeights, PERCENTAGE_SCALAR); - - emit RewardRecipientsUpdated(poolId, rewardRecipientAndWeights); - } - - function _setRewardRecipientWeights( - bytes32 poolId, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights, - uint256 expectedWeight - ) internal { - //we can't update the weights if it contains duplicates - if (Common._hasDuplicateAddresses(rewardRecipientAndWeights)) revert InvalidAddress(); - - //loop all the reward recipients and validate the weight and address - uint256 totalWeight; - for (uint256 i; i < rewardRecipientAndWeights.length; ++i) { - //get the weight - uint256 recipientWeight = rewardRecipientAndWeights[i].weight; - //get the address - address recipientAddress = rewardRecipientAndWeights[i].addr; - - //ensure the reward recipient address is not zero - if (recipientAddress == address(0)) revert InvalidAddress(); - - //save/overwrite the weight for the reward recipient - s_rewardRecipientWeights[poolId][recipientAddress] = recipientWeight; - - unchecked { - //keep track of the cumulative weight, this cannot overflow as the total weight is restricted at 1e18 - totalWeight += recipientWeight; - } - } - - //if total weight is not met, the fees will either be under or over distributed - if (totalWeight != expectedWeight) revert InvalidWeights(); - } - - /// @inheritdoc IRewardManager - function updateRewardRecipients( - bytes32 poolId, - Common.AddressAndWeight[] calldata newRewardRecipients - ) external override onlyOwner { - //create an array of poolIds to pass to _claimRewards if required - bytes32[] memory poolIds = new bytes32[](1); - poolIds[0] = poolId; - - //loop all the reward recipients and claim their rewards before updating their weights - uint256 existingTotalWeight; - for (uint256 i; i < newRewardRecipients.length; ++i) { - //get the address - address recipientAddress = newRewardRecipients[i].addr; - //get the existing weight - uint256 existingWeight = s_rewardRecipientWeights[poolId][recipientAddress]; - - //if a recipient is updated, the rewards must be claimed first as they can't claim previous fees at the new weight - _claimRewards(newRewardRecipients[i].addr, poolIds); - - unchecked { - //keep tally of the weights so that the expected collective weight is known - existingTotalWeight += existingWeight; - } - } - - //update the reward recipients, if the new collective weight isn't equal to the previous collective weight, the fees will either be under or over distributed - _setRewardRecipientWeights(poolId, newRewardRecipients, existingTotalWeight); - - //emit event - emit RewardRecipientsUpdated(poolId, newRewardRecipients); - } - - /// @inheritdoc IRewardManager - function payRecipients(bytes32 poolId, address[] calldata recipients) external onlyOwnerOrRecipientInPool(poolId) { - //convert poolIds to an array to match the interface of _claimRewards - bytes32[] memory poolIdsArray = new bytes32[](1); - poolIdsArray[0] = poolId; - - //loop each recipient and claim the rewards for each of the pools and assets - for (uint256 i; i < recipients.length; ++i) { - _claimRewards(recipients[i], poolIdsArray); - } - } - - /// @inheritdoc IRewardManager - function setFeeManager(address newFeeManagerAddress) external onlyOwner { - if (newFeeManagerAddress == address(0)) revert InvalidAddress(); - - s_feeManagerAddress = newFeeManagerAddress; - - emit FeeManagerUpdated(newFeeManagerAddress); - } - - /// @inheritdoc IRewardManager - function getAvailableRewardPoolIds( - address recipient, - uint256 startIndex, - uint256 endIndex - ) external view returns (bytes32[] memory) { - //get the length of the pool ids which we will loop through and potentially return - uint256 registeredPoolIdsLength = s_registeredPoolIds.length; - - uint256 lastIndex = endIndex > registeredPoolIdsLength ? registeredPoolIdsLength : endIndex; - - if (startIndex > lastIndex) revert InvalidPoolLength(); - - //create a new array with the maximum amount of potential pool ids - bytes32[] memory claimablePoolIds = new bytes32[](lastIndex - startIndex); - //we want the pools which a recipient has funds for to be sequential, so we need to keep track of the index - uint256 poolIdArrayIndex; - - //loop all the pool ids, and check if the recipient has a registered weight and a claimable amount - for (uint256 i = startIndex; i < lastIndex; ++i) { - //get the poolId - bytes32 poolId = s_registeredPoolIds[i]; - - //if the recipient has a weight, they are a recipient of this poolId - if (s_rewardRecipientWeights[poolId][recipient] != 0) { - //get the total in this pool - uint256 totalPoolAmount = s_totalRewardRecipientFees[poolId]; - //if the recipient has any LINK, then add the poolId to the array - unchecked { - //s_totalRewardRecipientFeesLastClaimedAmounts can never exceed total pool amount, and the number of pools can't exceed the max array length - if (totalPoolAmount - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] != 0) { - claimablePoolIds[poolIdArrayIndex++] = poolId; - } - } - } - } - - return claimablePoolIds; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol deleted file mode 100644 index fe57421..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/Verifier.sol +++ /dev/null @@ -1,559 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IVerifier} from "./interfaces/IVerifier.sol"; -import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; - -// OCR2 standard -uint256 constant MAX_NUM_ORACLES = 31; - -/* - * The verifier contract is used to verify offchain reports signed - * by DONs. A report consists of a price, block number and feed Id. It - * represents the observed price of an asset at a specified block number for - * a feed. The verifier contract is used to verify that such reports have - * been signed by the correct signers. - **/ -contract Verifier is IVerifier, ConfirmedOwner, TypeAndVersionInterface { - // The first byte of the mask can be 0, because we only ever have 31 oracles - uint256 internal constant ORACLE_MASK = 0x0001010101010101010101010101010101010101010101010101010101010101; - - enum Role { - // Default role for an oracle address. This means that the oracle address - // is not a signer - Unset, - // Role given to an oracle address that is allowed to sign feed data - Signer - } - - struct Signer { - // Index of oracle in a configuration - uint8 index; - // The oracle's role - Role role; - } - - struct Config { - // Fault tolerance - uint8 f; - // Marks whether or not a configuration is active - bool isActive; - // Map of signer addresses to oracles - mapping(address => Signer) oracles; - } - - struct VerifierState { - // The number of times a new configuration - /// has been set - uint32 configCount; - // The block number of the block the last time - /// the configuration was updated. - uint32 latestConfigBlockNumber; - // The latest epoch a report was verified for - uint32 latestEpoch; - // Whether or not the verifier for this feed has been deactivated - bool isDeactivated; - /// The latest config digest set - bytes32 latestConfigDigest; - /// The historical record of all previously set configs by feedId - mapping(bytes32 => Config) s_verificationDataConfigs; - } - - /// @notice This event is emitted when a new report is verified. - /// It is used to keep a historical record of verified reports. - event ReportVerified(bytes32 indexed feedId, address requester); - - /// @notice This event is emitted whenever a new configuration is set for a feed. It triggers a new run of the offchain reporting protocol. - event ConfigSet( - bytes32 indexed feedId, - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - bytes32[] offchainTransmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /// @notice This event is emitted whenever a configuration is deactivated - event ConfigDeactivated(bytes32 indexed feedId, bytes32 configDigest); - - /// @notice This event is emitted whenever a configuration is activated - event ConfigActivated(bytes32 indexed feedId, bytes32 configDigest); - - /// @notice This event is emitted whenever a feed is activated - event FeedActivated(bytes32 indexed feedId); - - /// @notice This event is emitted whenever a feed is deactivated - event FeedDeactivated(bytes32 indexed feedId); - - /// @notice This error is thrown whenever an address tries - /// to exeecute a transaction that it is not authorized to do so - error AccessForbidden(); - - /// @notice This error is thrown whenever a zero address is passed - error ZeroAddress(); - - /// @notice This error is thrown whenever the feed ID passed in - /// a signed report is empty - error FeedIdEmpty(); - - /// @notice This error is thrown whenever the config digest - /// is empty - error DigestEmpty(); - - /// @notice This error is thrown whenever the config digest - /// passed in has not been set in this verifier - /// @param feedId The feed ID in the signed report - /// @param configDigest The config digest that has not been set - error DigestNotSet(bytes32 feedId, bytes32 configDigest); - - /// @notice This error is thrown whenever the config digest - /// has been deactivated - /// @param feedId The feed ID in the signed report - /// @param configDigest The config digest that is inactive - error DigestInactive(bytes32 feedId, bytes32 configDigest); - - /// @notice This error is thrown whenever trying to set a config - /// with a fault tolerance of 0 - error FaultToleranceMustBePositive(); - - /// @notice This error is thrown whenever a report is signed - /// with more than the max number of signers - /// @param numSigners The number of signers who have signed the report - /// @param maxSigners The maximum number of signers that can sign a report - error ExcessSigners(uint256 numSigners, uint256 maxSigners); - - /// @notice This error is thrown whenever a report is signed - /// with less than the minimum number of signers - /// @param numSigners The number of signers who have signed the report - /// @param minSigners The minimum number of signers that need to sign a report - error InsufficientSigners(uint256 numSigners, uint256 minSigners); - - /// @notice This error is thrown whenever a report is signed - /// with an incorrect number of signers - /// @param numSigners The number of signers who have signed the report - /// @param expectedNumSigners The expected number of signers that need to sign - /// a report - error IncorrectSignatureCount(uint256 numSigners, uint256 expectedNumSigners); - - /// @notice This error is thrown whenever the R and S signer components - /// have different lengths - /// @param rsLength The number of r signature components - /// @param ssLength The number of s signature components - error MismatchedSignatures(uint256 rsLength, uint256 ssLength); - - /// @notice This error is thrown whenever setting a config with duplicate signatures - error NonUniqueSignatures(); - - /// @notice This error is thrown whenever a report fails to verify due to bad or duplicate signatures - error BadVerification(); - - /// @notice This error is thrown whenever the admin tries to deactivate - /// the latest config digest - /// @param feedId The feed ID in the signed report - /// @param configDigest The latest config digest - error CannotDeactivateLatestConfig(bytes32 feedId, bytes32 configDigest); - - /// @notice This error is thrown whenever the feed ID passed in is deactivated - /// @param feedId The feed ID - error InactiveFeed(bytes32 feedId); - - /// @notice This error is thrown whenever the feed ID passed in is not found - /// @param feedId The feed ID - error InvalidFeed(bytes32 feedId); - - /// @notice The address of the verifier proxy - address private immutable i_verifierProxyAddr; - - /// @notice Verifier states keyed on Feed ID - mapping(bytes32 => VerifierState) internal s_feedVerifierStates; - - /// @param verifierProxyAddr The address of the VerifierProxy contract - constructor(address verifierProxyAddr) ConfirmedOwner(msg.sender) { - if (verifierProxyAddr == address(0)) revert ZeroAddress(); - i_verifierProxyAddr = verifierProxyAddr; - } - - modifier checkConfigValid(uint256 numSigners, uint256 f) { - if (f == 0) revert FaultToleranceMustBePositive(); - if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); - if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); - _; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { - return interfaceId == this.verify.selector; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "Verifier 1.2.0"; - } - - /// @inheritdoc IVerifier - function verify( - bytes calldata signedReport, - address sender - ) external override returns (bytes memory verifierResponse) { - if (msg.sender != i_verifierProxyAddr) revert AccessForbidden(); - ( - bytes32[3] memory reportContext, - bytes memory reportData, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); - - // The feed ID is the first 32 bytes of the report data. - bytes32 feedId = bytes32(reportData); - - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - // If the feed has been deactivated, do not verify the report - if (feedVerifierState.isDeactivated) { - revert InactiveFeed(feedId); - } - - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - Config storage s_config = feedVerifierState.s_verificationDataConfigs[configDigest]; - - _validateReport(feedId, configDigest, rs, ss, s_config); - _updateEpoch(reportContext, feedVerifierState); - - bytes32 hashedReport = keccak256(reportData); - - _verifySignatures(hashedReport, reportContext, rs, ss, rawVs, s_config); - emit ReportVerified(feedId, sender); - - return reportData; - } - - /// @notice Validates parameters of the report - /// @param feedId Feed ID from the report - /// @param configDigest Config digest from the report - /// @param rs R components from the report - /// @param ss S components from the report - /// @param config Config for the given feed ID keyed on the config digest - function _validateReport( - bytes32 feedId, - bytes32 configDigest, - bytes32[] memory rs, - bytes32[] memory ss, - Config storage config - ) private view { - uint8 expectedNumSignatures = config.f + 1; - - if (!config.isActive) revert DigestInactive(feedId, configDigest); - if (rs.length != expectedNumSignatures) revert IncorrectSignatureCount(rs.length, expectedNumSignatures); - if (rs.length != ss.length) revert MismatchedSignatures(rs.length, ss.length); - } - - /** - * @notice Conditionally update the epoch for a feed - * @param reportContext Report context containing the epoch and round - * @param feedVerifierState Feed verifier state to conditionally update - */ - function _updateEpoch(bytes32[3] memory reportContext, VerifierState storage feedVerifierState) private { - uint40 epochAndRound = uint40(uint256(reportContext[1])); - uint32 epoch = uint32(epochAndRound >> 8); - if (epoch > feedVerifierState.latestEpoch) { - feedVerifierState.latestEpoch = epoch; - } - } - - /// @notice Verifies that a report has been signed by the correct - /// signers and that enough signers have signed the reports. - /// @param hashedReport The keccak256 hash of the raw report's bytes - /// @param reportContext The context the report was signed in - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param rawVs ith element is the the V component of the ith signature - /// @param s_config The config digest the report was signed for - function _verifySignatures( - bytes32 hashedReport, - bytes32[3] memory reportContext, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs, - Config storage s_config - ) private view { - bytes32 h = keccak256(abi.encodePacked(hashedReport, reportContext)); - // i-th byte counts number of sigs made by i-th signer - uint256 signedCount; - - Signer memory o; - address signerAddress; - uint256 numSigners = rs.length; - for (uint256 i; i < numSigners; ++i) { - signerAddress = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_config.oracles[signerAddress]; - if (o.role != Role.Signer) revert BadVerification(); - unchecked { - signedCount += 1 << (8 * o.index); - } - } - - if (signedCount & ORACLE_MASK != signedCount) revert BadVerification(); - } - - /// @inheritdoc IVerifier - function setConfig( - bytes32 feedId, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig( - feedId, - block.chainid, - address(this), - 0, // 0 defaults to feedConfig.configCount + 1 - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig, - recipientAddressesAndWeights - ); - } - - /// @inheritdoc IVerifier - function setConfigFromSource( - bytes32 feedId, - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig( - feedId, - sourceChainId, - sourceAddress, - newConfigCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig, - recipientAddressesAndWeights - ); - } - - /// @notice Sets config based on the given arguments - /// @param feedId Feed ID to set config for - /// @param sourceChainId Chain ID of source config - /// @param sourceAddress Address of source config Verifier - /// @param newConfigCount Optional param to force the new config count - /// @param signers addresses with which oracles sign the reports - /// @param offchainTransmitters CSA key for the ith Oracle - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - /// @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - function _setConfig( - bytes32 feedId, - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) internal { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - // Increment the number of times a config has been set first - if (newConfigCount > 0) feedVerifierState.configCount = newConfigCount; - else feedVerifierState.configCount++; - - bytes32 configDigest = _configDigestFromConfigData( - feedId, - sourceChainId, - sourceAddress, - feedVerifierState.configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - feedVerifierState.s_verificationDataConfigs[configDigest].f = f; - feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; - for (uint8 i; i < signers.length; ++i) { - address signerAddr = signers[i]; - if (signerAddr == address(0)) revert ZeroAddress(); - - // All signer roles are unset by default for a new config digest. - // Here the contract checks to see if a signer's address has already - // been set to ensure that the group of signer addresses that will - // sign reports with the config digest are unique. - bool isSignerAlreadySet = feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr].role != - Role.Unset; - if (isSignerAlreadySet) revert NonUniqueSignatures(); - feedVerifierState.s_verificationDataConfigs[configDigest].oracles[signerAddr] = Signer({ - role: Role.Signer, - index: i - }); - } - - IVerifierProxy(i_verifierProxyAddr).setVerifier( - feedVerifierState.latestConfigDigest, - configDigest, - recipientAddressesAndWeights - ); - - emit ConfigSet( - feedId, - feedVerifierState.latestConfigBlockNumber, - configDigest, - feedVerifierState.configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - feedVerifierState.latestEpoch = 0; - feedVerifierState.latestConfigBlockNumber = uint32(block.number); - feedVerifierState.latestConfigDigest = configDigest; - } - - /// @notice Generates the config digest from config data - /// @param feedId Feed ID to set config for - /// @param sourceChainId Chain ID of source config - /// @param sourceAddress Address of source config Verifier - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - /// @dev This function is a modified version of the method from OCR2Abstract - function _configDigestFromConfigData( - bytes32 feedId, - uint256 sourceChainId, - address sourceAddress, - uint64 configCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - feedId, - sourceChainId, - sourceAddress, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - // 0x0006 corresponds to ConfigDigestPrefixMercuryV02 in libocr - uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @inheritdoc IVerifier - function activateConfig(bytes32 feedId, bytes32 configDigest) external onlyOwner { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - if (configDigest == bytes32("")) revert DigestEmpty(); - if (feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(feedId, configDigest); - feedVerifierState.s_verificationDataConfigs[configDigest].isActive = true; - emit ConfigActivated(feedId, configDigest); - } - - /// @inheritdoc IVerifier - function deactivateConfig(bytes32 feedId, bytes32 configDigest) external onlyOwner { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - if (configDigest == bytes32("")) revert DigestEmpty(); - if (feedVerifierState.s_verificationDataConfigs[configDigest].f == 0) revert DigestNotSet(feedId, configDigest); - if (configDigest == feedVerifierState.latestConfigDigest) { - revert CannotDeactivateLatestConfig(feedId, configDigest); - } - feedVerifierState.s_verificationDataConfigs[configDigest].isActive = false; - emit ConfigDeactivated(feedId, configDigest); - } - - /// @inheritdoc IVerifier - function activateFeed(bytes32 feedId) external onlyOwner { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - if (feedVerifierState.configCount == 0) revert InvalidFeed(feedId); - feedVerifierState.isDeactivated = false; - emit FeedActivated(feedId); - } - - /// @inheritdoc IVerifier - function deactivateFeed(bytes32 feedId) external onlyOwner { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - - if (feedVerifierState.configCount == 0) revert InvalidFeed(feedId); - feedVerifierState.isDeactivated = true; - emit FeedDeactivated(feedId); - } - - /// @inheritdoc IVerifier - function latestConfigDigestAndEpoch( - bytes32 feedId - ) external view override returns (bool scanLogs, bytes32 configDigest, uint32 epoch) { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - return (false, feedVerifierState.latestConfigDigest, feedVerifierState.latestEpoch); - } - - /// @inheritdoc IVerifier - function latestConfigDetails( - bytes32 feedId - ) external view override returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) { - VerifierState storage feedVerifierState = s_feedVerifierStates[feedId]; - return ( - feedVerifierState.configCount, - feedVerifierState.latestConfigBlockNumber, - feedVerifierState.latestConfigDigest - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol deleted file mode 100644 index c06312d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/VerifierProxy.sol +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IVerifierProxy} from "./interfaces/IVerifierProxy.sol"; -import {IVerifier} from "./interfaces/IVerifier.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IVerifierFeeManager} from "./interfaces/IVerifierFeeManager.sol"; -import {Common} from "../libraries/Common.sol"; - -/** - * The verifier proxy contract is the gateway for all report verification requests - * on a chain. It is responsible for taking in a verification request and routing - * it to the correct verifier contract. - */ -contract VerifierProxy is IVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { - /// @notice This event is emitted whenever a new verifier contract is set - /// @param oldConfigDigest The config digest that was previously the latest config - /// digest of the verifier contract at the verifier address. - /// @param oldConfigDigest The latest config digest of the verifier contract - /// at the verifier address. - /// @param verifierAddress The address of the verifier contract that verifies reports for - /// a given digest - event VerifierSet(bytes32 oldConfigDigest, bytes32 newConfigDigest, address verifierAddress); - - /// @notice This event is emitted whenever a new verifier contract is initialized - /// @param verifierAddress The address of the verifier contract that verifies reports - event VerifierInitialized(address verifierAddress); - - /// @notice This event is emitted whenever a verifier is unset - /// @param configDigest The config digest that was unset - /// @param verifierAddress The Verifier contract address unset - event VerifierUnset(bytes32 configDigest, address verifierAddress); - - /// @notice This event is emitted when a new access controller is set - /// @param oldAccessController The old access controller address - /// @param newAccessController The new access controller address - event AccessControllerSet(address oldAccessController, address newAccessController); - - /// @notice This event is emitted when a new fee manager is set - /// @param oldFeeManager The old fee manager address - /// @param newFeeManager The new fee manager address - event FeeManagerSet(address oldFeeManager, address newFeeManager); - - /// @notice This error is thrown whenever an address tries - /// to exeecute a transaction that it is not authorized to do so - error AccessForbidden(); - - /// @notice This error is thrown whenever a zero address is passed - error ZeroAddress(); - - /// @notice This error is thrown when trying to set a verifier address - /// for a digest that has already been initialized - /// @param configDigest The digest for the verifier that has - /// already been set - /// @param verifier The address of the verifier the digest was set for - error ConfigDigestAlreadySet(bytes32 configDigest, address verifier); - - /// @notice This error is thrown when trying to set a verifier address that has already been initialized - error VerifierAlreadyInitialized(address verifier); - - /// @notice This error is thrown when the verifier at an address does - /// not conform to the verifier interface - error VerifierInvalid(); - - /// @notice This error is thrown when the fee manager at an address does - /// not conform to the fee manager interface - error FeeManagerInvalid(); - - /// @notice This error is thrown whenever a verifier is not found - /// @param configDigest The digest for which a verifier is not found - error VerifierNotFound(bytes32 configDigest); - - /// @notice This error is thrown whenever billing fails. - error BadVerification(); - - /// @notice Mapping of authorized verifiers - mapping(address => bool) private s_initializedVerifiers; - - /// @notice Mapping between config digests and verifiers - mapping(bytes32 => address) private s_verifiersByConfig; - - /// @notice The contract to control addresses that are allowed to verify reports - AccessControllerInterface public s_accessController; - - /// @notice The contract to control fees for report verification - IVerifierFeeManager public s_feeManager; - - constructor(AccessControllerInterface accessController) ConfirmedOwner(msg.sender) { - s_accessController = accessController; - } - - modifier checkAccess() { - AccessControllerInterface ac = s_accessController; - if (address(ac) != address(0) && !ac.hasAccess(msg.sender, msg.data)) revert AccessForbidden(); - _; - } - - modifier onlyInitializedVerifier() { - if (!s_initializedVerifiers[msg.sender]) revert AccessForbidden(); - _; - } - - modifier onlyValidVerifier(address verifierAddress) { - if (verifierAddress == address(0)) revert ZeroAddress(); - if (!IERC165(verifierAddress).supportsInterface(IVerifier.verify.selector)) revert VerifierInvalid(); - _; - } - - modifier onlyUnsetConfigDigest(bytes32 configDigest) { - address configDigestVerifier = s_verifiersByConfig[configDigest]; - if (configDigestVerifier != address(0)) revert ConfigDigestAlreadySet(configDigest, configDigestVerifier); - _; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "VerifierProxy 2.0.0"; - } - - /// @inheritdoc IVerifierProxy - function verify( - bytes calldata payload, - bytes calldata parameterPayload - ) external payable checkAccess returns (bytes memory) { - IVerifierFeeManager feeManager = s_feeManager; - - // Bill the verifier - if (address(feeManager) != address(0)) { - feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); - } - - return _verify(payload); - } - - /// @inheritdoc IVerifierProxy - function verifyBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload - ) external payable checkAccess returns (bytes[] memory verifiedReports) { - IVerifierFeeManager feeManager = s_feeManager; - - // Bill the verifier - if (address(feeManager) != address(0)) { - feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); - } - - //verify the reports - verifiedReports = new bytes[](payloads.length); - for (uint256 i; i < payloads.length; ++i) { - verifiedReports[i] = _verify(payloads[i]); - } - - return verifiedReports; - } - - function _verify(bytes calldata payload) internal returns (bytes memory verifiedReport) { - // First 32 bytes of the signed report is the config digest - bytes32 configDigest = bytes32(payload); - address verifierAddress = s_verifiersByConfig[configDigest]; - if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); - - return IVerifier(verifierAddress).verify(payload, msg.sender); - } - - /// @inheritdoc IVerifierProxy - function initializeVerifier(address verifierAddress) external override onlyOwner onlyValidVerifier(verifierAddress) { - if (s_initializedVerifiers[verifierAddress]) revert VerifierAlreadyInitialized(verifierAddress); - - s_initializedVerifiers[verifierAddress] = true; - emit VerifierInitialized(verifierAddress); - } - - /// @inheritdoc IVerifierProxy - function setVerifier( - bytes32 currentConfigDigest, - bytes32 newConfigDigest, - Common.AddressAndWeight[] calldata addressesAndWeights - ) external override onlyUnsetConfigDigest(newConfigDigest) onlyInitializedVerifier { - s_verifiersByConfig[newConfigDigest] = msg.sender; - - // Empty recipients array will be ignored and must be set off chain - if (addressesAndWeights.length > 0) { - if (address(s_feeManager) == address(0)) { - revert ZeroAddress(); - } - - s_feeManager.setFeeRecipients(newConfigDigest, addressesAndWeights); - } - - emit VerifierSet(currentConfigDigest, newConfigDigest, msg.sender); - } - - /// @inheritdoc IVerifierProxy - function unsetVerifier(bytes32 configDigest) external override onlyOwner { - address verifierAddress = s_verifiersByConfig[configDigest]; - if (verifierAddress == address(0)) revert VerifierNotFound(configDigest); - delete s_verifiersByConfig[configDigest]; - emit VerifierUnset(configDigest, verifierAddress); - } - - /// @inheritdoc IVerifierProxy - function getVerifier(bytes32 configDigest) external view override returns (address) { - return s_verifiersByConfig[configDigest]; - } - - /// @inheritdoc IVerifierProxy - function setAccessController(AccessControllerInterface accessController) external onlyOwner { - address oldAccessController = address(s_accessController); - s_accessController = accessController; - emit AccessControllerSet(oldAccessController, address(accessController)); - } - - /// @inheritdoc IVerifierProxy - function setFeeManager(IVerifierFeeManager feeManager) external onlyOwner { - if (address(feeManager) == address(0)) revert ZeroAddress(); - - if ( - !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFee.selector) || - !IERC165(feeManager).supportsInterface(IVerifierFeeManager.processFeeBulk.selector) - ) revert FeeManagerInvalid(); - - address oldFeeManager = address(s_feeManager); - s_feeManager = IVerifierFeeManager(feeManager); - emit FeeManagerSet(oldFeeManager, address(feeManager)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol deleted file mode 100644 index 818a3a0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IFeeManager.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; -import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; - -interface IFeeManager is IERC165, IVerifierFeeManager { - /** - * @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount. - * @param subscriber address trying to verify - * @param report report to calculate the fee for - * @param quoteAddress address of the quote payment token - * @return (fee, reward, totalDiscount) fee and the reward data with the discount applied - */ - function getFeeAndReward( - address subscriber, - bytes memory report, - address quoteAddress - ) external returns (Common.Asset memory, Common.Asset memory, uint256); - - /** - * @notice Sets the native surcharge - * @param surcharge surcharge to be paid if paying in native - */ - function setNativeSurcharge(uint64 surcharge) external; - - /** - * @notice Adds a subscriber to the fee manager - * @param subscriber address of the subscriber - * @param feedId feed id to apply the discount to - * @param token token to apply the discount to - * @param discount discount to be applied to the fee - */ - function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) external; - - /** - * @notice Withdraws any native or LINK rewards to the owner address - * @param assetAddress address of the asset to withdraw - * @param recipientAddress address to withdraw to - * @param quantity quantity to withdraw - */ - function withdraw(address assetAddress, address recipientAddress, uint192 quantity) external; - - /** - * @notice Returns the link balance of the fee manager - * @return link balance of the fee manager - */ - function linkAvailableForPayment() external returns (uint256); - - /** - * @notice Admin function to pay the LINK deficit for a given config digest - * @param configDigest the config digest to pay the deficit for - */ - function payLinkDeficit(bytes32 configDigest) external; - - /** - * @notice The structure to hold a fee and reward to verify a report - * @param digest the digest linked to the fee and reward - * @param fee the fee paid to verify the report - * @param reward the reward paid upon verification - & @param appliedDiscount the discount applied to the reward - */ - struct FeeAndReward { - bytes32 configDigest; - Common.Asset fee; - Common.Asset reward; - uint256 appliedDiscount; - } - - /** - * @notice The structure to hold quote metadata - * @param quoteAddress the address of the quote - */ - struct Quote { - address quoteAddress; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol deleted file mode 100644 index f08ce34..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IRewardManager.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IRewardManager is IERC165 { - /** - * @notice Record the fee received for a particular pool - * @param payments array of structs containing pool id and amount - * @param payee the user the funds should be retrieved from - */ - function onFeePaid(FeePayment[] calldata payments, address payee) external; - - /** - * @notice Claims the rewards in a specific pool - * @param poolIds array of poolIds to claim rewards for - */ - function claimRewards(bytes32[] calldata poolIds) external; - - /** - * @notice Set the RewardRecipients and weights for a specific pool. This should only be called once per pool Id. Else updateRewardRecipients should be used. - * @param poolId poolId to set RewardRecipients and weights for - * @param rewardRecipientAndWeights array of each RewardRecipient and associated weight - */ - function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata rewardRecipientAndWeights) external; - - /** - * @notice Updates a subset the reward recipients for a specific poolId. The collective weight of the recipients should add up to the recipients existing weights. Any recipients with a weight of 0 will be removed. - * @param poolId the poolId to update - * @param newRewardRecipients array of new reward recipients - */ - function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata newRewardRecipients) external; - - /** - * @notice Pays all the recipients for each of the pool ids - * @param poolId the pool id to pay recipients for - * @param recipients array of recipients to pay within the pool - */ - function payRecipients(bytes32 poolId, address[] calldata recipients) external; - - /** - * @notice Sets the fee manager. This needs to be done post construction to prevent a circular dependency. - * @param newFeeManager address of the new verifier proxy - */ - function setFeeManager(address newFeeManager) external; - - /** - * @notice Gets a list of pool ids which have reward for a specific recipient. - * @param recipient address of the recipient to get pool ids for - * @param startIndex the index to start from - * @param endIndex the index to stop at - */ - function getAvailableRewardPoolIds( - address recipient, - uint256 startIndex, - uint256 endIndex - ) external view returns (bytes32[] memory); - - /** - * @notice The structure to hold a fee payment notice - * @param poolId the poolId receiving the payment - * @param amount the amount being paid - */ - struct FeePayment { - bytes32 poolId; - uint192 amount; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol deleted file mode 100644 index 94b2603..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifier.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IVerifier is IERC165 { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the correct verifier. - * @param signedReport The encoded data to be verified. - * @param sender The address that requested to verify the contract. - * This is only used for logging purposes. - * @dev Verification is typically only done through the proxy contract so - * we can't just use msg.sender to log the requester as the msg.sender - * contract will always be the proxy. - * @return verifierResponse The encoded verified response. - */ - function verify(bytes calldata signedReport, address sender) external returns (bytes memory verifierResponse); - - /** - * @notice sets offchain reporting protocol configuration incl. participating oracles - * @param feedId Feed ID to set config for - * @param signers addresses with which oracles sign the reports - * @param offchainTransmitters CSA key for the ith Oracle - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - */ - function setConfig( - bytes32 feedId, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external; - - /** - * @notice identical to `setConfig` except with args for sourceChainId and sourceAddress - * @param feedId Feed ID to set config for - * @param sourceChainId Chain ID of source config - * @param sourceAddress Address of source config Verifier - * @param newConfigCount Param to force the new config count - * @param signers addresses with which oracles sign the reports - * @param offchainTransmitters CSA key for the ith Oracle - * @param f number of faulty oracles the system can tolerate - * @param onchainConfig serialized configuration used by the contract (and possibly oracles) - * @param offchainConfigVersion version number for offchainEncoding schema - * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - */ - function setConfigFromSource( - bytes32 feedId, - uint256 sourceChainId, - address sourceAddress, - uint32 newConfigCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external; - - /** - * @notice Activates the configuration for a config digest - * @param feedId Feed ID to activate config for - * @param configDigest The config digest to activate - * @dev This function can be called by the contract admin to activate a configuration. - */ - function activateConfig(bytes32 feedId, bytes32 configDigest) external; - - /** - * @notice Deactivates the configuration for a config digest - * @param feedId Feed ID to deactivate config for - * @param configDigest The config digest to deactivate - * @dev This function can be called by the contract admin to deactivate an incorrect configuration. - */ - function deactivateConfig(bytes32 feedId, bytes32 configDigest) external; - - /** - * @notice Activates the given feed - * @param feedId Feed ID to activated - * @dev This function can be called by the contract admin to activate a feed - */ - function activateFeed(bytes32 feedId) external; - - /** - * @notice Deactivates the given feed - * @param feedId Feed ID to deactivated - * @dev This function can be called by the contract admin to deactivate a feed - */ - function deactivateFeed(bytes32 feedId) external; - - /** - * @notice returns the latest config digest and epoch for a feed - * @param feedId Feed ID to fetch data for - * @return scanLogs indicates whether to rely on the configDigest and epoch - * returned or whether to scan logs for the Transmitted event instead. - * @return configDigest - * @return epoch - */ - function latestConfigDigestAndEpoch( - bytes32 feedId - ) external view returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /** - * @notice information about current offchain reporting protocol configuration - * @param feedId Feed ID to fetch data for - * @return configCount ordinal number of current config, out of all configs applied to this contract so far - * @return blockNumber block at which this config was set - * @return configDigest domain-separation tag for current config - */ - function latestConfigDetails( - bytes32 feedId - ) external view returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol deleted file mode 100644 index da3fdfa..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierFeeManager.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IVerifierFeeManager is IERC165 { - /** - * @notice Handles fees for a report from the subscriber and manages rewards - * @param payload report to process the fee for - * @param parameterPayload fee payload - * @param subscriber address of the fee will be applied - */ - function processFee(bytes calldata payload, bytes calldata parameterPayload, address subscriber) external payable; - - /** - * @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager - * @param payloads reports to process - * @param parameterPayload fee payload - * @param subscriber address of the user to process fee for - */ - function processFeeBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload, - address subscriber - ) external payable; - - /** - * @notice Sets the fee recipients according to the fee manager - * @param configDigest digest of the configuration - * @param rewardRecipientAndWeights the address and weights of all the recipients to receive rewards - */ - function setFeeRecipients( - bytes32 configDigest, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol deleted file mode 100644 index 6609e48..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/interfaces/IVerifierProxy.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Common} from "../../libraries/Common.sol"; -import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; -import {IVerifierFeeManager} from "./IVerifierFeeManager.sol"; - -interface IVerifierProxy { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the correct verifier, and bills the user if applicable. - * @param payload The encoded data to be verified, including the signed - * report. - * @param parameterPayload fee metadata for billing - * @return verifierResponse The encoded report from the verifier. - */ - function verify( - bytes calldata payload, - bytes calldata parameterPayload - ) external payable returns (bytes memory verifierResponse); - - /** - * @notice Bulk verifies that the data encoded has been signed - * correctly by routing to the correct verifier, and bills the user if applicable. - * @param payloads The encoded payloads to be verified, including the signed - * report. - * @param parameterPayload fee metadata for billing - * @return verifiedReports The encoded reports from the verifier. - */ - function verifyBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload - ) external payable returns (bytes[] memory verifiedReports); - - /** - * @notice Sets the verifier address initially, allowing `setVerifier` to be set by this Verifier in the future - * @param verifierAddress The address of the verifier contract to initialize - */ - function initializeVerifier(address verifierAddress) external; - - /** - * @notice Sets a new verifier for a config digest - * @param currentConfigDigest The current config digest - * @param newConfigDigest The config digest to set - * @param addressesAndWeights The addresses and weights of reward recipients - * reports for a given config digest. - */ - function setVerifier( - bytes32 currentConfigDigest, - bytes32 newConfigDigest, - Common.AddressAndWeight[] memory addressesAndWeights - ) external; - - /** - * @notice Removes a verifier for a given config digest - * @param configDigest The config digest of the verifier to remove - */ - function unsetVerifier(bytes32 configDigest) external; - - /** - * @notice Retrieves the verifier address that verifies reports - * for a config digest. - * @param configDigest The config digest to query for - * @return verifierAddress The address of the verifier contract that verifies - * reports for a given config digest. - */ - function getVerifier(bytes32 configDigest) external view returns (address verifierAddress); - - /** - * @notice Called by the admin to set an access controller contract - * @param accessController The new access controller to set - */ - function setAccessController(AccessControllerInterface accessController) external; - - /** - * @notice Updates the fee manager - * @param feeManager The new fee manager - */ - function setFeeManager(IVerifierFeeManager feeManager) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol deleted file mode 100644 index 0d598cd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/BaseFeeManager.t.sol +++ /dev/null @@ -1,379 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {FeeManager} from "../../FeeManager.sol"; -import {RewardManager} from "../../RewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; -import {FeeManagerProxy} from "../mocks/FeeManagerProxy.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice Base class for all feeManager tests - * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup the feeManager - */ -contract BaseFeeManagerTest is Test { - //contracts - FeeManager internal feeManager; - RewardManager internal rewardManager; - FeeManagerProxy internal feeManagerProxy; - - ERC20Mock internal link; - WERC20Mock internal native; - - //erc20 config - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - //contract owner - address internal constant INVALID_ADDRESS = address(0); - address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); - address internal constant USER = address(uint160(uint256(keccak256("USER")))); - address internal constant PROXY = address(uint160(uint256(keccak256("PROXY")))); - - //version masks - bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; - - //feed ids & config digests - bytes32 internal constant DEFAULT_FEED_1_V1 = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant DEFAULT_FEED_1_V2 = (keccak256("ETH-USD") & V_MASK) | V2_BITMASK; - bytes32 internal constant DEFAULT_FEED_1_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; - - bytes32 internal constant DEFAULT_FEED_2_V3 = (keccak256("LINK-USD") & V_MASK) | V3_BITMASK; - bytes32 internal constant DEFAULT_CONFIG_DIGEST = keccak256("DEFAULT_CONFIG_DIGEST"); - - //report - uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; - uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; - - //rewards - uint64 internal constant FEE_SCALAR = 1e18; - - address internal constant NATIVE_WITHDRAW_ADDRESS = address(0); - - //the selector for each error - bytes4 internal immutable INVALID_DISCOUNT_ERROR = FeeManager.InvalidDiscount.selector; - bytes4 internal immutable INVALID_ADDRESS_ERROR = FeeManager.InvalidAddress.selector; - bytes4 internal immutable INVALID_SURCHARGE_ERROR = FeeManager.InvalidSurcharge.selector; - bytes4 internal immutable EXPIRED_REPORT_ERROR = FeeManager.ExpiredReport.selector; - bytes4 internal immutable INVALID_DEPOSIT_ERROR = FeeManager.InvalidDeposit.selector; - bytes4 internal immutable INVALID_QUOTE_ERROR = FeeManager.InvalidQuote.selector; - bytes4 internal immutable UNAUTHORIZED_ERROR = FeeManager.Unauthorized.selector; - bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; - bytes internal constant INSUFFICIENT_ALLOWANCE_ERROR = "ERC20: insufficient allowance"; - bytes4 internal immutable ZERO_DEFICIT = FeeManager.ZeroDeficit.selector; - - //events emitted - event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); - event NativeSurchargeUpdated(uint64 newSurcharge); - event InsufficientLink(IRewardManager.FeePayment[] feesAndRewards); - event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); - event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); - event DiscountApplied( - bytes32 indexed configDigest, - address indexed subscriber, - Common.Asset fee, - Common.Asset reward, - uint256 appliedDiscountQuantity - ); - - function setUp() public virtual { - //change to admin user - vm.startPrank(ADMIN); - - //init required contracts - _initializeContracts(); - } - - function _initializeContracts() internal { - link = new ERC20Mock("LINK", "LINK", ADMIN, 0); - native = new WERC20Mock(); - - feeManagerProxy = new FeeManagerProxy(); - rewardManager = new RewardManager(address(link)); - feeManager = new FeeManager(address(link), address(native), address(feeManagerProxy), address(rewardManager)); - - //link the feeManager to the proxy - feeManagerProxy.setFeeManager(feeManager); - - //link the feeManager to the reward manager - rewardManager.setFeeManager(address(feeManager)); - - //mint some tokens to the admin - link.mint(ADMIN, DEFAULT_LINK_MINT_QUANTITY); - native.mint(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some tokens to the proxy - link.mint(PROXY, DEFAULT_LINK_MINT_QUANTITY); - native.mint(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function setSubscriberDiscount( - address subscriber, - bytes32 feedId, - address token, - uint256 discount, - address sender - ) internal { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the discount - feeManager.updateSubscriberDiscount(subscriber, feedId, token, uint64(discount)); - - //change back to the original address - changePrank(originalAddr); - } - - function setNativeSurcharge(uint256 surcharge, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the surcharge - feeManager.setNativeSurcharge(uint64(surcharge)); - - //change back to the original address - changePrank(originalAddr); - } - - // solium-disable-next-line no-unused-vars - function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { - //get the fee - (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote); - - return fee; - } - - function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { - //get the reward - (, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote); - - return reward; - } - - function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) { - //get the reward - (, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote); - - return appliedDiscount; - } - - function getV1Report(bytes32 feedId) public pure returns (bytes memory) { - return abi.encode(feedId, uint32(0), int192(0), int192(0), int192(0), uint64(0), bytes32(0), uint64(0), uint64(0)); - } - - function getV2Report(bytes32 feedId) public view returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(DEFAULT_REPORT_NATIVE_FEE), - uint192(DEFAULT_REPORT_LINK_FEE), - uint32(block.timestamp), - int192(0) - ); - } - - function getV3Report(bytes32 feedId) public view returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(DEFAULT_REPORT_NATIVE_FEE), - uint192(DEFAULT_REPORT_LINK_FEE), - uint32(block.timestamp), - int192(0), - int192(0), - int192(0) - ); - } - - function getV3ReportWithCustomExpiryAndFee( - bytes32 feedId, - uint256 expiry, - uint256 linkFee, - uint256 nativeFee - ) public pure returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(nativeFee), - uint192(linkFee), - uint32(expiry), - int192(0), - int192(0), - int192(0) - ); - } - - function getLinkQuote() public view returns (address) { - return address(link); - } - - function getNativeQuote() public view returns (address) { - return address(native); - } - - function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the surcharge - feeManager.withdraw(assetAddress, recipient, uint192(amount)); - - //change back to the original address - changePrank(originalAddr); - } - - function getLinkBalance(address balanceAddress) public view returns (uint256) { - return link.balanceOf(balanceAddress); - } - - function getNativeBalance(address balanceAddress) public view returns (uint256) { - return native.balanceOf(balanceAddress); - } - - function getNativeUnwrappedBalance(address balanceAddress) public view returns (uint256) { - return balanceAddress.balance; - } - - function mintLink(address recipient, uint256 amount) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(ADMIN); - - //mint the link to the recipient - link.mint(recipient, amount); - - //change back to the original address - changePrank(originalAddr); - } - - function mintNative(address recipient, uint256 amount, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //mint the native to the recipient - native.mint(recipient, amount); - - //change back to the original address - changePrank(originalAddr); - } - - function issueUnwrappedNative(address recipient, uint256 quantity) public { - vm.deal(recipient, quantity); - } - - function ProcessFeeAsUser( - bytes memory payload, - address subscriber, - address tokenAddress, - uint256 wrappedNativeValue, - address sender - ) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //process the fee - feeManager.processFee{value: wrappedNativeValue}(payload, abi.encode(tokenAddress), subscriber); - - //change ProcessFeeAsUserback to the original address - changePrank(originalAddr); - } - - function processFee(bytes memory payload, address subscriber, address feeAddress, uint256 wrappedNativeValue) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(subscriber); - - //process the fee - feeManagerProxy.processFee{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - //change back to the original address - changePrank(originalAddr); - } - - function processFee( - bytes[] memory payloads, - address subscriber, - address feeAddress, - uint256 wrappedNativeValue - ) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(subscriber); - - //process the fee - feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(payloads, abi.encode(feeAddress)); - - //change back to the original address - changePrank(originalAddr); - } - - function getPayload(bytes memory reportPayload) public pure returns (bytes memory) { - return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32("")); - } - - function approveLink(address spender, uint256 quantity, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - link.approve(spender, quantity); - - //change back to the original address - changePrank(originalAddr); - } - - function approveNative(address spender, uint256 quantity, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - native.approve(spender, quantity); - - //change back to the original address - changePrank(originalAddr); - } - - function payLinkDeficit(bytes32 configDigest, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - feeManager.payLinkDeficit(configDigest); - - //change back to the original address - changePrank(originalAddr); - } - - function getLinkDeficit(bytes32 configDigest) public view returns (uint256) { - return feeManager.s_linkDeficit(configDigest); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol deleted file mode 100644 index 571d348..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.general.t.sol +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import "./BaseFeeManager.t.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the setup functionality of the feemanager - */ -contract FeeManagerProcessFeeTest is BaseFeeManagerTest { - function setUp() public override { - super.setUp(); - } - - function test_WithdrawERC20() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //get the balances to ne used for comparison - uint256 contractBalance = getLinkBalance(address(feeManager)); - uint256 adminBalance = getLinkBalance(ADMIN); - - //the amount to withdraw - uint256 withdrawAmount = contractBalance / 2; - - //withdraw some balance - withdraw(address(link), ADMIN, withdrawAmount, ADMIN); - - //check the balance has been reduced - uint256 newContractBalance = getLinkBalance(address(feeManager)); - uint256 newAdminBalance = getLinkBalance(ADMIN); - - //check the balance is greater than zero - assertGt(newContractBalance, 0); - //check the balance has been reduced by the correct amount - assertEq(newContractBalance, contractBalance - withdrawAmount); - //check the admin balance has increased by the correct amount - assertEq(newAdminBalance, adminBalance + withdrawAmount); - } - - function test_WithdrawUnwrappedNative() public { - //issue funds straight to the contract to bypass the lack of fallback function - issueUnwrappedNative(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); - - //get the balances to be used for comparison - uint256 contractBalance = getNativeUnwrappedBalance(address(feeManager)); - uint256 adminBalance = getNativeUnwrappedBalance(ADMIN); - - //the amount to withdraw - uint256 withdrawAmount = contractBalance / 2; - - //withdraw some balance - withdraw(NATIVE_WITHDRAW_ADDRESS, ADMIN, withdrawAmount, ADMIN); - - //check the balance has been reduced - uint256 newContractBalance = getNativeUnwrappedBalance(address(feeManager)); - uint256 newAdminBalance = getNativeUnwrappedBalance(ADMIN); - - //check the balance is greater than zero - assertGt(newContractBalance, 0); - //check the balance has been reduced by the correct amount - assertEq(newContractBalance, contractBalance - withdrawAmount); - //check the admin balance has increased by the correct amount - assertEq(newAdminBalance, adminBalance + withdrawAmount); - } - - function test_WithdrawNonAdminAddr() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //should revert if not admin - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //withdraw some balance - withdraw(address(link), ADMIN, DEFAULT_LINK_MINT_QUANTITY, USER); - } - - function test_eventIsEmittedAfterSurchargeIsSet() public { - //native surcharge - uint64 nativeSurcharge = FEE_SCALAR / 5; - - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit NativeSurchargeUpdated(nativeSurcharge); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - } - - function test_subscriberDiscountEventIsEmittedOnUpdate() public { - //native surcharge - uint64 discount = FEE_SCALAR / 3; - - //an event should be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit SubscriberDiscountUpdated(USER, DEFAULT_FEED_1_V3, address(native), discount); - - //set the surcharge - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); - } - - function test_eventIsEmittedUponWithdraw() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //the amount to withdraw - uint192 withdrawAmount = 1; - - //expect an emit - vm.expectEmit(); - - //the event to be emitted - emit Withdraw(ADMIN, ADMIN, address(link), withdrawAmount); - - //withdraw some balance - withdraw(address(link), ADMIN, withdrawAmount, ADMIN); - } - - function test_linkAvailableForPaymentReturnsLinkBalance() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //check there's a balance - assertGt(getLinkBalance(address(feeManager)), 0); - - //check the link available for payment is the link balance - assertEq(feeManager.linkAvailableForPayment(), getLinkBalance(address(feeManager))); - } - - function test_payLinkDeficit() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //not enough funds in the reward pool should trigger an insufficient link event - vm.expectEmit(); - - IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); - contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - emit InsufficientLink(contractFees); - - //process the fee - processFee(payload, USER, address(native), 0); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - } - - function test_payLinkDeficitTwice() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //not enough funds in the reward pool should trigger an insufficient link event - vm.expectEmit(); - - IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); - contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - //emit the event that is expected to be emitted - emit InsufficientLink(contractFees); - - //process the fee - processFee(payload, USER, address(native), 0); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //paying again should revert with 0 - vm.expectRevert(ZERO_DEFICIT); - - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - } - - function test_payLinkDeficitPaysAllFeesProcessed() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 2, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(payload, USER, address(native), 0); - processFee(payload, USER, address(native), 0); - - //check the deficit has been increased twice - assertEq(getLinkDeficit(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE * 2); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 2); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE * 2); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); - } - - function test_payLinkDeficitOnlyCallableByAdmin() public { - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - payLinkDeficit(DEFAULT_CONFIG_DIGEST, USER); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol deleted file mode 100644 index 1b0f95d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.getFeeAndReward.t.sol +++ /dev/null @@ -1,606 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Common} from "../../../libraries/Common.sol"; -import "./BaseFeeManager.t.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager's getFeeAndReward - */ -contract FeeManagerProcessFeeTest is BaseFeeManagerTest { - function test_baseFeeIsAppliedForNative() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_baseFeeIsAppliedForLink() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_discountAIsNotAppliedWhenSetForOtherUsers() public { - //set the subscriber discount for another user - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), INVALID_ADDRESS); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_discountIsNotAppliedForInvalidTokenAddress() public { - //should revert with invalid address as it's not a configured token - vm.expectRevert(INVALID_ADDRESS_ERROR); - - //set the subscriber discount for another user - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, INVALID_ADDRESS, FEE_SCALAR / 2, ADMIN); - } - - function test_discountIsAppliedForLink() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_DiscountIsAppliedForNative() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE / 2); - } - - function test_discountIsNoLongerAppliedAfterRemoving() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); - - //remove the discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), 0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_surchargeIsApplied() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - } - - function test_surchargeIsNotAppliedForLinkFee() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_surchargeIsNoLongerAppliedAfterRemoving() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should be the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - - //remove the surcharge - setNativeSurcharge(0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_feeIsUpdatedAfterNewSurchargeIsApplied() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - - //change the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - } - - function test_surchargeIsAppliedForNativeFeeWithDiscount() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge quantity - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //calculate the expected discount quantity - uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge) / 2); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge - expectedDiscount); - } - - function test_emptyQuoteRevertsWithError() public { - //expect a revert - vm.expectRevert(INVALID_QUOTE_ERROR); - - //get the fee required by the feeManager - getFee(getV3Report(DEFAULT_FEED_1_V3), address(0), USER); - } - - function test_nativeSurcharge100Percent() public { - //set the surcharge - setNativeSurcharge(FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be twice the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2); - } - - function test_nativeSurcharge0Percent() public { - //set the surcharge - setNativeSurcharge(0, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_nativeSurchargeCannotExceed100Percent() public { - //should revert if surcharge is greater than 100% - vm.expectRevert(INVALID_SURCHARGE_ERROR); - - //set the surcharge above the max - setNativeSurcharge(FEE_SCALAR + 1, ADMIN); - } - - function test_discountIsAppliedWith100PercentSurcharge() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE; - - //fee should be twice the surcharge minus the discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2 - expectedDiscount); - } - - function test_feeIsZeroWith100PercentDiscount() public { - //set the subscriber discount to 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_feeIsUpdatedAfterDiscountIsRemoved() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; - - //fee should be 50% of the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - - //remove the discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), 0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_feeIsUpdatedAfterNewDiscountIsApplied() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; - - //fee should be 50% of the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - - //change the discount to 25% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //expected discount is now 25% - expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 4; - - //fee should be the base fee minus the expected discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - } - - function test_setDiscountOver100Percent() public { - //should revert with invalid discount - vm.expectRevert(INVALID_DISCOUNT_ERROR); - - //set the subscriber discount to over 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR + 1, ADMIN); - } - - function test_surchargeIsNotAppliedWith100PercentDiscount() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the subscriber discount to 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_nonAdminUserCanNotSetDiscount() public { - //should revert with unauthorized - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, USER); - } - - function test_surchargeFeeRoundsUpWhenUneven() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 3; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge quantity - uint256 expectedSurcharge = (DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR; - - //expected fee should the base fee offset by the expected surcharge - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge + 1); - } - - function test_discountFeeRoundsDownWhenUneven() public { - //native surcharge - uint256 discount = FEE_SCALAR / 3; - - //set the subscriber discount to 33.333% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected quantity - uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE * discount) / FEE_SCALAR); - - //expected fee should the base fee offset by the expected surcharge - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - } - - function test_reportWithNoExpiryOrFeeReturnsZero() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV1Report(DEFAULT_FEED_1_V1), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() public { - //set the subscriber and native discounts - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager for both tokens - Common.Asset memory linkFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - Common.Asset memory nativeFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity for each token - uint256 expectedDiscountLink = (DEFAULT_REPORT_LINK_FEE * FEE_SCALAR) / 4 / FEE_SCALAR; - uint256 expectedDiscountNative = (DEFAULT_REPORT_NATIVE_FEE * FEE_SCALAR) / 2 / FEE_SCALAR; - - //check the fee calculation for each token - assertEq(linkFee.amount, DEFAULT_REPORT_LINK_FEE - expectedDiscountLink); - assertEq(nativeFee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscountNative); - } - - function test_discountIsNotAppliedToOtherFeeds() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_2_V3), getNativeQuote(), USER); - - //fee should be the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_noFeeIsAppliedWhenReportHasZeroFee() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), - getNativeQuote(), - USER - ); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), - getNativeQuote(), - USER - ); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_nativeSurchargeEventIsEmittedOnUpdate() public { - //native surcharge - uint64 nativeSurcharge = FEE_SCALAR / 3; - - //an event should be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit NativeSurchargeUpdated(nativeSurcharge); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - } - - function test_getBaseRewardWithLinkQuote() public view { - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithLinkQuoteAndLinkDiscount() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the discounted base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_getRewardWithNativeQuote() public view { - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithNativeQuoteAndSurcharge() public { - //set the native surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link regardless of the surcharge - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithLinkDiscount() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the discounted base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_getLinkFeeIsRoundedUp() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal .66% + 1 of the base fee due to a 33% discount rounded up - assertEq(fee.amount, (DEFAULT_REPORT_LINK_FEE * 2) / 3 + 1); - } - - function test_getLinkRewardIsSameAsFee() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //check the reward is in link - assertEq(fee.assetAddress, address(link)); - - //the reward should equal .66% of the base fee due to a 33% discount rounded down - assertEq(reward.amount, fee.amount); - } - - function test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() public { - //set the native surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link regardless of the surcharge - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_testRevertIfReportHasExpired() public { - //expect a revert - vm.expectRevert(EXPIRED_REPORT_ERROR); - - //get the fee required by the feeManager - getFee( - getV3ReportWithCustomExpiryAndFee( - DEFAULT_FEED_1_V3, - block.timestamp - 1, - DEFAULT_REPORT_LINK_FEE, - DEFAULT_REPORT_NATIVE_FEE - ), - getNativeQuote(), - USER - ); - } - - function test_discountIsReturnedForLink() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_DiscountIsReturnedForNative() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_DiscountIsReturnedForNativeWithSurcharge() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR / 5, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol deleted file mode 100644 index 0e0ed89..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFee.t.sol +++ /dev/null @@ -1,492 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Common} from "../../../libraries/Common.sol"; -import "./BaseFeeManager.t.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager processFee - */ -contract FeeManagerProcessFeeTest is BaseFeeManagerTest { - function setUp() public override { - super.setUp(); - } - - function test_nonAdminProxyUserCannotProcessFee() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //should revert as the user is not the owner - vm.expectRevert(UNAUTHORIZED_ERROR); - - //process the fee - ProcessFeeAsUser(payload, USER, address(link), 0, USER); - } - - function test_processFeeAsProxy() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_processFeeIfSubscriberIsSelf() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert due to the feeManager being the subscriber - vm.expectRevert(INVALID_ADDRESS_ERROR); - - //process the fee will fail due to assertion - processFee(payload, address(feeManager), address(native), 0); - } - - function test_processFeeWithWithEmptyQuotePayload() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link by default - processFee(payload, USER, address(0), 0); - } - - function test_processFeeWithWithZeroQuotePayload() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as the quote is invalid - vm.expectRevert(INVALID_QUOTE_ERROR); - - //processing the fee will transfer the link by default - processFee(payload, USER, INVALID_ADDRESS, 0); - } - - function test_processFeeWithWithCorruptQuotePayload() public { - //get the default payload - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV3Report(DEFAULT_FEED_1_V3), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - //expect an evm revert as the quote is corrupt - vm.expectRevert(); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(payload, USER, address(link), 0); - } - - function test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() public { - //get the default payload - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(0), 0); - } - - function test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() public { - //get the default payload - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(payload, USER, address(link), 0); - } - - function test_processFeeNative() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeEmitsEventIfNotEnoughLink() public { - //simulate a deposit of half the link required for the fee - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE / 2); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //expect an emit as there's not enough link - vm.expectEmit(); - - IRewardManager.FeePayment[] memory contractFees = new IRewardManager.FeePayment[](1); - contractFees[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - //emit the event that is expected to be emitted - emit InsufficientLink(contractFees); - - //processing the fee will transfer the native from the user to the feeManager - processFee(payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check no link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), 0); - assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE / 2); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithUnwrappedNative() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //only the proxy or admin can call processFee, they will pass in the native value on the users behalf - processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE); - - //check the native has been transferred and converted to wrapped native - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeUnwrappedBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithUnwrappedNativeShortFunds() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as not enough funds - vm.expectRevert(INVALID_DEPOSIT_ERROR); - - //only the proxy or admin can call processFee, they will pass in the native value on the users behalf - processFee(payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE - 1); - } - - function test_processFeeWithUnwrappedNativeLinkAddress() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as not enough funds - vm.expectRevert(INSUFFICIENT_ALLOWANCE_ERROR); - - //the change will be returned and the user will attempted to be billed in LINK - processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE - 1); - } - - function test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() public { - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, PROXY); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. - processFee(payload, PROXY, address(link), DEFAULT_REPORT_NATIVE_FEE); - - //check the native unwrapped is no longer in the account - assertEq(getNativeBalance(address(feeManager)), 0); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //native should not be deducted - assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processFeeWithUnwrappedNativeWithExcessiveFee() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. - processFee(payload, PROXY, address(native), DEFAULT_REPORT_NATIVE_FEE * 2); - - //check the native has been transferred and converted to wrapped native - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeUsesCorrectDigest() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - - //check funds have been paid to the reward manager - assertEq(rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE); - } - - function test_V1PayloadVerifies() public { - //replicate a default payload - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV2Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(0), 0); - } - - function test_V2PayloadVerifies() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_V2PayloadWithoutQuoteFails() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(0), 0); - } - - function test_V2PayloadWithoutZeroFee() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(payload, USER, address(link), 0); - } - - function test_processFeeWithInvalidReportVersionFailsToDecode() public { - bytes memory data = abi.encode(0x0000100000000000000000000000000000000000000000000000000000000000); - - //get the default payload - bytes memory payload = getPayload(data); - - //serialization will fail as there is no report to decode - vm.expectRevert(); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(payload, USER, address(link), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) - ); - - //call processFee should not revert as the fee is 0 - processFee(payload, PROXY, address(native), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) - ); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link to the rewardManager from the user - processFee(payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check no link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), 0); - - //check the feeManager has had no link deducted - assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //call processFee should not revert as the fee is 0 - processFee(payload, USER, address(link), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkReturnsChange() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //call processFee should not revert as the fee is 0 - processFee(payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE); - - //check the change has been returned - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_V1PayloadVerifiesAndReturnsChange() public { - //emulate a V1 payload with no quote - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - processFee(payload, USER, address(0), DEFAULT_REPORT_NATIVE_FEE); - - //Fee manager should not contain any native - assertEq(address(feeManager).balance, 0); - assertEq(getNativeBalance(address(feeManager)), 0); - - //check the unused native passed in is returned - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processFeeWithDiscountEmitsEvent() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE / 2, USER); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - uint256 appliedDiscount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - vm.expectEmit(); - - emit DiscountApplied(DEFAULT_CONFIG_DIGEST, USER, fee, reward, appliedDiscount); - - //call processFee should not revert as the fee is 0 - processFee(payload, USER, address(native), 0); - } - - function test_processFeeWithNoDiscountDoesNotEmitEvent() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee should not revert as the fee is 0 - processFee(payload, USER, address(native), 0); - - //no logs should have been emitted - assertEq(vm.getRecordedLogs().length, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol deleted file mode 100644 index fa77b98..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/fee-manager/FeeManager.processFeeBulk.t.sol +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import "./BaseFeeManager.t.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager processFee - */ -contract FeeManagerProcessFeeTest is BaseFeeManagerTest { - uint256 internal constant NUMBER_OF_REPORTS = 5; - - function setUp() public override { - super.setUp(); - } - - function test_processMultipleLinkReports() public { - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); - - processFee(payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); - - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 0); - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - - //the subscriber (user) should receive funds back and not the proxy, although when live the proxy will forward the funds sent and not cover it seen here - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processMultipleWrappedNativeReports() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS, USER); - - processFee(payloads, USER, address(native), 0); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 1); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - } - - function test_processMultipleUnwrappedNativeReports() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - } - - function test_processV1V2V3Reports() public { - mintLink(address(feeManager), 1); - - bytes memory payloadV1 = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes memory linkPayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - bytes memory linkPayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = payloadV1; - payloads[1] = linkPayloadV2; - payloads[2] = linkPayloadV2; - payloads[3] = linkPayloadV3; - payloads[4] = linkPayloadV3; - - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * 4, USER); - - processFee(payloads, USER, address(link), 0); - - assertEq(getNativeBalance(address(feeManager)), 0); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - 0); - } - - function test_processV1V2V3ReportsWithUnwrapped() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 4 + 1); - - bytes memory payloadV1 = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes memory nativePayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - bytes memory nativePayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = payloadV1; - payloads[1] = nativePayloadV2; - payloads[2] = nativePayloadV2; - payloads[3] = nativePayloadV3; - payloads[4] = nativePayloadV3; - - processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 4); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 4); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 4); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processMultipleV1Reports() public { - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - processFee(payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 5); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_eventIsEmittedIfNotEnoughLink() public { - bytes memory nativePayload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = nativePayload; - payloads[1] = nativePayload; - payloads[2] = nativePayload; - payloads[3] = nativePayload; - payloads[4] = nativePayload; - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 5, USER); - - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](5); - payments[0] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[1] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[2] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[3] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[4] = IRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - vm.expectEmit(); - - emit InsufficientLink(payments); - - processFee(payloads, USER, address(native), 0); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol deleted file mode 100644 index ee8ba4c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/gas/Gas_VerifierTest.t.sol +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "../verifier/BaseVerifierTest.t.sol"; -import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -contract Verifier_setConfig is BaseTest { - address[] internal s_signerAddrs; - - function setUp() public override { - BaseTest.setUp(); - Signer[] memory signers = _getSigners(MAX_ORACLES); - s_signerAddrs = _getSignerAddresses(signers); - s_verifierProxy.initializeVerifier(address(s_verifier)); - } - - function testSetConfigSuccess_gas() public { - s_verifier.setConfig( - FEED_ID, - s_signerAddrs, - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } -} - -contract Verifier_verifyWithFee is BaseTestWithConfiguredVerifierAndFeeManager { - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - function setUp() public virtual override { - super.setUp(); - - //mint some link and eth to warm the storage - link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); - native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); - - //warm the rewardManager - link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); - (, , bytes32 latestConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some link tokens to the feeManager pool - link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //approve funds prior to test - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); - payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); - - changePrank(address(feeManager)); - rewardManager.onFeePaid(payments, address(this)); - - changePrank(USER); - } - - function testVerifyProxyWithLinkFeeSuccess_gas() public { - bytes memory signedLinkPayload = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - s_verifierProxy.verify(signedLinkPayload, abi.encode(link)); - } - - function testVerifyProxyWithNativeFeeSuccess_gas() public { - bytes memory signedNativePayload = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - s_verifierProxy.verify(signedNativePayload, abi.encode(native)); - } -} - -contract Verifier_bulkVerifyWithFee is BaseTestWithConfiguredVerifierAndFeeManager { - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - uint256 internal constant NUMBER_OF_REPORTS_TO_VERIFY = 5; - - function setUp() public virtual override { - super.setUp(); - - //mint some link and eth to warm the storage - link.mint(address(rewardManager), DEFAULT_LINK_MINT_QUANTITY); - native.mint(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); - - //warm the rewardManager - link.mint(address(this), DEFAULT_NATIVE_MINT_QUANTITY); - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, address(this)); - (, , bytes32 latestConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some link tokens to the feeManager pool - link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY); - - //approve funds prior to test - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS_TO_VERIFY, USER); - - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); - payments[0] = IRewardManager.FeePayment(latestConfigDigest, uint192(DEFAULT_REPORT_LINK_FEE)); - - changePrank(address(feeManager)); - rewardManager.onFeePaid(payments, address(this)); - - changePrank(USER); - } - - function testBulkVerifyProxyWithLinkFeeSuccess_gas() public { - bytes memory signedLinkPayload = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedLinkPayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); - for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { - signedLinkPayloads[i] = signedLinkPayload; - } - - s_verifierProxy.verifyBulk(signedLinkPayloads, abi.encode(link)); - } - - function testBulkVerifyProxyWithNativeFeeSuccess_gas() public { - bytes memory signedNativePayload = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedNativePayloads = new bytes[](NUMBER_OF_REPORTS_TO_VERIFY); - for (uint256 i = 0; i < NUMBER_OF_REPORTS_TO_VERIFY; i++) { - signedNativePayloads[i] = signedNativePayload; - } - - s_verifierProxy.verifyBulk(signedNativePayloads, abi.encode(native)); - } -} - -contract Verifier_verify is BaseTestWithConfiguredVerifierAndFeeManager { - bytes internal s_signedReport; - bytes32 internal s_configDigest; - - function setUp() public override { - BaseTestWithConfiguredVerifierAndFeeManager.setUp(); - BaseTest.V1Report memory s_testReportOne = _createV1Report( - FEED_ID, - OBSERVATIONS_TIMESTAMP, - MEDIAN, - BID, - ASK, - BLOCKNUMBER_UPPER_BOUND, - blockhash(BLOCKNUMBER_UPPER_BOUND), - BLOCKNUMBER_LOWER_BOUND, - uint32(block.timestamp) - ); - (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); - bytes32[3] memory reportContext; - reportContext[0] = s_configDigest; - reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); - } - - function testVerifySuccess_gas() public { - changePrank(address(s_verifierProxy)); - - s_verifier.verify(s_signedReport, msg.sender); - } - - function testVerifyProxySuccess_gas() public { - s_verifierProxy.verify(s_signedReport, abi.encode(native)); - } -} - -contract Verifier_accessControlledVerify is BaseTestWithConfiguredVerifierAndFeeManager { - bytes internal s_signedReport; - bytes32 internal s_configDigest; - SimpleWriteAccessController s_accessController; - - address internal constant CLIENT = address(9000); - address internal constant ACCESS_CONTROLLER_ADDR = address(10000); - - function setUp() public override { - BaseTestWithConfiguredVerifierAndFeeManager.setUp(); - BaseTest.V1Report memory s_testReportOne = _createV1Report( - FEED_ID, - OBSERVATIONS_TIMESTAMP, - MEDIAN, - BID, - ASK, - BLOCKNUMBER_UPPER_BOUND, - blockhash(BLOCKNUMBER_UPPER_BOUND), - BLOCKNUMBER_LOWER_BOUND, - uint32(block.timestamp) - ); - (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); - bytes32[3] memory reportContext; - reportContext[0] = s_configDigest; - reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - s_signedReport = _generateV1EncodedBlob(s_testReportOne, reportContext, _getSigners(FAULT_TOLERANCE + 1)); - s_accessController = new SimpleWriteAccessController(); - s_verifierProxy.setAccessController(s_accessController); - s_accessController.addAccess(CLIENT); - } - - function testVerifyWithAccessControl_gas() public { - changePrank(CLIENT); - s_verifierProxy.verify(s_signedReport, abi.encode(native)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol deleted file mode 100644 index e9dcd58..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ErroredVerifier.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {IVerifier} from "../../interfaces/IVerifier.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract ErroredVerifier is IVerifier { - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return interfaceId == this.verify.selector; - } - - //define each of the errors thrown in the revert below - - error FailedToVerify(); - error FailedToSetConfig(); - error FailedToActivateConfig(); - error FailedToDeactivateConfig(); - error FailedToActivateFeed(); - error FailedToDeactivateFeed(); - error FailedToGetLatestConfigDigestAndEpoch(); - error FailedToGetLatestConfigDetails(); - - function verify( - bytes memory, - /** - * signedReport* - */ - address - ) - external - pure - override - returns ( - /** - * sender* - */ - bytes memory - ) - { - revert FailedToVerify(); - } - - function setConfig( - bytes32, - address[] memory, - bytes32[] memory, - uint8, - bytes memory, - uint64, - bytes memory, - Common.AddressAndWeight[] memory - ) external pure override { - revert FailedToSetConfig(); - } - - function setConfigFromSource( - bytes32, - uint256, - address, - uint32, - address[] memory, - bytes32[] memory, - uint8, - bytes memory, - uint64, - bytes memory, - Common.AddressAndWeight[] memory - ) external pure override { - revert FailedToSetConfig(); - } - - function activateConfig(bytes32, bytes32) external pure { - revert FailedToActivateConfig(); - } - - function deactivateConfig(bytes32, bytes32) external pure { - revert FailedToDeactivateConfig(); - } - - function activateFeed(bytes32) external pure { - revert FailedToActivateFeed(); - } - - function deactivateFeed(bytes32) external pure { - revert FailedToDeactivateFeed(); - } - - function latestConfigDigestAndEpoch(bytes32) external pure override returns (bool, bytes32, uint32) { - revert FailedToGetLatestConfigDigestAndEpoch(); - } - - function latestConfigDetails(bytes32) external pure override returns (uint32, uint32, bytes32) { - revert FailedToGetLatestConfigDetails(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol deleted file mode 100644 index 1c004bf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/ExposedVerifier.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -// ExposedVerifier exposes certain internal Verifier -// methods/structures so that golang code can access them, and we get -// reliable type checking on their usage -contract ExposedVerifier { - constructor() {} - - function _configDigestFromConfigData( - bytes32 feedId, - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - feedId, - chainId, - contractAddress, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - function exposedConfigDigestFromConfigData( - bytes32 _feedId, - uint256 _chainId, - address _contractAddress, - uint64 _configCount, - address[] memory _signers, - bytes32[] memory _offchainTransmitters, - uint8 _f, - bytes calldata _onchainConfig, - uint64 _encodedConfigVersion, - bytes memory _encodedConfig - ) public pure returns (bytes32) { - return - _configDigestFromConfigData( - _feedId, - _chainId, - _contractAddress, - _configCount, - _signers, - _offchainTransmitters, - _f, - _onchainConfig, - _encodedConfigVersion, - _encodedConfig - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol deleted file mode 100644 index 9abb4c5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/mocks/FeeManagerProxy.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IFeeManager} from "../../interfaces/IFeeManager.sol"; - -contract FeeManagerProxy { - IFeeManager internal s_feeManager; - - function processFee(bytes calldata payload, bytes calldata parameterPayload) public payable { - s_feeManager.processFee{value: msg.value}(payload, parameterPayload, msg.sender); - } - - function processFeeBulk(bytes[] calldata payloads, bytes calldata parameterPayload) public payable { - s_feeManager.processFeeBulk{value: msg.value}(payloads, parameterPayload, msg.sender); - } - - function setFeeManager(IFeeManager feeManager) public { - s_feeManager = feeManager; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol deleted file mode 100644 index c7bd752..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/BaseRewardManager.t.sol +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {RewardManager} from "../../../v0.3.0/RewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice Base class for all reward manager tests - * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup a primary and secondary pool - */ -contract BaseRewardManagerTest is Test { - //contracts - ERC20Mock internal asset; - ERC20Mock internal unsupported; - RewardManager internal rewardManager; - - //default address for unregistered recipient - address internal constant INVALID_ADDRESS = address(0); - //contract owner - address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); - //address to represent verifier contract - address internal constant FEE_MANAGER = address(uint160(uint256(keccak256("FEE_MANAGER")))); - //a general user - address internal constant USER = address(uint160(uint256(keccak256("USER")))); - - //default recipients configured in reward manager - address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); - address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); - address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); - address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); - address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); - address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); - address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); - - //additional recipients not in the reward manager - address internal constant DEFAULT_RECIPIENT_8 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_8")))); - address internal constant DEFAULT_RECIPIENT_9 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_9")))); - - //two pools should be enough to test all edge cases - bytes32 internal constant PRIMARY_POOL_ID = keccak256("primary_pool"); - bytes32 internal constant SECONDARY_POOL_ID = keccak256("secondary_pool"); - bytes32 internal constant INVALID_POOL_ID = keccak256("invalid_pool"); - bytes32 internal constant ZERO_POOL_ID = bytes32(0); - - //convenience arrays of all pool combinations used for testing - bytes32[] internal PRIMARY_POOL_ARRAY = [PRIMARY_POOL_ID]; - bytes32[] internal SECONDARY_POOL_ARRAY = [SECONDARY_POOL_ID]; - bytes32[] internal ALL_POOLS = [PRIMARY_POOL_ID, SECONDARY_POOL_ID]; - - //erc20 config - uint256 internal constant DEFAULT_MINT_QUANTITY = 100 ether; - - //reward scalar (this should match the const in the contract) - uint64 internal constant POOL_SCALAR = 1e18; - uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; - uint64 internal constant FIFTY_PERCENT = POOL_SCALAR / 2; - uint64 internal constant TEN_PERCENT = POOL_SCALAR / 10; - - //the selector for each error - bytes4 internal immutable UNAUTHORIZED_ERROR_SELECTOR = RewardManager.Unauthorized.selector; - bytes4 internal immutable INVALID_ADDRESS_ERROR_SELECTOR = RewardManager.InvalidAddress.selector; - bytes4 internal immutable INVALID_WEIGHT_ERROR_SELECTOR = RewardManager.InvalidWeights.selector; - bytes4 internal immutable INVALID_POOL_ID_ERROR_SELECTOR = RewardManager.InvalidPoolId.selector; - bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; - bytes4 internal immutable INVALID_POOL_LENGTH_SELECTOR = RewardManager.InvalidPoolLength.selector; - - // Events emitted within the reward manager - event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); - event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); - event FeeManagerUpdated(address newProxyAddress); - event FeePaid(IRewardManager.FeePayment[] payments, address payee); - - function setUp() public virtual { - //change to admin user - vm.startPrank(ADMIN); - - //init required contracts - _initializeERC20Contracts(); - _initializeRewardManager(); - } - - function _initializeERC20Contracts() internal { - //create the contracts - asset = new ERC20Mock("ASSET", "AST", ADMIN, 0); - unsupported = new ERC20Mock("UNSUPPORTED", "UNS", ADMIN, 0); - - //mint some tokens to the admin - asset.mint(ADMIN, DEFAULT_MINT_QUANTITY); - unsupported.mint(ADMIN, DEFAULT_MINT_QUANTITY); - - //mint some tokens to the user - asset.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); - unsupported.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); - } - - function _initializeRewardManager() internal { - //create the contract - rewardManager = new RewardManager(address(asset)); - - rewardManager.setFeeManager(FEE_MANAGER); - } - - function createPrimaryPool() public { - rewardManager.setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients()); - } - - function createSecondaryPool() public { - rewardManager.setRewardRecipients(SECONDARY_POOL_ID, getSecondaryRecipients()); - } - - //override this to test variations of different recipients. changing this function will require existing tests to be updated as constants are hardcoded to be explicit - function getPrimaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights. 2500 = 25% of pool - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); - - return recipients; - } - - function getPrimaryRecipientAddresses() public pure returns (address[] memory) { - //array of recipients - address[] memory recipients = new address[](4); - - recipients[0] = DEFAULT_RECIPIENT_1; - recipients[1] = DEFAULT_RECIPIENT_2; - recipients[2] = DEFAULT_RECIPIENT_3; - recipients[3] = DEFAULT_RECIPIENT_4; - - return recipients; - } - - //override this to test variations of different recipients. - function getSecondaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights. 2500 = 25% of pool - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); - - return recipients; - } - - function getSecondaryRecipientAddresses() public pure returns (address[] memory) { - //array of recipients - address[] memory recipients = new address[](4); - - recipients[0] = DEFAULT_RECIPIENT_1; - recipients[1] = DEFAULT_RECIPIENT_5; - recipients[2] = DEFAULT_RECIPIENT_6; - recipients[3] = DEFAULT_RECIPIENT_7; - - return recipients; - } - - function addFundsToPool(bytes32 poolId, Common.Asset memory amount, address sender) public { - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); - payments[0] = IRewardManager.FeePayment(poolId, uint192(amount.amount)); - - addFundsToPool(payments, sender); - } - - function addFundsToPool(IRewardManager.FeePayment[] memory payments, address sender) public { - //record the current address and switch to the sender - address originalAddr = msg.sender; - changePrank(sender); - - uint256 totalPayment; - for (uint256 i; i < payments.length; ++i) { - totalPayment += payments[i].amount; - } - - //approve the amount being paid into the pool - ERC20Mock(address(asset)).approve(address(rewardManager), totalPayment); - - //this represents the verifier adding some funds to the pool - rewardManager.onFeePaid(payments, sender); - - //change back to the original address - changePrank(originalAddr); - } - - function getAsset(uint256 quantity) public view returns (Common.Asset memory) { - return Common.Asset(address(asset), quantity); - } - - function getAssetBalance(address addr) public view returns (uint256) { - return asset.balanceOf(addr); - } - - function claimRewards(bytes32[] memory poolIds, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //claim the rewards - rewardManager.claimRewards(poolIds); - - //change back to the original address - changePrank(originalAddr); - } - - function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.payRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.setRewardRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - function setFeeManager(address feeManager, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //update the proxy - rewardManager.setFeeManager(feeManager); - - //change back to the original address - changePrank(originalAddr); - } - - function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.updateRewardRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol deleted file mode 100644 index efbe9fd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.claim.t.sol +++ /dev/null @@ -1,790 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice This contract will test the claim functionality of the RewardManager contract. - */ -contract RewardManagerClaimTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipients() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } - - function test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() public { - //add funds to a different pool to ensure they're not claimed - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create an array containing duplicate poolIds - bytes32[] memory poolIds = new bytes32[](2); - poolIds[0] = PRIMARY_POOL_ID; - poolIds[1] = PRIMARY_POOL_ID; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(poolIds, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the pool should still have the remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimSingleRecipient() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); - } - - function test_claimMultipleRecipients() public { - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - (expectedRecipientAmount * 2)); - } - - function test_claimUnregisteredRecipient() public { - //claim the rewards for a recipient who isn't in this pool - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //check the recipients didn't receive any fees from this pool - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimUnevenAmountRoundsDown() public { - //adding 1 to the pool should leave 1 wei worth of dust, which the contract doesn't handle due to it being economically infeasible - addFundsToPool(PRIMARY_POOL_ID, getAsset(1), FEE_MANAGER); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //check the rewardManager has the remaining quantity equals 1 wei - assertEq(getAssetBalance(address(rewardManager)), 1); - } - - function test_claimUnregisteredPoolId() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the recipients balance is still 0 as there's no pool to receive fees from - assertEq(getAssetBalance(recipient.addr), 0); - - //check the rewardManager has the full amount - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_singleRecipientClaimMultipleDeposits() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); - - //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); - } - - function test_recipientsClaimMultipleDeposits() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should be 0 as all of the funds have been claimed - assertEq(getAssetBalance(address(rewardManager)), 0); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should again be 0 as all of the funds have been claimed - assertEq(getAssetBalance(address(rewardManager)), 0); - } - - function test_eventIsEmittedUponClaim() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardsClaimed(PRIMARY_POOL_ID, recipient.addr, uint192(POOL_DEPOSIT_AMOUNT / 4)); - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - } - - function test_eventIsNotEmittedUponUnsuccessfulClaim() public { - //record logs to check no events were emitted - vm.recordLogs(); - - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //no logs should have been emitted - assertEq(vm.getRecordedLogs().length, 0); - } -} - -contract RewardManagerRecipientClaimMultiplePoolsTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a two pools - createPrimaryPool(); - createSecondaryPool(); - - //add funds to each of the pools to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipientsSinglePool() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //check the pool balance is still equal to DEPOSIT_AMOUNT as the test only claims for one of the pools - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimMultipleRecipientsSinglePool() public { - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); - } - - function test_claimMultipleRecipientsMultiplePools() public { - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received. The first recipient is shared across both pools so should receive 1/4 of each pool - assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount * 2); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimAllRecipientsMultiplePools() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i = 1; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //claim funds for each recipient within the pool - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory secondaryRecipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, secondaryRecipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(secondaryRecipient.addr), expectedRecipientAmount); - } - - //special case to handle the first recipient of each pool as they're the same address - Common.AddressAndWeight memory commonRecipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for each pool - claimRewards(PRIMARY_POOL_ARRAY, commonRecipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, commonRecipient.addr); - - //check the balance matches the ratio the recipient should have received, which is 1/4 of each deposit for each pool - assertEq(getAssetBalance(commonRecipient.addr), expectedRecipientAmount * 2); - } - - function test_claimSingleUniqueRecipient() public { - //the first recipient of the secondary pool is in both pools, so take the second recipient which is unique - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[1]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount - uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; - - //the recipient should have received 1/4 of the deposit amount - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); - } - - function test_claimSingleRecipientMultiplePools() public { - //the first recipient of the secondary pool is in both pools - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount for each pool - uint256 recipientExpectedAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; - - //this recipient belongs in both pools so should have received 1/4 of each - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); - } - - function test_claimUnregisteredRecipient() public { - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - claimRewards(SECONDARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - - //check the recipients didn't receive any fees from this pool - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), 0); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2); - } - - function test_claimUnevenAmountRoundsDown() public { - //adding an uneven amount of dust to each pool, this should round down to the nearest whole number with 4 remaining in the contract - addFundsToPool(PRIMARY_POOL_ID, getAsset(3), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(1), FEE_MANAGER); - - //the recipient should have received 1/4 of the deposit amount for each pool - uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - } - - //special case to handle the first recipient of each pool as they're the same address - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), recipientExpectedAmount * 2); - - //claim funds for each recipient of the secondary pool except the first - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - } - - //contract should have 4 remaining - assertEq(getAssetBalance(address(rewardManager)), 4); - } - - function test_singleRecipientClaimMultipleDeposits() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit plus the deposit from the second pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - expectedRecipientAmount); - - //add funds to the pool to be split among the recipients - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the next deposit amount - expectedRecipientAmount += POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 3 - expectedRecipientAmount); - } - - function test_recipientsClaimMultipleDeposits() public { - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should contain only the funds of the secondary pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - - //add funds to the pool to be split among the recipients - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //special case to handle the first recipient of each pool as they're the same address - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount * 2); - - //claim funds for each recipient within the pool except the first - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); - } - - //the reward manager balance should again be the balance of the secondary pool as the primary pool has been emptied twice - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimEmptyPoolWhenSecondPoolContainsFunds() public { - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim all rewards for each recipient in the primary pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //claim all the rewards again for the first recipient as that address is a member of both pools - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); - } - - function test_getRewardsAvailableToRecipientInBothPools() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[0].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], SECONDARY_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInSinglePool() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[1].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInNoPools() public view { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, 0, type(uint256).max); - - //check the recipient is in neither pool - assertEq(poolIds[0], ZERO_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[0].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], SECONDARY_POOL_ID); - - //claim the rewards for each pool - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //get the available pools again - poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, type(uint256).max); - - //user should not be in any pool - assertEq(poolIds[0], ZERO_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() public { - vm.expectRevert(INVALID_POOL_LENGTH_SELECTOR); - - rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, type(uint256).max, 0); - } - - function test_getAvailableRewardsCursorAndTotalPoolsEqual() public { - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 2, 2); - - assertEq(poolIds.length, 0); - } - - function test_getAvailableRewardsCursorSingleResult() public { - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, 1); - - assertEq(poolIds[0], PRIMARY_POOL_ID); - } -} - -contract RewardManagerRecipientClaimDifferentWeightsTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with uneven weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 8); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 6); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 4); - - return recipients; - } - - function test_allRecipientsClaimingReceiveExpectedAmount() public { - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } -} - -contract RewardManagerRecipientClaimUnevenWeightTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - } - - function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - - uint64 oneThird = POOL_SCALAR / 3; - - //init each recipient with even weights. - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, oneThird); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 2 * oneThird + 1); - - return recipients; - } - - function test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() public { - //add a smaller amount of funds to the pool - uint256 smallDeposit = 1e8; - - //add a smaller amount of funds to the pool - addFundsToPool(PRIMARY_POOL_ID, getAsset(smallDeposit), FEE_MANAGER); - - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (smallDeposit * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //smaller deposits will consequently have less precision and will not be able to be split as evenly, the remaining 1 will be lost due to 333...|... being paid out instead of 333...4| - assertEq(getAssetBalance(address(rewardManager)), 1); - } - - function test_allRecipientsClaimingReceiveExpectedAmount() public { - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //their should be 0 wei left over indicating a successful split - assertEq(getAssetBalance(address(rewardManager)), 0); - } -} - -contract RewardManagerNoRecipientSet is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //add funds to the pool to be split among the recipients once registered - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipientsAfterRecipientsSet() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //try and claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //there should be no rewards claimed as the recipient is not registered - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the recipient received nothing - assertEq(getAssetBalance(recipient.addr), 0); - } - - //Set the recipients after the rewards have been paid into the pool - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //there should be no rewards claimed as the recipient is registered - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol deleted file mode 100644 index baff388..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.general.t.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; -import {RewardManager} from "../../../v0.3.0/RewardManager.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice This contract will test the core functionality of the RewardManager contract - */ -contract RewardManagerSetupTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - } - - function test_rejectsZeroLinkAddressOnConstruction() public { - //should revert if the contract is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //create a rewardManager with a zero link address - new RewardManager(address(0)); - } - - function test_eventEmittedUponFeeManagerUpdate() public { - //expect the event to be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit FeeManagerUpdated(FEE_MANAGER); - - //set the verifier proxy - setFeeManager(FEE_MANAGER, ADMIN); - } - - function test_eventEmittedUponFeePaid() public { - //create pool and add funds - createPrimaryPool(); - - //change to the feeManager who is the one who will be paying the fees - changePrank(FEE_MANAGER); - - //approve the amount being paid into the pool - ERC20Mock(getAsset(POOL_DEPOSIT_AMOUNT).assetAddress).approve(address(rewardManager), POOL_DEPOSIT_AMOUNT); - - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); - payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); - - //event is emitted when funds are added - vm.expectEmit(); - emit FeePaid(payments, FEE_MANAGER); - - //this represents the verifier adding some funds to the pool - rewardManager.onFeePaid(payments, FEE_MANAGER); - } - - function test_setFeeManagerZeroAddress() public { - //should revert if the contract is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the verifier proxy - setFeeManager(address(0), ADMIN); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol deleted file mode 100644 index 89fac66..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.payRecipients.t.sol +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; -import {IRewardManager} from "../../interfaces/IRewardManager.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice This contract will test the payRecipients functionality of the RewardManager contract - */ -contract RewardManagerPayRecipientsTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_payAllRecipients() public { - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); - - //each recipient should receive 1/4 of the pool - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_paySingleRecipient() public { - //get the first individual recipient - address recipient = getPrimaryRecipientAddresses()[0]; - - //get a single recipient as an array - address[] memory recipients = new address[](1); - recipients[0] = recipient; - - //pay a single recipient - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - assertEq(getAssetBalance(recipient), expectedRecipientAmount); - } - - function test_payRecipientWithInvalidPool() public { - //get the first individual recipient - address recipient = getPrimaryRecipientAddresses()[0]; - - //get a single recipient as an array - address[] memory recipients = new address[](1); - recipients[0] = recipient; - - //pay a single recipient - payRecipients(SECONDARY_POOL_ID, recipients, ADMIN); - - //the recipient should have received nothing - assertEq(getAssetBalance(recipient), 0); - } - - function test_payRecipientsEmptyRecipientList() public { - //get a single recipient - address[] memory recipients = new address[](0); - - //pay a single recipient - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //rewardManager should have the full balance - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_payAllRecipientsWithAdditionalUnregisteredRecipient() public { - //load all the recipients and add an additional one who is not in the pool - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - recipients[recipients.length - 1] = DEFAULT_RECIPIENT_5; - - //pay the recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - - //the unregistered recipient should receive nothing - assertEq(getAssetBalance(DEFAULT_RECIPIENT_5), 0); - } - - function test_payAllRecipientsWithAdditionalInvalidRecipient() public { - //load all the recipients and add an additional one which is invalid, that should receive nothing - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - recipients[recipients.length - 1] = INVALID_ADDRESS; - - //pay the recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_paySubsetOfRecipientsInPool() public { - //load a subset of the recipients into an array - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length - 1); - for (uint256 i = 0; i < recipients.length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - - //pay the subset of recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each subset of recipients received the correct amount - for (uint256 i = 0; i < recipients.length - 1; i++) { - assertEq(getAssetBalance(recipients[i]), expectedRecipientAmount); - } - - //check the pool has the remaining balance - assertEq( - getAssetBalance(address(rewardManager)), - POOL_DEPOSIT_AMOUNT - expectedRecipientAmount * recipients.length - ); - } - - function test_payAllRecipientsFromNonAdminUser() public { - //should revert if the caller isn't an admin or recipient within the pool - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), FEE_MANAGER); - } - - function test_payAllRecipientsFromRecipientInPool() public { - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), DEFAULT_RECIPIENT_1); - - //each recipient should receive 1/4 of the pool - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_payRecipientsWithInvalidPoolId() public { - //pay all the recipients in the pool - payRecipients(INVALID_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); - - //pool should still contain the full balance - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_addFundsToPoolAsOwner() public { - //add funds to the pool - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_addFundsToPoolAsNonOwnerOrFeeManager() public { - //should revert if the caller isn't an admin or recipient within the pool - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - IRewardManager.FeePayment[] memory payments = new IRewardManager.FeePayment[](1); - payments[0] = IRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); - - //add funds to the pool - rewardManager.onFeePaid(payments, USER); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol deleted file mode 100644 index d3e6990..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.setRecipients.t.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice This contract will test the setRecipient functionality of the RewardManager contract - */ -contract RewardManagerSetRecipientsTest is BaseRewardManagerTest { - function setUp() public override { - //setup contracts - super.setUp(); - } - - function test_setRewardRecipients() public { - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRewardRecipientsIsEmpty() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWithZeroWeight() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 25); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 25); - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, 0); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWithZeroAddress() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = getPrimaryRecipients(); - - //override the first recipient with a zero address - recipients[0].addr = address(0); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWeights() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 25); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, 25); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, 25); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //set the recipients with a recipient with a weight of 100% - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setSingleRewardRecipient() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR); - - //set the recipients with a recipient with a weight of 100% - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientTwice() public { - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //should revert if recipients for this pool have already been set - vm.expectRevert(INVALID_POOL_ID_ERROR_SELECTOR); - - //set the recipients again - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() public { - //should revert if the sender is not the owner or proxy - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), USER); - } - - function test_setRewardRecipientFromManagerAddress() public { - //update the proxy address - setFeeManager(FEE_MANAGER, ADMIN); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); - } - - function test_eventIsEmittedUponSetRecipients() public { - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRecipientContainsDuplicateRecipients() public { - //create a new array to hold the existing recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add all the existing recipients again - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; - } - - //should revert as the list contains a duplicate - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol deleted file mode 100644 index 0d3a2b6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/reward-manager/RewardManager.updateRewardRecipients.t.sol +++ /dev/null @@ -1,450 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseRewardManagerTest} from "./BaseRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title BaseRewardManagerTest - * @author Michael Fletcher - * @notice This contract will test the updateRecipient functionality of the RewardManager contract - */ -contract RewardManagerUpdateRewardRecipientsTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_onlyAdminCanUpdateRecipients() public { - //should revert if the caller is not the admin - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); - } - - function test_updateAllRecipientsWithSameAddressAndWeight() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); - } - } - - function test_updatePartialRecipientsWithSameAddressAndWeight() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //get a subset of the recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should still have half remaining funds - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); - } - - function test_updateRecipientWithNewZeroAddress() public { - //create a new array to hold the existing recipients plus a new zero address - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 1); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add a new address to the primary recipients - recipients[recipients.length - 1] = Common.AddressAndWeight(address(0), 0); - - //should revert if the recipient is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //update the recipients with invalid address - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsContainsDuplicateRecipients() public { - //create a new array to hold the existing recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add all the existing recipients again - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; - } - - //should revert as the list contains a duplicate - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //update the recipients with the duplicate addresses - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 4); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, ONE_PERCENT * 25); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, ONE_PERCENT * 25); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, ONE_PERCENT * 25); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, ONE_PERCENT * 25); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentPartialSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, FIFTY_PERCENT); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, FIFTY_PERCENT); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentLargerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 5); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 2); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT * 2); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT * 2); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT * 2); - recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT * 2); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsUpdateAndRemoveExistingForLargerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](9); - - //update the existing recipients - recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); - recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); - recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 3); - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT); - recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT); - - //should revert as the weight does not equal 100% - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); - - //update the existing recipients - recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); - recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); - recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 2); - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentSetWithInvalidWeights() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); - - //should revert as the weight will not equal 100% - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsToSubset() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 0); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 0); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 5); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsWithUnderWeightSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); - - //should revert as the new weights exceed the previous weights being replaced - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsWithExcessiveWeight() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR); - - //should revert as the new weights exceed the previous weights being replaced - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set with their new weights - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should have no funds remaining - assertEq(getAssetBalance(address(rewardManager)), 0); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop each user and claim the rewards - for (uint256 i; i < recipients.length; i++) { - //claim the rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); - } - - //manually check the balance of each recipient - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_1), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_2), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_3), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 3) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_4), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 5) / POOL_SCALAR + expectedRecipientAmount - ); - } - - function test_partialUpdateRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set with their new weights - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should have half the funds remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop each user and claim the rewards - for (uint256 i; i < recipients.length; i++) { - //claim the rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); - } - - //manually check the balance of each recipient - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_1), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_2), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - - //the reward manager should have half the funds remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_eventIsEmittedUponUpdateRecipients() public { - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); - } - } -} - -contract RewardManagerUpdateRewardRecipientsMultiplePoolsTest is BaseRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - createSecondaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function getSecondaryRecipients() public override returns (Common.AddressAndWeight[] memory) { - //for testing purposes, the primary and secondary pool to contain the same recipients - return getPrimaryRecipients(); - } - - function test_updatePrimaryRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT * 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should still have the funds for the secondary pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the rewards for the updated recipients manually - claimRewards(PRIMARY_POOL_ARRAY, recipients[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[1].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[2].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[3].addr); - - //check the balance matches the ratio the recipient who were updated should have received - assertEq( - getAssetBalance(recipients[0].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[1].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[2].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[3].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol deleted file mode 100644 index 4d65414..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/BaseVerifierTest.t.sol +++ /dev/null @@ -1,502 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {VerifierProxy} from "../../VerifierProxy.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IVerifier} from "../../interfaces/IVerifier.sol"; -import {ErroredVerifier} from "../mocks/ErroredVerifier.sol"; -import {Verifier} from "../../Verifier.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {FeeManager} from "../../FeeManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; -import {RewardManager} from "../../RewardManager.sol"; - -contract BaseTest is Test { - uint256 internal constant MAX_ORACLES = 31; - address internal constant ADMIN = address(1); - address internal constant USER = address(2); - address internal constant MOCK_VERIFIER_ADDRESS = address(100); - address internal constant MOCK_VERIFIER_ADDRESS_TWO = address(200); - address internal constant ACCESS_CONTROLLER_ADDRESS = address(300); - - bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; - - //version 0 feeds - bytes32 internal constant FEED_ID = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant FEED_ID_2 = (keccak256("LINK-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant FEED_ID_3 = (keccak256("BTC-USD") & V_MASK) | V1_BITMASK; - - //version 3 feeds - bytes32 internal constant FEED_ID_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; - - bytes32 internal constant INVALID_FEED = keccak256("INVALID"); - uint32 internal constant OBSERVATIONS_TIMESTAMP = 1000; - uint64 internal constant BLOCKNUMBER_LOWER_BOUND = 1000; - uint64 internal constant BLOCKNUMBER_UPPER_BOUND = BLOCKNUMBER_LOWER_BOUND + 5; - int192 internal constant MEDIAN = 1 ether; - int192 internal constant BID = 500000000 gwei; - int192 internal constant ASK = 2 ether; - - bytes32 internal constant EMPTY_BYTES = bytes32(""); - - uint8 internal constant FAULT_TOLERANCE = 10; - uint64 internal constant VERIFIER_VERSION = 1; - - string internal constant SERVER_URL = "https://mercury.server/client/"; - uint8 internal constant MAX_COMMITMENT_DELAY = 5; - - VerifierProxy internal s_verifierProxy; - Verifier internal s_verifier; - Verifier internal s_verifier_2; - ErroredVerifier internal s_erroredVerifier; - - struct Signer { - uint256 mockPrivateKey; - address signerAddress; - } - - struct V1Report { - // The feed ID the report has data for - bytes32 feedId; - // The time the median value was observed on - uint32 observationsTimestamp; - // The median value agreed in an OCR round - int192 median; - // The best bid value agreed in an OCR round - int192 bid; - // The best ask value agreed in an OCR round - int192 ask; - // The upper bound of the block range the median value was observed within - uint64 blocknumberUpperBound; - // The blockhash for the upper bound of block range (ensures correct blockchain) - bytes32 upperBlockhash; - // The lower bound of the block range the median value was observed within - uint64 blocknumberLowerBound; - // The current block timestamp - uint64 currentBlockTimestamp; - } - - Signer[MAX_ORACLES] internal s_signers; - bytes32[] internal s_offchaintransmitters; - bool private s_baseTestInitialized; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - vm.startPrank(ADMIN); - vm.mockCall( - MOCK_VERIFIER_ADDRESS, - abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), - abi.encode(true) - ); - s_verifierProxy = new VerifierProxy(AccessControllerInterface(address(0))); - - s_verifier = new Verifier(address(s_verifierProxy)); - s_verifier_2 = new Verifier(address(s_verifierProxy)); - s_erroredVerifier = new ErroredVerifier(); - - for (uint256 i; i < MAX_ORACLES; i++) { - uint256 mockPK = i + 1; - s_signers[i].mockPrivateKey = mockPK; - s_signers[i].signerAddress = vm.addr(mockPK); - } - } - - function _getSigners(uint256 numSigners) internal view returns (Signer[] memory) { - Signer[] memory signers = new Signer[](numSigners); - for (uint256 i; i < numSigners; i++) { - signers[i] = s_signers[i]; - } - return signers; - } - - function _getSignerAddresses(Signer[] memory signers) internal view returns (address[] memory) { - address[] memory signerAddrs = new address[](signers.length); - for (uint256 i = 0; i < signerAddrs.length; i++) { - signerAddrs[i] = s_signers[i].signerAddress; - } - return signerAddrs; - } - - function _generateSignerSignatures( - bytes memory report, - bytes32[3] memory reportContext, - Signer[] memory signers - ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) { - bytes32[] memory rs = new bytes32[](signers.length); - bytes32[] memory ss = new bytes32[](signers.length); - bytes memory vs = new bytes(signers.length); - - bytes32 hash = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - for (uint256 i = 0; i < signers.length; i++) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].mockPrivateKey, hash); - rs[i] = r; - ss[i] = s; - vs[i] = bytes1(v - 27); - } - return (rs, ss, bytes32(vs)); - } - - function _encodeReport(V1Report memory report) internal pure returns (bytes memory) { - return - abi.encode( - report.feedId, - report.observationsTimestamp, - report.median, - report.bid, - report.ask, - report.blocknumberUpperBound, - report.upperBlockhash, - report.blocknumberLowerBound, - report.currentBlockTimestamp - ); - } - - function _generateV1EncodedBlob( - V1Report memory report, - bytes32[3] memory reportContext, - Signer[] memory signers - ) internal pure returns (bytes memory) { - bytes memory reportBytes = _encodeReport(report); - (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( - reportBytes, - reportContext, - signers - ); - return abi.encode(reportContext, reportBytes, rs, ss, rawVs); - } - - function _configDigestFromConfigData( - bytes32 feedId, - uint256 chainId, - address verifierAddr, - uint64 configCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - feedId, - chainId, - verifierAddr, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 prefix = 0x0006 << (256 - 16); // 0x000600..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - function _createV1Report( - bytes32 feedId, - uint32 observationsTimestamp, - int192 median, - int192 bid, - int192 ask, - uint64 blocknumberUpperBound, - bytes32 upperBlockhash, - uint64 blocknumberLowerBound, - uint32 currentBlockTimestamp - ) internal pure returns (V1Report memory) { - return - V1Report({ - feedId: feedId, - observationsTimestamp: observationsTimestamp, - median: median, - bid: bid, - ask: ask, - blocknumberUpperBound: blocknumberUpperBound, - upperBlockhash: upperBlockhash, - blocknumberLowerBound: blocknumberLowerBound, - currentBlockTimestamp: currentBlockTimestamp - }); - } - - function _ccipReadURL(bytes32 feedId, uint256 commitmentBlock) internal pure returns (string memory url) { - return - string( - abi.encodePacked( - SERVER_URL, - "?feedIDHex=", - Strings.toHexString(uint256(feedId)), - "&L2Blocknumber=", - Strings.toString(commitmentBlock) - ) - ); - } -} - -contract BaseTestWithConfiguredVerifierAndFeeManager is BaseTest { - FeeManager internal feeManager; - RewardManager internal rewardManager; - ERC20Mock internal link; - WERC20Mock internal native; - - uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; - uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; - - bytes32 internal v1ConfigDigest; - bytes32 internal v3ConfigDigest; - - struct V3Report { - // The feed ID the report has data for - bytes32 feedId; - // The time the median value was observed on - uint32 observationsTimestamp; - // The timestamp the report is valid from - uint32 validFromTimestamp; - // The link fee - uint192 linkFee; - // The native fee - uint192 nativeFee; - // The expiry of the report - uint32 expiresAt; - // The median value agreed in an OCR round - int192 benchmarkPrice; - // The best bid value agreed in an OCR round - int192 bid; - // The best ask value agreed in an OCR round - int192 ask; - } - - function setUp() public virtual override { - BaseTest.setUp(); - Signer[] memory signers = _getSigners(MAX_ORACLES); - - s_verifierProxy.initializeVerifier(address(s_verifier)); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , v1ConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - - s_verifier.setConfig( - FEED_ID_V3, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , v3ConfigDigest) = s_verifier.latestConfigDetails(FEED_ID_V3); - - link = new ERC20Mock("LINK", "LINK", ADMIN, 0); - native = new WERC20Mock(); - - rewardManager = new RewardManager(address(link)); - feeManager = new FeeManager(address(link), address(native), address(s_verifierProxy), address(rewardManager)); - - s_verifierProxy.setFeeManager(feeManager); - rewardManager.setFeeManager(address(feeManager)); - } - - function _encodeReport(V3Report memory report) internal pure returns (bytes memory) { - return - abi.encode( - report.feedId, - report.observationsTimestamp, - report.validFromTimestamp, - report.nativeFee, - report.linkFee, - report.expiresAt, - report.benchmarkPrice, - report.bid, - report.ask - ); - } - - function _generateV3EncodedBlob( - V3Report memory report, - bytes32[3] memory reportContext, - Signer[] memory signers - ) internal pure returns (bytes memory) { - bytes memory reportBytes = _encodeReport(report); - (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( - reportBytes, - reportContext, - signers - ); - return abi.encode(reportContext, reportBytes, rs, ss, rawVs); - } - - function _generateV1Report() internal view returns (V1Report memory) { - return - _createV1Report( - FEED_ID, - OBSERVATIONS_TIMESTAMP, - MEDIAN, - BID, - ASK, - BLOCKNUMBER_UPPER_BOUND, - bytes32(blockhash(BLOCKNUMBER_UPPER_BOUND)), - BLOCKNUMBER_LOWER_BOUND, - uint32(block.timestamp) - ); - } - - function _generateV3Report() internal view returns (V3Report memory) { - return - V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function _generateReportContext(bytes32 configDigest) internal pure returns (bytes32[3] memory) { - bytes32[3] memory reportContext; - reportContext[0] = configDigest; - reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - return reportContext; - } - - function _approveLink(address spender, uint256 quantity, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - link.approve(spender, quantity); - changePrank(originalAddr); - } - - function _approveNative(address spender, uint256 quantity, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - native.approve(spender, quantity); - changePrank(originalAddr); - } - - function _verify(bytes memory payload, address feeAddress, uint256 wrappedNativeValue, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - s_verifierProxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - changePrank(originalAddr); - } - - function _verifyBulk( - bytes[] memory payload, - address feeAddress, - uint256 wrappedNativeValue, - address sender - ) internal { - address originalAddr = msg.sender; - changePrank(sender); - - s_verifierProxy.verifyBulk{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - changePrank(originalAddr); - } -} - -contract BaseTestWithMultipleConfiguredDigests is BaseTestWithConfiguredVerifierAndFeeManager { - bytes32 internal s_configDigestOne; - bytes32 internal s_configDigestTwo; - bytes32 internal s_configDigestThree; - bytes32 internal s_configDigestFour; - bytes32 internal s_configDigestFive; - - uint32 internal s_numConfigsSet; - - uint8 internal constant FAULT_TOLERANCE_TWO = 2; - uint8 internal constant FAULT_TOLERANCE_THREE = 1; - - function setUp() public virtual override { - BaseTestWithConfiguredVerifierAndFeeManager.setUp(); - Signer[] memory signers = _getSigners(MAX_ORACLES); - - (, , s_configDigestOne) = s_verifier.latestConfigDetails(FEED_ID); - - // Verifier 1, Feed 1, Config 2 - Signer[] memory secondSetOfSigners = _getSigners(8); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(secondSetOfSigners), - s_offchaintransmitters, - FAULT_TOLERANCE_TWO, - bytes(""), - 2, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , s_configDigestTwo) = s_verifier.latestConfigDetails(FEED_ID); - - // Verifier 1, Feed 1, Config 3 - Signer[] memory thirdSetOfSigners = _getSigners(5); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(thirdSetOfSigners), - s_offchaintransmitters, - FAULT_TOLERANCE_THREE, - bytes(""), - 3, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (s_numConfigsSet, , s_configDigestThree) = s_verifier.latestConfigDetails(FEED_ID); - - // Verifier 1, Feed 2, Config 1 - s_verifier.setConfig( - FEED_ID_2, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - 4, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , s_configDigestFour) = s_verifier.latestConfigDetails(FEED_ID_2); - - // Verifier 2, Feed 3, Config 1 - s_verifierProxy.initializeVerifier(address(s_verifier_2)); - s_verifier_2.setConfig( - FEED_ID_3, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , s_configDigestFive) = s_verifier_2.latestConfigDetails(FEED_ID_3); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol deleted file mode 100644 index 99daabe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierActivateConfigTest.t.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; - -contract VerifierActivateConfigTest is BaseTestWithConfiguredVerifierAndFeeManager { - function test_revertsIfNotOwner() public { - vm.expectRevert("Only callable by owner"); - - changePrank(address(s_verifierProxy)); - s_verifier.activateConfig(FEED_ID, bytes32("mock")); - } - - function test_revertsIfDigestIsEmpty() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); - s_verifier.activateConfig(FEED_ID, bytes32("")); - } - - function test_revertsIfDigestNotSet() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, FEED_ID, bytes32("non-existent-digest"))); - s_verifier.activateConfig(FEED_ID, bytes32("non-existent-digest")); - } -} - -contract VerifierActivateConfigWithDeactivatedConfigTest is BaseTestWithMultipleConfiguredDigests { - bytes32[3] internal s_reportContext; - - event ConfigActivated(bytes32 configDigest); - - V1Report internal s_testReportOne; - - function setUp() public override { - BaseTestWithMultipleConfiguredDigests.setUp(); - s_reportContext[0] = s_configDigestTwo; - s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReportOne = _createV1Report( - FEED_ID, - uint32(block.timestamp), - MEDIAN, - BID, - ASK, - uint64(block.number), - blockhash(block.number + 3), - uint64(block.number + 3), - uint32(block.timestamp) - ); - - s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); - } - - function test_allowsVerification() public { - s_verifier.activateConfig(FEED_ID, s_configDigestTwo); - changePrank(address(s_verifierProxy)); - - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE_TWO + 1) - ); - s_verifier.verify(signedReport, msg.sender); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol deleted file mode 100644 index fb52c1c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierDeactivateFeedTest.t.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; - -contract VerifierActivateFeedTest is BaseTestWithConfiguredVerifierAndFeeManager { - function test_revertsIfNotOwnerActivateFeed() public { - changePrank(address(s_verifierProxy)); - vm.expectRevert("Only callable by owner"); - s_verifier.activateFeed(FEED_ID); - } - - function test_revertsIfNotOwnerDeactivateFeed() public { - changePrank(address(s_verifierProxy)); - vm.expectRevert("Only callable by owner"); - s_verifier.deactivateFeed(FEED_ID); - } - - function test_revertsIfNoFeedExistsActivate() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.InvalidFeed.selector, INVALID_FEED)); - s_verifier.activateFeed(INVALID_FEED); - } - - function test_revertsIfNoFeedExistsDeactivate() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.InvalidFeed.selector, INVALID_FEED)); - s_verifier.deactivateFeed(INVALID_FEED); - } -} - -contract VerifierDeactivateFeedWithVerifyTest is BaseTestWithMultipleConfiguredDigests { - bytes32[3] internal s_reportContext; - - event ConfigActivated(bytes32 configDigest); - - V1Report internal s_testReportOne; - - function setUp() public override { - BaseTestWithMultipleConfiguredDigests.setUp(); - s_reportContext[0] = s_configDigestOne; - s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReportOne = _createV1Report( - FEED_ID, - uint32(block.timestamp), - MEDIAN, - BID, - ASK, - uint64(block.number), - blockhash(block.number + 3), - uint64(block.number + 3), - uint32(block.timestamp) - ); - - s_verifier.deactivateFeed(FEED_ID); - } - - function test_currentReportAllowsVerification() public { - s_verifier.activateFeed(FEED_ID); - changePrank(address(s_verifierProxy)); - - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - s_verifier.verify(signedReport, msg.sender); - } - - function test_previousReportAllowsVerification() public { - s_verifier.activateFeed(FEED_ID); - changePrank(address(s_verifierProxy)); - - s_reportContext[0] = s_configDigestTwo; - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE_TWO + 1) - ); - s_verifier.verify(signedReport, msg.sender); - } - - function test_currentReportFailsVerification() public { - changePrank(address(s_verifierProxy)); - - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - vm.expectRevert(abi.encodeWithSelector(Verifier.InactiveFeed.selector, FEED_ID)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_previousReportFailsVerification() public { - changePrank(address(s_verifierProxy)); - - s_reportContext[0] = s_configDigestTwo; - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE_TWO + 1) - ); - - vm.expectRevert(abi.encodeWithSelector(Verifier.InactiveFeed.selector, FEED_ID)); - s_verifier.verify(signedReport, msg.sender); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol deleted file mode 100644 index 82efd89..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyConstructorTest.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseVerifierTest.t.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; - -contract VerifierProxyConstructorTest is BaseTest { - function test_correctlySetsTheOwner() public { - VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(address(0))); - assertEq(proxy.owner(), ADMIN); - } - - function test_correctlySetsTheCorrectAccessControllerInterface() public { - address accessControllerAddr = address(1234); - VerifierProxy proxy = new VerifierProxy(AccessControllerInterface(accessControllerAddr)); - assertEq(address(proxy.s_accessController()), accessControllerAddr); - } - - function test_correctlySetsVersion() public view { - string memory version = s_verifierProxy.typeAndVersion(); - assertEq(version, "VerifierProxy 2.0.0"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol deleted file mode 100644 index 5537d27..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyInitializeVerifierTest.t.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseVerifierTest.t.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; - -contract VerifierProxyInitializeVerifierTest is BaseTest { - bytes32 latestDigest; - - function setUp() public override { - BaseTest.setUp(); - } - - function test_revertsIfNotOwner() public { - changePrank(USER); - vm.expectRevert("Only callable by owner"); - s_verifierProxy.initializeVerifier(address(s_verifier)); - } - - function test_revertsIfZeroAddress() public { - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); - s_verifierProxy.initializeVerifier(address(0)); - } - - function test_revertsIfVerifierAlreadyInitialized() public { - s_verifierProxy.initializeVerifier(address(s_verifier)); - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierAlreadyInitialized.selector, address(s_verifier))); - s_verifierProxy.initializeVerifier(address(s_verifier)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol deleted file mode 100644 index 03bd6d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetAccessControllerTest.t.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseVerifierTest.t.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; - -contract VerifierProxySetAccessControllerTest is BaseTest { - event AccessControllerSet(address oldAccessController, address newAccessController); - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - - changePrank(USER); - s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); - } - - function test_successfullySetsNewAccessController() public { - s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); - AccessControllerInterface ac = s_verifierProxy.s_accessController(); - assertEq(address(ac), ACCESS_CONTROLLER_ADDRESS); - } - - function test_successfullySetsNewAccessControllerIsEmpty() public { - s_verifierProxy.setAccessController(AccessControllerInterface(address(0))); - AccessControllerInterface ac = s_verifierProxy.s_accessController(); - assertEq(address(ac), address(0)); - } - - function test_emitsTheCorrectEvent() public { - vm.expectEmit(true, false, false, false); - emit AccessControllerSet(address(0), ACCESS_CONTROLLER_ADDRESS); - s_verifierProxy.setAccessController(AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol deleted file mode 100644 index 78e5ff0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxySetVerifierTest.t.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; -import {IVerifier} from "../../interfaces/IVerifier.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { - function test_revertsIfNotCorrectVerifier() public { - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); - s_verifierProxy.setVerifier(bytes32("prev-config"), bytes32("new-config"), new Common.AddressAndWeight[](0)); - } - - function test_revertsIfDigestAlreadySet() public { - (, , bytes32 takenDigest) = s_verifier.latestConfigDetails(FEED_ID); - - address maliciousVerifier = address(666); - bytes32 maliciousDigest = bytes32("malicious-digest"); - vm.mockCall( - maliciousVerifier, - abi.encodeWithSelector(IERC165.supportsInterface.selector, IVerifier.verify.selector), - abi.encode(true) - ); - s_verifierProxy.initializeVerifier(maliciousVerifier); - vm.expectRevert( - abi.encodeWithSelector(VerifierProxy.ConfigDigestAlreadySet.selector, takenDigest, address(s_verifier)) - ); - changePrank(address(maliciousVerifier)); - s_verifierProxy.setVerifier(maliciousDigest, takenDigest, new Common.AddressAndWeight[](0)); - } - - function test_updatesVerifierIfVerifier() public { - (, , bytes32 prevDigest) = s_verifier.latestConfigDetails(FEED_ID); - changePrank(address(s_verifier)); - s_verifierProxy.setVerifier(prevDigest, bytes32("new-config"), new Common.AddressAndWeight[](0)); - assertEq(s_verifierProxy.getVerifier(bytes32("new-config")), address(s_verifier)); - assertEq(s_verifierProxy.getVerifier(prevDigest), address(s_verifier)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol deleted file mode 100644 index 441626e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyTest.t.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; -import {FeeManager} from "../../../v0.3.0/FeeManager.sol"; - -contract VerifierProxyInitializeVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { - function test_setFeeManagerZeroAddress() public { - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.ZeroAddress.selector)); - s_verifierProxy.setFeeManager(FeeManager(address(0))); - } - - function test_setFeeManagerWhichDoesntHonourInterface() public { - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.FeeManagerInvalid.selector)); - s_verifierProxy.setFeeManager(FeeManager(address(s_verifier))); - } - - function test_setFeeManagerWhichDoesntHonourIERC165Interface() public { - vm.expectRevert(); - s_verifierProxy.setFeeManager(FeeManager(address(1))); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol deleted file mode 100644 index a51c67e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierProxyUnsetVerifierTest.t.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest, BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; - -contract VerifierProxyUnsetVerifierTest is BaseTest { - function test_revertsIfNotAdmin() public { - vm.expectRevert("Only callable by owner"); - - changePrank(USER); - s_verifierProxy.unsetVerifier(bytes32("")); - } - - function test_revertsIfDigestDoesNotExist() public { - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32(""))); - s_verifierProxy.unsetVerifier(bytes32("")); - } -} - -contract VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest is BaseTestWithConfiguredVerifierAndFeeManager { - bytes32 internal s_configDigest; - - event VerifierUnset(bytes32 configDigest, address verifierAddr); - - function setUp() public override { - BaseTestWithConfiguredVerifierAndFeeManager.setUp(); - (, , s_configDigest) = s_verifier.latestConfigDetails(FEED_ID); - } - - function test_correctlyUnsetsVerifier() public { - s_verifierProxy.unsetVerifier(s_configDigest); - address verifierAddr = s_verifierProxy.getVerifier(s_configDigest); - assertEq(verifierAddr, address(0)); - } - - function test_emitsAnEventAfterUnsettingVerifier() public { - vm.expectEmit(true, false, false, false); - emit VerifierUnset(s_configDigest, address(s_verifier)); - s_verifierProxy.unsetVerifier(s_configDigest); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol deleted file mode 100644 index 9ee9b52..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigFromSourceTest.t.sol +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierSetConfigFromSourceTest is BaseTest { - function setUp() public virtual override { - BaseTest.setUp(); - } - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - Signer[] memory signers = _getSigners(MAX_ORACLES); - - changePrank(USER); - s_verifier.setConfigFromSource( - FEED_ID, - 12345, - address(12345), - 0, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } -} - -contract VerifierSetConfigFromSourceMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { - function test_correctlyUpdatesTheDigestInTheProxy() public { - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfigFromSource( - FEED_ID, - 12345, - address(12345), - 0, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - address verifierAddr = s_verifierProxy.getVerifier(configDigest); - assertEq(verifierAddr, address(s_verifier)); - } - - function test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() public { - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfigFromSource( - FEED_ID_2, - 12345, - address(12345), - 0, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID_2); - address verifierAddr = s_verifierProxy.getVerifier(configDigest); - assertEq(verifierAddr, address(s_verifier)); - - s_verifier_2.setConfigFromSource( - FEED_ID_3, - 12345, - address(12345), - 0, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest2) = s_verifier_2.latestConfigDetails(FEED_ID_3); - address verifierAddr2 = s_verifierProxy.getVerifier(configDigest2); - assertEq(verifierAddr2, address(s_verifier_2)); - } - - function test_correctlySetsConfigWhenDigestsAreRemoved() public { - s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); - - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfigFromSource( - FEED_ID, - 12345, - address(s_verifier), - 0, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - bytes32 expectedConfigDigest = _configDigestFromConfigData( - FEED_ID, - 12345, - address(s_verifier), - s_numConfigsSet + 1, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes("") - ); - - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - - assertEq(configCount, s_numConfigsSet + 1); - assertEq(blockNumber, block.number); - assertEq(configDigest, expectedConfigDigest); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol deleted file mode 100644 index 972ead8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierSetConfigTest.t.sol +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest, BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierSetConfigTest is BaseTest { - function setUp() public virtual override { - BaseTest.setUp(); - } - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - Signer[] memory signers = _getSigners(MAX_ORACLES); - - changePrank(USER); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_revertsIfSetWithTooManySigners() public { - address[] memory signers = new address[](MAX_ORACLES + 1); - vm.expectRevert(abi.encodeWithSelector(Verifier.ExcessSigners.selector, signers.length, MAX_ORACLES)); - s_verifier.setConfig( - FEED_ID, - signers, - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_revertsIfFaultToleranceIsZero() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.FaultToleranceMustBePositive.selector)); - Signer[] memory signers = _getSigners(MAX_ORACLES); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(signers), - s_offchaintransmitters, - 0, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_revertsIfNotEnoughSigners() public { - address[] memory signers = new address[](2); - signers[0] = address(1000); - signers[1] = address(1001); - - vm.expectRevert( - abi.encodeWithSelector(Verifier.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) - ); - s_verifier.setConfig( - FEED_ID, - signers, - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_revertsIfDuplicateSigners() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - signerAddrs[0] = signerAddrs[1]; - vm.expectRevert(abi.encodeWithSelector(Verifier.NonUniqueSignatures.selector)); - s_verifier.setConfig( - FEED_ID, - signerAddrs, - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_revertsIfSignerContainsZeroAddress() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - signerAddrs[0] = address(0); - vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); - s_verifier.setConfig( - FEED_ID, - signerAddrs, - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - } - - function test_correctlyUpdatesTheConfig() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - s_verifierProxy.initializeVerifier(address(s_verifier)); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - bytes32 expectedConfigDigest = _configDigestFromConfigData( - FEED_ID, - block.chainid, - address(s_verifier), - 1, - _getSignerAddresses(signers), - s_offchaintransmitters, - FAULT_TOLERANCE, - bytes(""), - VERIFIER_VERSION, - bytes("") - ); - - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(configCount, 1); - assertEq(blockNumber, block.number); - assertEq(configDigest, expectedConfigDigest); - - (bool scanLogs, bytes32 configDigestTwo, uint32 epoch) = s_verifier.latestConfigDigestAndEpoch(FEED_ID); - assertEq(scanLogs, false); - assertEq(configDigestTwo, expectedConfigDigest); - assertEq(epoch, 0); - } -} - -contract VerifierSetConfigWhenThereAreMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { - function test_correctlyUpdatesTheDigestInTheProxy() public { - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - address verifierAddr = s_verifierProxy.getVerifier(configDigest); - assertEq(verifierAddr, address(s_verifier)); - } - - function test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() public { - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfig( - FEED_ID_2, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID_2); - address verifierAddr = s_verifierProxy.getVerifier(configDigest); - assertEq(verifierAddr, address(s_verifier)); - - s_verifier_2.setConfig( - FEED_ID_3, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - (, , bytes32 configDigest2) = s_verifier_2.latestConfigDetails(FEED_ID_3); - address verifierAddr2 = s_verifierProxy.getVerifier(configDigest2); - assertEq(verifierAddr2, address(s_verifier_2)); - } - - function test_correctlySetsConfigWhenDigestsAreRemoved() public { - s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); - - Signer[] memory newSigners = _getSigners(15); - - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - - bytes32 expectedConfigDigest = _configDigestFromConfigData( - FEED_ID, - block.chainid, - address(s_verifier), - s_numConfigsSet + 1, - _getSignerAddresses(newSigners), - s_offchaintransmitters, - 4, - bytes(""), - VERIFIER_VERSION, - bytes("") - ); - - (uint32 configCount, uint32 blockNumber, bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - - assertEq(configCount, s_numConfigsSet + 1); - assertEq(blockNumber, block.number); - assertEq(configDigest, expectedConfigDigest); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol deleted file mode 100644 index 81f65f0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTest.t.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; - -contract VerifierConstructorTest is BaseTest { - function test_revertsIfInitializedWithEmptyVerifierProxy() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.ZeroAddress.selector)); - new Verifier(address(0)); - } - - function test_setsTheCorrectProperties() public { - Verifier v = new Verifier(address(s_verifierProxy)); - assertEq(v.owner(), ADMIN); - - (bool scanLogs, bytes32 configDigest, uint32 epoch) = v.latestConfigDigestAndEpoch(FEED_ID); - assertEq(scanLogs, false); - assertEq(configDigest, EMPTY_BYTES); - assertEq(epoch, 0); - - (uint32 configCount, uint32 blockNumber, bytes32 configDigestTwo) = v.latestConfigDetails(FEED_ID); - assertEq(configCount, 0); - assertEq(blockNumber, 0); - assertEq(configDigestTwo, EMPTY_BYTES); - - string memory typeAndVersion = s_verifier.typeAndVersion(); - assertEq(typeAndVersion, "Verifier 1.2.0"); - } -} - -contract VerifierSupportsInterfaceTest is BaseTest { - function test_falseIfIsNotCorrectInterface() public view { - bool isInterface = s_verifier.supportsInterface(bytes4("abcd")); - assertEq(isInterface, false); - } - - function test_trueIfIsCorrectInterface() public view { - bool isInterface = s_verifier.supportsInterface(Verifier.verify.selector); - assertEq(isInterface, true); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol deleted file mode 100644 index ad67a23..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierTestBillingReport.t.sol +++ /dev/null @@ -1,218 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; - -contract VerifierTestWithConfiguredVerifierAndFeeManager is BaseTestWithConfiguredVerifierAndFeeManager { - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - function setUp() public virtual override { - super.setUp(); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some link tokens to the feeManager pool - link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); - } -} - -contract VerifierTestBillingReport is VerifierTestWithConfiguredVerifierAndFeeManager { - function test_verifyWithLink() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - _verify(signedReport, address(link), 0, USER); - - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_verifyWithNative() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - _verify(signedReport, address(native), 0, USER); - - assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - } - - function test_verifyWithNativeUnwrapped() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE, USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - assertEq(address(feeManager).balance, 0); - } - - function test_verifyWithNativeUnwrappedReturnsChange() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE * 2, USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - assertEq(address(feeManager).balance, 0); - } -} - -contract VerifierBulkVerifyBillingReport is VerifierTestWithConfiguredVerifierAndFeeManager { - uint256 internal constant NUMBERS_OF_REPORTS = 5; - - function test_verifyWithBulkLink() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS, USER); - - _verifyBulk(signedReports, address(link), 0, USER); - - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); - } - - function test_verifyWithBulkNative() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); - - _verifyBulk(signedReports, address(native), 0, USER); - - assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); - } - - function test_verifyWithBulkNativeUnwrapped() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(address(feeManager).balance, 0); - } - - function test_verifyWithBulkNativeUnwrappedReturnsChange() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * (NUMBERS_OF_REPORTS * 2), USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); - assertEq(address(feeManager).balance, 0); - } - - function test_verifyMultiVersions() public { - bytes memory signedReportV1 = _generateV1EncodedBlob( - _generateV1Report(), - _generateReportContext(v1ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes memory signedReportV3 = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](3); - - signedReports[0] = signedReportV1; - signedReports[1] = signedReportV3; - signedReports[2] = signedReportV3; - - _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); - - _verifyBulk(signedReports, address(link), 0, USER); - - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - 2 * DEFAULT_REPORT_LINK_FEE); - assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); - } - - function test_verifyMultiVersionsReturnsVerifiedReports() public { - bytes memory signedReportV1 = _generateV1EncodedBlob( - _generateV1Report(), - _generateReportContext(v1ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes memory signedReportV3 = _generateV3EncodedBlob( - _generateV3Report(), - _generateReportContext(v3ConfigDigest), - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](3); - - signedReports[0] = signedReportV1; - signedReports[1] = signedReportV3; - signedReports[2] = signedReportV3; - - _approveLink(address(rewardManager), 2 * DEFAULT_REPORT_LINK_FEE, USER); - - address originalAddr = msg.sender; - changePrank(USER); - - bytes[] memory verifierReports = s_verifierProxy.verifyBulk{value: 0}(signedReports, abi.encode(link)); - - changePrank(originalAddr); - - assertEq(verifierReports[0], _encodeReport(_generateV1Report())); - assertEq(verifierReports[1], _encodeReport(_generateV3Report())); - assertEq(verifierReports[2], _encodeReport(_generateV3Report())); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol deleted file mode 100644 index e192a2e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierUnsetConfigTest.t.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithMultipleConfiguredDigests} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; - -contract VerificationdeactivateConfigWhenThereAreMultipleDigestsTest is BaseTestWithMultipleConfiguredDigests { - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - - changePrank(USER); - s_verifier.deactivateConfig(FEED_ID, bytes32("")); - } - - function test_revertsIfRemovingAnEmptyDigest() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestEmpty.selector)); - s_verifier.deactivateConfig(FEED_ID, bytes32("")); - } - - function test_revertsIfRemovingAnNonExistentDigest() public { - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestNotSet.selector, FEED_ID, bytes32("mock-digest"))); - s_verifier.deactivateConfig(FEED_ID, bytes32("mock-digest")); - } - - function test_correctlyRemovesAMiddleDigest() public { - s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); - (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(lastConfigDigest, s_configDigestThree); - } - - function test_correctlyRemovesTheFirstDigest() public { - s_verifier.deactivateConfig(FEED_ID, s_configDigestOne); - (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(lastConfigDigest, s_configDigestThree); - } - - function test_correctlyUnsetsDigestsInSequence() public { - // Delete config digest 2 - s_verifier.deactivateConfig(FEED_ID, s_configDigestTwo); - (, , bytes32 lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(lastConfigDigest, s_configDigestThree); - - // Delete config digest 1 - s_verifier.deactivateConfig(FEED_ID, s_configDigestOne); - (, , lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(lastConfigDigest, s_configDigestThree); - - // Delete config digest 3 - vm.expectRevert( - abi.encodeWithSelector(Verifier.CannotDeactivateLatestConfig.selector, FEED_ID, s_configDigestThree) - ); - s_verifier.deactivateConfig(FEED_ID, s_configDigestThree); - (, , lastConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - assertEq(lastConfigDigest, s_configDigestThree); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol deleted file mode 100644 index 1c14ba9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.3.0/test/verifier/VerifierVerifyTest.t.sol +++ /dev/null @@ -1,314 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTestWithConfiguredVerifierAndFeeManager} from "./BaseVerifierTest.t.sol"; -import {Verifier} from "../../../v0.3.0/Verifier.sol"; -import {VerifierProxy} from "../../../v0.3.0/VerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierVerifyTest is BaseTestWithConfiguredVerifierAndFeeManager { - bytes32[3] internal s_reportContext; - - event ReportVerified(bytes32 indexed feedId, address requester); - - V1Report internal s_testReportOne; - - function setUp() public virtual override { - BaseTestWithConfiguredVerifierAndFeeManager.setUp(); - (, , bytes32 configDigest) = s_verifier.latestConfigDetails(FEED_ID); - s_reportContext[0] = configDigest; - s_reportContext[1] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReportOne = _createV1Report( - FEED_ID, - OBSERVATIONS_TIMESTAMP, - MEDIAN, - BID, - ASK, - BLOCKNUMBER_UPPER_BOUND, - blockhash(BLOCKNUMBER_UPPER_BOUND), - BLOCKNUMBER_LOWER_BOUND, - uint32(block.timestamp) - ); - } - - function assertReportsEqual(bytes memory response, V1Report memory testReport) public pure { - ( - bytes32 feedId, - uint32 timestamp, - int192 median, - int192 bid, - int192 ask, - uint64 blockNumUB, - bytes32 upperBlockhash, - uint64 blockNumLB - ) = abi.decode(response, (bytes32, uint32, int192, int192, int192, uint64, bytes32, uint64)); - assertEq(feedId, testReport.feedId); - assertEq(timestamp, testReport.observationsTimestamp); - assertEq(median, testReport.median); - assertEq(bid, testReport.bid); - assertEq(ask, testReport.ask); - assertEq(blockNumLB, testReport.blocknumberLowerBound); - assertEq(blockNumUB, testReport.blocknumberUpperBound); - assertEq(upperBlockhash, testReport.upperBlockhash); - } -} - -contract VerifierProxyVerifyTest is VerifierVerifyTest { - function test_revertsIfNoVerifierConfigured() public { - s_reportContext[0] = bytes32("corrupt-digest"); - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.VerifierNotFound.selector, bytes32("corrupt-digest"))); - s_verifierProxy.verify(signedReport, bytes("")); - } - - function test_proxiesToTheCorrectVerifier() public { - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes memory response = s_verifierProxy.verify(signedReport, abi.encode(native)); - assertReportsEqual(response, s_testReportOne); - } -} - -contract VerifierProxyAccessControlledVerificationTest is VerifierVerifyTest { - function setUp() public override { - VerifierVerifyTest.setUp(); - AccessControllerInterface accessController = AccessControllerInterface(ACCESS_CONTROLLER_ADDRESS); - - s_verifierProxy.setAccessController(accessController); - } - - function test_revertsIfNoAccess() public { - vm.mockCall( - ACCESS_CONTROLLER_ADDRESS, - abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), - abi.encode(false) - ); - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - vm.expectRevert(abi.encodeWithSelector(VerifierProxy.AccessForbidden.selector)); - - changePrank(USER); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_proxiesToTheVerifierIfHasAccess() public { - vm.mockCall( - ACCESS_CONTROLLER_ADDRESS, - abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), - abi.encode(true) - ); - - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - changePrank(USER); - bytes memory response = s_verifierProxy.verify(signedReport, bytes("")); - assertReportsEqual(response, s_testReportOne); - } -} - -contract VerifierVerifySingleConfigDigestTest is VerifierVerifyTest { - function test_revertsIfVerifiedByNonProxy() public { - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - vm.expectRevert(abi.encodeWithSelector(Verifier.AccessForbidden.selector)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfVerifiedWithIncorrectAddresses() public { - Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); - signers[10].mockPrivateKey = 1234; - bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); - changePrank(address(s_verifierProxy)); - vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfMismatchedSignatureLength() public { - bytes32[] memory rs = new bytes32[](FAULT_TOLERANCE + 1); - bytes32[] memory ss = new bytes32[](FAULT_TOLERANCE + 3); - bytes32 rawVs = bytes32(""); - bytes memory signedReport = abi.encode(s_reportContext, abi.encode(s_testReportOne), rs, ss, rawVs); - changePrank(address(s_verifierProxy)); - vm.expectRevert(abi.encodeWithSelector(Verifier.MismatchedSignatures.selector, rs.length, ss.length)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfConfigDigestNotSet() public { - bytes32[3] memory reportContext = s_reportContext; - reportContext[0] = bytes32("wrong-context-digest"); - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID, reportContext[0])); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfReportHasUnconfiguredFeedID() public { - V1Report memory report = _createV1Report( - FEED_ID_2, - OBSERVATIONS_TIMESTAMP, - MEDIAN, - BID, - ASK, - BLOCKNUMBER_UPPER_BOUND, - blockhash(BLOCKNUMBER_UPPER_BOUND), - BLOCKNUMBER_LOWER_BOUND, - uint32(block.timestamp) - ); - bytes memory signedReport = _generateV1EncodedBlob(report, s_reportContext, _getSigners(FAULT_TOLERANCE + 1)); - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID_2, s_reportContext[0])); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfWrongNumberOfSigners() public { - bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, _getSigners(10)); - vm.expectRevert(abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, 10, FAULT_TOLERANCE + 1)); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_revertsIfDuplicateSignersHaveSigned() public { - Signer[] memory signers = _getSigners(FAULT_TOLERANCE + 1); - // Duplicate signer at index 1 - signers[0] = signers[1]; - bytes memory signedReport = _generateV1EncodedBlob(s_testReportOne, s_reportContext, signers); - vm.expectRevert(abi.encodeWithSelector(Verifier.BadVerification.selector)); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } - - function test_returnsThePriceAndBlockNumIfReportVerified() public { - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - changePrank(address(s_verifierProxy)); - bytes memory response = s_verifier.verify(signedReport, msg.sender); - - assertReportsEqual(response, s_testReportOne); - } - - function test_setsTheCorrectEpoch() public { - s_reportContext[1] = bytes32(uint256(5 << 8)); - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - - (, , uint32 latestEpoch) = s_verifier.latestConfigDigestAndEpoch(FEED_ID); - assertEq(latestEpoch, 5); - } - - function test_emitsAnEventIfReportVerified() public { - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - vm.expectEmit(true, true, true, true, address(s_verifier)); - emit ReportVerified(s_testReportOne.feedId, msg.sender); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } -} - -contract VerifierVerifyMultipleConfigDigestTest is VerifierVerifyTest { - bytes32 internal s_oldConfigDigest; - bytes32 internal s_newConfigDigest; - - uint8 internal constant FAULT_TOLERANCE_TWO = 5; - - function setUp() public override { - VerifierVerifyTest.setUp(); - (, , s_oldConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - s_verifier.setConfig( - FEED_ID, - _getSignerAddresses(_getSigners(20)), - s_offchaintransmitters, - FAULT_TOLERANCE_TWO, - bytes(""), - VERIFIER_VERSION, - bytes(""), - new Common.AddressAndWeight[](0) - ); - (, , s_newConfigDigest) = s_verifier.latestConfigDetails(FEED_ID); - } - - function test_revertsIfVerifyingWithAnUnsetDigest() public { - s_verifier.deactivateConfig(FEED_ID, (s_oldConfigDigest)); - - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - changePrank(address(s_verifierProxy)); - vm.expectRevert(abi.encodeWithSelector(Verifier.DigestInactive.selector, FEED_ID, s_reportContext[0])); - s_verifier.verify(signedReport, msg.sender); - } - - function test_canVerifyOlderReportsWithOlderConfigs() public { - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - changePrank(address(s_verifierProxy)); - bytes memory response = s_verifier.verify(signedReport, msg.sender); - assertReportsEqual(response, s_testReportOne); - } - - function test_canVerifyNewerReportsWithNewerConfigs() public { - s_reportContext[0] = s_newConfigDigest; - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE_TWO + 1) - ); - changePrank(address(s_verifierProxy)); - bytes memory response = s_verifier.verify(signedReport, msg.sender); - assertReportsEqual(response, s_testReportOne); - } - - function test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() public { - // Try sending the older digest signed with the new set of signers - s_reportContext[0] = s_oldConfigDigest; - bytes memory signedReport = _generateV1EncodedBlob( - s_testReportOne, - s_reportContext, - _getSigners(FAULT_TOLERANCE_TWO + 1) - ); - vm.expectRevert( - abi.encodeWithSelector(Verifier.IncorrectSignatureCount.selector, FAULT_TOLERANCE_TWO + 1, FAULT_TOLERANCE + 1) - ); - changePrank(address(s_verifierProxy)); - s_verifier.verify(signedReport, msg.sender); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol deleted file mode 100644 index 08ac1d4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationFeeManager.sol +++ /dev/null @@ -1,573 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; -import {IWERC20} from "../../shared/interfaces/IWERC20.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {Math} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; -import {IDestinationFeeManager} from "./interfaces/IDestinationFeeManager.sol"; -import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; - -/** - * @title FeeManager - * @author Michael Fletcher - * @author Austin Born - * @notice This contract is used for the handling of fees required for users verifying reports. - */ -contract DestinationFeeManager is - IDestinationFeeManager, - IDestinationVerifierFeeManager, - ConfirmedOwner, - TypeAndVersionInterface -{ - using SafeERC20 for IERC20; - - /// @notice list of subscribers and their discounts subscriberDiscounts[subscriber][feedId][token] - mapping(address => mapping(bytes32 => mapping(address => uint256))) public s_subscriberDiscounts; - - /// @notice map of global discounts - mapping(address => mapping(address => uint256)) public s_globalDiscounts; - - /// @notice keep track of any subsidised link that is owed to the reward manager. - mapping(bytes32 => uint256) public s_linkDeficit; - - /// @notice the total discount that can be applied to a fee, 1e18 = 100% discount - uint64 private constant PERCENTAGE_SCALAR = 1e18; - - /// @notice the LINK token address - address public immutable i_linkAddress; - - /// @notice the native token address - address public immutable i_nativeAddress; - - /// @notice the verifier address - mapping(address => address) public s_verifierAddressList; - - /// @notice the reward manager address - IDestinationRewardManager public i_rewardManager; - - // @notice the mask to apply to get the report version - bytes32 private constant REPORT_VERSION_MASK = 0xffff000000000000000000000000000000000000000000000000000000000000; - - // @notice the different report versions - bytes32 private constant REPORT_V1 = 0x0001000000000000000000000000000000000000000000000000000000000000; - - /// @notice the surcharge fee to be paid if paying in native - uint256 public s_nativeSurcharge; - - /// @notice the error thrown if the discount or surcharge is invalid - error InvalidSurcharge(); - - /// @notice the error thrown if the discount is invalid - error InvalidDiscount(); - - /// @notice the error thrown if the address is invalid - error InvalidAddress(); - - /// @notice thrown if msg.value is supplied with a bad quote - error InvalidDeposit(); - - /// @notice thrown if a report has expired - error ExpiredReport(); - - /// @notice thrown if a report has no quote - error InvalidQuote(); - - // @notice thrown when the caller is not authorized - error Unauthorized(); - - // @notice thrown when trying to clear a zero deficit - error ZeroDeficit(); - - /// @notice thrown when trying to pay an address that cannot except funds - error InvalidReceivingAddress(); - - /// @notice thrown when trying to bulk verify reports where theres not a matching number of poolIds - error PoolIdMismatch(); - - /// @notice Emitted whenever a subscriber's discount is updated - /// @param subscriber address of the subscriber to update discounts for - /// @param feedId Feed ID for the discount - /// @param token Token address for the discount - /// @param discount Discount to apply, in relation to the PERCENTAGE_SCALAR - event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); - - /// @notice Emitted when updating the native surcharge - /// @param newSurcharge Surcharge amount to apply relative to PERCENTAGE_SCALAR - event NativeSurchargeUpdated(uint64 newSurcharge); - - /// @notice Emits when this contract does not have enough LINK to send to the reward manager when paying in native - /// @param rewards Config digest and link fees which could not be subsidised - event InsufficientLink(IDestinationRewardManager.FeePayment[] rewards); - - /// @notice Emitted when funds are withdrawn - /// @param adminAddress Address of the admin - /// @param recipient Address of the recipient - /// @param assetAddress Address of the asset withdrawn - /// @param quantity Amount of the asset withdrawn - event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); - - /// @notice Emits when a deficit has been cleared for a particular config digest - /// @param configDigest Config digest of the deficit cleared - /// @param linkQuantity Amount of LINK required to pay the deficit - event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); - - /// @notice Emits when a fee has been processed - /// @param configDigest Config digest of the fee processed - /// @param subscriber Address of the subscriber who paid the fee - /// @param fee Fee paid - /// @param reward Reward paid - /// @param appliedDiscount Discount applied to the fee - event DiscountApplied( - bytes32 indexed configDigest, - address indexed subscriber, - Common.Asset fee, - Common.Asset reward, - uint256 appliedDiscount - ); - - /** - * @notice Construct the FeeManager contract - * @param _linkAddress The address of the LINK token - * @param _nativeAddress The address of the wrapped ERC-20 version of the native token (represents fee in native or wrapped) - * @param _verifierAddress The address of the verifier contract - * @param _rewardManagerAddress The address of the reward manager contract - */ - constructor( - address _linkAddress, - address _nativeAddress, - address _verifierAddress, - address _rewardManagerAddress - ) ConfirmedOwner(msg.sender) { - if ( - _linkAddress == address(0) || - _nativeAddress == address(0) || - _verifierAddress == address(0) || - _rewardManagerAddress == address(0) - ) revert InvalidAddress(); - - i_linkAddress = _linkAddress; - i_nativeAddress = _nativeAddress; - s_verifierAddressList[_verifierAddress] = _verifierAddress; - i_rewardManager = IDestinationRewardManager(_rewardManagerAddress); - - IERC20(i_linkAddress).approve(address(i_rewardManager), type(uint256).max); - } - - modifier onlyVerifier() { - if (msg.sender != s_verifierAddressList[msg.sender]) revert Unauthorized(); - _; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "DestinationFeeManager 0.4.0"; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return - interfaceId == type(IDestinationFeeManager).interfaceId || - interfaceId == type(IDestinationVerifierFeeManager).interfaceId; - } - - /// @inheritdoc IDestinationVerifierFeeManager - function processFee( - bytes32 recipient, - bytes calldata payload, - bytes calldata parameterPayload, - address subscriber - ) external payable override onlyVerifier { - (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _calculateFee( - payload, - parameterPayload, - subscriber - ); - - if (fee.amount == 0) { - _tryReturnChange(subscriber, msg.value); - return; - } - - IDestinationFeeManager.FeeAndReward[] memory feeAndReward = new IDestinationFeeManager.FeeAndReward[](1); - feeAndReward[0] = IDestinationFeeManager.FeeAndReward(recipient, fee, reward, appliedDiscount); - - if (fee.assetAddress == i_linkAddress) { - _handleFeesAndRewards(subscriber, feeAndReward, 1, 0); - } else { - _handleFeesAndRewards(subscriber, feeAndReward, 0, 1); - } - } - - /// @inheritdoc IDestinationVerifierFeeManager - function processFeeBulk( - bytes32[] memory poolIds, - bytes[] calldata payloads, - bytes calldata parameterPayload, - address subscriber - ) external payable override onlyVerifier { - //poolIDs are mapped to payloads, so they should be the same length - if (poolIds.length != payloads.length) revert PoolIdMismatch(); - - IDestinationFeeManager.FeeAndReward[] memory feesAndRewards = new IDestinationFeeManager.FeeAndReward[]( - payloads.length - ); - - //keep track of the number of fees to prevent over initialising the FeePayment array within _convertToLinkAndNativeFees - uint256 numberOfLinkFees; - uint256 numberOfNativeFees; - - uint256 feesAndRewardsIndex; - for (uint256 i; i < payloads.length; ++i) { - if (poolIds[i] == bytes32(0)) revert InvalidAddress(); - - (Common.Asset memory fee, Common.Asset memory reward, uint256 appliedDiscount) = _calculateFee( - payloads[i], - parameterPayload, - subscriber - ); - - if (fee.amount != 0) { - feesAndRewards[feesAndRewardsIndex++] = IDestinationFeeManager.FeeAndReward( - poolIds[i], - fee, - reward, - appliedDiscount - ); - - unchecked { - //keep track of some tallys to make downstream calculations more efficient - if (fee.assetAddress == i_linkAddress) { - ++numberOfLinkFees; - } else { - ++numberOfNativeFees; - } - } - } - } - - if (numberOfLinkFees != 0 || numberOfNativeFees != 0) { - _handleFeesAndRewards(subscriber, feesAndRewards, numberOfLinkFees, numberOfNativeFees); - } else { - _tryReturnChange(subscriber, msg.value); - } - } - - /// @inheritdoc IDestinationFeeManager - function getFeeAndReward( - address subscriber, - bytes memory report, - address quoteAddress - ) public view returns (Common.Asset memory, Common.Asset memory, uint256) { - Common.Asset memory fee; - Common.Asset memory reward; - - //get the feedId from the report - bytes32 feedId = bytes32(report); - - //the report needs to be a support version - bytes32 reportVersion = _getReportVersion(feedId); - - //version 1 of the reports don't require quotes, so the fee will be 0 - if (reportVersion == REPORT_V1) { - fee.assetAddress = i_nativeAddress; - reward.assetAddress = i_linkAddress; - return (fee, reward, 0); - } - - //verify the quote payload is a supported token - if (quoteAddress != i_nativeAddress && quoteAddress != i_linkAddress) { - revert InvalidQuote(); - } - - //decode the report depending on the version - uint256 linkQuantity; - uint256 nativeQuantity; - uint256 expiresAt; - (, , , nativeQuantity, linkQuantity, expiresAt) = abi.decode( - report, - (bytes32, uint32, uint32, uint192, uint192, uint32) - ); - - //read the timestamp bytes from the report data and verify it has not expired - if (expiresAt < block.timestamp) { - revert ExpiredReport(); - } - - //check if feed discount has been applied - uint256 discount = s_subscriberDiscounts[subscriber][feedId][quoteAddress]; - - if (discount == 0) { - //check if a global discount has been applied - discount = s_globalDiscounts[subscriber][quoteAddress]; - } - - //the reward is always set in LINK - reward.assetAddress = i_linkAddress; - reward.amount = Math.ceilDiv(linkQuantity * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); - - //calculate either the LINK fee or native fee if it's within the report - if (quoteAddress == i_linkAddress) { - fee.assetAddress = i_linkAddress; - fee.amount = reward.amount; - } else { - uint256 surchargedFee = Math.ceilDiv(nativeQuantity * (PERCENTAGE_SCALAR + s_nativeSurcharge), PERCENTAGE_SCALAR); - - fee.assetAddress = i_nativeAddress; - fee.amount = Math.ceilDiv(surchargedFee * (PERCENTAGE_SCALAR - discount), PERCENTAGE_SCALAR); - } - - //return the fee - return (fee, reward, discount); - } - - /// @inheritdoc IDestinationVerifierFeeManager - function setFeeRecipients( - bytes32 configDigest, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external onlyVerifier { - i_rewardManager.setRewardRecipients(configDigest, rewardRecipientAndWeights); - } - - /// @inheritdoc IDestinationFeeManager - function setNativeSurcharge(uint64 surcharge) external onlyOwner { - if (surcharge > PERCENTAGE_SCALAR) revert InvalidSurcharge(); - - s_nativeSurcharge = surcharge; - - emit NativeSurchargeUpdated(surcharge); - } - - /// @inheritdoc IDestinationFeeManager - function updateSubscriberDiscount( - address subscriber, - bytes32 feedId, - address token, - uint64 discount - ) external onlyOwner { - //make sure the discount is not greater than the total discount that can be applied - if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); - //make sure the token is either LINK or native - if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); - - s_subscriberDiscounts[subscriber][feedId][token] = discount; - - emit SubscriberDiscountUpdated(subscriber, feedId, token, discount); - } - - function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external onlyOwner { - //make sure the discount is not greater than the total discount that can be applied - if (discount > PERCENTAGE_SCALAR) revert InvalidDiscount(); - //make sure the token is either LINK or native - if (token != i_linkAddress && token != i_nativeAddress) revert InvalidAddress(); - - s_globalDiscounts[subscriber][token] = discount; - - emit SubscriberDiscountUpdated(subscriber, bytes32(0), token, discount); - } - - /// @inheritdoc IDestinationFeeManager - function withdraw(address assetAddress, address recipient, uint192 quantity) external onlyOwner { - //address 0 is used to withdraw native in the context of withdrawing - if (assetAddress == address(0)) { - (bool success, ) = payable(recipient).call{value: quantity}(""); - - if (!success) revert InvalidReceivingAddress(); - return; - } - - //withdraw the requested asset - IERC20(assetAddress).safeTransfer(recipient, quantity); - - //emit event when funds are withdrawn - emit Withdraw(msg.sender, recipient, assetAddress, uint192(quantity)); - } - - /// @inheritdoc IDestinationFeeManager - function linkAvailableForPayment() external view returns (uint256) { - //return the amount of LINK this contact has available to pay rewards - return IERC20(i_linkAddress).balanceOf(address(this)); - } - - /** - * @notice Gets the current version of the report that is encoded as the last two bytes of the feed - * @param feedId feed id to get the report version for - */ - function _getReportVersion(bytes32 feedId) internal pure returns (bytes32) { - return REPORT_VERSION_MASK & feedId; - } - - function _calculateFee( - bytes calldata payload, - bytes calldata parameterPayload, - address subscriber - ) internal view returns (Common.Asset memory, Common.Asset memory, uint256) { - if (subscriber == address(this)) revert InvalidAddress(); - - //decode the report from the payload - (, bytes memory report) = abi.decode(payload, (bytes32[3], bytes)); - - //get the feedId from the report - bytes32 feedId = bytes32(report); - - //v1 doesn't need a quote payload, so skip the decoding - address quote; - if (_getReportVersion(feedId) != REPORT_V1) { - //decode the quote from the bytes - (quote) = abi.decode(parameterPayload, (address)); - } - - //decode the fee, it will always be native or LINK - return getFeeAndReward(subscriber, report, quote); - } - - function _handleFeesAndRewards( - address subscriber, - IDestinationFeeManager.FeeAndReward[] memory feesAndRewards, - uint256 numberOfLinkFees, - uint256 numberOfNativeFees - ) internal { - IDestinationRewardManager.FeePayment[] memory linkRewards = new IDestinationRewardManager.FeePayment[]( - numberOfLinkFees - ); - IDestinationRewardManager.FeePayment[] memory nativeFeeLinkRewards = new IDestinationRewardManager.FeePayment[]( - numberOfNativeFees - ); - - uint256 totalNativeFee; - uint256 totalNativeFeeLinkValue; - - uint256 linkRewardsIndex; - uint256 nativeFeeLinkRewardsIndex; - - uint256 totalNumberOfFees = numberOfLinkFees + numberOfNativeFees; - for (uint256 i; i < totalNumberOfFees; ++i) { - if (feesAndRewards[i].fee.assetAddress == i_linkAddress) { - linkRewards[linkRewardsIndex++] = IDestinationRewardManager.FeePayment( - feesAndRewards[i].configDigest, - uint192(feesAndRewards[i].reward.amount) - ); - } else { - nativeFeeLinkRewards[nativeFeeLinkRewardsIndex++] = IDestinationRewardManager.FeePayment( - feesAndRewards[i].configDigest, - uint192(feesAndRewards[i].reward.amount) - ); - totalNativeFee += feesAndRewards[i].fee.amount; - totalNativeFeeLinkValue += feesAndRewards[i].reward.amount; - } - - if (feesAndRewards[i].appliedDiscount != 0) { - emit DiscountApplied( - feesAndRewards[i].configDigest, - subscriber, - feesAndRewards[i].fee, - feesAndRewards[i].reward, - feesAndRewards[i].appliedDiscount - ); - } - } - - //keep track of change in case of any over payment - uint256 change; - - if (msg.value != 0) { - //there must be enough to cover the fee - if (totalNativeFee > msg.value) revert InvalidDeposit(); - - //wrap the amount required to pay the fee & approve as the subscriber paid in wrapped native - IWERC20(i_nativeAddress).deposit{value: totalNativeFee}(); - - unchecked { - //msg.value is always >= to fee.amount - change = msg.value - totalNativeFee; - } - } else { - if (totalNativeFee != 0) { - //subscriber has paid in wrapped native, so transfer the native to this contract - IERC20(i_nativeAddress).safeTransferFrom(subscriber, address(this), totalNativeFee); - } - } - - if (linkRewards.length != 0) { - i_rewardManager.onFeePaid(linkRewards, subscriber); - } - - if (nativeFeeLinkRewards.length != 0) { - //distribute subsidised fees paid in Native - if (totalNativeFeeLinkValue > IERC20(i_linkAddress).balanceOf(address(this))) { - // If not enough LINK on this contract to forward for rewards, tally the deficit to be paid by out-of-band LINK - for (uint256 i; i < nativeFeeLinkRewards.length; ++i) { - unchecked { - //we have previously tallied the fees, any overflows would have already reverted - s_linkDeficit[nativeFeeLinkRewards[i].poolId] += nativeFeeLinkRewards[i].amount; - } - } - - emit InsufficientLink(nativeFeeLinkRewards); - } else { - //distribute the fees - i_rewardManager.onFeePaid(nativeFeeLinkRewards, address(this)); - } - } - - // a refund may be needed if the payee has paid in excess of the fee - _tryReturnChange(subscriber, change); - } - - function _tryReturnChange(address subscriber, uint256 quantity) internal { - if (quantity != 0) { - payable(subscriber).transfer(quantity); - } - } - - /// @inheritdoc IDestinationFeeManager - function payLinkDeficit(bytes32 configDigest) external onlyOwner { - uint256 deficit = s_linkDeficit[configDigest]; - - if (deficit == 0) revert ZeroDeficit(); - - delete s_linkDeficit[configDigest]; - - IDestinationRewardManager.FeePayment[] memory deficitFeePayment = new IDestinationRewardManager.FeePayment[](1); - - deficitFeePayment[0] = IDestinationRewardManager.FeePayment(configDigest, uint192(deficit)); - - i_rewardManager.onFeePaid(deficitFeePayment, address(this)); - - emit LinkDeficitCleared(configDigest, deficit); - } - - /// @inheritdoc IDestinationFeeManager - function addVerifier(address verifierAddress) external onlyOwner { - if (verifierAddress == address(0)) revert InvalidAddress(); - //check doesn't already exist - if (s_verifierAddressList[verifierAddress] != address(0)) revert InvalidAddress(); - s_verifierAddressList[verifierAddress] = verifierAddress; - } - - /// @inheritdoc IDestinationFeeManager - function removeVerifier(address verifierAddress) external onlyOwner { - if (verifierAddress == address(0)) revert InvalidAddress(); - //check doesn't already exist - if (s_verifierAddressList[verifierAddress] == address(0)) revert InvalidAddress(); - delete s_verifierAddressList[verifierAddress]; - } - - /// @inheritdoc IDestinationFeeManager - function setRewardManager(address rewardManagerAddress) external onlyOwner { - if (rewardManagerAddress == address(0)) revert InvalidAddress(); - - if (!IERC165(rewardManagerAddress).supportsInterface(type(IDestinationRewardManager).interfaceId)) { - revert InvalidAddress(); - } - - IERC20(i_linkAddress).approve(address(i_rewardManager), 0); - i_rewardManager = IDestinationRewardManager(rewardManagerAddress); - IERC20(i_linkAddress).approve(address(rewardManagerAddress), type(uint256).max); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol deleted file mode 100644 index 4b4c1f5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationRewardManager.sol +++ /dev/null @@ -1,328 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IDestinationRewardManager} from "./interfaces/IDestinationRewardManager.sol"; -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {Common} from "../libraries/Common.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/** - * @title DestinationRewardManager - * @author Michael Fletcher - * @author Austin Born - * @notice This contract will be used to reward any configured recipients within a pool. Recipients will receive a share of their pool relative to their configured weight. - */ -contract DestinationRewardManager is IDestinationRewardManager, ConfirmedOwner, TypeAndVersionInterface { - using SafeERC20 for IERC20; - - // @dev The mapping of total fees collected for a particular pot: s_totalRewardRecipientFees[poolId] - mapping(bytes32 => uint256) public s_totalRewardRecipientFees; - - // @dev The mapping of fee balances for each pot last time the recipient claimed: s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] - mapping(bytes32 => mapping(address => uint256)) public s_totalRewardRecipientFeesLastClaimedAmounts; - - // @dev The mapping of RewardRecipient weights for a particular poolId: s_rewardRecipientWeights[poolId][rewardRecipient]. - mapping(bytes32 => mapping(address => uint256)) public s_rewardRecipientWeights; - - // @dev Keep track of the reward recipient weights that have been set to prevent duplicates - mapping(bytes32 => bool) public s_rewardRecipientWeightsSet; - - // @dev Store a list of pool ids that have been registered, to make off chain lookups easier - bytes32[] public s_registeredPoolIds; - - // @dev The address for the LINK contract - address public immutable i_linkAddress; - - // The total weight of all RewardRecipients. 1e18 = 100% of the pool fees - uint64 private constant PERCENTAGE_SCALAR = 1e18; - - // The fee manager address - mapping(address => address) public s_feeManagerAddressList; - - // @notice Thrown whenever the RewardRecipient weights are invalid - error InvalidWeights(); - - // @notice Thrown when any given address is invalid - error InvalidAddress(); - - // @notice Thrown when the pool id is invalid - error InvalidPoolId(); - - // @notice Thrown when the calling contract is not within the authorized contracts - error Unauthorized(); - - // @notice Thrown when getAvailableRewardPoolIds parameters are incorrectly set - error InvalidPoolLength(); - - // Events emitted upon state change - event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); - event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); - event FeeManagerUpdated(address newFeeManagerAddress); - event FeePaid(FeePayment[] payments, address payer); - - /** - * @notice Constructor - * @param linkAddress address of the wrapped LINK token - */ - constructor(address linkAddress) ConfirmedOwner(msg.sender) { - //ensure that the address ia not zero - if (linkAddress == address(0)) revert InvalidAddress(); - - i_linkAddress = linkAddress; - } - - // @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "DestinationRewardManager 0.4.0"; - } - - // @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return interfaceId == type(IDestinationRewardManager).interfaceId; - } - - modifier onlyOwnerOrFeeManager() { - if (msg.sender != s_feeManagerAddressList[msg.sender] && msg.sender != owner()) revert Unauthorized(); - _; - } - - modifier onlyOwnerOrRecipientInPool(bytes32 poolId) { - if (s_rewardRecipientWeights[poolId][msg.sender] == 0 && msg.sender != owner()) revert Unauthorized(); - _; - } - - modifier onlyFeeManager() { - if (msg.sender != s_feeManagerAddressList[msg.sender]) revert Unauthorized(); - _; - } - - /// @inheritdoc IDestinationRewardManager - function onFeePaid(FeePayment[] calldata payments, address payer) external override onlyFeeManager { - uint256 totalFeeAmount; - for (uint256 i; i < payments.length; ++i) { - unchecked { - //the total amount for any ERC-20 asset cannot exceed 2^256 - 1 - //see https://github.com/OpenZeppelin/openzeppelin-contracts/blob/36bf1e46fa811f0f07d38eb9cfbc69a955f300ce/contracts/token/ERC20/ERC20.sol#L266 - //for example implementation. - s_totalRewardRecipientFees[payments[i].poolId] += payments[i].amount; - - //tally the total payable fees - totalFeeAmount += payments[i].amount; - } - } - - //transfer the fees to this contract - IERC20(i_linkAddress).safeTransferFrom(payer, address(this), totalFeeAmount); - - emit FeePaid(payments, payer); - } - - /// @inheritdoc IDestinationRewardManager - function claimRewards(bytes32[] memory poolIds) external override { - _claimRewards(msg.sender, poolIds); - } - - // wrapper impl for claimRewards - function _claimRewards(address recipient, bytes32[] memory poolIds) internal returns (uint256) { - //get the total amount claimable for this recipient - uint256 claimAmount; - - //loop and claim all the rewards in the poolId pot - for (uint256 i; i < poolIds.length; ++i) { - //get the poolId to be claimed - bytes32 poolId = poolIds[i]; - - //get the total fees for the pot - uint256 totalFeesInPot = s_totalRewardRecipientFees[poolId]; - - unchecked { - //avoid unnecessary storage reads if there's no fees in the pot - if (totalFeesInPot == 0) continue; - - //get the claimable amount for this recipient, this calculation will never exceed the amount in the pot - uint256 claimableAmount = totalFeesInPot - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient]; - - //calculate the recipients share of the fees, which is their weighted share of the difference between the last amount they claimed and the current amount in the pot. This can never be more than the total amount in existence - uint256 recipientShare = (claimableAmount * s_rewardRecipientWeights[poolId][recipient]) / PERCENTAGE_SCALAR; - - //if there's no fees to claim, continue as there's nothing to update - if (recipientShare == 0) continue; - - //keep track of the total amount claimable, this can never be more than the total amount in existence - claimAmount += recipientShare; - - //set the current total amount of fees in the pot as it's used to calculate future claims - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] = totalFeesInPot; - - //emit event if the recipient has rewards to claim - emit RewardsClaimed(poolIds[i], recipient, uint192(recipientShare)); - } - } - - //check if there's any rewards to claim in the given poolId - if (claimAmount != 0) { - //transfer the reward to the recipient - IERC20(i_linkAddress).safeTransfer(recipient, claimAmount); - } - - return claimAmount; - } - - /// @inheritdoc IDestinationRewardManager - function setRewardRecipients( - bytes32 poolId, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external override onlyOwnerOrFeeManager { - //revert if there are no recipients to set - if (rewardRecipientAndWeights.length == 0) revert InvalidAddress(); - - //check that the weights have not been previously set - if (s_rewardRecipientWeightsSet[poolId]) revert InvalidPoolId(); - - //keep track of the registered poolIds to make off chain lookups easier - s_registeredPoolIds.push(poolId); - - //keep track of which pools have had their reward recipients set - s_rewardRecipientWeightsSet[poolId] = true; - - //set the reward recipients, this will only be called once and contain the full set of RewardRecipients with a total weight of 100% - _setRewardRecipientWeights(poolId, rewardRecipientAndWeights, PERCENTAGE_SCALAR); - - emit RewardRecipientsUpdated(poolId, rewardRecipientAndWeights); - } - - function _setRewardRecipientWeights( - bytes32 poolId, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights, - uint256 expectedWeight - ) internal { - //we can't update the weights if it contains duplicates - if (Common._hasDuplicateAddresses(rewardRecipientAndWeights)) revert InvalidAddress(); - - //loop all the reward recipients and validate the weight and address - uint256 totalWeight; - for (uint256 i; i < rewardRecipientAndWeights.length; ++i) { - //get the weight - uint256 recipientWeight = rewardRecipientAndWeights[i].weight; - //get the address - address recipientAddress = rewardRecipientAndWeights[i].addr; - - //ensure the reward recipient address is not zero - if (recipientAddress == address(0)) revert InvalidAddress(); - - //save/overwrite the weight for the reward recipient - s_rewardRecipientWeights[poolId][recipientAddress] = recipientWeight; - - unchecked { - //keep track of the cumulative weight, this cannot overflow as the total weight is restricted at 1e18 - totalWeight += recipientWeight; - } - } - - //if total weight is not met, the fees will either be under or over distributed - if (totalWeight != expectedWeight) revert InvalidWeights(); - } - - /// @inheritdoc IDestinationRewardManager - function updateRewardRecipients( - bytes32 poolId, - Common.AddressAndWeight[] calldata newRewardRecipients - ) external override onlyOwner { - //create an array of poolIds to pass to _claimRewards if required - bytes32[] memory poolIds = new bytes32[](1); - poolIds[0] = poolId; - - //loop all the reward recipients and claim their rewards before updating their weights - uint256 existingTotalWeight; - for (uint256 i; i < newRewardRecipients.length; ++i) { - //get the address - address recipientAddress = newRewardRecipients[i].addr; - //get the existing weight - uint256 existingWeight = s_rewardRecipientWeights[poolId][recipientAddress]; - - //if a recipient is updated, the rewards must be claimed first as they can't claim previous fees at the new weight - _claimRewards(newRewardRecipients[i].addr, poolIds); - - unchecked { - //keep tally of the weights so that the expected collective weight is known - existingTotalWeight += existingWeight; - } - } - - //update the reward recipients, if the new collective weight isn't equal to the previous collective weight, the fees will either be under or over distributed - _setRewardRecipientWeights(poolId, newRewardRecipients, existingTotalWeight); - - //emit event - emit RewardRecipientsUpdated(poolId, newRewardRecipients); - } - - /// @inheritdoc IDestinationRewardManager - function payRecipients(bytes32 poolId, address[] calldata recipients) external onlyOwnerOrRecipientInPool(poolId) { - //convert poolIds to an array to match the interface of _claimRewards - bytes32[] memory poolIdsArray = new bytes32[](1); - poolIdsArray[0] = poolId; - - //loop each recipient and claim the rewards for each of the pools and assets - for (uint256 i; i < recipients.length; ++i) { - _claimRewards(recipients[i], poolIdsArray); - } - } - - /// @inheritdoc IDestinationRewardManager - function addFeeManager(address newFeeManagerAddress) external onlyOwner { - if (newFeeManagerAddress == address(0)) revert InvalidAddress(); - if (s_feeManagerAddressList[newFeeManagerAddress] != address(0)) revert InvalidAddress(); - - s_feeManagerAddressList[newFeeManagerAddress] = newFeeManagerAddress; - - emit FeeManagerUpdated(newFeeManagerAddress); - } - - /// @inheritdoc IDestinationRewardManager - function removeFeeManager(address feeManagerAddress) external onlyOwner { - if (s_feeManagerAddressList[feeManagerAddress] == address(0)) revert InvalidAddress(); - delete s_feeManagerAddressList[feeManagerAddress]; - } - - /// @inheritdoc IDestinationRewardManager - function getAvailableRewardPoolIds( - address recipient, - uint256 startIndex, - uint256 endIndex - ) external view returns (bytes32[] memory) { - //get the length of the pool ids which we will loop through and potentially return - uint256 registeredPoolIdsLength = s_registeredPoolIds.length; - - uint256 lastIndex = endIndex > registeredPoolIdsLength ? registeredPoolIdsLength : endIndex; - - if (startIndex > lastIndex) revert InvalidPoolLength(); - - //create a new array with the maximum amount of potential pool ids - bytes32[] memory claimablePoolIds = new bytes32[](lastIndex - startIndex); - //we want the pools which a recipient has funds for to be sequential, so we need to keep track of the index - uint256 poolIdArrayIndex; - - //loop all the pool ids, and check if the recipient has a registered weight and a claimable amount - for (uint256 i = startIndex; i < lastIndex; ++i) { - //get the poolId - bytes32 poolId = s_registeredPoolIds[i]; - - //if the recipient has a weight, they are a recipient of this poolId - if (s_rewardRecipientWeights[poolId][recipient] != 0) { - //get the total in this pool - uint256 totalPoolAmount = s_totalRewardRecipientFees[poolId]; - //if the recipient has any LINK, then add the poolId to the array - unchecked { - //s_totalRewardRecipientFeesLastClaimedAmounts can never exceed total pool amount, and the number of pools can't exceed the max array length - if (totalPoolAmount - s_totalRewardRecipientFeesLastClaimedAmounts[poolId][recipient] != 0) { - claimablePoolIds[poolIdArrayIndex++] = poolId; - } - } - } - } - - return claimablePoolIds; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol deleted file mode 100644 index 8ab0f6a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifier.sol +++ /dev/null @@ -1,443 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {IDestinationVerifier} from "./interfaces/IDestinationVerifier.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../libraries/Common.sol"; -import {IAccessController} from "../../shared/interfaces/IAccessController.sol"; -import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; -import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; -import {IDestinationVerifierFeeManager} from "./interfaces/IDestinationVerifierFeeManager.sol"; - -// OCR2 standard -uint256 constant MAX_NUM_ORACLES = 31; - -/** - * @title DestinationVerifier - * @author Michael Fletcher - * @notice This contract will be used to verify reports based on the oracle signatures. This is not the source verifier which required individual fee configurations, instead, this checks that a report has been signed by one of the configured oracles. - */ -contract DestinationVerifier is - IDestinationVerifier, - IDestinationVerifierProxyVerifier, - ConfirmedOwner, - TypeAndVersionInterface -{ - /// @notice The list of DON configurations by hash(address|donConfigId) - set to true if the signer is part of the config - mapping(bytes32 => bool) private s_signerByAddressAndDonConfigId; - - /// array of DON configs - DonConfig[] private s_donConfigs; - - /// @notice The address of the verifierProxy - address public s_feeManager; - - /// @notice The address of the access controller - address public s_accessController; - - /// @notice The address of the verifierProxy - IDestinationVerifierProxy public immutable i_verifierProxy; - - /// @notice This error is thrown whenever trying to set a config - /// with a fault tolerance of 0 - error FaultToleranceMustBePositive(); - - /// @notice This error is thrown whenever a report is signed - /// with more than the max number of signers - /// @param numSigners The number of signers who have signed the report - /// @param maxSigners The maximum number of signers that can sign a report - error ExcessSigners(uint256 numSigners, uint256 maxSigners); - - /// @notice This error is thrown whenever a report is signed or expected to be signed with less than the minimum number of signers - /// @param numSigners The number of signers who have signed the report - /// @param minSigners The minimum number of signers that need to sign a report - error InsufficientSigners(uint256 numSigners, uint256 minSigners); - - /// @notice This error is thrown whenever a report is submitted with no signatures - error NoSigners(); - - /// @notice This error is thrown whenever a DonConfig already exists - /// @param donConfigId The ID of the DonConfig that already exists - error DonConfigAlreadyExists(bytes24 donConfigId); - - /// @notice This error is thrown whenever the R and S signer components - /// have different lengths - /// @param rsLength The number of r signature components - /// @param ssLength The number of s signature components - error MismatchedSignatures(uint256 rsLength, uint256 ssLength); - - /// @notice This error is thrown whenever setting a config with duplicate signatures - error NonUniqueSignatures(); - - /* @notice This error is thrown whenever a report fails to verify. This error be thrown for multiple reasons and it's purposely like - * this to prevent information being leaked about the verification process which could be used to enable free verifications maliciously - */ - error BadVerification(); - - /// @notice This error is thrown whenever a zero address is passed - error ZeroAddress(); - - /// @notice This error is thrown when the fee manager at an address does - /// not conform to the fee manager interface - error FeeManagerInvalid(); - - /// @notice This error is thrown whenever an address tries - /// to execute a verification that it is not authorized to do so - error AccessForbidden(); - - /// @notice This error is thrown whenever a config does not exist - error DonConfigDoesNotExist(); - - /// @notice This error is thrown when the activation time is either in the future or less than the current configs - error BadActivationTime(); - - /// @notice This event is emitted when a new report is verified. - /// It is used to keep a historical record of verified reports. - event ReportVerified(bytes32 indexed feedId, address requester); - - /// @notice This event is emitted whenever a configuration is activated or deactivated - event ConfigActivated(bytes24 donConfigId, bool isActive); - - /// @notice This event is emitted whenever a configuration is removed - event ConfigRemoved(bytes24 donConfigId); - - /// @notice event is emitted whenever a new DON Config is set - event ConfigSet( - bytes24 indexed donConfigId, - address[] signers, - uint8 f, - Common.AddressAndWeight[] recipientAddressesAndWeights, - uint16 donConfigIndex - ); - - /// @notice This event is emitted when a new fee manager is set - /// @param oldFeeManager The old fee manager address - /// @param newFeeManager The new fee manager address - event FeeManagerSet(address oldFeeManager, address newFeeManager); - - /// @notice This event is emitted when a new access controller is set - /// @param oldAccessController The old access controller address - /// @param newAccessController The new access controller address - event AccessControllerSet(address oldAccessController, address newAccessController); - - struct DonConfig { - // The ID of the DonConfig - bytes24 donConfigId; - // Fault tolerance of the DON - uint8 f; - // Whether the config is active - bool isActive; - // The time the config was set - uint32 activationTime; - } - - constructor(address verifierProxy) ConfirmedOwner(msg.sender) { - if (verifierProxy == address(0)) { - revert ZeroAddress(); - } - - i_verifierProxy = IDestinationVerifierProxy(verifierProxy); - } - - /// @inheritdoc IDestinationVerifierProxyVerifier - function verify( - bytes calldata signedReport, - bytes calldata parameterPayload, - address sender - ) external payable override onlyProxy checkAccess(sender) returns (bytes memory) { - (bytes memory verifierResponse, bytes32 donConfigId) = _verify(signedReport, sender); - - address fm = s_feeManager; - if (fm != address(0)) { - //process the fee and catch the error - try - IDestinationVerifierFeeManager(fm).processFee{value: msg.value}( - donConfigId, - signedReport, - parameterPayload, - sender - ) - { - //do nothing - } catch { - // we purposefully obfuscate the error here to prevent information leaking leading to free verifications - revert BadVerification(); - } - } - - return verifierResponse; - } - - /// @inheritdoc IDestinationVerifierProxyVerifier - function verifyBulk( - bytes[] calldata signedReports, - bytes calldata parameterPayload, - address sender - ) external payable override onlyProxy checkAccess(sender) returns (bytes[] memory) { - bytes[] memory verifierResponses = new bytes[](signedReports.length); - bytes32[] memory donConfigs = new bytes32[](signedReports.length); - - for (uint256 i; i < signedReports.length; ++i) { - (bytes memory report, bytes32 config) = _verify(signedReports[i], sender); - verifierResponses[i] = report; - donConfigs[i] = config; - } - - address fm = s_feeManager; - if (fm != address(0)) { - //process the fee and catch the error - try - IDestinationVerifierFeeManager(fm).processFeeBulk{value: msg.value}( - donConfigs, - signedReports, - parameterPayload, - sender - ) - { - //do nothing - } catch { - // we purposefully obfuscate the error here to prevent information leaking leading to free verifications - revert BadVerification(); - } - } - - return verifierResponses; - } - - function _verify(bytes calldata signedReport, address sender) internal returns (bytes memory, bytes32) { - ( - bytes32[3] memory reportContext, - bytes memory reportData, - bytes32[] memory rs, - bytes32[] memory ss, - bytes32 rawVs - ) = abi.decode(signedReport, (bytes32[3], bytes, bytes32[], bytes32[], bytes32)); - - // Signature lengths must match - if (rs.length != ss.length) revert MismatchedSignatures(rs.length, ss.length); - - //Must always be at least 1 signer - if (rs.length == 0) revert NoSigners(); - - // The payload is hashed and signed by the oracles - we need to recover the addresses - bytes32 signedPayload = keccak256(abi.encodePacked(keccak256(reportData), reportContext)); - address[] memory signers = new address[](rs.length); - for (uint256 i; i < rs.length; ++i) { - signers[i] = ecrecover(signedPayload, uint8(rawVs[i]) + 27, rs[i], ss[i]); - } - - // Duplicate signatures are not allowed - if (Common._hasDuplicateAddresses(signers)) { - revert BadVerification(); - } - - //We need to know the timestamp the report was generated to lookup the active activeDonConfig - uint256 reportTimestamp = _decodeReportTimestamp(reportData); - - // Find the latest config for this report - DonConfig memory activeDonConfig = _findActiveConfig(reportTimestamp); - - // Check a config has been set - if (activeDonConfig.donConfigId == bytes24(0)) { - revert BadVerification(); - } - - //check the config is active - if (!activeDonConfig.isActive) { - revert BadVerification(); - } - - //check we have enough signatures - if (signers.length <= activeDonConfig.f) { - revert BadVerification(); - } - - //check each signer is registered against the active DON - bytes32 signerDonConfigKey; - for (uint256 i; i < signers.length; ++i) { - signerDonConfigKey = keccak256(abi.encodePacked(signers[i], activeDonConfig.donConfigId)); - if (!s_signerByAddressAndDonConfigId[signerDonConfigKey]) { - revert BadVerification(); - } - } - - emit ReportVerified(bytes32(reportData), sender); - - return (reportData, activeDonConfig.donConfigId); - } - - /// @inheritdoc IDestinationVerifier - function setConfigWithActivationTime( - address[] memory signers, - uint8 f, - Common.AddressAndWeight[] memory recipientAddressesAndWeights, - uint32 activationTime - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig(signers, f, recipientAddressesAndWeights, activationTime); - } - - /// @inheritdoc IDestinationVerifier - function setConfig( - address[] memory signers, - uint8 f, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig(signers, f, recipientAddressesAndWeights, uint32(block.timestamp)); - } - - function _setConfig( - address[] memory signers, - uint8 f, - Common.AddressAndWeight[] memory recipientAddressesAndWeights, - uint32 activationTime - ) internal { - // Duplicate addresses would break protocol rules - if (Common._hasDuplicateAddresses(signers)) { - revert NonUniqueSignatures(); - } - - //activation time cannot be in the future - if (activationTime > block.timestamp) { - revert BadActivationTime(); - } - - // Sort signers to ensure donConfigId is deterministic - Common._quickSort(signers, 0, int256(signers.length - 1)); - - //DonConfig is made up of hash(signers|f) - bytes24 donConfigId = bytes24(keccak256(abi.encodePacked(signers, f))); - - // Register the signers for this DON - for (uint256 i; i < signers.length; ++i) { - if (signers[i] == address(0)) revert ZeroAddress(); - /** This index is registered so we can efficiently lookup whether a NOP is part of a config without having to - loop through the entire config each verification. It's effectively a DonConfig <-> Signer - composite key which keys track of all historic configs for a signer */ - s_signerByAddressAndDonConfigId[keccak256(abi.encodePacked(signers[i], donConfigId))] = true; - } - - // Check the activation time is greater than the latest config - uint256 donConfigLength = s_donConfigs.length; - if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].activationTime >= activationTime) { - revert BadActivationTime(); - } - - // Check the config we're setting isn't already set as the current active config as this will increase search costs unnecessarily when verifying historic reports - if (donConfigLength > 0 && s_donConfigs[donConfigLength - 1].donConfigId == donConfigId) { - revert DonConfigAlreadyExists(donConfigId); - } - - // We may want to register these later or skip this step in the unlikely scenario they've previously been registered in the RewardsManager - if (recipientAddressesAndWeights.length != 0) { - if (s_feeManager == address(0)) { - revert FeeManagerInvalid(); - } - IDestinationVerifierFeeManager(s_feeManager).setFeeRecipients(donConfigId, recipientAddressesAndWeights); - } - - // push the DonConfig - s_donConfigs.push(DonConfig(donConfigId, f, true, activationTime)); - - emit ConfigSet(donConfigId, signers, f, recipientAddressesAndWeights, uint16(donConfigLength)); - } - - /// @inheritdoc IDestinationVerifier - function setFeeManager(address feeManager) external override onlyOwner { - if (!IERC165(feeManager).supportsInterface(type(IDestinationVerifierFeeManager).interfaceId)) - revert FeeManagerInvalid(); - - address oldFeeManager = s_feeManager; - s_feeManager = feeManager; - - emit FeeManagerSet(oldFeeManager, feeManager); - } - - /// @inheritdoc IDestinationVerifier - function setAccessController(address accessController) external override onlyOwner { - address oldAccessController = s_accessController; - s_accessController = accessController; - emit AccessControllerSet(oldAccessController, accessController); - } - - /// @inheritdoc IDestinationVerifier - function setConfigActive(uint256 donConfigIndex, bool isActive) external onlyOwner { - // Config must exist - if (donConfigIndex >= s_donConfigs.length) { - revert DonConfigDoesNotExist(); - } - - // Update the config - DonConfig storage config = s_donConfigs[donConfigIndex]; - config.isActive = isActive; - - emit ConfigActivated(config.donConfigId, isActive); - } - - /// @inheritdoc IDestinationVerifier - function removeLatestConfig() external onlyOwner { - if (s_donConfigs.length == 0) { - revert DonConfigDoesNotExist(); - } - - DonConfig memory config = s_donConfigs[s_donConfigs.length - 1]; - - s_donConfigs.pop(); - - emit ConfigRemoved(config.donConfigId); - } - - function _decodeReportTimestamp(bytes memory reportPayload) internal pure returns (uint256) { - (, , uint256 timestamp) = abi.decode(reportPayload, (bytes32, uint32, uint32)); - - return timestamp; - } - - function _findActiveConfig(uint256 timestamp) internal view returns (DonConfig memory) { - DonConfig memory activeDonConfig; - - // 99% of the time the signer config will be the last index, however for historic reports generated by a previous configuration we'll need to cycle back - uint256 i = s_donConfigs.length; - while (i > 0) { - --i; - if (s_donConfigs[i].activationTime <= timestamp) { - activeDonConfig = s_donConfigs[i]; - break; - } - } - return activeDonConfig; - } - - modifier checkConfigValid(uint256 numSigners, uint256 f) { - if (f == 0) revert FaultToleranceMustBePositive(); - if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); - if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); - _; - } - - modifier onlyProxy() { - if (address(i_verifierProxy) != msg.sender) { - revert AccessForbidden(); - } - _; - } - - modifier checkAccess(address sender) { - address ac = s_accessController; - if (address(ac) != address(0) && !IAccessController(ac).hasAccess(sender, msg.data)) revert AccessForbidden(); - _; - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { - return - interfaceId == type(IDestinationVerifier).interfaceId || - interfaceId == type(IDestinationVerifierProxyVerifier).interfaceId; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "DestinationVerifier 0.4.0"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol deleted file mode 100644 index 6790883..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/DestinationVerifierProxy.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IDestinationVerifierProxy} from "./interfaces/IDestinationVerifierProxy.sol"; -import {IDestinationVerifierProxyVerifier} from "./interfaces/IDestinationVerifierProxyVerifier.sol"; - -/** - * @title DestinationVerifierProxy - * @author Michael Fletcher - * @notice This contract will be used to route all requests through to the assigned verifier contract. This contract does not support individual feed configurations and is aimed at being a simple proxy for the verifier contract on any destination chain. - */ -contract DestinationVerifierProxy is IDestinationVerifierProxy, ConfirmedOwner, TypeAndVersionInterface { - /// @notice The active verifier for this proxy - IDestinationVerifierProxyVerifier private s_verifier; - - /// @notice This error is thrown whenever a zero address is passed - error ZeroAddress(); - - /// @notice This error is thrown when trying to set a verifier address that does not implement the expected interface - error VerifierInvalid(address verifierAddress); - - constructor() ConfirmedOwner(msg.sender) {} - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "DestinationVerifierProxy 0.4.0"; - } - - /// @inheritdoc IDestinationVerifierProxy - function verify(bytes calldata payload, bytes calldata parameterPayload) external payable returns (bytes memory) { - return s_verifier.verify{value: msg.value}(payload, parameterPayload, msg.sender); - } - - /// @inheritdoc IDestinationVerifierProxy - function verifyBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload - ) external payable returns (bytes[] memory verifiedReports) { - return s_verifier.verifyBulk{value: msg.value}(payloads, parameterPayload, msg.sender); - } - - /// @inheritdoc IDestinationVerifierProxy - function setVerifier(address verifierAddress) external onlyOwner { - //check it supports the functions we need - if (!IERC165(verifierAddress).supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId)) - revert VerifierInvalid(verifierAddress); - - s_verifier = IDestinationVerifierProxyVerifier(verifierAddress); - } - - /// @inheritdoc IDestinationVerifierProxy - // solhint-disable-next-line func-name-mixedcase - function s_feeManager() external view override returns (address) { - return s_verifier.s_feeManager(); - } - - /// @inheritdoc IDestinationVerifierProxy - // solhint-disable-next-line func-name-mixedcase - function s_accessController() external view override returns (address) { - return s_verifier.s_accessController(); - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { - return interfaceId == type(IDestinationVerifierProxy).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol deleted file mode 100644 index 00420a4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationFeeManager.sol +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IDestinationFeeManager is IERC165 { - /** - * @notice Calculate the applied fee and the reward from a report. If the sender is a subscriber, they will receive a discount. - * @param subscriber address trying to verify - * @param report report to calculate the fee for - * @param quoteAddress address of the quote payment token - * @return (fee, reward, totalDiscount) fee and the reward data with the discount applied - */ - function getFeeAndReward( - address subscriber, - bytes memory report, - address quoteAddress - ) external returns (Common.Asset memory, Common.Asset memory, uint256); - - /** - * @notice Sets the native surcharge - * @param surcharge surcharge to be paid if paying in native - */ - function setNativeSurcharge(uint64 surcharge) external; - - /** - * @notice Adds a subscriber to the fee manager - * @param subscriber address of the subscriber - * @param feedId feed id to apply the discount to - * @param token token to apply the discount to - * @param discount discount to be applied to the fee - */ - function updateSubscriberDiscount(address subscriber, bytes32 feedId, address token, uint64 discount) external; - - /** - * @notice Adds a subscriber to the fee manager - * @param subscriber address of the subscriber - * @param token token to apply the discount to - * @param discount discount to be applied to the fee - */ - function updateSubscriberGlobalDiscount(address subscriber, address token, uint64 discount) external; - - /** - * @notice Withdraws any native or LINK rewards to the owner address - * @param assetAddress address of the asset to withdraw - * @param recipientAddress address to withdraw to - * @param quantity quantity to withdraw - */ - function withdraw(address assetAddress, address recipientAddress, uint192 quantity) external; - - /** - * @notice Returns the link balance of the fee manager - * @return link balance of the fee manager - */ - function linkAvailableForPayment() external returns (uint256); - - /** - * @notice Admin function to pay the LINK deficit for a given config digest - * @param configDigest the config digest to pay the deficit for - */ - function payLinkDeficit(bytes32 configDigest) external; - - /** - * @notice Adds the verifier to the list of verifiers able to use the feeManager - * @param verifier address of the verifier - */ - function addVerifier(address verifier) external; - - /** - * @notice Removes the verifier from the list of verifiers able to use the feeManager - * @param verifier address of the verifier - */ - function removeVerifier(address verifier) external; - - /** - * @notice Sets the reward manager to the address - * @param rewardManager address of the reward manager - */ - function setRewardManager(address rewardManager) external; - - /** - * @notice The structure to hold a fee and reward to verify a report - * @param digest the digest linked to the fee and reward - * @param fee the fee paid to verify the report - * @param reward the reward paid upon verification - & @param appliedDiscount the discount applied to the reward - */ - struct FeeAndReward { - bytes32 configDigest; - Common.Asset fee; - Common.Asset reward; - uint256 appliedDiscount; - } - - /** - * @notice The structure to hold quote metadata - * @param quoteAddress the address of the quote - */ - struct Quote { - address quoteAddress; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol deleted file mode 100644 index 95f0793..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationRewardManager.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IDestinationRewardManager is IERC165 { - /** - * @notice Record the fee received for a particular pool - * @param payments array of structs containing pool id and amount - * @param payee the user the funds should be retrieved from - */ - function onFeePaid(FeePayment[] calldata payments, address payee) external; - - /** - * @notice Claims the rewards in a specific pool - * @param poolIds array of poolIds to claim rewards for - */ - function claimRewards(bytes32[] calldata poolIds) external; - - /** - * @notice Set the RewardRecipients and weights for a specific pool. This should only be called once per pool Id. Else updateRewardRecipients should be used. - * @param poolId poolId to set RewardRecipients and weights for - * @param rewardRecipientAndWeights array of each RewardRecipient and associated weight - */ - function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata rewardRecipientAndWeights) external; - - /** - * @notice Updates a subset the reward recipients for a specific poolId. The collective weight of the recipients should add up to the recipients existing weights. Any recipients with a weight of 0 will be removed. - * @param poolId the poolId to update - * @param newRewardRecipients array of new reward recipients - */ - function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] calldata newRewardRecipients) external; - - /** - * @notice Pays all the recipients for each of the pool ids - * @param poolId the pool id to pay recipients for - * @param recipients array of recipients to pay within the pool - */ - function payRecipients(bytes32 poolId, address[] calldata recipients) external; - - /** - * @notice Add the fee manager to the list of feeManagers able to call the reward manager - * @param newFeeManager address of the new verifier proxy - */ - function addFeeManager(address newFeeManager) external; - - /** - * @notice Removes the fee manager. This needs to be done post construction to prevent a circular dependency. - * @param feeManager address of the verifier proxy to remove - */ - function removeFeeManager(address feeManager) external; - - /** - * @notice Gets a list of pool ids which have reward for a specific recipient. - * @param recipient address of the recipient to get pool ids for - * @param startIndex the index to start from - * @param endIndex the index to stop at - */ - function getAvailableRewardPoolIds( - address recipient, - uint256 startIndex, - uint256 endIndex - ) external view returns (bytes32[] memory); - - /** - * @notice The structure to hold a fee payment notice - * @param poolId the poolId receiving the payment - * @param amount the amount being paid - */ - struct FeePayment { - bytes32 poolId; - uint192 amount; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol deleted file mode 100644 index 041a8c8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifier.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Common} from "../../libraries/Common.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -interface IDestinationVerifier is IERC165 { - /** - * @notice sets off-chain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param f number of faulty oracles the system can tolerate - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - */ - function setConfig( - address[] memory signers, - uint8 f, - Common.AddressAndWeight[] memory recipientAddressesAndWeights - ) external; - - /** - * @notice sets off-chain reporting protocol configuration incl. participating oracles - * @param signers addresses with which oracles sign the reports - * @param f number of faulty oracles the system can tolerate - * @param recipientAddressesAndWeights the addresses and weights of all the recipients to receive rewards - * @param activationTime the time at which the config was activated - */ - function setConfigWithActivationTime( - address[] memory signers, - uint8 f, - Common.AddressAndWeight[] memory recipientAddressesAndWeights, - uint32 activationTime - ) external; - - /** - * @notice Sets the fee manager address - * @param feeManager The address of the fee manager - */ - function setFeeManager(address feeManager) external; - - /** - * @notice Sets the access controller address - * @param accessController The address of the access controller - */ - function setAccessController(address accessController) external; - - /** - * @notice Updates the config active status - * @param donConfigId The ID of the config to update - * @param isActive The new config active status - */ - function setConfigActive(uint256 donConfigId, bool isActive) external; - - /** - * @notice Removes the latest config - */ - function removeLatestConfig() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol deleted file mode 100644 index 291f370..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierFeeManager.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {Common} from "../../libraries/Common.sol"; - -interface IDestinationVerifierFeeManager is IERC165 { - /** - * @notice Handles fees for a report from the subscriber and manages rewards - * @param poolId pool id of the pool to pay into - * @param payload report to process the fee for - * @param parameterPayload fee payload - * @param subscriber address of the fee will be applied - */ - function processFee( - bytes32 poolId, - bytes calldata payload, - bytes calldata parameterPayload, - address subscriber - ) external payable; - - /** - * @notice Processes the fees for each report in the payload, billing the subscriber and paying the reward manager - * @param poolIds pool ids of the pool to pay into - * @param payloads reports to process - * @param parameterPayload fee payload - * @param subscriber address of the user to process fee for - */ - function processFeeBulk( - bytes32[] memory poolIds, - bytes[] calldata payloads, - bytes calldata parameterPayload, - address subscriber - ) external payable; - - /** - * @notice Sets the fee recipients according to the fee manager - * @param configDigest digest of the configuration - * @param rewardRecipientAndWeights the address and weights of all the recipients to receive rewards - */ - function setFeeRecipients( - bytes32 configDigest, - Common.AddressAndWeight[] calldata rewardRecipientAndWeights - ) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol deleted file mode 100644 index e0dcb30..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxy.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -interface IDestinationVerifierProxy is IERC165 { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the verifier, and bills the user if applicable. - * @param payload The encoded data to be verified, including the signed - * report. - * @param parameterPayload fee metadata for billing - * @return verifierResponse The encoded report from the verifier. - */ - function verify( - bytes calldata payload, - bytes calldata parameterPayload - ) external payable returns (bytes memory verifierResponse); - - /** - * @notice Bulk verifies that the data encoded has been signed - * correctly by routing to the correct verifier, and bills the user if applicable. - * @param payloads The encoded payloads to be verified, including the signed - * report. - * @param parameterPayload fee metadata for billing - * @return verifiedReports The encoded reports from the verifier. - */ - function verifyBulk( - bytes[] calldata payloads, - bytes calldata parameterPayload - ) external payable returns (bytes[] memory verifiedReports); - - /** - * @notice Sets the active verifier for this proxy - * @param verifierAddress The address of the verifier contract - */ - function setVerifier(address verifierAddress) external; - - /** - * @notice Used to honor the source verifierProxy feeManager interface - * @return IVerifierFeeManager - */ - // solhint-disable-next-line func-name-mixedcase - function s_feeManager() external view returns (address); - - /** - * @notice Used to honor the source verifierProxy feeManager interface - * @return AccessControllerInterface - */ - // solhint-disable-next-line func-name-mixedcase - function s_accessController() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol deleted file mode 100644 index a957f8f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -interface IDestinationVerifierProxyVerifier is IERC165 { - /** - * @notice Verifies that the data encoded has been signed correctly using the signatures included within the payload. - * @param signedReport The encoded data to be verified. - * @param parameterPayload The encoded parameters to be used in the verification and billing process. - * @param sender The address that requested to verify the contract.Used for logging and applying the fee. - * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. - * @return verifierResponse The encoded verified response. - */ - function verify( - bytes calldata signedReport, - bytes calldata parameterPayload, - address sender - ) external payable returns (bytes memory verifierResponse); - - /** - * @notice Bulk verifies that the data encoded has been signed correctly using the signatures included within the payload. - * @param signedReports The encoded data to be verified. - * @param parameterPayload The encoded parameters to be used in the verification and billing process. - * @param sender The address that requested to verify the contract. Used for logging and applying the fee. - * @dev Verification is typically only done through the proxy contract so we can't just use msg.sender. - * @return verifiedReports The encoded verified responses. - */ - function verifyBulk( - bytes[] calldata signedReports, - bytes calldata parameterPayload, - address sender - ) external payable returns (bytes[] memory verifiedReports); - - /* - * @notice Returns the reward manager - * @return IDestinationRewardManager - */ - // solhint-disable-next-line func-name-mixedcase - function s_feeManager() external view returns (address); - - /** - * @notice Returns the access controller - * @return IDestinationFeeManager - */ - // solhint-disable-next-line func-name-mixedcase - function s_accessController() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol deleted file mode 100644 index 38b1bad..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/BaseDestinationFeeManager.t.sol +++ /dev/null @@ -1,406 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {DestinationFeeManager} from "../../DestinationFeeManager.sol"; -import {DestinationRewardManager} from "../../DestinationRewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; -import {DestinationFeeManagerProxy} from "../mocks/DestinationFeeManagerProxy.sol"; - -/** - * @title BaseDestinationFeeManagerTest - * @author Michael Fletcher - * @notice Base class for all feeManager tests - * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup the feeManager - */ -contract BaseDestinationFeeManagerTest is Test { - //contracts - DestinationFeeManager internal feeManager; - DestinationRewardManager internal rewardManager; - DestinationFeeManagerProxy internal feeManagerProxy; - - ERC20Mock internal link; - WERC20Mock internal native; - - //erc20 config - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - //contract owner - address internal constant INVALID_ADDRESS = address(0); - address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); - address internal constant USER = address(uint160(uint256(keccak256("USER")))); - address internal constant PROXY = address(uint160(uint256(keccak256("PROXY")))); - - //version masks - bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; - - //feed ids & config digests - bytes32 internal constant DEFAULT_FEED_1_V1 = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant DEFAULT_FEED_1_V2 = (keccak256("ETH-USD") & V_MASK) | V2_BITMASK; - bytes32 internal constant DEFAULT_FEED_1_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; - - bytes32 internal constant DEFAULT_FEED_2_V3 = (keccak256("LINK-USD") & V_MASK) | V3_BITMASK; - bytes32 internal constant DEFAULT_CONFIG_DIGEST = keccak256("DEFAULT_CONFIG_DIGEST"); - bytes32 internal constant DEFAULT_CONFIG_DIGEST2 = keccak256("DEFAULT_CONFIG_DIGEST2"); - - //report - uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; - uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; - - //rewards - uint64 internal constant FEE_SCALAR = 1e18; - - address internal constant NATIVE_WITHDRAW_ADDRESS = address(0); - - //the selector for each error - bytes4 internal immutable INVALID_DISCOUNT_ERROR = DestinationFeeManager.InvalidDiscount.selector; - bytes4 internal immutable INVALID_ADDRESS_ERROR = DestinationFeeManager.InvalidAddress.selector; - bytes4 internal immutable INVALID_SURCHARGE_ERROR = DestinationFeeManager.InvalidSurcharge.selector; - bytes4 internal immutable EXPIRED_REPORT_ERROR = DestinationFeeManager.ExpiredReport.selector; - bytes4 internal immutable INVALID_DEPOSIT_ERROR = DestinationFeeManager.InvalidDeposit.selector; - bytes4 internal immutable INVALID_QUOTE_ERROR = DestinationFeeManager.InvalidQuote.selector; - bytes4 internal immutable UNAUTHORIZED_ERROR = DestinationFeeManager.Unauthorized.selector; - bytes4 internal immutable POOLID_MISMATCH_ERROR = DestinationFeeManager.PoolIdMismatch.selector; - bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; - bytes internal constant INSUFFICIENT_ALLOWANCE_ERROR = "ERC20: insufficient allowance"; - bytes4 internal immutable ZERO_DEFICIT = DestinationFeeManager.ZeroDeficit.selector; - - //events emitted - event SubscriberDiscountUpdated(address indexed subscriber, bytes32 indexed feedId, address token, uint64 discount); - event NativeSurchargeUpdated(uint64 newSurcharge); - event InsufficientLink(IDestinationRewardManager.FeePayment[] feesAndRewards); - event Withdraw(address adminAddress, address recipient, address assetAddress, uint192 quantity); - event LinkDeficitCleared(bytes32 indexed configDigest, uint256 linkQuantity); - event DiscountApplied( - bytes32 indexed configDigest, - address indexed subscriber, - Common.Asset fee, - Common.Asset reward, - uint256 appliedDiscountQuantity - ); - - function setUp() public virtual { - //change to admin user - vm.startPrank(ADMIN); - - //init required contracts - _initializeContracts(); - } - - function _initializeContracts() internal { - link = new ERC20Mock("LINK", "LINK", ADMIN, 0); - native = new WERC20Mock(); - - feeManagerProxy = new DestinationFeeManagerProxy(); - rewardManager = new DestinationRewardManager(address(link)); - feeManager = new DestinationFeeManager( - address(link), - address(native), - address(feeManagerProxy), - address(rewardManager) - ); - - //link the feeManager to the proxy - feeManagerProxy.setDestinationFeeManager(address(feeManager)); - - //link the feeManager to the reward manager - rewardManager.addFeeManager(address(feeManager)); - - //mint some tokens to the admin - link.mint(ADMIN, DEFAULT_LINK_MINT_QUANTITY); - native.mint(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(ADMIN, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some tokens to the proxy - link.mint(PROXY, DEFAULT_LINK_MINT_QUANTITY); - native.mint(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(PROXY, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function setSubscriberDiscount( - address subscriber, - bytes32 feedId, - address token, - uint256 discount, - address sender - ) internal { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the discount - feeManager.updateSubscriberDiscount(subscriber, feedId, token, uint64(discount)); - - //change back to the original address - changePrank(originalAddr); - } - - function setSubscriberGlobalDiscount(address subscriber, address token, uint256 discount, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the discount - feeManager.updateSubscriberGlobalDiscount(subscriber, token, uint64(discount)); - - //change back to the original address - changePrank(originalAddr); - } - - function setNativeSurcharge(uint256 surcharge, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the surcharge - feeManager.setNativeSurcharge(uint64(surcharge)); - - //change back to the original address - changePrank(originalAddr); - } - - // solium-disable-next-line no-unused-vars - function getFee(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { - //get the fee - (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(subscriber, report, quote); - - return fee; - } - - function getReward(bytes memory report, address quote, address subscriber) public view returns (Common.Asset memory) { - //get the reward - (, Common.Asset memory reward, ) = feeManager.getFeeAndReward(subscriber, report, quote); - - return reward; - } - - function getAppliedDiscount(bytes memory report, address quote, address subscriber) public view returns (uint256) { - //get the reward - (, , uint256 appliedDiscount) = feeManager.getFeeAndReward(subscriber, report, quote); - - return appliedDiscount; - } - - function getV1Report(bytes32 feedId) public pure returns (bytes memory) { - return abi.encode(feedId, uint32(0), int192(0), int192(0), int192(0), uint64(0), bytes32(0), uint64(0), uint64(0)); - } - - function getV2Report(bytes32 feedId) public view returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(DEFAULT_REPORT_NATIVE_FEE), - uint192(DEFAULT_REPORT_LINK_FEE), - uint32(block.timestamp), - int192(0) - ); - } - - function getV3Report(bytes32 feedId) public view returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(DEFAULT_REPORT_NATIVE_FEE), - uint192(DEFAULT_REPORT_LINK_FEE), - uint32(block.timestamp), - int192(0), - int192(0), - int192(0) - ); - } - - function getV3ReportWithCustomExpiryAndFee( - bytes32 feedId, - uint256 expiry, - uint256 linkFee, - uint256 nativeFee - ) public pure returns (bytes memory) { - return - abi.encode( - feedId, - uint32(0), - uint32(0), - uint192(nativeFee), - uint192(linkFee), - uint32(expiry), - int192(0), - int192(0), - int192(0) - ); - } - - function getLinkQuote() public view returns (address) { - return address(link); - } - - function getNativeQuote() public view returns (address) { - return address(native); - } - - function withdraw(address assetAddress, address recipient, uint256 amount, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //set the surcharge - feeManager.withdraw(assetAddress, recipient, uint192(amount)); - - //change back to the original address - changePrank(originalAddr); - } - - function getLinkBalance(address balanceAddress) public view returns (uint256) { - return link.balanceOf(balanceAddress); - } - - function getNativeBalance(address balanceAddress) public view returns (uint256) { - return native.balanceOf(balanceAddress); - } - - function getNativeUnwrappedBalance(address balanceAddress) public view returns (uint256) { - return balanceAddress.balance; - } - - function mintLink(address recipient, uint256 amount) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(ADMIN); - - //mint the link to the recipient - link.mint(recipient, amount); - - //change back to the original address - changePrank(originalAddr); - } - - function mintNative(address recipient, uint256 amount, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //mint the native to the recipient - native.mint(recipient, amount); - - //change back to the original address - changePrank(originalAddr); - } - - function issueUnwrappedNative(address recipient, uint256 quantity) public { - vm.deal(recipient, quantity); - } - - function ProcessFeeAsUser( - bytes32 poolId, - bytes memory payload, - address subscriber, - address tokenAddress, - uint256 wrappedNativeValue, - address sender - ) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //process the fee - feeManager.processFee{value: wrappedNativeValue}(poolId, payload, abi.encode(tokenAddress), subscriber); - - //change ProcessFeeAsUserback to the original address - changePrank(originalAddr); - } - - function processFee( - bytes32 poolId, - bytes memory payload, - address subscriber, - address feeAddress, - uint256 wrappedNativeValue - ) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(subscriber); - - //process the fee - feeManagerProxy.processFee{value: wrappedNativeValue}(poolId, payload, abi.encode(feeAddress)); - - //change back to the original address - changePrank(originalAddr); - } - - function processFee( - bytes32[] memory poolIds, - bytes[] memory payloads, - address subscriber, - address feeAddress, - uint256 wrappedNativeValue - ) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(subscriber); - - //process the fee - feeManagerProxy.processFeeBulk{value: wrappedNativeValue}(poolIds, payloads, abi.encode(feeAddress)); - - //change back to the original address - changePrank(originalAddr); - } - - function getPayload(bytes memory reportPayload) public pure returns (bytes memory) { - return abi.encode([DEFAULT_CONFIG_DIGEST, 0, 0], reportPayload, new bytes32[](1), new bytes32[](1), bytes32("")); - } - - function approveLink(address spender, uint256 quantity, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - link.approve(spender, quantity); - - //change back to the original address - changePrank(originalAddr); - } - - function approveNative(address spender, uint256 quantity, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - native.approve(spender, quantity); - - //change back to the original address - changePrank(originalAddr); - } - - function payLinkDeficit(bytes32 configDigest, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //approve the link to be transferred - feeManager.payLinkDeficit(configDigest); - - //change back to the original address - changePrank(originalAddr); - } - - function getLinkDeficit(bytes32 configDigest) public view returns (uint256) { - return feeManager.s_linkDeficit(configDigest); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol deleted file mode 100644 index 305125c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.general.t.sol +++ /dev/null @@ -1,299 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import "./BaseDestinationFeeManager.t.sol"; - -/** - * @title BaseDestinationFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the setup functionality of the feemanager - */ -contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { - function setUp() public override { - super.setUp(); - } - - function test_WithdrawERC20() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //get the balances to ne used for comparison - uint256 contractBalance = getLinkBalance(address(feeManager)); - uint256 adminBalance = getLinkBalance(ADMIN); - - //the amount to withdraw - uint256 withdrawAmount = contractBalance / 2; - - //withdraw some balance - withdraw(address(link), ADMIN, withdrawAmount, ADMIN); - - //check the balance has been reduced - uint256 newContractBalance = getLinkBalance(address(feeManager)); - uint256 newAdminBalance = getLinkBalance(ADMIN); - - //check the balance is greater than zero - assertGt(newContractBalance, 0); - //check the balance has been reduced by the correct amount - assertEq(newContractBalance, contractBalance - withdrawAmount); - //check the admin balance has increased by the correct amount - assertEq(newAdminBalance, adminBalance + withdrawAmount); - } - - function test_WithdrawUnwrappedNative() public { - //issue funds straight to the contract to bypass the lack of fallback function - issueUnwrappedNative(address(feeManager), DEFAULT_NATIVE_MINT_QUANTITY); - - //get the balances to be used for comparison - uint256 contractBalance = getNativeUnwrappedBalance(address(feeManager)); - uint256 adminBalance = getNativeUnwrappedBalance(ADMIN); - - //the amount to withdraw - uint256 withdrawAmount = contractBalance / 2; - - //withdraw some balance - withdraw(NATIVE_WITHDRAW_ADDRESS, ADMIN, withdrawAmount, ADMIN); - - //check the balance has been reduced - uint256 newContractBalance = getNativeUnwrappedBalance(address(feeManager)); - uint256 newAdminBalance = getNativeUnwrappedBalance(ADMIN); - - //check the balance is greater than zero - assertGt(newContractBalance, 0); - //check the balance has been reduced by the correct amount - assertEq(newContractBalance, contractBalance - withdrawAmount); - //check the admin balance has increased by the correct amount - assertEq(newAdminBalance, adminBalance + withdrawAmount); - } - - function test_WithdrawNonAdminAddr() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //should revert if not admin - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //withdraw some balance - withdraw(address(link), ADMIN, DEFAULT_LINK_MINT_QUANTITY, USER); - } - - function test_eventIsEmittedAfterSurchargeIsSet() public { - //native surcharge - uint64 nativeSurcharge = FEE_SCALAR / 5; - - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit NativeSurchargeUpdated(nativeSurcharge); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - } - - function test_subscriberDiscountEventIsEmittedOnUpdate() public { - //native surcharge - uint64 discount = FEE_SCALAR / 3; - - //an event should be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit SubscriberDiscountUpdated(USER, DEFAULT_FEED_1_V3, address(native), discount); - - //set the surcharge - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); - } - - function test_eventIsEmittedUponWithdraw() public { - //simulate a fee - mintLink(address(feeManager), DEFAULT_LINK_MINT_QUANTITY); - - //the amount to withdraw - uint192 withdrawAmount = 1; - - //expect an emit - vm.expectEmit(); - - //the event to be emitted - emit Withdraw(ADMIN, ADMIN, address(link), withdrawAmount); - - //withdraw some balance - withdraw(address(link), ADMIN, withdrawAmount, ADMIN); - } - - function test_linkAvailableForPaymentReturnsLinkBalance() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //check there's a balance - assertGt(getLinkBalance(address(feeManager)), 0); - - //check the link available for payment is the link balance - assertEq(feeManager.linkAvailableForPayment(), getLinkBalance(address(feeManager))); - } - - function test_payLinkDeficit() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //not enough funds in the reward pool should trigger an insufficient link event - vm.expectEmit(); - - IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); - contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - emit InsufficientLink(contractFees); - - //process the fee - processFee(contractFees[0].poolId, payload, USER, address(native), 0); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - } - - function test_payLinkDeficitTwice() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //not enough funds in the reward pool should trigger an insufficient link event - vm.expectEmit(); - - IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); - contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - //emit the event that is expected to be emitted - emit InsufficientLink(contractFees); - - //process the fee - processFee(contractFees[0].poolId, payload, USER, address(native), 0); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //paying again should revert with 0 - vm.expectRevert(ZERO_DEFICIT); - - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - } - - function test_payLinkDeficitPaysAllFeesProcessed() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 2, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - - //check the deficit has been increased twice - assertEq(getLinkDeficit(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE * 2); - - //double check the rewardManager balance is 0 - assertEq(getLinkBalance(address(rewardManager)), 0); - - //simulate a deposit of link to cover the deficit - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 2); - - vm.expectEmit(); - emit LinkDeficitCleared(DEFAULT_CONFIG_DIGEST, DEFAULT_REPORT_LINK_FEE * 2); - - //pay the deficit which will transfer link from the rewardManager to the rewardManager - payLinkDeficit(DEFAULT_CONFIG_DIGEST, ADMIN); - - //check the rewardManager received the link - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 2); - } - - function test_payLinkDeficitOnlyCallableByAdmin() public { - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - payLinkDeficit(DEFAULT_CONFIG_DIGEST, USER); - } - - function test_revertOnSettingAnAddressZeroVerifier() public { - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.addVerifier(address(0)); - } - - function test_onlyCallableByOwnerReverts() public { - address STRANGER = address(999); - changePrank(STRANGER); - vm.expectRevert(bytes("Only callable by owner")); - feeManager.addVerifier(address(0)); - } - - function test_addVerifierExistingAddress() public { - address dummyAddress = address(998); - feeManager.addVerifier(dummyAddress); - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.addVerifier(dummyAddress); - } - - function test_addVerifier() public { - address dummyAddress = address(998); - feeManager.addVerifier(dummyAddress); - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.addVerifier(dummyAddress); - - // check calls to setFeeRecipients it should not error unauthorized - changePrank(dummyAddress); - bytes32 dummyConfigDigest = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef; - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); - recipients[0] = Common.AddressAndWeight(address(991), 1e18); - feeManager.setFeeRecipients(dummyConfigDigest, recipients); - - // removing this verifier should result in unauthorized when calling setFeeRecipients - changePrank(ADMIN); - feeManager.removeVerifier(dummyAddress); - changePrank(dummyAddress); - vm.expectRevert(UNAUTHORIZED_ERROR); - feeManager.setFeeRecipients(dummyConfigDigest, recipients); - } - - function test_removeVerifierZeroAaddress() public { - address dummyAddress = address(0); - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.removeVerifier(dummyAddress); - } - - function test_removeVerifierNonExistentAddress() public { - address dummyAddress = address(991); - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.removeVerifier(dummyAddress); - } - - function test_setRewardManagerZeroAddress() public { - vm.expectRevert(INVALID_ADDRESS_ERROR); - feeManager.setRewardManager(address(0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol deleted file mode 100644 index ddd3ac5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.getFeeAndReward.t.sol +++ /dev/null @@ -1,720 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Common} from "../../../libraries/Common.sol"; -import "./BaseDestinationFeeManager.t.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager's getFeeAndReward - */ -contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { - function test_baseFeeIsAppliedForNative() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_baseFeeIsAppliedForLink() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_discountAIsNotAppliedWhenSetForOtherUsers() public { - //set the subscriber discount for another user - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), INVALID_ADDRESS); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_discountIsNotAppliedForInvalidTokenAddress() public { - //should revert with invalid address as it's not a configured token - vm.expectRevert(INVALID_ADDRESS_ERROR); - - //set the subscriber discount for another user - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, INVALID_ADDRESS, FEE_SCALAR / 2, ADMIN); - } - - function test_discountIsAppliedForLink() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_DiscountIsAppliedForNative() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE / 2); - } - - function test_discountIsNoLongerAppliedAfterRemoving() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE / 2); - - //remove the discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), 0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_surchargeIsApplied() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - } - - function test_surchargeIsNotAppliedForLinkFee() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_surchargeIsNoLongerAppliedAfterRemoving() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should be the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - - //remove the surcharge - setNativeSurcharge(0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the default - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_feeIsUpdatedAfterNewSurchargeIsApplied() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - - //change the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge - expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge); - } - - function test_surchargeIsAppliedForNativeFeeWithDiscount() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge quantity - uint256 expectedSurcharge = ((DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR); - - //calculate the expected discount quantity - uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge) / 2); - - //expected fee should the base fee offset by the surcharge and discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge - expectedDiscount); - } - - function test_emptyQuoteRevertsWithError() public { - //expect a revert - vm.expectRevert(INVALID_QUOTE_ERROR); - - //get the fee required by the feeManager - getFee(getV3Report(DEFAULT_FEED_1_V3), address(0), USER); - } - - function test_nativeSurcharge100Percent() public { - //set the surcharge - setNativeSurcharge(FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be twice the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2); - } - - function test_nativeSurcharge0Percent() public { - //set the surcharge - setNativeSurcharge(0, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_nativeSurchargeCannotExceed100Percent() public { - //should revert if surcharge is greater than 100% - vm.expectRevert(INVALID_SURCHARGE_ERROR); - - //set the surcharge above the max - setNativeSurcharge(FEE_SCALAR + 1, ADMIN); - } - - function test_discountIsAppliedWith100PercentSurcharge() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE; - - //fee should be twice the surcharge minus the discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE * 2 - expectedDiscount); - } - - function test_feeIsZeroWith100PercentDiscount() public { - //set the subscriber discount to 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_feeIsUpdatedAfterDiscountIsRemoved() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; - - //fee should be 50% of the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - - //remove the discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), 0, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_feeIsUpdatedAfterNewDiscountIsApplied() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity - uint256 expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 2; - - //fee should be 50% of the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - - //change the discount to 25% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); - - //get the fee required by the feeManager - fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //expected discount is now 25% - expectedDiscount = DEFAULT_REPORT_NATIVE_FEE / 4; - - //fee should be the base fee minus the expected discount - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - } - - function test_setDiscountOver100Percent() public { - //should revert with invalid discount - vm.expectRevert(INVALID_DISCOUNT_ERROR); - - //set the subscriber discount to over 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR + 1, ADMIN); - } - - function test_surchargeIsNotAppliedWith100PercentDiscount() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 5; - - //set the subscriber discount to 100% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, ADMIN); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_nonAdminUserCanNotSetDiscount() public { - //should revert with unauthorized - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR, USER); - } - - function test_surchargeFeeRoundsUpWhenUneven() public { - //native surcharge - uint256 nativeSurcharge = FEE_SCALAR / 3; - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected surcharge quantity - uint256 expectedSurcharge = (DEFAULT_REPORT_NATIVE_FEE * nativeSurcharge) / FEE_SCALAR; - - //expected fee should the base fee offset by the expected surcharge - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE + expectedSurcharge + 1); - } - - function test_discountFeeRoundsDownWhenUneven() public { - //native surcharge - uint256 discount = FEE_SCALAR / 3; - - //set the subscriber discount to 33.333% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), discount, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected quantity - uint256 expectedDiscount = ((DEFAULT_REPORT_NATIVE_FEE * discount) / FEE_SCALAR); - - //expected fee should the base fee offset by the expected surcharge - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscount); - } - - function test_reportWithNoExpiryOrFeeReturnsZero() public view { - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV1Report(DEFAULT_FEED_1_V1), getNativeQuote(), USER); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() public { - //set the subscriber and native discounts - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager for both tokens - Common.Asset memory linkFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - Common.Asset memory nativeFee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //calculate the expected discount quantity for each token - uint256 expectedDiscountLink = (DEFAULT_REPORT_LINK_FEE * FEE_SCALAR) / 4 / FEE_SCALAR; - uint256 expectedDiscountNative = (DEFAULT_REPORT_NATIVE_FEE * FEE_SCALAR) / 2 / FEE_SCALAR; - - //check the fee calculation for each token - assertEq(linkFee.amount, DEFAULT_REPORT_LINK_FEE - expectedDiscountLink); - assertEq(nativeFee.amount, DEFAULT_REPORT_NATIVE_FEE - expectedDiscountNative); - } - - function test_discountIsNotAppliedToOtherFeeds() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_2_V3), getNativeQuote(), USER); - - //fee should be the base fee - assertEq(fee.amount, DEFAULT_REPORT_NATIVE_FEE); - } - - function test_noFeeIsAppliedWhenReportHasZeroFee() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), - getNativeQuote(), - USER - ); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, uint32(block.timestamp), 0, 0), - getNativeQuote(), - USER - ); - - //fee should be zero - assertEq(fee.amount, 0); - } - - function test_nativeSurchargeEventIsEmittedOnUpdate() public { - //native surcharge - uint64 nativeSurcharge = FEE_SCALAR / 3; - - //an event should be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit NativeSurchargeUpdated(nativeSurcharge); - - //set the surcharge - setNativeSurcharge(nativeSurcharge, ADMIN); - } - - function test_getBaseRewardWithLinkQuote() public view { - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithLinkQuoteAndLinkDiscount() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the discounted base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_getRewardWithNativeQuote() public view { - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithNativeQuoteAndSurcharge() public { - //set the native surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link regardless of the surcharge - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_getRewardWithLinkDiscount() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal the discounted base fee - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE / 2); - } - - function test_getLinkFeeIsRoundedUp() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //the reward should equal .66% + 1 of the base fee due to a 33% discount rounded up - assertEq(fee.amount, (DEFAULT_REPORT_LINK_FEE * 2) / 3 + 1); - } - - function test_getLinkRewardIsSameAsFee() public { - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //check the reward is in link - assertEq(fee.assetAddress, address(link)); - - //the reward should equal .66% of the base fee due to a 33% discount rounded down - assertEq(reward.amount, fee.amount); - } - - function test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() public { - //set the native surcharge - setNativeSurcharge(FEE_SCALAR / 2, ADMIN); - - //set the link discount - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 3, ADMIN); - - //get the fee required by the feeManager - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //the reward should equal the base fee in link regardless of the surcharge - assertEq(reward.amount, DEFAULT_REPORT_LINK_FEE); - } - - function test_testRevertIfReportHasExpired() public { - //expect a revert - vm.expectRevert(EXPIRED_REPORT_ERROR); - - //get the fee required by the feeManager - getFee( - getV3ReportWithCustomExpiryAndFee( - DEFAULT_FEED_1_V3, - block.timestamp - 1, - DEFAULT_REPORT_LINK_FEE, - DEFAULT_REPORT_NATIVE_FEE - ), - getNativeQuote(), - USER - ); - } - - function test_discountIsReturnedForLink() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 2, ADMIN); - - //get the fee applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_DiscountIsReturnedForNative() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_DiscountIsReturnedForNativeWithSurcharge() public { - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //set the surcharge - setNativeSurcharge(FEE_SCALAR / 5, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_GlobalDiscountWithNative() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_GlobalDiscountWithLink() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_GlobalDiscountWithNativeAndLink() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); - setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - } - - function test_GlobalDiscountIsOverridenByIndividualDiscountNative() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 4, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 4); - } - - function test_GlobalDiscountIsOverridenByIndividualDiscountLink() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(link), FEE_SCALAR / 4, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 4); - } - - function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroLink() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(link), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - - //set the global discount to zero - setSubscriberGlobalDiscount(USER, address(link), 0, ADMIN); - - //get the discount applied - discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getLinkQuote(), USER); - - //fee should be zero - assertEq(discount, 0); - } - - function test_GlobalDiscountIsUpdatedAfterBeingSetToZeroNative() public { - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, ADMIN); - - //get the discount applied - uint256 discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be half the default - assertEq(discount, FEE_SCALAR / 2); - - //set the global discount to zero - setSubscriberGlobalDiscount(USER, address(native), 0, ADMIN); - - //get the discount applied - discount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - //fee should be zero - assertEq(discount, 0); - } - - function test_GlobalDiscountCantBeSetToMoreThanMaximum() public { - //should revert with invalid discount - vm.expectRevert(INVALID_DISCOUNT_ERROR); - - //set the global discount to 101% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR + 1, ADMIN); - } - - function test_onlyOwnerCanSetGlobalDiscount() public { - //should revert with unauthorized - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //set the global discount to 50% - setSubscriberGlobalDiscount(USER, address(native), FEE_SCALAR / 2, USER); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol deleted file mode 100644 index 0880352..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFee.t.sol +++ /dev/null @@ -1,492 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Common} from "../../../libraries/Common.sol"; -import "./BaseDestinationFeeManager.t.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager processFee - */ -contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { - function setUp() public override { - super.setUp(); - } - - function test_nonAdminProxyUserCannotProcessFee() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //should revert as the user is not the owner - vm.expectRevert(UNAUTHORIZED_ERROR); - - //process the fee - ProcessFeeAsUser(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0, USER); - } - - function test_processFeeAsProxy() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_processFeeIfSubscriberIsSelf() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert due to the feeManager being the subscriber - vm.expectRevert(INVALID_ADDRESS_ERROR); - - //process the fee will fail due to assertion - processFee(DEFAULT_CONFIG_DIGEST, payload, address(feeManager), address(native), 0); - } - - function test_processFeeWithWithEmptyQuotePayload() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link by default - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); - } - - function test_processFeeWithWithZeroQuotePayload() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as the quote is invalid - vm.expectRevert(INVALID_QUOTE_ERROR); - - //processing the fee will transfer the link by default - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, INVALID_ADDRESS, 0); - } - - function test_processFeeWithWithCorruptQuotePayload() public { - //get the default payload - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV3Report(DEFAULT_FEED_1_V3), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - //expect an evm revert as the quote is corrupt - vm.expectRevert(); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - } - - function test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() public { - //get the default payload - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); - } - - function test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() public { - //get the default payload - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - } - - function test_processFeeNative() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeEmitsEventIfNotEnoughLink() public { - //simulate a deposit of half the link required for the fee - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE / 2); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //expect an emit as there's not enough link - vm.expectEmit(); - - IDestinationRewardManager.FeePayment[] memory contractFees = new IDestinationRewardManager.FeePayment[](1); - contractFees[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - //emit the event that is expected to be emitted - emit InsufficientLink(contractFees); - - //processing the fee will transfer the native from the user to the feeManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check no link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), 0); - assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE / 2); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithUnwrappedNative() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //only the proxy or admin can call processFee, they will pass in the native value on the users behalf - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE); - - //check the native has been transferred and converted to wrapped native - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeUnwrappedBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithUnwrappedNativeShortFunds() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as not enough funds - vm.expectRevert(INVALID_DEPOSIT_ERROR); - - //only the proxy or admin can call processFee, they will pass in the native value on the users behalf - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), DEFAULT_REPORT_NATIVE_FEE - 1); - } - - function test_processFeeWithUnwrappedNativeLinkAddress() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //expect a revert as not enough funds - vm.expectRevert(INSUFFICIENT_ALLOWANCE_ERROR); - - //the change will be returned and the user will attempted to be billed in LINK - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE - 1); - } - - function test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() public { - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, PROXY); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. - processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(link), DEFAULT_REPORT_NATIVE_FEE); - - //check the native unwrapped is no longer in the account - assertEq(getNativeBalance(address(feeManager)), 0); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //native should not be deducted - assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processFeeWithUnwrappedNativeWithExcessiveFee() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee from the proxy to test whether the funds are returned to the subscriber. In reality, the funds would be returned to the caller of the proxy. - processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(native), DEFAULT_REPORT_NATIVE_FEE * 2); - - //check the native has been transferred and converted to wrapped native - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - assertEq(getNativeUnwrappedBalance(address(feeManager)), 0); - - //check the link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the feeManager has had the link deducted, the remaining balance should be 0 - assertEq(getLinkBalance(address(feeManager)), 0); - - //check the subscriber has had the native deducted - assertEq(getNativeUnwrappedBalance(PROXY), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeUsesCorrectDigest() public { - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - - //check funds have been paid to the reward manager - assertEq(rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST), DEFAULT_REPORT_LINK_FEE); - } - - function test_V1PayloadVerifies() public { - //replicate a default payload - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV2Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); - } - - function test_V2PayloadVerifies() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_V2PayloadWithoutQuoteFails() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), 0); - } - - function test_V2PayloadWithoutZeroFee() public { - //get the default payload - bytes memory payload = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - - //expect a revert as the quote is invalid - vm.expectRevert(); - - //processing the fee will transfer the link from the user to the rewardManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - } - - function test_processFeeWithInvalidReportVersionFailsToDecode() public { - bytes memory data = abi.encode(0x0000100000000000000000000000000000000000000000000000000000000000); - - //get the default payload - bytes memory payload = getPayload(data); - - //serialization will fail as there is no report to decode - vm.expectRevert(); - - //processing the fee will not withdraw anything as there is no fee to collect - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) - ); - - //call processFee should not revert as the fee is 0 - processFee(DEFAULT_CONFIG_DIGEST, payload, PROXY, address(native), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, DEFAULT_REPORT_LINK_FEE, 0) - ); - - //approve the link to be transferred from the from the subscriber to the rewardManager - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - - //processing the fee will transfer the link to the rewardManager from the user - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - - //check the link has been transferred - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - //check the user has had the link fee deducted - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - } - - function test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //processing the fee will transfer the native from the user to the feeManager - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - - //check the native has been transferred - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE); - - //check no link has been transferred to the rewardManager - assertEq(getLinkBalance(address(rewardManager)), 0); - - //check the feeManager has had no link deducted - assertEq(getLinkBalance(address(feeManager)), DEFAULT_REPORT_LINK_FEE); - - //check the subscriber has had the native deducted - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - } - - function test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //call processFee should not revert as the fee is 0 - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), 0); - } - - function test_processFeeWithZeroNativeNonZeroLinkReturnsChange() public { - //get the default payload - bytes memory payload = getPayload( - getV3ReportWithCustomExpiryAndFee(DEFAULT_FEED_1_V3, block.timestamp, 0, DEFAULT_REPORT_NATIVE_FEE) - ); - - //call processFee should not revert as the fee is 0 - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(link), DEFAULT_REPORT_NATIVE_FEE); - - //check the change has been returned - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_V1PayloadVerifiesAndReturnsChange() public { - //emulate a V1 payload with no quote - bytes memory payload = getPayload(getV1Report(DEFAULT_FEED_1_V1)); - - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(0), DEFAULT_REPORT_NATIVE_FEE); - - //Fee manager should not contain any native - assertEq(address(feeManager).balance, 0); - assertEq(getNativeBalance(address(feeManager)), 0); - - //check the unused native passed in is returned - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processFeeWithDiscountEmitsEvent() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //set the subscriber discount to 50% - setSubscriberDiscount(USER, DEFAULT_FEED_1_V3, address(native), FEE_SCALAR / 2, ADMIN); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE / 2, USER); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - Common.Asset memory fee = getFee(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - Common.Asset memory reward = getReward(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - uint256 appliedDiscount = getAppliedDiscount(getV3Report(DEFAULT_FEED_1_V3), getNativeQuote(), USER); - - vm.expectEmit(); - - emit DiscountApplied(DEFAULT_CONFIG_DIGEST, USER, fee, reward, appliedDiscount); - - //call processFee should not revert as the fee is 0 - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - } - - function test_processFeeWithNoDiscountDoesNotEmitEvent() public { - //simulate a deposit of link for the conversion pool - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE); - - //approve the native to be transferred from the user - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - - //get the default payload - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - //call processFee should not revert as the fee is 0 - processFee(DEFAULT_CONFIG_DIGEST, payload, USER, address(native), 0); - - //no logs should have been emitted - assertEq(vm.getRecordedLogs().length, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol deleted file mode 100644 index a50441b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/fee-manager/DestinationFeeManager.processFeeBulk.t.sol +++ /dev/null @@ -1,310 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import "./BaseDestinationFeeManager.t.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -/** - * @title BaseFeeManagerTest - * @author Michael Fletcher - * @notice This contract will test the functionality of the feeManager processFee - */ -contract DestinationFeeManagerProcessFeeTest is BaseDestinationFeeManagerTest { - uint256 internal constant NUMBER_OF_REPORTS = 5; - - function setUp() public override { - super.setUp(); - } - - function test_processMultipleLinkReports() public { - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); - - processFee(poolIds, payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); - - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 0); - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - - //the subscriber (user) should receive funds back and not the proxy, although when live the proxy will forward the funds sent and not cover it seen here - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processMultipleWrappedNativeReports() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS, USER); - - processFee(poolIds, payloads, USER, address(native), 0); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 1); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - } - - function test_processMultipleUnwrappedNativeReports() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS); - } - - function test_processV1V2V3Reports() public { - mintLink(address(feeManager), 1); - - bytes memory payloadV1 = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes memory linkPayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - bytes memory linkPayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = payloadV1; - payloads[1] = linkPayloadV2; - payloads[2] = linkPayloadV2; - payloads[3] = linkPayloadV3; - payloads[4] = linkPayloadV3; - - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * 4, USER); - - bytes32[] memory poolIds = new bytes32[](5); - for (uint256 i = 0; i < 5; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - processFee(poolIds, payloads, USER, address(link), 0); - - assertEq(getNativeBalance(address(feeManager)), 0); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - 0); - } - - function test_processV1V2V3ReportsWithUnwrapped() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * 4 + 1); - - bytes memory payloadV1 = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes memory nativePayloadV2 = getPayload(getV2Report(DEFAULT_FEED_1_V2)); - bytes memory nativePayloadV3 = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = payloadV1; - payloads[1] = nativePayloadV2; - payloads[2] = nativePayloadV2; - payloads[3] = nativePayloadV3; - payloads[4] = nativePayloadV3; - - bytes32[] memory poolIds = new bytes32[](5); - for (uint256 i = 0; i < 5; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 4); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 4); - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * 4); - assertEq(getLinkBalance(address(feeManager)), 1); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 4); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_processMultipleV1Reports() public { - bytes memory payload = abi.encode( - [DEFAULT_CONFIG_DIGEST, 0, 0], - getV1Report(DEFAULT_FEED_1_V1), - new bytes32[](1), - new bytes32[](1), - bytes32("") - ); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * 5); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - } - - function test_eventIsEmittedIfNotEnoughLink() public { - bytes memory nativePayload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](5); - payloads[0] = nativePayload; - payloads[1] = nativePayload; - payloads[2] = nativePayload; - payloads[3] = nativePayload; - payloads[4] = nativePayload; - - approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * 5, USER); - - IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](5); - payments[0] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[1] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[2] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[3] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - payments[4] = IDestinationRewardManager.FeePayment(DEFAULT_CONFIG_DIGEST, uint192(DEFAULT_REPORT_LINK_FEE)); - - vm.expectEmit(); - - bytes32[] memory poolIds = new bytes32[](5); - for (uint256 i = 0; i < 5; ++i) { - poolIds[i] = payments[i].poolId; - } - - emit InsufficientLink(payments); - - processFee(poolIds, payloads, USER, address(native), 0); - - assertEq(getNativeBalance(address(feeManager)), DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(getNativeBalance(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY); - } - - function test_processPoolIdsPassedMismatched() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - // poolIds passed are different that number of reports in payload - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS - 1); - for (uint256 i = 0; i < NUMBER_OF_REPORTS - 1; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - vm.expectRevert(POOLID_MISMATCH_ERROR); - processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); - } - - function test_poolIdsCannotBeZeroAddress() public { - mintLink(address(feeManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS + 1); - - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - - poolIds[2] = 0x000; - vm.expectRevert(INVALID_ADDRESS_ERROR); - processFee(poolIds, payloads, USER, address(native), DEFAULT_REPORT_NATIVE_FEE * NUMBER_OF_REPORTS * 2); - } - - function test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() public { - bytes memory payload = getPayload(getV3Report(DEFAULT_FEED_1_V3)); - - bytes[] memory payloads = new bytes[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - payloads[i] = payload; - } - - bytes32[] memory poolIds = new bytes32[](NUMBER_OF_REPORTS); - for (uint256 i = 0; i < NUMBER_OF_REPORTS - 1; ++i) { - poolIds[i] = DEFAULT_CONFIG_DIGEST; - } - poolIds[NUMBER_OF_REPORTS - 1] = DEFAULT_CONFIG_DIGEST2; - - approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS, USER); - - // Checking no rewards yet for each pool - for (uint256 i = 0; i < NUMBER_OF_REPORTS; ++i) { - bytes32 p_id = poolIds[i]; - uint256 poolDeficit = rewardManager.s_totalRewardRecipientFees(p_id); - assertEq(poolDeficit, 0); - } - - processFee(poolIds, payloads, USER, address(link), DEFAULT_NATIVE_MINT_QUANTITY); - - assertEq(getLinkBalance(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - assertEq(getLinkBalance(address(feeManager)), 0); - assertEq(getLinkBalance(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBER_OF_REPORTS); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY); - assertEq(PROXY.balance, DEFAULT_NATIVE_MINT_QUANTITY); - - // Checking each pool got the correct rewards - uint256 expectedRewards = DEFAULT_REPORT_LINK_FEE * (NUMBER_OF_REPORTS - 1); - uint256 poolRewards = rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST); - assertEq(poolRewards, expectedRewards); - - expectedRewards = DEFAULT_REPORT_LINK_FEE; - poolRewards = rewardManager.s_totalRewardRecipientFees(DEFAULT_CONFIG_DIGEST2); - assertEq(poolRewards, expectedRewards); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol deleted file mode 100644 index 7dde878..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/mocks/DestinationFeeManagerProxy.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IDestinationVerifierFeeManager} from "../../interfaces/IDestinationVerifierFeeManager.sol"; - -contract DestinationFeeManagerProxy { - IDestinationVerifierFeeManager internal s_feeManager; - - function processFee(bytes32 poolId, bytes calldata payload, bytes calldata parameterPayload) public payable { - s_feeManager.processFee{value: msg.value}(poolId, payload, parameterPayload, msg.sender); - } - - function processFeeBulk( - bytes32[] memory poolIds, - bytes[] calldata payloads, - bytes calldata parameterPayload - ) public payable { - s_feeManager.processFeeBulk{value: msg.value}(poolIds, payloads, parameterPayload, msg.sender); - } - - function setDestinationFeeManager(address feeManager) public { - s_feeManager = IDestinationVerifierFeeManager(feeManager); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol deleted file mode 100644 index 7cafb16..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/BaseDestinationRewardManager.t.sol +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -/** - * @title DestinationRewardManagerTest - * @author Michael Fletcher - * @notice Base class for all reward manager tests - * @dev This contract is intended to be inherited from and not used directly. It contains functionality to setup a primary and secondary pool - */ -contract BaseDestinationRewardManagerTest is Test { - //contracts - ERC20Mock internal asset; - ERC20Mock internal unsupported; - DestinationRewardManager internal rewardManager; - - //default address for unregistered recipient - address internal constant INVALID_ADDRESS = address(0); - //contract owner - address internal constant ADMIN = address(uint160(uint256(keccak256("ADMIN")))); - //address to represent feeManager contract - address internal constant FEE_MANAGER = address(uint160(uint256(keccak256("FEE_MANAGER")))); - //address to represent another feeManager - address internal constant FEE_MANAGER_2 = address(uint160(uint256(keccak256("FEE_MANAGER_2")))); - //a general user - address internal constant USER = address(uint160(uint256(keccak256("USER")))); - - //default recipients configured in reward manager - address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); - address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); - address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); - address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); - address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); - address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); - address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); - - //additional recipients not in the reward manager - address internal constant DEFAULT_RECIPIENT_8 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_8")))); - address internal constant DEFAULT_RECIPIENT_9 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_9")))); - - //two pools should be enough to test all edge cases - bytes32 internal constant PRIMARY_POOL_ID = keccak256("primary_pool"); - bytes32 internal constant SECONDARY_POOL_ID = keccak256("secondary_pool"); - bytes32 internal constant INVALID_POOL_ID = keccak256("invalid_pool"); - bytes32 internal constant ZERO_POOL_ID = bytes32(0); - - //convenience arrays of all pool combinations used for testing - bytes32[] internal PRIMARY_POOL_ARRAY = [PRIMARY_POOL_ID]; - bytes32[] internal SECONDARY_POOL_ARRAY = [SECONDARY_POOL_ID]; - bytes32[] internal ALL_POOLS = [PRIMARY_POOL_ID, SECONDARY_POOL_ID]; - - //erc20 config - uint256 internal constant DEFAULT_MINT_QUANTITY = 100 ether; - - //reward scalar (this should match the const in the contract) - uint64 internal constant POOL_SCALAR = 1e18; - uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; - uint64 internal constant FIFTY_PERCENT = POOL_SCALAR / 2; - uint64 internal constant TEN_PERCENT = POOL_SCALAR / 10; - - //the selector for each error - bytes4 internal immutable UNAUTHORIZED_ERROR_SELECTOR = DestinationRewardManager.Unauthorized.selector; - bytes4 internal immutable INVALID_ADDRESS_ERROR_SELECTOR = DestinationRewardManager.InvalidAddress.selector; - bytes4 internal immutable INVALID_WEIGHT_ERROR_SELECTOR = DestinationRewardManager.InvalidWeights.selector; - bytes4 internal immutable INVALID_POOL_ID_ERROR_SELECTOR = DestinationRewardManager.InvalidPoolId.selector; - bytes internal constant ONLY_CALLABLE_BY_OWNER_ERROR = "Only callable by owner"; - bytes4 internal immutable INVALID_POOL_LENGTH_SELECTOR = DestinationRewardManager.InvalidPoolLength.selector; - - // Events emitted within the reward manager - event RewardRecipientsUpdated(bytes32 indexed poolId, Common.AddressAndWeight[] newRewardRecipients); - event RewardsClaimed(bytes32 indexed poolId, address indexed recipient, uint192 quantity); - event FeeManagerUpdated(address newProxyAddress); - event FeePaid(IDestinationRewardManager.FeePayment[] payments, address payee); - - function setUp() public virtual { - //change to admin user - vm.startPrank(ADMIN); - - //init required contracts - _initializeERC20Contracts(); - _initializeRewardManager(); - } - - function _initializeERC20Contracts() internal { - //create the contracts - asset = new ERC20Mock("ASSET", "AST", ADMIN, 0); - unsupported = new ERC20Mock("UNSUPPORTED", "UNS", ADMIN, 0); - - //mint some tokens to the admin - asset.mint(ADMIN, DEFAULT_MINT_QUANTITY); - unsupported.mint(ADMIN, DEFAULT_MINT_QUANTITY); - - //mint some tokens to the user - asset.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); - unsupported.mint(FEE_MANAGER, DEFAULT_MINT_QUANTITY); - } - - function _initializeRewardManager() internal { - //create the contract - rewardManager = new DestinationRewardManager(address(asset)); - - rewardManager.addFeeManager(FEE_MANAGER); - } - - function createPrimaryPool() public { - rewardManager.setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients()); - } - - function createSecondaryPool() public { - rewardManager.setRewardRecipients(SECONDARY_POOL_ID, getSecondaryRecipients()); - } - - //override this to test variations of different recipients. changing this function will require existing tests to be updated as constants are hardcoded to be explicit - function getPrimaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights. 2500 = 25% of pool - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); - - return recipients; - } - - function getPrimaryRecipientAddresses() public pure returns (address[] memory) { - //array of recipients - address[] memory recipients = new address[](4); - - recipients[0] = DEFAULT_RECIPIENT_1; - recipients[1] = DEFAULT_RECIPIENT_2; - recipients[2] = DEFAULT_RECIPIENT_3; - recipients[3] = DEFAULT_RECIPIENT_4; - - return recipients; - } - - //override this to test variations of different recipients. - function getSecondaryRecipients() public virtual returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights. 2500 = 25% of pool - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); - - return recipients; - } - - function getSecondaryRecipientAddresses() public pure returns (address[] memory) { - //array of recipients - address[] memory recipients = new address[](4); - - recipients[0] = DEFAULT_RECIPIENT_1; - recipients[1] = DEFAULT_RECIPIENT_5; - recipients[2] = DEFAULT_RECIPIENT_6; - recipients[3] = DEFAULT_RECIPIENT_7; - - return recipients; - } - - function addFundsToPool(bytes32 poolId, Common.Asset memory amount, address sender) public { - IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); - payments[0] = IDestinationRewardManager.FeePayment(poolId, uint192(amount.amount)); - - addFundsToPool(payments, sender); - } - - function addFundsToPool(IDestinationRewardManager.FeePayment[] memory payments, address sender) public { - //record the current address and switch to the sender - address originalAddr = msg.sender; - changePrank(sender); - - uint256 totalPayment; - for (uint256 i; i < payments.length; ++i) { - totalPayment += payments[i].amount; - } - - //approve the amount being paid into the pool - ERC20Mock(address(asset)).approve(address(rewardManager), totalPayment); - - //this represents the verifier adding some funds to the pool - rewardManager.onFeePaid(payments, sender); - - //change back to the original address - changePrank(originalAddr); - } - - function getAsset(uint256 quantity) public view returns (Common.Asset memory) { - return Common.Asset(address(asset), quantity); - } - - function getAssetBalance(address addr) public view returns (uint256) { - return asset.balanceOf(addr); - } - - function claimRewards(bytes32[] memory poolIds, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //claim the rewards - rewardManager.claimRewards(poolIds); - - //change back to the original address - changePrank(originalAddr); - } - - function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.payRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - function setRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.setRewardRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - function setFeeManager(address feeManager, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //update the proxy - rewardManager.addFeeManager(feeManager); - - //change back to the original address - changePrank(originalAddr); - } - - function updateRewardRecipients(bytes32 poolId, Common.AddressAndWeight[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.updateRewardRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol deleted file mode 100644 index c0a67d0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.claim.t.sol +++ /dev/null @@ -1,790 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title DestinationRewardManagerClaimTest - * @author Michael Fletcher - * @notice This contract will test the claim functionality of the RewardManager contract. - */ -contract DestinationRewardManagerClaimTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipients() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } - - function test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() public { - //add funds to a different pool to ensure they're not claimed - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create an array containing duplicate poolIds - bytes32[] memory poolIds = new bytes32[](2); - poolIds[0] = PRIMARY_POOL_ID; - poolIds[1] = PRIMARY_POOL_ID; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(poolIds, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the pool should still have the remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimSingleRecipient() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); - } - - function test_claimMultipleRecipients() public { - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - (expectedRecipientAmount * 2)); - } - - function test_claimUnregisteredRecipient() public { - //claim the rewards for a recipient who isn't in this pool - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //check the recipients didn't receive any fees from this pool - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimUnevenAmountRoundsDown() public { - //adding 1 to the pool should leave 1 wei worth of dust, which the contract doesn't handle due to it being economically infeasible - addFundsToPool(PRIMARY_POOL_ID, getAsset(1), FEE_MANAGER); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //check the rewardManager has the remaining quantity equals 1 wei - assertEq(getAssetBalance(address(rewardManager)), 1); - } - - function test_claimUnregisteredPoolId() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the recipients balance is still 0 as there's no pool to receive fees from - assertEq(getAssetBalance(recipient.addr), 0); - - //check the rewardManager has the full amount - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_singleRecipientClaimMultipleDeposits() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT - expectedRecipientAmount); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); - - //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); - } - - function test_recipientsClaimMultipleDeposits() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should be 0 as all of the funds have been claimed - assertEq(getAssetBalance(address(rewardManager)), 0); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //expected recipient amount is 1/4 of the pool deposit - expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should again be 0 as all of the funds have been claimed - assertEq(getAssetBalance(address(rewardManager)), 0); - } - - function test_eventIsEmittedUponClaim() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardsClaimed(PRIMARY_POOL_ID, recipient.addr, uint192(POOL_DEPOSIT_AMOUNT / 4)); - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - } - - function test_eventIsNotEmittedUponUnsuccessfulClaim() public { - //record logs to check no events were emitted - vm.recordLogs(); - - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //no logs should have been emitted - assertEq(vm.getRecordedLogs().length, 0); - } -} - -contract DestinationRewardManagerRecipientClaimMultiplePoolsTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a two pools - createPrimaryPool(); - createSecondaryPool(); - - //add funds to each of the pools to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipientsSinglePool() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //check the pool balance is still equal to DEPOSIT_AMOUNT as the test only claims for one of the pools - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimMultipleRecipientsSinglePool() public { - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - (expectedRecipientAmount * 2)); - } - - function test_claimMultipleRecipientsMultiplePools() public { - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received. The first recipient is shared across both pools so should receive 1/4 of each pool - assertEq(getAssetBalance(getPrimaryRecipients()[0].addr), expectedRecipientAmount * 2); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), expectedRecipientAmount); - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimAllRecipientsMultiplePools() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i = 1; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //claim funds for each recipient within the pool - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory secondaryRecipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, secondaryRecipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(secondaryRecipient.addr), expectedRecipientAmount); - } - - //special case to handle the first recipient of each pool as they're the same address - Common.AddressAndWeight memory commonRecipient = getPrimaryRecipients()[0]; - - //claim the individual rewards for each pool - claimRewards(PRIMARY_POOL_ARRAY, commonRecipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, commonRecipient.addr); - - //check the balance matches the ratio the recipient should have received, which is 1/4 of each deposit for each pool - assertEq(getAssetBalance(commonRecipient.addr), expectedRecipientAmount * 2); - } - - function test_claimSingleUniqueRecipient() public { - //the first recipient of the secondary pool is in both pools, so take the second recipient which is unique - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[1]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount - uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; - - //the recipient should have received 1/4 of the deposit amount - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); - } - - function test_claimSingleRecipientMultiplePools() public { - //the first recipient of the secondary pool is in both pools - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount for each pool - uint256 recipientExpectedAmount = (POOL_DEPOSIT_AMOUNT / 4) * 2; - - //this recipient belongs in both pools so should have received 1/4 of each - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - recipientExpectedAmount); - } - - function test_claimUnregisteredRecipient() public { - //claim the individual rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[1].addr); - claimRewards(SECONDARY_POOL_ARRAY, getPrimaryRecipients()[1].addr); - - //check the recipients didn't receive any fees from this pool - assertEq(getAssetBalance(getSecondaryRecipients()[1].addr), 0); - assertEq(getAssetBalance(getPrimaryRecipients()[1].addr), 0); - - //check the rewardManager has the remaining quantity - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2); - } - - function test_claimUnevenAmountRoundsDown() public { - //adding an uneven amount of dust to each pool, this should round down to the nearest whole number with 4 remaining in the contract - addFundsToPool(PRIMARY_POOL_ID, getAsset(3), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(1), FEE_MANAGER); - - //the recipient should have received 1/4 of the deposit amount for each pool - uint256 recipientExpectedAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - } - - //special case to handle the first recipient of each pool as they're the same address - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), recipientExpectedAmount * 2); - - //claim funds for each recipient of the secondary pool except the first - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), recipientExpectedAmount); - } - - //contract should have 4 remaining - assertEq(getAssetBalance(address(rewardManager)), 4); - } - - function test_singleRecipientClaimMultipleDeposits() public { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[0]; - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is 3/4 of the initial deposit plus the deposit from the second pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 2 - expectedRecipientAmount); - - //add funds to the pool to be split among the recipients - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the individual rewards for this recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received 1/4 of the next deposit amount - expectedRecipientAmount += POOL_DEPOSIT_AMOUNT / 4; - - //check the recipients balance matches the ratio the recipient should have received, which is 1/4 of each deposit - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - - //check the rewardManager has the remaining quantity, which is now 3/4 of both deposits - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT * 3 - expectedRecipientAmount); - } - - function test_recipientsClaimMultipleDeposits() public { - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim funds for each recipient within the pool - for (uint256 i; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //the reward manager balance should contain only the funds of the secondary pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - - //add funds to the pool to be split among the recipients - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //special case to handle the first recipient of each pool as they're the same address - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount * 2); - - //claim funds for each recipient within the pool except the first - for (uint256 i = 1; i < getSecondaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getSecondaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(SECONDARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount * 2); - } - - //the reward manager balance should again be the balance of the secondary pool as the primary pool has been emptied twice - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_claimEmptyPoolWhenSecondPoolContainsFunds() public { - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //claim all rewards for each recipient in the primary pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //claim all the rewards again for the first recipient as that address is a member of both pools - claimRewards(PRIMARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //check the balance - assertEq(getAssetBalance(getSecondaryRecipients()[0].addr), expectedRecipientAmount); - } - - function test_getRewardsAvailableToRecipientInBothPools() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[0].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], SECONDARY_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInSinglePool() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[1].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInNoPools() public view { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, 0, type(uint256).max); - - //check the recipient is in neither pool - assertEq(poolIds[0], ZERO_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() public { - //get index 0 as this recipient is in both default pools - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds( - getPrimaryRecipients()[0].addr, - 0, - type(uint256).max - ); - - //check the recipient is in both pools - assertEq(poolIds[0], PRIMARY_POOL_ID); - assertEq(poolIds[1], SECONDARY_POOL_ID); - - //claim the rewards for each pool - claimRewards(PRIMARY_POOL_ARRAY, getPrimaryRecipients()[0].addr); - claimRewards(SECONDARY_POOL_ARRAY, getSecondaryRecipients()[0].addr); - - //get the available pools again - poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, type(uint256).max); - - //user should not be in any pool - assertEq(poolIds[0], ZERO_POOL_ID); - assertEq(poolIds[1], ZERO_POOL_ID); - } - - function test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() public { - vm.expectRevert(INVALID_POOL_LENGTH_SELECTOR); - - rewardManager.getAvailableRewardPoolIds(FEE_MANAGER, type(uint256).max, 0); - } - - function test_getAvailableRewardsCursorAndTotalPoolsEqual() public { - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 2, 2); - - assertEq(poolIds.length, 0); - } - - function test_getAvailableRewardsCursorSingleResult() public { - bytes32[] memory poolIds = rewardManager.getAvailableRewardPoolIds(getPrimaryRecipients()[0].addr, 0, 1); - - assertEq(poolIds[0], PRIMARY_POOL_ID); - } -} - -contract DestinationRewardManagerRecipientClaimDifferentWeightsTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with uneven weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 8); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 6); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 4); - - return recipients; - } - - function test_allRecipientsClaimingReceiveExpectedAmount() public { - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } -} - -contract DestinationRewardManagerRecipientClaimUnevenWeightTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - } - - function getPrimaryRecipients() public virtual override returns (Common.AddressAndWeight[] memory) { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - - uint64 oneThird = POOL_SCALAR / 3; - - //init each recipient with even weights. - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, oneThird); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 2 * oneThird + 1); - - return recipients; - } - - function test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() public { - //add a smaller amount of funds to the pool - uint256 smallDeposit = 1e8; - - //add a smaller amount of funds to the pool - addFundsToPool(PRIMARY_POOL_ID, getAsset(smallDeposit), FEE_MANAGER); - - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (smallDeposit * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //smaller deposits will consequently have less precision and will not be able to be split as evenly, the remaining 1 will be lost due to 333...|... being paid out instead of 333...4| - assertEq(getAssetBalance(address(rewardManager)), 1); - } - - function test_allRecipientsClaimingReceiveExpectedAmount() public { - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop all the recipients and claim their expected amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //claim the individual rewards for each recipient - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //the recipient should have received a share proportional to their weight - uint256 expectedRecipientAmount = (POOL_DEPOSIT_AMOUNT * recipient.weight) / POOL_SCALAR; - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - - //their should be 0 wei left over indicating a successful split - assertEq(getAssetBalance(address(rewardManager)), 0); - } -} - -contract DestinationRewardManagerNoRecipientSet is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //add funds to the pool to be split among the recipients once registered - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_claimAllRecipientsAfterRecipientsSet() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //try and claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //there should be no rewards claimed as the recipient is not registered - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the recipient received nothing - assertEq(getAssetBalance(recipient.addr), 0); - } - - //Set the recipients after the rewards have been paid into the pool - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //claim funds for each recipient within the pool - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //get the recipient that is claiming - Common.AddressAndWeight memory recipient = getPrimaryRecipients()[i]; - - //there should be no rewards claimed as the recipient is registered - claimRewards(PRIMARY_POOL_ARRAY, recipient.addr); - - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipient.addr), expectedRecipientAmount); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol deleted file mode 100644 index 4c79d2c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.general.t.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; -import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -/** - * @title DestinationRewardManagerSetupTest - * @author Michael Fletcher - * @notice This contract will test the core functionality of the DestinationRewardManager contract - */ -contract DestinationRewardManagerSetupTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - } - - function test_rejectsZeroLinkAddressOnConstruction() public { - //should revert if the contract is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //create a rewardManager with a zero link address - new DestinationRewardManager(address(0)); - } - - function test_eventEmittedUponFeeManagerUpdate() public { - //expect the event to be emitted - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit FeeManagerUpdated(FEE_MANAGER_2); - - //set the verifier proxy - setFeeManager(FEE_MANAGER_2, ADMIN); - } - - function test_eventEmittedUponFeePaid() public { - //create pool and add funds - createPrimaryPool(); - - //change to the feeManager who is the one who will be paying the fees - changePrank(FEE_MANAGER); - - //approve the amount being paid into the pool - ERC20Mock(getAsset(POOL_DEPOSIT_AMOUNT).assetAddress).approve(address(rewardManager), POOL_DEPOSIT_AMOUNT); - - IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); - payments[0] = IDestinationRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); - - //event is emitted when funds are added - vm.expectEmit(); - emit FeePaid(payments, FEE_MANAGER); - - //this represents the verifier adding some funds to the pool - rewardManager.onFeePaid(payments, FEE_MANAGER); - } - - function test_setFeeManagerZeroAddress() public { - //should revert if the contract is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the verifier proxy - setFeeManager(address(0), ADMIN); - } - - function test_addFeeManagerZeroAddress() public { - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - rewardManager.addFeeManager(address(0)); - } - - function test_addFeeManagerExistingAddress() public { - address dummyAddress = address(998); - rewardManager.addFeeManager(dummyAddress); - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - rewardManager.addFeeManager(dummyAddress); - } - - function test_removeFeeManagerNonExistentAddress() public { - address dummyAddress = address(991); - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - rewardManager.removeFeeManager(dummyAddress); - } - - function test_addRemoveFeeManager() public { - address dummyAddress1 = address(1); - address dummyAddress2 = address(2); - rewardManager.addFeeManager(dummyAddress1); - rewardManager.addFeeManager(dummyAddress2); - assertEq(rewardManager.s_feeManagerAddressList(dummyAddress1), dummyAddress1); - assertEq(rewardManager.s_feeManagerAddressList(dummyAddress2), dummyAddress2); - rewardManager.removeFeeManager(dummyAddress1); - assertEq(rewardManager.s_feeManagerAddressList(dummyAddress1), address(0)); - assertEq(rewardManager.s_feeManagerAddressList(dummyAddress2), dummyAddress2); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol deleted file mode 100644 index 4aa3c86..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.payRecipients.t.sol +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -/** - * @title DestinationRewardManagerPayRecipientsTest - * @author Michael Fletcher - * @notice This contract will test the payRecipients functionality of the RewardManager contract - */ -contract DestinationRewardManagerPayRecipientsTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_payAllRecipients() public { - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); - - //each recipient should receive 1/4 of the pool - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_paySingleRecipient() public { - //get the first individual recipient - address recipient = getPrimaryRecipientAddresses()[0]; - - //get a single recipient as an array - address[] memory recipients = new address[](1); - recipients[0] = recipient; - - //pay a single recipient - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //the recipient should have received 1/4 of the deposit amount - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - assertEq(getAssetBalance(recipient), expectedRecipientAmount); - } - - function test_payRecipientWithInvalidPool() public { - //get the first individual recipient - address recipient = getPrimaryRecipientAddresses()[0]; - - //get a single recipient as an array - address[] memory recipients = new address[](1); - recipients[0] = recipient; - - //pay a single recipient - payRecipients(SECONDARY_POOL_ID, recipients, ADMIN); - - //the recipient should have received nothing - assertEq(getAssetBalance(recipient), 0); - } - - function test_payRecipientsEmptyRecipientList() public { - //get a single recipient - address[] memory recipients = new address[](0); - - //pay a single recipient - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //rewardManager should have the full balance - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_payAllRecipientsWithAdditionalUnregisteredRecipient() public { - //load all the recipients and add an additional one who is not in the pool - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - recipients[recipients.length - 1] = DEFAULT_RECIPIENT_5; - - //pay the recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - - //the unregistered recipient should receive nothing - assertEq(getAssetBalance(DEFAULT_RECIPIENT_5), 0); - } - - function test_payAllRecipientsWithAdditionalInvalidRecipient() public { - //load all the recipients and add an additional one which is invalid, that should receive nothing - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length + 1); - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - recipients[recipients.length - 1] = INVALID_ADDRESS; - - //pay the recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_paySubsetOfRecipientsInPool() public { - //load a subset of the recipients into an array - address[] memory recipients = new address[](getPrimaryRecipientAddresses().length - 1); - for (uint256 i = 0; i < recipients.length; i++) { - recipients[i] = getPrimaryRecipientAddresses()[i]; - } - - //pay the subset of recipients - payRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //each recipient should receive 1/4 of the pool except the last - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each subset of recipients received the correct amount - for (uint256 i = 0; i < recipients.length - 1; i++) { - assertEq(getAssetBalance(recipients[i]), expectedRecipientAmount); - } - - //check the pool has the remaining balance - assertEq( - getAssetBalance(address(rewardManager)), - POOL_DEPOSIT_AMOUNT - expectedRecipientAmount * recipients.length - ); - } - - function test_payAllRecipientsFromNonAdminUser() public { - //should revert if the caller isn't an admin or recipient within the pool - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), FEE_MANAGER); - } - - function test_payAllRecipientsFromRecipientInPool() public { - //pay all the recipients in the pool - payRecipients(PRIMARY_POOL_ID, getPrimaryRecipientAddresses(), DEFAULT_RECIPIENT_1); - - //each recipient should receive 1/4 of the pool - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //check each recipient received the correct amount - for (uint256 i = 0; i < getPrimaryRecipientAddresses().length; i++) { - assertEq(getAssetBalance(getPrimaryRecipientAddresses()[i]), expectedRecipientAmount); - } - } - - function test_payRecipientsWithInvalidPoolId() public { - //pay all the recipients in the pool - payRecipients(INVALID_POOL_ID, getPrimaryRecipientAddresses(), ADMIN); - - //pool should still contain the full balance - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_addFundsToPoolAsOwner() public { - //add funds to the pool - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_addFundsToPoolAsNonOwnerOrFeeManager() public { - //should revert if the caller isn't an admin or recipient within the pool - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - IDestinationRewardManager.FeePayment[] memory payments = new IDestinationRewardManager.FeePayment[](1); - payments[0] = IDestinationRewardManager.FeePayment(PRIMARY_POOL_ID, uint192(POOL_DEPOSIT_AMOUNT)); - - //add funds to the pool - rewardManager.onFeePaid(payments, USER); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol deleted file mode 100644 index facbaa1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.setRecipients.t.sol +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title DestinationRewardManagerSetRecipientsTest - * @author Michael Fletcher - * @notice This contract will test the setRecipient functionality of the RewardManager contract - */ -contract DestinationRewardManagerSetRecipientsTest is BaseDestinationRewardManagerTest { - function setUp() public override { - //setup contracts - super.setUp(); - } - - function test_setRewardRecipients() public { - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRewardRecipientsIsEmpty() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWithZeroWeight() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 25); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, ONE_PERCENT * 25); - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, 0); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWithZeroAddress() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = getPrimaryRecipients(); - - //override the first recipient with a zero address - recipients[0].addr = address(0); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientWeights() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 25); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, 25); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, 25); - - //should revert if the recipients array is empty - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //set the recipients with a recipient with a weight of 100% - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setSingleRewardRecipient() public { - //array of recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](1); - - //init each recipient with even weights - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR); - - //set the recipients with a recipient with a weight of 100% - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_setRewardRecipientTwice() public { - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //should revert if recipients for this pool have already been set - vm.expectRevert(INVALID_POOL_ID_ERROR_SELECTOR); - - //set the recipients again - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() public { - //should revert if the sender is not the owner or proxy - vm.expectRevert(UNAUTHORIZED_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), USER); - } - - function test_setRewardRecipientFromManagerAddress() public { - //update the proxy address - setFeeManager(FEE_MANAGER_2, ADMIN); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER_2); - } - - function test_eventIsEmittedUponSetRecipients() public { - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - } - - function test_setRecipientContainsDuplicateRecipients() public { - //create a new array to hold the existing recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add all the existing recipients again - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; - } - - //should revert as the list contains a duplicate - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //set the recipients - setRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol deleted file mode 100644 index 226be8e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/reward-manager/DestinationRewardManager.updateRewardRecipients.t.sol +++ /dev/null @@ -1,450 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseDestinationRewardManagerTest} from "./BaseDestinationRewardManager.t.sol"; -import {Common} from "../../../libraries/Common.sol"; - -/** - * @title DestinationRewardManagerUpdateRewardRecipientsTest - * @author Michael Fletcher - * @notice This contract will test the updateRecipient functionality of the RewardManager contract - */ -contract DestinationRewardManagerUpdateRewardRecipientsTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function test_onlyAdminCanUpdateRecipients() public { - //should revert if the caller is not the admin - vm.expectRevert(ONLY_CALLABLE_BY_OWNER_ERROR); - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), FEE_MANAGER); - } - - function test_updateAllRecipientsWithSameAddressAndWeight() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); - } - } - - function test_updatePartialRecipientsWithSameAddressAndWeight() public { - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //get a subset of the recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 25); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 25); - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should still have half remaining funds - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); - } - - function test_updateRecipientWithNewZeroAddress() public { - //create a new array to hold the existing recipients plus a new zero address - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 1); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add a new address to the primary recipients - recipients[recipients.length - 1] = Common.AddressAndWeight(address(0), 0); - - //should revert if the recipient is a zero address - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //update the recipients with invalid address - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsContainsDuplicateRecipients() public { - //create a new array to hold the existing recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length * 2); - - //add all the existing recipients - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i] = getPrimaryRecipients()[i]; - } - //add all the existing recipients again - for (uint256 i; i < getPrimaryRecipients().length; i++) { - recipients[i + getPrimaryRecipients().length] = getPrimaryRecipients()[i]; - } - - //should revert as the list contains a duplicate - vm.expectRevert(INVALID_ADDRESS_ERROR_SELECTOR); - - //update the recipients with the duplicate addresses - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 4); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, ONE_PERCENT * 25); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, ONE_PERCENT * 25); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, ONE_PERCENT * 25); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, ONE_PERCENT * 25); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentPartialSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, FIFTY_PERCENT); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, FIFTY_PERCENT); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentLargerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 5); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 2); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT * 2); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT * 2); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT * 2); - recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT * 2); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsUpdateAndRemoveExistingForLargerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](9); - - //update the existing recipients - recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); - recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); - recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 3); - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); - recipients[6] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, TEN_PERCENT); - recipients[7] = Common.AddressAndWeight(DEFAULT_RECIPIENT_8, TEN_PERCENT); - recipients[8] = Common.AddressAndWeight(DEFAULT_RECIPIENT_9, TEN_PERCENT); - - //should revert as the weight does not equal 100% - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](5); - - //update the existing recipients - recipients[0] = Common.AddressAndWeight(getPrimaryRecipients()[0].addr, 0); - recipients[1] = Common.AddressAndWeight(getPrimaryRecipients()[1].addr, 0); - recipients[2] = Common.AddressAndWeight(getPrimaryRecipients()[2].addr, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(getPrimaryRecipients()[3].addr, TEN_PERCENT * 2); - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientsToDifferentSetWithInvalidWeights() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](getPrimaryRecipients().length + 2); - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //copy the recipient and set the weight to 0 which implies the recipient is being replaced - recipients[i] = Common.AddressAndWeight(getPrimaryRecipients()[i].addr, 0); - } - - //add the new recipients individually - recipients[4] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, TEN_PERCENT * 5); - recipients[5] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, TEN_PERCENT); - - //should revert as the weight will not equal 100% - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsToSubset() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, 0); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, 0); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 5); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsWithUnderWeightSet() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); - - //should revert as the new weights exceed the previous weights being replaced - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updatePartialRecipientsWithExcessiveWeight() public { - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR); - - //should revert as the new weights exceed the previous weights being replaced - vm.expectRevert(INVALID_WEIGHT_ERROR_SELECTOR); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - } - - function test_updateRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set with their new weights - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT * 3); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT * 5); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should have no funds remaining - assertEq(getAssetBalance(address(rewardManager)), 0); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop each user and claim the rewards - for (uint256 i; i < recipients.length; i++) { - //claim the rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); - } - - //manually check the balance of each recipient - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_1), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_2), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_3), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 3) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_4), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 5) / POOL_SCALAR + expectedRecipientAmount - ); - } - - function test_partialUpdateRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set with their new weights - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](2); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should have half the funds remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT / 2); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //loop each user and claim the rewards - for (uint256 i; i < recipients.length; i++) { - //claim the rewards for this recipient - claimRewards(PRIMARY_POOL_ARRAY, recipients[i].addr); - } - - //manually check the balance of each recipient - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_1), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(DEFAULT_RECIPIENT_2), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - - //the reward manager should have half the funds remaining - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - } - - function test_eventIsEmittedUponUpdateRecipients() public { - //expect an emit - vm.expectEmit(); - - //emit the event that is expected to be emitted - emit RewardRecipientsUpdated(PRIMARY_POOL_ID, getPrimaryRecipients()); - - //expected recipient amount is 1/4 of the pool deposit - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //updating a recipient should force the funds to be paid out - updateRewardRecipients(PRIMARY_POOL_ID, getPrimaryRecipients(), ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < getPrimaryRecipients().length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(getPrimaryRecipients()[i].addr), expectedRecipientAmount); - } - } -} - -contract DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest is BaseDestinationRewardManagerTest { - uint256 internal constant POOL_DEPOSIT_AMOUNT = 10e18; - - function setUp() public override { - //setup contracts - super.setUp(); - - //create a single pool for these tests - createPrimaryPool(); - createSecondaryPool(); - - //add funds to the pool to be split among the recipients - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - addFundsToPool(SECONDARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - } - - function getSecondaryRecipients() public override returns (Common.AddressAndWeight[] memory) { - //for testing purposes, the primary and secondary pool to contain the same recipients - return getPrimaryRecipients(); - } - - function test_updatePrimaryRecipientWeights() public { - //expected recipient amount is 1/4 of the pool deposit for original recipients - uint256 expectedRecipientAmount = POOL_DEPOSIT_AMOUNT / 4; - - //create a list of containing recipients from the primary configured set, and new recipients - Common.AddressAndWeight[] memory recipients = new Common.AddressAndWeight[](4); - recipients[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, TEN_PERCENT * 4); - recipients[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, TEN_PERCENT * 4); - recipients[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, TEN_PERCENT); - recipients[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, TEN_PERCENT); - - //updating a recipient should force the funds to be paid out for the primary recipients - updateRewardRecipients(PRIMARY_POOL_ID, recipients, ADMIN); - - //check each recipient received the correct amount - for (uint256 i; i < recipients.length; i++) { - //check the balance matches the ratio the recipient should have received - assertEq(getAssetBalance(recipients[i].addr), expectedRecipientAmount); - } - - //the reward manager should still have the funds for the secondary pool - assertEq(getAssetBalance(address(rewardManager)), POOL_DEPOSIT_AMOUNT); - - //add more funds to the pool to check new distribution - addFundsToPool(PRIMARY_POOL_ID, getAsset(POOL_DEPOSIT_AMOUNT), FEE_MANAGER); - - //claim the rewards for the updated recipients manually - claimRewards(PRIMARY_POOL_ARRAY, recipients[0].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[1].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[2].addr); - claimRewards(PRIMARY_POOL_ARRAY, recipients[3].addr); - - //check the balance matches the ratio the recipient who were updated should have received - assertEq( - getAssetBalance(recipients[0].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[1].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT * 4) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[2].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - assertEq( - getAssetBalance(recipients[3].addr), - (POOL_DEPOSIT_AMOUNT * TEN_PERCENT) / POOL_SCALAR + expectedRecipientAmount - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol deleted file mode 100644 index ec3b3a0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/BaseDestinationVerifierTest.t.sol +++ /dev/null @@ -1,347 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {DestinationVerifierProxy} from "../../DestinationVerifierProxy.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IDestinationVerifier} from "../../interfaces/IDestinationVerifier.sol"; -import {IDestinationVerifierProxy} from "../../interfaces/IDestinationVerifierProxy.sol"; -import {DestinationVerifier} from "../../DestinationVerifier.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {DestinationFeeManager} from "../../DestinationFeeManager.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {ERC20Mock} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; -import {WERC20Mock} from "../../../../shared/mocks/WERC20Mock.sol"; -import {DestinationRewardManager} from "../../DestinationRewardManager.sol"; -import {IDestinationRewardManager} from "../../interfaces/IDestinationRewardManager.sol"; - -contract BaseTest is Test { - uint64 internal constant POOL_SCALAR = 1e18; - uint64 internal constant ONE_PERCENT = POOL_SCALAR / 100; - uint256 internal constant MAX_ORACLES = 31; - address internal constant ADMIN = address(1); - address internal constant USER = address(2); - - address internal constant MOCK_VERIFIER_ADDRESS = address(100); - address internal constant ACCESS_CONTROLLER_ADDRESS = address(300); - - uint256 internal constant DEFAULT_REPORT_LINK_FEE = 1e10; - uint256 internal constant DEFAULT_REPORT_NATIVE_FEE = 1e12; - - uint64 internal constant VERIFIER_VERSION = 1; - - uint8 internal constant FAULT_TOLERANCE = 10; - - DestinationVerifierProxy internal s_verifierProxy; - DestinationVerifier internal s_verifier; - DestinationFeeManager internal feeManager; - DestinationRewardManager internal rewardManager; - ERC20Mock internal link; - WERC20Mock internal native; - - struct Signer { - uint256 mockPrivateKey; - address signerAddress; - } - - Signer[MAX_ORACLES] internal s_signers; - bytes32[] internal s_offchaintransmitters; - bool private s_baseTestInitialized; - - struct V3Report { - // The feed ID the report has data for - bytes32 feedId; - // The time the median value was observed on - uint32 observationsTimestamp; - // The timestamp the report is valid from - uint32 validFromTimestamp; - // The link fee - uint192 linkFee; - // The native fee - uint192 nativeFee; - // The expiry of the report - uint32 expiresAt; - // The median value agreed in an OCR round - int192 benchmarkPrice; - // The best bid value agreed in an OCR round - int192 bid; - // The best ask value agreed in an OCR round - int192 ask; - } - - bytes32 internal constant V_MASK = 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - bytes32 internal constant V1_BITMASK = 0x0001000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V2_BITMASK = 0x0002000000000000000000000000000000000000000000000000000000000000; - bytes32 internal constant V3_BITMASK = 0x0003000000000000000000000000000000000000000000000000000000000000; - - bytes32 internal constant INVALID_FEED = keccak256("INVALID"); - uint32 internal constant OBSERVATIONS_TIMESTAMP = 1000; - uint64 internal constant BLOCKNUMBER_LOWER_BOUND = 1000; - uint64 internal constant BLOCKNUMBER_UPPER_BOUND = BLOCKNUMBER_LOWER_BOUND + 5; - int192 internal constant MEDIAN = 1 ether; - int192 internal constant BID = 500000000 gwei; - int192 internal constant ASK = 2 ether; - - //version 0 feeds - bytes32 internal constant FEED_ID = (keccak256("ETH-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant FEED_ID_2 = (keccak256("LINK-USD") & V_MASK) | V1_BITMASK; - bytes32 internal constant FEED_ID_3 = (keccak256("BTC-USD") & V_MASK) | V1_BITMASK; - - //version 3 feeds - bytes32 internal constant FEED_ID_V3 = (keccak256("ETH-USD") & V_MASK) | V3_BITMASK; - - function _encodeReport(V3Report memory report) internal pure returns (bytes memory) { - return - abi.encode( - report.feedId, - report.observationsTimestamp, - report.validFromTimestamp, - report.nativeFee, - report.linkFee, - report.expiresAt, - report.benchmarkPrice, - report.bid, - report.ask - ); - } - - function _generateSignerSignatures( - bytes memory report, - bytes32[3] memory reportContext, - Signer[] memory signers - ) internal pure returns (bytes32[] memory rawRs, bytes32[] memory rawSs, bytes32 rawVs) { - bytes32[] memory rs = new bytes32[](signers.length); - bytes32[] memory ss = new bytes32[](signers.length); - bytes memory vs = new bytes(signers.length); - - bytes32 hash = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - for (uint256 i = 0; i < signers.length; i++) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(signers[i].mockPrivateKey, hash); - rs[i] = r; - ss[i] = s; - vs[i] = bytes1(v - 27); - } - return (rs, ss, bytes32(vs)); - } - - function _generateV3EncodedBlob( - V3Report memory report, - bytes32[3] memory reportContext, - Signer[] memory signers - ) internal pure returns (bytes memory) { - bytes memory reportBytes = _encodeReport(report); - (bytes32[] memory rs, bytes32[] memory ss, bytes32 rawVs) = _generateSignerSignatures( - reportBytes, - reportContext, - signers - ); - return abi.encode(reportContext, reportBytes, rs, ss, rawVs); - } - - function _verify(bytes memory payload, address feeAddress, uint256 wrappedNativeValue, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - s_verifierProxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - changePrank(originalAddr); - } - - function _generateV3Report() internal view returns (V3Report memory) { - return - V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function _verifyBulk( - bytes[] memory payload, - address feeAddress, - uint256 wrappedNativeValue, - address sender - ) internal { - address originalAddr = msg.sender; - changePrank(sender); - - s_verifierProxy.verifyBulk{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - changePrank(originalAddr); - } - - function _approveLink(address spender, uint256 quantity, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - link.approve(spender, quantity); - changePrank(originalAddr); - } - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - vm.startPrank(ADMIN); - - s_verifierProxy = new DestinationVerifierProxy(); - s_verifier = new DestinationVerifier(address(s_verifierProxy)); - s_verifierProxy.setVerifier(address(s_verifier)); - - // setting up FeeManager and RewardManager - native = new WERC20Mock(); - link = new ERC20Mock("LINK", "LINK", ADMIN, 0); - rewardManager = new DestinationRewardManager(address(link)); - feeManager = new DestinationFeeManager(address(link), address(native), address(s_verifier), address(rewardManager)); - - for (uint256 i; i < MAX_ORACLES; i++) { - uint256 mockPK = i + 1; - s_signers[i].mockPrivateKey = mockPK; - s_signers[i].signerAddress = vm.addr(mockPK); - } - } - - function _getSigners(uint256 numSigners) internal view returns (Signer[] memory) { - Signer[] memory signers = new Signer[](numSigners); - for (uint256 i; i < numSigners; i++) { - signers[i] = s_signers[i]; - } - return signers; - } - - function _getSignerAddresses(Signer[] memory signers) internal pure returns (address[] memory) { - address[] memory signerAddrs = new address[](signers.length); - for (uint256 i = 0; i < signerAddrs.length; i++) { - signerAddrs[i] = signers[i].signerAddress; - } - return signerAddrs; - } - - function _signerAddressAndDonConfigKey(address signer, bytes24 donConfigId) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(signer, donConfigId)); - } - - function _donConfigIdFromConfigData(address[] memory signers, uint8 f) internal pure returns (bytes24) { - Common._quickSort(signers, 0, int256(signers.length - 1)); - bytes24 donConfigId = bytes24(keccak256(abi.encodePacked(signers, f))); - return donConfigId; - } - - function assertReportsEqual(bytes memory response, V3Report memory testReport) public pure { - ( - bytes32 feedId, - uint32 observationsTimestamp, - uint32 validFromTimestamp, - uint192 nativeFee, - uint192 linkFee, - uint32 expiresAt, - int192 benchmarkPrice, - int192 bid, - int192 ask - ) = abi.decode(response, (bytes32, uint32, uint32, uint192, uint192, uint32, int192, int192, int192)); - assertEq(feedId, testReport.feedId); - assertEq(observationsTimestamp, testReport.observationsTimestamp); - assertEq(validFromTimestamp, testReport.validFromTimestamp); - assertEq(expiresAt, testReport.expiresAt); - assertEq(benchmarkPrice, testReport.benchmarkPrice); - assertEq(bid, testReport.bid); - assertEq(ask, testReport.ask); - assertEq(linkFee, testReport.linkFee); - assertEq(nativeFee, testReport.nativeFee); - } - - function _approveNative(address spender, uint256 quantity, address sender) internal { - address originalAddr = msg.sender; - changePrank(sender); - - native.approve(spender, quantity); - changePrank(originalAddr); - } -} - -contract VerifierWithFeeManager is BaseTest { - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - function setUp() public virtual override { - BaseTest.setUp(); - - s_verifierProxy.setVerifier(address(s_verifier)); - s_verifier.setFeeManager(address(feeManager)); - rewardManager.addFeeManager(address(feeManager)); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some link tokens to the feeManager pool - link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); - } -} - -contract MultipleVerifierWithMultipleFeeManagers is BaseTest { - uint256 internal constant DEFAULT_LINK_MINT_QUANTITY = 100 ether; - uint256 internal constant DEFAULT_NATIVE_MINT_QUANTITY = 100 ether; - - DestinationVerifier internal s_verifier2; - DestinationVerifier internal s_verifier3; - - DestinationVerifierProxy internal s_verifierProxy2; - DestinationVerifierProxy internal s_verifierProxy3; - - DestinationFeeManager internal feeManager2; - - function setUp() public virtual override { - /* - - Sets up 3 verifiers - - Sets up 2 Fee managers, wire the fee managers and verifiers - - Sets up a Reward Manager which can be used by both fee managers - */ - BaseTest.setUp(); - - s_verifierProxy2 = new DestinationVerifierProxy(); - s_verifierProxy3 = new DestinationVerifierProxy(); - - s_verifier2 = new DestinationVerifier(address(s_verifierProxy2)); - s_verifier3 = new DestinationVerifier(address(s_verifierProxy3)); - - s_verifierProxy2.setVerifier(address(s_verifier2)); - s_verifierProxy3.setVerifier(address(s_verifier3)); - - feeManager2 = new DestinationFeeManager( - address(link), - address(native), - address(s_verifier), - address(rewardManager) - ); - - s_verifier.setFeeManager(address(feeManager)); - s_verifier2.setFeeManager(address(feeManager)); - s_verifier3.setFeeManager(address(feeManager2)); - - // this is already set in the base contract - // feeManager.addVerifier(address(s_verifier)); - feeManager.addVerifier(address(s_verifier2)); - feeManager2.addVerifier(address(s_verifier3)); - - rewardManager.addFeeManager(address(feeManager)); - rewardManager.addFeeManager(address(feeManager2)); - - //mint some tokens to the user - link.mint(USER, DEFAULT_LINK_MINT_QUANTITY); - native.mint(USER, DEFAULT_NATIVE_MINT_QUANTITY); - vm.deal(USER, DEFAULT_NATIVE_MINT_QUANTITY); - - //mint some link tokens to the feeManager pool - link.mint(address(feeManager), DEFAULT_REPORT_LINK_FEE); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol deleted file mode 100644 index d4772ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierInterfacesTest.t.sol +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {Test} from "forge-std/Test.sol"; -import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {IDestinationFeeManager} from "../../../v0.4.0/interfaces/IDestinationFeeManager.sol"; -import {IDestinationRewardManager} from "../../../v0.4.0/interfaces/IDestinationRewardManager.sol"; -import {IDestinationVerifierProxy} from "../../../v0.4.0/interfaces/IDestinationVerifierProxy.sol"; -import {Common} from "../../../libraries/Common.sol"; -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol"; - -/* -This test checks the interfaces of destination verifier matches the expectations. -The code here comes from this example: - -https://docs.chain.link/chainlink-automation/guides/streams-lookup - -*/ - -// Custom interfaces for IVerifierProxy and IFeeManager -interface IVerifierProxy { - /** - * @notice Verifies that the data encoded has been signed. - * correctly by routing to the correct verifier, and bills the user if applicable. - * @param payload The encoded data to be verified, including the signed - * report. - * @param parameterPayload Fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address. - * @return verifierResponse The encoded report from the verifier. - */ - function verify( - bytes calldata payload, - bytes calldata parameterPayload - ) external payable returns (bytes memory verifierResponse); - - function s_feeManager() external view returns (IDestinationFeeManager); -} - -interface IFeeManager { - /** - * @notice Calculates the fee and reward associated with verifying a report, including discounts for subscribers. - * This function assesses the fee and reward for report verification, applying a discount for recognized subscriber addresses. - * @param subscriber The address attempting to verify the report. A discount is applied if this address - * is recognized as a subscriber. - * @param unverifiedReport The report data awaiting verification. The content of this report is used to - * determine the base fee and reward, before considering subscriber discounts. - * @param quoteAddress The payment token address used for quoting fees and rewards. - * @return fee The fee assessed for verifying the report, with subscriber discounts applied where applicable. - * @return reward The reward allocated to the caller for successfully verifying the report. - * @return totalDiscount The total discount amount deducted from the fee for subscribers. - */ - function getFeeAndReward( - address subscriber, - bytes memory unverifiedReport, - address quoteAddress - ) external returns (Common.Asset memory, Common.Asset memory, uint256); - - function i_linkAddress() external view returns (address); - - function i_nativeAddress() external view returns (address); - - function i_rewardManager() external view returns (address); -} - -//Tests -// https://docs.chain.link/chainlink-automation/guides/streams-lookup -contract VerifierInterfacesTest is VerifierWithFeeManager { - address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); - - IVerifierProxy public verifier; - V3Report internal s_testReport; - - address public FEE_ADDRESS; - string public constant DATASTREAMS_FEEDLABEL = "feedIDs"; - string public constant DATASTREAMS_QUERYLABEL = "timestamp"; - int192 public last_retrieved_price; - bytes internal signedReport; - bytes32[3] internal s_reportContext; - uint8 MINIMAL_FAULT_TOLERANCE = 2; - - function setUp() public virtual override { - VerifierWithFeeManager.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - Signer[] memory signers = _getSigners(MAX_ORACLES); - - s_testReport = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); - weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); - s_verifier.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights); - signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); - - verifier = IVerifierProxy(address(s_verifierProxy)); - } - - function test_DestinationContractInterfaces() public { - bytes memory unverifiedReport = signedReport; - - (, bytes memory reportData) = abi.decode(unverifiedReport, (bytes32[3], bytes)); - - // Report verification fees - IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager())); - IDestinationRewardManager rewardManager = IDestinationRewardManager(address(feeManager.i_rewardManager())); - - address feeTokenAddress = feeManager.i_linkAddress(); - (Common.Asset memory fee, , ) = feeManager.getFeeAndReward(address(this), reportData, feeTokenAddress); - - // Approve rewardManager to spend this contract's balance in fees - _approveLink(address(rewardManager), fee.amount, USER); - _verify(unverifiedReport, address(feeTokenAddress), 0, USER); - - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - fee.amount); - assertEq(link.balanceOf(address(rewardManager)), fee.amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol deleted file mode 100644 index 2851057..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierProxyTest.t.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationFeeManager} from "../../../v0.4.0/DestinationFeeManager.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -contract DestinationVerifierProxyInitializeVerifierTest is BaseTest { - function test_setVerifierCalledByNoOwner() public { - address STRANGER = address(999); - changePrank(STRANGER); - vm.expectRevert(bytes("Only callable by owner")); - s_verifierProxy.setVerifier(address(s_verifier)); - } - - function test_setVerifierWhichDoesntHonourInterface() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifierProxy.VerifierInvalid.selector, address(rewardManager))); - s_verifierProxy.setVerifier(address(rewardManager)); - } - - function test_setVerifierOk() public { - s_verifierProxy.setVerifier(address(s_verifier)); - assertEq(s_verifierProxy.s_feeManager(), s_verifier.s_feeManager()); - assertEq(s_verifierProxy.s_accessController(), s_verifier.s_accessController()); - } - - function test_correctlySetsTheOwner() public { - DestinationVerifierProxy proxy = new DestinationVerifierProxy(); - assertEq(proxy.owner(), ADMIN); - } - - function test_correctlySetsVersion() public view { - string memory version = s_verifierProxy.typeAndVersion(); - assertEq(version, "DestinationVerifierProxy 0.4.0"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol deleted file mode 100644 index 6309efc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierRemoveLatestConfigTest.t.sol +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract DestinationVerifierSetConfigTest is BaseTest { - bytes32[3] internal s_reportContext; - V3Report internal s_testReport; - - function setUp() public virtual override { - BaseTest.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - } - - function test_removeLatestConfigWhenNoConfigShouldFail() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); - s_verifier.removeLatestConfig(); - } - - function test_removeLatestConfig() public { - /* - This test sets two Configs: Config A and Config B. - - it removes and readds config B multiple times while trying Config A verifications - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); - signersA[0] = signers[0]; - signersA[1] = signers[1]; - signersA[2] = signers[2]; - signersA[3] = signers[3]; - signersA[4] = signers[4]; - signersA[5] = signers[5]; - signersA[6] = signers[6]; - - // ConfigA - address[] memory signersAddrA = _getSignerAddresses(signersA); - s_verifier.setConfig(signersAddrA, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 10); - V3Report memory s_testReportA = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - vm.warp(block.timestamp + 100); - // Config B - BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); - // signers in ConfigA - signersB[0] = signers[8]; - signersB[1] = signers[9]; - signersB[2] = signers[10]; - signersB[3] = signers[11]; - signersB[4] = signers[12]; - signersB[5] = signers[13]; - signersB[6] = signers[14]; - address[] memory signersAddrsB = _getSignerAddresses(signersB); - s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory s_testReportB = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); - reportSignersA[0] = signers[0]; - reportSignersA[1] = signers[1]; - reportSignersA[2] = signers[2]; - - BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); - reportSignersB[0] = signers[8]; - reportSignersB[1] = signers[9]; - reportSignersB[2] = signers[10]; - - bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); - bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); - - // verifying should work - s_verifierProxy.verify(signedReportA, abi.encode(native)); - s_verifierProxy.verify(signedReportB, abi.encode(native)); - - s_verifier.removeLatestConfig(); - - // this should remove the latest config, so ConfigA should be able to verify reports still - s_verifierProxy.verify(signedReportA, abi.encode(native)); - // this report cannot be verified any longer because ConfigB is not there - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReportB, abi.encode(native)); - - // since ConfigB is removed we should be able to set it again with no errors - s_verifier.setConfig(signersAddrsB, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - // we should be able to remove ConfigB - s_verifier.removeLatestConfig(); - // removing configA - s_verifier.removeLatestConfig(); - - // verifigny should fail - // verifying should work - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReportA, abi.encode(native)); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReportB, abi.encode(native)); - - // removing again should fail. no other configs exist - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); - s_verifier.removeLatestConfig(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol deleted file mode 100644 index d40b674..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetAccessControllerTest.t.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; - -contract DestinationVerifierSetAccessControllerTest is BaseTest { - event AccessControllerSet(address oldAccessController, address newAccessController); - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - - changePrank(USER); - s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); - } - - function test_successfullySetsNewAccessController() public { - s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); - address ac = s_verifier.s_accessController(); - assertEq(ac, ACCESS_CONTROLLER_ADDRESS); - } - - function test_successfullySetsNewAccessControllerIsEmpty() public { - s_verifier.setAccessController(address(0)); - address ac = s_verifier.s_accessController(); - assertEq(ac, address(0)); - } - - function test_emitsTheCorrectEvent() public { - vm.expectEmit(true, false, false, false); - emit AccessControllerSet(address(0), ACCESS_CONTROLLER_ADDRESS); - s_verifier.setAccessController(ACCESS_CONTROLLER_ADDRESS); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol deleted file mode 100644 index 4f96e49..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetConfigTest.t.sol +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationRewardManager} from "../../../v0.4.0/DestinationRewardManager.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract DestinationVerifierSetConfigTest is BaseTest { - function setUp() public virtual override { - BaseTest.setUp(); - } - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - Signer[] memory signers = _getSigners(MAX_ORACLES); - changePrank(USER); - s_verifier.setConfig(_getSignerAddresses(signers), FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_revertsIfSetWithTooManySigners() public { - address[] memory signers = new address[](MAX_ORACLES + 1); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ExcessSigners.selector, signers.length, MAX_ORACLES)); - s_verifier.setConfig(signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_revertsIfFaultToleranceIsZero() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.FaultToleranceMustBePositive.selector)); - Signer[] memory signers = _getSigners(MAX_ORACLES); - s_verifier.setConfig(_getSignerAddresses(signers), 0, new Common.AddressAndWeight[](0)); - } - - function test_revertsIfNotEnoughSigners() public { - address[] memory signers = new address[](2); - signers[0] = address(1000); - signers[1] = address(1001); - - vm.expectRevert( - abi.encodeWithSelector(DestinationVerifier.InsufficientSigners.selector, signers.length, FAULT_TOLERANCE * 3 + 1) - ); - s_verifier.setConfig(signers, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_revertsIfDuplicateSigners() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - signerAddrs[0] = signerAddrs[1]; - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.NonUniqueSignatures.selector)); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_revertsIfSignerContainsZeroAddress() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - signerAddrs[0] = address(0); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ZeroAddress.selector)); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_donConfigIdIsSameForSignersInDifferentOrder() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - - bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 1); - - address temp = signerAddrs[0]; - signerAddrs[0] = signerAddrs[1]; - signerAddrs[1] = temp; - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigAlreadyExists.selector, expectedDonConfigId)); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } - - function test_NoDonConfigAlreadyExists() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - vm.warp(block.timestamp + 1); - - // testing adding same set of Signers but different FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); - - vm.warp(block.timestamp + 1); - - // testing adding a different set of Signers with same FAULT_TOLERENCE does not result in DonConfigAlreadyExists revert - address[] memory signerAddrsMinusOne = new address[](signerAddrs.length - 1); - for (uint256 i = 0; i < signerAddrs.length - 1; i++) { - signerAddrsMinusOne[i] = signerAddrs[i]; - } - s_verifier.setConfig(signerAddrsMinusOne, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); - } - - function test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 1); - - bytes24 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigAlreadyExists.selector, expectedDonConfigId)); - - // Same call to setConfig with different addressAndWeights do not entail a new DonConfigID - // Resulting in a DonConfigAlreadyExists error - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); - weights[0] = Common.AddressAndWeight(signers[0].signerAddress, 1); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - } - - function test_setConfigActiveUnknownDonConfigId() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.DonConfigDoesNotExist.selector)); - s_verifier.setConfigActive(3, true); - } - - function test_setConfigWithActivationTime() public { - // simple case setting a config with specific activation time - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - uint32 activationTime = 10; - s_verifier.setConfigWithActivationTime( - signerAddrs, - FAULT_TOLERANCE, - new Common.AddressAndWeight[](0), - activationTime - ); - } - - function test_setConfigWithActivationTimeNoFutureTimeShouldFail() public { - // calling setConfigWithActivationTime with a future timestamp should fail - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - uint32 activationTime = uint32(block.timestamp) + 100; - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); - s_verifier.setConfigWithActivationTime( - signerAddrs, - FAULT_TOLERANCE, - new Common.AddressAndWeight[](0), - activationTime - ); - } - - function test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() public { - // setting a config older than the latest current config should fail - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - uint32 oldActivationTime = uint32(block.timestamp) - 1; - // sets a config with timestamp = block.timestamp - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - // setting a config with ealier timestamp retuls in failure - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); - s_verifier.setConfigWithActivationTime( - signerAddrs, - FAULT_TOLERANCE - 1, - new Common.AddressAndWeight[](0), - oldActivationTime - ); - } - - function test_setConfigWithActivationTimeTheSameAsLatestConfigShouldFail() public { - // setting a config older than the latest current config should fail - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - // sets a config with timestamp = block.timestamp - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - // setting a config with ealier timestamp retuls in failure - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadActivationTime.selector)); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol deleted file mode 100644 index fdf75d6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierSetFeeManagerTest.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; - -contract VerifierSetAccessControllerTest is BaseTest { - event FeeManagerSet(address oldFeeManager, address newFeeManager); - - function test_revertsIfCalledByNonOwner() public { - vm.expectRevert("Only callable by owner"); - changePrank(USER); - s_verifier.setFeeManager(address(feeManager)); - } - - function test_successfullySetsNewFeeManager() public { - vm.expectEmit(true, false, false, false); - emit FeeManagerSet(address(0), ACCESS_CONTROLLER_ADDRESS); - s_verifier.setFeeManager(address(feeManager)); - address ac = s_verifier.s_feeManager(); - assertEq(ac, address(feeManager)); - } - - function test_setFeeManagerWhichDoesntHonourInterface() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.FeeManagerInvalid.selector)); - s_verifier.setFeeManager(address(rewardManager)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol deleted file mode 100644 index 476acbf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTest.t.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {IDestinationVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifier.sol"; -import {IDestinationVerifierProxyVerifier} from "../../../v0.4.0/interfaces/IDestinationVerifierProxyVerifier.sol"; - -contract DestinationVerifierConstructorTest is BaseTest { - bytes32[3] internal s_reportContext; - - function test_revertsIfInitializedWithEmptyVerifierProxy() public { - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.ZeroAddress.selector)); - new DestinationVerifier(address(0)); - } - - function test_typeAndVersion() public { - DestinationVerifier v = new DestinationVerifier(address(s_verifierProxy)); - assertEq(v.owner(), ADMIN); - string memory typeAndVersion = s_verifier.typeAndVersion(); - assertEq(typeAndVersion, "DestinationVerifier 0.4.0"); - } - - function test_falseIfIsNotCorrectInterface() public view { - bool isInterface = s_verifier.supportsInterface(bytes4("abcd")); - assertEq(isInterface, false); - } - - function test_trueIfIsCorrectInterface() public view { - bool isInterface = s_verifier.supportsInterface(type(IDestinationVerifier).interfaceId) && - s_verifier.supportsInterface(type(IDestinationVerifierProxyVerifier).interfaceId); - assertEq(isInterface, true); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol deleted file mode 100644 index 574e169..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestBillingReport.t.sol +++ /dev/null @@ -1,189 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierBillingTests is VerifierWithFeeManager { - bytes32[3] internal s_reportContext; - V3Report internal s_testReportThree; - - function setUp() public virtual override { - VerifierWithFeeManager.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReportThree = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function test_verifyWithLinkV3Report() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); - bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(signedReport, address(link), 0, USER); - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - - // internal state checks - assertEq(feeManager.s_linkDeficit(expectedDonConfigId), 0); - assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigId), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - } - - function test_verifyWithNativeERC20() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); - weights[0] = Common.AddressAndWeight(signerAddrs[0], ONE_PERCENT * 100); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - bytes memory signedReport = _generateV3EncodedBlob( - s_testReportThree, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE, USER); - _verify(signedReport, address(native), 0, USER); - assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - } - - function test_verifyWithNativeUnwrapped() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - bytes memory signedReport = _generateV3EncodedBlob( - s_testReportThree, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE, USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - assertEq(address(feeManager).balance, 0); - } - - function test_verifyWithNativeUnwrappedReturnsChange() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - bytes memory signedReport = _generateV3EncodedBlob( - s_testReportThree, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - _verify(signedReport, address(native), DEFAULT_REPORT_NATIVE_FEE * 2, USER); - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE); - assertEq(address(feeManager).balance, 0); - } -} - -contract DestinationVerifierBulkVerifyBillingReport is VerifierWithFeeManager { - uint256 internal constant NUMBERS_OF_REPORTS = 5; - - bytes32[3] internal s_reportContext; - - function setUp() public virtual override { - VerifierWithFeeManager.setUp(); - // setting a DonConfig we can reuse in the rest of tests - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](0); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - } - - function test_verifyWithBulkLink() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS, USER); - - _verifyBulk(signedReports, address(link), 0, USER); - - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE * NUMBERS_OF_REPORTS); - } - - function test_verifyWithBulkNative() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _approveNative(address(feeManager), DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); - _verifyBulk(signedReports, address(native), 0, USER); - assertEq(native.balanceOf(USER), DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); - } - - function test_verifyWithBulkNativeUnwrapped() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _verifyBulk(signedReports, address(native), 200 * DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS, USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * 5); - assertEq(address(feeManager).balance, 0); - } - - function test_verifyWithBulkNativeUnwrappedReturnsChange() public { - bytes memory signedReport = _generateV3EncodedBlob( - _generateV3Report(), - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](NUMBERS_OF_REPORTS); - for (uint256 i = 0; i < NUMBERS_OF_REPORTS; i++) { - signedReports[i] = signedReport; - } - - _verifyBulk(signedReports, address(native), DEFAULT_REPORT_NATIVE_FEE * (NUMBERS_OF_REPORTS * 2), USER); - - assertEq(USER.balance, DEFAULT_NATIVE_MINT_QUANTITY - DEFAULT_REPORT_NATIVE_FEE * NUMBERS_OF_REPORTS); - assertEq(address(feeManager).balance, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol deleted file mode 100644 index 8ca954b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewards.t.sol +++ /dev/null @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {VerifierWithFeeManager} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierBillingTests is VerifierWithFeeManager { - uint8 MINIMAL_FAULT_TOLERANCE = 2; - address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); - address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); - address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); - address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); - address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); - address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); - address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); - - function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.payRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - bytes32[3] internal s_reportContext; - V3Report internal s_testReport; - - function setUp() public virtual override { - VerifierWithFeeManager.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReport = generateReportAtTimestamp(block.timestamp); - } - - function generateReportAtTimestamp(uint256 timestamp) public pure returns (V3Report memory) { - return - V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - // ask michael about this expires at, is it usually set at what blocks - expiresAt: uint32(timestamp) + 500, - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function getRecipientAndWeightsGroup2() public pure returns (Common.AddressAndWeight[] memory, address[] memory) { - address[] memory recipients = new address[](4); - recipients[0] = DEFAULT_RECIPIENT_4; - recipients[1] = DEFAULT_RECIPIENT_5; - recipients[2] = DEFAULT_RECIPIENT_6; - recipients[3] = DEFAULT_RECIPIENT_7; - - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](4); - //init each recipient with even weights. 2500 = 25% of pool - weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); - weights[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_5, POOL_SCALAR / 4); - weights[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_6, POOL_SCALAR / 4); - weights[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_7, POOL_SCALAR / 4); - return (weights, recipients); - } - - function getRecipientAndWeightsGroup1() public pure returns (Common.AddressAndWeight[] memory, address[] memory) { - address[] memory recipients = new address[](4); - recipients[0] = DEFAULT_RECIPIENT_1; - recipients[1] = DEFAULT_RECIPIENT_2; - recipients[2] = DEFAULT_RECIPIENT_3; - recipients[3] = DEFAULT_RECIPIENT_4; - - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](4); - //init each recipient with even weights. 2500 = 25% of pool - weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, POOL_SCALAR / 4); - weights[1] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, POOL_SCALAR / 4); - weights[2] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, POOL_SCALAR / 4); - weights[3] = Common.AddressAndWeight(DEFAULT_RECIPIENT_4, POOL_SCALAR / 4); - return (weights, recipients); - } - - function test_rewardsAreDistributedAccordingToWeights() public { - /* - Simple test verifying that rewards are distributed according to address and weights - associated to the DonConfig used to verify the report - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); - weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); - bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(signedReport, address(link), 0, USER); - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - - // internal state checks - assertEq(feeManager.s_linkDeficit(expectedDonConfigId), 0); - assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigId), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - // check the recipients are paid according to weights - address[] memory recipients = new address[](1); - recipients[0] = DEFAULT_RECIPIENT_1; - payRecipients(expectedDonConfigId, recipients, ADMIN); - assertEq(link.balanceOf(recipients[0]), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), 0); - } - - function test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() public { - /* - Rewards are distributed according to AddressAndWeight's - associated to the DonConfig used to verify the report: - - multiple recipients - - multiple verifications - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - (Common.AddressAndWeight[] memory weights, address[] memory recipients) = getRecipientAndWeightsGroup1(); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - - bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); - bytes32 expectedDonConfigId = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - - uint256 number_of_reports_verified = 10; - - for (uint256 i = 0; i < number_of_reports_verified; i++) { - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(signedReport, address(link), 0, USER); - } - - uint256 expected_pool_amount = DEFAULT_REPORT_LINK_FEE * number_of_reports_verified; - - //each recipient should receive 1/4 of the pool - uint256 expectedRecipientAmount = expected_pool_amount / 4; - - payRecipients(expectedDonConfigId, recipients, ADMIN); - for (uint256 i = 0; i < recipients.length; i++) { - // checking each recipient got rewards as set by the weights - assertEq(link.balanceOf(recipients[i]), expectedRecipientAmount); - } - // checking nothing left in reward manager - assertEq(link.balanceOf(address(rewardManager)), 0); - } - - function test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() public { - /* - Verifies that reports verified with historical give rewards according to the verifying config AddressAndWeight. - - Sets two Configs: ConfigA and ConfigB, These two Configs have different Recipient and Weights - - Verifies a couple reports with each config - - Pays recipients - - Asserts expected rewards for each recipient - */ - - Signer[] memory signers = _getSigners(10); - address[] memory signerAddrs = _getSignerAddresses(signers); - - (Common.AddressAndWeight[] memory weights, address[] memory recipients) = getRecipientAndWeightsGroup1(); - - // Create ConfigA - s_verifier.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights); - vm.warp(block.timestamp + 100); - - V3Report memory testReportAtT1 = generateReportAtTimestamp(block.timestamp); - bytes memory signedReportT1 = _generateV3EncodedBlob(testReportAtT1, s_reportContext, signers); - bytes32 expectedDonConfigIdA = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE); - - uint256 number_of_reports_verified = 2; - - // advancing the blocktimestamp so we can test verifying with configs - vm.warp(block.timestamp + 100); - - Signer[] memory signers2 = _getSigners(12); - address[] memory signerAddrs2 = _getSignerAddresses(signers2); - (Common.AddressAndWeight[] memory weights2, address[] memory recipients2) = getRecipientAndWeightsGroup2(); - - // Create ConfigB - s_verifier.setConfig(signerAddrs2, MINIMAL_FAULT_TOLERANCE, weights2); - bytes32 expectedDonConfigIdB = _donConfigIdFromConfigData(signerAddrs2, MINIMAL_FAULT_TOLERANCE); - - V3Report memory testReportAtT2 = generateReportAtTimestamp(block.timestamp); - - // verifiying using ConfigA (report with Old timestamp) - for (uint256 i = 0; i < number_of_reports_verified; i++) { - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(signedReportT1, address(link), 0, USER); - } - - // verifying using ConfigB (report with new timestamp) - for (uint256 i = 0; i < number_of_reports_verified; i++) { - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(_generateV3EncodedBlob(testReportAtT2, s_reportContext, signers2), address(link), 0, USER); - } - - uint256 expected_pool_amount = DEFAULT_REPORT_LINK_FEE * number_of_reports_verified; - assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigIdA), expected_pool_amount); - assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigIdB), expected_pool_amount); - - // check the recipients are paid according to weights - payRecipients(expectedDonConfigIdA, recipients, ADMIN); - - for (uint256 i = 0; i < recipients.length; i++) { - // //each recipient should receive 1/4 of the pool - assertEq(link.balanceOf(recipients[i]), expected_pool_amount / 4); - } - - payRecipients(expectedDonConfigIdB, recipients2, ADMIN); - - for (uint256 i = 1; i < recipients2.length; i++) { - // //each recipient should receive 1/4 of the pool - assertEq(link.balanceOf(recipients2[i]), expected_pool_amount / 4); - } - - // this recipient was part of the two config weights - assertEq(link.balanceOf(recipients2[0]), (expected_pool_amount / 4) * 2); - assertEq(link.balanceOf(address(rewardManager)), 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol deleted file mode 100644 index 6a90cbf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierTestRewardsMultiVefifierFeeManager.t.sol +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {MultipleVerifierWithMultipleFeeManagers} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract MultiVerifierBillingTests is MultipleVerifierWithMultipleFeeManagers { - uint8 MINIMAL_FAULT_TOLERANCE = 2; - address internal constant DEFAULT_RECIPIENT_1 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_1")))); - address internal constant DEFAULT_RECIPIENT_2 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_2")))); - address internal constant DEFAULT_RECIPIENT_3 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_3")))); - address internal constant DEFAULT_RECIPIENT_4 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_4")))); - address internal constant DEFAULT_RECIPIENT_5 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_5")))); - address internal constant DEFAULT_RECIPIENT_6 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_6")))); - address internal constant DEFAULT_RECIPIENT_7 = address(uint160(uint256(keccak256("DEFAULT_RECIPIENT_7")))); - - bytes32[3] internal s_reportContext; - V3Report internal s_testReport; - - function setUp() public virtual override { - MultipleVerifierWithMultipleFeeManagers.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - s_testReport = generateReportAtTimestamp(block.timestamp); - } - - function _verify( - DestinationVerifierProxy proxy, - bytes memory payload, - address feeAddress, - uint256 wrappedNativeValue, - address sender - ) internal { - address originalAddr = msg.sender; - changePrank(sender); - - proxy.verify{value: wrappedNativeValue}(payload, abi.encode(feeAddress)); - - changePrank(originalAddr); - } - - function generateReportAtTimestamp(uint256 timestamp) public pure returns (V3Report memory) { - return - V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - // ask michael about this expires at, is it usually set at what blocks - expiresAt: uint32(timestamp) + 500, - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function payRecipients(bytes32 poolId, address[] memory recipients, address sender) public { - //record the current address and switch to the recipient - address originalAddr = msg.sender; - changePrank(sender); - - //pay the recipients - rewardManager.payRecipients(poolId, recipients); - - //change back to the original address - changePrank(originalAddr); - } - - function test_multipleFeeManagersAndVerifiers() public { - /* - In this test we got: - - three verifiers (verifier, verifier2, verifier3). - - two fee managers (feeManager, feeManager2) - - one reward manager - - we glue: - - feeManager is used by verifier1 and verifier2 - - feeManager is used by verifier3 - - Rewardmanager is used by feeManager and feeManager2 - - In this test we do verificatons via verifier1, verifier2 and verifier3 and check that rewards are set accordingly - - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - Common.AddressAndWeight[] memory weights = new Common.AddressAndWeight[](1); - weights[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_1, ONE_PERCENT * 100); - - Common.AddressAndWeight[] memory weights2 = new Common.AddressAndWeight[](1); - weights2[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_2, ONE_PERCENT * 100); - - Common.AddressAndWeight[] memory weights3 = new Common.AddressAndWeight[](1); - weights3[0] = Common.AddressAndWeight(DEFAULT_RECIPIENT_3, ONE_PERCENT * 100); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, weights); - s_verifier2.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE, weights2); - s_verifier3.setConfig(signerAddrs, MINIMAL_FAULT_TOLERANCE + 1, weights3); - bytes memory signedReport = _generateV3EncodedBlob(s_testReport, s_reportContext, signers); - bytes32 expectedDonConfigID = _donConfigIdFromConfigData(signerAddrs, FAULT_TOLERANCE); - bytes32 expectedDonConfigID2 = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE); - bytes32 expectedDonConfigID3 = _donConfigIdFromConfigData(signerAddrs, MINIMAL_FAULT_TOLERANCE + 1); - - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(s_verifierProxy, signedReport, address(link), 0, USER); - assertEq(link.balanceOf(USER), DEFAULT_LINK_MINT_QUANTITY - DEFAULT_REPORT_LINK_FEE); - - // internal state checks - assertEq(feeManager.s_linkDeficit(expectedDonConfigID), 0); - assertEq(rewardManager.s_totalRewardRecipientFees(expectedDonConfigID), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), DEFAULT_REPORT_LINK_FEE); - - // check the recipients are paid according to weights - // These rewards happened through verifier1 and feeManager1 - address[] memory recipients = new address[](1); - recipients[0] = DEFAULT_RECIPIENT_1; - payRecipients(expectedDonConfigID, recipients, ADMIN); - assertEq(link.balanceOf(recipients[0]), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), 0); - - // these rewards happaned through verifier2 and feeManager1 - address[] memory recipients2 = new address[](1); - recipients2[0] = DEFAULT_RECIPIENT_2; - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(s_verifierProxy2, signedReport, address(link), 0, USER); - payRecipients(expectedDonConfigID2, recipients2, ADMIN); - assertEq(link.balanceOf(recipients2[0]), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), 0); - - // these rewards happened through verifier3 and feeManager2 - address[] memory recipients3 = new address[](1); - recipients3[0] = DEFAULT_RECIPIENT_3; - _approveLink(address(rewardManager), DEFAULT_REPORT_LINK_FEE, USER); - _verify(s_verifierProxy3, signedReport, address(link), 0, USER); - payRecipients(expectedDonConfigID3, recipients3, ADMIN); - assertEq(link.balanceOf(recipients3[0]), DEFAULT_REPORT_LINK_FEE); - assertEq(link.balanceOf(address(rewardManager)), 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol deleted file mode 100644 index 1c57295..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyBulkTest.t.sol +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierVerifyBulkTest is BaseTest { - bytes32[3] internal s_reportContext; - V3Report internal s_testReportThree; - - function setUp() public virtual override { - BaseTest.setUp(); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - - s_testReportThree = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function test_revertsVerifyBulkIfNoAccess() public { - vm.mockCall( - ACCESS_CONTROLLER_ADDRESS, - abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), - abi.encode(false) - ); - bytes memory signedReport = _generateV3EncodedBlob( - s_testReportThree, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - bytes[] memory signedReports = new bytes[](2); - signedReports[0] = signedReport; - signedReports[1] = signedReport; - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.AccessForbidden.selector)); - changePrank(USER); - s_verifier.verifyBulk(signedReports, abi.encode(native), msg.sender); - } - - function test_verifyBulkSingleCaseWithSingleConfig() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - // Config1 - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory report = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); - reportSigners[0] = signers[0]; - reportSigners[1] = signers[1]; - reportSigners[2] = signers[2]; - - bytes[] memory signedReports = new bytes[](10); - - bytes memory signedReport = _generateV3EncodedBlob(report, s_reportContext, reportSigners); - - for (uint256 i = 0; i < signedReports.length; i++) { - signedReports[i] = signedReport; - } - - bytes[] memory verifierResponses = s_verifierProxy.verifyBulk(signedReports, abi.encode(native)); - - for (uint256 i = 0; i < verifierResponses.length; i++) { - bytes memory verifierResponse = verifierResponses[i]; - assertReportsEqual(verifierResponse, report); - } - } - - function test_verifyBulkWithSingleConfigOneVerifyFails() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - // Config1 - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); - reportSigners[0] = signers[0]; - reportSigners[1] = signers[1]; - reportSigners[2] = signers[2]; - - bytes[] memory signedReports = new bytes[](11); - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners); - - for (uint256 i = 0; i < 10; i++) { - signedReports[i] = signedReport; - } - - // Making the last report in this batch not verifiable - BaseTest.Signer[] memory reportSigners2 = new BaseTest.Signer[](3); - reportSigners2[0] = signers[30]; - reportSigners2[1] = signers[29]; - reportSigners2[2] = signers[28]; - signedReports[10] = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners2); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verifyBulk(signedReports, abi.encode(native)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol deleted file mode 100644 index e72cfd0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.4.0/test/verifier/DestinationVerifierVerifyTest.t.sol +++ /dev/null @@ -1,714 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseDestinationVerifierTest.t.sol"; -import {DestinationVerifier} from "../../../v0.4.0/DestinationVerifier.sol"; -import {DestinationVerifierProxy} from "../../../v0.4.0/DestinationVerifierProxy.sol"; -import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; -import {Common} from "../../../libraries/Common.sol"; - -contract VerifierVerifyTest is BaseTest { - bytes32[3] internal s_reportContext; - V3Report internal s_testReportThree; - - function setUp() public virtual override { - BaseTest.setUp(); - - s_testReportThree = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - } - - function test_verifyReport() public { - // Simple use case just setting a config and verifying a report - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); - - bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); - assertReportsEqual(verifierResponse, s_testReportThree); - } - - function test_verifyTooglingActiveFlagsDonConfigs() public { - // sets config - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signers); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - // verifies report - bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); - assertReportsEqual(verifierResponse, s_testReportThree); - - // test verifying via a config that is deactivated - s_verifier.setConfigActive(0, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); - - // test verifying via a reactivated config - s_verifier.setConfigActive(0, true); - verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); - assertReportsEqual(verifierResponse, s_testReportThree); - } - - function test_failToVerifyReportIfNotEnoughSigners() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - // only one signer, signers < MINIMAL_FAULT_TOLERANCE - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](1); - signersSubset2[0] = signers[4]; - - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_failToVerifyReportIfNoSigners() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - // No signers for this report - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](0); - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.NoSigners.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_failToVerifyReportIfDupSigners() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - // One signer is repeated - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](4); - signersSubset2[0] = signers[0]; - signersSubset2[1] = signers[1]; - // repeated signers - signersSubset2[2] = signers[2]; - signersSubset2[3] = signers[2]; - - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, signersSubset2); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_failToVerifyReportIfSignerNotInConfig() public { - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - // one report whose signer is not in the config - BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](4); - // these signers are part ofm the config - reportSigners[0] = signers[4]; - reportSigners[1] = signers[5]; - reportSigners[2] = signers[6]; - // this single signer is not in the config - reportSigners[3] = signers[7]; - - bytes memory signedReport = _generateV3EncodedBlob(s_testReportThree, s_reportContext, reportSigners); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_canVerifyOlderV3ReportsWithOlderConfigs() public { - /* - This test is checking we can use historical Configs to verify reports: - - DonConfigA has signers {A, B, C, E} is set at time T1 - - DonConfigB has signers {A, B, C, D} is set at time T2 - - checks we can verify a report with {B, C, D} signers (via DonConfigB) - - checks we can verify a report with {B, C, E} signers and timestamp below T2 (via DonConfigA historical config) - - checks we can't verify a report with {B, C, E} signers and timestamp above T2 (it gets verivied via DonConfigB) - - sets DonConfigA as deactivated - - checks we can't verify a report with {B, C, E} signers and timestamp below T2 (via DonConfigA) - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - // Config1 - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); - signersSubset2[0] = signers[0]; - signersSubset2[1] = signers[1]; - signersSubset2[2] = signers[2]; - signersSubset2[3] = signers[3]; - signersSubset2[4] = signers[4]; - signersSubset2[5] = signers[5]; - signersSubset2[6] = signers[29]; - address[] memory signersAddrSubset2 = _getSignerAddresses(signersSubset2); - - V3Report memory reportAtSetConfig1Timestmap = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - vm.warp(block.timestamp + 100); - - // Config2 - s_verifier.setConfig(signersAddrSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory reportAtSetConfig2Timestmap = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](5); - reportSigners[0] = signers[0]; - reportSigners[1] = signers[1]; - reportSigners[2] = signers[2]; - reportSigners[3] = signers[3]; - reportSigners[4] = signers[29]; - - bytes memory signedReport = _generateV3EncodedBlob(reportAtSetConfig2Timestmap, s_reportContext, reportSigners); - - // this report is verified via Config2 - bytes memory verifierResponse = s_verifierProxy.verify(signedReport, abi.encode(native)); - assertReportsEqual(verifierResponse, reportAtSetConfig2Timestmap); - - BaseTest.Signer[] memory reportSigners2 = new BaseTest.Signer[](5); - reportSigners2[0] = signers[0]; - reportSigners2[1] = signers[1]; - reportSigners2[2] = signers[2]; - reportSigners2[3] = signers[3]; - reportSigners2[4] = signers[6]; - - bytes memory signedReport2 = _generateV3EncodedBlob(reportAtSetConfig1Timestmap, s_reportContext, reportSigners2); - - // this report is verified via Config1 (using a historical config) - bytes memory verifierResponse2 = s_verifierProxy.verify(signedReport2, abi.encode(native)); - assertReportsEqual(verifierResponse2, reportAtSetConfig1Timestmap); - - // same report with same signers but with a higher timestamp gets verified via Config2 - // which means verification fails - bytes memory signedReport3 = _generateV3EncodedBlob(reportAtSetConfig2Timestmap, s_reportContext, reportSigners2); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport3, abi.encode(native)); - - // deactivating Config1 and trying a reverifications ends in failure - s_verifier.setConfigActive(0, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport2, abi.encode(native)); - } - - function test_revertsVerifyIfNoAccess() public { - vm.mockCall( - ACCESS_CONTROLLER_ADDRESS, - abi.encodeWithSelector(AccessControllerInterface.hasAccess.selector, USER), - abi.encode(false) - ); - bytes memory signedReport = _generateV3EncodedBlob( - s_testReportThree, - s_reportContext, - _getSigners(FAULT_TOLERANCE + 1) - ); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.AccessForbidden.selector)); - - changePrank(USER); - s_verifier.verify(signedReport, abi.encode(native), msg.sender); - } - - function test_canVerifyNewerReportsWithNewerConfigs() public { - /* - This test is checking that we use prefer verifiying via newer configs instead of old ones. - - DonConfigA has signers {A, B, C, E} is set at time T1 - - DonConfigB has signers {F, G, H, I} is set at time T2 - - DonConfigC has signers {J, K, L, M } is set at time T3 - - checks we can verify a report with {K, L, M} signers (via DonConfigC) - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - // Config1 - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 1); - - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); - signersSubset2[0] = signers[7]; - signersSubset2[1] = signers[8]; - signersSubset2[2] = signers[9]; - signersSubset2[3] = signers[10]; - signersSubset2[4] = signers[11]; - signersSubset2[5] = signers[12]; - signersSubset2[6] = signers[13]; - - address[] memory signersAddrSubset2 = _getSignerAddresses(signersSubset2); - // Config2 - s_verifier.setConfig(signersAddrSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 1); - - BaseTest.Signer[] memory signersSubset3 = new BaseTest.Signer[](7); - signersSubset3[0] = signers[30]; - signersSubset3[1] = signers[29]; - signersSubset3[2] = signers[28]; - signersSubset3[3] = signers[27]; - signersSubset3[4] = signers[26]; - signersSubset3[5] = signers[25]; - signersSubset3[6] = signers[24]; - - address[] memory signersAddrSubset3 = _getSignerAddresses(signersSubset3); - // Config3 - s_verifier.setConfig(signersAddrSubset3, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 1); - - V3Report memory report = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSigners = new BaseTest.Signer[](3); - reportSigners[0] = signers[30]; - reportSigners[1] = signers[29]; - reportSigners[2] = signers[28]; - - bytes memory signedReport = _generateV3EncodedBlob(report, s_reportContext, reportSigners); - - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_rollingOutConfiguration() public { - /* - This test is checking that we can roll out to a new DON without downtime using a transition configuration - - DonConfigA has signers {A, B, C} is set at time T1 - - DonConfigB (transition config) has signers {A, B, C, D, E, F} is set at time T2 - - DonConfigC has signers {D, E, F} is set at time T3 - - - checks we can verify a report with {A, B, C} signers (via DonConfigA) at time between T1 and T2 - - checks we can verify a report with {A, B, C} signers (via DonConfigB) at time between T2 and T3 - - checks we can verify a report with {D, E, F} signers (via DonConfigB) at time between T2 and T3 - - checks we can verify a report with {D, E, F} signers (via DonConfigC) at time > T3 - - checks we can't verify a report with {A, B, C} signers (via DonConfigC) and timestamp >T3 at time > T3 - - checks we can verify a report with {A, B, C} signers (via DonConfigC) and timestamp between T2 and T3 at time > T3 (historical check) - - */ - - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersSubset1 = new BaseTest.Signer[](7); - signersSubset1[0] = signers[0]; - signersSubset1[1] = signers[1]; - signersSubset1[2] = signers[2]; - signersSubset1[3] = signers[3]; - signersSubset1[4] = signers[4]; - signersSubset1[5] = signers[5]; - signersSubset1[6] = signers[6]; - - // ConfigA - address[] memory signersAddrSubset1 = _getSignerAddresses(signersSubset1); - s_verifier.setConfig(signersAddrSubset1, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory reportT1 = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSignersConfigA = new BaseTest.Signer[](3); - reportSignersConfigA[0] = signers[0]; - reportSignersConfigA[1] = signers[1]; - reportSignersConfigA[2] = signers[2]; - - // just testing ConfigA - bytes memory signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); - s_verifierProxy.verify(signedReport, abi.encode(native)); - - vm.warp(block.timestamp + 100); - - BaseTest.Signer[] memory signersSuperset = new BaseTest.Signer[](14); - // signers in ConfigA - signersSuperset[0] = signers[0]; - signersSuperset[1] = signers[1]; - signersSuperset[2] = signers[2]; - signersSuperset[3] = signers[3]; - signersSuperset[4] = signers[4]; - signersSuperset[5] = signers[5]; - signersSuperset[6] = signers[6]; - // new signers - signersSuperset[7] = signers[7]; - signersSuperset[8] = signers[8]; - signersSuperset[9] = signers[9]; - signersSuperset[10] = signers[10]; - signersSuperset[11] = signers[11]; - signersSuperset[12] = signers[12]; - signersSuperset[13] = signers[13]; - - BaseTest.Signer[] memory reportSignersConfigC = new BaseTest.Signer[](3); - reportSignersConfigC[0] = signers[7]; - reportSignersConfigC[1] = signers[8]; - reportSignersConfigC[2] = signers[9]; - - // ConfigB (transition Config) - address[] memory signersAddrsSuperset = _getSignerAddresses(signersSuperset); - s_verifier.setConfig(signersAddrsSuperset, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory reportT2 = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - // testing we can verify a fresh (block timestamp) report with ConfigA signers. This should use ConfigB - signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigA); - s_verifierProxy.verify(signedReport, abi.encode(native)); - - // testing we can verify an old ( non fresh block timestamp) report with ConfigA signers. This should use ConfigA - signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); - s_verifierProxy.verify(signedReport, abi.encode(native)); - // deactivating to make sure we are really verifiying via ConfigA - s_verifier.setConfigActive(0, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - s_verifier.setConfigActive(0, true); - - // testing we can verify a fresh (block timestamp) report with the new signers. This should use ConfigB - signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigC); - s_verifierProxy.verify(signedReport, abi.encode(native)); - - vm.warp(block.timestamp + 100); - - // Adding ConfigC - BaseTest.Signer[] memory signersSubset2 = new BaseTest.Signer[](7); - signersSubset2[0] = signers[7]; - signersSubset2[1] = signers[8]; - signersSubset2[2] = signers[9]; - signersSubset2[3] = signers[10]; - signersSubset2[4] = signers[11]; - signersSubset2[5] = signers[12]; - signersSubset2[6] = signers[13]; - address[] memory signersAddrsSubset2 = _getSignerAddresses(signersSubset2); - s_verifier.setConfig(signersAddrsSubset2, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - V3Report memory reportT3 = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - // testing we can verify reports with ConfigC signers - signedReport = _generateV3EncodedBlob(reportT3, s_reportContext, reportSignersConfigC); - s_verifierProxy.verify(signedReport, abi.encode(native)); - - // testing an old report (block timestamp) with ConfigC signers should verify via ConfigB - signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigC); - s_verifierProxy.verify(signedReport, abi.encode(native)); - // deactivating to make sure we are really verifiying via ConfigB - s_verifier.setConfigActive(1, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - s_verifier.setConfigActive(1, true); - - // testing a recent report with ConfigA signers should not verify - signedReport = _generateV3EncodedBlob(reportT3, s_reportContext, reportSignersConfigA); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - - // testing an old report (block timestamp) with ConfigA signers should verify via ConfigB - signedReport = _generateV3EncodedBlob(reportT2, s_reportContext, reportSignersConfigA); - s_verifierProxy.verify(signedReport, abi.encode(native)); - // deactivating to make sure we are really verifiying via ConfigB - s_verifier.setConfigActive(1, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - s_verifier.setConfigActive(1, true); - - // testing an old report (block timestamp) with ConfigA signers should verify via ConfigA - signedReport = _generateV3EncodedBlob(reportT1, s_reportContext, reportSignersConfigA); - s_verifierProxy.verify(signedReport, abi.encode(native)); - // deactivating to make sure we are really verifiying via ConfigB - s_verifier.setConfigActive(0, false); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - s_verifier.setConfigActive(0, true); - } - - function test_verifyFailsWhenReportIsOlderThanConfig() public { - /* - - SetConfig A at time T0 - - SetConfig B at time T1 - - tries verifing report issued at blocktimestmap < T0 - - this test is failing: ToDo Ask Michael - */ - Signer[] memory signers = _getSigners(MAX_ORACLES); - address[] memory signerAddrs = _getSignerAddresses(signers); - s_reportContext[0] = bytes32(abi.encode(uint32(5), uint8(1))); - - vm.warp(block.timestamp + 100); - - V3Report memory reportAtTMinus100 = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp - 100), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - vm.warp(block.timestamp + 100); - s_verifier.setConfig(signerAddrs, FAULT_TOLERANCE - 1, new Common.AddressAndWeight[](0)); - - bytes memory signedReport = _generateV3EncodedBlob(reportAtTMinus100, s_reportContext, signers); - - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedReport, abi.encode(native)); - } - - function test_scenarioRollingNewChainWithHistoricConfigs() public { - /* - This test is checking that we can roll out in a new network and set historic configurations : - - Stars with a chain at blocktimestamp 1000 - - SetConfigA with teimstamp 100 - - SetConfigB with timesmtap 200 - - SetConfigC with timestamp current - - tries verifying reports for all the configs - */ - - vm.warp(block.timestamp + 1000); - - Signer[] memory signers = _getSigners(MAX_ORACLES); - - uint8 MINIMAL_FAULT_TOLERANCE = 2; - BaseTest.Signer[] memory signersA = new BaseTest.Signer[](7); - signersA[0] = signers[0]; - signersA[1] = signers[1]; - signersA[2] = signers[2]; - signersA[3] = signers[3]; - signersA[4] = signers[4]; - signersA[5] = signers[5]; - signersA[6] = signers[6]; - - // ConfigA (historical config) - uint32 configATimestmap = 100; - address[] memory signersAddrA = _getSignerAddresses(signersA); - s_verifier.setConfigWithActivationTime( - signersAddrA, - MINIMAL_FAULT_TOLERANCE, - new Common.AddressAndWeight[](0), - configATimestmap - ); - - // ConfigB (historical config) - uint32 configBTimestmap = 200; - // Config B - BaseTest.Signer[] memory signersB = new BaseTest.Signer[](7); - // signers in ConfigA - signersB[0] = signers[8]; - signersB[1] = signers[9]; - signersB[2] = signers[10]; - signersB[3] = signers[11]; - signersB[4] = signers[12]; - signersB[5] = signers[13]; - signersB[6] = signers[14]; - address[] memory signersAddrsB = _getSignerAddresses(signersB); - s_verifier.setConfigWithActivationTime( - signersAddrsB, - MINIMAL_FAULT_TOLERANCE, - new Common.AddressAndWeight[](0), - configBTimestmap - ); - - // ConfigC (config at current timestamp) - // BaseTest.Signer[] memory signersC = new BaseTest.Signer[](7); - // signers in ConfigA - signersB[6] = signers[15]; - address[] memory signersAddrsC = _getSignerAddresses(signersB); - s_verifier.setConfig(signersAddrsC, MINIMAL_FAULT_TOLERANCE, new Common.AddressAndWeight[](0)); - - vm.warp(block.timestamp + 10); - - // historical report - V3Report memory s_testReportA = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(101), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp + 1000), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - // historical report - V3Report memory s_testReportB = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(201), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp + 1000), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - // report at recent timestamp - V3Report memory s_testReportC = V3Report({ - feedId: FEED_ID_V3, - observationsTimestamp: OBSERVATIONS_TIMESTAMP, - validFromTimestamp: uint32(block.timestamp), - nativeFee: uint192(DEFAULT_REPORT_NATIVE_FEE), - linkFee: uint192(DEFAULT_REPORT_LINK_FEE), - expiresAt: uint32(block.timestamp + 1000), - benchmarkPrice: MEDIAN, - bid: BID, - ask: ASK - }); - - BaseTest.Signer[] memory reportSignersA = new BaseTest.Signer[](3); - reportSignersA[0] = signers[0]; - reportSignersA[1] = signers[1]; - reportSignersA[2] = signers[2]; - - BaseTest.Signer[] memory reportSignersB = new BaseTest.Signer[](3); - reportSignersB[0] = signers[8]; - reportSignersB[1] = signers[9]; - reportSignersB[2] = signers[14]; - - BaseTest.Signer[] memory reportSignersC = new BaseTest.Signer[](3); - reportSignersC[0] = signers[15]; - reportSignersC[1] = signers[13]; - reportSignersC[2] = signers[12]; - - bytes memory signedReportA = _generateV3EncodedBlob(s_testReportA, s_reportContext, reportSignersA); - bytes memory signedReportB = _generateV3EncodedBlob(s_testReportB, s_reportContext, reportSignersB); - bytes memory signedReportC = _generateV3EncodedBlob(s_testReportC, s_reportContext, reportSignersC); - - // verifying historical reports - s_verifierProxy.verify(signedReportA, abi.encode(native)); - s_verifierProxy.verify(signedReportB, abi.encode(native)); - // verifiying a current report - s_verifierProxy.verify(signedReportC, abi.encode(native)); - - // current report verified by historical report fails - bytes memory signedNewReportWithOldSignatures = _generateV3EncodedBlob( - s_testReportC, - s_reportContext, - reportSignersA - ); - vm.expectRevert(abi.encodeWithSelector(DestinationVerifier.BadVerification.selector)); - s_verifierProxy.verify(signedNewReportWithOldSignatures, abi.encode(native)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol deleted file mode 100644 index f5e5040..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/ChannelConfigStore.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {IChannelConfigStore} from "./interfaces/IChannelConfigStore.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; - -contract ChannelConfigStore is ConfirmedOwner, IChannelConfigStore, TypeAndVersionInterface { - event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); - - constructor() ConfirmedOwner(msg.sender) {} - - /// @notice The version of a channel definition keyed by DON ID - // Increments by 1 on every update - mapping(uint256 => uint256) internal s_channelDefinitionVersions; - - function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external onlyOwner { - uint32 newVersion = uint32(++s_channelDefinitionVersions[uint256(donId)]); - emit NewChannelDefinition(donId, newVersion, url, sha); - } - - function typeAndVersion() external pure override returns (string memory) { - return "ChannelConfigStore 0.0.1"; - } - - function supportsInterface(bytes4 interfaceId) external pure returns (bool) { - return interfaceId == type(IChannelConfigStore).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol deleted file mode 100644 index 5945f7a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol +++ /dev/null @@ -1,188 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -import {IConfigurator} from "../../interfaces/IConfigurator.sol"; - -// OCR2 standard -uint256 constant MAX_NUM_ORACLES = 31; - -/** - * @title Configurator - * @author samsondav - * @notice This contract is intended to be deployed on the source chain and acts as a OCR3 configurator for LLO/Mercury - **/ - -contract Configurator is IConfigurator, ConfirmedOwner, TypeAndVersionInterface, IERC165 { - /// @notice This error is thrown whenever trying to set a config - /// with a fault tolerance of 0 - error FaultToleranceMustBePositive(); - - /// @notice This error is thrown whenever a report is signed - /// with more than the max number of signers - /// @param numSigners The number of signers who have signed the report - /// @param maxSigners The maximum number of signers that can sign a report - error ExcessSigners(uint256 numSigners, uint256 maxSigners); - - /// @notice This error is thrown whenever a report is signed - /// with less than the minimum number of signers - /// @param numSigners The number of signers who have signed the report - /// @param minSigners The minimum number of signers that need to sign a report - error InsufficientSigners(uint256 numSigners, uint256 minSigners); - - struct ConfigurationState { - // The number of times a new configuration - // has been set - uint64 configCount; - // The block number of the block the last time - /// the configuration was updated. - uint32 latestConfigBlockNumber; - } - - constructor() ConfirmedOwner(msg.sender) {} - - /// @notice Configuration states keyed on DON ID - mapping(bytes32 => ConfigurationState) internal s_configurationStates; - - /// @inheritdoc IConfigurator - function setConfig( - bytes32 donId, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external override checkConfigValid(signers.length, f) onlyOwner { - _setConfig( - donId, - block.chainid, - address(this), - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - } - - /// @notice Sets config based on the given arguments - /// @param donId DON ID to set config for - /// @param sourceChainId Chain ID of source config - /// @param sourceAddress Address of source config Verifier - /// @param signers addresses with which oracles sign the reports - /// @param offchainTransmitters CSA key for the ith Oracle - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - function _setConfig( - bytes32 donId, - uint256 sourceChainId, - address sourceAddress, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal { - ConfigurationState storage configurationState = s_configurationStates[donId]; - - uint64 newConfigCount = ++configurationState.configCount; - - bytes32 configDigest = _configDigestFromConfigData( - donId, - sourceChainId, - sourceAddress, - newConfigCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - emit ConfigSet( - donId, - configurationState.latestConfigBlockNumber, - configDigest, - newConfigCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ); - - configurationState.latestConfigBlockNumber = uint32(block.number); - } - - /// @notice Generates the config digest from config data - /// @param donId DON ID to set config for - /// @param sourceChainId Chain ID of configurator contract - /// @param sourceAddress Address of configurator contract - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param offchainTransmitters ith element is address ith oracle used to transmit reports (in this case used for flexible additional field, such as CSA pub keys) - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - /// @dev This function is a modified version of the method from OCR2Abstract - function _configDigestFromConfigData( - bytes32 donId, - uint256 sourceChainId, - address sourceAddress, - uint64 configCount, - address[] memory signers, - bytes32[] memory offchainTransmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - donId, - sourceChainId, - sourceAddress, - configCount, - signers, - offchainTransmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 - // 0x0006 corresponds to ConfigDigestPrefixLLO in libocr - uint256 prefix = 0x0009 << (256 - 16); // 0x000900..00 - return bytes32((prefix & prefixMask) | (h & ~prefixMask)); - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) external pure override returns (bool isVerifier) { - return interfaceId == type(IConfigurator).interfaceId; - } - - /// @inheritdoc TypeAndVersionInterface - function typeAndVersion() external pure override returns (string memory) { - return "Configurator 0.4.0"; - } - - modifier checkConfigValid(uint256 numSigners, uint256 f) { - if (f == 0) revert FaultToleranceMustBePositive(); - if (numSigners > MAX_NUM_ORACLES) revert ExcessSigners(numSigners, MAX_NUM_ORACLES); - if (numSigners <= 3 * f) revert InsufficientSigners(numSigners, 3 * f + 1); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol deleted file mode 100644 index 8628e3c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/interfaces/IChannelConfigStore.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; - -interface IChannelConfigStore is IERC165 { - function setChannelDefinitions(uint32 donId, string calldata url, bytes32 sha) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol deleted file mode 100644 index 70b033e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/ChannelConfigStore.t.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.19; - -import {IChannelConfigStore} from "../interfaces/IChannelConfigStore.sol"; -import {Test} from "forge-std/Test.sol"; -import {ChannelConfigStore} from "../ChannelConfigStore.sol"; -import {ExposedChannelConfigStore} from "./mocks/ExposedChannelConfigStore.sol"; - -/** - * @title ChannelConfigStoreTest - * @author samsondav - * @notice Base class for ChannelConfigStore tests - */ -contract ChannelConfigStoreTest is Test { - ExposedChannelConfigStore public channelConfigStore; - event NewChannelDefinition(uint256 indexed donId, uint32 version, string url, bytes32 sha); - - function setUp() public virtual { - channelConfigStore = new ExposedChannelConfigStore(); - } - - function testTypeAndVersion() public view { - assertEq(channelConfigStore.typeAndVersion(), "ChannelConfigStore 0.0.1"); - } - - function testSupportsInterface() public view { - assertTrue(channelConfigStore.supportsInterface(type(IChannelConfigStore).interfaceId)); - } - - function testSetChannelDefinitions() public { - vm.expectEmit(); - emit NewChannelDefinition(42, 1, "url", keccak256("sha")); - channelConfigStore.setChannelDefinitions(42, "url", keccak256("sha")); - - vm.expectEmit(); - emit NewChannelDefinition(42, 2, "url2", keccak256("sha2")); - channelConfigStore.setChannelDefinitions(42, "url2", keccak256("sha2")); - - assertEq(channelConfigStore.exposedReadChannelDefinitionStates(42), uint32(2)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol deleted file mode 100644 index 1ffd512..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedChannelConfigStore.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ChannelConfigStore} from "../../ChannelConfigStore.sol"; - -// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore -// methods/structures so that golang code can access them, and we get -// reliable type checking on their usage -contract ExposedChannelConfigStore is ChannelConfigStore { - constructor() {} - - function exposedReadChannelDefinitionStates(uint256 donId) public view returns (uint256) { - return s_channelDefinitionVersions[donId]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol deleted file mode 100644 index 7b1370a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/mocks/ExposedConfigurator.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Configurator} from "../../Configurator.sol"; - -// Exposed ChannelConfigStore exposes certain internal ChannelConfigStore -// methods/structures so that golang code can access them, and we get -// reliable type checking on their usage -contract ExposedConfigurator is Configurator { - constructor() {} - - function exposedReadConfigurationStates(bytes32 donId) public view returns (ConfigurationState memory) { - return s_configurationStates[donId]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol deleted file mode 100644 index 753ba91..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsBillingRegistryEventsMock.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -// Warning: this is an autogenerated file! DO NOT EDIT. - -pragma solidity ^0.8.6; - -contract FunctionsBillingRegistryEventsMock { - struct Commitment {uint64 subscriptionId;address client;uint32 gasLimit;uint256 gasPrice;address don;uint96 donFee;uint96 registryFee;uint96 estimatedCost;uint256 timestamp; } - event AuthorizedSendersChanged(address[] senders,address changedBy); - event BillingEnd(bytes32 indexed requestId,uint64 subscriptionId,uint96 signerPayment,uint96 transmitterPayment,uint96 totalCost,bool success); - event BillingStart(bytes32 indexed requestId,Commitment commitment); - event ConfigSet(uint32 maxGasLimit,uint32 stalenessSeconds,uint256 gasAfterPaymentCalculation,int256 fallbackWeiPerUnitLink,uint32 gasOverhead); - event FundsRecovered(address to,uint256 amount); - event Initialized(uint8 version); - event OwnershipTransferRequested(address indexed from,address indexed to); - event OwnershipTransferred(address indexed from,address indexed to); - event Paused(address account); - event RequestTimedOut(bytes32 indexed requestId); - event SubscriptionCanceled(uint64 indexed subscriptionId,address to,uint256 amount); - event SubscriptionConsumerAdded(uint64 indexed subscriptionId,address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subscriptionId,address consumer); - event SubscriptionCreated(uint64 indexed subscriptionId,address owner); - event SubscriptionFunded(uint64 indexed subscriptionId,uint256 oldBalance,uint256 newBalance); - event SubscriptionOwnerTransferRequested(uint64 indexed subscriptionId,address from,address to); - event SubscriptionOwnerTransferred(uint64 indexed subscriptionId,address from,address to); - event Unpaused(address account); - function emitAuthorizedSendersChanged(address[] memory senders,address changedBy) public { - emit AuthorizedSendersChanged(senders,changedBy); - } - function emitBillingEnd(bytes32 requestId,uint64 subscriptionId,uint96 signerPayment,uint96 transmitterPayment,uint96 totalCost,bool success) public { - emit BillingEnd(requestId,subscriptionId,signerPayment,transmitterPayment,totalCost,success); - } - function emitBillingStart(bytes32 requestId,Commitment memory commitment) public { - emit BillingStart(requestId,commitment); - } - function emitConfigSet(uint32 maxGasLimit,uint32 stalenessSeconds,uint256 gasAfterPaymentCalculation,int256 fallbackWeiPerUnitLink,uint32 gasOverhead) public { - emit ConfigSet(maxGasLimit,stalenessSeconds,gasAfterPaymentCalculation,fallbackWeiPerUnitLink,gasOverhead); - } - function emitFundsRecovered(address to,uint256 amount) public { - emit FundsRecovered(to,amount); - } - function emitInitialized(uint8 version) public { - emit Initialized(version); - } - function emitOwnershipTransferRequested(address from,address to) public { - emit OwnershipTransferRequested(from,to); - } - function emitOwnershipTransferred(address from,address to) public { - emit OwnershipTransferred(from,to); - } - function emitPaused(address account) public { - emit Paused(account); - } - function emitRequestTimedOut(bytes32 requestId) public { - emit RequestTimedOut(requestId); - } - function emitSubscriptionCanceled(uint64 subscriptionId,address to,uint256 amount) public { - emit SubscriptionCanceled(subscriptionId,to,amount); - } - function emitSubscriptionConsumerAdded(uint64 subscriptionId,address consumer) public { - emit SubscriptionConsumerAdded(subscriptionId,consumer); - } - function emitSubscriptionConsumerRemoved(uint64 subscriptionId,address consumer) public { - emit SubscriptionConsumerRemoved(subscriptionId,consumer); - } - function emitSubscriptionCreated(uint64 subscriptionId,address owner) public { - emit SubscriptionCreated(subscriptionId,owner); - } - function emitSubscriptionFunded(uint64 subscriptionId,uint256 oldBalance,uint256 newBalance) public { - emit SubscriptionFunded(subscriptionId,oldBalance,newBalance); - } - function emitSubscriptionOwnerTransferRequested(uint64 subscriptionId,address from,address to) public { - emit SubscriptionOwnerTransferRequested(subscriptionId,from,to); - } - function emitSubscriptionOwnerTransferred(uint64 subscriptionId,address from,address to) public { - emit SubscriptionOwnerTransferred(subscriptionId,from,to); - } - function emitUnpaused(address account) public { - emit Unpaused(account); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol deleted file mode 100644 index c68de7f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/FunctionsOracleEventsMock.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -// Warning: this is an autogenerated file! DO NOT EDIT. - -pragma solidity ^0.8.6; - -contract FunctionsOracleEventsMock { - event AuthorizedSendersActive(address account); - event AuthorizedSendersChanged(address[] senders,address changedBy); - event AuthorizedSendersDeactive(address account); - event ConfigSet(uint32 previousConfigBlockNumber,bytes32 configDigest,uint64 configCount,address[] signers,address[] transmitters,uint8 f,bytes onchainConfig,uint64 offchainConfigVersion,bytes offchainConfig); - event Initialized(uint8 version); - event InvalidRequestID(bytes32 indexed requestId); - event OracleRequest(bytes32 indexed requestId,address requestingContract,address requestInitiator,uint64 subscriptionId,address subscriptionOwner,bytes data); - event OracleResponse(bytes32 indexed requestId); - event OwnershipTransferRequested(address indexed from,address indexed to); - event OwnershipTransferred(address indexed from,address indexed to); - event ResponseTransmitted(bytes32 indexed requestId,address transmitter); - event Transmitted(bytes32 configDigest,uint32 epoch); - event UserCallbackError(bytes32 indexed requestId,string reason); - event UserCallbackRawError(bytes32 indexed requestId,bytes lowLevelData); - function emitAuthorizedSendersActive(address account) public { - emit AuthorizedSendersActive(account); - } - function emitAuthorizedSendersChanged(address[] memory senders,address changedBy) public { - emit AuthorizedSendersChanged(senders,changedBy); - } - function emitAuthorizedSendersDeactive(address account) public { - emit AuthorizedSendersDeactive(account); - } - function emitConfigSet(uint32 previousConfigBlockNumber,bytes32 configDigest,uint64 configCount,address[] memory signers,address[] memory transmitters,uint8 f,bytes memory onchainConfig,uint64 offchainConfigVersion,bytes memory offchainConfig) public { - emit ConfigSet(previousConfigBlockNumber,configDigest,configCount,signers,transmitters,f,onchainConfig,offchainConfigVersion,offchainConfig); - } - function emitInitialized(uint8 version) public { - emit Initialized(version); - } - function emitInvalidRequestID(bytes32 requestId) public { - emit InvalidRequestID(requestId); - } - function emitOracleRequest(bytes32 requestId,address requestingContract,address requestInitiator,uint64 subscriptionId,address subscriptionOwner,bytes memory data) public { - emit OracleRequest(requestId,requestingContract,requestInitiator,subscriptionId,subscriptionOwner,data); - } - function emitOracleResponse(bytes32 requestId) public { - emit OracleResponse(requestId); - } - function emitOwnershipTransferRequested(address from,address to) public { - emit OwnershipTransferRequested(from,to); - } - function emitOwnershipTransferred(address from,address to) public { - emit OwnershipTransferred(from,to); - } - function emitResponseTransmitted(bytes32 requestId,address transmitter) public { - emit ResponseTransmitted(requestId,transmitter); - } - function emitTransmitted(bytes32 configDigest,uint32 epoch) public { - emit Transmitted(configDigest,epoch); - } - function emitUserCallbackError(bytes32 requestId,string memory reason) public { - emit UserCallbackError(requestId,reason); - } - function emitUserCallbackRawError(bytes32 requestId,bytes memory lowLevelData) public { - emit UserCallbackRawError(requestId,lowLevelData); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol deleted file mode 100644 index bdc935c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockAggregatorValidator.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../shared/interfaces/AggregatorValidatorInterface.sol"; - -contract MockAggregatorValidator is AggregatorValidatorInterface { - uint8 immutable id; - - constructor(uint8 id_) { - id = id_; - } - - event ValidateCalled( - uint8 id, - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ); - - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external override returns (bool) { - emit ValidateCalled(id, previousRoundId, previousAnswer, currentRoundId, currentAnswer); - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol deleted file mode 100644 index fbfdf0f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockArbSys.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -/** - * @dev this contract mocks the arbitrum precompiled ArbSys contract - * https://developer.arbitrum.io/arbos/precompiles#ArbSys - */ -contract MockArbSys { - function arbBlockNumber() public view returns (uint256) { - return block.number; - } - - function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32) { - return blockhash(arbBlockNum); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol deleted file mode 100644 index a68f1b1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockLinkToken.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; - -contract MockLinkToken { - uint256 private constant TOTAL_SUPPLY = 1_000_000_000 * 1e18; - - constructor() { - balances[msg.sender] = TOTAL_SUPPLY; - } - - mapping(address => uint256) public balances; - - function totalSupply() external pure returns (uint256 totalTokensIssued) { - return TOTAL_SUPPLY; // 1 billion LINK -> 1e27 Juels - } - - function transfer(address _to, uint256 _value) public returns (bool) { - balances[msg.sender] = balances[msg.sender] - _value; - balances[_to] = balances[_to] + _value; - return true; - } - - function setBalance(address _address, uint256 _value) external returns (bool) { - balances[_address] = _value; - return true; - } - - function balanceOf(address _address) external view returns (uint256) { - return balances[_address]; - } - - function transferAndCall(address _to, uint256 _value, bytes calldata _data) public returns (bool success) { - transfer(_to, _value); - if (isContract(_to)) { - contractFallback(_to, _value, _data); - } - return true; - } - - function isContract(address _addr) private view returns (bool hasCode) { - uint256 length; - assembly { - length := extcodesize(_addr) - } - return length > 0; - } - - function contractFallback(address _to, uint256 _value, bytes calldata _data) private { - IERC677Receiver receiver = IERC677Receiver(_to); - receiver.onTokenTransfer(msg.sender, _value, _data); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol deleted file mode 100644 index 5366bbe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/mocks/MockOffchainAggregator.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -contract MockOffchainAggregator { - event RoundIdUpdated(uint80 roundId); - - uint80 public roundId; - - function requestNewRound() external returns (uint80) { - roundId++; - emit RoundIdUpdated(roundId); - return roundId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol deleted file mode 100644 index ffb0924..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedForwarder.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwnerWithProposal} from "../shared/access/ConfirmedOwnerWithProposal.sol"; -import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; - -// solhint-disable gas-custom-errors -contract AuthorizedForwarder is ConfirmedOwnerWithProposal, AuthorizedReceiver { - using Address for address; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable linkToken; - - event OwnershipTransferRequestedWithMessage(address indexed from, address indexed to, bytes message); - - constructor( - address link, - address owner, - address recipient, - bytes memory message - ) ConfirmedOwnerWithProposal(owner, recipient) { - require(link != address(0), "Link token cannot be a zero address"); - linkToken = link; - if (recipient != address(0)) { - emit OwnershipTransferRequestedWithMessage(owner, recipient, message); - } - } - - string public constant typeAndVersion = "AuthorizedForwarder 1.1.0"; - - // @notice Forward a call to another contract - // @dev Only callable by an authorized sender - // @param to address - // @param data to forward - function forward(address to, bytes calldata data) external validateAuthorizedSender { - require(to != linkToken, "Cannot forward to Link token"); - _forward(to, data); - } - - // @notice Forward multiple calls to other contracts in a multicall style - // @dev Only callable by an authorized sender - // @param tos An array of addresses to forward the calls to - // @param datas An array of data to forward to each corresponding address - function multiForward(address[] calldata tos, bytes[] calldata datas) external validateAuthorizedSender { - require(tos.length == datas.length, "Arrays must have the same length"); - - for (uint256 i = 0; i < tos.length; ++i) { - address to = tos[i]; - require(to != linkToken, "Cannot forward to Link token"); - - // Perform the forward operation - _forward(to, datas[i]); - } - } - - // @notice Forward a call to another contract - // @dev Only callable by the owner - // @param to address - // @param data to forward - function ownerForward(address to, bytes calldata data) external onlyOwner { - _forward(to, data); - } - - // @notice Transfer ownership with instructions for recipient - // @param to address proposed recipient of ownership - // @param message instructions for recipient upon accepting ownership - function transferOwnershipWithMessage(address to, bytes calldata message) external { - transferOwnership(to); - emit OwnershipTransferRequestedWithMessage(msg.sender, to, message); - } - - // @notice concrete implementation of AuthorizedReceiver - // @return bool of whether sender is authorized - function _canSetAuthorizedSenders() internal view override returns (bool) { - return owner() == msg.sender; - } - - // @notice common forwarding functionality and validation - function _forward(address to, bytes calldata data) private { - require(to.isContract(), "Must forward to a contract"); - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory result) = to.call(data); - if (!success) { - if (result.length == 0) revert("Forwarded call reverted without reason"); - assembly { - revert(add(32, result), mload(result)) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol deleted file mode 100644 index 919602b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/AuthorizedReceiver.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; - -// solhint-disable gas-custom-errors -abstract contract AuthorizedReceiver is IAuthorizedReceiver { - mapping(address sender => bool authorized) private s_authorizedSenders; - address[] private s_authorizedSenderList; - - event AuthorizedSendersChanged(address[] senders, address changedBy); - - // @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. - // @param senders The addresses of the authorized Chainlink node - function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter { - require(senders.length > 0, "Must have at least 1 sender"); - // Set previous authorized senders to false - uint256 authorizedSendersLength = s_authorizedSenderList.length; - for (uint256 i = 0; i < authorizedSendersLength; ++i) { - s_authorizedSenders[s_authorizedSenderList[i]] = false; - } - // Set new to true - for (uint256 i = 0; i < senders.length; ++i) { - require(s_authorizedSenders[senders[i]] == false, "Must not have duplicate senders"); - s_authorizedSenders[senders[i]] = true; - } - // Replace list - s_authorizedSenderList = senders; - emit AuthorizedSendersChanged(senders, msg.sender); - } - - // @notice Retrieve a list of authorized senders - // @return array of addresses - function getAuthorizedSenders() external view override returns (address[] memory) { - return s_authorizedSenderList; - } - - // @notice Use this to check if a node is authorized for fulfilling requests - // @param sender The address of the Chainlink node - // @return The authorization status of the node - function isAuthorizedSender(address sender) public view override returns (bool) { - return s_authorizedSenders[sender]; - } - - // @notice customizable guard of who can update the authorized sender list - // @return bool whether sender can update authorized sender list - function _canSetAuthorizedSenders() internal virtual returns (bool); - - // @notice validates the sender is an authorized sender - function _validateIsAuthorizedSender() internal view { - require(isAuthorizedSender(msg.sender), "Not authorized sender"); - } - - // @notice prevents non-authorized addresses from calling this method - modifier validateAuthorizedSender() { - _validateIsAuthorizedSender(); - _; - } - - // @notice prevents non-authorized addresses from calling this method - modifier validateAuthorizedSenderSetter() { - require(_canSetAuthorizedSenders(), "Cannot set authorized senders"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol deleted file mode 100644 index dab259c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/LinkTokenReceiver.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -// solhint-disable gas-custom-errors -abstract contract LinkTokenReceiver { - // @notice Called when LINK is sent to the contract via `transferAndCall` - // @dev The data payload's first 2 words will be overwritten by the `sender` and `amount` - // values to ensure correctness. Calls oracleRequest. - // @param sender Address of the sender - // @param amount Amount of LINK sent (specified in wei) - // @param data Payload of the transaction - function onTokenTransfer( - address sender, - uint256 amount, - bytes memory data - ) public validateFromLINK permittedFunctionsForLINK(data) { - assembly { - // solhint-disable-next-line avoid-low-level-calls - mstore(add(data, 36), sender) // ensure correct sender is passed - // solhint-disable-next-line avoid-low-level-calls - mstore(add(data, 68), amount) // ensure correct amount is passed0.8.19 - } - // solhint-disable-next-line avoid-low-level-calls - (bool success, ) = address(this).delegatecall(data); // calls oracleRequest - require(success, "Unable to create request"); - } - - function getChainlinkToken() public view virtual returns (address); - - // @notice Validate the function called on token transfer - function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal virtual; - - // @dev Reverts if not sent from the LINK token - modifier validateFromLINK() { - require(msg.sender == getChainlinkToken(), "Must use LINK token"); - _; - } - - // @dev Reverts if the given data does not begin with the `oracleRequest` function selector - // @param data The data payload of the request - modifier permittedFunctionsForLINK(bytes memory data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(data, 32)) - } - _validateTokenTransferAction(funcSelector, data); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol deleted file mode 100644 index 64882e4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/Operator.sol +++ /dev/null @@ -1,497 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; -import {LinkTokenReceiver} from "./LinkTokenReceiver.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; -import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; -import {OperatorInterface} from "../interfaces/OperatorInterface.sol"; -import {IOwnable} from "../shared/interfaces/IOwnable.sol"; -import {IWithdrawal} from "./interfaces/IWithdrawal.sol"; -import {OracleInterface} from "../interfaces/OracleInterface.sol"; -import {SafeCast} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; - -// @title The Chainlink Operator contract -// @notice Node operators can deploy this contract to fulfill requests sent to them -// solhint-disable gas-custom-errors -contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, IWithdrawal { - struct Commitment { - bytes31 paramsHash; - uint8 dataVersion; - } - - uint256 public constant EXPIRYTIME = 5 minutes; - uint256 private constant MAXIMUM_DATA_VERSION = 256; - uint256 private constant MINIMUM_CONSUMER_GAS_LIMIT = 400000; - uint256 private constant SELECTOR_LENGTH = 4; - uint256 private constant EXPECTED_REQUEST_WORDS = 2; - uint256 private constant MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS); - // We initialize fields to 1 instead of 0 so that the first invocation - // does not cost more gas. - uint256 private constant ONE_FOR_CONSISTENT_GAS_COST = 1; - // oracleRequest is intended for version 1, enabling single word responses - bytes4 private constant ORACLE_REQUEST_SELECTOR = this.oracleRequest.selector; - // operatorRequest is intended for version 2, enabling multi-word responses - bytes4 private constant OPERATOR_REQUEST_SELECTOR = this.operatorRequest.selector; - - LinkTokenInterface internal immutable i_linkToken; - mapping(bytes32 => Commitment) private s_commitments; - mapping(address => bool) private s_owned; - // Tokens sent for requests that have not been fulfilled yet - uint256 private s_tokensInEscrow = ONE_FOR_CONSISTENT_GAS_COST; - - event OracleRequest( - bytes32 indexed specId, - address requester, - bytes32 requestId, - uint256 payment, - address callbackAddr, - bytes4 callbackFunctionId, - uint256 cancelExpiration, - uint256 dataVersion, - bytes data - ); - - event CancelOracleRequest(bytes32 indexed requestId); - - event OracleResponse(bytes32 indexed requestId); - - event OwnableContractAccepted(address indexed acceptedContract); - - event TargetsUpdatedAuthorizedSenders(address[] targets, address[] senders, address changedBy); - - // @notice Deploy with the address of the LINK token - // @dev Sets the LinkToken address for the imported LinkTokenInterface - // @param link The address of the LINK token - // @param owner The address of the owner - constructor(address link, address owner) ConfirmedOwner(owner) { - i_linkToken = LinkTokenInterface(link); // external but already deployed and unalterable - } - - string public constant typeAndVersion = "Operator 1.0.0"; - - // @notice Creates the Chainlink request. This is a backwards compatible API - // with the Oracle.sol contract, but the behavior changes because - // callbackAddress is assumed to be the same as the request sender. - // @param callbackAddress The consumer of the request - // @param payment The amount of payment given (specified in wei) - // @param specId The Job Specification ID - // @param callbackAddress The address the oracle data will be sent to - // @param callbackFunctionId The callback function ID for the response - // @param nonce The nonce sent by the requester - // @param dataVersion The specified data version - // @param data The extra request parameters - function oracleRequest( - address sender, - uint256 payment, - bytes32 specId, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external override validateFromLINK { - (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( - sender, - payment, - callbackAddress, - callbackFunctionId, - nonce, - dataVersion - ); - emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); - } - - // @notice Creates the Chainlink request - // @dev Stores the hash of the params as the on-chain commitment for the request. - // Emits OracleRequest event for the Chainlink node to detect. - // @param sender The sender of the request - // @param payment The amount of payment given (specified in wei) - // @param specId The Job Specification ID - // @param callbackFunctionId The callback function ID for the response - // @param nonce The nonce sent by the requester - // @param dataVersion The specified data version - // @param data The extra request parameters - function operatorRequest( - address sender, - uint256 payment, - bytes32 specId, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external override validateFromLINK { - (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( - sender, - payment, - sender, - callbackFunctionId, - nonce, - dataVersion - ); - emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); - } - - // @notice Called by the Chainlink node to fulfill requests - // @dev Given params must hash back to the commitment stored from `oracleRequest`. - // Will call the callback address' callback function without bubbling up error - // checking in a `require` so that the node can get paid. - // @param requestId The fulfillment request ID that must match the requester's - // @param payment The payment amount that will be released for the oracle (specified in wei) - // @param callbackAddress The callback address to call for fulfillment - // @param callbackFunctionId The callback function ID to use for fulfillment - // @param expiration The expiration that the node should respond by before the requester can cancel - // @param data The data to return to the consuming contract - // @return Status if the external call was successful - function fulfillOracleRequest( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes32 data - ) - external - override - validateAuthorizedSender - validateRequestId(requestId) - validateCallbackAddress(callbackAddress) - returns (bool) - { - _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 1); - emit OracleResponse(requestId); - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = callbackAddress.call(abi.encodeWithSelector(callbackFunctionId, requestId, data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - // @notice Called by the Chainlink node to fulfill requests with multi-word support - // @dev Given params must hash back to the commitment stored from `oracleRequest`. - // Will call the callback address' callback function without bubbling up error - // checking in a `require` so that the node can get paid. - // @param requestId The fulfillment request ID that must match the requester's - // @param payment The payment amount that will be released for the oracle (specified in wei) - // @param callbackAddress The callback address to call for fulfillment - // @param callbackFunctionId The callback function ID to use for fulfillment - // @param expiration The expiration that the node should respond by before the requester can cancel - // @param data The data to return to the consuming contract - // @return Status if the external call was successful - function fulfillOracleRequest2( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes calldata data - ) - external - override - validateAuthorizedSender - validateRequestId(requestId) - validateCallbackAddress(callbackAddress) - validateMultiWordResponseId(requestId, data) - returns (bool) - { - _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 2); - emit OracleResponse(requestId); - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = callbackAddress.call(abi.encodePacked(callbackFunctionId, data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - // @notice Transfer the ownership of ownable contracts. This is primarily - // intended for Authorized Forwarders but could possibly be extended to work - // with future contracts.OracleInterface - // @param ownable list of addresses to transfer - // @param newOwner address to transfer ownership to - function transferOwnableContracts(address[] calldata ownable, address newOwner) external onlyOwner { - for (uint256 i = 0; i < ownable.length; ++i) { - s_owned[ownable[i]] = false; - IOwnable(ownable[i]).transferOwnership(newOwner); - } - } - - // @notice Accept the ownership of an ownable contract. This is primarily - // intended for Authorized Forwarders but could possibly be extended to work - // with future contracts. - // @dev Must be the pending owner on the contract - // @param ownable list of addresses of Ownable contracts to accept - function acceptOwnableContracts(address[] calldata ownable) public validateAuthorizedSenderSetter { - for (uint256 i = 0; i < ownable.length; ++i) { - s_owned[ownable[i]] = true; - emit OwnableContractAccepted(ownable[i]); - IOwnable(ownable[i]).acceptOwnership(); - } - } - - // @notice Sets the fulfillment permission for - // @param targets The addresses to set permissions on - // @param senders The addresses that are allowed to send updates - function setAuthorizedSendersOn( - address[] calldata targets, - address[] calldata senders - ) public validateAuthorizedSenderSetter { - emit TargetsUpdatedAuthorizedSenders(targets, senders, msg.sender); - - for (uint256 i = 0; i < targets.length; ++i) { - IAuthorizedReceiver(targets[i]).setAuthorizedSenders(senders); - } - } - - // @notice Accepts ownership of ownable contracts and then immediately sets - // the authorized sender list on each of the newly owned contracts. This is - // primarily intended for Authorized Forwarders but could possibly be - // extended to work with future contracts. - // @param targets The addresses to set permissions on - // @param senders The addresses that are allowed to send updates - function acceptAuthorizedReceivers( - address[] calldata targets, - address[] calldata senders - ) external validateAuthorizedSenderSetter { - acceptOwnableContracts(targets); - setAuthorizedSendersOn(targets, senders); - } - - // @notice Allows the node operator to withdraw earned LINK to a given address - // @dev The owner of the contract can be another wallet and does not have to be a Chainlink node - // @param recipient The address to send the LINK token to - // @param amount The amount to send (specified in wei) - function withdraw( - address recipient, - uint256 amount - ) external override(OracleInterface, IWithdrawal) onlyOwner validateAvailableFunds(amount) { - assert(i_linkToken.transfer(recipient, amount)); - } - - // @notice Displays the amount of LINK that is available for the node operator to withdraw - // @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage - // @return The amount of withdrawable LINK on the contract - function withdrawable() external view override(OracleInterface, IWithdrawal) returns (uint256) { - return _fundsAvailable(); - } - - // @notice Forward a call to another contract - // @dev Only callable by the owner - // @param to address - // @param data to forward - function ownerForward(address to, bytes calldata data) external onlyOwner validateNotToLINK(to) { - require(to.code.length != 0, "Must forward to a contract"); - // solhint-disable-next-line avoid-low-level-calls - (bool status, ) = to.call(data); - require(status, "Forwarded call failed"); - } - - // @notice Interact with other LinkTokenReceiver contracts by calling transferAndCall - // @param to The address to transfer to. - // @param value The amount to be transferred. - // @param data The extra data to be passed to the receiving contract. - // @return success bool - function ownerTransferAndCall( - address to, - uint256 value, - bytes calldata data - ) external override onlyOwner validateAvailableFunds(value) returns (bool success) { - return i_linkToken.transferAndCall(to, value, data); - } - - // @notice Distribute funds to multiple addresses using ETH send - // to this payable function. - // @dev Array length must be equal, ETH sent must equal the sum of amounts. - // A malicious receiver could cause the distribution to revert, in which case - // it is expected that the address is removed from the list. - // @param receivers list of addresses - // @param amounts list of amounts - function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable { - require(receivers.length > 0 && receivers.length == amounts.length, "Invalid array length(s)"); - uint256 valueRemaining = msg.value; - for (uint256 i = 0; i < receivers.length; ++i) { - uint256 sendAmount = amounts[i]; - valueRemaining = valueRemaining - sendAmount; - (bool success, ) = receivers[i].call{value: sendAmount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - require(valueRemaining == 0, "Too much ETH sent"); - } - - // @notice Allows recipient to cancel requests sent to this oracle contract. - // Will transfer the LINK sent for the request back to the recipient address. - // @dev Given params must hash to a commitment stored on the contract in order - // for the request to be valid. Emits CancelOracleRequest event. - // @param requestId The request ID - // @param payment The amount of payment given (specified in wei) - // @param callbackFunc The requester's specified callback function selector - // @param expiration The time of the expiration for the request - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) public override { - bytes31 paramsHash = _buildParamsHash(payment, msg.sender, callbackFunc, expiration); - require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); - // solhint-disable-next-line not-rely-on-time - require(expiration <= block.timestamp, "Request is not expired"); - - delete s_commitments[requestId]; - emit CancelOracleRequest(requestId); - - // Free up the escrowed funds, as we're sending them back to the requester - s_tokensInEscrow -= payment; - i_linkToken.transfer(msg.sender, payment); - } - - // @notice Allows requester to cancel requests sent to this oracle contract. - // Will transfer the LINK sent for the request back to the recipient address. - // @dev Given params must hash to a commitment stored on the contract in order - // for the request to be valid. Emits CancelOracleRequest event. - // @param nonce The nonce used to generate the request ID - // @param payment The amount of payment given (specified in wei) - // @param callbackFunc The requester's specified callback function selector - // @param expiration The time of the expiration for the request - function cancelOracleRequestByRequester( - uint256 nonce, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) external { - cancelOracleRequest(keccak256(abi.encodePacked(msg.sender, nonce)), payment, callbackFunc, expiration); - } - - // @notice Returns the address of the LINK token - // @dev This is the public implementation for chainlinkTokenAddress, which is - // an internal method of the ChainlinkClient contract - function getChainlinkToken() public view override returns (address) { - return address(i_linkToken); - } - - // @notice Require that the token transfer action is valid - // @dev OPERATOR_REQUEST_SELECTOR = multiword, ORACLE_REQUEST_SELECTOR = singleword - function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal pure override { - require(data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length"); - require( - funcSelector == OPERATOR_REQUEST_SELECTOR || funcSelector == ORACLE_REQUEST_SELECTOR, - "Must use whitelisted functions" - ); - } - - // @notice Verify the Oracle Request and record necessary information - // @param sender The sender of the request - // @param payment The amount of payment given (specified in wei) - // @param callbackAddress The callback address for the response - // @param callbackFunctionId The callback function ID for the response - // @param nonce The nonce sent by the requester - function _verifyAndProcessOracleRequest( - address sender, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion - ) private validateNotToLINK(callbackAddress) returns (bytes32 requestId, uint256 expiration) { - requestId = keccak256(abi.encodePacked(sender, nonce)); - require(s_commitments[requestId].paramsHash == 0, "Must use a unique ID"); - // solhint-disable-next-line not-rely-on-time - expiration = block.timestamp + EXPIRYTIME; - bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); - s_commitments[requestId] = Commitment(paramsHash, SafeCast.toUint8(dataVersion)); - s_tokensInEscrow = s_tokensInEscrow + payment; - return (requestId, expiration); - } - - // @notice Verify the Oracle request and unlock escrowed payment - // @param requestId The fulfillment request ID that must match the requester's - // @param payment The payment amount that will be released for the oracle (specified in wei) - // @param callbackAddress The callback address to call for fulfillment - // @param callbackFunctionId The callback function ID to use for fulfillment - // @param expiration The expiration that the node should respond by before the requester can cancel - function _verifyOracleRequestAndProcessPayment( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - uint256 dataVersion - ) internal { - bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); - require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); - require(s_commitments[requestId].dataVersion <= SafeCast.toUint8(dataVersion), "Data versions must match"); - s_tokensInEscrow = s_tokensInEscrow - payment; - delete s_commitments[requestId]; - } - - // @notice Build the bytes31 hash from the payment, callback and expiration. - // @param payment The payment amount that will be released for the oracle (specified in wei) - // @param callbackAddress The callback address to call for fulfillment - // @param callbackFunctionId The callback function ID to use for fulfillment - // @param expiration The expiration that the node should respond by before the requester can cancel - // @return hash bytes31 - function _buildParamsHash( - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration - ) internal pure returns (bytes31) { - return bytes31(keccak256(abi.encodePacked(payment, callbackAddress, callbackFunctionId, expiration))); - } - - // @notice Returns the LINK available in this contract, not locked in escrow - // @return uint256 LINK tokens available - function _fundsAvailable() private view returns (uint256) { - return i_linkToken.balanceOf(address(this)) - (s_tokensInEscrow - ONE_FOR_CONSISTENT_GAS_COST); - } - - // @notice concrete implementation of AuthorizedReceiver - // @return bool of whether sender is authorized - function _canSetAuthorizedSenders() internal view override returns (bool) { - return isAuthorizedSender(msg.sender) || owner() == msg.sender; - } - - // MODIFIERS - - // @dev Reverts if the first 32 bytes of the bytes array is not equal to requestId - // @param requestId bytes32 - // @param data bytes - modifier validateMultiWordResponseId(bytes32 requestId, bytes calldata data) { - require(data.length >= 32, "Response must be > 32 bytes"); - bytes32 firstDataWord; - assembly { - firstDataWord := calldataload(data.offset) - } - require(requestId == firstDataWord, "First word must be requestId"); - _; - } - - // @dev Reverts if amount requested is greater than withdrawable balance - // @param amount The given amount to compare to `s_withdrawableTokens` - modifier validateAvailableFunds(uint256 amount) { - require(_fundsAvailable() >= amount, "Amount requested is greater than withdrawable balance"); - _; - } - - // @dev Reverts if request ID does not exist - // @param requestId The given request ID to check in stored `commitments` - modifier validateRequestId(bytes32 requestId) { - require(s_commitments[requestId].paramsHash != 0, "Must have a valid requestId"); - _; - } - - // @dev Reverts if the callback address is the LINK token - // @param to The callback address - modifier validateNotToLINK(address to) { - require(to != address(i_linkToken), "Cannot call to LINK"); - _; - } - - // @dev Reverts if the target address is owned by the operator - modifier validateCallbackAddress(address callbackAddress) { - require(!s_owned[callbackAddress], "Cannot call owned contract"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol deleted file mode 100644 index 1503535..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/OperatorFactory.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Operator} from "./Operator.sol"; -import {AuthorizedForwarder} from "./AuthorizedForwarder.sol"; - -// @title Operator Factory -// @notice Creates Operator contracts for node operators -// solhint-disable gas-custom-errors -contract OperatorFactory { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address public immutable linkToken; - mapping(address => bool) private s_created; - - event OperatorCreated(address indexed operator, address indexed owner, address indexed sender); - event AuthorizedForwarderCreated(address indexed forwarder, address indexed owner, address indexed sender); - - // @param linkAddress address - constructor(address linkAddress) { - linkToken = linkAddress; - } - - string public constant typeAndVersion = "OperatorFactory 1.0.0"; - - // @notice creates a new Operator contract with the msg.sender as owner - function deployNewOperator() external returns (address) { - Operator operator = new Operator(linkToken, msg.sender); - - s_created[address(operator)] = true; - emit OperatorCreated(address(operator), msg.sender, msg.sender); - - return address(operator); - } - - // @notice creates a new Operator contract with the msg.sender as owner and a - // new Operator Forwarder with the OperatorFactory as the owner - function deployNewOperatorAndForwarder() external returns (address, address) { - Operator operator = new Operator(linkToken, msg.sender); - s_created[address(operator)] = true; - emit OperatorCreated(address(operator), msg.sender, msg.sender); - - AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, address(this), address(operator), new bytes(0)); - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), address(this), msg.sender); - - return (address(operator), address(forwarder)); - } - - // @notice creates a new Forwarder contract with the msg.sender as owner - function deployNewForwarder() external returns (address) { - AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, msg.sender, address(0), new bytes(0)); - - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); - - return address(forwarder); - } - - // @notice creates a new Forwarder contract with the msg.sender as owner - function deployNewForwarderAndTransferOwnership(address to, bytes calldata message) external returns (address) { - AuthorizedForwarder forwarder = new AuthorizedForwarder(linkToken, msg.sender, to, message); - - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); - - return address(forwarder); - } - - // @notice indicates whether this factory deployed an address - function created(address query) external view returns (bool) { - return s_created[query]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol deleted file mode 100644 index 78140d5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IAuthorizedReceiver.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IAuthorizedReceiver { - function isAuthorizedSender(address sender) external view returns (bool); - - function getAuthorizedSenders() external returns (address[] memory); - - function setAuthorizedSenders(address[] calldata senders) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol deleted file mode 100644 index 433738d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/interfaces/IWithdrawal.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IWithdrawal { - // @notice transfer LINK held by the contract belonging to msg.sender to - // another address - // @param recipient is the address to send the LINK to - // @param amount is the amount of LINK to send - function withdraw(address recipient, uint256 amount) external; - - // @notice query the available amount of LINK to withdraw by msg.sender - function withdrawable() external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol deleted file mode 100644 index d54dc62..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Factory.t.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {Deployer} from "./testhelpers/Deployer.t.sol"; -import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; -import {Operator} from "../Operator.sol"; - -contract FactoryTest is Deployer { - function setUp() public { - _setUp(); - - vm.startPrank(ALICE); - } - - function test_DeployNewOperator_Success() public { - // Deploy a new operator using the factory. - address newOperator = s_factory.deployNewOperator(); - // Assert that the new operator was indeed created by the factory. - assertTrue(s_factory.created(newOperator)); - // Ensure that Alice is the owner of the newly deployed operator. - require(Operator(newOperator).owner() == ALICE); - } - - function test_DeployNewOperatorAndForwarder_Success() public { - // Deploy both a new operator and a new forwarder using the factory. - (address newOperator, address newForwarder) = s_factory.deployNewOperatorAndForwarder(); - - // Assert that the new operator and the new forwarder were indeed created by the factory. - assertTrue(s_factory.created(newOperator)); - assertTrue(s_factory.created(newForwarder)); - // Ensure that Alice is the owner of the newly deployed operator. - require(Operator(newOperator).owner() == ALICE); - - //Operator to accept ownership - vm.startPrank(newOperator); - AuthorizedForwarder(newForwarder).acceptOwnership(); - - // Ensure that the newly deployed operator is the owner of the newly deployed forwarder. - require(AuthorizedForwarder(newForwarder).owner() == newOperator, "operator is not the owner"); - } - - function test_DeployNewForwarder_Success() public { - // Deploy a new forwarder using the factory. - address newForwarder = s_factory.deployNewForwarder(); - // Assert that the new forwarder was indeed created by the factory. - assertTrue(s_factory.created(newForwarder)); - // Ensure that Alice is the owner of the newly deployed forwarder. - require(AuthorizedForwarder(newForwarder).owner() == ALICE); - } - - function test_DeployNewForwarderAndTransferOwnership_Success() public { - // Deploy a new forwarder with a proposal to transfer its ownership to Bob. - address newForwarder = s_factory.deployNewForwarderAndTransferOwnership(BOB, new bytes(0)); - // Assert that the new forwarder was indeed created by the factory. - assertTrue(s_factory.created(newForwarder)); - // Ensure that Alice is still the current owner of the newly deployed forwarder. - require(AuthorizedForwarder(newForwarder).owner() == ALICE); - - // Only proposed owner can call acceptOwnership() - vm.expectRevert("Must be proposed owner"); - AuthorizedForwarder(newForwarder).acceptOwnership(); - - vm.startPrank(BOB); - // Let Bob accept the ownership. - AuthorizedForwarder(newForwarder).acceptOwnership(); - // Ensure that Bob is now the owner of the forwarder after the transfer. - require(AuthorizedForwarder(newForwarder).owner() == BOB); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol deleted file mode 100644 index ba6ce1c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/Forwarder.t.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {Deployer} from "./testhelpers/Deployer.t.sol"; -import {AuthorizedForwarder} from "../AuthorizedForwarder.sol"; - -contract ForwarderTest is Deployer { - AuthorizedForwarder internal s_forwarder; - - function setUp() public { - _setUp(); - - vm.prank(ALICE); - s_forwarder = AuthorizedForwarder(s_factory.deployNewForwarder()); - } - - function test_SetAuthorizedSenders_Success() public { - address[] memory senders; - - // Expect a revert when trying to set an empty list of authorized senders - vm.expectRevert("Cannot set authorized senders"); - s_forwarder.setAuthorizedSenders(senders); - - vm.prank(ALICE); - // Expect a revert because the sender list is empty - vm.expectRevert("Must have at least 1 sender"); - s_forwarder.setAuthorizedSenders(senders); - - // Create a list with two identical sender addresses - senders = new address[](2); - senders[0] = SENDER_1; - senders[1] = SENDER_1; - - vm.prank(ALICE); - // Expect a revert because the sender list has duplicates - vm.expectRevert("Must not have duplicate senders"); - s_forwarder.setAuthorizedSenders(senders); - - // Set the second sender to a different address - senders[1] = SENDER_2; - - vm.prank(ALICE); - // Update the authorized senders list - s_forwarder.setAuthorizedSenders(senders); - - // Check if both SENDER_1 and SENDER_2 are now authorized - assertTrue(s_forwarder.isAuthorizedSender(SENDER_1)); - assertTrue(s_forwarder.isAuthorizedSender(SENDER_2)); - - // Fetch the authorized senders and verify they match the set addresses - address[] memory returnedSenders = s_forwarder.getAuthorizedSenders(); - require(returnedSenders[0] == senders[0]); - require(returnedSenders[1] == senders[1]); - - // Create a new list with only SENDER_3 - senders = new address[](1); - senders[0] = SENDER_3; - - // Prank 'alice' and update the authorized senders to just SENDER_3 - vm.prank(ALICE); - s_forwarder.setAuthorizedSenders(senders); - - // Ensure SENDER_1 and SENDER_2 are no longer authorized - assertFalse(s_forwarder.isAuthorizedSender(SENDER_1)); - assertFalse(s_forwarder.isAuthorizedSender(SENDER_2)); - - // Check that SENDER_3 is now the only authorized sender - assertTrue(s_forwarder.isAuthorizedSender(SENDER_3)); - returnedSenders = s_forwarder.getAuthorizedSenders(); - require(returnedSenders[0] == senders[0]); - } - - function test_Forward_Success(uint256 _value) public { - _addSenders(); - - vm.expectRevert("Not authorized sender"); - s_forwarder.forward(address(0), new bytes(0)); - - vm.prank(SENDER_1); - vm.expectRevert("Cannot forward to Link token"); - s_forwarder.forward(address(s_link), new bytes(0)); - - vm.prank(SENDER_1); - vm.expectRevert("Must forward to a contract"); - s_forwarder.forward(address(0), new bytes(0)); - - vm.prank(SENDER_1); - vm.expectRevert("Forwarded call reverted without reason"); - s_forwarder.forward(address(s_mockReceiver), new bytes(0)); - - vm.prank(SENDER_1); - vm.expectRevert("test revert message"); - s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("revertMessage()")); - - vm.prank(SENDER_1); - s_forwarder.forward(address(s_mockReceiver), abi.encodeWithSignature("receiveData(uint256)", _value)); - - require(s_mockReceiver.getValue() == _value); - } - - function test_MultiForward_Success(uint256 _value1, uint256 _value2) public { - _addSenders(); - - address[] memory tos; - bytes[] memory datas; - - vm.expectRevert("Not authorized sender"); - s_forwarder.multiForward(tos, datas); - - tos = new address[](2); - datas = new bytes[](1); - - vm.prank(SENDER_1); - vm.expectRevert("Arrays must have the same length"); - s_forwarder.multiForward(tos, datas); - - datas = new bytes[](2); - - vm.prank(SENDER_1); - vm.expectRevert("Must forward to a contract"); - s_forwarder.multiForward(tos, datas); - - tos[0] = address(s_mockReceiver); - tos[1] = address(s_link); - - vm.prank(SENDER_1); - vm.expectRevert("Forwarded call reverted without reason"); - s_forwarder.multiForward(tos, datas); - - datas[0] = abi.encodeWithSignature("receiveData(uint256)", _value1); - datas[1] = abi.encodeWithSignature("receiveData(uint256)", _value2); - - vm.prank(SENDER_1); - vm.expectRevert("Cannot forward to Link token"); - s_forwarder.multiForward(tos, datas); - - tos[1] = address(s_mockReceiver); - - vm.prank(SENDER_1); - s_forwarder.multiForward(tos, datas); - - require(s_mockReceiver.getValue() == _value2); - } - - function test_OwnerForward_Success() public { - vm.expectRevert("Only callable by owner"); - s_forwarder.ownerForward(address(0), new bytes(0)); - - vm.prank(ALICE); - vm.expectRevert("Forwarded call reverted without reason"); - s_forwarder.ownerForward(address(s_link), new bytes(0)); - - vm.prank(ALICE); - s_forwarder.ownerForward(address(s_link), abi.encodeWithSignature("balanceOf(address)", address(0))); - } - - function test_TransferOwnershipWithMessage_Success() public { - vm.prank(BOB); - vm.expectRevert("Only callable by owner"); - s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); - - vm.prank(ALICE); - s_forwarder.transferOwnershipWithMessage(BOB, new bytes(0)); - - vm.expectRevert("Must be proposed owner"); - s_forwarder.acceptOwnership(); - - vm.prank(BOB); - s_forwarder.acceptOwnership(); - - require(s_forwarder.owner() == BOB); - } - - function _addSenders() internal { - address[] memory senders = new address[](3); - senders[0] = SENDER_1; - senders[1] = SENDER_2; - senders[2] = SENDER_3; - - vm.prank(ALICE); - s_forwarder.setAuthorizedSenders(senders); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol deleted file mode 100644 index 6c4a7c2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/operator.t.sol +++ /dev/null @@ -1,291 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {Operator} from "../Operator.sol"; -import {Callback} from "./testhelpers/Callback.sol"; -import {ChainlinkClientHelper} from "./testhelpers/ChainlinkClientHelper.sol"; -import {Deployer} from "./testhelpers/Deployer.t.sol"; - -contract OperatorTest is Deployer { - ChainlinkClientHelper private s_client; - Callback private s_callback; - Operator private s_operator; - - function setUp() public { - _setUp(); - s_client = new ChainlinkClientHelper(address(s_link)); - - address[] memory auth = new address[](1); - auth[0] = address(this); - s_operator = new Operator(address(s_link), address(this)); - s_operator.setAuthorizedSenders(auth); - - s_callback = new Callback(address(s_operator)); - } - - function test_SendRequest_Success(uint96 payment) public { - vm.assume(payment > 0); - deal(address(s_link), address(s_client), payment); - // We're going to cancel one request and fulfill the other - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // 1 payment in escrow - // Client has zero link - assertEq(s_operator.withdrawable(), 0); - assertEq(s_link.balanceOf(address(s_operator)), payment); - assertEq(s_link.balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation. - assertEq(s_operator.withdrawable(), 0); - assertEq(s_link.balanceOf(address(s_operator)), 0); - assertEq(s_link.balanceOf(address(s_client)), payment); - } - - function test_SendRequestAndCancelRequest_Success(uint96 payment) public { - vm.assume(payment > 1); - payment /= payment; - - deal(address(s_link), address(s_client), 2 * payment); - - // Initial state, client has 2 payments, zero in escrow, zero in the operator, zeero withdrawable - assertEq(s_operator.withdrawable(), 0); - assertEq(s_link.balanceOf(address(s_operator)), 0); - assertEq(s_link.balanceOf(address(s_client)), 2 * payment); - - // We're going to cancel one request and fulfill the other - bytes32 requestId = s_client.sendRequest(address(s_operator), payment); - bytes32 requestIdToCancel = s_client.sendRequest(address(s_operator), payment); - - // Nothing withdrawable - // Operator now has the 2 payments in escrow - // Client has zero payments - assertEq(s_operator.withdrawable(), 0); - assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); - assertEq(s_link.balanceOf(address(s_client)), 0); - - // Fulfill one request - uint256 expiration = block.timestamp + s_operator.EXPIRYTIME(); - s_operator.fulfillOracleRequest( - requestId, - payment, - address(s_client), - s_client.FULFILL_SELECTOR(), - expiration, - bytes32(hex"01") - ); - // 1 payment withdrawable from fulfilling `requestId`, 1 payment in escrow - assertEq(s_operator.withdrawable(), payment); - assertEq(s_link.balanceOf(address(s_operator)), 2 * payment); - assertEq(s_link.balanceOf(address(s_client)), 0); - - // Advance time so we can cancel - vm.warp(expiration + 1); - s_client.cancelRequest(requestIdToCancel, payment, expiration); - - // 1 payment has been returned due to the cancellation, 1 payment should be withdrawable - assertEq(s_operator.withdrawable(), payment); - assertEq(s_link.balanceOf(address(s_operator)), payment); - assertEq(s_link.balanceOf(address(s_client)), payment); - - // Withdraw the remaining payment - s_operator.withdraw(address(s_client), payment); - - // End state is exactly the same as the initial state. - assertEq(s_operator.withdrawable(), 0); - assertEq(s_link.balanceOf(address(s_operator)), 0); - assertEq(s_link.balanceOf(address(s_client)), 2 * payment); - } - - function test_OracleRequest_Success() public { - // Define some mock values - bytes32 specId = keccak256("testSpec"); - bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); - uint256 nonce = 0; - uint256 dataVersion = 1; - bytes memory data = ""; - - uint256 initialLinkBalance = s_link.balanceOf(address(s_operator)); - uint256 payment = 1 ether; // Mock payment value - - uint256 withdrawableBefore = s_operator.withdrawable(); - - // Send LINK tokens to the Operator contract using `transferAndCall` - deal(address(s_link), ALICE, payment); - assertEq(s_link.balanceOf(ALICE), 1 ether, "balance update failed"); - - vm.prank(ALICE); - s_link.transferAndCall( - address(s_operator), - payment, - abi.encodeWithSignature( - "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", - address(this), - payment, - specId, - address(s_callback), - callbackFunctionId, - nonce, - dataVersion, - data - ) - ); - - // Check that the LINK tokens were transferred to the Operator contract - assertEq(s_link.balanceOf(address(s_operator)), initialLinkBalance + payment); - // No withdrawable LINK as it's all locked - assertEq(s_operator.withdrawable(), withdrawableBefore); - } - - function test_FulfillOracleRequest_Success() public { - // This test file is the callback target and actual sender contract - // so we should enable it to set Authorised senders to itself - address[] memory senders = new address[](2); - senders[0] = address(this); - senders[0] = BOB; - - s_operator.setAuthorizedSenders(senders); - - uint256 withdrawableBefore = s_operator.withdrawable(); - - // Define mock values for creating a new oracle request - bytes32 specId = keccak256("testSpecForFulfill"); - bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); - uint256 nonce = 1; - uint256 dataVersion = 1; - bytes memory dataBytes = ""; - uint256 payment = 1 ether; - uint256 expiration = block.timestamp + 5 minutes; - - // Convert bytes to bytes32 - bytes32 data = bytes32(keccak256(dataBytes)); - - // Send LINK tokens to the Operator contract using `transferAndCall` - deal(address(s_link), BOB, payment); - vm.prank(BOB); - s_link.transferAndCall( - address(s_operator), - payment, - abi.encodeWithSignature( - "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", - address(this), - payment, - specId, - address(s_callback), - callbackFunctionId, - nonce, - dataVersion, - dataBytes - ) - ); - - // Fulfill the request using the operator - bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); - vm.prank(BOB); - s_operator.fulfillOracleRequest(requestId, payment, address(s_callback), callbackFunctionId, expiration, data); - - assertEq(s_callback.getCallbacksReceived(), 1, "Oracle request was not fulfilled"); - - // Withdrawable balance - assertEq(s_operator.withdrawable(), withdrawableBefore + payment, "Internal accounting not updated correctly"); - } - - function test_CancelOracleRequest_Success() public { - // Define mock values for creating a new oracle request - bytes32 specId = keccak256("testSpecForCancel"); - bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); - uint256 nonce = 2; - uint256 dataVersion = 1; - bytes memory dataBytes = ""; - uint256 payment = 1 ether; - uint256 expiration = block.timestamp + 5 minutes; - - uint256 withdrawableBefore = s_operator.withdrawable(); - - // Send LINK tokens to the Operator contract using `transferAndCall` - deal(address(s_link), BOB, payment); - vm.prank(BOB); - s_link.transferAndCall( - address(s_operator), - payment, - abi.encodeWithSignature( - "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", - BOB, - payment, - specId, - BOB, - callbackFunctionId, - nonce, - dataVersion, - dataBytes - ) - ); - - // No withdrawable balance as it's all locked - assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); - - bytes32 requestId = keccak256(abi.encodePacked(BOB, nonce)); - - vm.startPrank(ALICE); - vm.expectRevert(bytes("Params do not match request ID")); - s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); - - vm.startPrank(BOB); - vm.expectRevert(bytes("Request is not expired")); - s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); - - vm.warp(expiration); - s_operator.cancelOracleRequest(requestId, payment, callbackFunctionId, expiration); - - // Check if the LINK tokens were refunded to the sender (bob in this case) - assertEq(s_link.balanceOf(BOB), 1 ether, "Oracle request was not canceled properly"); - - assertEq(s_operator.withdrawable(), withdrawableBefore, "Internal accounting not updated correctly"); - } - - function test_NotAuthorizedSender_Revert() public { - bytes32 specId = keccak256("unauthorizedFulfillSpec"); - bytes4 callbackFunctionId = bytes4(keccak256("callback(bytes32)")); - uint256 nonce = 5; - uint256 dataVersion = 1; - bytes memory dataBytes = ""; - uint256 payment = 1 ether; - uint256 expiration = block.timestamp + 5 minutes; - - deal(address(s_link), ALICE, payment); - vm.prank(ALICE); - s_link.transferAndCall( - address(s_operator), - payment, - abi.encodeWithSignature( - "oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)", - ALICE, - payment, - specId, - address(s_callback), - callbackFunctionId, - nonce, - dataVersion, - dataBytes - ) - ); - - bytes32 requestId = keccak256(abi.encodePacked(ALICE, nonce)); - - vm.prank(BOB); - vm.expectRevert(bytes("Not authorized sender")); - s_operator.fulfillOracleRequest( - requestId, - payment, - address(s_callback), - callbackFunctionId, - expiration, - bytes32(keccak256(dataBytes)) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol deleted file mode 100644 index 7004b53..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/BasicConsumer.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Consumer} from "./Consumer.sol"; - -contract BasicConsumer is Consumer { - constructor(address _link, address _oracle, bytes32 _specId) { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - s_specId = _specId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol deleted file mode 100644 index 3d72571..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Callback.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract Callback { - address private s_operator; - uint256 private s_callbacksReceived = 0; - - constructor(address _operator) { - s_operator = _operator; - } - - // Callback function for oracle request fulfillment - function callback(bytes32) public { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == s_operator, "Only Operator can call this function"); - s_callbacksReceived += 1; - } - - function getCallbacksReceived() public view returns (uint256) { - return s_callbacksReceived; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol deleted file mode 100644 index 9b6ba6b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/ChainlinkClientHelper.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainlinkClient} from "../../../ChainlinkClient.sol"; - -contract ChainlinkClientHelper is ChainlinkClient { - bytes4 public constant FULFILL_SELECTOR = this.fulfill.selector; - - constructor(address link) { - _setChainlinkToken(link); - } - - function sendRequest(address op, uint256 payment) external returns (bytes32) { - return _sendChainlinkRequestTo(op, _buildOperatorRequest(bytes32(hex"10"), FULFILL_SELECTOR), payment); - } - - function cancelRequest(bytes32 requestId, uint256 payment, uint256 expiration) external { - _cancelChainlinkRequest(requestId, payment, this.fulfill.selector, expiration); - } - - function fulfill(bytes32) external {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol deleted file mode 100644 index dba5d40..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Chainlinked.sol +++ /dev/null @@ -1,127 +0,0 @@ -pragma solidity ^0.8.0; - -import {ChainlinkClient, Chainlink} from "../../../ChainlinkClient.sol"; - -/** - * @title The Chainlinked contract - * @notice Contract writers can inherit this contract in order to create requests for the - * Chainlink network. ChainlinkClient is an alias of the Chainlinked contract. - */ -// solhint-disable -contract Chainlinked is ChainlinkClient { - /** - * @notice Creates a request that can hold additional parameters - * @param _specId The Job Specification ID that the request will be created for - * @param _callbackAddress The callback address that the response will be sent to - * @param _callbackFunctionSignature The callback function signature to use for the callback address - * @return A Chainlink Request struct in memory - */ - function newRequest( - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunctionSignature - ) internal pure returns (Chainlink.Request memory) { - return _buildChainlinkRequest(_specId, _callbackAddress, _callbackFunctionSignature); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev Calls `sendChainlinkRequestTo` with the stored oracle address - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return The request ID - */ - function chainlinkRequest(Chainlink.Request memory _req, uint256 _payment) internal returns (bytes32) { - return _sendChainlinkRequest(_req, _payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param _oracle The address of the oracle for the request - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function chainlinkRequestTo( - address _oracle, - Chainlink.Request memory _req, - uint256 _payment - ) internal returns (bytes32 requestId) { - return _sendChainlinkRequestTo(_oracle, _req, _payment); - } - - /** - * @notice Sets the stored oracle address - * @param _oracle The address of the oracle contract - */ - function setOracle(address _oracle) internal { - _setChainlinkOracle(_oracle); - } - - /** - * @notice Sets the LINK token address - * @param _link The address of the LINK token contract - */ - function setLinkToken(address _link) internal { - _setChainlinkToken(_link); - } - - /** - * @notice Retrieves the stored address of the LINK token - * @return The address of the LINK token - */ - function chainlinkToken() internal view returns (address) { - return _chainlinkTokenAddress(); - } - - /** - * @notice Retrieves the stored address of the oracle contract - * @return The address of the oracle contract - */ - function oracleAddress() internal view returns (address) { - return _chainlinkOracleAddress(); - } - - /** - * @notice Ensures that the fulfillment is valid for this contract - * @dev Use if the contract developer prefers methods instead of modifiers for validation - * @param _requestId The request ID for fulfillment - */ - function fulfillChainlinkRequest( - bytes32 _requestId - ) - internal - recordChainlinkFulfillment(_requestId) // solhint-disable-next-line no-empty-blocks - {} - - /** - * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS - * @dev Accounts for subnodes having different resolvers - * @param _ens The address of the ENS contract - * @param _node The ENS node hash - */ - function setChainlinkWithENS(address _ens, bytes32 _node) internal { - _useChainlinkWithENS(_ens, _node); - } - - /** - * @notice Sets the stored oracle contract with the address resolved by ENS - * @dev This may be called on its own as long as `setChainlinkWithENS` has been called previously - */ - function setOracleWithENS() internal { - _updateChainlinkOracleWithENS(); - } - - /** - * @notice Allows for a request which was created on another contract to be fulfilled - * on this contract - * @param _oracle The address of the oracle contract that will fulfill the request - * @param _requestId The request ID used for the response - */ - function addExternalRequest(address _oracle, bytes32 _requestId) internal { - _addChainlinkExternalRequest(_oracle, _requestId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol deleted file mode 100644 index 3ec32dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Consumer.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../Chainlink.sol"; - -contract Consumer is ChainlinkClient { - using Chainlink for Chainlink.Request; - - bytes32 internal s_specId; - bytes32 internal s_currentPrice; - - event RequestFulfilled( - bytes32 indexed requestId, // User-defined ID - bytes32 indexed price - ); - - function requestEthereumPrice(string memory _currency, uint256 _payment) public { - requestEthereumPriceByCallback(_currency, _payment, address(this)); - } - - function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public { - Chainlink.Request memory req = _buildChainlinkRequest(s_specId, _callback, this.fulfill.selector); - req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = _currency; - req._addStringArray("path", path); - _sendChainlinkRequest(req, _payment); - } - - function cancelRequest( - address _oracle, - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); - // solhint-disable-next-line gas-custom-errors - require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); - } - - function addExternalRequest(address _oracle, bytes32 _requestId) external { - _addChainlinkExternalRequest(_oracle, _requestId); - } - - function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { - emit RequestFulfilled(_requestId, _price); - s_currentPrice = _price; - } - - function getCurrentPrice() public view returns (bytes32) { - return s_currentPrice; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol deleted file mode 100644 index da746c7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/Deployer.t.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; - -import {MockReceiver} from "./MockReceiver.sol"; -import {AuthorizedForwarder} from "../../AuthorizedForwarder.sol"; -import {Operator} from "../../Operator.sol"; -import {OperatorFactory} from "../../OperatorFactory.sol"; -import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; - -abstract contract Deployer is Test { - OperatorFactory internal s_factory; - LinkToken internal s_link; - MockReceiver internal s_mockReceiver; - - address internal constant ALICE = address(0x101); - address internal constant BOB = address(0x102); - address internal constant SENDER_1 = address(0x103); - address internal constant SENDER_2 = address(0x104); - address internal constant SENDER_3 = address(0x105); - - function _setUp() internal { - _deploy(); - } - - function _deploy() internal { - s_link = new LinkToken(); - s_factory = new OperatorFactory(address(s_link)); - - s_mockReceiver = new MockReceiver(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol deleted file mode 100644 index f278791..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/EmptyOracle.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; -import {OracleInterface} from "../../../interfaces/OracleInterface.sol"; - -/* solhint-disable no-empty-blocks */ -contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { - function cancelOracleRequest(bytes32, uint256, bytes4, uint256) external override {} - function fulfillOracleRequest(bytes32, uint256, address, bytes4, uint256, bytes32) external override returns (bool) {} - function getAuthorizationStatus(address) external pure returns (bool) { - return false; - } - function onTokenTransfer(address, uint256, bytes calldata) external pure {} - function oracleRequest( - address, - uint256, - bytes32, - address, - bytes4, - uint256, - uint256, - bytes calldata - ) external override {} - function setFulfillmentPermission(address, bool) external {} - function withdraw(address, uint256) external override {} - function withdrawable() external view override returns (uint256) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol deleted file mode 100644 index 0291020..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GasGuzzlingConsumer.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Consumer} from "./Consumer.sol"; -import {Chainlink} from "../../../Chainlink.sol"; - -contract GasGuzzlingConsumer is Consumer { - using Chainlink for Chainlink.Request; - - constructor(address _link, address _oracle, bytes32 _specId) { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - s_specId = _specId; - } - - function gassyRequestEthereumPrice(uint256 _payment) public { - Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyFulfill.selector); - req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = "USD"; - req._addStringArray("path", path); - _sendChainlinkRequest(req, _payment); - } - - function gassyFulfill(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { - while (true) {} - } - - function gassyMultiWordRequest(uint256 _payment) public { - Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyMultiWordFulfill.selector); - req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = "USD"; - req._addStringArray("path", path); - _sendChainlinkRequest(req, _payment); - } - - function gassyMultiWordFulfill(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - while (true) {} - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol deleted file mode 100644 index 722362b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/GetterSetter.sol +++ /dev/null @@ -1,50 +0,0 @@ -pragma solidity ^0.8.0; - -// GetterSetter is a contract to aid debugging and testing during development. -// solhint-disable -contract GetterSetter { - bytes32 private s_getBytes32; - uint256 private s_getUint256; - bytes32 private s_requestId; - bytes private s_getBytes; - - event SetBytes32(address indexed from, bytes32 indexed value); - event SetUint256(address indexed from, uint256 indexed value); - event SetBytes(address indexed from, bytes value); - - event Output(bytes32 b32, uint256 u256, bytes32 b322); - - function setBytes32(bytes32 _value) public { - s_getBytes32 = _value; - emit SetBytes32(msg.sender, _value); - } - - function requestedBytes32(bytes32 _requestId, bytes32 _value) public { - s_requestId = _requestId; - setBytes32(_value); - } - - function setBytes(bytes memory _value) public { - s_getBytes = _value; - emit SetBytes(msg.sender, _value); - } - - function getBytes() public view returns (bytes memory _value) { - return s_getBytes; - } - - function requestedBytes(bytes32 _requestId, bytes memory _value) public { - s_requestId = _requestId; - setBytes(_value); - } - - function setUint256(uint256 _value) public { - s_getUint256 = _value; - emit SetUint256(msg.sender, _value); - } - - function requestedUint256(bytes32 _requestId, uint256 _value) public { - s_requestId = _requestId; - setUint256(_value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol deleted file mode 100644 index 11c863f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlink.sol +++ /dev/null @@ -1,67 +0,0 @@ -pragma solidity ^0.8.0; - -import {CBORChainlink as CBOR_Chainlink} from "../../../vendor/CBORChainlink.sol"; -import {BufferChainlink as Buffer_Chainlink} from "../../../vendor/BufferChainlink.sol"; - -// solhint-disable -library MaliciousChainlink { - using CBOR_Chainlink for Buffer_Chainlink.buffer; - - struct Request { - bytes32 specId; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - Buffer_Chainlink.buffer buf; - } - - struct WithdrawRequest { - bytes32 specId; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - Buffer_Chainlink.buffer buf; - } - - function initializeWithdraw( - WithdrawRequest memory self, - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunction - ) internal pure returns (MaliciousChainlink.WithdrawRequest memory) { - Buffer_Chainlink.init(self.buf, 128); - self.specId = _specId; - self.callbackAddress = _callbackAddress; - self.callbackFunctionId = _callbackFunction; - return self; - } - - function add(Request memory self, string memory _key, string memory _value) internal pure { - self.buf.encodeString(_key); - self.buf.encodeString(_value); - } - - function addBytes(Request memory self, string memory _key, bytes memory _value) internal pure { - self.buf.encodeString(_key); - self.buf.encodeBytes(_value); - } - - function addInt(Request memory self, string memory _key, int256 _value) internal pure { - self.buf.encodeString(_key); - self.buf.encodeInt(_value); - } - - function addUint(Request memory self, string memory _key, uint256 _value) internal pure { - self.buf.encodeString(_key); - self.buf.encodeUInt(_value); - } - - function addStringArray(Request memory self, string memory _key, string[] memory _values) internal pure { - self.buf.encodeString(_key); - self.buf.startArray(); - for (uint256 i = 0; i < _values.length; i++) { - self.buf.encodeString(_values[i]); - } - self.buf.endSequence(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol deleted file mode 100644 index 989c39c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousChainlinked.sol +++ /dev/null @@ -1,116 +0,0 @@ -pragma solidity ^0.8.0; - -import {MaliciousChainlink} from "./MaliciousChainlink.sol"; -import {Chainlinked, Chainlink} from "./Chainlinked.sol"; -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; - -// solhint-disable -contract MaliciousChainlinked is Chainlinked { - using MaliciousChainlink for MaliciousChainlink.Request; - using MaliciousChainlink for MaliciousChainlink.WithdrawRequest; - using Chainlink for Chainlink.Request; - - uint256 private s_maliciousRequests = 1; - mapping(bytes32 => address) private s_maliciousPendingRequests; - - function newWithdrawRequest( - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunction - ) internal pure returns (MaliciousChainlink.WithdrawRequest memory) { - MaliciousChainlink.WithdrawRequest memory req; - return req.initializeWithdraw(_specId, _callbackAddress, _callbackFunction); - } - - function chainlinkTargetRequest( - address _target, - Chainlink.Request memory _req, - uint256 _amount - ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(_target, s_maliciousRequests)); - _req.nonce = s_maliciousRequests; - s_maliciousPendingRequests[requestId] = oracleAddress(); - emit ChainlinkRequested(requestId); - LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); - require( - link.transferAndCall(oracleAddress(), _amount, encodeTargetRequest(_req)), - "Unable to transferAndCall to oracle" - ); - s_maliciousRequests += 1; - - return requestId; - } - - function chainlinkPriceRequest(Chainlink.Request memory _req, uint256 _amount) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); - _req.nonce = s_maliciousRequests; - s_maliciousPendingRequests[requestId] = oracleAddress(); - emit ChainlinkRequested(requestId); - LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); - require( - link.transferAndCall(oracleAddress(), _amount, encodePriceRequest(_req)), - "Unable to transferAndCall to oracle" - ); - s_maliciousRequests += 1; - - return requestId; - } - - function chainlinkWithdrawRequest( - MaliciousChainlink.WithdrawRequest memory _req, - uint256 _wei - ) internal returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, s_maliciousRequests)); - _req.nonce = s_maliciousRequests; - s_maliciousPendingRequests[requestId] = oracleAddress(); - emit ChainlinkRequested(requestId); - LinkTokenInterface link = LinkTokenInterface(chainlinkToken()); - require( - link.transferAndCall(oracleAddress(), _wei, encodeWithdrawRequest(_req)), - "Unable to transferAndCall to oracle" - ); - s_maliciousRequests += 1; - return requestId; - } - - function encodeWithdrawRequest(MaliciousChainlink.WithdrawRequest memory _req) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - bytes4(keccak256("withdraw(address,uint256)")), - _req.callbackAddress, - _req.callbackFunctionId, - _req.nonce, - _req.buf.buf - ); - } - - function encodeTargetRequest(Chainlink.Request memory _req) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - bytes4(keccak256("oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)")), - 0, // overridden by onTokenTransfer - 0, // overridden by onTokenTransfer - _req.id, - _req.callbackAddress, - _req.callbackFunctionId, - _req.nonce, - 1, - _req.buf.buf - ); - } - - function encodePriceRequest(Chainlink.Request memory _req) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - bytes4(keccak256("oracleRequest(address,uint256,bytes32,address,bytes4,uint256,uint256,bytes)")), - 0, // overridden by onTokenTransfer - 2000000000000000000, // overridden by onTokenTransfer - _req.id, - _req.callbackAddress, - _req.callbackFunctionId, - _req.nonce, - 1, - _req.buf.buf - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol deleted file mode 100644 index bd731c7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol +++ /dev/null @@ -1,49 +0,0 @@ -pragma solidity ^0.8.0; - -import {Chainlinked, Chainlink} from "./Chainlinked.sol"; - -// solhint-disable -contract MaliciousConsumer is Chainlinked { - uint256 private constant ORACLE_PAYMENT = 1 ether; - uint256 private s_expiration; - - constructor(address _link, address _oracle) payable { - setLinkToken(_link); - setOracle(_oracle); - } - - fallback() external payable {} // solhint-disable-line no-empty-blocks - - function requestData(bytes32 _id, bytes memory _callbackFunc) public { - Chainlink.Request memory req = newRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); - s_expiration = block.timestamp + 5 minutes; - chainlinkRequest(req, ORACLE_PAYMENT); - } - - function assertFail(bytes32, bytes32) public pure { - assert(1 == 2); - } - - function cancelRequestOnFulfill(bytes32 _requestId, bytes32) public { - _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); - } - - function remove() public { - selfdestruct(payable(address(0))); - } - - function stealEthCall(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { - (bool success, ) = address(this).call{value: 100}(""); - require(success, "Call failed"); - } - - function stealEthSend(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { - require(payable(address(this)).send(100), "Send failed"); - } - - function stealEthTransfer(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { - payable(address(this)).transfer(100); - } - - function doesNothing(bytes32, bytes32) public pure {} // solhint-disable-line no-empty-blocks -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol deleted file mode 100644 index 93af16f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainlinkClient} from "../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../Chainlink.sol"; - -contract MaliciousMultiWordConsumer is ChainlinkClient { - uint256 private constant ORACLE_PAYMENT = 1 ether; - uint256 private s_expiration; - - constructor(address _link, address _oracle) payable { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - } - - receive() external payable {} // solhint-disable-line no-empty-blocks - - function requestData(bytes32 _id, bytes memory _callbackFunc) public { - Chainlink.Request memory req = _buildChainlinkRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); - s_expiration = block.timestamp + 5 minutes; // solhint-disable-line not-rely-on-time - _sendChainlinkRequest(req, ORACLE_PAYMENT); - } - - function assertFail(bytes32, bytes memory) public pure { - assert(1 == 2); - } - - function cancelRequestOnFulfill(bytes32 _requestId, bytes memory) public { - _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); - } - - function remove() public { - selfdestruct(payable(address(0))); - } - - function stealEthCall(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - (bool success, ) = address(this).call{value: 100}(""); // solhint-disable-line avoid-call-value - // solhint-disable-next-line gas-custom-errors - require(success, "Call failed"); - } - - function stealEthSend(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - // solhint-disable-next-line check-send-result - bool success = payable(address(this)).send(100); // solhint-disable-line multiple-sends - // solhint-disable-next-line gas-custom-errors - require(success, "Send failed"); - } - - function stealEthTransfer(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - payable(address(this)).transfer(100); - } - - function doesNothing(bytes32, bytes memory) public pure {} // solhint-disable-line no-empty-blocks -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol deleted file mode 100644 index c01c8a6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousRequester.sol +++ /dev/null @@ -1,52 +0,0 @@ -pragma solidity ^0.8.0; - -import {MaliciousChainlink} from "./MaliciousChainlink.sol"; -import {MaliciousChainlinked, Chainlink} from "./MaliciousChainlinked.sol"; -import {ChainlinkRequestInterface} from "../../../interfaces/ChainlinkRequestInterface.sol"; - -contract MaliciousRequester is MaliciousChainlinked { - uint256 private constant ORACLE_PAYMENT = 1 ether; - uint256 private s_expiration; - - constructor(address _link, address _oracle) { - setLinkToken(_link); - setOracle(_oracle); - } - - function maliciousWithdraw() public { - MaliciousChainlink.WithdrawRequest memory req = newWithdrawRequest( - "specId", - address(this), - this.doesNothing.selector - ); - chainlinkWithdrawRequest(req, ORACLE_PAYMENT); - } - - function request(bytes32 _id, address _target, bytes memory _callbackFunc) public returns (bytes32 requestId) { - Chainlink.Request memory req = newRequest(_id, _target, bytes4(keccak256(_callbackFunc))); - s_expiration = block.timestamp + 5 minutes; // solhint-disable-line not-rely-on-time - return chainlinkRequest(req, ORACLE_PAYMENT); - } - - function maliciousPrice(bytes32 _id) public returns (bytes32 requestId) { - Chainlink.Request memory req = newRequest(_id, address(this), this.doesNothing.selector); - return chainlinkPriceRequest(req, ORACLE_PAYMENT); - } - - function maliciousTargetConsumer(address _target) public returns (bytes32 requestId) { - Chainlink.Request memory req = newRequest("specId", _target, bytes4(keccak256("fulfill(bytes32,bytes32)"))); - return chainlinkTargetRequest(_target, req, ORACLE_PAYMENT); - } - - function maliciousRequestCancel(bytes32 _id, bytes memory _callbackFunc) public { - ChainlinkRequestInterface oracle = ChainlinkRequestInterface(oracleAddress()); - oracle.cancelOracleRequest( - request(_id, address(this), _callbackFunc), - ORACLE_PAYMENT, - this.maliciousRequestCancel.selector, - s_expiration - ); - } - - function doesNothing(bytes32, bytes32) public pure {} // solhint-disable-line no-empty-blocks -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol deleted file mode 100644 index 38a0c3d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MockReceiver.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -contract MockReceiver { - uint256 private s_value; - - function receiveData(uint256 _value) public { - s_value = _value; - } - - function revertMessage() public pure { - // solhint-disable-next-line gas-custom-errors - revert("test revert message"); - } - - function getValue() external view returns (uint256) { - return s_value; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol deleted file mode 100644 index b3fdfcb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/operatorforwarder/test/testhelpers/MultiWordConsumer.sol +++ /dev/null @@ -1,145 +0,0 @@ -pragma solidity ^0.8.0; - -import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../ChainlinkClient.sol"; -import {Chainlink} from "../../../Chainlink.sol"; - -contract MultiWordConsumer is ChainlinkClient { - using Chainlink for Chainlink.Request; - - bytes32 internal s_specId; - bytes internal s_currentPrice; - - bytes32 private s_usd; - bytes32 private s_eur; - bytes32 private s_jpy; - - uint256 private s_usdInt; - uint256 private s_eurInt; - uint256 private s_jpyInt; - - event RequestFulfilled( - bytes32 indexed requestId, // User-defined ID - bytes indexed price - ); - - event RequestMultipleFulfilled(bytes32 indexed requestId, bytes32 indexed usd, bytes32 indexed eur, bytes32 jpy); - - event RequestMultipleFulfilledWithCustomURLs( - bytes32 indexed requestId, - uint256 indexed usd, - uint256 indexed eur, - uint256 jpy - ); - - constructor(address _link, address _oracle, bytes32 _specId) { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - s_specId = _specId; - } - - function setSpecID(bytes32 _specId) public { - s_specId = _specId; - } - - function requestEthereumPrice(string memory, uint256 _payment) public { - Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillBytes.selector); - _sendOperatorRequest(req, _payment); - } - - function requestMultipleParameters(string memory, uint256 _payment) public { - Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillMultipleParameters.selector); - _sendOperatorRequest(req, _payment); - } - - function requestMultipleParametersWithCustomURLs( - string memory _urlUSD, - string memory _pathUSD, - string memory _urlEUR, - string memory _pathEUR, - string memory _urlJPY, - string memory _pathJPY, - uint256 _payment - ) public { - Chainlink.Request memory req = _buildOperatorRequest( - s_specId, - this.fulfillMultipleParametersWithCustomURLs.selector - ); - req._add("urlUSD", _urlUSD); - req._add("pathUSD", _pathUSD); - req._add("urlEUR", _urlEUR); - req._add("pathEUR", _pathEUR); - req._add("urlJPY", _urlJPY); - req._add("pathJPY", _pathJPY); - _sendOperatorRequest(req, _payment); - } - - function cancelRequest( - address _oracle, - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); - // solhint-disable-next-line gas-custom-errors - require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); - } - - function addExternalRequest(address _oracle, bytes32 _requestId) external { - _addChainlinkExternalRequest(_oracle, _requestId); - } - - function fulfillMultipleParameters( - bytes32 _requestId, - bytes32 _usd, - bytes32 _eur, - bytes32 _jpy - ) public recordChainlinkFulfillment(_requestId) { - emit RequestMultipleFulfilled(_requestId, _usd, _eur, _jpy); - s_usd = _usd; - s_eur = _eur; - s_jpy = _jpy; - } - - function fulfillMultipleParametersWithCustomURLs( - bytes32 _requestId, - uint256 _usd, - uint256 _eur, - uint256 _jpy - ) public recordChainlinkFulfillment(_requestId) { - emit RequestMultipleFulfilledWithCustomURLs(_requestId, _usd, _eur, _jpy); - s_usdInt = _usd; - s_eurInt = _eur; - s_jpyInt = _jpy; - } - - function fulfillBytes(bytes32 _requestId, bytes memory _price) public recordChainlinkFulfillment(_requestId) { - emit RequestFulfilled(_requestId, _price); - s_currentPrice = _price; - } - - function publicGetNextRequestCount() external view returns (uint256) { - return _getNextRequestCount(); - } - - function getCurrentPrice() public view returns (bytes memory _value) { - return s_currentPrice; - } - - function usd() public view returns (bytes32 _value) { - return s_usd; - } - - function eur() public view returns (bytes32 _value) { - return s_eur; - } - - function jpy() public view returns (bytes32 _value) { - return s_jpy; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol deleted file mode 100644 index 93102d1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/AuthorizedCallers.sol +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {OwnerIsCreator} from "./OwnerIsCreator.sol"; -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/// @title The AuthorizedCallers contract -/// @notice A contract that manages multiple authorized callers. Enables restricting access to certain functions to a set of addresses. -contract AuthorizedCallers is OwnerIsCreator { - using EnumerableSet for EnumerableSet.AddressSet; - - event AuthorizedCallerAdded(address caller); - event AuthorizedCallerRemoved(address caller); - - error UnauthorizedCaller(address caller); - error ZeroAddressNotAllowed(); - - /// @notice Update args for changing the authorized callers - struct AuthorizedCallerArgs { - address[] addedCallers; - address[] removedCallers; - } - - /// @dev Set of authorized callers - EnumerableSet.AddressSet internal s_authorizedCallers; - - /// @param authorizedCallers the authorized callers to set - constructor(address[] memory authorizedCallers) { - _applyAuthorizedCallerUpdates( - AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) - ); - } - - /// @return authorizedCallers Returns all authorized callers - function getAllAuthorizedCallers() external view returns (address[] memory) { - return s_authorizedCallers.values(); - } - - /// @notice Updates the list of authorized callers - /// @param authorizedCallerArgs Callers to add and remove. Removals are performed first. - function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyOwner { - _applyAuthorizedCallerUpdates(authorizedCallerArgs); - } - - /// @notice Updates the list of authorized callers - /// @param authorizedCallerArgs Callers to add and remove. Removals are performed first. - function _applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) internal { - address[] memory removedCallers = authorizedCallerArgs.removedCallers; - for (uint256 i = 0; i < removedCallers.length; ++i) { - address caller = removedCallers[i]; - - if (s_authorizedCallers.remove(caller)) { - emit AuthorizedCallerRemoved(caller); - } - } - - address[] memory addedCallers = authorizedCallerArgs.addedCallers; - for (uint256 i = 0; i < addedCallers.length; ++i) { - address caller = addedCallers[i]; - - if (caller == address(0)) { - revert ZeroAddressNotAllowed(); - } - - s_authorizedCallers.add(caller); - emit AuthorizedCallerAdded(caller); - } - } - - /// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller. - function _validateCaller() internal view { - if (!s_authorizedCallers.contains(msg.sender)) { - revert UnauthorizedCaller(msg.sender); - } - } - - /// @notice Checks the sender and reverts if it is anyone other than a listed authorized caller. - modifier onlyAuthorizedCallers() { - _validateCaller(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol deleted file mode 100644 index 5b0c159..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol"; - -/// @title The ConfirmedOwner contract -/// @notice A contract with helpers for basic contract ownership. -contract ConfirmedOwner is ConfirmedOwnerWithProposal { - constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol deleted file mode 100644 index 2a6dd94..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/ConfirmedOwnerWithProposal.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IOwnable} from "../interfaces/IOwnable.sol"; - -/// @title The ConfirmedOwner contract -/// @notice A contract with helpers for basic contract ownership. -contract ConfirmedOwnerWithProposal is IOwnable { - address private s_owner; - address private s_pendingOwner; - - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - - constructor(address newOwner, address pendingOwner) { - // solhint-disable-next-line gas-custom-errors - require(newOwner != address(0), "Cannot set owner to zero"); - - s_owner = newOwner; - if (pendingOwner != address(0)) { - _transferOwnership(pendingOwner); - } - } - - /// @notice Allows an owner to begin transferring ownership to a new address. - function transferOwnership(address to) public override onlyOwner { - _transferOwnership(to); - } - - /// @notice Allows an ownership transfer to be completed by the recipient. - function acceptOwnership() external override { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == s_pendingOwner, "Must be proposed owner"); - - address oldOwner = s_owner; - s_owner = msg.sender; - s_pendingOwner = address(0); - - emit OwnershipTransferred(oldOwner, msg.sender); - } - - /// @notice Get the current owner - function owner() public view override returns (address) { - return s_owner; - } - - /// @notice validate, transfer ownership, and emit relevant events - function _transferOwnership(address to) private { - // solhint-disable-next-line gas-custom-errors - require(to != msg.sender, "Cannot transfer to self"); - - s_pendingOwner = to; - - emit OwnershipTransferRequested(s_owner, to); - } - - /// @notice validate access - function _validateOwnership() internal view { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == s_owner, "Only callable by owner"); - } - - /// @notice Reverts if called by anyone other than the contract owner. - modifier onlyOwner() { - _validateOwnership(); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol deleted file mode 100644 index 829c687..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/OwnerIsCreator.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "./ConfirmedOwner.sol"; - -/// @title The OwnerIsCreator contract -/// @notice A contract with helpers for basic contract ownership. -contract OwnerIsCreator is ConfirmedOwner { - constructor() ConfirmedOwner(msg.sender) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol deleted file mode 100644 index f4ea905..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleReadAccessController.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {SimpleWriteAccessController} from "./SimpleWriteAccessController.sol"; - -/// @title SimpleReadAccessController -/// @notice Gives access to: -/// - any externally owned account (note that off-chain actors can always read -/// any contract storage regardless of on-chain access control measures, so this -/// does not weaken the access control while improving usability) -/// - accounts explicitly added to an access list -/// @dev SimpleReadAccessController is not suitable for access controlling writes -/// since it grants any externally owned account access! See -/// SimpleWriteAccessController for that. -contract SimpleReadAccessController is SimpleWriteAccessController { - /// @notice Returns the access of an address - /// @param _user The address to query - function hasAccess(address _user, bytes memory _calldata) public view virtual override returns (bool) { - // solhint-disable-next-line avoid-tx-origin - return super.hasAccess(_user, _calldata) || _user == tx.origin; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol deleted file mode 100644 index 5a53bdf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/access/SimpleWriteAccessController.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "./ConfirmedOwner.sol"; -import {AccessControllerInterface} from "../interfaces/AccessControllerInterface.sol"; - -/// @title SimpleWriteAccessController -/// @notice Gives access to accounts explicitly added to an access list by the controller's owner. -/// @dev does not make any special permissions for externally, see SimpleReadAccessController for that. -contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwner { - bool public checkEnabled; - mapping(address => bool) internal s_accessList; - - event AddedAccess(address user); - event RemovedAccess(address user); - event CheckAccessEnabled(); - event CheckAccessDisabled(); - - constructor() ConfirmedOwner(msg.sender) { - checkEnabled = true; - } - - /// @notice Returns the access of an address - /// @param _user The address to query - function hasAccess(address _user, bytes memory) public view virtual override returns (bool) { - return s_accessList[_user] || !checkEnabled; - } - - /// @notice Adds an address to the access list - /// @param _user The address to add - function addAccess(address _user) external onlyOwner { - if (!s_accessList[_user]) { - s_accessList[_user] = true; - - emit AddedAccess(_user); - } - } - - /// @notice Removes an address from the access list - /// @param _user The address to remove - function removeAccess(address _user) external onlyOwner { - if (s_accessList[_user]) { - s_accessList[_user] = false; - - emit RemovedAccess(_user); - } - } - - /// @notice makes the access check enforced - function enableAccessCheck() external onlyOwner { - if (!checkEnabled) { - checkEnabled = true; - - emit CheckAccessEnabled(); - } - } - - /// @notice makes the access check unenforced - function disableAccessCheck() external onlyOwner { - if (checkEnabled) { - checkEnabled = false; - - emit CheckAccessDisabled(); - } - } - - /// @dev reverts if the caller does not have access - modifier checkAccess() { - // solhint-disable-next-line gas-custom-errors - require(hasAccess(msg.sender, msg.data), "No access"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol deleted file mode 100644 index 6716dc1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/call/CallWithExactGas.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice This library contains various callWithExactGas functions. All of them are -/// safe from gas bomb attacks. -/// @dev There is code duplication in this library. This is done to not leave the assembly -/// the blocks. -library CallWithExactGas { - error NoContract(); - error NoGasForCallExactCheck(); - error NotEnoughGasForCall(); - - bytes4 internal constant NO_CONTRACT_SIG = 0x0c3b563c; - bytes4 internal constant NO_GAS_FOR_CALL_EXACT_CHECK_SIG = 0xafa32a2c; - bytes4 internal constant NOT_ENOUGH_GAS_FOR_CALL_SIG = 0x37c3be29; - - /// @notice calls target address with exactly gasAmount gas and payload as calldata. - /// Accounts for gasForCallExactCheck gas that will be used by this function. Will revert - /// if the target is not a contact. Will revert when there is not enough gas to call the - /// target with gasAmount gas. - /// @dev Ignores the return data, which makes it immune to gas bomb attacks. - /// @return success whether the call succeeded - function _callWithExactGas( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck - ) internal returns (bool success) { - assembly { - // solidity calls check that a contract actually exists at the destination, so we do the same - // Note we do this check prior to measuring gas so gasForCallExactCheck (our "cushion") - // doesn't need to account for it. - if iszero(extcodesize(target)) { - mstore(0x0, NO_CONTRACT_SIG) - revert(0x0, 0x4) - } - - let g := gas() - // Compute g -= gasForCallExactCheck and check for underflow - // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. gasForCallExactCheck ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, gasForCallExactCheck) { - mstore(0x0, NO_GAS_FOR_CALL_EXACT_CHECK_SIG) - revert(0x0, 0x4) - } - g := sub(g, gasForCallExactCheck) - // if g - g//64 <= gasAmount, revert. We subtract g//64 because of EIP-150 - if iszero(gt(sub(g, div(g, 64)), gasLimit)) { - mstore(0x0, NOT_ENOUGH_GAS_FOR_CALL_SIG) - revert(0x0, 0x4) - } - - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) - } - return success; - } - - /// @notice calls target address with exactly gasAmount gas and payload as calldata. - /// Account for gasForCallExactCheck gas that will be used by this function. Will revert - /// if the target is not a contact. Will revert when there is not enough gas to call the - /// target with gasAmount gas. - /// @dev Caps the return data length, which makes it immune to gas bomb attacks. - /// @dev Return data cap logic borrowed from - /// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol. - /// @return success whether the call succeeded - /// @return retData the return data from the call, capped at maxReturnBytes bytes - /// @return gasUsed the gas used by the external call. Does not include the overhead of this function. - function _callWithExactGasSafeReturnData( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck, - uint16 maxReturnBytes - ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { - // allocate retData memory ahead of time - retData = new bytes(maxReturnBytes); - - assembly { - // solidity calls check that a contract actually exists at the destination, so we do the same - // Note we do this check prior to measuring gas so gasForCallExactCheck (our "cushion") - // doesn't need to account for it. - if iszero(extcodesize(target)) { - mstore(0x0, NO_CONTRACT_SIG) - revert(0x0, 0x4) - } - - let g := gas() - // Compute g -= gasForCallExactCheck and check for underflow - // The gas actually passed to the callee is _min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. gasForCallExactCheck ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, gasForCallExactCheck) { - mstore(0x0, NO_GAS_FOR_CALL_EXACT_CHECK_SIG) - revert(0x0, 0x4) - } - g := sub(g, gasForCallExactCheck) - // if g - g//64 <= gasAmount, revert. We subtract g//64 because of EIP-150 - if iszero(gt(sub(g, div(g, 64)), gasLimit)) { - mstore(0x0, NOT_ENOUGH_GAS_FOR_CALL_SIG) - revert(0x0, 0x4) - } - - // We save the gas before the call so we can calculate how much gas the call used - let gasBeforeCall := gas() - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) - gasUsed := sub(gasBeforeCall, gas()) - - // limit our copy to maxReturnBytes bytes - let toCopy := returndatasize() - if gt(toCopy, maxReturnBytes) { - toCopy := maxReturnBytes - } - // Store the length of the copied bytes - mstore(retData, toCopy) - // copy the bytes from retData[0:_toCopy] - returndatacopy(add(retData, 0x20), 0x0, toCopy) - } - return (success, retData, gasUsed); - } - - /// @notice Calls target address with exactly gasAmount gas and payload as calldata - /// or reverts if at least gasLimit gas is not available. - /// @dev Does not check if target is a contract. If it is not a contract, the low-level - /// call will still be made and it will succeed. - /// @dev Ignores the return data, which makes it immune to gas bomb attacks. - /// @return success whether the call succeeded - /// @return sufficientGas Whether there was enough gas to make the call - function _callWithExactGasEvenIfTargetIsNoContract( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck - ) internal returns (bool success, bool sufficientGas) { - assembly { - let g := gas() - // Compute g -= CALL_WITH_EXACT_GAS_CUSHION and check for underflow. We - // need the cushion since the logic following the above call to gas also - // costs gas which we cannot account for exactly. So cushion is a - // conservative upper bound for the cost of this logic. - if iszero(lt(g, gasForCallExactCheck)) { - g := sub(g, gasForCallExactCheck) - // If g - g//64 <= gasAmount, we don't have enough gas. We subtract g//64 because of EIP-150. - if gt(sub(g, div(g, 64)), gasLimit) { - // Call and ignore success/return data. Note that we did not check - // whether a contract actually exists at the target address. - success := call(gasLimit, target, 0, add(payload, 0x20), mload(payload), 0x0, 0x0) - sufficientGas := true - } - } - } - return (success, sufficientGas); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol deleted file mode 100644 index c14a03b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapAddresses.sol +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: MIT -/* solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore */ -pragma solidity ^0.8.0; - -import {EnumerableMap} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol"; -import {EnumerableMapBytes32} from "./EnumerableMapBytes32.sol"; - -// TODO: the lib can be replaced with OZ v5.1 post-upgrade, which has AddressToAddressMap and AddressToBytes32Map -library EnumerableMapAddresses { - using EnumerableMap for EnumerableMap.UintToAddressMap; - using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map; - using EnumerableMapBytes32 for EnumerableMapBytes32.Bytes32ToBytesMap; - - struct AddressToAddressMap { - EnumerableMap.UintToAddressMap _inner; - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) { - return map._inner.set(uint256(uint160(key)), value); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function remove(AddressToAddressMap storage map, address key) internal returns (bool) { - return map._inner.remove(uint256(uint160(key))); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { - return map._inner.contains(uint256(uint160(key))); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function length(AddressToAddressMap storage map) internal view returns (uint256) { - return map._inner.length(); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) { - (uint256 key, address value) = map._inner.at(index); - return (address(uint160(key)), value); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) { - return map._inner.tryGet(uint256(uint160(key))); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function get(AddressToAddressMap storage map, address key) internal view returns (address) { - return map._inner.get(uint256(uint160(key))); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function get( - AddressToAddressMap storage map, - address key, - string memory errorMessage - ) internal view returns (address) { - return map._inner.get(uint256(uint160(key)), errorMessage); - } - - struct AddressToBytes32Map { - EnumerableMap.Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) { - return map._inner.set(bytes32(uint256(uint160(key))), value); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function remove(AddressToBytes32Map storage map, address key) internal returns (bool) { - return map._inner.remove(bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) { - return map._inner.contains(bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function length(AddressToBytes32Map storage map) internal view returns (uint256) { - return map._inner.length(); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address, bytes32) { - (bytes32 key, bytes32 value) = map._inner.at(index); - return (address(uint160(uint256(key))), value); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool, bytes32) { - (bool success, bytes32 value) = map._inner.tryGet(bytes32(uint256(uint160(key)))); - return (success, value); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) { - return map._inner.get(bytes32(uint256(uint160(key)))); - } - - struct AddressToBytesMap { - EnumerableMapBytes32.Bytes32ToBytesMap _inner; - } - - /** - * @dev Sets the value for `key` in the map. Returns true if the key was added to the map, that is if it was not already present. - * @param map The map where the value will be set - * @param key The key to set the value for - * @param value The value to set for the key - * @return bool indicating whether the key was added to the map - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function set(AddressToBytesMap storage map, address key, bytes memory value) internal returns (bool) { - return map._inner.set(bytes32(uint256(uint160(key))), value); - } - - /** - * @dev Removes the value for `key` in the map. Returns true if the key was removed from the map, that is if it was present. - * @param map The map where the value will be removed - * @param key The key to remove the value for - * @return bool indicating whether the key was removed from the map - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function remove(AddressToBytesMap storage map, address key) internal returns (bool) { - return map._inner.remove(bytes32(uint256(uint160(key)))); - } - - /** - * @dev Checks if the map contains the `key`. Returns true if the key is in the map. - * @param map The map to check for the presence of the key - * @param key The key to check for presence in the map - * @return bool indicating whether the key is in the map - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function contains(AddressToBytesMap storage map, address key) internal view returns (bool) { - return map._inner.contains(bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. - * @param map The map to check the length of - * @return uint256 indicating the number of elements in the map - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function length(AddressToBytesMap storage map) internal view returns (uint256) { - return map._inner.length(); - } - - /** - * @dev Returns the element stored at position `index` in the map. Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed. - * @param map The map to retrieve the element from - * @param index The index to retrieve the element at - * @return address The key of the element at the specified index - * @return bytes The value of the element at the specified index - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function at(AddressToBytesMap storage map, uint256 index) internal view returns (address, bytes memory) { - (bytes32 key, bytes memory value) = map._inner.at(index); - return (address(uint160(uint256(key))), value); - } - - /** - * @dev Tries to return the value associated with `key`. Does not revert if `key` is not in the map. - * @param map The map to retrieve the value from - * @param key The key to retrieve the value for - * @return bool indicating whether the key was in the map - * @return bytes The value associated with the key - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function tryGet(AddressToBytesMap storage map, address key) internal view returns (bool, bytes memory) { - return map._inner.tryGet(bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the value associated with `key`. - * @param map The map to retrieve the value from - * @param key The key to retrieve the value for - * @return bytes The value associated with the key - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function get(AddressToBytesMap storage map, address key) internal view returns (bytes memory) { - return map._inner.get(bytes32(uint256(uint160(key)))); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol deleted file mode 100644 index 2ec9098..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableMapBytes32.sol +++ /dev/null @@ -1,136 +0,0 @@ -// SPDX-License-Identifier: MIT -/* solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore */ -pragma solidity ^0.8.0; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; - -/** - * @dev Library for managing an enumerable variant of Solidity's - * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] - * type. - * - * Maps have the following properties: - * - * - Entries are added, removed, and checked for existence in constant time - * (O(1)). - * - Entries are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableMapBytes32 for EnumerableMapBytes32.Bytes32ToBytesMap; - * - * // Declare a set state variable - * EnumerableMapBytes32.Bytes32ToBytesMap private myMap; - * } - * ``` - * - * The following map types are supported: - * - * - `bytes32 -> bytes` (`Bytes32ToBytes`) - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean up an EnumerableMapBytes32, you should remove all elements one by one. - * ==== - */ -library EnumerableMapBytes32 { - using EnumerableSet for EnumerableSet.Bytes32Set; - - error NonexistentKeyError(); - - struct Bytes32ToBytesMap { - EnumerableSet.Bytes32Set _keys; - mapping(bytes32 => bytes) _values; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function set(Bytes32ToBytesMap storage map, bytes32 key, bytes memory value) internal returns (bool) { - map._values[key] = value; - return map._keys.add(key); - } - - /** - * @dev Removes a key-value pair from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function remove(Bytes32ToBytesMap storage map, bytes32 key) internal returns (bool) { - delete map._values[key]; - return map._keys.remove(key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function contains(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool) { - return map._keys.contains(key); - } - - /** - * @dev Returns the number of key-value pairs in the map. O(1). - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function length(Bytes32ToBytesMap storage map) internal view returns (uint256) { - return map._keys.length(); - } - - /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). - * - * Note that there are no guarantees on the ordering of entries inside the - * array, and it may change when more entries are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function at(Bytes32ToBytesMap storage map, uint256 index) internal view returns (bytes32, bytes memory) { - bytes32 key = map._keys.at(index); - return (key, map._values[key]); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function tryGet(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bool, bytes memory) { - bytes memory value = map._values[key]; - if (value.length == 0) { - return (contains(map, key), bytes("")); - } else { - return (true, value); - } - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function get(Bytes32ToBytesMap storage map, bytes32 key) internal view returns (bytes memory) { - bytes memory value = map._values[key]; - if (value.length == 0 && !contains(map, key)) { - revert NonexistentKeyError(); - } - return value; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol deleted file mode 100644 index b780967..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol +++ /dev/null @@ -1,454 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. - -/// @dev this is a fully copy of OZ's EnumerableSet library with the addition of a Bytes16Set - -pragma solidity ^0.8.0; - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ```solidity - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position is the index of the value in the `values` array plus 1. - // Position 0 is used to mean a value is not in the set. - mapping(bytes32 value => uint256) _positions; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._positions[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We cache the value's position to prevent multiple reads from the same storage slot - uint256 position = set._positions[value]; - - if (position != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 valueIndex = position - 1; - uint256 lastIndex = set._values.length - 1; - - if (valueIndex != lastIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the lastValue to the index where the value to delete is - set._values[valueIndex] = lastValue; - // Update the tracked position of the lastValue (that was just moved) - set._positions[lastValue] = position; - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the tracked position for the deleted slot - delete set._positions[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._positions[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - bytes32[] memory store = _values(set._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // Bytes16Set - - struct Bytes16Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes16Set storage set, bytes16 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes16Set storage set, bytes16 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes16Set storage set, bytes16 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes16Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes16Set storage set, uint256 index) internal view returns (bytes16) { - return bytes16(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes16Set storage set) internal view returns (bytes16[] memory) { - bytes32[] memory store = _values(set._inner); - bytes16[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol deleted file mode 100644 index cc51e85..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AccessControllerInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface AccessControllerInterface { - function hasAccess(address user, bytes calldata data) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol deleted file mode 100644 index 0ee4aa5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface AggregatorInterface { - function latestAnswer() external view returns (int256); - - function latestTimestamp() external view returns (uint256); - - function latestRound() external view returns (uint256); - - function getAnswer(uint256 roundId) external view returns (int256); - - function getTimestamp(uint256 roundId) external view returns (uint256); - - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - - event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol deleted file mode 100644 index 7e27915..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AggregatorInterface} from "./AggregatorInterface.sol"; -import {AggregatorV3Interface} from "./AggregatorV3Interface.sol"; - -// solhint-disable-next-line interface-starts-with-i -interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol deleted file mode 100644 index 2ba1925..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface AggregatorV3Interface { - function decimals() external view returns (uint8); - - function description() external view returns (string memory); - - function version() external view returns (uint256); - - function getRoundData( - uint80 _roundId - ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); - - function latestRoundData() - external - view - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol deleted file mode 100644 index f654cda..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/AggregatorValidatorInterface.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface AggregatorValidatorInterface { - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol deleted file mode 100644 index 07cb7a1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IAccessController.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IAccessController { - function hasAccess(address user, bytes calldata data) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol deleted file mode 100644 index 5cb8cfc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IERC677Receiver.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -interface IERC677Receiver { - function onTokenTransfer(address sender, uint256 amount, bytes calldata data) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol deleted file mode 100644 index 3141fe9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IOwnable.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IOwnable { - function owner() external returns (address); - - function transferOwnership(address recipient) external; - - function acceptOwnership() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol deleted file mode 100644 index 135f6d0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/ITypeAndVersion.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface ITypeAndVersion { - function typeAndVersion() external pure returns (string memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol deleted file mode 100644 index 9607353..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/IWERC20.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IWERC20 { - function deposit() external payable; - - function withdraw(uint256) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol deleted file mode 100644 index b23736b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/interfaces/LinkTokenInterface.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface LinkTokenInterface { - function allowance(address owner, address spender) external view returns (uint256 remaining); - - function approve(address spender, uint256 value) external returns (bool success); - - function balanceOf(address owner) external view returns (uint256 balance); - - function decimals() external view returns (uint8 decimalPlaces); - - function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); - - function increaseApproval(address spender, uint256 subtractedValue) external; - - function name() external view returns (string memory tokenName); - - function symbol() external view returns (string memory tokenSymbol); - - function totalSupply() external view returns (uint256 totalTokensIssued); - - function transfer(address to, uint256 value) external returns (bool success); - - function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); - - function transferFrom(address from, address to, uint256 value) external returns (bool success); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol deleted file mode 100644 index 6155b38..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/mocks/WERC20Mock.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; - -contract WERC20Mock is ERC20 { - constructor() ERC20("WERC20Mock", "WERC") {} - - event Deposit(address indexed dst, uint256 wad); - event Withdrawal(address indexed src, uint256 wad); - - receive() external payable { - deposit(); - } - - function deposit() public payable { - _mint(msg.sender, msg.value); - emit Deposit(msg.sender, msg.value); - } - - function withdraw(uint256 wad) public { - // solhint-disable-next-line gas-custom-errors, reason-string - require(balanceOf(msg.sender) >= wad); - _burn(msg.sender, wad); - payable(msg.sender).transfer(wad); - emit Withdrawal(msg.sender, wad); - } - - function mint(address account, uint256 amount) external { - _mint(account, amount); - } - - function burn(address account, uint256 amount) external { - _burn(account, amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol deleted file mode 100644 index cd3f197..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Abstract.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ITypeAndVersion} from "../interfaces/ITypeAndVersion.sol"; - -abstract contract OCR2Abstract is ITypeAndVersion { - uint256 internal constant MAX_NUM_ORACLES = 31; - uint256 private constant PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..00 - uint256 private constant PREFIX = 0x0001 << (256 - 16); // 0x000100..00 - - /// @notice triggers a new run of the offchain reporting protocol - /// @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis - /// @param configDigest configDigest of this configuration - /// @param configCount ordinal number of this config setting among all config settings over the life of this contract - /// @param signers ith element is address ith oracle uses to sign a report - /// @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method - /// @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - event ConfigSet( - uint32 previousConfigBlockNumber, - bytes32 configDigest, - uint64 configCount, - address[] signers, - address[] transmitters, - uint8 f, - bytes onchainConfig, - uint64 offchainConfigVersion, - bytes offchainConfig - ); - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param signers addresses with which oracles sign the reports - /// @param transmitters addresses oracles use to transmit the reports - /// @param f number of faulty oracles the system can tolerate - /// @param onchainConfig serialized configuration used by the contract (and possibly oracles) - /// @param offchainConfigVersion version number for offchainEncoding schema - /// @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract - function setConfig( - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) external virtual; - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see _configDigestFromConfigData) - function latestConfigDetails() - external - view - virtual - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest); - - function _configDigestFromConfigData( - uint256 chainId, - address contractAddress, - uint64 configCount, - address[] memory signers, - address[] memory transmitters, - uint8 f, - bytes memory onchainConfig, - uint64 offchainConfigVersion, - bytes memory offchainConfig - ) internal pure returns (bytes32) { - uint256 h = uint256( - keccak256( - abi.encode( - chainId, - contractAddress, - configCount, - signers, - transmitters, - f, - onchainConfig, - offchainConfigVersion, - offchainConfig - ) - ) - ); - return bytes32((PREFIX & PREFIX_MASK) | (h & ~PREFIX_MASK)); - } - - /// @notice optionally emitted to indicate the latest configDigest and epoch for - /// which a report was successfully transmitted. Alternatively, the contract may - /// use latestConfigDigestAndEpoch with scanLogs set to false. - event Transmitted(bytes32 configDigest, uint32 epoch); - - /// @notice optionally returns the latest configDigest and epoch for which a - /// report was successfully transmitted. Alternatively, the contract may return - /// scanLogs set to true and use Transmitted events to provide this information - /// to offchain watchers. - /// @return scanLogs indicates whether to rely on the configDigest and epoch - /// returned or whether to scan logs for the Transmitted event instead. - /// @return configDigest - /// @return epoch - function latestConfigDigestAndEpoch() - external - view - virtual - returns (bool scanLogs, bytes32 configDigest, uint32 epoch); - - /// @notice transmit is called to post a new report to the contract - /// @param reportContext [0]: ConfigDigest, [1]: 27 byte padding, 4-byte epoch and 1-byte round, [2]: ExtraHash - /// @param report serialized report, which the signatures are signing. - /// @param rs ith element is the R components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param ss ith element is the S components of the ith signature on report. Must have at most MAX_NUM_ORACLES entries - /// @param rawVs ith element is the the V component of the ith signature - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external virtual; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol deleted file mode 100644 index 1dfc21f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/OCR2Base.sol +++ /dev/null @@ -1,330 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {OwnerIsCreator} from "../access/OwnerIsCreator.sol"; -import {OCR2Abstract} from "./OCR2Abstract.sol"; - -/// @notice Onchain verification of reports from the offchain reporting protocol -/// @dev THIS CONTRACT HAS NOT GONE THROUGH ANY SECURITY REVIEW. DO NOT USE IN PROD. -/// @dev For details on its operation, see the offchain reporting protocol design -/// doc, which refers to this contract as simply the "contract". -/// @dev This contract is meant to aid rapid development of new applications based on OCR2. -/// However, for actual production contracts, it is expected that most of the logic of this contract -/// will be folded directly into the application contract. Inheritance prevents us from doing lots -/// of juicy storage layout optimizations, leading to a substantial increase in gas cost. -// solhint-disable gas-custom-errors -abstract contract OCR2Base is OwnerIsCreator, OCR2Abstract { - error ReportInvalid(); - - bool internal immutable i_uniqueReports; - - constructor(bool uniqueReports) OwnerIsCreator() { - i_uniqueReports = uniqueReports; - } - - /// @dev Storing these fields used on the hot path in a ConfigInfo variable reduces - /// the retrieval of all of them to a single SLOAD. If any further fields are - /// added, make sure that storage of the struct still takes at most 32 bytes. - struct ConfigInfo { - bytes32 latestConfigDigest; - uint8 f; // ───╮ - uint8 n; // ───╯ - } - ConfigInfo internal s_configInfo; - - /// @dev Incremented each time a new config is posted. This count is incorporated - /// into the config digest, to prevent replay attacks. - uint32 internal s_configCount; - /// @dev Makes it easier for offchain systems to extract config from logs. - uint32 internal s_latestConfigBlockNumber; - - /// @dev Used for s_oracles[a].role, where a is an address, to track the purpose - /// of the address, or to indicate that the address is unset. - enum Role { - // No oracle role has been set for address a - Unset, - // Signing address for the s_oracles[a].index'th oracle. I.e., report - // signatures from this oracle should ecrecover back to address a. - Signer, - // Transmission address for the s_oracles[a].index'th oracle. I.e., if a - // report is received by OCR2Aggregator.transmit in which msg.sender is - // a, it is attributed to the s_oracles[a].index'th oracle. - Transmitter - } - - struct Oracle { - uint8 index; // ───╮ Index of oracle in s_signers/s_transmitters - Role role; // ─────╯ Role of the address which mapped to this struct - } - - mapping(address => Oracle) /* signer OR transmitter address */ internal s_oracles; - - /// @notice Contains the signing address of each oracle - address[] internal s_signers; - - /// @notice Contains the transmission address of each oracle, - /// i.e. the address the oracle actually sends transactions to the contract from - address[] internal s_transmitters; - - /// @dev Reverts transaction if config args are invalid - modifier checkConfigValid(uint256 _numSigners, uint256 _numTransmitters, uint256 _f) { - require(_numSigners <= MAX_NUM_ORACLES, "too many signers"); - require(_f > 0, "f must be positive"); - require(_numSigners == _numTransmitters, "oracle addresses out of registration"); - require(_numSigners > 3 * _f, "faulty-oracle f too high"); - _; - } - - // solhint-disable-next-line gas-struct-packing - struct SetConfigArgs { - address[] signers; - address[] transmitters; - uint8 f; - bytes onchainConfig; - uint64 offchainConfigVersion; - bytes offchainConfig; - } - - /// @inheritdoc OCR2Abstract - function latestConfigDigestAndEpoch() - external - view - virtual - override - returns (bool scanLogs, bytes32 configDigest, uint32 epoch) - { - return (true, bytes32(0), uint32(0)); - } - - /// @notice sets offchain reporting protocol configuration incl. participating oracles - /// @param _signers addresses with which oracles sign the reports - /// @param _transmitters addresses oracles use to transmit the reports - /// @param _f number of faulty oracles the system can tolerate - /// @param _onchainConfig encoded on-chain contract configuration - /// @param _offchainConfigVersion version number for offchainEncoding schema - /// @param _offchainConfig encoded off-chain oracle configuration - function setConfig( - address[] memory _signers, - address[] memory _transmitters, - uint8 _f, - bytes memory _onchainConfig, - uint64 _offchainConfigVersion, - bytes memory _offchainConfig - ) external override checkConfigValid(_signers.length, _transmitters.length, _f) onlyOwner { - SetConfigArgs memory args = SetConfigArgs({ - signers: _signers, - transmitters: _transmitters, - f: _f, - onchainConfig: _onchainConfig, - offchainConfigVersion: _offchainConfigVersion, - offchainConfig: _offchainConfig - }); - - _beforeSetConfig(args.f, args.onchainConfig); - - while (s_signers.length != 0) { - // remove any old signer/transmitter addresses - uint256 lastIdx = s_signers.length - 1; - address signer = s_signers[lastIdx]; - address transmitter = s_transmitters[lastIdx]; - delete s_oracles[signer]; - delete s_oracles[transmitter]; - s_signers.pop(); - s_transmitters.pop(); - } - - for (uint256 i = 0; i < args.signers.length; ++i) { - // add new signer/transmitter addresses - require(s_oracles[args.signers[i]].role == Role.Unset, "repeated signer address"); - s_oracles[args.signers[i]] = Oracle(uint8(i), Role.Signer); - require(s_oracles[args.transmitters[i]].role == Role.Unset, "repeated transmitter address"); - s_oracles[args.transmitters[i]] = Oracle(uint8(i), Role.Transmitter); - s_signers.push(args.signers[i]); - s_transmitters.push(args.transmitters[i]); - } - s_configInfo.f = args.f; - uint32 previousConfigBlockNumber = s_latestConfigBlockNumber; - s_latestConfigBlockNumber = uint32(block.number); - s_configCount += 1; - { - s_configInfo.latestConfigDigest = _configDigestFromConfigData( - block.chainid, - address(this), - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - } - s_configInfo.n = uint8(args.signers.length); - - emit ConfigSet( - previousConfigBlockNumber, - s_configInfo.latestConfigDigest, - s_configCount, - args.signers, - args.transmitters, - args.f, - args.onchainConfig, - args.offchainConfigVersion, - args.offchainConfig - ); - - _afterSetConfig(args.f, args.onchainConfig); - } - - /// @notice information about current offchain reporting protocol configuration - /// @return configCount ordinal number of current config, out of all configs applied to this contract so far - /// @return blockNumber block at which this config was set - /// @return configDigest domain-separation tag for current config (see configDigestFromConfigData) - function latestConfigDetails() - external - view - override - returns (uint32 configCount, uint32 blockNumber, bytes32 configDigest) - { - return (s_configCount, s_latestConfigBlockNumber, s_configInfo.latestConfigDigest); - } - - /// @return list of addresses permitted to transmit reports to this contract - /// @dev The list will match the order used to specify the transmitter during setConfig - function transmitters() external view returns (address[] memory) { - return s_transmitters; - } - - function _beforeSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - function _afterSetConfig(uint8 _f, bytes memory _onchainConfig) internal virtual; - - /// @dev hook to allow additional validation of the report by the extending contract - /// @param configDigest separation tag for current config (see configDigestFromConfigData) - /// @param epochAndRound 27 byte padding, 4-byte epoch and 1-byte round - /// @param report serialized report - function _validateReport( - bytes32 configDigest, - uint40 epochAndRound, - bytes memory report - ) internal virtual returns (bool); - - /// @dev hook called after the report has been fully validated - /// for the extending contract to handle additional logic, such as oracle payment - /// @param initialGas the amount of gas before validation - /// @param transmitter the address of the account that submitted the report - /// @param signers the addresses of all signing accounts - /// @param report serialized report - function _report( - uint256 initialGas, - address transmitter, - uint8 signerCount, - address[MAX_NUM_ORACLES] memory signers, - bytes calldata report - ) internal virtual; - - // The constant-length components of the msg.data sent to transmit. - // See the "If we wanted to call sam" example on for example reasoning - // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html - uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT = - 4 + // function selector - 32 * - 3 + // 3 words containing reportContext - 32 + // word containing start location of abiencoded report value - 32 + // word containing location start of abiencoded rs value - 32 + // word containing start location of abiencoded ss value - 32 + // rawVs value - 32 + // word containing length of report - 32 + // word containing length rs - 32 + // word containing length of ss - 0; // placeholder - - function _requireExpectedMsgDataLength( - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss - ) private pure { - // calldata will never be big enough to make this overflow - uint256 expected = uint256(TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT) + - report.length + // one byte pure entry in _report - rs.length * - 32 + // 32 bytes per entry in _rs - ss.length * - 32 + // 32 bytes per entry in _ss - 0; // placeholder - require(msg.data.length == expected, "calldata length mismatch"); - } - - /// @notice transmit is called to post a new report to the contract - /// @param report serialized report, which the signatures are signing. - /// @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries - /// @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries - /// @param rawVs ith element is the the V component of the ith signature - function transmit( - // NOTE: If these parameters are changed, expectedMsgDataLength and/or - // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly - bytes32[3] calldata reportContext, - bytes calldata report, - bytes32[] calldata rs, - bytes32[] calldata ss, - bytes32 rawVs // signatures - ) external override { - uint256 initialGas = gasleft(); // This line must come first - - { - // reportContext consists of: - // reportContext[0]: ConfigDigest - // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round - // reportContext[2]: ExtraHash - bytes32 configDigest = reportContext[0]; - uint32 epochAndRound = uint32(uint256(reportContext[1])); - - if (!_validateReport(configDigest, epochAndRound, report)) { - revert ReportInvalid(); - } - - emit Transmitted(configDigest, uint32(epochAndRound >> 8)); - - ConfigInfo memory configInfo = s_configInfo; - require(configInfo.latestConfigDigest == configDigest, "configDigest mismatch"); - - _requireExpectedMsgDataLength(report, rs, ss); - - uint256 expectedNumSignatures; - if (i_uniqueReports) { - expectedNumSignatures = (configInfo.n + configInfo.f) / 2 + 1; - } else { - expectedNumSignatures = configInfo.f + 1; - } - - require(rs.length == expectedNumSignatures, "wrong number of signatures"); - require(rs.length == ss.length, "signatures out of registration"); - - Oracle memory transmitter = s_oracles[msg.sender]; - require( // Check that sender is authorized to report - transmitter.role == Role.Transmitter && msg.sender == s_transmitters[transmitter.index], - "unauthorized transmitter" - ); - } - - address[MAX_NUM_ORACLES] memory signed; - uint8 signerCount = 0; - - { - // Verify signatures attached to report - bytes32 h = keccak256(abi.encodePacked(keccak256(report), reportContext)); - - Oracle memory o; - for (uint256 i = 0; i < rs.length; ++i) { - address signer = ecrecover(h, uint8(rawVs[i]) + 27, rs[i], ss[i]); - o = s_oracles[signer]; - require(o.role == Role.Signer, "address not authorized to sign"); - require(signed[o.index] == address(0), "non-unique signature"); - signed[o.index] = signer; - signerCount += 1; - } - } - - _report(initialGas, msg.sender, signerCount, signed, report); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md deleted file mode 100644 index e7ccc51..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/ocr2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# OCR2 Rapid Prototype Contracts - -The contracts in this directory are to aid rapid prototyping of OCR2 based products. They abstract OCR2 config and boilerplate code so that specific logic can be implemented and tested quickly. They are not optimized or audited. - -Do not use these contracts in production. For actual production contracts, it is expected that most of the logic of these contracts will be folded directly into the application contract. \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol deleted file mode 100644 index 4d8ef60..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/BaseTest.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import "forge-std/Test.sol"; - -contract BaseTest is Test { - bool private s_baseTestInitialized; - address internal constant OWNER = 0x72da681452Ab957d1020c25fFaCA47B43980b7C3; - address internal constant STRANGER = 0x02e7d5DD1F4dDbC9f512FfA01d30aa190Ae3edBb; - - // Fri May 26 2023 13:49:53 GMT+0000 - uint256 internal constant BLOCK_TIME = 1685108993; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - vm.label(OWNER, "Owner"); - vm.label(STRANGER, "Stranger"); - - // Set the sender to OWNER permanently - vm.startPrank(OWNER); - deal(OWNER, 1e20); - - // Set the block time to a constant known value - vm.warp(BLOCK_TIME); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol deleted file mode 100644 index 34ae684..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/access/AuthorizedCallers.t.sol +++ /dev/null @@ -1,186 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {AuthorizedCallers} from "../../access/AuthorizedCallers.sol"; -import {BaseTest} from "../BaseTest.t.sol"; - -contract AuthorizedCallers_setup is BaseTest { - address[] s_callers; - - AuthorizedCallers s_authorizedCallers; - - function setUp() public override { - super.setUp(); - s_callers.push(makeAddr("caller1")); - s_callers.push(makeAddr("caller2")); - - s_authorizedCallers = new AuthorizedCallers(s_callers); - } -} - -contract AuthorizedCallers_constructor is AuthorizedCallers_setup { - event AuthorizedCallerAdded(address caller); - - function test_constructor_Success() public { - for (uint256 i = 0; i < s_callers.length; ++i) { - vm.expectEmit(); - emit AuthorizedCallerAdded(s_callers[i]); - } - - s_authorizedCallers = new AuthorizedCallers(s_callers); - - assertEq(s_callers, s_authorizedCallers.getAllAuthorizedCallers()); - } - - function test_ZeroAddressNotAllowed_Revert() public { - s_callers[0] = address(0); - - vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - - new AuthorizedCallers(s_callers); - } -} - -contract AuthorizedCallers_applyAuthorizedCallerUpdates is AuthorizedCallers_setup { - event AuthorizedCallerAdded(address caller); - event AuthorizedCallerRemoved(address caller); - - function test_OnlyAdd_Success() public { - address[] memory addedCallers = new address[](2); - addedCallers[0] = vm.addr(3); - addedCallers[1] = vm.addr(4); - - address[] memory removedCallers = new address[](0); - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); - - vm.expectEmit(); - emit AuthorizedCallerAdded(addedCallers[0]); - vm.expectEmit(); - emit AuthorizedCallerAdded(addedCallers[1]); - - s_authorizedCallers.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - address[] memory expectedCallers = new address[](4); - expectedCallers[0] = s_callers[0]; - expectedCallers[1] = s_callers[1]; - expectedCallers[2] = addedCallers[0]; - expectedCallers[3] = addedCallers[1]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); - } - - function test_OnlyRemove_Success() public { - address[] memory addedCallers = new address[](0); - address[] memory removedCallers = new address[](1); - removedCallers[0] = s_callers[0]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); - - vm.expectEmit(); - emit AuthorizedCallerRemoved(removedCallers[0]); - - s_authorizedCallers.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - address[] memory expectedCallers = new address[](1); - expectedCallers[0] = s_callers[1]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); - } - - function test_AddAndRemove_Success() public { - address[] memory addedCallers = new address[](2); - addedCallers[0] = address(42); - addedCallers[1] = address(43); - - address[] memory removedCallers = new address[](1); - removedCallers[0] = s_callers[0]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); - - vm.expectEmit(); - emit AuthorizedCallerRemoved(removedCallers[0]); - vm.expectEmit(); - emit AuthorizedCallerAdded(addedCallers[0]); - vm.expectEmit(); - emit AuthorizedCallerAdded(addedCallers[1]); - - s_authorizedCallers.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - // Order of the set changes on removal - address[] memory expectedCallers = new address[](3); - expectedCallers[0] = s_callers[1]; - expectedCallers[1] = addedCallers[0]; - expectedCallers[2] = addedCallers[1]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); - } - - function test_RemoveThenAdd_Success() public { - address[] memory addedCallers = new address[](1); - addedCallers[0] = s_callers[0]; - - address[] memory removedCallers = new address[](1); - removedCallers[0] = s_callers[0]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); - - vm.expectEmit(); - emit AuthorizedCallerRemoved(removedCallers[0]); - - vm.expectEmit(); - emit AuthorizedCallerAdded(addedCallers[0]); - - s_authorizedCallers.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - address[] memory expectedCallers = new address[](2); - expectedCallers[0] = s_callers[1]; - expectedCallers[1] = s_callers[0]; - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), expectedCallers); - } - - function test_SkipRemove_Success() public { - address[] memory addedCallers = new address[](0); - - address[] memory removedCallers = new address[](1); - removedCallers[0] = address(42); - - vm.recordLogs(); - s_authorizedCallers.applyAuthorizedCallerUpdates( - AuthorizedCallers.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - assertEq(s_authorizedCallers.getAllAuthorizedCallers(), s_callers); - assertEq(vm.getRecordedLogs().length, 0); - } - - function test_OnlyCallableByOwner_Revert() public { - vm.stopPrank(); - - AuthorizedCallers.AuthorizedCallerArgs memory authorizedCallerArgs = AuthorizedCallers.AuthorizedCallerArgs({ - addedCallers: new address[](0), - removedCallers: new address[](0) - }); - - vm.expectRevert("Only callable by owner"); - - s_authorizedCallers.applyAuthorizedCallerUpdates(authorizedCallerArgs); - } - - function test_ZeroAddressNotAllowed_Revert() public { - s_callers[0] = address(0); - - vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - - new AuthorizedCallers(s_callers); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol deleted file mode 100644 index 3623cb8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol +++ /dev/null @@ -1,512 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {CallWithExactGas} from "../../call/CallWithExactGas.sol"; -import {CallWithExactGasHelper} from "./CallWithExactGasHelper.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {GenericReceiver} from "../testhelpers/GenericReceiver.sol"; -import {GasConsumer} from "../testhelpers/GasConsumer.sol"; - -contract CallWithExactGasSetup is BaseTest { - GenericReceiver internal s_receiver; - CallWithExactGasHelper internal s_caller; - GasConsumer internal s_gasConsumer; - - uint256 internal constant DEFAULT_GAS_LIMIT = 20_000; - uint16 internal constant DEFAULT_GAS_FOR_CALL_EXACT_CHECK = 5000; - uint256 internal constant EXTCODESIZE_GAS_COST = 2600; - - function setUp() public virtual override { - BaseTest.setUp(); - - s_receiver = new GenericReceiver(false); - s_caller = new CallWithExactGasHelper(); - s_gasConsumer = new GasConsumer(); - } -} - -contract CallWithExactGas__callWithExactGas is CallWithExactGasSetup { - function test_callWithExactGasSuccess(bytes memory payload, bytes4 funcSelector) public { - vm.pauseGasMetering(); - - bytes memory data = abi.encodeWithSelector(funcSelector, payload); - vm.assume( - funcSelector != GenericReceiver.setRevert.selector && - funcSelector != GenericReceiver.setErr.selector && - funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector - ); - - vm.expectCall(address(s_receiver), data); - vm.resumeGasMetering(); - - bool success = s_caller.callWithExactGas( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - assertTrue(success); - } - - function test_CallWithExactGasSafeReturnDataExactGas() public { - // The calculated overhead for otherwise unaccounted for gas usage - uint256 overheadForCallWithExactGas = 364; - - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGas.selector, - "", - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - // Since only 63/64th of the gas gets passed, we compensate - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); - - allowedGas += EXTCODESIZE_GAS_COST + DEFAULT_GAS_FOR_CALL_EXACT_CHECK + overheadForCallWithExactGas; - - // Due to EIP-150 we expect to lose 1/64, so we compensate for this - allowedGas = (allowedGas * 64) / 63; - - (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); - - assertTrue(success); - assertEq(abi.encode(true), retData); - } - - function test_CallWithExactGasReceiverErrorSuccess() public { - bytes memory data = abi.encode("0x52656E73"); - - bytes memory errorData = new bytes(20); - for (uint256 i = 0; i < errorData.length; ++i) { - errorData[i] = 0x01; - } - s_receiver.setErr(errorData); - s_receiver.setRevert(true); - - vm.expectCall(address(s_receiver), data); - - bool success = s_caller.callWithExactGas( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT * 10, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - assertFalse(success); - } - - function test_NoContractReverts() public { - address addressWithoutContract = address(1337); - - vm.expectRevert(CallWithExactGas.NoContract.selector); - - s_caller.callWithExactGas( - "", // empty payload as it will revert well before needing it - addressWithoutContract, - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - } - - function test_NoGasForCallExactCheckReverts() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGas.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - (bool success, bytes memory retData) = address(s_caller).call{gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1}(payload); - assertFalse(success); - assertEq(retData.length, CallWithExactGas.NoGasForCallExactCheck.selector.length); - assertEq(abi.encodeWithSelector(CallWithExactGas.NoGasForCallExactCheck.selector), retData); - } - - function test_NotEnoughGasForCallReverts() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGas.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - // the extcodesize and account for EIP-150. This doesn't account for any other gas - // usage, and will therefore fail because the checks and memory stored/loads - // also cost gas. - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; - // extcodesize gas cost - allowedGas += EXTCODESIZE_GAS_COST; - // EIP-150 - allowedGas = (allowedGas * 64) / 63; - - // Expect this call to fail due to not having enough gas for the final call - (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); - - assertFalse(success); - assertEq(retData.length, CallWithExactGas.NotEnoughGasForCall.selector.length); - assertEq(abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector), retData); - } -} - -contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSetup { - function testFuzz_CallWithExactGasSafeReturnDataSuccess(bytes memory payload, bytes4 funcSelector) public { - vm.pauseGasMetering(); - bytes memory data = abi.encodeWithSelector(funcSelector, payload); - vm.assume( - funcSelector != GenericReceiver.setRevert.selector && - funcSelector != GenericReceiver.setErr.selector && - funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector - ); - uint16 maxRetBytes = 0; - - vm.expectCall(address(s_receiver), data); - vm.resumeGasMetering(); - - (bool success, bytes memory retData, uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - maxRetBytes - ); - - assertTrue(success); - assertEq(retData.length, 0); - assertGt(gasUsed, 500); - } - - function test_CallWithExactGasSafeReturnDataExactGas() public { - // The gas cost for `extcodesize` - uint256 extcodesizeGas = EXTCODESIZE_GAS_COST; - // The calculated overhead for retData initialization - uint256 overheadForRetDataInit = 114; - // The calculated overhead for otherwise unaccounted for gas usage - uint256 overheadForCallWithExactGas = 486; - - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasSafeReturnData.selector, - "", - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - 0 - ); - - // Since only 63/64th of the gas gets passed, we compensate - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); - - allowedGas += - extcodesizeGas + - DEFAULT_GAS_FOR_CALL_EXACT_CHECK + - overheadForRetDataInit + - overheadForCallWithExactGas; - - // Due to EIP-150 we expect to lose 1/64, so we compensate for this - allowedGas = (allowedGas * 64) / 63; - - vm.expectCall(address(s_receiver), ""); - (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); - - assertTrue(success); - (bool innerSuccess, bytes memory innerRetData, uint256 gasUsed) = abi.decode(retData, (bool, bytes, uint256)); - - assertTrue(innerSuccess); - assertEq(innerRetData.length, 0); - assertGt(gasUsed, 500); - } - - function test_Fuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { - vm.assume(gasLimitMultiplier > 0); // Assume not zero to avoid zero gas being passed to s_gasConsumer - uint16 maxRetBytes = 0; - - vm.expectCall(address(s_gasConsumer), abi.encodeWithSelector(s_gasConsumer.consumeAllGas.selector)); - - // Default gas limit of 20k times the amount generated by the fuzzer - uint256 gasLimit = DEFAULT_GAS_LIMIT * gasLimitMultiplier; - - (bool success, , uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( - abi.encodePacked(s_gasConsumer.consumeAllGas.selector), - address(s_gasConsumer), - gasLimit, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - maxRetBytes - ); - - // Was determined as the least amount of gas needed for pre-call stack management. - // when an OOG error is thrown, used gas returned by the library is 122 <= x <= 137 based on the - // gas limit passed in. This was determined through trial and error and fuzzing. - uint256 CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD = 122; - - assertTrue(success, "Error: External Call Failed"); - - // Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library - assertApproxEqAbs( - gasUsed - CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD, - gasLimit, - gasLimit / 64, - "Error: All gas not consumed by receiver" - ); - } - - function test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() external { - uint16 maxRetBytes = 0; - - vm.expectCall(address(s_gasConsumer), abi.encodeWithSelector(s_gasConsumer.throwOutOfGasError.selector)); - - (bool success, , ) = s_caller.callWithExactGasSafeReturnData( - abi.encodePacked(s_gasConsumer.throwOutOfGasError.selector), - address(s_gasConsumer), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - maxRetBytes - ); - - assertFalse(success, "Error: External Call Succeeded where it should not"); - } - - function testFuzz_CallWithExactGasReceiverErrorSuccess(uint16 testRetBytes) public { - uint16 maxReturnBytes = 500; - // Bound with upper limit, otherwise the test runs out of gas. - testRetBytes = uint16(bound(testRetBytes, 0, maxReturnBytes * 10)); - - bytes memory data = abi.encode("0x52656E73"); - - bytes memory errorData = new bytes(testRetBytes); - for (uint256 i = 0; i < errorData.length; ++i) { - errorData[i] = 0x01; - } - s_receiver.setErr(errorData); - s_receiver.setRevert(true); - - vm.expectCall(address(s_receiver), data); - - (bool success, bytes memory retData, uint256 gasUsed) = s_caller.callWithExactGasSafeReturnData( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT * 10, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - maxReturnBytes - ); - - assertFalse(success); - - bytes memory expectedReturnData = errorData; - - // If expected return data is longer than MAX_RET_BYTES, truncate it to MAX_RET_BYTES - if (expectedReturnData.length > maxReturnBytes) { - expectedReturnData = new bytes(maxReturnBytes); - for (uint256 i = 0; i < maxReturnBytes; ++i) { - expectedReturnData[i] = errorData[i]; - } - } - assertEq(expectedReturnData, retData); - assertGt(gasUsed, 500); - } - - function test_NoContractReverts() public { - address addressWithoutContract = address(1337); - - vm.expectRevert(CallWithExactGas.NoContract.selector); - - s_caller.callWithExactGasSafeReturnData( - "", // empty payload as it will revert well before needing it - addressWithoutContract, - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - 0 - ); - } - - function test_NoGasForCallExactCheckReverts() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasSafeReturnData.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - 0 - ); - - (bool success, bytes memory retData) = address(s_caller).call{gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1}(payload); - assertFalse(success); - assertEq(retData.length, CallWithExactGas.NoGasForCallExactCheck.selector.length); - assertEq(abi.encodeWithSelector(CallWithExactGas.NoGasForCallExactCheck.selector), retData); - } - - function test_NotEnoughGasForCallReverts() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasSafeReturnData.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - 0 - ); - - // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - // the extcodesize and account for EIP-150. This doesn't account for any other gas - // usage, and will therefore fail because the checks and memory stored/loads - // also cost gas. - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; - // extcodesize gas cost - allowedGas += EXTCODESIZE_GAS_COST; - // EIP-150 - allowedGas = (allowedGas * 64) / 63; - - // Expect this call to fail due to not having enough gas for the final call - (bool success, bytes memory retData) = address(s_caller).call{gas: allowedGas}(payload); - - assertFalse(success); - assertEq(retData.length, CallWithExactGas.NotEnoughGasForCall.selector.length); - assertEq(abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector), retData); - } -} - -contract CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract is CallWithExactGasSetup { - function test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes memory payload, bytes4 funcSelector) public { - vm.pauseGasMetering(); - bytes memory data = abi.encodeWithSelector(funcSelector, payload); - vm.assume( - funcSelector != GenericReceiver.setRevert.selector && - funcSelector != GenericReceiver.setErr.selector && - funcSelector != 0x5100fc21 // s_toRevert(), which is public and therefore has a function selector - ); - vm.expectCall(address(s_receiver), data); - vm.resumeGasMetering(); - - (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - assertTrue(success); - assertTrue(sufficientGas); - } - - function test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() public { - // The calculated overhead for otherwise unaccounted for gas usage - uint256 overheadForCallWithExactGas = 446; - - bytes memory data = abi.encode("0x52656E73"); - - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, - data, - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - // Since only 63/64th of the gas gets passed, we compensate - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)); - - allowedGas += DEFAULT_GAS_FOR_CALL_EXACT_CHECK + overheadForCallWithExactGas; - - // Due to EIP-150 we expect to lose 1/64, so we compensate for this - allowedGas = (allowedGas * 64) / 63; - - vm.expectCall(address(s_receiver), data); - (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{gas: allowedGas}(payload); - - // The call succeeds - assertTrue(outerCallSuccess); - - (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); - assertTrue(success); - assertTrue(sufficientGas); - } - - function test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() public { - bytes memory data = abi.encode("0x52656E73"); - - bytes memory errorData = new bytes(20); - for (uint256 i = 0; i < errorData.length; ++i) { - errorData[i] = 0x01; - } - s_receiver.setErr(errorData); - s_receiver.setRevert(true); - - vm.expectCall(address(s_receiver), data); - - (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( - data, - address(s_receiver), - DEFAULT_GAS_LIMIT * 10, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - // We don't care if it reverts, we only care if we have enough gas - assertFalse(success); - assertTrue(sufficientGas); - } - - function test_NoContractSuccess() public { - bytes memory data = abi.encode("0x52656E73"); - address addressWithoutContract = address(1337); - - (bool success, bool sufficientGas) = s_caller.callWithExactGasEvenIfTargetIsNoContract( - data, - addressWithoutContract, - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - assertTrue(success); - assertTrue(sufficientGas); - } - - function test_NoGasForCallExactCheckReturnFalseSuccess() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{ - gas: DEFAULT_GAS_FOR_CALL_EXACT_CHECK - 1 - }(payload); - - // The call succeeds - assertTrue(outerCallSuccess); - - (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); - assertFalse(success); - assertFalse(sufficientGas); - } - - function test_NotEnoughGasForCallReturnsFalseSuccess() public { - bytes memory payload = abi.encodeWithSelector( - s_caller.callWithExactGasEvenIfTargetIsNoContract.selector, - "", // empty payload as it will revert well before needing it - address(s_receiver), - DEFAULT_GAS_LIMIT, - DEFAULT_GAS_FOR_CALL_EXACT_CHECK - ); - - // Supply enough gas for the final call, the DEFAULT_GAS_FOR_CALL_EXACT_CHECK, - // and account for EIP-150. This doesn't account for any other gas usage, and - // will therefore fail because the checks and memory stored/loads also cost gas. - uint256 allowedGas = (DEFAULT_GAS_LIMIT + (DEFAULT_GAS_LIMIT / 64)) + DEFAULT_GAS_FOR_CALL_EXACT_CHECK; - // EIP-150 - allowedGas = (allowedGas * 64) / 63; - - // Expect this call to fail due to not having enough gas for the final call - (bool outerCallSuccess, bytes memory SuccessAndSufficientGas) = address(s_caller).call{gas: allowedGas}(payload); - - // The call succeeds - assertTrue(outerCallSuccess); - - (bool success, bool sufficientGas) = abi.decode(SuccessAndSufficientGas, (bool, bool)); - assertFalse(success); - assertFalse(sufficientGas); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol deleted file mode 100644 index 9323156..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/call/CallWithExactGasHelper.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {CallWithExactGas} from "../../call/CallWithExactGas.sol"; - -contract CallWithExactGasHelper { - function callWithExactGas( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck - ) public returns (bool success) { - return CallWithExactGas._callWithExactGas(payload, target, gasLimit, gasForCallExactCheck); - } - - function callWithExactGasSafeReturnData( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck, - uint16 maxReturnBytes - ) public returns (bool success, bytes memory retData, uint256 gasUsed) { - return - CallWithExactGas._callWithExactGasSafeReturnData(payload, target, gasLimit, gasForCallExactCheck, maxReturnBytes); - } - - function callWithExactGasEvenIfTargetIsNoContract( - bytes memory payload, - address target, - uint256 gasLimit, - uint16 gasForCallExactCheck - ) public returns (bool success, bool sufficientGas) { - return CallWithExactGas._callWithExactGasEvenIfTargetIsNoContract(payload, target, gasLimit, gasForCallExactCheck); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol deleted file mode 100644 index 097e79e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/enumerable/EnumerableMapAddresses.t.sol +++ /dev/null @@ -1,249 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BaseTest} from "../BaseTest.t.sol"; -import {EnumerableMapAddresses} from "../../enumerable/EnumerableMapAddresses.sol"; - -contract EnumerableMapAddressesTest is BaseTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - EnumerableMapAddresses.AddressToAddressMap internal s_addressToAddressMap; - EnumerableMapAddresses.AddressToBytes32Map internal s_addressToBytes32Map; - EnumerableMapAddresses.AddressToBytesMap internal s_addressToBytesMap; - - bytes32 internal constant MOCK_BYTES32_VALUE = bytes32(uint256(42)); - bytes internal constant MOCK_BYTES_VALUE = "0x123456789abcdef"; - - function setUp() public virtual override { - BaseTest.setUp(); - } -} - -contract EnumerableMapAddresses_set is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testSetSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - assertTrue(!s_addressToAddressMap.set(address(this), address(this))); - } - - function testBytes32SetSuccess() public { - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertTrue(s_addressToBytes32Map.contains(address(this))); - assertTrue(!s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - } - - function testBytesSetSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - assertTrue(!s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - } -} - -contract EnumerableMapAddresses_remove is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testRemoveSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.remove(address(this))); - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(!s_addressToAddressMap.remove(address(this))); - } - - function testBytes32RemoveSuccess() public { - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertTrue(s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.remove(address(this))); - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(!s_addressToBytes32Map.remove(address(this))); - } - - function testBytesRemoveSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.remove(address(this))); - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(!s_addressToBytesMap.remove(address(this))); - } -} - -contract EnumerableMapAddresses_contains is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testContainsSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - } - - function testBytes32ContainsSuccess() public { - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertTrue(s_addressToBytes32Map.contains(address(this))); - } - - function testBytesContainsSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - } -} - -contract EnumerableMapAddresses_length is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testLengthSuccess() public { - assertEq(s_addressToAddressMap.length(), 0); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertEq(s_addressToAddressMap.length(), 1); - assertTrue(s_addressToAddressMap.remove(address(this))); - assertEq(s_addressToAddressMap.length(), 0); - } - - function testBytes32LengthSuccess() public { - assertEq(s_addressToBytes32Map.length(), 0); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertEq(s_addressToBytes32Map.length(), 1); - assertTrue(s_addressToBytes32Map.remove(address(this))); - assertEq(s_addressToBytes32Map.length(), 0); - } - - function testBytesLengthSuccess() public { - assertEq(s_addressToBytesMap.length(), 0); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertEq(s_addressToBytesMap.length(), 1); - assertTrue(s_addressToBytesMap.remove(address(this))); - assertEq(s_addressToBytesMap.length(), 0); - } -} - -contract EnumerableMapAddresses_at is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testAtSuccess() public { - assertEq(s_addressToAddressMap.length(), 0); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertEq(s_addressToAddressMap.length(), 1); - (address key, address value) = s_addressToAddressMap.at(0); - assertEq(key, address(this)); - assertEq(value, address(this)); - } - - function testBytes32AtSuccess() public { - assertEq(s_addressToBytes32Map.length(), 0); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertEq(s_addressToBytes32Map.length(), 1); - (address key, bytes32 value) = s_addressToBytes32Map.at(0); - assertEq(key, address(this)); - assertEq(value, MOCK_BYTES32_VALUE); - } - - function testBytesAtSuccess() public { - assertEq(s_addressToBytesMap.length(), 0); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertEq(s_addressToBytesMap.length(), 1); - (address key, bytes memory value) = s_addressToBytesMap.at(0); - assertEq(key, address(this)); - assertEq(value, MOCK_BYTES_VALUE); - } -} - -contract EnumerableMapAddresses_tryGet is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testTryGetSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - (bool success, address value) = s_addressToAddressMap.tryGet(address(this)); - assertTrue(success); - assertEq(value, address(this)); - } - - function testBytes32TryGetSuccess() public { - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertTrue(s_addressToBytes32Map.contains(address(this))); - (bool success, bytes32 value) = s_addressToBytes32Map.tryGet(address(this)); - assertTrue(success); - assertEq(value, MOCK_BYTES32_VALUE); - } - - function testBytesTryGetSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - (bool success, bytes memory value) = s_addressToBytesMap.tryGet(address(this)); - assertTrue(success); - assertEq(value, MOCK_BYTES_VALUE); - } -} - -contract EnumerableMapAddresses_get is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testGetSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - assertEq(s_addressToAddressMap.get(address(this)), address(this)); - } - - function testBytes32GetSuccess() public { - assertTrue(!s_addressToBytes32Map.contains(address(this))); - assertTrue(s_addressToBytes32Map.set(address(this), MOCK_BYTES32_VALUE)); - assertTrue(s_addressToBytes32Map.contains(address(this))); - assertEq(s_addressToBytes32Map.get(address(this)), MOCK_BYTES32_VALUE); - } - - function testBytesGetSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - assertEq(s_addressToBytesMap.get(address(this)), MOCK_BYTES_VALUE); - } -} - -contract EnumerableMapAddresses_get_errorMessage is EnumerableMapAddressesTest { - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytes32Map; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; - using EnumerableMapAddresses for EnumerableMapAddresses.AddressToBytesMap; - - function testGetErrorMessageSuccess() public { - assertTrue(!s_addressToAddressMap.contains(address(this))); - assertTrue(s_addressToAddressMap.set(address(this), address(this))); - assertTrue(s_addressToAddressMap.contains(address(this))); - assertEq(s_addressToAddressMap.get(address(this), "EnumerableMapAddresses: nonexistent key"), address(this)); - } - - function testBytesGetErrorMessageSuccess() public { - assertTrue(!s_addressToBytesMap.contains(address(this))); - assertTrue(s_addressToBytesMap.set(address(this), MOCK_BYTES_VALUE)); - assertTrue(s_addressToBytesMap.contains(address(this))); - assertEq(s_addressToBytesMap.get(address(this)), MOCK_BYTES_VALUE); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol deleted file mode 100644 index 4dd9fe9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/ChainReaderTester.sol +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line gas-struct-packing -struct TestStruct { - int32 Field; - string DifferentField; - uint8 OracleId; - uint8[32] OracleIds; - address Account; - address[] Accounts; - int192 BigField; - MidLevelDynamicTestStruct NestedDynamicStruct; - MidLevelStaticTestStruct NestedStaticStruct; -} - -struct MidLevelDynamicTestStruct { - bytes2 FixedBytes; - InnerDynamicTestStruct Inner; -} - -struct InnerDynamicTestStruct { - int64 IntVal; - string S; -} - -struct MidLevelStaticTestStruct { - bytes2 FixedBytes; - InnerStaticTestStruct Inner; -} - -struct InnerStaticTestStruct { - int64 IntVal; - address A; -} - -contract ChainReaderTester { - event Triggered( - int32 indexed field, - uint8 oracleId, - MidLevelDynamicTestStruct nestedDynamicStruct, - MidLevelStaticTestStruct nestedStaticStruct, - uint8[32] oracleIds, - address Account, - address[] Accounts, - string differentField, - int192 bigField - ); - - event TriggeredEventWithDynamicTopic(string indexed fieldHash, string field); - - // First topic is event hash - event TriggeredWithFourTopics(int32 indexed field1, int32 indexed field2, int32 indexed field3); - - // first topic is event hash, second and third topics get hashed before getting stored - event TriggeredWithFourTopicsWithHashed(string indexed field1, uint8[32] indexed field2, bytes32 indexed field3); - - // emits dynamic bytes which encode data in the same way every time. - event StaticBytes(bytes message); - - TestStruct[] private s_seen; - uint64[] private s_arr; - uint64 private s_value; - - constructor() { - // See chain_reader_interface_tests.go in chainlink-relay - s_arr.push(3); - s_arr.push(4); - } - - function addTestStruct( - int32 field, - string calldata differentField, - uint8 oracleId, - uint8[32] calldata oracleIds, - address account, - address[] calldata accounts, - int192 bigField, - MidLevelDynamicTestStruct calldata nestedDynamicStruct, - MidLevelStaticTestStruct calldata nestedStaticStruct - ) public { - s_seen.push( - TestStruct( - field, - differentField, - oracleId, - oracleIds, - account, - accounts, - bigField, - nestedDynamicStruct, - nestedStaticStruct - ) - ); - } - - function setAlterablePrimitiveValue(uint64 value) public { - s_value = value; - } - - function returnSeen( - int32 field, - string calldata differentField, - uint8 oracleId, - uint8[32] calldata oracleIds, - address account, - address[] calldata accounts, - int192 bigField, - MidLevelDynamicTestStruct calldata nestedDynamicStruct, - MidLevelStaticTestStruct calldata nestedStaticStruct - ) public pure returns (TestStruct memory) { - return - TestStruct( - field, - differentField, - oracleId, - oracleIds, - account, - accounts, - bigField, - nestedDynamicStruct, - nestedStaticStruct - ); - } - - function getElementAtIndex(uint256 i) public view returns (TestStruct memory) { - // See chain_reader_interface_tests.go in chainlink-relay - return s_seen[i - 1]; - } - - function getPrimitiveValue() public pure returns (uint64) { - // See chain_reader_interface_tests.go in chainlink-relay - return 3; - } - - function getAlterablePrimitiveValue() public view returns (uint64) { - // See chain_reader_interface_tests.go in chainlink-relay - return s_value; - } - - function getDifferentPrimitiveValue() public pure returns (uint64) { - // See chain_reader_interface_tests.go in chainlink-relay - return 1990; - } - - function getSliceValue() public view returns (uint64[] memory) { - return s_arr; - } - - function triggerEvent( - int32 field, - uint8 oracleId, - MidLevelDynamicTestStruct calldata nestedDynamicStruct, - MidLevelStaticTestStruct calldata nestedStaticStruct, - uint8[32] calldata oracleIds, - address account, - address[] calldata accounts, - string calldata differentField, - int192 bigField - ) public { - emit Triggered( - field, - oracleId, - nestedDynamicStruct, - nestedStaticStruct, - oracleIds, - account, - accounts, - differentField, - bigField - ); - } - - function triggerEventWithDynamicTopic(string calldata field) public { - emit TriggeredEventWithDynamicTopic(field, field); - } - - // first topic is the event signature - function triggerWithFourTopics(int32 field1, int32 field2, int32 field3) public { - emit TriggeredWithFourTopics(field1, field2, field3); - } - - // first topic is event hash, second and third topics get hashed before getting stored - function triggerWithFourTopicsWithHashed(string memory field1, uint8[32] memory field2, bytes32 field3) public { - emit TriggeredWithFourTopicsWithHashed(field1, field2, field3); - } - - // emulate CCTP message event. - function triggerStaticBytes( - uint32 val1, - uint32 val2, - uint32 val3, - uint64 val4, - bytes32 val5, - bytes32 val6, - bytes32 val7, - bytes memory raw - ) public { - bytes memory _message = abi.encodePacked(val1, val2, val3, val4, val5, val6, val7, raw); - emit StaticBytes(_message); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol deleted file mode 100644 index f2b2f19..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkToken} from "../../token/ERC677/LinkToken.sol"; - -// This contract exists to mirror the functionality of the old token, which -// always deployed with 1b tokens sent to the deployer. -contract LinkTokenTestHelper is LinkToken { - constructor() { - _mint(msg.sender, 1e27); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol deleted file mode 100644 index 47ecbb0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../access/ConfirmedOwner.sol"; - -contract ConfirmedOwnerTestHelper is ConfirmedOwner { - event Here(); - - constructor() ConfirmedOwner(msg.sender) {} - - function modifierOnlyOwner() public onlyOwner { - emit Here(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol deleted file mode 100644 index daf8479..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol +++ /dev/null @@ -1,24 +0,0 @@ -pragma solidity ^0.8.0; - -contract GasConsumer { - function consumeAllGas() external view { - assembly { - // While loop that operates indefinitely, written in yul to ensure better granularity over exactly how much gas is spent - for { - // Loop will run forever since 0 < 1 - } lt(0, 1) {} { - // If 100 gas is remaining, then exit the loop by returning. 100 was determined by manual binary search to be - // the minimal amount of gas needed but less than the cost of another loop - if lt(gas(), 100) { - return(0x0, 0x0) // Return with no return data - } - } - } - } - - function throwOutOfGasError() external pure { - while (true) { - // Intentionally consume all gas to throw an OOG error. - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol deleted file mode 100644 index 2c05801..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/testhelpers/GenericReceiver.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract GenericReceiver { - bool public s_toRevert; - bytes private s_err; - - constructor(bool toRevert) { - s_toRevert = toRevert; - } - - function setRevert(bool toRevert) external { - s_toRevert = toRevert; - } - - function setErr(bytes memory err) external { - s_err = err; - } - - // solhint-disable-next-line payable-fallback - fallback() external { - if (s_toRevert) { - bytes memory reason = s_err; - assembly { - revert(add(32, reason), mload(reason)) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol deleted file mode 100644 index 2815f99..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol +++ /dev/null @@ -1,347 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IBurnMintERC20} from "../../../token/ERC20/IBurnMintERC20.sol"; -import {IERC677} from "../../../token/ERC677/IERC677.sol"; - -import {BaseTest} from "../../BaseTest.t.sol"; -import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract BurnMintERC677Setup is BaseTest { - event Transfer(address indexed from, address indexed to, uint256 value); - event MintAccessGranted(address indexed minter); - event BurnAccessGranted(address indexed burner); - event MintAccessRevoked(address indexed minter); - event BurnAccessRevoked(address indexed burner); - - BurnMintERC677 internal s_burnMintERC677; - - address internal s_mockPool = address(6243783892); - uint256 internal s_amount = 1e18; - - function setUp() public virtual override { - BaseTest.setUp(); - s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 1e27); - - // Set s_mockPool to be a burner and minter - s_burnMintERC677.grantMintAndBurnRoles(s_mockPool); - deal(address(s_burnMintERC677), OWNER, s_amount); - } -} - -contract BurnMintERC677_constructor is BurnMintERC677Setup { - function testConstructorSuccess() public { - string memory name = "Chainlink token v2"; - string memory symbol = "LINK2"; - uint8 decimals = 19; - uint256 maxSupply = 1e33; - s_burnMintERC677 = new BurnMintERC677(name, symbol, decimals, maxSupply); - - assertEq(name, s_burnMintERC677.name()); - assertEq(symbol, s_burnMintERC677.symbol()); - assertEq(decimals, s_burnMintERC677.decimals()); - assertEq(maxSupply, s_burnMintERC677.maxSupply()); - } -} - -contract BurnMintERC677_approve is BurnMintERC677Setup { - function testApproveSuccess() public { - uint256 balancePre = s_burnMintERC677.balanceOf(STRANGER); - uint256 sendingAmount = s_amount / 2; - - s_burnMintERC677.approve(STRANGER, sendingAmount); - - changePrank(STRANGER); - - s_burnMintERC677.transferFrom(OWNER, STRANGER, sendingAmount); - - assertEq(sendingAmount + balancePre, s_burnMintERC677.balanceOf(STRANGER)); - } - - // Reverts - - function testInvalidAddressReverts() public { - vm.expectRevert(); - - s_burnMintERC677.approve(address(s_burnMintERC677), s_amount); - } -} - -contract BurnMintERC677_transfer is BurnMintERC677Setup { - function testTransferSuccess() public { - uint256 balancePre = s_burnMintERC677.balanceOf(STRANGER); - uint256 sendingAmount = s_amount / 2; - - s_burnMintERC677.transfer(STRANGER, sendingAmount); - - assertEq(sendingAmount + balancePre, s_burnMintERC677.balanceOf(STRANGER)); - } - - // Reverts - - function testInvalidAddressReverts() public { - vm.expectRevert(); - - s_burnMintERC677.transfer(address(s_burnMintERC677), s_amount); - } -} - -contract BurnMintERC677_mint is BurnMintERC677Setup { - function testBasicMintSuccess() public { - uint256 balancePre = s_burnMintERC677.balanceOf(OWNER); - - s_burnMintERC677.grantMintAndBurnRoles(OWNER); - - vm.expectEmit(); - emit Transfer(address(0), OWNER, s_amount); - - s_burnMintERC677.mint(OWNER, s_amount); - - assertEq(balancePre + s_amount, s_burnMintERC677.balanceOf(OWNER)); - } - - // Revert - - function testSenderNotMinterReverts() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, OWNER)); - s_burnMintERC677.mint(STRANGER, 1e18); - } - - function testMaxSupplyExceededReverts() public { - changePrank(s_mockPool); - - // Mint max supply - s_burnMintERC677.mint(OWNER, s_burnMintERC677.maxSupply()); - - vm.expectRevert( - abi.encodeWithSelector(BurnMintERC677.MaxSupplyExceeded.selector, s_burnMintERC677.maxSupply() + 1) - ); - - // Attempt to mint 1 more than max supply - s_burnMintERC677.mint(OWNER, 1); - } -} - -contract BurnMintERC677_burn is BurnMintERC677Setup { - function testBasicBurnSuccess() public { - s_burnMintERC677.grantBurnRole(OWNER); - deal(address(s_burnMintERC677), OWNER, s_amount); - - vm.expectEmit(); - emit Transfer(OWNER, address(0), s_amount); - - s_burnMintERC677.burn(s_amount); - - assertEq(0, s_burnMintERC677.balanceOf(OWNER)); - } - - // Revert - - function testSenderNotBurnerReverts() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); - - s_burnMintERC677.burnFrom(STRANGER, s_amount); - } - - function testExceedsBalanceReverts() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC677.burn(s_amount * 2); - } - - function testBurnFromZeroAddressReverts() public { - s_burnMintERC677.grantBurnRole(address(0)); - changePrank(address(0)); - - vm.expectRevert("ERC20: burn from the zero address"); - - s_burnMintERC677.burn(0); - } -} - -contract BurnMintERC677_burnFromAlias is BurnMintERC677Setup { - function setUp() public virtual override { - BurnMintERC677Setup.setUp(); - } - - function testBurnFromSuccess() public { - s_burnMintERC677.approve(s_mockPool, s_amount); - - changePrank(s_mockPool); - - s_burnMintERC677.burn(OWNER, s_amount); - - assertEq(0, s_burnMintERC677.balanceOf(OWNER)); - } - - // Reverts - - function testSenderNotBurnerReverts() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); - - s_burnMintERC677.burn(OWNER, s_amount); - } - - function testInsufficientAllowanceReverts() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_burnMintERC677.burn(OWNER, s_amount); - } - - function testExceedsBalanceReverts() public { - s_burnMintERC677.approve(s_mockPool, s_amount * 2); - - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC677.burn(OWNER, s_amount * 2); - } -} - -contract BurnMintERC677_burnFrom is BurnMintERC677Setup { - function setUp() public virtual override { - BurnMintERC677Setup.setUp(); - } - - function testBurnFromSuccess() public { - s_burnMintERC677.approve(s_mockPool, s_amount); - - changePrank(s_mockPool); - - s_burnMintERC677.burnFrom(OWNER, s_amount); - - assertEq(0, s_burnMintERC677.balanceOf(OWNER)); - } - - // Reverts - - function testSenderNotBurnerReverts() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); - - s_burnMintERC677.burnFrom(OWNER, s_amount); - } - - function testInsufficientAllowanceReverts() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_burnMintERC677.burnFrom(OWNER, s_amount); - } - - function testExceedsBalanceReverts() public { - s_burnMintERC677.approve(s_mockPool, s_amount * 2); - - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC677.burnFrom(OWNER, s_amount * 2); - } -} - -contract BurnMintERC677_grantRole is BurnMintERC677Setup { - function testGrantMintAccessSuccess() public { - assertFalse(s_burnMintERC677.isMinter(STRANGER)); - - vm.expectEmit(); - emit MintAccessGranted(STRANGER); - - s_burnMintERC677.grantMintAndBurnRoles(STRANGER); - - assertTrue(s_burnMintERC677.isMinter(STRANGER)); - - vm.expectEmit(); - emit MintAccessRevoked(STRANGER); - - s_burnMintERC677.revokeMintRole(STRANGER); - - assertFalse(s_burnMintERC677.isMinter(STRANGER)); - } - - function testGrantBurnAccessSuccess() public { - assertFalse(s_burnMintERC677.isBurner(STRANGER)); - - vm.expectEmit(); - emit BurnAccessGranted(STRANGER); - - s_burnMintERC677.grantBurnRole(STRANGER); - - assertTrue(s_burnMintERC677.isBurner(STRANGER)); - - vm.expectEmit(); - emit BurnAccessRevoked(STRANGER); - - s_burnMintERC677.revokeBurnRole(STRANGER); - - assertFalse(s_burnMintERC677.isBurner(STRANGER)); - } - - function testGrantManySuccess() public { - uint256 numberOfPools = 10; - address[] memory permissionedAddresses = new address[](numberOfPools + 1); - permissionedAddresses[0] = s_mockPool; - - for (uint160 i = 0; i < numberOfPools; ++i) { - permissionedAddresses[i + 1] = address(i); - s_burnMintERC677.grantMintAndBurnRoles(address(i)); - } - - assertEq(permissionedAddresses, s_burnMintERC677.getBurners()); - assertEq(permissionedAddresses, s_burnMintERC677.getMinters()); - } -} - -contract BurnMintERC677_grantMintAndBurnRoles is BurnMintERC677Setup { - function testGrantMintAndBurnRolesSuccess() public { - assertFalse(s_burnMintERC677.isMinter(STRANGER)); - assertFalse(s_burnMintERC677.isBurner(STRANGER)); - - vm.expectEmit(); - emit MintAccessGranted(STRANGER); - vm.expectEmit(); - emit BurnAccessGranted(STRANGER); - - s_burnMintERC677.grantMintAndBurnRoles(STRANGER); - - assertTrue(s_burnMintERC677.isMinter(STRANGER)); - assertTrue(s_burnMintERC677.isBurner(STRANGER)); - } -} - -contract BurnMintERC677_decreaseApproval is BurnMintERC677Setup { - function testDecreaseApprovalSuccess() public { - s_burnMintERC677.approve(s_mockPool, s_amount); - uint256 allowance = s_burnMintERC677.allowance(OWNER, s_mockPool); - assertEq(allowance, s_amount); - s_burnMintERC677.decreaseApproval(s_mockPool, s_amount); - assertEq(s_burnMintERC677.allowance(OWNER, s_mockPool), allowance - s_amount); - } -} - -contract BurnMintERC677_increaseApproval is BurnMintERC677Setup { - function testIncreaseApprovalSuccess() public { - s_burnMintERC677.approve(s_mockPool, s_amount); - uint256 allowance = s_burnMintERC677.allowance(OWNER, s_mockPool); - assertEq(allowance, s_amount); - s_burnMintERC677.increaseApproval(s_mockPool, s_amount); - assertEq(s_burnMintERC677.allowance(OWNER, s_mockPool), allowance + s_amount); - } -} - -contract BurnMintERC677_supportsInterface is BurnMintERC677Setup { - function testConstructorSuccess() public view { - assertTrue(s_burnMintERC677.supportsInterface(type(IERC20).interfaceId)); - assertTrue(s_burnMintERC677.supportsInterface(type(IERC677).interfaceId)); - assertTrue(s_burnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); - assertTrue(s_burnMintERC677.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol deleted file mode 100644 index 614b3be..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IBurnMintERC20} from "../../../token/ERC20/IBurnMintERC20.sol"; -import {IOptimismMintableERC20Minimal, IOptimismMintableERC20} from "../../../token/ERC20/IOptimismMintableERC20.sol"; -import {IERC677} from "../../../token/ERC677/IERC677.sol"; - -import {BurnMintERC677} from "../../../token/ERC677/BurnMintERC677.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; -import {OpStackBurnMintERC677} from "../../../token/ERC677/OpStackBurnMintERC677.sol"; - -import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract OpStackBurnMintERC677Setup is BaseTest { - address internal s_l1Token = address(897352983527); - address internal s_l2Bridge = address(1928235235); - - OpStackBurnMintERC677 internal s_opStackBurnMintERC677; - - function setUp() public virtual override { - BaseTest.setUp(); - s_opStackBurnMintERC677 = new OpStackBurnMintERC677("Chainlink Token", "LINK", 18, 1e27, s_l1Token, s_l2Bridge); - } -} - -contract OpStackBurnMintERC677_constructor is OpStackBurnMintERC677Setup { - function testConstructorSuccess() public { - string memory name = "Chainlink token l2"; - string memory symbol = "LINK L2"; - uint8 decimals = 18; - uint256 maxSupply = 1e33; - s_opStackBurnMintERC677 = new OpStackBurnMintERC677(name, symbol, decimals, maxSupply, s_l1Token, s_l2Bridge); - - assertEq(name, s_opStackBurnMintERC677.name()); - assertEq(symbol, s_opStackBurnMintERC677.symbol()); - assertEq(decimals, s_opStackBurnMintERC677.decimals()); - assertEq(maxSupply, s_opStackBurnMintERC677.maxSupply()); - assertEq(s_l1Token, s_opStackBurnMintERC677.remoteToken()); - assertEq(s_l2Bridge, s_opStackBurnMintERC677.bridge()); - } -} - -contract OpStackBurnMintERC677_supportsInterface is OpStackBurnMintERC677Setup { - function testConstructorSuccess() public view { - assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IOptimismMintableERC20Minimal).interfaceId)); - assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC677).interfaceId)); - assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); - assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC165).interfaceId)); - } -} - -contract OpStackBurnMintERC677_interfaceCompatibility is OpStackBurnMintERC677Setup { - event Transfer(address indexed from, address indexed to, uint256 value); - - IOptimismMintableERC20 internal s_opStackToken; - - function setUp() public virtual override { - OpStackBurnMintERC677Setup.setUp(); - s_opStackToken = IOptimismMintableERC20(address(s_opStackBurnMintERC677)); - } - - function testStaticFunctionsCompatibility() public { - assertEq(s_l1Token, s_opStackToken.remoteToken()); - assertEq(s_l2Bridge, s_opStackToken.bridge()); - } - - function testMintCompatibility() public { - // Ensure roles work - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, OWNER)); - s_opStackToken.mint(OWNER, 1); - - // Use the actual contract to grant mint - s_opStackBurnMintERC677.grantMintRole(OWNER); - - // Ensure zero address check works - vm.expectRevert("ERC20: mint to the zero address"); - s_opStackToken.mint(address(0x0), 0); - - address mintToAddress = address(0x1); - uint256 mintAmount = 1; - - vm.expectEmit(); - emit Transfer(address(0), mintToAddress, mintAmount); - - s_opStackToken.mint(mintToAddress, mintAmount); - } - - function testBurnCompatibility() public { - // Ensure roles work - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, OWNER)); - s_opStackToken.burn(address(0x0), 1); - - // Use the actual contract to grant burn - s_opStackBurnMintERC677.grantBurnRole(OWNER); - - // Ensure zero address check works - vm.expectRevert("ERC20: approve from the zero address"); - s_opStackToken.burn(address(0x0), 0); - - address burnFromAddress = address(0x1); - uint256 burnAmount = 1; - - // Ensure `burn(address, amount)` works like burnFrom and requires allowance - vm.expectRevert("ERC20: insufficient allowance"); - s_opStackToken.burn(burnFromAddress, burnAmount); - - changePrank(burnFromAddress); - deal(address(s_opStackToken), burnFromAddress, burnAmount); - s_opStackBurnMintERC677.approve(OWNER, burnAmount); - changePrank(OWNER); - - vm.expectEmit(); - emit Transfer(burnFromAddress, address(0x0), burnAmount); - - s_opStackToken.burn(burnFromAddress, burnAmount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol deleted file mode 100644 index bf88df6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {BaseTest} from "../BaseTest.t.sol"; -import {SortedSetValidationUtil} from "../../../shared/util/SortedSetValidationUtil.sol"; - -contract SortedSetValidationUtilBaseTest is BaseTest { - uint256 constant OFFSET = 5; - - modifier _ensureSetLength(uint256 subsetLength, uint256 supersetLength) { - vm.assume(subsetLength > 0 && supersetLength > 0 && subsetLength <= supersetLength); - _; - } - - function _createSets( - uint256 subsetLength, - uint256 supersetLength - ) internal pure returns (bytes32[] memory subset, bytes32[] memory superset) { - subset = new bytes32[](subsetLength); - superset = new bytes32[](supersetLength); - } - - function _convertArrayToSortedSet(bytes32[] memory arr, uint256 offSet) internal pure { - for (uint256 i = 1; i < arr.length; ++i) { - arr[i] = bytes32(uint256(arr[i - 1]) + offSet); - } - } - - function _convertToUnsortedSet(bytes32[] memory arr, uint256 ptr1, uint256 ptr2) internal pure { - // Swap two elements to make it unsorted - (arr[ptr1], arr[ptr2]) = (arr[ptr2], arr[ptr1]); - } - - function _convertArrayToSubset(bytes32[] memory subset, bytes32[] memory superset) internal pure { - for (uint256 i; i < subset.length; ++i) { - subset[i] = superset[i]; - } - } - - function _makeInvalidSubset(bytes32[] memory subset, bytes32[] memory superset, uint256 ptr) internal pure { - _convertArrayToSubset(subset, superset); - subset[ptr] = bytes32(uint256(subset[ptr]) + 1); - } - - function _convertArrayToHaveDuplicates(bytes32[] memory arr, uint256 ptr1, uint256 ptr2) internal pure { - arr[ptr2] = arr[ptr1]; - } -} - -contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValidationUtilBaseTest { - // Successes. - - function test__checkIsValidUniqueSubset_ValidSubset_Success() public pure { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertArrayToSubset(subset, superset); - - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - // Reverts. - - function test__checkIsValidUniqueSubset_EmptySubset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(0, 5); - _convertArrayToSortedSet(superset, OFFSET); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.EmptySet.selector)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_EmptySuperset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 0); - _convertArrayToSortedSet(subset, OFFSET); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.EmptySet.selector)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_NotASubset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _makeInvalidSubset(subset, superset, 1); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertToUnsortedSet(subset, 1, 2); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, subset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertArrayToSubset(subset, superset); - _convertToUnsortedSet(superset, 1, 2); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, superset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_HasDuplicates_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertArrayToSubset(subset, superset); - _convertArrayToHaveDuplicates(subset, 1, 2); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, subset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(6, 5); - _convertArrayToSortedSet(subset, OFFSET); - _convertArrayToSortedSet(superset, OFFSET); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public pure { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(5, 5); - _convertArrayToSortedSet(subset, OFFSET); - _convertArrayToSortedSet(superset, OFFSET); - - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SingleElementSubset() public pure { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertArrayToSubset(subset, superset); - - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public pure { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); - _convertArrayToSortedSet(subset, OFFSET); - _convertArrayToSortedSet(superset, OFFSET); - - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); - _convertArrayToSortedSet(subset, OFFSET); - superset[0] = bytes32(uint256(subset[0]) + 10); // Different value - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, subset, superset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } - - function test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() public { - (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); - _convertArrayToSortedSet(superset, OFFSET); - _convertArrayToSubset(subset, superset); - _convertArrayToHaveDuplicates(superset, 1, 2); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, superset)); - SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol deleted file mode 100644 index b9b3b54..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IBurnMintERC20.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -interface IBurnMintERC20 is IERC20 { - /// @notice Mints new tokens for a given address. - /// @param account The address to mint the new tokens to. - /// @param amount The number of tokens to be minted. - /// @dev this function increases the total supply. - function mint(address account, uint256 amount) external; - - /// @notice Burns tokens from the sender. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burn(uint256 amount) external; - - /// @notice Burns tokens from a given address.. - /// @param account The address to burn tokens from. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burn(address account, uint256 amount) external; - - /// @notice Burns tokens from a given address.. - /// @param account The address to burn tokens from. - /// @param amount The number of tokens to be burned. - /// @dev this function decreases the total supply. - function burnFrom(address account, uint256 amount) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol deleted file mode 100644 index 4e9d3a2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC20/IOptimismMintableERC20.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable one-contract-per-file -pragma solidity ^0.8.0; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -/// @title IOptimismMintableERC20Minimal -/// @dev This interface is a subset of the Optimism ERC20 interface that is defined -/// below. This is done to now have to overwrite the burn and mint functions again in -/// the implementation, as that leads to more complicated, error prone code. -interface IOptimismMintableERC20Minimal is IERC165 { - /// @notice Returns the address of the token on L1. - function remoteToken() external view returns (address); - - /// @notice Returns the address of the bridge on L2. - function bridge() external returns (address); -} - -/// @title IOptimismMintableERC20 -/// @notice This is the complete interface for the Optimism mintable ERC20 token as defined in -/// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/universal/IOptimismMintableERC20.sol -interface IOptimismMintableERC20 is IERC165, IOptimismMintableERC20Minimal { - function mint(address _to, uint256 _amount) external; - - function burn(address _from, uint256 _amount) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol deleted file mode 100644 index 24573f3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/BurnMintERC677.sol +++ /dev/null @@ -1,217 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IBurnMintERC20} from "../ERC20/IBurnMintERC20.sol"; -import {IERC677} from "./IERC677.sol"; - -import {ERC677} from "./ERC677.sol"; -import {OwnerIsCreator} from "../../access/OwnerIsCreator.sol"; - -import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -/// @notice A basic ERC677 compatible token contract with burn and minting roles. -/// @dev The total supply can be limited during deployment. -contract BurnMintERC677 is IBurnMintERC20, ERC677, IERC165, ERC20Burnable, OwnerIsCreator { - using EnumerableSet for EnumerableSet.AddressSet; - - error SenderNotMinter(address sender); - error SenderNotBurner(address sender); - error MaxSupplyExceeded(uint256 supplyAfterMint); - - event MintAccessGranted(address indexed minter); - event BurnAccessGranted(address indexed burner); - event MintAccessRevoked(address indexed minter); - event BurnAccessRevoked(address indexed burner); - - // @dev the allowed minter addresses - EnumerableSet.AddressSet internal s_minters; - // @dev the allowed burner addresses - EnumerableSet.AddressSet internal s_burners; - - /// @dev The number of decimals for the token - uint8 internal immutable i_decimals; - - /// @dev The maximum supply of the token, 0 if unlimited - uint256 internal immutable i_maxSupply; - - constructor(string memory name, string memory symbol, uint8 decimals_, uint256 maxSupply_) ERC677(name, symbol) { - i_decimals = decimals_; - i_maxSupply = maxSupply_; - } - - function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) { - return - interfaceId == type(IERC20).interfaceId || - interfaceId == type(IERC677).interfaceId || - interfaceId == type(IBurnMintERC20).interfaceId || - interfaceId == type(IERC165).interfaceId; - } - - // ================================================================ - // | ERC20 | - // ================================================================ - - /// @dev Returns the number of decimals used in its user representation. - function decimals() public view virtual override returns (uint8) { - return i_decimals; - } - - /// @dev Returns the max supply of the token, 0 if unlimited. - function maxSupply() public view virtual returns (uint256) { - return i_maxSupply; - } - - /// @dev Uses OZ ERC20 _transfer to disallow sending to address(0). - /// @dev Disallows sending to address(this) - function _transfer(address from, address to, uint256 amount) internal virtual override validAddress(to) { - super._transfer(from, to, amount); - } - - /// @dev Uses OZ ERC20 _approve to disallow approving for address(0). - /// @dev Disallows approving for address(this) - function _approve(address owner, address spender, uint256 amount) internal virtual override validAddress(spender) { - super._approve(owner, spender, amount); - } - - /// @dev Exists to be backwards compatible with the older naming convention. - function decreaseApproval(address spender, uint256 subtractedValue) external returns (bool success) { - return decreaseAllowance(spender, subtractedValue); - } - - /// @dev Exists to be backwards compatible with the older naming convention. - function increaseApproval(address spender, uint256 addedValue) external { - increaseAllowance(spender, addedValue); - } - - /// @notice Check if recipient is valid (not this contract address). - /// @param recipient the account we transfer/approve to. - /// @dev Reverts with an empty revert to be compatible with the existing link token when - /// the recipient is this contract address. - modifier validAddress(address recipient) virtual { - // solhint-disable-next-line reason-string, gas-custom-errors - if (recipient == address(this)) revert(); - _; - } - - // ================================================================ - // | Burning & minting | - // ================================================================ - - /// @inheritdoc ERC20Burnable - /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). - /// @dev Decreases the total supply. - function burn(uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyBurner { - super.burn(amount); - } - - /// @inheritdoc IBurnMintERC20 - /// @dev Alias for BurnFrom for compatibility with the older naming convention. - /// @dev Uses burnFrom for all validation & logic. - function burn(address account, uint256 amount) public virtual override { - burnFrom(account, amount); - } - - /// @inheritdoc ERC20Burnable - /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). - /// @dev Decreases the total supply. - function burnFrom(address account, uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyBurner { - super.burnFrom(account, amount); - } - - /// @inheritdoc IBurnMintERC20 - /// @dev Uses OZ ERC20 _mint to disallow minting to address(0). - /// @dev Disallows minting to address(this) - /// @dev Increases the total supply. - function mint(address account, uint256 amount) external override onlyMinter validAddress(account) { - if (i_maxSupply != 0 && totalSupply() + amount > i_maxSupply) revert MaxSupplyExceeded(totalSupply() + amount); - - _mint(account, amount); - } - - // ================================================================ - // | Roles | - // ================================================================ - - /// @notice grants both mint and burn roles to `burnAndMinter`. - /// @dev calls public functions so this function does not require - /// access controls. This is handled in the inner functions. - function grantMintAndBurnRoles(address burnAndMinter) external { - grantMintRole(burnAndMinter); - grantBurnRole(burnAndMinter); - } - - /// @notice Grants mint role to the given address. - /// @dev only the owner can call this function. - function grantMintRole(address minter) public onlyOwner { - if (s_minters.add(minter)) { - emit MintAccessGranted(minter); - } - } - - /// @notice Grants burn role to the given address. - /// @dev only the owner can call this function. - function grantBurnRole(address burner) public onlyOwner { - if (s_burners.add(burner)) { - emit BurnAccessGranted(burner); - } - } - - /// @notice Revokes mint role for the given address. - /// @dev only the owner can call this function. - function revokeMintRole(address minter) public onlyOwner { - if (s_minters.remove(minter)) { - emit MintAccessRevoked(minter); - } - } - - /// @notice Revokes burn role from the given address. - /// @dev only the owner can call this function - function revokeBurnRole(address burner) public onlyOwner { - if (s_burners.remove(burner)) { - emit BurnAccessRevoked(burner); - } - } - - /// @notice Returns all permissioned minters - function getMinters() public view returns (address[] memory) { - return s_minters.values(); - } - - /// @notice Returns all permissioned burners - function getBurners() public view returns (address[] memory) { - return s_burners.values(); - } - - // ================================================================ - // | Access | - // ================================================================ - - /// @notice Checks whether a given address is a minter for this token. - /// @return true if the address is allowed to mint. - function isMinter(address minter) public view returns (bool) { - return s_minters.contains(minter); - } - - /// @notice Checks whether a given address is a burner for this token. - /// @return true if the address is allowed to burn. - function isBurner(address burner) public view returns (bool) { - return s_burners.contains(burner); - } - - /// @notice Checks whether the msg.sender is a permissioned minter for this token - /// @dev Reverts with a SenderNotMinter if the check fails - modifier onlyMinter() { - if (!isMinter(msg.sender)) revert SenderNotMinter(msg.sender); - _; - } - - /// @notice Checks whether the msg.sender is a permissioned burner for this token - /// @dev Reverts with a SenderNotBurner if the check fails - modifier onlyBurner() { - if (!isBurner(msg.sender)) revert SenderNotBurner(msg.sender); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol deleted file mode 100644 index 5876ddf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/ERC677.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {IERC677} from "./IERC677.sol"; -import {IERC677Receiver} from "../../interfaces/IERC677Receiver.sol"; - -import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; - -contract ERC677 is IERC677, ERC20 { - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} - - /// @inheritdoc IERC677 - function transferAndCall(address to, uint256 amount, bytes memory data) public returns (bool success) { - super.transfer(to, amount); - emit Transfer(msg.sender, to, amount, data); - if (to.code.length > 0) { - IERC677Receiver(to).onTokenTransfer(msg.sender, amount, data); - } - return true; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol deleted file mode 100644 index 7e303a4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/IERC677.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IERC677 { - event Transfer(address indexed from, address indexed to, uint256 value, bytes data); - - /// @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver - /// @param to The address which you want to transfer to - /// @param amount The amount of tokens to be transferred - /// @param data bytes Additional data with no specified format, sent in call to `to` - /// @return true unless throwing - function transferAndCall(address to, uint256 amount, bytes memory data) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol deleted file mode 100644 index b4640a8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/LinkToken.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {BurnMintERC677} from "./BurnMintERC677.sol"; - -contract LinkToken is BurnMintERC677 { - constructor() BurnMintERC677("ChainLink Token", "LINK", 18, 1e27) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol deleted file mode 100644 index 95c64c9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/token/ERC677/OpStackBurnMintERC677.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IOptimismMintableERC20Minimal, IOptimismMintableERC20} from "../ERC20/IOptimismMintableERC20.sol"; - -import {BurnMintERC677} from "./BurnMintERC677.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -/// @notice A basic ERC677 compatible token contract with burn and minting roles that supports -/// the native L2 bridging requirements of the Optimism Stack. -/// @dev Note: the L2 bridge contract needs to be given burn and mint privileges manually, -/// since this contract does not automatically grant them. This allows the owner to revoke -/// the bridge's privileges if necessary. -contract OpStackBurnMintERC677 is BurnMintERC677, IOptimismMintableERC20Minimal { - /// @dev The address of the L1 token. - address internal immutable i_l1Token; - /// @dev The address of the L2 bridge. - address internal immutable i_l2Bridge; - - constructor( - string memory name, - string memory symbol, - uint8 decimals_, - uint256 maxSupply_, - address l1Token, - address l2Bridge - ) BurnMintERC677(name, symbol, decimals_, maxSupply_) { - i_l1Token = l1Token; - i_l2Bridge = l2Bridge; - } - - function supportsInterface(bytes4 interfaceId) public pure virtual override(IERC165, BurnMintERC677) returns (bool) { - return - interfaceId == type(IOptimismMintableERC20).interfaceId || - interfaceId == type(IOptimismMintableERC20Minimal).interfaceId || - super.supportsInterface(interfaceId); - } - - /// @notice Returns the address of the L1 token. - function remoteToken() public view override returns (address) { - return i_l1Token; - } - - /// @notice Returns the address of the L2 bridge. - function bridge() public view override returns (address) { - return i_l2Bridge; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol deleted file mode 100644 index fec11e4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/shared/util/SortedSetValidationUtil.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -/// @title Sorted Set Validation Utility -/// @notice Provides utility functions for validating sorted sets and their subset relationships. -/// @dev This library is used to ensure that arrays of bytes32 are sorted sets and to check subset relations. -library SortedSetValidationUtil { - /// @dev Error to be thrown when an operation is attempted on an empty set. - error EmptySet(); - /// @dev Error to be thrown when the set is not in ascending unique order. - error NotASortedSet(bytes32[] set); - /// @dev Error to be thrown when the first array is not a subset of the second array. - error NotASubset(bytes32[] subset, bytes32[] superset); - - /// @notice Checks if `subset` is a valid and unique subset of `superset`. - /// NOTE: Empty set is not considered a valid subset of superset for our use case. - /// @dev Both arrays must be valid sets (unique, sorted in ascending order) and `subset` must be entirely contained within `superset`. - /// @param subset The array of bytes32 to validate as a subset. - /// @param superset The array of bytes32 in which subset is checked against. - /// @custom:revert EmptySet If either `subset` or `superset` is empty. - /// @custom:revert NotASubset If `subset` is not a subset of `superset`. - function _checkIsValidUniqueSubset(bytes32[] memory subset, bytes32[] memory superset) internal pure { - if (subset.length == 0 || superset.length == 0) { - revert EmptySet(); - } - - _checkIsValidSet(subset); - _checkIsValidSet(superset); - - uint256 i = 0; // Pointer for 'subset' - uint256 j = 0; // Pointer for 'superset' - - while (i < subset.length && j < superset.length) { - if (subset[i] > superset[j]) { - ++j; // Move the pointer in 'superset' to find a match - } else if (subset[i] == superset[j]) { - ++i; // Found a match, move the pointer in 'subset' - ++j; // Also move in 'superset' to continue checking - } else { - revert NotASubset(subset, superset); - } - } - - if (i < subset.length) { - revert NotASubset(subset, superset); - } - } - - /// @notice Validates that a given set is sorted and has unique elements. - /// @dev Iterates through the array to check that each element is greater than the previous. - /// @param set The array of bytes32 to validate. - /// @custom:revert NotASortedSet If any element is not greater than its predecessor or if any two consecutive elements are equal. - function _checkIsValidSet(bytes32[] memory set) private pure { - for (uint256 i = 1; i < set.length; ++i) { - if (set[i] <= set[i - 1]) { - revert NotASortedSet(set); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol deleted file mode 100644 index e85521a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/AutomationConsumerBenchmark.sol +++ /dev/null @@ -1,82 +0,0 @@ -pragma solidity 0.8.16; - -contract AutomationConsumerBenchmark { - event PerformingUpkeep(uint256 id, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); - - mapping(uint256 => uint256) public initialCall; - mapping(uint256 => uint256) public nextEligible; - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - mapping(uint256 => uint256) public count; - uint256 deployedAt; - - constructor() { - deployedAt = block.number; - } - - function checkUpkeep(bytes calldata checkData) external view returns (bool, bytes memory) { - ( - uint256 id, - uint256 interval, - uint256 range, - uint256 checkBurnAmount, - uint256 performBurnAmount, - uint256 firstEligibleBuffer - ) = abi.decode(checkData, (uint256, uint256, uint256, uint256, uint256, uint256)); - uint256 startGas = gasleft(); - bytes32 dummyIndex = blockhash(block.number - 1); - bool dummy; - // burn gas - if (checkBurnAmount > 0 && eligible(id, range, firstEligibleBuffer)) { - while (startGas - gasleft() < checkBurnAmount) { - dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads - dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); - } - } - return (eligible(id, range, firstEligibleBuffer), checkData); - } - - function performUpkeep(bytes calldata performData) external { - ( - uint256 id, - uint256 interval, - uint256 range, - uint256 checkBurnAmount, - uint256 performBurnAmount, - uint256 firstEligibleBuffer - ) = abi.decode(performData, (uint256, uint256, uint256, uint256, uint256, uint256)); - require(eligible(id, range, firstEligibleBuffer)); - uint256 startGas = gasleft(); - if (initialCall[id] == 0) { - initialCall[id] = block.number; - } - nextEligible[id] = block.number + interval; - count[id]++; - emit PerformingUpkeep(id, tx.origin, initialCall[id], nextEligible[id], block.number); - // burn gas - bytes32 dummyIndex = blockhash(block.number - 1); - bool dummy; - while (startGas - gasleft() < performBurnAmount) { - dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads - dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); - } - } - - function getCountPerforms(uint256 id) public view returns (uint256) { - return count[id]; - } - - function eligible(uint256 id, uint256 range, uint256 firstEligibleBuffer) internal view returns (bool) { - return - initialCall[id] == 0 - ? block.number >= firstEligibleBuffer + deployedAt - : (block.number - initialCall[id] < range && block.number > nextEligible[id]); - } - - function checkEligible(uint256 id, uint256 range, uint256 firstEligibleBuffer) public view returns (bool) { - return eligible(id, range, firstEligibleBuffer); - } - - function reset() external { - deployedAt = block.number; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol deleted file mode 100644 index 21fa9b0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Broken.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.8.0; - -// Broken is a contract to aid debugging and testing reverting calls during development. -contract Broken { - error Unauthorized(string reason, int256 reason2); - - function revertWithCustomError() public pure { - revert Unauthorized("param", 121); - } - - function revertWithMessage(string memory message) public pure { - require(false, message); - } - - function revertSilently() public pure { - require(false); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol deleted file mode 100644 index a344138..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkClientTestHelper.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../ChainlinkClient.sol"; - -contract ChainlinkClientTestHelper is ChainlinkClient { - constructor(address _link, address _oracle) { - _setChainlinkToken(_link); - _setChainlinkOracle(_oracle); - } - - event Request(bytes32 id, address callbackAddress, bytes4 callbackfunctionSelector, bytes data); - event LinkAmount(uint256 amount); - - function publicNewRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature) public { - Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - emit Request(req.id, req.callbackAddress, req.callbackFunctionId, req.buf.buf); - } - - function publicRequest(bytes32 _id, address _address, bytes memory _fulfillmentSignature, uint256 _wei) public { - Chainlink.Request memory req = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - _sendChainlinkRequest(req, _wei); - } - - function publicRequestRunTo( - address _oracle, - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = _buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - _sendChainlinkRequestTo(_oracle, run, _wei); - } - - function publicRequestOracleData(bytes32 _id, bytes memory _fulfillmentSignature, uint256 _wei) public { - Chainlink.Request memory req = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - _sendOperatorRequest(req, _wei); - } - - function publicRequestOracleDataFrom( - address _oracle, - bytes32 _id, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = _buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - _sendOperatorRequestTo(_oracle, run, _wei); - } - - function publicCancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - _cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function publicChainlinkToken() public view returns (address) { - return _chainlinkTokenAddress(); - } - - function publicFulfillChainlinkRequest(bytes32 _requestId, bytes32) public { - fulfillRequest(_requestId, bytes32(0)); - } - - function fulfillRequest(bytes32 _requestId, bytes32) public { - _validateChainlinkCallback(_requestId); - } - - function publicLINK(uint256 _amount) public { - emit LinkAmount(LINK_DIVISIBILITY * _amount); - } - - function publicOracleAddress() public view returns (address) { - return _chainlinkOracleAddress(); - } - - function publicAddExternalRequest(address _oracle, bytes32 _requestId) public { - _addChainlinkExternalRequest(_oracle, _requestId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol deleted file mode 100644 index d42f30c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ChainlinkTestHelper.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../Chainlink.sol"; -import "../vendor/CBORChainlink.sol"; -import "../vendor/BufferChainlink.sol"; - -contract ChainlinkTestHelper { - using Chainlink for Chainlink.Request; - using CBORChainlink for BufferChainlink.buffer; - - Chainlink.Request private req; - - event RequestData(bytes payload); - - function closeEvent() public { - emit RequestData(req.buf.buf); - } - - function setBuffer(bytes memory data) public { - Chainlink.Request memory r2 = req; - r2._setBuffer(data); - req = r2; - } - - function add(string memory _key, string memory _value) public { - Chainlink.Request memory r2 = req; - r2._add(_key, _value); - req = r2; - } - - function addBytes(string memory _key, bytes memory _value) public { - Chainlink.Request memory r2 = req; - r2._addBytes(_key, _value); - req = r2; - } - - function addInt(string memory _key, int256 _value) public { - Chainlink.Request memory r2 = req; - r2._addInt(_key, _value); - req = r2; - } - - function addUint(string memory _key, uint256 _value) public { - Chainlink.Request memory r2 = req; - r2._addUint(_key, _value); - req = r2; - } - - // Temporarily have method receive bytes32[] memory until experimental - // string[] memory can be invoked from truffle tests. - function addStringArray(string memory _key, string[] memory _values) public { - Chainlink.Request memory r2 = req; - r2._addStringArray(_key, _values); - req = r2; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol deleted file mode 100644 index 1ceb789..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Counter.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -contract Counter { - error AlwaysRevert(); - - uint256 public count = 0; - - function increment() public returns (uint256) { - count += 1; - return count; - } - - function reset() public { - count = 0; - } - - function alwaysRevert() public pure { - revert AlwaysRevert(); - } - - function alwaysRevertWithString() public pure { - revert("always revert"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol deleted file mode 100644 index cee50c1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/CronReceiver.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -contract CronReceiver { - event Received1(); - event Received2(); - - function handler1() external { - emit Received1(); - } - - function handler2() external { - emit Received2(); - } - - function revertHandler() external { - revert("revert!"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol deleted file mode 100644 index a29ba36..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ERC20BalanceMonitorExposed.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import "../automation/upkeeps/ERC20BalanceMonitor.sol"; - -contract ERC20BalanceMonitorExposed is ERC20BalanceMonitor { - constructor( - address erc20TokenAddress, - address keeperRegistryAddress, - uint256 minWaitPeriod - ) ERC20BalanceMonitor(erc20TokenAddress, keeperRegistryAddress, minWaitPeriod) {} - - function setLastTopUpXXXTestOnly(address target, uint56 lastTopUpTimestamp) external { - s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol deleted file mode 100644 index 74cc682..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/EthBalanceMonitorExposed.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import "../automation/upkeeps/EthBalanceMonitor.sol"; - -contract EthBalanceMonitorExposed is EthBalanceMonitor { - constructor( - address keeperRegistryAddress, - uint256 minWaitPeriod - ) EthBalanceMonitor(keeperRegistryAddress, minWaitPeriod) {} - - function setLastTopUpXXXTestOnly(address target, uint56 lastTopUpTimestamp) external { - s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol deleted file mode 100644 index c9fc623..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FeedConsumer.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AggregatorV2V3Interface} from "../shared/interfaces/AggregatorV2V3Interface.sol"; - -contract FeedConsumer { - AggregatorV2V3Interface public immutable AGGREGATOR; - - constructor(address feedAddress) { - AGGREGATOR = AggregatorV2V3Interface(feedAddress); - } - - function latestAnswer() external view returns (int256 answer) { - return AGGREGATOR.latestAnswer(); - } - - function latestTimestamp() external view returns (uint256) { - return AGGREGATOR.latestTimestamp(); - } - - function latestRound() external view returns (uint256) { - return AGGREGATOR.latestRound(); - } - - function getAnswer(uint256 roundId) external view returns (int256) { - return AGGREGATOR.getAnswer(roundId); - } - - function getTimestamp(uint256 roundId) external view returns (uint256) { - return AGGREGATOR.getTimestamp(roundId); - } - - function decimals() external view returns (uint8) { - return AGGREGATOR.decimals(); - } - - function description() external view returns (string memory) { - return AGGREGATOR.description(); - } - - function version() external view returns (uint256) { - return AGGREGATOR.version(); - } - - function getRoundData( - uint80 _roundId - ) - external - view - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return AGGREGATOR.getRoundData(_roundId); - } - - function latestRoundData() - external - view - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return AGGREGATOR.latestRoundData(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol deleted file mode 100644 index 3e35cae..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/FlagsTestHelper.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../Flags.sol"; - -contract FlagsTestHelper { - Flags public flags; - - constructor(address flagsContract) { - flags = Flags(flagsContract); - } - - function getFlag(address subject) external view returns (bool) { - return flags.getFlag(subject); - } - - function getFlags(address[] calldata subjects) external view returns (bool[] memory) { - return flags.getFlags(subjects); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol deleted file mode 100644 index 88ccca5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/Greeter.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.8.0; - -import "../shared/access/ConfirmedOwner.sol"; - -contract Greeter is ConfirmedOwner { - string public greeting; - - constructor(address owner) ConfirmedOwner(owner) {} - - function setGreeting(string calldata _greeting) external onlyOwner { - require(bytes(_greeting).length > 0, "Invalid greeting length"); - greeting = _greeting; - } - - function triggerRevert() external pure { - require(false, "Greeter: revert triggered"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol deleted file mode 100644 index 2e931c4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/KeeperCompatibleTestHelper.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../automation/KeeperCompatible.sol"; - -contract KeeperCompatibleTestHelper is KeeperCompatible { - function checkUpkeep(bytes calldata) external override returns (bool, bytes memory) {} - - function performUpkeep(bytes calldata) external override {} - - function verifyCannotExecute() public view cannotExecute {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol deleted file mode 100644 index 37306cc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/LogEmitter.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract LogEmitter { - event Log1(uint256); - event Log2(uint256 indexed); - event Log3(string); - event Log4(uint256 indexed, uint256 indexed); - - function EmitLog1(uint256[] memory v) public { - for (uint256 i = 0; i < v.length; i++) { - emit Log1(v[i]); - } - } - - function EmitLog2(uint256[] memory v) public { - for (uint256 i = 0; i < v.length; i++) { - emit Log2(v[i]); - } - } - - function EmitLog3(string[] memory v) public { - for (uint256 i = 0; i < v.length; i++) { - emit Log3(v[i]); - } - } - - function EmitLog4(uint256 v, uint256 w, uint256 c) public { - for (uint256 i = 0; i < c; i++) { - emit Log4(v, w); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol deleted file mode 100644 index f85e028..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbGasInfo.sol +++ /dev/null @@ -1,11 +0,0 @@ -pragma solidity 0.8.6; - -contract MockArbGasInfo { - function getCurrentTxL1GasFees() external view returns (uint256) { - return 1000000; - } - - function getPricesInWei() external view returns (uint256, uint256, uint256, uint256, uint256, uint256) { - return (0, 1000, 0, 0, 0, 0); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol deleted file mode 100644 index 445a361..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockArbitrumInbox.sol +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -import {IInbox} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; -import {IBridge} from "../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol"; - -contract MockArbitrumInbox is IInbox { - event RetryableTicketNoRefundAliasRewriteCreated( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes data - ); - - function sendL2Message(bytes calldata /* messageData */) external pure override returns (uint256) { - return 0; - } - - function sendUnsignedTransaction( - uint256 /* maxGas */, - uint256 /* gasPriceBid */, - uint256 /* nonce */, - address /* destAddr */, - uint256 /* amount */, - bytes calldata /* data */ - ) external pure override returns (uint256) { - return 0; - } - - function sendContractTransaction( - uint256 /* maxGas */, - uint256 /* gasPriceBid */, - address /* destAddr */, - uint256 /* amount */, - bytes calldata /* data */ - ) external pure override returns (uint256) { - return 0; - } - - function sendL1FundedUnsignedTransaction( - uint256 /* maxGas */, - uint256 /* gasPriceBid */, - uint256 /* nonce */, - address /* destAddr */, - bytes calldata /* data */ - ) external payable override returns (uint256) { - return 0; - } - - function sendL1FundedContractTransaction( - uint256 /* maxGas */, - uint256 /* gasPriceBid */, - address /* destAddr */, - bytes calldata /* data */ - ) external payable override returns (uint256) { - return 0; - } - - function createRetryableTicketNoRefundAliasRewrite( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes calldata data - ) external payable override returns (uint256) { - emit RetryableTicketNoRefundAliasRewriteCreated( - destAddr, - arbTxCallValue, - maxSubmissionCost, - submissionRefundAddress, - valueRefundAddress, - maxGas, - gasPriceBid, - data - ); - return 42; - } - - function createRetryableTicket( - address /* destAddr */, - uint256 /* arbTxCallValue */, - uint256 /* maxSubmissionCost */, - address /* submissionRefundAddress */, - address /* valueRefundAddress */, - uint256 /* maxGas */, - uint256 /* gasPriceBid */, - bytes calldata /* data */ - ) external payable override returns (uint256) { - return 0; - } - - function depositEth(address /* destAddr */) external payable override returns (uint256) { - return 0; - } - - function depositEthRetryable( - address /* destAddr */, - uint256 /* maxSubmissionCost */, - uint256 /* maxGas */, - uint256 /* maxGasPrice */ - ) external payable override returns (uint256) { - return 0; - } - - function bridge() external pure override returns (IBridge) { - return IBridge(address(0)); - } - - /// @notice This mock function simply replicates the formula used by Arbitrum's - /// DelayedInbox in the Nitro upgrade. The function has been copied here from the Arbitrum - /// team's repository. - /// @param dataLength The length of the calldata that will be executed in L2 - /// @param baseFee The base fee to pay for the transaction. - /// @dev The calculation will use the L1 base fee if it is passed 0. - function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee) public view returns (uint256) { - return (1400 + 6 * dataLength) * (baseFee == 0 ? block.basefee : baseFee); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol deleted file mode 100644 index d685aac..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockETHLINKAggregator.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../shared/interfaces/AggregatorV3Interface.sol"; - -contract MockETHLINKAggregator is AggregatorV3Interface { - int256 public answer; - - constructor(int256 _answer) public { - answer = _answer; - } - - function decimals() external view override returns (uint8) { - return 18; - } - - function description() external view override returns (string memory) { - return "MockETHLINKAggregator"; - } - - function version() external view override returns (uint256) { - return 1; - } - - function getRoundData( - uint80 _roundId - ) - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } - - function latestRoundData() - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol deleted file mode 100644 index 3184f9d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockGasBoundCaller.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -contract MockGasBoundCaller { - error TransactionFailed(address target); - - function gasBoundCall(address target, uint256 gasAmount, bytes memory data) external payable { - bool success; - assembly { - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - - // gas bound caller will propagate the revert - if (!success) { - revert TransactionFailed(target); - } - - uint256 pubdataGas = 500000; - bytes memory returnData = abi.encode(address(0), pubdataGas); - - uint256 paddedReturndataLen = returnData.length + 96; - if (paddedReturndataLen % 32 != 0) { - paddedReturndataLen += 32 - (paddedReturndataLen % 32); - } - - assembly { - mstore(sub(returnData, 0x40), 0x40) - mstore(sub(returnData, 0x20), pubdataGas) - return(sub(returnData, 0x40), paddedReturndataLen) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol deleted file mode 100644 index 6bb0dae..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOVMGasPriceOracle.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -contract MockOVMGasPriceOracle { - function getL1Fee(bytes memory) public pure returns (uint256) { - return 2000000; - } - - function getL1FeeUpperBound(uint256) public pure returns (uint256) { - return 2000000; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol deleted file mode 100644 index a92ff8f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL1CrossDomainMessenger.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Interface Imports */ -import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; - -contract MockOptimismL1CrossDomainMessenger is IL1CrossDomainMessenger { - uint256 private s_nonce; - - // slither-disable-next-line external-function - function xDomainMessageSender() public pure returns (address) { - return address(0); - } - - function sendMessage(address _target, bytes memory _message, uint32 _gasLimit) public { - emit SentMessage(_target, msg.sender, _message, s_nonce, _gasLimit); - s_nonce++; - } - - /** - * Relays a cross domain message to a contract. - * @inheritdoc IL1CrossDomainMessenger - */ - // slither-disable-next-line external-function - function relayMessage( - address _target, - address _sender, - bytes memory _message, - uint256 _messageNonce, - L2MessageInclusionProof memory _proof - ) public {} - - function replayMessage( - address _target, - address _sender, - bytes memory _message, - uint256 _queueIndex, - uint32 _oldGasLimit, - uint32 _newGasLimit - ) public {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol deleted file mode 100644 index 38ec337..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockOptimismL2CrossDomainMessenger.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* Interface Imports */ -import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; - -contract MockOptimismL2CrossDomainMessenger is IL2CrossDomainMessenger { - uint256 private s_nonce; - address private s_sender; - - // slither-disable-next-line external-function - function xDomainMessageSender() public view returns (address) { - return s_sender; - } - - function setSender(address newSender) external { - s_sender = newSender; - } - - function sendMessage(address _target, bytes memory _message, uint32 _gasLimit) public { - emit SentMessage(_target, msg.sender, _message, s_nonce, _gasLimit); - s_nonce++; - } - - function relayMessage(address _target, address _sender, bytes memory _message, uint256 _messageNonce) external {} - - receive() external payable {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol deleted file mode 100644 index 9822d23..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockV3Aggregator.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../shared/interfaces/AggregatorV2V3Interface.sol"; - -/** - * @title MockV3Aggregator - * @notice Based on the FluxAggregator contract - * @notice Use this contract when you need to test - * other contract's ability to read data from an - * aggregator contract, but how the aggregator got - * its answer is unimportant - */ -contract MockV3Aggregator is AggregatorV2V3Interface { - uint256 public constant override version = 0; - - uint8 public override decimals; - int256 public override latestAnswer; - uint256 public override latestTimestamp; - uint256 public override latestRound; - - mapping(uint256 => int256) public override getAnswer; - mapping(uint256 => uint256) public override getTimestamp; - mapping(uint256 => uint256) private getStartedAt; - - constructor(uint8 _decimals, int256 _initialAnswer) { - decimals = _decimals; - updateAnswer(_initialAnswer); - } - - function updateAnswer(int256 _answer) public { - latestAnswer = _answer; - latestTimestamp = block.timestamp; - latestRound++; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = block.timestamp; - getStartedAt[latestRound] = block.timestamp; - } - - function updateRoundData(uint80 _roundId, int256 _answer, uint256 _timestamp, uint256 _startedAt) public { - latestRound = _roundId; - latestAnswer = _answer; - latestTimestamp = _timestamp; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = _timestamp; - getStartedAt[latestRound] = _startedAt; - } - - function getRoundData( - uint80 _roundId - ) - external - view - override - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId); - } - - function latestRoundData() - external - view - override - returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return ( - uint80(latestRound), - getAnswer[latestRound], - getStartedAt[latestRound], - getTimestamp[latestRound], - uint80(latestRound) - ); - } - - function description() external pure override returns (string memory) { - return "v0.8/tests/MockV3Aggregator.sol"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol deleted file mode 100644 index 265d4b6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/MockZKSyncSystemContext.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.19; - -contract MockZKSyncSystemContext { - function gasPrice() external pure returns (uint256) { - return 250000000; // 0.25 gwei - } - - function gasPerPubdataByte() external pure returns (uint256) { - return 500; - } - - function getCurrentPubdataSpent() external pure returns (uint256 currentPubdataSpent) { - return 1000; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol deleted file mode 100644 index 641bf75..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveEmitter.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -contract ReceiveEmitter { - event FundsReceived(uint256 amount, uint256 newBalance); - - receive() external payable { - emit FundsReceived(msg.value, address(this).balance); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol deleted file mode 100644 index 618787e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveFallbackEmitter.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -contract ReceiveFallbackEmitter { - event FundsReceived(uint256 amount, uint256 newBalance); - - fallback() external payable { - emit FundsReceived(msg.value, address(this).balance); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol deleted file mode 100644 index d9a2bdc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/ReceiveReverter.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -contract ReceiveReverter { - receive() external payable { - revert("Can't send funds"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol deleted file mode 100644 index dec93d5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/StreamsLookupUpkeep.sol +++ /dev/null @@ -1,159 +0,0 @@ -pragma solidity 0.8.16; - -import "../automation/interfaces/AutomationCompatibleInterface.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; -import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; - -interface IVerifierProxy { - /** - * @notice Verifies that the data encoded has been signed - * correctly by routing to the correct verifier. - * @param signedReport The encoded data to be verified. - * @return verifierResponse The encoded response from the verifier. - */ - function verify(bytes memory signedReport) external returns (bytes memory verifierResponse); -} - -contract StreamsLookupUpkeep is AutomationCompatibleInterface, StreamsLookupCompatibleInterface { - event MercuryPerformEvent(address indexed sender, uint256 indexed blockNumber, bytes v0, bytes verifiedV0, bytes ed); - - ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); - // keep these in sync with verifier proxy in RDD - IVerifierProxy internal constant PRODUCTION_TESTNET_VERIFIER_PROXY = - IVerifierProxy(0x09DFf56A4fF44e0f4436260A04F5CFa65636A481); - IVerifierProxy internal constant STAGING_TESTNET_VERIFIER_PROXY = - IVerifierProxy(0x60448B880c9f3B501af3f343DA9284148BD7D77C); - - uint256 public testRange; - uint256 public interval; - uint256 public previousPerformBlock; - uint256 public initialBlock; - uint256 public counter; - string[] public feeds; - string public feedParamKey; - string public timeParamKey; - bool public immutable useArbBlock; - bool public staging; - bool public verify; - bool public shouldRevertCallback; - bool public callbackReturnBool; - - constructor(uint256 _testRange, uint256 _interval, bool _useArbBlock, bool _staging, bool _verify) { - testRange = _testRange; - interval = _interval; - previousPerformBlock = 0; - initialBlock = 0; - counter = 0; - useArbBlock = _useArbBlock; - feedParamKey = "feedIDs"; // feedIDs for v0.3 - timeParamKey = "timestamp"; // timestamp - // search feeds in notion: "Schema and Feed ID Registry" - feeds = [ - //"0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", // ETH / USD in production testnet v0.2 - //"0x4254432d5553442d415242495452554d2d544553544e45540000000000000000" // BTC / USD in production testnet v0.2 - "0x00028c915d6af0fd66bba2d0fc9405226bca8d6806333121a7d9832103d1563c" // ETH / USD in staging testnet v0.3 - ]; - staging = _staging; - verify = _verify; - callbackReturnBool = true; - } - - function setParamKeys(string memory _feedParamKey, string memory _timeParamKey) external { - feedParamKey = _feedParamKey; - timeParamKey = _timeParamKey; - } - - function setFeeds(string[] memory _feeds) external { - feeds = _feeds; - } - - function setShouldRevertCallback(bool value) public { - shouldRevertCallback = value; - } - - function setCallbackReturnBool(bool value) public { - callbackReturnBool = value; - } - - function reset() public { - previousPerformBlock = 0; - initialBlock = 0; - counter = 0; - } - - function checkCallback(bytes[] memory values, bytes memory extraData) external view returns (bool, bytes memory) { - require(!shouldRevertCallback, "shouldRevertCallback is true"); - // do sth about the chainlinkBlob data in values and extraData - bytes memory performData = abi.encode(values, extraData); - return (callbackReturnBool, performData); - } - - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (false, new bytes(0)); - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - if (!eligible()) { - return (false, data); - } - uint256 timeParam; - if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { - if (useArbBlock) { - timeParam = ARB_SYS.arbBlockNumber(); - } else { - timeParam = block.number; - } - } else { - // assume this will be feedIDs for v0.3 - timeParam = block.timestamp; - } - - // encode ARB_SYS as extraData to verify that it is provided to checkCallback correctly. - // in reality, this can be any data or empty - revert StreamsLookup(feedParamKey, feeds, timeParamKey, timeParam, abi.encodePacked(address(ARB_SYS))); - } - - function performUpkeep(bytes calldata performData) external { - uint256 blockNumber; - if (useArbBlock) { - blockNumber = ARB_SYS.arbBlockNumber(); - } else { - blockNumber = block.number; - } - if (initialBlock == 0) { - initialBlock = blockNumber; - } - (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); - previousPerformBlock = blockNumber; - counter = counter + 1; - - bytes memory v0 = ""; - bytes memory v1 = ""; - if (verify) { - if (staging) { - v0 = STAGING_TESTNET_VERIFIER_PROXY.verify(values[0]); - } else { - v0 = PRODUCTION_TESTNET_VERIFIER_PROXY.verify(values[0]); - } - } - emit MercuryPerformEvent(msg.sender, blockNumber, values[0], v0, extraData); - } - - function eligible() public view returns (bool) { - if (initialBlock == 0) { - return true; - } - - uint256 blockNumber; - if (useArbBlock) { - blockNumber = ARB_SYS.arbBlockNumber(); - } else { - blockNumber = block.number; - } - return (blockNumber - initialBlock) < testRange && (blockNumber - previousPerformBlock) >= interval; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol deleted file mode 100644 index 18b9960..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VRFLogEmitter.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract VRFLogEmitter { - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint64 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address indexed sender - ); - event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); - - function emitRandomWordsRequested( - bytes32 keyHash, - uint256 requestId, - uint256 preSeed, - uint64 subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address sender - ) public { - emit RandomWordsRequested( - keyHash, - requestId, - preSeed, - subId, - minimumRequestConfirmations, - callbackGasLimit, - numWords, - sender - ); - } - - function emitRandomWordsFulfilled(uint256 requestId, uint256 outputSeed, uint96 payment, bool success) public { - emit RandomWordsFulfilled(requestId, outputSeed, payment, success); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol deleted file mode 100644 index 86ebf8b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadBase.sol +++ /dev/null @@ -1,572 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {IKeeperRegistryMaster, IAutomationV21PlusCommon} from "../automation/interfaces/v2_1/IKeeperRegistryMaster.sol"; -import {ArbSys} from "../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import "../automation/v2_1/AutomationRegistrar2_1.sol"; -import {LogTriggerConfig} from "../automation/v2_1/AutomationUtils2_1.sol"; - -abstract contract VerifiableLoadBase is ConfirmedOwner { - error IndexOutOfRange(); - event LogEmitted(uint256 indexed upkeepId, uint256 indexed blockNum, address indexed addr); - event LogEmittedAgain(uint256 indexed upkeepId, uint256 indexed blockNum, address indexed addr); - event UpkeepTopUp(uint256 upkeepId, uint96 amount, uint256 blockNum); - - using EnumerableSet for EnumerableSet.UintSet; - ArbSys internal constant ARB_SYS = ArbSys(0x0000000000000000000000000000000000000064); - //bytes32 public constant emittedSig = 0x97009585a4d2440f981ab6f6eec514343e1e6b2aa9b991a26998e6806f41bf08; //keccak256(LogEmitted(uint256,uint256,address)) - bytes32 public immutable emittedSig = LogEmitted.selector; - // bytes32 public constant emittedAgainSig = 0xc76416badc8398ce17c93eab7b4f60f263241694cf503e4df24f233a8cc1c50d; //keccak256(LogEmittedAgain(uint256,uint256,address)) - bytes32 public immutable emittedAgainSig = LogEmittedAgain.selector; - - mapping(uint256 => uint256) public lastTopUpBlocks; - mapping(uint256 => uint256) public intervals; - mapping(uint256 => uint256) public previousPerformBlocks; - mapping(uint256 => uint256) public firstPerformBlocks; - mapping(uint256 => uint256) public counters; - mapping(uint256 => uint256) public performGasToBurns; - mapping(uint256 => uint256) public checkGasToBurns; - mapping(uint256 => uint256) public performDataSizes; - mapping(uint256 => uint256) public gasLimits; - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - mapping(uint256 => uint256[]) public delays; // how to query for delays for a certain past period: calendar day and/or past 24 hours - - mapping(uint256 => mapping(uint16 => uint256[])) public bucketedDelays; - mapping(uint256 => uint16) public buckets; - EnumerableSet.UintSet internal s_upkeepIDs; - AutomationRegistrar2_1 public registrar; - LinkTokenInterface public linkToken; - IKeeperRegistryMaster public registry; - // check if an upkeep is eligible for adding funds at this interval - uint256 public upkeepTopUpCheckInterval = 5; - // an upkeep will get this amount of LINK for every top up - uint96 public addLinkAmount = 200000000000000000; // 0.2 LINK - // if an upkeep's balance is less than this threshold * min balance, this upkeep is eligible for adding funds - uint8 public minBalanceThresholdMultiplier = 20; - // if this contract is using arbitrum block number - bool public immutable useArbitrumBlockNum; - - // the following fields are immutable bc if they are adjusted, the existing upkeeps' delays will be stored in - // different sizes of buckets. it's better to redeploy this contract with new values. - uint16 public immutable BUCKET_SIZE = 100; - - // search feeds in notion: "Schema and Feed ID Registry" - string[] public feedsHex = [ - "0x4554482d5553442d415242495452554d2d544553544e45540000000000000000", - "0x4254432d5553442d415242495452554d2d544553544e45540000000000000000" - ]; - string public feedParamKey = "feedIdHex"; // feedIDs for v0.3 - string public timeParamKey = "blockNumber"; // timestamp for v0.3 - - /** - * @param _registrar a automation registrar 2.1 address - * @param _useArb if this contract will use arbitrum block number - */ - constructor(AutomationRegistrar2_1 _registrar, bool _useArb) ConfirmedOwner(msg.sender) { - registrar = _registrar; - (address registryAddress, ) = registrar.getConfig(); - registry = IKeeperRegistryMaster(payable(address(registryAddress))); - linkToken = registrar.LINK(); - useArbitrumBlockNum = _useArb; - } - - receive() external payable {} - - function setParamKeys(string memory _feedParamKey, string memory _timeParamKey) external { - feedParamKey = _feedParamKey; - timeParamKey = _timeParamKey; - } - - function setFeeds(string[] memory _feeds) external { - feedsHex = _feeds; - } - - /** - * @notice withdraws LINKs from this contract to msg sender when testing is finished. - */ - function withdrawLinks() external onlyOwner { - uint256 balance = linkToken.balanceOf(address(this)); - linkToken.transfer(msg.sender, balance); - } - - function getBlockNumber() internal view returns (uint256) { - if (useArbitrumBlockNum) { - return ARB_SYS.arbBlockNumber(); - } else { - return block.number; - } - } - - /** - * @notice sets registrar, registry, and link token address. - * @param newRegistrar the new registrar address - */ - function setConfig(AutomationRegistrar2_1 newRegistrar) external { - registrar = newRegistrar; - (address registryAddress, ) = registrar.getConfig(); - registry = IKeeperRegistryMaster(payable(address(registryAddress))); - linkToken = registrar.LINK(); - } - - /** - * @notice gets an array of active upkeep IDs. - * @param startIndex the start index of upkeep IDs - * @param maxCount the max number of upkeep IDs requested - * @return an array of active upkeep IDs - */ - function getActiveUpkeepIDsDeployedByThisContract( - uint256 startIndex, - uint256 maxCount - ) external view returns (uint256[] memory) { - uint256 maxIdx = s_upkeepIDs.length(); - if (startIndex >= maxIdx) revert IndexOutOfRange(); - if (maxCount == 0) { - maxCount = maxIdx - startIndex; - } - uint256[] memory ids = new uint256[](maxCount); - for (uint256 idx = 0; idx < maxCount; idx++) { - ids[idx] = s_upkeepIDs.at(startIndex + idx); - } - return ids; - } - - /** - * @notice gets an array of active upkeep IDs. - * @param startIndex the start index of upkeep IDs - * @param maxCount the max number of upkeep IDs requested - * @return an array of active upkeep IDs - */ - function getAllActiveUpkeepIDsOnRegistry( - uint256 startIndex, - uint256 maxCount - ) external view returns (uint256[] memory) { - return registry.getActiveUpkeepIDs(startIndex, maxCount); - } - - /** - * @notice register an upkeep via the registrar. - * @param params a registration params struct - * @return an upkeep ID - */ - function _registerUpkeep(AutomationRegistrar2_1.RegistrationParams memory params) private returns (uint256) { - uint256 upkeepId = registrar.registerUpkeep(params); - s_upkeepIDs.add(upkeepId); - gasLimits[upkeepId] = params.gasLimit; - return upkeepId; - } - - /** - * @notice returns a log trigger config - */ - function getLogTriggerConfig( - address addr, - uint8 selector, - bytes32 topic0, - bytes32 topic1, - bytes32 topic2, - bytes32 topic3 - ) external view returns (bytes memory logTrigger) { - LogTriggerConfig memory cfg = LogTriggerConfig({ - contractAddress: addr, - filterSelector: selector, - topic0: topic0, - topic1: topic1, - topic2: topic2, - topic3: topic3 - }); - return abi.encode(cfg); - } - - // this function sets pipeline data and trigger config for log trigger upkeeps - function batchPreparingUpkeeps( - uint256[] calldata upkeepIds, - uint8 selector, - bytes32 topic0, - bytes32 topic1, - bytes32 topic2, - bytes32 topic3 - ) external { - uint256 len = upkeepIds.length; - for (uint256 i = 0; i < len; i++) { - uint256 upkeepId = upkeepIds[i]; - - this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); - - uint8 triggerType = registry.getTriggerType(upkeepId); - if (triggerType == 1) { - // currently no using a filter selector - bytes memory triggerCfg = this.getLogTriggerConfig(address(this), selector, topic0, topic2, topic2, topic3); - registry.setUpkeepTriggerConfig(upkeepId, triggerCfg); - } - } - } - - // this function sets pipeline data and trigger config for log trigger upkeeps - function batchPreparingUpkeepsSimple(uint256[] calldata upkeepIds, uint8 log, uint8 selector) external { - uint256 len = upkeepIds.length; - for (uint256 i = 0; i < len; i++) { - uint256 upkeepId = upkeepIds[i]; - - this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); - - uint8 triggerType = registry.getTriggerType(upkeepId); - if (triggerType == 1) { - // currently no using a filter selector - bytes32 sig = emittedSig; - if (log != 0) { - sig = emittedAgainSig; - } - bytes memory triggerCfg = this.getLogTriggerConfig( - address(this), - selector, - sig, - bytes32(abi.encode(upkeepId)), - bytes32(0), - bytes32(0) - ); - registry.setUpkeepTriggerConfig(upkeepId, triggerCfg); - } - } - } - - function updateLogTriggerConfig1( - uint256 upkeepId, - address addr, - uint8 selector, - bytes32 topic0, - bytes32 topic1, - bytes32 topic2, - bytes32 topic3 - ) external { - registry.setUpkeepTriggerConfig(upkeepId, this.getLogTriggerConfig(addr, selector, topic0, topic1, topic2, topic3)); - } - - function updateLogTriggerConfig2(uint256 upkeepId, bytes calldata cfg) external { - registry.setUpkeepTriggerConfig(upkeepId, cfg); - } - - /** - * @notice batch registering upkeeps. - * @param number the number of upkeeps to be registered - * @param gasLimit the gas limit of each upkeep - * @param triggerType the trigger type of this upkeep, 0 for conditional, 1 for log trigger - * @param triggerConfig the trigger config of this upkeep - * @param amount the amount of LINK to fund each upkeep - * @param checkGasToBurn the amount of check gas to burn - * @param performGasToBurn the amount of perform gas to burn - */ - function batchRegisterUpkeeps( - uint8 number, - uint32 gasLimit, - uint8 triggerType, - bytes memory triggerConfig, - uint96 amount, - uint256 checkGasToBurn, - uint256 performGasToBurn - ) external { - AutomationRegistrar2_1.RegistrationParams memory params = AutomationRegistrar2_1.RegistrationParams({ - name: "test", - encryptedEmail: bytes(""), - upkeepContract: address(this), - gasLimit: gasLimit, - adminAddress: address(this), // use address of this contract as the admin - triggerType: triggerType, - checkData: bytes(""), // update pipeline data later bc upkeep id is not available now - triggerConfig: triggerConfig, - offchainConfig: bytes(""), - amount: amount - }); - - linkToken.approve(address(registrar), amount * number); - - uint256[] memory upkeepIds = new uint256[](number); - for (uint8 i = 0; i < number; i++) { - uint256 upkeepId = _registerUpkeep(params); - upkeepIds[i] = upkeepId; - checkGasToBurns[upkeepId] = checkGasToBurn; - performGasToBurns[upkeepId] = performGasToBurn; - } - } - - function topUpFund(uint256 upkeepId, uint256 blockNum) public { - if (blockNum - lastTopUpBlocks[upkeepId] > upkeepTopUpCheckInterval) { - IAutomationV21PlusCommon.UpkeepInfoLegacy memory info = registry.getUpkeep(upkeepId); - uint96 minBalance = registry.getMinBalanceForUpkeep(upkeepId); - if (info.balance < minBalanceThresholdMultiplier * minBalance) { - addFunds(upkeepId, addLinkAmount); - lastTopUpBlocks[upkeepId] = blockNum; - emit UpkeepTopUp(upkeepId, addLinkAmount, blockNum); - } - } - } - - function getMinBalanceForUpkeep(uint256 upkeepId) external view returns (uint96) { - return registry.getMinBalanceForUpkeep(upkeepId); - } - - function getForwarder(uint256 upkeepID) external view returns (address) { - return registry.getForwarder(upkeepID); - } - - function getBalance(uint256 id) external view returns (uint96 balance) { - return registry.getBalance(id); - } - - function getTriggerType(uint256 upkeepId) external view returns (uint8) { - return registry.getTriggerType(upkeepId); - } - - function burnPerformGas(uint256 upkeepId, uint256 startGas, uint256 blockNum) public { - uint256 performGasToBurn = performGasToBurns[upkeepId]; - while (startGas - gasleft() + 10000 < performGasToBurn) { - dummyMap[blockhash(blockNum)] = false; - } - } - - /** - * @notice adds fund for an upkeep. - * @param upkeepId the upkeep ID - * @param amount the amount of LINK to be funded for the upkeep - */ - function addFunds(uint256 upkeepId, uint96 amount) public { - linkToken.approve(address(registry), amount); - registry.addFunds(upkeepId, amount); - } - - /** - * @notice updates pipeline data for an upkeep. In order for the upkeep to be performed, the pipeline data must be the abi encoded upkeep ID. - * @param upkeepId the upkeep ID - * @param pipelineData the new pipeline data for the upkeep - */ - function updateUpkeepPipelineData(uint256 upkeepId, bytes calldata pipelineData) external { - registry.setUpkeepCheckData(upkeepId, pipelineData); - } - - function withdrawLinks(uint256 upkeepId) external { - registry.withdrawFunds(upkeepId, address(this)); - } - - function batchWithdrawLinks(uint256[] calldata upkeepIds) external { - uint256 len = upkeepIds.length; - for (uint32 i = 0; i < len; i++) { - this.withdrawLinks(upkeepIds[i]); - } - } - - /** - * @notice batch canceling upkeeps. - * @param upkeepIds an array of upkeep IDs - */ - function batchCancelUpkeeps(uint256[] calldata upkeepIds) external { - uint256 len = upkeepIds.length; - for (uint8 i = 0; i < len; i++) { - registry.cancelUpkeep(upkeepIds[i]); - s_upkeepIDs.remove(upkeepIds[i]); - } - } - - function eligible(uint256 upkeepId) public view returns (bool) { - if (firstPerformBlocks[upkeepId] == 0) { - return true; - } - return (getBlockNumber() - previousPerformBlocks[upkeepId]) >= intervals[upkeepId]; - } - - // /** - // * @notice set a new add LINK amount. - // * @param amount the new value - // */ - // function setAddLinkAmount(uint96 amount) external { - // addLinkAmount = amount; - // } - // - // function setUpkeepTopUpCheckInterval(uint256 newInterval) external { - // upkeepTopUpCheckInterval = newInterval; - // } - // - // function setMinBalanceThresholdMultiplier(uint8 newMinBalanceThresholdMultiplier) external { - // minBalanceThresholdMultiplier = newMinBalanceThresholdMultiplier; - // } - - // function setPerformGasToBurn(uint256 upkeepId, uint256 value) public { - // performGasToBurns[upkeepId] = value; - // } - // - // function setCheckGasToBurn(uint256 upkeepId, uint256 value) public { - // checkGasToBurns[upkeepId] = value; - // } - - function setPerformDataSize(uint256 upkeepId, uint256 value) public { - performDataSizes[upkeepId] = value; - } - - function setUpkeepGasLimit(uint256 upkeepId, uint32 gasLimit) public { - registry.setUpkeepGasLimit(upkeepId, gasLimit); - gasLimits[upkeepId] = gasLimit; - } - - function setInterval(uint256 upkeepId, uint256 _interval) external { - intervals[upkeepId] = _interval; - firstPerformBlocks[upkeepId] = 0; - counters[upkeepId] = 0; - - delete delays[upkeepId]; - uint16 currentBucket = buckets[upkeepId]; - for (uint16 i = 0; i <= currentBucket; i++) { - delete bucketedDelays[upkeepId][i]; - } - delete buckets[upkeepId]; - } - - /** - * @notice batch setting intervals for an array of upkeeps. - * @param upkeepIds an array of upkeep IDs - * @param interval a new interval - */ - function batchSetIntervals(uint256[] calldata upkeepIds, uint32 interval) external { - uint256 len = upkeepIds.length; - for (uint256 i = 0; i < len; i++) { - this.setInterval(upkeepIds[i], interval); - } - } - - /** - * @notice batch updating pipeline data for all upkeeps. - * @param upkeepIds an array of upkeep IDs - */ - function batchUpdatePipelineData(uint256[] calldata upkeepIds) external { - uint256 len = upkeepIds.length; - for (uint256 i = 0; i < len; i++) { - uint256 upkeepId = upkeepIds[i]; - this.updateUpkeepPipelineData(upkeepId, abi.encode(upkeepId)); - } - } - - /** - * @notice finds all log trigger upkeeps and emits logs to serve as the initial trigger for upkeeps - */ - function batchSendLogs(uint8 log) external { - uint256[] memory upkeepIds = this.getActiveUpkeepIDsDeployedByThisContract(0, 0); - uint256 len = upkeepIds.length; - uint256 blockNum = getBlockNumber(); - for (uint256 i = 0; i < len; i++) { - uint256 upkeepId = upkeepIds[i]; - uint8 triggerType = registry.getTriggerType(upkeepId); - if (triggerType == 1) { - if (log == 0) { - emit LogEmitted(upkeepId, blockNum, address(this)); - } else { - emit LogEmittedAgain(upkeepId, blockNum, address(this)); - } - } - } - } - - function getUpkeepInfo(uint256 upkeepId) public view returns (IAutomationV21PlusCommon.UpkeepInfoLegacy memory) { - return registry.getUpkeep(upkeepId); - } - - function getUpkeepTriggerConfig(uint256 upkeepId) public view returns (bytes memory) { - return registry.getUpkeepTriggerConfig(upkeepId); - } - - function getUpkeepPrivilegeConfig(uint256 upkeepId) public view returns (bytes memory) { - return registry.getUpkeepPrivilegeConfig(upkeepId); - } - - function setUpkeepPrivilegeConfig(uint256 upkeepId, bytes memory cfg) external { - registry.setUpkeepPrivilegeConfig(upkeepId, cfg); - } - - function sendLog(uint256 upkeepId, uint8 log) external { - uint256 blockNum = getBlockNumber(); - if (log == 0) { - emit LogEmitted(upkeepId, blockNum, address(this)); - } else { - emit LogEmittedAgain(upkeepId, blockNum, address(this)); - } - } - - function getDelaysLength(uint256 upkeepId) public view returns (uint256) { - return delays[upkeepId].length; - } - - function getBucketedDelaysLength(uint256 upkeepId) public view returns (uint256) { - uint16 currentBucket = buckets[upkeepId]; - uint256 len = 0; - for (uint16 i = 0; i <= currentBucket; i++) { - len += bucketedDelays[upkeepId][i].length; - } - return len; - } - - function getDelays(uint256 upkeepId) public view returns (uint256[] memory) { - return delays[upkeepId]; - } - - function getBucketedDelays(uint256 upkeepId, uint16 bucket) public view returns (uint256[] memory) { - return bucketedDelays[upkeepId][bucket]; - } - - function getSumDelayLastNPerforms(uint256 upkeepId, uint256 n) public view returns (uint256, uint256) { - uint256[] memory delays = delays[upkeepId]; - return getSumDelayLastNPerforms(delays, n); - } - - function getSumDelayInBucket(uint256 upkeepId, uint16 bucket) public view returns (uint256, uint256) { - uint256[] memory delays = bucketedDelays[upkeepId][bucket]; - return getSumDelayLastNPerforms(delays, delays.length); - } - - function getSumDelayLastNPerforms(uint256[] memory delays, uint256 n) internal view returns (uint256, uint256) { - uint256 i; - uint256 len = delays.length; - if (n == 0 || n >= len) { - n = len; - } - uint256 sum = 0; - - for (i = 0; i < n; i++) sum = sum + delays[len - i - 1]; - return (sum, n); - } - - function getPxDelayLastNPerforms(uint256 upkeepId, uint256 p, uint256 n) public view returns (uint256) { - return getPxDelayLastNPerforms(delays[upkeepId], p, n); - } - - function getPxDelayLastNPerforms(uint256[] memory delays, uint256 p, uint256 n) internal view returns (uint256) { - uint256 i; - uint256 len = delays.length; - if (n == 0 || n >= len) { - n = len; - } - uint256[] memory subArr = new uint256[](n); - - for (i = 0; i < n; i++) subArr[i] = (delays[len - i - 1]); - quickSort(subArr, int256(0), int256(subArr.length - 1)); - - if (p == 100) { - return subArr[subArr.length - 1]; - } - return subArr[(p * subArr.length) / 100]; - } - - function quickSort(uint256[] memory arr, int256 left, int256 right) private pure { - int256 i = left; - int256 j = right; - if (i == j) return; - uint256 pivot = arr[uint256(left + (right - left) / 2)]; - while (i <= j) { - while (arr[uint256(i)] < pivot) i++; - while (pivot < arr[uint256(j)]) j--; - if (i <= j) { - (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); - i++; - j--; - } - } - if (left < j) quickSort(arr, left, j); - if (i < right) quickSort(arr, i, right); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol deleted file mode 100644 index 39b95bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadLogTriggerUpkeep.sol +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import "./VerifiableLoadBase.sol"; -import "../automation/interfaces/ILogAutomation.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; - -contract VerifiableLoadLogTriggerUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface, ILogAutomation { - bool public useMercury; - uint8 public logNum; - - /** - * @param _registrar a automation registrar 2.1 address - * @param _useArb if this contract will use arbitrum block number - * @param _useMercury if the log trigger upkeeps will use mercury lookup - */ - constructor( - AutomationRegistrar2_1 _registrar, - bool _useArb, - bool _useMercury - ) VerifiableLoadBase(_registrar, _useArb) { - useMercury = _useMercury; - logNum = 0; - } - - function setLog(uint8 _log) external { - logNum = _log; - } - - function checkLog(Log calldata log, bytes memory checkData) external returns (bool, bytes memory) { - uint256 startGas = gasleft(); - uint256 blockNum = getBlockNumber(); - uint256 uid = abi.decode(checkData, (uint256)); - - bytes32 sig = emittedSig; - if (logNum != 0) { - sig = emittedAgainSig; - } - // filter by event signature - if (log.topics[0] == sig) { - bytes memory t1 = abi.encodePacked(log.topics[1]); // bytes32 to bytes - uint256 upkeepId = abi.decode(t1, (uint256)); - if (upkeepId != uid) { - revert("upkeep ids don't match"); - } - bytes memory t2 = abi.encodePacked(log.topics[2]); - uint256 blockNum = abi.decode(t2, (uint256)); - - bytes memory t3 = abi.encodePacked(log.topics[3]); - address addr = abi.decode(t3, (address)); - - uint256 checkGasToBurn = checkGasToBurns[upkeepId]; - while (startGas - gasleft() + 15000 < checkGasToBurn) { - dummyMap[blockhash(blockNum)] = false; - } - - uint256 timeParam; - if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { - timeParam = blockNum; - } else { - // assume this will be feedIDs for v0.3 - timeParam = block.timestamp; - } - - if (useMercury) { - revert StreamsLookup(feedParamKey, feedsHex, timeParamKey, timeParam, abi.encode(upkeepId, blockNum, addr)); - } - - // if we don't use mercury, create a perform data which resembles the output of checkCallback - bytes[] memory values = new bytes[](feedsHex.length); - bytes memory extraData = abi.encode(upkeepId, blockNum, addr); - return (true, abi.encode(values, extraData)); - } - revert("unexpected event sig"); - } - - function performUpkeep(bytes calldata performData) external { - uint256 startGas = gasleft(); - (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); - (uint256 upkeepId, uint256 logBlockNumber, address addr) = abi.decode(extraData, (uint256, uint256, address)); - - uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; - uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; - uint256 currentBlockNum = getBlockNumber(); - - if (firstPerformBlock == 0) { - firstPerformBlocks[upkeepId] = currentBlockNum; - } else { - uint256 delay = currentBlockNum - logBlockNumber; - uint16 bucket = buckets[upkeepId]; - uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; - if (bucketDelays.length == BUCKET_SIZE) { - bucket++; - buckets[upkeepId] = bucket; - } - bucketedDelays[upkeepId][bucket].push(delay); - delays[upkeepId].push(delay); - } - - uint256 counter = counters[upkeepId] + 1; - counters[upkeepId] = counter; - previousPerformBlocks[upkeepId] = currentBlockNum; - - // for every upkeepTopUpCheckInterval (5), check if the upkeep balance is at least - // minBalanceThresholdMultiplier (20) * min balance. If not, add addLinkAmount (0.2) to the upkeep - // upkeepTopUpCheckInterval, minBalanceThresholdMultiplier, and addLinkAmount are configurable - topUpFund(upkeepId, currentBlockNum); - emit LogEmitted(upkeepId, currentBlockNum, address(this)); - burnPerformGas(upkeepId, startGas, currentBlockNum); - } - - function checkCallback( - bytes[] memory values, - bytes memory extraData - ) external pure override returns (bool, bytes memory) { - bytes memory performData = abi.encode(values, extraData); - return (true, performData); - } - - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (false, new bytes(0)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol deleted file mode 100644 index c74aec1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadStreamsLookupUpkeep.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import "./VerifiableLoadBase.sol"; -import "../automation/interfaces/StreamsLookupCompatibleInterface.sol"; - -contract VerifiableLoadStreamsLookupUpkeep is VerifiableLoadBase, StreamsLookupCompatibleInterface { - constructor(AutomationRegistrar2_1 _registrar, bool _useArb) VerifiableLoadBase(_registrar, _useArb) {} - - function checkCallback( - bytes[] memory values, - bytes memory extraData - ) external pure override returns (bool, bytes memory) { - // do sth about the chainlinkBlob data in values and extraData - bytes memory performData = abi.encode(values, extraData); - return (true, performData); - } - - function checkErrorHandler( - uint256 errCode, - bytes memory extraData - ) external view override returns (bool upkeepNeeded, bytes memory performData) { - // dummy function with default values - return (false, new bytes(0)); - } - - function checkUpkeep(bytes calldata checkData) external returns (bool, bytes memory) { - uint256 startGas = gasleft(); - uint256 upkeepId = abi.decode(checkData, (uint256)); - - uint256 performDataSize = performDataSizes[upkeepId]; - uint256 checkGasToBurn = checkGasToBurns[upkeepId]; - bytes memory pData = abi.encode(upkeepId, new bytes(performDataSize)); - uint256 blockNum = getBlockNumber(); - bool needed = eligible(upkeepId); - while (startGas - gasleft() + 10000 < checkGasToBurn) { - // 10K margin over gas to burn - // Hard coded check gas to burn - dummyMap[blockhash(blockNum)] = false; // arbitrary storage writes - } - if (!needed) { - return (false, pData); - } - - uint256 timeParam; - if (keccak256(abi.encodePacked(feedParamKey)) == keccak256(abi.encodePacked("feedIdHex"))) { - timeParam = blockNum; - } else { - // assume this will be feedIDs for v0.3 - timeParam = block.timestamp; - } - - revert StreamsLookup(feedParamKey, feedsHex, timeParamKey, timeParam, abi.encode(upkeepId)); - } - - function performUpkeep(bytes calldata performData) external { - uint256 startGas = gasleft(); - (bytes[] memory values, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); - uint256 upkeepId = abi.decode(extraData, (uint256)); - uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; - uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; - uint256 blockNum = getBlockNumber(); - - if (firstPerformBlock == 0) { - firstPerformBlocks[upkeepId] = blockNum; - } else { - uint256 delay = blockNum - previousPerformBlock - intervals[upkeepId]; - uint16 bucket = buckets[upkeepId]; - uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; - if (bucketDelays.length == BUCKET_SIZE) { - bucket++; - buckets[upkeepId] = bucket; - } - bucketedDelays[upkeepId][bucket].push(delay); - delays[upkeepId].push(delay); - } - - uint256 counter = counters[upkeepId] + 1; - counters[upkeepId] = counter; - previousPerformBlocks[upkeepId] = blockNum; - - topUpFund(upkeepId, blockNum); - burnPerformGas(upkeepId, startGas, blockNum); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol deleted file mode 100644 index bab75e9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/tests/VerifiableLoadUpkeep.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.16; - -import "./VerifiableLoadBase.sol"; - -contract VerifiableLoadUpkeep is VerifiableLoadBase { - constructor(AutomationRegistrar2_1 _registrar, bool _useArb) VerifiableLoadBase(_registrar, _useArb) {} - - function checkUpkeep(bytes calldata checkData) external returns (bool, bytes memory) { - uint256 startGas = gasleft(); - uint256 upkeepId = abi.decode(checkData, (uint256)); - - uint256 performDataSize = performDataSizes[upkeepId]; - uint256 checkGasToBurn = checkGasToBurns[upkeepId]; - bytes memory pData = abi.encode(upkeepId, new bytes(performDataSize)); - uint256 blockNum = getBlockNumber(); - bool needed = eligible(upkeepId); - while (startGas - gasleft() + 10000 < checkGasToBurn) { - dummyMap[blockhash(blockNum)] = false; - blockNum--; - } - return (needed, pData); - } - - function performUpkeep(bytes calldata performData) external { - uint256 startGas = gasleft(); - (uint256 upkeepId, ) = abi.decode(performData, (uint256, bytes)); - uint256 firstPerformBlock = firstPerformBlocks[upkeepId]; - uint256 previousPerformBlock = previousPerformBlocks[upkeepId]; - uint256 blockNum = getBlockNumber(); - if (firstPerformBlock == 0) { - firstPerformBlocks[upkeepId] = blockNum; - } else { - uint256 delay = blockNum - previousPerformBlock - intervals[upkeepId]; - uint16 bucket = buckets[upkeepId]; - uint256[] memory bucketDelays = bucketedDelays[upkeepId][bucket]; - if (bucketDelays.length == BUCKET_SIZE) { - bucket++; - buckets[upkeepId] = bucket; - } - bucketedDelays[upkeepId][bucket].push(delay); - delays[upkeepId].push(delay); - } - - uint256 counter = counters[upkeepId] + 1; - counters[upkeepId] = counter; - previousPerformBlocks[upkeepId] = blockNum; - - topUpFund(upkeepId, blockNum); - burnPerformGas(upkeepId, startGas, blockNum); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol deleted file mode 100644 index 932d350..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol"; -import {SCALibrary} from "./SCALibrary.sol"; -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; -import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; - -/// @dev LINK token paymaster implementation. -/// TODO: more documentation. -contract Paymaster is IPaymaster, ConfirmedOwner { - error OnlyCallableFromLink(); - error InvalidCalldata(); - error Unauthorized(address sender, address validator); - error UserOperationAlreadyTried(bytes32 userOpHash); - error InsufficientFunds(uint256 juelsNeeded, uint256 subscriptionBalance); - - LinkTokenInterface public immutable i_linkToken; - AggregatorV3Interface public immutable i_linkEthFeed; - address public immutable i_entryPoint; - - struct Config { - uint32 stalenessSeconds; - int256 fallbackWeiPerUnitLink; - } - Config public s_config; - - mapping(bytes32 => bool) internal s_userOpHashMapping; - mapping(address => uint256) internal s_subscriptions; - - constructor( - LinkTokenInterface linkToken, - AggregatorV3Interface linkEthFeed, - address entryPoint - ) ConfirmedOwner(msg.sender) { - i_linkToken = linkToken; - i_linkEthFeed = linkEthFeed; - i_entryPoint = entryPoint; - } - - function setConfig(uint32 stalenessSeconds, int256 fallbackWeiPerUnitLink) external onlyOwner { - s_config = Config({stalenessSeconds: stalenessSeconds, fallbackWeiPerUnitLink: fallbackWeiPerUnitLink}); - } - - function onTokenTransfer(address /* _sender */, uint256 _amount, bytes calldata _data) external { - if (msg.sender != address(i_linkToken)) { - revert OnlyCallableFromLink(); - } - if (_data.length != 32) { - revert InvalidCalldata(); - } - - address subscription = abi.decode(_data, (address)); - s_subscriptions[subscription] += _amount; - } - - function validatePaymasterUserOp( - UserOperation calldata userOp, - bytes32 userOpHash, - uint256 maxCost - ) external returns (bytes memory context, uint256 validationData) { - if (msg.sender != i_entryPoint) { - revert Unauthorized(msg.sender, i_entryPoint); - } - if (s_userOpHashMapping[userOpHash]) { - revert UserOperationAlreadyTried(userOpHash); - } - - uint256 extraCostJuels = _handleExtraCostJuels(userOp); - uint256 costJuels = _getCostJuels(maxCost) + extraCostJuels; - if (s_subscriptions[userOp.sender] < costJuels) { - revert InsufficientFunds(costJuels, s_subscriptions[userOp.sender]); - } - - s_userOpHashMapping[userOpHash] = true; - return (abi.encode(userOp.sender, extraCostJuels), _packValidationData(false, 0, 0)); // success - } - - /// @dev Calculates any extra LINK cost for the user operation, based on the funding type passed to the - /// @dev paymaster. Handles funding the LINK token funding described in the user operation. - /// TODO: add logic for subscription top-up. - function _handleExtraCostJuels(UserOperation calldata userOp) internal returns (uint256 extraCost) { - if (userOp.paymasterAndData.length == 20) { - return 0; // no extra data, stop here - } - - uint8 paymentType = uint8(userOp.paymasterAndData[20]); - - // For direct funding, use top-up logic. - if (paymentType == uint8(SCALibrary.LinkPaymentType.DIRECT_FUNDING)) { - SCALibrary.DirectFundingData memory directFundingData = abi.decode( - userOp.paymasterAndData[21:], - (SCALibrary.DirectFundingData) - ); - if ( - directFundingData.topupThreshold != 0 && - i_linkToken.balanceOf(directFundingData.recipient) < directFundingData.topupThreshold - ) { - i_linkToken.transfer(directFundingData.recipient, directFundingData.topupAmount); - extraCost = directFundingData.topupAmount; - } - } - return extraCost; - } - - /// @dev Deducts user subscription balance after execution. - function postOp(PostOpMode /* mode */, bytes calldata context, uint256 actualGasCost) external { - if (msg.sender != i_entryPoint) { - revert Unauthorized(msg.sender, i_entryPoint); - } - (address sender, uint256 extraCostJuels) = abi.decode(context, (address, uint256)); - s_subscriptions[sender] -= (_getCostJuels(actualGasCost) + extraCostJuels); - } - - function _getCostJuels(uint256 costWei) internal view returns (uint256 costJuels) { - costJuels = (1e18 * costWei) / uint256(_getFeedData()); - return costJuels; - } - - function _getFeedData() internal view returns (int256) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = i_linkEthFeed.latestRoundData(); - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_config.fallbackWeiPerUnitLink; - } - return weiPerUnitLink; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol deleted file mode 100644 index 589c55f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {IAccount} from "../../../vendor/entrypoint/interfaces/IAccount.sol"; -import {SCALibrary} from "./SCALibrary.sol"; -import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; -import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; - -/// @dev Smart Contract Account, a contract deployed for a single user and that allows -/// @dev them to invoke meta-transactions. -/// TODO: Consider making the Smart Contract Account upgradeable. -contract SCA is IAccount { - uint256 public s_nonce; - address public immutable i_owner; - address public immutable i_entryPoint; - - error IncorrectNonce(uint256 currentNonce, uint256 nonceGiven); - error NotAuthorized(address sender); - error BadFormatOrOOG(); - error TransactionExpired(uint256 deadline, uint256 currentTimestamp); - error InvalidSignature(bytes32 operationHash, address owner); - - // Assign the owner of this contract upon deployment. - constructor(address owner, address entryPoint) { - i_owner = owner; - i_entryPoint = entryPoint; - } - - /// @dev Validates the user operation via a signature check. - /// TODO: Utilize a "validAfter" for a tx to be only valid _after_ a certain time. - function validateUserOp( - UserOperation calldata userOp, - bytes32 userOpHash, - uint256 /* missingAccountFunds - unused in favor of paymaster */ - ) external returns (uint256 validationData) { - if (userOp.nonce != s_nonce) { - // Revert for non-signature errors. - revert IncorrectNonce(s_nonce, userOp.nonce); - } - - // Verify signature on hash. - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, address(this)); - bytes memory signature = userOp.signature; - if (SCALibrary._recoverSignature(signature, fullHash) != i_owner) { - return _packValidationData(true, 0, 0); // signature error - } - s_nonce++; - - // Unpack deadline, return successful signature. - (, , uint48 deadline, ) = abi.decode(userOp.callData[4:], (address, uint256, uint48, bytes)); - return _packValidationData(false, deadline, 0); - } - - /// @dev Execute a transaction on behalf of the owner. This function can only - /// @dev be called by the EntryPoint contract, and assumes that `validateUserOp` has succeeded. - function executeTransactionFromEntryPoint(address to, uint256 value, uint48 deadline, bytes calldata data) external { - if (msg.sender != i_entryPoint) { - revert NotAuthorized(msg.sender); - } - if (deadline != 0 && block.timestamp > deadline) { - revert TransactionExpired(deadline, block.timestamp); - } - - // Execute transaction. Bubble up an error if found. - (bool success, bytes memory returnData) = to.call{value: value}(data); - if (!success) { - if (returnData.length == 0) revert BadFormatOrOOG(); - assembly { - revert(add(32, returnData), mload(returnData)) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol deleted file mode 100644 index 095a342..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -library SCALibrary { - // keccak256("EIP712Domain(uint256 chainId, address verifyingContract)"); - bytes32 internal constant DOMAIN_SEPARATOR = hex"1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea61"; - - // keccak256("executeTransactionFromEntryPoint(address to, uint256 value, bytes calldata data)"); - bytes32 internal constant TYPEHASH = hex"4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0"; - - enum LinkPaymentType { - DIRECT_FUNDING, - SUBSCRIPTION // TODO: implement - } - - struct DirectFundingData { - address recipient; // recipient of the top-up - uint256 topupThreshold; // set to zero to disable auto-topup - uint256 topupAmount; - } - - function _getUserOpFullHash(bytes32 userOpHash, address scaAddress) internal view returns (bytes32 fullHash) { - bytes32 hashOfEncoding = keccak256(abi.encode(SCALibrary.TYPEHASH, userOpHash)); - fullHash = keccak256( - abi.encodePacked( - bytes1(0x19), - bytes1(0x01), - SCALibrary.DOMAIN_SEPARATOR, - block.chainid, - scaAddress, - hashOfEncoding - ) - ); - return fullHash; - } - - function _recoverSignature(bytes memory signature, bytes32 fullHash) internal pure returns (address) { - bytes32 r; - bytes32 s; - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - } - uint8 v = uint8(signature[64]); - - return ecrecover(fullHash, v + 27, r, s); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol deleted file mode 100644 index f27c8e1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -contract SmartContractAccountFactory { - event ContractCreated(address scaAddress); - - error DeploymentFailed(); - - /// @dev Use create2 to deploy a new Smart Contract Account. - /// @dev See EIP-1014 for more on CREATE2. - /// TODO: Return the address of the Smart Contract Account even if it is already - /// deployed. - function deploySmartContractAccount( - bytes32 abiEncodedOwnerAddress, - bytes memory initCode - ) external payable returns (address scaAddress) { - assembly { - scaAddress := create2( - 0, // value - left at zero here - add(0x20, initCode), // initialization bytecode - mload(initCode), // length of initialization bytecode - abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses - ) - } - if (scaAddress == address(0)) { - revert DeploymentFailed(); - } - - emit ContractCreated(scaAddress); - - return scaAddress; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol deleted file mode 100644 index 5851c86..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/// @dev Ownerless greeter contract. -contract Greeter { - string private s_greeting; - - function setGreeting(string memory greeting) external { - s_greeting = greeting; - } - - function getGreeting() external view returns (string memory) { - return s_greeting; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol deleted file mode 100644 index b080484..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {SCA} from "../ERC-4337/SCA.sol"; -import {SmartContractAccountFactory} from "../ERC-4337/SmartContractAccountFactory.sol"; -import {SCALibrary} from "../ERC-4337/SCALibrary.sol"; - -library SmartContractAccountHelper { - bytes internal constant INITIALIZE_CODE = type(SCA).creationCode; - - function getFullEndTxEncoding( - address endContract, - uint256 value, - uint256 deadline, - bytes memory data - ) public view returns (bytes memory encoding) { - encoding = bytes.concat( - SCA.executeTransactionFromEntryPoint.selector, - abi.encode(endContract, value, block.timestamp + deadline, data) - ); - return encoding; - } - - function getFullHashForSigning(bytes32 userOpHash, address scaAddress) public view returns (bytes32) { - return SCALibrary._getUserOpFullHash(userOpHash, scaAddress); - } - - function getSCAInitCodeWithConstructor( - address owner, - address entryPoint - ) public pure returns (bytes memory initCode) { - initCode = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - return initCode; - } - - function getInitCode( - address factory, - address owner, - address entryPoint - ) external pure returns (bytes memory initCode) { - bytes32 salt = bytes32(uint256(uint160(owner)) << 96); - bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - initCode = bytes.concat( - bytes20(address(factory)), - abi.encodeWithSelector( - SmartContractAccountFactory.deploySmartContractAccount.selector, - salt, - initializeCodeWithConstructor - ) - ); - return initCode; - } - - /// @dev Computes the smart contract address that results from a CREATE2 operation, per EIP-1014. - function calculateSmartContractAccountAddress( - address owner, - address entryPoint, - address factory - ) external pure returns (address) { - bytes32 salt = bytes32(uint256(uint160(owner)) << 96); - bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); - bytes32 initializeCodeHash = keccak256(initializeCodeWithConstructor); - return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(factory), salt, initializeCodeHash))))); - } - - function getAbiEncodedDirectRequestData( - address recipient, - uint256 topupThreshold, - uint256 topupAmount - ) external pure returns (bytes memory) { - SCALibrary.DirectFundingData memory data = SCALibrary.DirectFundingData({ - recipient: recipient, - topupThreshold: topupThreshold, - topupAmount: topupAmount - }); - return abi.encode(data); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol deleted file mode 100644 index 4da698d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/BaseTest.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; - -contract BaseTest is Test { - bool private s_baseTestInitialized; - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - // Set msg.sender to OWNER until changePrank or stopPrank is called - vm.startPrank(OWNER); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol deleted file mode 100644 index fdfe190..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol +++ /dev/null @@ -1,365 +0,0 @@ -pragma solidity 0.8.19; - -import "../../shared/interfaces/LinkTokenInterface.sol"; - -import "./BaseTest.t.sol"; -import "../dev/ERC-4337/SmartContractAccountFactory.sol"; -import "../dev/testhelpers/SmartContractAccountHelper.sol"; -import "../dev/ERC-4337/SCA.sol"; -import "../dev/testhelpers/Greeter.sol"; -import "../dev/ERC-4337/Paymaster.sol"; -import "../../transmission/dev/ERC-4337/SCALibrary.sol"; -import "../../mocks/MockLinkToken.sol"; -import "../../tests/MockV3Aggregator.sol"; -import "../../vrf/mocks/VRFCoordinatorMock.sol"; -import "../../vrf/testhelpers/VRFConsumer.sol"; - -import "../../vendor/entrypoint/interfaces/UserOperation.sol"; -import "../../vendor/entrypoint/core/EntryPoint.sol"; -import "../../vendor/entrypoint/interfaces/IEntryPoint.sol"; - -/*--------------------------------------------------------------------------------------------------------------------+ -| EIP 712 + 1014 + 4337 | -| ________________ | -| This implementation allows for meta-transactions to be signed by end-users and posted on-chain by executors. It | -| utilizes the following components: | -| - EIP-712: The method by which meta-transactions are authorized. | -| - EIP-1014: The method by which the Smart Contract Account is generated. | -| - EIP-4337: The method by which meta-transactions are executed. | -| | -| The below tests illustrate end-user flows for interacting with this meta-transaction system. For users with | -| existing Smart Contract Accounts (SCAs), they simply sign off on the operation, after which the executor | -| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then execute the transaction | -| as the SCA. For users without existing SCAs, EIP-1014 ensures that the address of an SCA can be known in advance, | -| so users can sign-off on transactions that will be executed by a not-yet-deployed SCA. The EntryPoint contract | -| takes advantage of this functionality and allows for the SCA to be created in the same user operation that invokes | -| it, and the end-user signs off on this creation-and-execution flow. After the initial creation-and-execution, the | -| SCA is reused for future transactions. | -| | -| End-Dapps/protocols do not need to be EIP-2771-compliant or accommodate any other kind of transaction standard. | -| They can be interacted with out-of-the-box through the SCA, which acts in place of the user's EOA as their | -| immutable identity. | -| | --+---------------------------------------------------------------------------------------------------------------------*/ - -contract EIP_712_1014_4337 is BaseTest { - event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); - - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - address internal ENTRY_POINT; - - Greeter greeter; - EntryPoint entryPoint; - MockV3Aggregator linkEthFeed; - - // Randomly generated private/public key pair. - uint256 END_USER_PKEY = uint256(bytes32(hex"99d518dbfea4b4ec301390f7e26d53d711fa1ca0c1a6e4cbed89617d4c578a8e")); - address END_USER = 0xB6708257D4E1bf0b8C144793fc2Ff3193C737ed1; - - function setUp() public override { - BaseTest.setUp(); - // Fund user accounts; - vm.deal(END_USER, 10_000 ether); - vm.deal(LINK_WHALE, 10_000 ether); - - // Impersonate a LINK whale. - changePrank(LINK_WHALE); - - // Create simple greeter contract. - greeter = new Greeter(); - assertEq("", greeter.getGreeting()); - - // Create entry point contract. - entryPoint = new EntryPoint(); - ENTRY_POINT = address(entryPoint); - - // Deploy link/eth feed. - linkEthFeed = new MockV3Aggregator(18, 5000000000000000); // .005 ETH - } - - /// @dev Test case for user that already has a Smart Contract Account. - /// @dev EntryPoint.sol should use the existing SCA to execute the meta transaction. - function testEIP712EIP4337WithExistingSmartContractAccount() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Deploy the end-contract. - bytes32 salt = bytes32(uint256(uint160(END_USER)) << 96); - bytes memory fullInitializeCode = SmartContractAccountHelper.getSCAInitCodeWithConstructor(END_USER, ENTRY_POINT); - factory.deploySmartContractAccount(salt, fullInitializeCode); - changePrank(END_USER); - - // Ensure a correct deployment and a functioning end-contract. - uint256 contractCodeSize; - assembly { - contractCodeSize := extcodesize(toDeployAddress) - } - assertTrue(contractCodeSize > 0); - assertEq(END_USER, SCA(toDeployAddress).i_owner()); - - // Create the calldata for a setGreeting call. - string memory greeting = "hi"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); // abi.encodeWithSelector equivalent - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: "", - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: "", - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(toDeployAddress); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("hi", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - /// @dev Test case for fresh user, EntryPoint.sol should generate a - /// @dev Smart Contract Account for them and execute the meta transaction. - function testEIP712EIP4337AndCreateSmartContractAccount() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a setGreeting call. - string memory greeting = "bye"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: "", - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(toDeployAddress); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("bye", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - assertEq(SCA(toDeployAddress).i_owner(), END_USER); - } - - /// @dev Test case for a user executing a setGreeting with a LINK token paymaster. - function testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a setGreeting call. - string memory greeting = "good day"; - bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(greeter), - uint256(0), - 0, - encodedGreetingCall - ); - - // Create Link token, and deposit into paymaster. - MockLinkToken linkToken = new MockLinkToken(); - Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); - linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); - - // Construct the user opeartion. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 1_000_000, - verificationGasLimit: 1_500_000, - preVerificationGas: 10_000, - maxFeePerGas: 100, - maxPriorityFeePerGas: 200, - paymasterAndData: abi.encodePacked(address(paymaster)), - signature: "" - }); - - // Sign user operation. - bytes32 userOpHash = entryPoint.getUserOpHash(op); - bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); - op.signature = abi.encodePacked(r, s, v - 27); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(address(paymaster)); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - entryPoint.handleOps(operations, payable(END_USER)); - - // Assert that the greeting was set. - assertEq("good day", Greeter(greeter).getGreeting()); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - /// @dev Test case for a VRF Request via LINK token paymaster and an SCA. - function testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() public { - // Pre-calculate user smart contract account address. - SmartContractAccountFactory factory = new SmartContractAccountFactory(); - address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( - END_USER, - ENTRY_POINT, - address(factory) - ); - - // Construct initCode byte array. - bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); - - // Create the calldata for a VRF request. - bytes32 keyhash = bytes32(uint256(123)); - uint256 fee = 1 ether; - bytes memory encodedVRFRequestCallData = bytes.concat( - VRFConsumer.doRequestRandomness.selector, - abi.encode(keyhash, fee) - ); - - // Create the VRF Contracts - MockLinkToken linkToken = new MockLinkToken(); - VRFCoordinatorMock vrfCoordinator = new VRFCoordinatorMock(address(linkToken)); - VRFConsumer vrfConsumer = new VRFConsumer(address(vrfCoordinator), address(linkToken)); - - // Produce the final full end-tx encoding, to be used as calldata in the user operation. - bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( - address(vrfConsumer), // end-contract - uint256(0), // value - 0, // timeout (seconds) - encodedVRFRequestCallData - ); - - // Create Link token, and deposit into paymaster. - Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); - linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); - - // Construct direct funding data. - SCALibrary.DirectFundingData memory directFundingData = SCALibrary.DirectFundingData({ - recipient: address(vrfConsumer), - topupThreshold: 1, - topupAmount: 10 ether - }); - - // Construct the user operation. - UserOperation memory op = UserOperation({ - sender: toDeployAddress, - nonce: 0, - initCode: fullInitializeCode, - callData: fullEncoding, - callGasLimit: 200_000, - verificationGasLimit: 1_000_000, - preVerificationGas: 10_000, - maxFeePerGas: 10, - maxPriorityFeePerGas: 10, - paymasterAndData: abi.encodePacked(address(paymaster), uint8(0), abi.encode(directFundingData)), - signature: "" - }); - - // Sign user operation. - bytes32 fullHash = SCALibrary._getUserOpFullHash(entryPoint.getUserOpHash(op), toDeployAddress); - op.signature = getSignature(fullHash); - - // Deposit funds for the transaction. - entryPoint.depositTo{value: 10 ether}(address(paymaster)); - - // Assert correct log is emitted for the end-contract vrf request. - vm.expectEmit(true, true, true, true); - emit RandomnessRequest( - address(vrfConsumer), - keyhash, - 0, // seed - we use a zero seed - fee - ); - - // Execute the user operation. - UserOperation[] memory operations = new UserOperation[](1); - operations[0] = op; - - // Execute user operation and ensure correct outcome. - entryPoint.handleOps(operations, payable(END_USER)); - assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); - } - - function getSignature(bytes32 h) internal view returns (bytes memory) { - (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, h); - return abi.encodePacked(r, s, v - 27); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol deleted file mode 100644 index 0517df2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE -// SPDX-License-Identifier: BUSL-1.1 - -pragma solidity >=0.4.21 <0.9.0; - -/// @title Provides insight into the cost of using the chain. -/// @notice These methods have been adjusted to account for Nitro's heavy use of calldata compression. -/// Of note to end-users, we no longer make a distinction between non-zero and zero-valued calldata bytes. -/// Precompiled contract that exists in every Arbitrum chain at 0x000000000000000000000000000000000000006c. -interface ArbGasInfo { - /// @notice Get gas prices for a provided aggregator - /// @return return gas prices in wei - /// ( - /// per L2 tx, - /// per L1 calldata byte - /// per storage allocation, - /// per ArbGas base, - /// per ArbGas congestion, - /// per ArbGas total - /// ) - function getPricesInWeiWithAggregator(address aggregator) - external - view - returns ( - uint256, - uint256, - uint256, - uint256, - uint256, - uint256 - ); - - /// @notice Get gas prices. Uses the caller's preferred aggregator, or the default if the caller doesn't have a preferred one. - /// @return return gas prices in wei - /// ( - /// per L2 tx, - /// per L1 calldata byte - /// per storage allocation, - /// per ArbGas base, - /// per ArbGas congestion, - /// per ArbGas total - /// ) - function getPricesInWei() - external - view - returns ( - uint256, - uint256, - uint256, - uint256, - uint256, - uint256 - ); - - /// @notice Get prices in ArbGas for the supplied aggregator - /// @return (per L2 tx, per L1 calldata byte, per storage allocation) - function getPricesInArbGasWithAggregator(address aggregator) - external - view - returns ( - uint256, - uint256, - uint256 - ); - - /// @notice Get prices in ArbGas. Assumes the callers preferred validator, or the default if caller doesn't have a preferred one. - /// @return (per L2 tx, per L1 calldata byte, per storage allocation) - function getPricesInArbGas() - external - view - returns ( - uint256, - uint256, - uint256 - ); - - /// @notice Get the gas accounting parameters. `gasPoolMax` is always zero, as the exponential pricing model has no such notion. - /// @return (speedLimitPerSecond, gasPoolMax, maxTxGasLimit) - function getGasAccountingParams() - external - view - returns ( - uint256, - uint256, - uint256 - ); - - /// @notice Get the minimum gas price needed for a tx to succeed - function getMinimumGasPrice() external view returns (uint256); - - /// @notice Get ArbOS's estimate of the L1 basefee in wei - function getL1BaseFeeEstimate() external view returns (uint256); - - /// @notice Get how slowly ArbOS updates its estimate of the L1 basefee - function getL1BaseFeeEstimateInertia() external view returns (uint64); - - /// @notice Get the L1 pricer reward rate, in wei per unit - /// Available in ArbOS version 11 - function getL1RewardRate() external view returns (uint64); - - /// @notice Get the L1 pricer reward recipient - /// Available in ArbOS version 11 - function getL1RewardRecipient() external view returns (address); - - /// @notice Deprecated -- Same as getL1BaseFeeEstimate() - function getL1GasPriceEstimate() external view returns (uint256); - - /// @notice Get L1 gas fees paid by the current transaction - function getCurrentTxL1GasFees() external view returns (uint256); - - /// @notice Get the backlogged amount of gas burnt in excess of the speed limit - function getGasBacklog() external view returns (uint64); - - /// @notice Get how slowly ArbOS updates the L2 basefee in response to backlogged gas - function getPricingInertia() external view returns (uint64); - - /// @notice Get the forgivable amount of backlogged gas ArbOS will ignore when raising the basefee - function getGasBacklogTolerance() external view returns (uint64); - - /// @notice Returns the surplus of funds for L1 batch posting payments (may be negative). - function getL1PricingSurplus() external view returns (int256); - - /// @notice Returns the base charge (in L1 gas) attributed to each data batch in the calldata pricer - function getPerBatchGasCharge() external view returns (int64); - - /// @notice Returns the cost amortization cap in basis points - function getAmortizedCostCapBips() external view returns (uint64); - - /// @notice Returns the available funds from L1 fees - function getL1FeesAvailable() external view returns (uint256); - - /// @notice Returns the equilibration units parameter for L1 price adjustment algorithm - /// Available in ArbOS version 20 - function getL1PricingEquilibrationUnits() external view returns (uint256); - - /// @notice Returns the last time the L1 calldata pricer was updated. - /// Available in ArbOS version 20 - function getLastL1PricingUpdateTime() external view returns (uint64); - - /// @notice Returns the amount of L1 calldata payments due for rewards (per the L1 reward rate) - /// Available in ArbOS version 20 - function getL1PricingFundsDueForRewards() external view returns (uint256); - - /// @notice Returns the amount of L1 calldata posted since the last update. - /// Available in ArbOS version 20 - function getL1PricingUnitsSinceUpdate() external view returns (uint64); - - /// @notice Returns the L1 pricing surplus as of the last update (may be negative). - /// Available in ArbOS version 20 - function getLastL1PricingSurplus() external view returns (int256); -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol deleted file mode 100644 index fb48f36..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// SPDX-License-Identifier: BUSL-1.1 - -pragma solidity >=0.4.21 <0.9.0; - -/** - * @title System level functionality - * @notice For use by contracts to interact with core L2-specific functionality. - * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. - */ -interface ArbSys { - /** - * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) - * @return block number as int - */ - function arbBlockNumber() external view returns (uint256); - - /** - * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum) - * @return block hash - */ - function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32); - - /** - * @notice Gets the rollup's unique chain identifier - * @return Chain identifier as int - */ - function arbChainID() external view returns (uint256); - - /** - * @notice Get internal version number identifying an ArbOS build - * @return version number as int - */ - function arbOSVersion() external view returns (uint256); - - /** - * @notice Returns 0 since Nitro has no concept of storage gas - * @return uint 0 - */ - function getStorageGasAvailable() external view returns (uint256); - - /** - * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract) - * @dev this call has been deprecated and may be removed in a future release - * @return true if current execution frame is not a call by another L2 contract - */ - function isTopLevelCall() external view returns (bool); - - /** - * @notice map L1 sender contract address to its L2 alias - * @param sender sender address - * @param unused argument no longer used - * @return aliased sender address - */ - function mapL1SenderContractAddressToL2Alias(address sender, address unused) - external - pure - returns (address); - - /** - * @notice check if the caller (of this caller of this) is an aliased L1 contract address - * @return true iff the caller's address is an alias for an L1 contract address - */ - function wasMyCallersAddressAliased() external view returns (bool); - - /** - * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing - * @return address of the caller's caller, without applying L1 contract address aliasing - */ - function myCallersAddressWithoutAliasing() external view returns (address); - - /** - * @notice Send given amount of Eth to dest from sender. - * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data. - * @param destination recipient address on L1 - * @return unique identifier for this L2-to-L1 transaction. - */ - function withdrawEth(address destination) - external - payable - returns (uint256); - - /** - * @notice Send a transaction to L1 - * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data - * to a contract address without any code (as enforced by the Bridge contract). - * @param destination recipient address on L1 - * @param data (optional) calldata for L1 contract call - * @return a unique identifier for this L2-to-L1 transaction. - */ - function sendTxToL1(address destination, bytes calldata data) - external - payable - returns (uint256); - - /** - * @notice Get send Merkle tree state - * @return size number of sends in the history - * @return root root hash of the send history - * @return partials hashes of partial subtrees in the send history tree - */ - function sendMerkleTreeState() - external - view - returns ( - uint256 size, - bytes32 root, - bytes32[] memory partials - ); - - /** - * @notice creates a send txn from L2 to L1 - * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf - */ - event L2ToL1Tx( - address caller, - address indexed destination, - uint256 indexed hash, - uint256 indexed position, - uint256 arbBlockNum, - uint256 ethBlockNum, - uint256 timestamp, - uint256 callvalue, - bytes data - ); - - /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade - event L2ToL1Transaction( - address caller, - address indexed destination, - uint256 indexed uniqueId, - uint256 indexed batchNumber, - uint256 indexInBatch, - uint256 arbBlockNum, - uint256 ethBlockNum, - uint256 timestamp, - uint256 callvalue, - bytes data - ); - - /** - * @notice logs a merkle branch for proof synthesis - * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event - * @param hash the merkle hash - * @param position = (level << 192) + leaf - */ - event SendMerkleUpdate( - uint256 indexed reserved, - bytes32 indexed hash, - uint256 indexed position - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol deleted file mode 100644 index a57b4dd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@ensdomains/buffer/v0.1.0/Buffer.sol +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -pragma solidity ^0.8.4; - -/** -* @dev A library for working with mutable byte buffers in Solidity. -* -* Byte buffers are mutable and expandable, and provide a variety of primitives -* for appending to them. At any time you can fetch a bytes object containing the -* current contents of the buffer. The bytes object should not be stored between -* operations, as it may change due to resizing of the buffer. -*/ -library Buffer { - /** - * @dev Represents a mutable buffer. Buffers have a current value (buf) and - * a capacity. The capacity may be longer than the current value, in - * which case it can be extended without the need to allocate more memory. - */ - struct buffer { - bytes buf; - uint capacity; - } - - /** - * @dev Initializes a buffer with an initial capacity. - * @param buf The buffer to initialize. - * @param capacity The number of bytes of space to allocate the buffer. - * @return The buffer, for chaining. - */ - function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { - if (capacity % 32 != 0) { - capacity += 32 - (capacity % 32); - } - // Allocate space for the buffer data - buf.capacity = capacity; - assembly { - let ptr := mload(0x40) - mstore(buf, ptr) - mstore(ptr, 0) - let fpm := add(32, add(ptr, capacity)) - if lt(fpm, ptr) { - revert(0, 0) - } - mstore(0x40, fpm) - } - return buf; - } - - /** - * @dev Initializes a new buffer from an existing bytes object. - * Changes to the buffer may mutate the original value. - * @param b The bytes object to initialize the buffer with. - * @return A new buffer. - */ - function fromBytes(bytes memory b) internal pure returns(buffer memory) { - buffer memory buf; - buf.buf = b; - buf.capacity = b.length; - return buf; - } - - function resize(buffer memory buf, uint capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); - } - - /** - * @dev Sets buffer length to 0. - * @param buf The buffer to truncate. - * @return The original buffer, for chaining.. - */ - function truncate(buffer memory buf) internal pure returns (buffer memory) { - assembly { - let bufptr := mload(buf) - mstore(bufptr, 0) - } - return buf; - } - - /** - * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data, uint len) internal pure returns(buffer memory) { - require(len <= data.length); - - uint off = buf.buf.length; - uint newCapacity = off + len; - if (newCapacity > buf.capacity) { - resize(buf, newCapacity * 2); - } - - uint dest; - uint src; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + offset + sizeof(buffer length) - dest := add(add(bufptr, 32), off) - // Update buffer length if we're extending it - if gt(newCapacity, buflen) { - mstore(bufptr, newCapacity) - } - src := add(data, 32) - } - - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - unchecked { - uint mask = (256 ** (32 - len)) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - } - - return buf; - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { - return append(buf, data, data.length); - } - - /** - * @dev Appends a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { - uint off = buf.buf.length; - uint offPlusOne = off + 1; - if (off >= buf.capacity) { - resize(buf, offPlusOne * 2); - } - - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + off - let dest := add(add(bufptr, off), 32) - mstore8(dest, data) - // Update buffer length if we extended it - if gt(offPlusOne, mload(bufptr)) { - mstore(bufptr, offPlusOne) - } - } - - return buf; - } - - /** - * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to write (left-aligned). - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes32 data, uint len) private pure returns(buffer memory) { - uint off = buf.buf.length; - uint newCapacity = len + off; - if (newCapacity > buf.capacity) { - resize(buf, newCapacity * 2); - } - - unchecked { - uint mask = (256 ** len) - 1; - // Right-align data - data = data >> (8 * (32 - len)); - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + newCapacity - let dest := add(bufptr, newCapacity) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(newCapacity, mload(bufptr)) { - mstore(bufptr, newCapacity) - } - } - } - return buf; - } - - /** - * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chhaining. - */ - function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { - return append(buf, bytes32(data), 20); - } - - /** - * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { - return append(buf, data, 32); - } - - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to write (right-aligned). - * @return The original buffer. - */ - function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { - uint off = buf.buf.length; - uint newCapacity = len + off; - if (newCapacity > buf.capacity) { - resize(buf, newCapacity * 2); - } - - uint mask = (256 ** len) - 1; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + newCapacity - let dest := add(bufptr, newCapacity) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(newCapacity, mload(bufptr)) { - mstore(bufptr, newCapacity) - } - } - return buf; - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol deleted file mode 100644 index aebc1f7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -import { ISemver } from "../universal/ISemver.sol"; -import { Predeploys } from "../libraries/Predeploys.sol"; -import { L1Block } from "./L1Block.sol"; - -/// @custom:proxied -/// @custom:predeploy 0x420000000000000000000000000000000000000F -/// @title GasPriceOracle -/// @notice This contract maintains the variables responsible for computing the L1 portion of the -/// total fee charged on L2. Before Bedrock, this contract held variables in state that were -/// read during the state transition function to compute the L1 portion of the transaction -/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has -/// the values used to compute the L1 portion of the fee in its state. -/// -/// The contract exposes an API that is useful for knowing how large the L1 portion of the -/// transaction fee will be. The following events were deprecated with Bedrock: -/// - event OverheadUpdated(uint256 overhead); -/// - event ScalarUpdated(uint256 scalar); -/// - event DecimalsUpdated(uint256 decimals); -contract GasPriceOracle is ISemver { - /// @notice Number of decimals used in the scalar. - uint256 public constant DECIMALS = 6; - - /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; - - /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input - /// transaction, the current L1 base fee, and the various dynamic parameters. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function getL1Fee(bytes memory _data) external view returns (uint256) { - uint256 l1GasUsed = getL1GasUsed(_data); - uint256 l1Fee = l1GasUsed * l1BaseFee(); - uint256 divisor = 10 ** DECIMALS; - uint256 unscaled = l1Fee * scalar(); - uint256 scaled = unscaled / divisor; - return scaled; - } - - /// @notice Retrieves the current gas price (base fee). - /// @return Current L2 gas price (base fee). - function gasPrice() public view returns (uint256) { - return block.basefee; - } - - /// @notice Retrieves the current base fee. - /// @return Current L2 base fee. - function baseFee() public view returns (uint256) { - return block.basefee; - } - - /// @notice Retrieves the current fee overhead. - /// @return Current fee overhead. - function overhead() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); - } - - /// @notice Retrieves the current fee scalar. - /// @return Current fee scalar. - function scalar() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); - } - - /// @notice Retrieves the latest known L1 base fee. - /// @return Latest known L1 base fee. - function l1BaseFee() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); - } - - /// @custom:legacy - /// @notice Retrieves the number of decimals used in the scalar. - /// @return Number of decimals used in the scalar. - function decimals() public pure returns (uint256) { - return DECIMALS; - } - - /// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which - /// represents the per-transaction gas overhead of posting the transaction and state - /// roots to L1. Adds 68 bytes of padding to account for the fact that the input does - /// not have a signature. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. - /// @return Amount of L1 gas used to publish the transaction. - function getL1GasUsed(bytes memory _data) public view returns (uint256) { - uint256 total = 0; - uint256 length = _data.length; - for (uint256 i = 0; i < length; i++) { - if (_data[i] == 0) { - total += 4; - } else { - total += 16; - } - } - uint256 unsigned = total + overhead(); - return unsigned + (68 * 16); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol deleted file mode 100644 index 7722b53..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/L1Block.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -import { ISemver } from "../universal/ISemver.sol"; - -/// @custom:proxied -/// @custom:predeploy 0x4200000000000000000000000000000000000015 -/// @title L1Block -/// @notice The L1Block predeploy gives users access to information about the last known L1 block. -/// Values within this contract are updated once per epoch (every L1 block) and can only be -/// set by the "depositor" account, a special system address. Depositor account transactions -/// are created by the protocol whenever we move to a new epoch. -contract L1Block is ISemver { - /// @notice Address of the special depositor account. - address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; - - /// @notice The latest L1 block number known by the L2 system. - uint64 public number; - - /// @notice The latest L1 timestamp known by the L2 system. - uint64 public timestamp; - - /// @notice The latest L1 basefee. - uint256 public basefee; - - /// @notice The latest L1 blockhash. - bytes32 public hash; - - /// @notice The number of L2 blocks in the same epoch. - uint64 public sequenceNumber; - - /// @notice The versioned hash to authenticate the batcher by. - bytes32 public batcherHash; - - /// @notice The overhead value applied to the L1 portion of the transaction fee. - uint256 public l1FeeOverhead; - - /// @notice The scalar value applied to the L1 portion of the transaction fee. - uint256 public l1FeeScalar; - - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; - - /// @notice Updates the L1 block values. - /// @param _number L1 blocknumber. - /// @param _timestamp L1 timestamp. - /// @param _basefee L1 basefee. - /// @param _hash L1 blockhash. - /// @param _sequenceNumber Number of L2 blocks since epoch start. - /// @param _batcherHash Versioned hash to authenticate batcher by. - /// @param _l1FeeOverhead L1 fee overhead. - /// @param _l1FeeScalar L1 fee scalar. - function setL1BlockValues( - uint64 _number, - uint64 _timestamp, - uint256 _basefee, - bytes32 _hash, - uint64 _sequenceNumber, - bytes32 _batcherHash, - uint256 _l1FeeOverhead, - uint256 _l1FeeScalar - ) - external - { - require(msg.sender == DEPOSITOR_ACCOUNT, "L1Block: only the depositor account can set L1 block values"); - - number = _number; - timestamp = _timestamp; - basefee = _basefee; - hash = _hash; - sequenceNumber = _sequenceNumber; - batcherHash = _batcherHash; - l1FeeOverhead = _l1FeeOverhead; - l1FeeScalar = _l1FeeScalar; - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol deleted file mode 100644 index 4a0d399..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/libraries/Predeploys.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title Predeploys -/// @notice Contains constant addresses for contracts that are pre-deployed to the L2 system. -library Predeploys { - /// @notice Address of the L2ToL1MessagePasser predeploy. - address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016; - - /// @notice Address of the L2CrossDomainMessenger predeploy. - address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; - - /// @notice Address of the L2StandardBridge predeploy. - address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; - - /// @notice Address of the L2ERC721Bridge predeploy. - address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014; - - //// @notice Address of the SequencerFeeWallet predeploy. - address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; - - /// @notice Address of the OptimismMintableERC20Factory predeploy. - address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012; - - /// @notice Address of the OptimismMintableERC721Factory predeploy. - address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017; - - /// @notice Address of the L1Block predeploy. - address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; - - /// @notice Address of the GasPriceOracle predeploy. Includes fee information - /// and helpers for computing the L1 portion of the transaction fee. - address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F; - - /// @custom:legacy - /// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger - /// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead. - address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; - - /// @custom:legacy - /// @notice Address of the DeployerWhitelist predeploy. No longer active. - address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; - - /// @custom:legacy - /// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the - /// state trie as of the Bedrock upgrade. Contract has been locked and write functions - /// can no longer be accessed. - address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; - - /// @custom:legacy - /// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy - /// instead, which exposes more information about the L1 state. - address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013; - - /// @custom:legacy - /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated - /// L2ToL1MessagePasser contract instead. - address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; - - /// @notice Address of the ProxyAdmin predeploy. - address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; - - /// @notice Address of the BaseFeeVault predeploy. - address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; - - /// @notice Address of the L1FeeVault predeploy. - address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; - - /// @notice Address of the GovernanceToken predeploy. - address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; - - /// @notice Address of the SchemaRegistry predeploy. - address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020; - - /// @notice Address of the EAS predeploy. - address internal constant EAS = 0x4200000000000000000000000000000000000021; -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol deleted file mode 100644 index ae9569a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/universal/ISemver.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @title ISemver -/// @notice ISemver is a simple contract for ensuring that contracts are -/// versioned using semantic versioning. -interface ISemver { - /// @notice Getter for the semantic version of the contract. This is not - /// meant to be used onchain but instead meant to be used by offchain - /// tooling. - /// @return Semver contract version as a string. - function version() external view returns (string memory); -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol deleted file mode 100644 index 01e07a7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -import {ISemver} from "../universal/ISemver.sol"; -import {Predeploys} from "../libraries/Predeploys.sol"; -import {L1Block} from "../L2/L1Block.sol"; -import {Constants} from "../libraries/Constants.sol"; -import {LibZip} from "../deps/LibZip.sol"; - -/// @custom:proxied -/// @custom:predeploy 0x420000000000000000000000000000000000000F -/// @title GasPriceOracle -/// @notice This contract maintains the variables responsible for computing the L1 portion of the -/// total fee charged on L2. Before Bedrock, this contract held variables in state that were -/// read during the state transition function to compute the L1 portion of the transaction -/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has -/// the values used to compute the L1 portion of the fee in its state. -/// -/// The contract exposes an API that is useful for knowing how large the L1 portion of the -/// transaction fee will be. The following events were deprecated with Bedrock: -/// - event OverheadUpdated(uint256 overhead); -/// - event ScalarUpdated(uint256 scalar); -/// - event DecimalsUpdated(uint256 decimals); -contract GasPriceOracle is ISemver { - /// @notice Number of decimals used in the scalar. - uint256 public constant DECIMALS = 6; - - /// @notice Semantic version. - /// @custom:semver 1.3.0 - string public constant version = "1.3.0"; - - /// @notice This is the intercept value for the linear regression used to estimate the final size of the - /// compressed transaction. - int32 private constant COST_INTERCEPT = -42_585_600; - - /// @notice This is the coefficient value for the linear regression used to estimate the final size of the - /// compressed transaction. - uint32 private constant COST_FASTLZ_COEF = 836_500; - - /// @notice This is the minimum bound for the fastlz to brotli size estimation. Any estimations below this - /// are set to this value. - uint256 private constant MIN_TRANSACTION_SIZE = 100; - - /// @notice Indicates whether the network has gone through the Ecotone upgrade. - bool public isEcotone; - - /// @notice Indicates whether the network has gone through the Fjord upgrade. - bool public isFjord; - - /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input - /// transaction, the current L1 base fee, and the various dynamic parameters. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function getL1Fee(bytes memory _data) external view returns (uint256) { - if (isFjord) { - return _getL1FeeFjord(_data); - } else if (isEcotone) { - return _getL1FeeEcotone(_data); - } - return _getL1FeeBedrock(_data); - } - - /// @notice returns an upper bound for the L1 fee for a given transaction size. - /// It is provided for callers who wish to estimate L1 transaction costs in the - /// write path, and is much more gas efficient than `getL1Fee`. - /// It assumes the worst case of fastlz upper-bound which covers %99.99 txs. - /// @param _unsignedTxSize Unsigned fully RLP-encoded transaction size to get the L1 fee for. - /// @return L1 estimated upper-bound fee that should be paid for the tx - function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256) { - require(isFjord, "GasPriceOracle: getL1FeeUpperBound only supports Fjord"); - - // Add 68 to the size to account for unsigned tx: - uint256 txSize = _unsignedTxSize + 68; - // txSize / 255 + 16 is the pratical fastlz upper-bound covers %99.99 txs. - uint256 flzUpperBound = txSize + txSize / 255 + 16; - - return _fjordL1Cost(flzUpperBound); - } - - /// @notice Set chain to be Ecotone chain (callable by depositor account) - function setEcotone() external { - require( - msg.sender == Constants.DEPOSITOR_ACCOUNT, - "GasPriceOracle: only the depositor account can set isEcotone flag" - ); - require(isEcotone == false, "GasPriceOracle: Ecotone already active"); - isEcotone = true; - } - - /// @notice Set chain to be Fjord chain (callable by depositor account) - function setFjord() external { - require( - msg.sender == Constants.DEPOSITOR_ACCOUNT, - "GasPriceOracle: only the depositor account can set isFjord flag" - ); - require(isEcotone, "GasPriceOracle: Fjord can only be activated after Ecotone"); - require(isFjord == false, "GasPriceOracle: Fjord already active"); - isFjord = true; - } - - /// @notice Retrieves the current gas price (base fee). - /// @return Current L2 gas price (base fee). - function gasPrice() public view returns (uint256) { - return block.basefee; - } - - /// @notice Retrieves the current base fee. - /// @return Current L2 base fee. - function baseFee() public view returns (uint256) { - return block.basefee; - } - - /// @custom:legacy - /// @notice Retrieves the current fee overhead. - /// @return Current fee overhead. - function overhead() public view returns (uint256) { - require(!isEcotone, "GasPriceOracle: overhead() is deprecated"); - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); - } - - /// @custom:legacy - /// @notice Retrieves the current fee scalar. - /// @return Current fee scalar. - function scalar() public view returns (uint256) { - require(!isEcotone, "GasPriceOracle: scalar() is deprecated"); - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); - } - - /// @notice Retrieves the latest known L1 base fee. - /// @return Latest known L1 base fee. - function l1BaseFee() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); - } - - /// @notice Retrieves the current blob base fee. - /// @return Current blob base fee. - function blobBaseFee() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee(); - } - - /// @notice Retrieves the current base fee scalar. - /// @return Current base fee scalar. - function baseFeeScalar() public view returns (uint32) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar(); - } - - /// @notice Retrieves the current blob base fee scalar. - /// @return Current blob base fee scalar. - function blobBaseFeeScalar() public view returns (uint32) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar(); - } - - /// @custom:legacy - /// @notice Retrieves the number of decimals used in the scalar. - /// @return Number of decimals used in the scalar. - function decimals() public pure returns (uint256) { - return DECIMALS; - } - - /// @notice Computes the amount of L1 gas used for a transaction. Adds 68 bytes - /// of padding to account for the fact that the input does not have a signature. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. - /// @return Amount of L1 gas used to publish the transaction. - /// @custom:deprecated This method does not accurately estimate the gas used for a transaction. - /// If you are calculating fees use getL1Fee or getL1FeeUpperBound. - function getL1GasUsed(bytes memory _data) public view returns (uint256) { - if (isFjord) { - // Add 68 to the size to account for unsigned tx - // Assume the compressed data is mostly non-zero, and would pay 16 gas per calldata byte - // Divide by 1e6 due to the scaling factor of the linear regression - return (_fjordLinearRegression(LibZip.flzCompress(_data).length + 68) * 16) / 1e6; - } - uint256 l1GasUsed = _getCalldataGas(_data); - if (isEcotone) { - return l1GasUsed; - } - return l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); - } - - /// @notice Computation of the L1 portion of the fee for Bedrock. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function _getL1FeeBedrock(bytes memory _data) internal view returns (uint256) { - uint256 l1GasUsed = _getCalldataGas(_data); - uint256 fee = (l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * - l1BaseFee() * - L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); - return fee / (10 ** DECIMALS); - } - - /// @notice L1 portion of the fee after Ecotone. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function _getL1FeeEcotone(bytes memory _data) internal view returns (uint256) { - uint256 l1GasUsed = _getCalldataGas(_data); - uint256 scaledBaseFee = baseFeeScalar() * 16 * l1BaseFee(); - uint256 scaledBlobBaseFee = blobBaseFeeScalar() * blobBaseFee(); - uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee); - return fee / (16 * 10 ** DECIMALS); - } - - /// @notice L1 portion of the fee after Fjord. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function _getL1FeeFjord(bytes memory _data) internal view returns (uint256) { - return _fjordL1Cost(LibZip.flzCompress(_data).length + 68); - } - - /// @notice L1 gas estimation calculation. - /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. - /// @return Amount of L1 gas used to publish the transaction. - function _getCalldataGas(bytes memory _data) internal pure returns (uint256) { - uint256 total = 0; - uint256 length = _data.length; - for (uint256 i = 0; i < length; i++) { - if (_data[i] == 0) { - total += 4; - } else { - total += 16; - } - } - return total + (68 * 16); - } - - /// @notice Fjord L1 cost based on the compressed and original tx size. - /// @param _fastLzSize estimated compressed tx size. - /// @return Fjord L1 fee that should be paid for the tx - function _fjordL1Cost(uint256 _fastLzSize) internal view returns (uint256) { - // Apply the linear regression to estimate the Brotli 10 size - uint256 estimatedSize = _fjordLinearRegression(_fastLzSize); - uint256 feeScaled = baseFeeScalar() * 16 * l1BaseFee() + blobBaseFeeScalar() * blobBaseFee(); - return (estimatedSize * feeScaled) / (10 ** (DECIMALS * 2)); - } - - /// @notice Takes the fastLz size compression and returns the estimated Brotli - /// @param _fastLzSize fastlz compressed tx size. - /// @return Number of bytes in the compressed transaction - function _fjordLinearRegression(uint256 _fastLzSize) internal pure returns (uint256) { - int256 estimatedSize = COST_INTERCEPT + int256(COST_FASTLZ_COEF * _fastLzSize); - if (estimatedSize < int256(MIN_TRANSACTION_SIZE) * 1e6) { - estimatedSize = int256(MIN_TRANSACTION_SIZE) * 1e6; - } - return uint256(estimatedSize); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol deleted file mode 100644 index a58c85b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/L1Block.sol +++ /dev/null @@ -1,169 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/L1Block.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -import {ISemver} from "../universal/ISemver.sol"; -import {Constants} from "../libraries/Constants.sol"; -import {GasPayingToken, IGasToken} from "../libraries/GasPayingToken.sol"; -import "../libraries/L1BlockErrors.sol"; - -/// @custom:proxied -/// @custom:predeploy 0x4200000000000000000000000000000000000015 -/// @title L1Block -/// @notice The L1Block predeploy gives users access to information about the last known L1 block. -/// Values within this contract are updated once per epoch (every L1 block) and can only be -/// set by the "depositor" account, a special system address. Depositor account transactions -/// are created by the protocol whenever we move to a new epoch. -contract L1Block is ISemver, IGasToken { - /// @notice Event emitted when the gas paying token is set. - event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); - - /// @notice Address of the special depositor account. - function DEPOSITOR_ACCOUNT() public pure returns (address addr_) { - addr_ = Constants.DEPOSITOR_ACCOUNT; - } - - /// @notice The latest L1 block number known by the L2 system. - uint64 public number; - - /// @notice The latest L1 timestamp known by the L2 system. - uint64 public timestamp; - - /// @notice The latest L1 base fee. - uint256 public basefee; - - /// @notice The latest L1 blockhash. - bytes32 public hash; - - /// @notice The number of L2 blocks in the same epoch. - uint64 public sequenceNumber; - - /// @notice The scalar value applied to the L1 blob base fee portion of the blob-capable L1 cost func. - uint32 public blobBaseFeeScalar; - - /// @notice The scalar value applied to the L1 base fee portion of the blob-capable L1 cost func. - uint32 public baseFeeScalar; - - /// @notice The versioned hash to authenticate the batcher by. - bytes32 public batcherHash; - - /// @notice The overhead value applied to the L1 portion of the transaction fee. - /// @custom:legacy - uint256 public l1FeeOverhead; - - /// @notice The scalar value applied to the L1 portion of the transaction fee. - /// @custom:legacy - uint256 public l1FeeScalar; - - /// @notice The latest L1 blob base fee. - uint256 public blobBaseFee; - - /// @custom:semver 1.4.1-beta.1 - function version() public pure virtual returns (string memory) { - return "1.4.1-beta.1"; - } - - /// @notice Returns the gas paying token, its decimals, name and symbol. - /// If nothing is set in state, then it means ether is used. - function gasPayingToken() public view returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = GasPayingToken.getToken(); - } - - /// @notice Returns the gas paying token name. - /// If nothing is set in state, then it means ether is used. - function gasPayingTokenName() public view returns (string memory name_) { - name_ = GasPayingToken.getName(); - } - - /// @notice Returns the gas paying token symbol. - /// If nothing is set in state, then it means ether is used. - function gasPayingTokenSymbol() public view returns (string memory symbol_) { - symbol_ = GasPayingToken.getSymbol(); - } - - /// @notice Getter for custom gas token paying networks. Returns true if the - /// network uses a custom gas token. - function isCustomGasToken() public view returns (bool) { - (address token, ) = gasPayingToken(); - return token != Constants.ETHER; - } - - /// @custom:legacy - /// @notice Updates the L1 block values. - /// @param _number L1 blocknumber. - /// @param _timestamp L1 timestamp. - /// @param _basefee L1 basefee. - /// @param _hash L1 blockhash. - /// @param _sequenceNumber Number of L2 blocks since epoch start. - /// @param _batcherHash Versioned hash to authenticate batcher by. - /// @param _l1FeeOverhead L1 fee overhead. - /// @param _l1FeeScalar L1 fee scalar. - function setL1BlockValues( - uint64 _number, - uint64 _timestamp, - uint256 _basefee, - bytes32 _hash, - uint64 _sequenceNumber, - bytes32 _batcherHash, - uint256 _l1FeeOverhead, - uint256 _l1FeeScalar - ) external { - require(msg.sender == DEPOSITOR_ACCOUNT(), "L1Block: only the depositor account can set L1 block values"); - - number = _number; - timestamp = _timestamp; - basefee = _basefee; - hash = _hash; - sequenceNumber = _sequenceNumber; - batcherHash = _batcherHash; - l1FeeOverhead = _l1FeeOverhead; - l1FeeScalar = _l1FeeScalar; - } - - /// @notice Updates the L1 block values for an Ecotone upgraded chain. - /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. - /// Params are expected to be in the following order: - /// 1. _baseFeeScalar L1 base fee scalar - /// 2. _blobBaseFeeScalar L1 blob base fee scalar - /// 3. _sequenceNumber Number of L2 blocks since epoch start. - /// 4. _timestamp L1 timestamp. - /// 5. _number L1 blocknumber. - /// 6. _basefee L1 base fee. - /// 7. _blobBaseFee L1 blob base fee. - /// 8. _hash L1 blockhash. - /// 9. _batcherHash Versioned hash to authenticate batcher by. - function setL1BlockValuesEcotone() external { - address depositor = DEPOSITOR_ACCOUNT(); - assembly { - // Revert if the caller is not the depositor account. - if xor(caller(), depositor) { - mstore(0x00, 0x3cc50b45) // 0x3cc50b45 is the 4-byte selector of "NotDepositor()" - revert(0x1C, 0x04) // returns the stored 4-byte selector from above - } - // sequencenum (uint64), blobBaseFeeScalar (uint32), baseFeeScalar (uint32) - sstore(sequenceNumber.slot, shr(128, calldataload(4))) - // number (uint64) and timestamp (uint64) - sstore(number.slot, shr(128, calldataload(20))) - sstore(basefee.slot, calldataload(36)) // uint256 - sstore(blobBaseFee.slot, calldataload(68)) // uint256 - sstore(hash.slot, calldataload(100)) // bytes32 - sstore(batcherHash.slot, calldataload(132)) // bytes32 - } - } - - /// @notice Sets the gas paying token for the L2 system. Can only be called by the special - /// depositor account. This function is not called on every L2 block but instead - /// only called by specially crafted L1 deposit transactions. - function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external { - if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor(); - - GasPayingToken.set({_token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol}); - - emit GasPayingTokenSet({token: _token, decimals: _decimals, name: _name, symbol: _symbol}); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol deleted file mode 100644 index bf6d8c2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibString.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/transmissions11/solmate/blob/97bdb2003b70382996a79a406813f76417b1cf90/src/utils/LibString.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @notice Library for converting numbers into strings and other string operations. -/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) -/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) -/// -/// Note: -/// For performance and bytecode compactness, most of the string operations are restricted to -/// byte strings (7-bit ASCII), except where otherwise specified. -/// Usage of byte string operations on charsets with runes spanning two or more bytes -/// can lead to undefined behavior. -library LibString { - /// @dev Returns a string from a small bytes32 string. - /// `s` must be null-terminated, or behavior will be undefined. - function fromSmallString(bytes32 s) internal pure returns (string memory result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(0x40) - let n := 0 - for { - - } byte(n, s) { - n := add(n, 1) - } { - - } // Scan for '\0'. - mstore(result, n) - let o := add(result, 0x20) - mstore(o, s) - mstore(add(o, n), 0) - mstore(0x40, add(result, 0x40)) - } - } - - /// @dev Returns the string as a normalized null-terminated small string. - function toSmallString(string memory s) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - result := mload(s) - if iszero(lt(result, 33)) { - mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. - revert(0x1c, 0x04) - } - result := shl(shl(3, sub(32, result)), mload(add(s, result))) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol deleted file mode 100644 index 5adc429..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/deps/LibZip.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/Vectorized/solady/blob/3e8031b16417154dc2beae71b7b45f415d29566b/src/utils/LibZip.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @notice Library for compressing and decompressing bytes. -/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol) -/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor) -/// @author FastLZ by ariya (https://github.com/ariya/FastLZ) -/// -/// @dev Note: -/// The accompanying solady.js library includes implementations of -/// FastLZ and calldata operations for convenience. -library LibZip { - /// @dev Returns the compressed `data`. - function flzCompress(bytes memory data) internal pure returns (bytes memory result) { - /// @solidity memory-safe-assembly - assembly { - function ms8(d_, v_) -> _d { - mstore8(d_, v_) - _d := add(d_, 1) - } - function u24(p_) -> _u { - let w := mload(p_) - _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w))) - } - function cmp(p_, q_, e_) -> _l { - for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } { - e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_) - } - } - function literals(runs_, src_, dest_) -> _o { - for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } { - mstore(ms8(_o, 31), mload(src_)) - _o := add(_o, 0x21) - src_ := add(src_, 0x20) - } - if iszero(runs_) { leave } - mstore(ms8(_o, sub(runs_, 1)), mload(src_)) - _o := add(1, add(_o, runs_)) - } - function match(l_, d_, o_) -> _o { - for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } { - o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_)) - } - if iszero(lt(l_, 7)) { - _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_)) - leave - } - _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_)) - } - function setHash(i_, v_) { - let p := add(mload(0x40), shl(2, i_)) - mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_)))) - } - function getHash(i_) -> _h { - _h := shr(224, mload(add(mload(0x40), shl(2, i_)))) - } - function hash(v_) -> _r { - _r := and(shr(19, mul(2654435769, v_)), 0x1fff) - } - function setNextHash(ip_, ipStart_) -> _ip { - setHash(hash(u24(ip_)), sub(ip_, ipStart_)) - _ip := add(ip_, 1) - } - codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap. - let op := add(mload(0x40), 0x8000) - let a := add(data, 0x20) - let ipStart := a - let ipLimit := sub(add(ipStart, mload(data)), 13) - for { let ip := add(2, a) } lt(ip, ipLimit) {} { - let r := 0 - let d := 0 - for {} 1 {} { - let s := u24(ip) - let h := hash(s) - r := add(ipStart, getHash(h)) - setHash(h, sub(ip, ipStart)) - d := sub(ip, r) - if iszero(lt(ip, ipLimit)) { break } - ip := add(ip, 1) - if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } } - } - if iszero(lt(ip, ipLimit)) { break } - ip := sub(ip, 1) - if gt(ip, a) { op := literals(sub(ip, a), a, op) } - let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9)) - op := match(l, d, op) - ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart) - a := ip - } - op := literals(sub(add(ipStart, mload(data)), a), a, op) - result := mload(0x40) - let t := add(result, 0x8000) - let n := sub(op, t) - mstore(result, n) // Store the length. - // Copy the result to compact the memory, overwriting the hashmap. - let o := add(result, 0x20) - for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) } - mstore(add(o, n), 0) // Zeroize the slot after the string. - mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory. - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol deleted file mode 100644 index 79981ec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Constants.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Constants.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @title Constants -/// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just -/// the stuff used in multiple contracts. Constants that only apply to a single contract -/// should be defined in that contract instead. -library Constants { - /// @notice Special address to be used as the tx origin for gas estimation calls in the - /// OptimismPortal and CrossDomainMessenger calls. You only need to use this address if - /// the minimum gas limit specified by the user is not actually enough to execute the - /// given message and you're attempting to estimate the actual necessary gas limit. We - /// use address(1) because it's the ecrecover precompile and therefore guaranteed to - /// never have any code on any EVM chain. - address internal constant ESTIMATION_ADDRESS = address(1); - - /// @notice Value used for the L2 sender storage slot in both the OptimismPortal and the - /// CrossDomainMessenger contracts before an actual sender is set. This value is - /// non-zero to reduce the gas cost of message passing transactions. - address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; - - /// @notice The storage slot that holds the address of a proxy implementation. - /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` - bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - - /// @notice The storage slot that holds the address of the owner. - /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` - bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; - - /// @notice The address that represents ether when dealing with ERC20 token addresses. - address internal constant ETHER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - - /// @notice The address that represents the system caller responsible for L1 attributes - /// transactions. - address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol deleted file mode 100644 index 7754f50..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/GasPayingToken.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/GasPayingToken.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -import {Storage} from "./Storage.sol"; -import {Constants} from "./Constants.sol"; -import {LibString} from "../deps/LibString.sol"; - -/// @title IGasToken -/// @notice Implemented by contracts that are aware of the custom gas token used -/// by the L2 network. -interface IGasToken { - /// @notice Getter for the ERC20 token address that is used to pay for gas and its decimals. - function gasPayingToken() external view returns (address, uint8); - /// @notice Returns the gas token name. - function gasPayingTokenName() external view returns (string memory); - /// @notice Returns the gas token symbol. - function gasPayingTokenSymbol() external view returns (string memory); - /// @notice Returns true if the network uses a custom gas token. - function isCustomGasToken() external view returns (bool); -} - -/// @title GasPayingToken -/// @notice Handles reading and writing the custom gas token to storage. -/// To be used in any place where gas token information is read or -/// written to state. If multiple contracts use this library, the -/// values in storage should be kept in sync between them. -library GasPayingToken { - /// @notice The storage slot that contains the address and decimals of the gas paying token - bytes32 internal constant GAS_PAYING_TOKEN_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtoken")) - 1); - - /// @notice The storage slot that contains the ERC20 `name()` of the gas paying token - bytes32 internal constant GAS_PAYING_TOKEN_NAME_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokenname")) - 1); - - /// @notice the storage slot that contains the ERC20 `symbol()` of the gas paying token - bytes32 internal constant GAS_PAYING_TOKEN_SYMBOL_SLOT = - bytes32(uint256(keccak256("opstack.gaspayingtokensymbol")) - 1); - - /// @notice Reads the gas paying token and its decimals from the magic - /// storage slot. If nothing is set in storage, then the ether - /// address is returned instead. - function getToken() internal view returns (address addr_, uint8 decimals_) { - bytes32 slot = Storage.getBytes32(GAS_PAYING_TOKEN_SLOT); - addr_ = address(uint160(uint256(slot) & uint256(type(uint160).max))); - if (addr_ == address(0)) { - addr_ = Constants.ETHER; - decimals_ = 18; - } else { - decimals_ = uint8(uint256(slot) >> 160); - } - } - - /// @notice Reads the gas paying token's name from the magic storage slot. - /// If nothing is set in storage, then the ether name, 'Ether', is returned instead. - function getName() internal view returns (string memory name_) { - (address addr, ) = getToken(); - if (addr == Constants.ETHER) { - name_ = "Ether"; - } else { - name_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_NAME_SLOT)); - } - } - - /// @notice Reads the gas paying token's symbol from the magic storage slot. - /// If nothing is set in storage, then the ether symbol, 'ETH', is returned instead. - function getSymbol() internal view returns (string memory symbol_) { - (address addr, ) = getToken(); - if (addr == Constants.ETHER) { - symbol_ = "ETH"; - } else { - symbol_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT)); - } - } - - /// @notice Writes the gas paying token, its decimals, name and symbol to the magic storage slot. - function set(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) internal { - Storage.setBytes32(GAS_PAYING_TOKEN_SLOT, bytes32((uint256(_decimals) << 160) | uint256(uint160(_token)))); - Storage.setBytes32(GAS_PAYING_TOKEN_NAME_SLOT, _name); - Storage.setBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT, _symbol); - } - - /// @notice Maps a string to a normalized null-terminated small string. - function sanitize(string memory _str) internal pure returns (bytes32) { - require(bytes(_str).length <= 32, "GasPayingToken: string cannot be greater than 32 bytes"); - - return LibString.toSmallString(_str); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol deleted file mode 100644 index e6a180a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/L1BlockErrors.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @notice Error returns when a non-depositor account tries to set L1 block values. -error NotDepositor(); - -/// @notice Error when a chain ID is not in the interop dependency set. -error NotDependency(); - -/// @notice Error when the interop dependency set size is too large. -error DependencySetSizeTooLarge(); - -/// @notice Error when a chain ID already in the interop dependency set is attempted to be added. -error AlreadyDependency(); - -/// @notice Error when the chain's chain ID is attempted to be removed from the interop dependency set. -error CantRemovedDependency(); diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol deleted file mode 100644 index 5b42d2e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Predeploys.sol +++ /dev/null @@ -1,171 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Predeploys.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @title Predeploys -/// @notice Contains constant addresses for protocol contracts that are pre-deployed to the L2 system. -// This excludes the preinstalls (non-protocol contracts). -library Predeploys { - /// @notice Number of predeploy-namespace addresses reserved for protocol usage. - uint256 internal constant PREDEPLOY_COUNT = 2048; - - /// @custom:legacy - /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated - /// L2ToL1MessagePasser contract instead. - address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; - - /// @custom:legacy - /// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger - /// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead. - /// Not embedded into new OP-Stack chains. - address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; - - /// @custom:legacy - /// @notice Address of the DeployerWhitelist predeploy. No longer active. - address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; - - /// @notice Address of the canonical WETH contract. - address internal constant WETH = 0x4200000000000000000000000000000000000006; - - /// @notice Address of the L2CrossDomainMessenger predeploy. - address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; - - /// @notice Address of the GasPriceOracle predeploy. Includes fee information - /// and helpers for computing the L1 portion of the transaction fee. - address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F; - - /// @notice Address of the L2StandardBridge predeploy. - address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; - - //// @notice Address of the SequencerFeeWallet predeploy. - address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; - - /// @notice Address of the OptimismMintableERC20Factory predeploy. - address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012; - - /// @custom:legacy - /// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy - /// instead, which exposes more information about the L1 state. - address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013; - - /// @notice Address of the L2ERC721Bridge predeploy. - address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014; - - /// @notice Address of the L1Block predeploy. - address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; - - /// @notice Address of the L2ToL1MessagePasser predeploy. - address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016; - - /// @notice Address of the OptimismMintableERC721Factory predeploy. - address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017; - - /// @notice Address of the ProxyAdmin predeploy. - address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018; - - /// @notice Address of the BaseFeeVault predeploy. - address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019; - - /// @notice Address of the L1FeeVault predeploy. - address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A; - - /// @notice Address of the SchemaRegistry predeploy. - address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020; - - /// @notice Address of the EAS predeploy. - address internal constant EAS = 0x4200000000000000000000000000000000000021; - - /// @notice Address of the GovernanceToken predeploy. - address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; - - /// @custom:legacy - /// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the - /// state trie as of the Bedrock upgrade. Contract has been locked and write functions - /// can no longer be accessed. - address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; - - /// @notice Address of the CrossL2Inbox predeploy. - address internal constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; - - /// @notice Address of the L2ToL2CrossDomainMessenger predeploy. - address internal constant L2_TO_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000023; - - /// @notice Returns the name of the predeploy at the given address. - function getName(address _addr) internal pure returns (string memory out_) { - require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); - if (_addr == LEGACY_MESSAGE_PASSER) return "LegacyMessagePasser"; - if (_addr == L1_MESSAGE_SENDER) return "L1MessageSender"; - if (_addr == DEPLOYER_WHITELIST) return "DeployerWhitelist"; - if (_addr == WETH) return "WETH"; - if (_addr == L2_CROSS_DOMAIN_MESSENGER) return "L2CrossDomainMessenger"; - if (_addr == GAS_PRICE_ORACLE) return "GasPriceOracle"; - if (_addr == L2_STANDARD_BRIDGE) return "L2StandardBridge"; - if (_addr == SEQUENCER_FEE_WALLET) return "SequencerFeeVault"; - if (_addr == OPTIMISM_MINTABLE_ERC20_FACTORY) return "OptimismMintableERC20Factory"; - if (_addr == L1_BLOCK_NUMBER) return "L1BlockNumber"; - if (_addr == L2_ERC721_BRIDGE) return "L2ERC721Bridge"; - if (_addr == L1_BLOCK_ATTRIBUTES) return "L1Block"; - if (_addr == L2_TO_L1_MESSAGE_PASSER) return "L2ToL1MessagePasser"; - if (_addr == OPTIMISM_MINTABLE_ERC721_FACTORY) return "OptimismMintableERC721Factory"; - if (_addr == PROXY_ADMIN) return "ProxyAdmin"; - if (_addr == BASE_FEE_VAULT) return "BaseFeeVault"; - if (_addr == L1_FEE_VAULT) return "L1FeeVault"; - if (_addr == SCHEMA_REGISTRY) return "SchemaRegistry"; - if (_addr == EAS) return "EAS"; - if (_addr == GOVERNANCE_TOKEN) return "GovernanceToken"; - if (_addr == LEGACY_ERC20_ETH) return "LegacyERC20ETH"; - if (_addr == CROSS_L2_INBOX) return "CrossL2Inbox"; - if (_addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) return "L2ToL2CrossDomainMessenger"; - revert("Predeploys: unnamed predeploy"); - } - - /// @notice Returns true if the predeploy is not proxied. - function notProxied(address _addr) internal pure returns (bool) { - return _addr == GOVERNANCE_TOKEN || _addr == WETH; - } - - /// @notice Returns true if the address is a defined predeploy that is embedded into new OP-Stack chains. - function isSupportedPredeploy(address _addr, bool _useInterop) internal pure returns (bool) { - return - _addr == LEGACY_MESSAGE_PASSER || - _addr == DEPLOYER_WHITELIST || - _addr == WETH || - _addr == L2_CROSS_DOMAIN_MESSENGER || - _addr == GAS_PRICE_ORACLE || - _addr == L2_STANDARD_BRIDGE || - _addr == SEQUENCER_FEE_WALLET || - _addr == OPTIMISM_MINTABLE_ERC20_FACTORY || - _addr == L1_BLOCK_NUMBER || - _addr == L2_ERC721_BRIDGE || - _addr == L1_BLOCK_ATTRIBUTES || - _addr == L2_TO_L1_MESSAGE_PASSER || - _addr == OPTIMISM_MINTABLE_ERC721_FACTORY || - _addr == PROXY_ADMIN || - _addr == BASE_FEE_VAULT || - _addr == L1_FEE_VAULT || - _addr == SCHEMA_REGISTRY || - _addr == EAS || - _addr == GOVERNANCE_TOKEN || - (_useInterop && _addr == CROSS_L2_INBOX) || - (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER); - } - - function isPredeployNamespace(address _addr) internal pure returns (bool) { - return uint160(_addr) >> 11 == uint160(0x4200000000000000000000000000000000000000) >> 11; - } - - /// @notice Function to compute the expected address of the predeploy implementation - /// in the genesis state. - function predeployToCodeNamespace(address _addr) internal pure returns (address) { - require(isPredeployNamespace(_addr), "Predeploys: can only derive code-namespace address for predeploy addresses"); - return - address( - uint160((uint256(uint160(_addr)) & 0xffff) | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000))) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol deleted file mode 100644 index 3da986b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/libraries/Storage.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Storage.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @title Storage -/// @notice Storage handles reading and writing to arbitary storage locations -library Storage { - /// @notice Returns an address stored in an arbitrary storage slot. - /// These storage slots decouple the storage layout from - /// solc's automation. - /// @param _slot The storage slot to retrieve the address from. - function getAddress(bytes32 _slot) internal view returns (address addr_) { - assembly { - addr_ := sload(_slot) - } - } - - /// @notice Stores an address in an arbitrary storage slot, `_slot`. - /// @param _slot The storage slot to store the address in. - /// @param _address The protocol version to store - /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses - /// in arbitrary storage slots. - function setAddress(bytes32 _slot, address _address) internal { - assembly { - sstore(_slot, _address) - } - } - - /// @notice Returns a uint256 stored in an arbitrary storage slot. - /// These storage slots decouple the storage layout from - /// solc's automation. - /// @param _slot The storage slot to retrieve the address from. - function getUint(bytes32 _slot) internal view returns (uint256 value_) { - assembly { - value_ := sload(_slot) - } - } - - /// @notice Stores a value in an arbitrary storage slot, `_slot`. - /// @param _slot The storage slot to store the address in. - /// @param _value The protocol version to store - /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values - /// in arbitrary storage slots. - function setUint(bytes32 _slot, uint256 _value) internal { - assembly { - sstore(_slot, _value) - } - } - - /// @notice Returns a bytes32 stored in an arbitrary storage slot. - /// These storage slots decouple the storage layout from - /// solc's automation. - /// @param _slot The storage slot to retrieve the address from. - function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) { - assembly { - value_ := sload(_slot) - } - } - - /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`. - /// @param _slot The storage slot to store the address in. - /// @param _value The bytes32 value to store. - /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values - /// in arbitrary storage slots. - function setBytes32(bytes32 _slot, bytes32 _value) internal { - assembly { - sstore(_slot, _value) - } - } - - /// @notice Stores a bool value in an arbitrary storage slot, `_slot`. - /// @param _slot The storage slot to store the bool in. - /// @param _value The bool value to store - /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values - /// in arbitrary storage slots. - function setBool(bytes32 _slot, bool _value) internal { - assembly { - sstore(_slot, _value) - } - } - - /// @notice Returns a bool stored in an arbitrary storage slot. - /// @param _slot The storage slot to retrieve the bool from. - function getBool(bytes32 _slot) internal view returns (bool value_) { - assembly { - value_ := sload(_slot) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol deleted file mode 100644 index d9f3cfd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/universal/ISemver.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice: IMPORTANT NOTICE for anyone who wants to use this contract -/// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/universal/ISemver.sol -/// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle -/// @notice We need this file so that Solidity compiler will not complain because some functions don't exist -/// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract - -/// @title ISemver -/// @notice ISemver is a simple contract for ensuring that contracts are -/// versioned using semantic versioning. -interface ISemver { - /// @notice Getter for the semantic version of the contract. This is not - /// meant to be used onchain but instead meant to be used by offchain - /// tooling. - /// @return Semver contract version as a string. - function version() external view returns (string memory); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol deleted file mode 100644 index 8b5aad8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.7.6 <0.9.0; - -/** - * @title iOVM_CrossDomainMessenger - */ -interface iOVM_CrossDomainMessenger { - /********** - * Events * - **********/ - - event SentMessage(bytes message); - event RelayedMessage(bytes32 msgHash); - event FailedRelayedMessage(bytes32 msgHash); - - /************* - * Variables * - *************/ - - function xDomainMessageSender() external view returns (address); - - /******************** - * Public Functions * - ********************/ - - /** - * Sends a cross domain message to the target messenger. - * @param _target Target contract address. - * @param _message Message to send to the target. - * @param _gasLimit Gas limit for the provided message. - */ - function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol deleted file mode 100644 index a3e137a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.6; - -/* External Imports */ -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title OVM_GasPriceOracle - * @dev This contract exposes the current l2 gas price, a measure of how congested the network - * currently is. This measure is used by the Sequencer to determine what fee to charge for - * transactions. When the system is more congested, the l2 gas price will increase and fees - * will also increase as a result. - * - * All public variables are set while generating the initial L2 state. The - * constructor doesn't run in practice as the L2 state generation script uses - * the deployed bytecode instead of running the initcode. - */ -contract OVM_GasPriceOracle is Ownable { - /************* - * Variables * - *************/ - - // Current L2 gas price - uint256 public gasPrice; - // Current L1 base fee - uint256 public l1BaseFee; - // Amortized cost of batch submission per transaction - uint256 public overhead; - // Value to scale the fee up by - uint256 public scalar; - // Number of decimals of the scalar - uint256 public decimals; - - /*************** - * Constructor * - ***************/ - - /** - * @param _owner Address that will initially own this contract. - */ - constructor(address _owner) Ownable() { - transferOwnership(_owner); - } - - /********** - * Events * - **********/ - - event GasPriceUpdated(uint256); - event L1BaseFeeUpdated(uint256); - event OverheadUpdated(uint256); - event ScalarUpdated(uint256); - event DecimalsUpdated(uint256); - - /******************** - * Public Functions * - ********************/ - - /** - * Allows the owner to modify the l2 gas price. - * @param _gasPrice New l2 gas price. - */ - // slither-disable-next-line external-function - function setGasPrice(uint256 _gasPrice) public onlyOwner { - gasPrice = _gasPrice; - emit GasPriceUpdated(_gasPrice); - } - - /** - * Allows the owner to modify the l1 base fee. - * @param _baseFee New l1 base fee - */ - // slither-disable-next-line external-function - function setL1BaseFee(uint256 _baseFee) public onlyOwner { - l1BaseFee = _baseFee; - emit L1BaseFeeUpdated(_baseFee); - } - - /** - * Allows the owner to modify the overhead. - * @param _overhead New overhead - */ - // slither-disable-next-line external-function - function setOverhead(uint256 _overhead) public onlyOwner { - overhead = _overhead; - emit OverheadUpdated(_overhead); - } - - /** - * Allows the owner to modify the scalar. - * @param _scalar New scalar - */ - // slither-disable-next-line external-function - function setScalar(uint256 _scalar) public onlyOwner { - scalar = _scalar; - emit ScalarUpdated(_scalar); - } - - /** - * Allows the owner to modify the decimals. - * @param _decimals New decimals - */ - // slither-disable-next-line external-function - function setDecimals(uint256 _decimals) public onlyOwner { - decimals = _decimals; - emit DecimalsUpdated(_decimals); - } - - /** - * Computes the L1 portion of the fee - * based on the size of the RLP encoded tx - * and the current l1BaseFee - * @param _data Unsigned RLP encoded tx, 6 elements - * @return L1 fee that should be paid for the tx - */ - // slither-disable-next-line external-function - function getL1Fee(bytes memory _data) public view returns (uint256) { - uint256 l1GasUsed = getL1GasUsed(_data); - uint256 l1Fee = l1GasUsed * l1BaseFee; - uint256 divisor = 10**decimals; - uint256 unscaled = l1Fee * scalar; - uint256 scaled = unscaled / divisor; - return scaled; - } - - // solhint-disable max-line-length - /** - * Computes the amount of L1 gas used for a transaction - * The overhead represents the per batch gas overhead of - * posting both transaction and state roots to L1 given larger - * batch sizes. - * 4 gas for 0 byte - * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33 - * 16 gas for non zero byte - * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87 - * This will need to be updated if calldata gas prices change - * Account for the transaction being unsigned - * Padding is added to account for lack of signature on transaction - * 1 byte for RLP V prefix - * 1 byte for V - * 1 byte for RLP R prefix - * 32 bytes for R - * 1 byte for RLP S prefix - * 32 bytes for S - * Total: 68 bytes of padding - * @param _data Unsigned RLP encoded tx, 6 elements - * @return Amount of L1 gas used for a transaction - */ - // solhint-enable max-line-length - function getL1GasUsed(bytes memory _data) public view returns (uint256) { - uint256 total = 0; - for (uint256 i = 0; i < _data.length; i++) { - if (_data[i] == 0) { - total += 4; - } else { - total += 16; - } - } - uint256 unsigned = total + overhead; - return unsigned + (68 * 16); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol deleted file mode 100644 index b2a6c78..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -/* External Imports */ -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title OVM_GasPriceOracle - * @dev This contract exposes the current l2 gas price, a measure of how congested the network - * currently is. This measure is used by the Sequencer to determine what fee to charge for - * transactions. When the system is more congested, the l2 gas price will increase and fees - * will also increase as a result. - * - * All public variables are set while generating the initial L2 state. The - * constructor doesn't run in practice as the L2 state generation script uses - * the deployed bytecode instead of running the initcode. - */ -contract OVM_GasPriceOracle is Ownable { - /************* - * Variables * - *************/ - - // Current L2 gas price - uint256 public gasPrice; - // Current L1 base fee - uint256 public l1BaseFee; - // Amortized cost of batch submission per transaction - uint256 public overhead; - // Value to scale the fee up by - uint256 public scalar; - // Number of decimals of the scalar - uint256 public decimals; - - /*************** - * Constructor * - ***************/ - - /** - * @param _owner Address that will initially own this contract. - */ - constructor(address _owner) Ownable() { - transferOwnership(_owner); - } - - /********** - * Events * - **********/ - - event GasPriceUpdated(uint256); - event L1BaseFeeUpdated(uint256); - event OverheadUpdated(uint256); - event ScalarUpdated(uint256); - event DecimalsUpdated(uint256); - - /******************** - * Public Functions * - ********************/ - - /** - * Allows the owner to modify the l2 gas price. - * @param _gasPrice New l2 gas price. - */ - // slither-disable-next-line external-function - function setGasPrice(uint256 _gasPrice) public onlyOwner { - gasPrice = _gasPrice; - emit GasPriceUpdated(_gasPrice); - } - - /** - * Allows the owner to modify the l1 base fee. - * @param _baseFee New l1 base fee - */ - // slither-disable-next-line external-function - function setL1BaseFee(uint256 _baseFee) public onlyOwner { - l1BaseFee = _baseFee; - emit L1BaseFeeUpdated(_baseFee); - } - - /** - * Allows the owner to modify the overhead. - * @param _overhead New overhead - */ - // slither-disable-next-line external-function - function setOverhead(uint256 _overhead) public onlyOwner { - overhead = _overhead; - emit OverheadUpdated(_overhead); - } - - /** - * Allows the owner to modify the scalar. - * @param _scalar New scalar - */ - // slither-disable-next-line external-function - function setScalar(uint256 _scalar) public onlyOwner { - scalar = _scalar; - emit ScalarUpdated(_scalar); - } - - /** - * Allows the owner to modify the decimals. - * @param _decimals New decimals - */ - // slither-disable-next-line external-function - function setDecimals(uint256 _decimals) public onlyOwner { - decimals = _decimals; - emit DecimalsUpdated(_decimals); - } - - /** - * Computes the L1 portion of the fee - * based on the size of the RLP encoded tx - * and the current l1BaseFee - * @param _data Unsigned RLP encoded tx, 6 elements - * @return L1 fee that should be paid for the tx - */ - // slither-disable-next-line external-function - function getL1Fee(bytes memory _data) public view returns (uint256) { - uint256 l1GasUsed = getL1GasUsed(_data); - uint256 l1Fee = l1GasUsed * l1BaseFee; - uint256 divisor = 10 ** decimals; - uint256 unscaled = l1Fee * scalar; - uint256 scaled = unscaled / divisor; - return scaled; - } - - // solhint-disable max-line-length - /** - * Computes the amount of L1 gas used for a transaction - * The overhead represents the per batch gas overhead of - * posting both transaction and state roots to L1 given larger - * batch sizes. - * 4 gas for 0 byte - * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33 - * 16 gas for non zero byte - * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87 - * This will need to be updated if calldata gas prices change - * Account for the transaction being unsigned - * Padding is added to account for lack of signature on transaction - * 1 byte for RLP V prefix - * 1 byte for V - * 1 byte for RLP R prefix - * 32 bytes for R - * 1 byte for RLP S prefix - * 32 bytes for S - * Total: 68 bytes of padding - * @param _data Unsigned RLP encoded tx, 6 elements - * @return Amount of L1 gas used for a transaction - */ - // solhint-enable max-line-length - function getL1GasUsed(bytes memory _data) public view returns (uint256) { - uint256 total = 0; - for (uint256 i = 0; i < _data.length; i++) { - if (_data[i] == 0) { - total += 4; - } else { - total += 16; - } - } - uint256 unsigned = total + overhead; - return unsigned + (68 * 16); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol deleted file mode 100644 index 95b88e9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -interface IScrollL1GasPriceOracle { - /********** - * Events * - **********/ - - /// @notice Emitted when current fee overhead is updated. - /// @param overhead The current fee overhead updated. - event OverheadUpdated(uint256 overhead); - - /// @notice Emitted when current fee scalar is updated. - /// @param scalar The current fee scalar updated. - event ScalarUpdated(uint256 scalar); - - /// @notice Emitted when current l1 base fee is updated. - /// @param l1BaseFee The current l1 base fee updated. - event L1BaseFeeUpdated(uint256 l1BaseFee); - - /************************* - * Public View Functions * - *************************/ - - /// @notice Return the current l1 fee overhead. - function overhead() external view returns (uint256); - - /// @notice Return the current l1 fee scalar. - function scalar() external view returns (uint256); - - /// @notice Return the latest known l1 base fee. - function l1BaseFee() external view returns (uint256); - - /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input - /// transaction, the current L1 base fee, and the various dynamic parameters. - /// @param data Unsigned fully RLP-encoded transaction to get the L1 fee for. - /// @return L1 fee that should be paid for the tx - function getL1Fee(bytes memory data) external view returns (uint256); - - /// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which - /// represents the per-transaction gas overhead of posting the transaction and state - /// roots to L1. Adds 74 bytes of padding to account for the fact that the input does - /// not have a signature. - /// @param data Unsigned fully RLP-encoded transaction to get the L1 gas for. - /// @return Amount of L1 gas used to publish the transaction. - function getL1GasUsed(bytes memory data) external view returns (uint256); - - /***************************** - * Public Mutating Functions * - *****************************/ - - /// @notice Allows whitelisted caller to modify the l1 base fee. - /// @param _l1BaseFee New l1 base fee. - function setL1BaseFee(uint256 _l1BaseFee) external; -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol deleted file mode 100644 index 761fac9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol +++ /dev/null @@ -1,337 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @dev A library for working with mutable byte buffers in Solidity. - * - * Byte buffers are mutable and expandable, and provide a variety of primitives - * for writing to them. At any time you can fetch a bytes object containing the - * current contents of the buffer. The bytes object should not be stored between - * operations, as it may change due to resizing of the buffer. - */ -library BufferChainlink { - /** - * @dev Represents a mutable buffer. Buffers have a current value (buf) and - * a capacity. The capacity may be longer than the current value, in - * which case it can be extended without the need to allocate more memory. - */ - struct buffer { - bytes buf; - uint256 capacity; - } - - /** - * @dev Initializes a buffer with an initial capacity. - * @param buf The buffer to initialize. - * @param capacity The number of bytes of space to allocate the buffer. - * @return The buffer, for chaining. - */ - function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) { - if (capacity % 32 != 0) { - capacity += 32 - (capacity % 32); - } - // Allocate space for the buffer data - buf.capacity = capacity; - assembly { - let ptr := mload(0x40) - mstore(buf, ptr) - mstore(ptr, 0) - mstore(0x40, add(32, add(ptr, capacity))) - } - return buf; - } - - /** - * @dev Initializes a new buffer from an existing bytes object. - * Changes to the buffer may mutate the original value. - * @param b The bytes object to initialize the buffer with. - * @return A new buffer. - */ - function fromBytes(bytes memory b) internal pure returns (buffer memory) { - buffer memory buf; - buf.buf = b; - buf.capacity = b.length; - return buf; - } - - function resize(buffer memory buf, uint256 capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); - } - - function max(uint256 a, uint256 b) private pure returns (uint256) { - if (a > b) { - return a; - } - return b; - } - - /** - * @dev Sets buffer length to 0. - * @param buf The buffer to truncate. - * @return The original buffer, for chaining.. - */ - function truncate(buffer memory buf) internal pure returns (buffer memory) { - assembly { - let bufptr := mload(buf) - mstore(bufptr, 0) - } - return buf; - } - - /** - * @dev Writes a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The start offset to write to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function write( - buffer memory buf, - uint256 off, - bytes memory data, - uint256 len - ) internal pure returns (buffer memory) { - require(len <= data.length); - - if (off + len > buf.capacity) { - resize(buf, max(buf.capacity, len + off) * 2); - } - - uint256 dest; - uint256 src; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + offset + sizeof(buffer length) - dest := add(add(bufptr, 32), off) - // Update buffer length if we're extending it - if gt(add(len, off), buflen) { - mstore(bufptr, add(len, off)) - } - src := add(data, 32) - } - - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - unchecked { - uint256 mask = (256**(32 - len)) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - } - - return buf; - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function append( - buffer memory buf, - bytes memory data, - uint256 len - ) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, len); - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, data.length); - } - - /** - * @dev Writes a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write the byte at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeUint8( - buffer memory buf, - uint256 off, - uint8 data - ) internal pure returns (buffer memory) { - if (off >= buf.capacity) { - resize(buf, buf.capacity * 2); - } - - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + sizeof(buffer length) + off - let dest := add(add(bufptr, off), 32) - mstore8(dest, data) - // Update buffer length if we extended it - if eq(off, buflen) { - mstore(bufptr, add(buflen, 1)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) { - return writeUint8(buf, buf.buf.length, data); - } - - /** - * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (left-aligned). - * @return The original buffer, for chaining. - */ - function write( - buffer memory buf, - uint256 off, - bytes32 data, - uint256 len - ) private pure returns (buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - unchecked { - uint256 mask = (256**len) - 1; - // Right-align data - data = data >> (8 * (32 - len)); - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + off + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - } - return buf; - } - - /** - * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeBytes20( - buffer memory buf, - uint256 off, - bytes20 data - ) internal pure returns (buffer memory) { - return write(buf, off, bytes32(data), 20); - } - - /** - * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chhaining. - */ - function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, bytes32(data), 20); - } - - /** - * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, 32); - } - - /** - * @dev Writes an integer to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (right-aligned). - * @return The original buffer, for chaining. - */ - function writeInt( - buffer memory buf, - uint256 off, - uint256 data, - uint256 len - ) private pure returns (buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint256 mask = (256**len) - 1; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + off + sizeof(buffer length) + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function appendInt( - buffer memory buf, - uint256 data, - uint256 len - ) internal pure returns (buffer memory) { - return writeInt(buf, buf.buf.length, data, len); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol deleted file mode 100644 index 5ee0cec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.19; - -import {BufferChainlink} from "./BufferChainlink.sol"; - -library CBORChainlink { - using BufferChainlink for BufferChainlink.buffer; - - uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; - uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; - uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; - uint8 private constant MAJOR_TYPE_TAG = 6; - uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - - uint8 private constant TAG_TYPE_BIGNUM = 2; - uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; - - function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { - if(value <= 23) { - buf.appendUint8(uint8((major << 5) | value)); - } else if (value <= 0xFF) { - buf.appendUint8(uint8((major << 5) | 24)); - buf.appendInt(value, 1); - } else if (value <= 0xFFFF) { - buf.appendUint8(uint8((major << 5) | 25)); - buf.appendInt(value, 2); - } else if (value <= 0xFFFFFFFF) { - buf.appendUint8(uint8((major << 5) | 26)); - buf.appendInt(value, 4); - } else { - buf.appendUint8(uint8((major << 5) | 27)); - buf.appendInt(value, 8); - } - } - - function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { - buf.appendUint8(uint8((major << 5) | 31)); - } - - function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { - if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, value); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); - } - } - - function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { - if(value < -0x10000000000000000) { - encodeSignedBigNum(buf, value); - } else if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, uint(value)); - } else if(value >= 0) { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value))); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value))); - } - } - - function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); - buf.append(value); - } - - function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); - encodeBytes(buf, abi.encode(value)); - } - - function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); - encodeBytes(buf, abi.encode(uint256(-1 - input))); - } - - function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); - buf.append(bytes(value)); - } - - function startArray(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); - } - - function startMap(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); - } - - function endSequence(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol deleted file mode 100644 index d375ca4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/DateTime.sol +++ /dev/null @@ -1,254 +0,0 @@ -// SPDX-License-Identifier: MIT - -// sourced from https://github.com/pipermerriam/ethereum-datetime - -pragma solidity ^0.8.0; - -library DateTime { - /* - * Date and Time utilities for ethereum contracts - * - */ - struct _DateTime { - uint16 year; - uint8 month; - uint8 day; - uint8 hour; - uint8 minute; - uint8 second; - uint8 weekday; - } - - uint256 constant DAY_IN_SECONDS = 86400; - uint256 constant YEAR_IN_SECONDS = 31536000; - uint256 constant LEAP_YEAR_IN_SECONDS = 31622400; - - uint256 constant HOUR_IN_SECONDS = 3600; - uint256 constant MINUTE_IN_SECONDS = 60; - - uint16 constant ORIGIN_YEAR = 1970; - - function isLeapYear(uint16 year) internal pure returns (bool) { - if (year % 4 != 0) { - return false; - } - if (year % 100 != 0) { - return true; - } - if (year % 400 != 0) { - return false; - } - return true; - } - - function leapYearsBefore(uint256 year) internal pure returns (uint256) { - year -= 1; - return year / 4 - year / 100 + year / 400; - } - - function getDaysInMonth(uint8 month, uint16 year) - internal - pure - returns (uint8) - { - if ( - month == 1 || - month == 3 || - month == 5 || - month == 7 || - month == 8 || - month == 10 || - month == 12 - ) { - return 31; - } else if (month == 4 || month == 6 || month == 9 || month == 11) { - return 30; - } else if (isLeapYear(year)) { - return 29; - } else { - return 28; - } - } - - function parseTimestamp(uint256 timestamp) - internal - pure - returns (_DateTime memory dt) - { - uint256 secondsAccountedFor = 0; - uint256 buf; - uint8 i; - - // Year - dt.year = getYear(timestamp); - buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); - - secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; - secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); - - // Month - uint256 secondsInMonth; - for (i = 1; i <= 12; i++) { - secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); - if (secondsInMonth + secondsAccountedFor > timestamp) { - dt.month = i; - break; - } - secondsAccountedFor += secondsInMonth; - } - - // Day - for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { - if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { - dt.day = i; - break; - } - secondsAccountedFor += DAY_IN_SECONDS; - } - - // Hour - dt.hour = getHour(timestamp); - - // Minute - dt.minute = getMinute(timestamp); - - // Second - dt.second = getSecond(timestamp); - - // Day of week. - dt.weekday = getWeekday(timestamp); - } - - function getYear(uint256 timestamp) internal pure returns (uint16) { - uint256 secondsAccountedFor = 0; - uint16 year; - uint256 numLeapYears; - - // Year - year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); - numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); - - secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; - secondsAccountedFor += - YEAR_IN_SECONDS * - (year - ORIGIN_YEAR - numLeapYears); - - while (secondsAccountedFor > timestamp) { - if (isLeapYear(uint16(year - 1))) { - secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; - } else { - secondsAccountedFor -= YEAR_IN_SECONDS; - } - year -= 1; - } - return year; - } - - function getMonth(uint256 timestamp) internal pure returns (uint8) { - return parseTimestamp(timestamp).month; - } - - function getDay(uint256 timestamp) internal pure returns (uint8) { - return parseTimestamp(timestamp).day; - } - - function getHour(uint256 timestamp) internal pure returns (uint8) { - return uint8((timestamp / 60 / 60) % 24); - } - - function getMinute(uint256 timestamp) internal pure returns (uint8) { - return uint8((timestamp / 60) % 60); - } - - function getSecond(uint256 timestamp) internal pure returns (uint8) { - return uint8(timestamp % 60); - } - - function getWeekday(uint256 timestamp) internal pure returns (uint8) { - return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); - } - - function toTimestamp( - uint16 year, - uint8 month, - uint8 day - ) internal pure returns (uint256 timestamp) { - return toTimestamp(year, month, day, 0, 0, 0); - } - - function toTimestamp( - uint16 year, - uint8 month, - uint8 day, - uint8 hour - ) internal pure returns (uint256 timestamp) { - return toTimestamp(year, month, day, hour, 0, 0); - } - - function toTimestamp( - uint16 year, - uint8 month, - uint8 day, - uint8 hour, - uint8 minute - ) internal pure returns (uint256 timestamp) { - return toTimestamp(year, month, day, hour, minute, 0); - } - - function toTimestamp( - uint16 year, - uint8 month, - uint8 day, - uint8 hour, - uint8 minute, - uint8 second - ) internal pure returns (uint256 timestamp) { - uint16 i; - - // Year - for (i = ORIGIN_YEAR; i < year; i++) { - if (isLeapYear(i)) { - timestamp += LEAP_YEAR_IN_SECONDS; - } else { - timestamp += YEAR_IN_SECONDS; - } - } - - // Month - uint8[12] memory monthDayCounts; - monthDayCounts[0] = 31; - if (isLeapYear(year)) { - monthDayCounts[1] = 29; - } else { - monthDayCounts[1] = 28; - } - monthDayCounts[2] = 31; - monthDayCounts[3] = 30; - monthDayCounts[4] = 31; - monthDayCounts[5] = 30; - monthDayCounts[6] = 31; - monthDayCounts[7] = 31; - monthDayCounts[8] = 30; - monthDayCounts[9] = 31; - monthDayCounts[10] = 30; - monthDayCounts[11] = 31; - - for (i = 1; i < month; i++) { - timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1]; - } - - // Day - timestamp += DAY_IN_SECONDS * (day - 1); - - // Hour - timestamp += HOUR_IN_SECONDS * (hour); - - // Minute - timestamp += MINUTE_IN_SECONDS * (minute); - - // Second - timestamp += second; - - return timestamp; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol deleted file mode 100644 index eb92ced..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -abstract contract ENSResolver { - function addr(bytes32 node) public view virtual returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol deleted file mode 100644 index 9af4bf8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/IERC165.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -interface IERC165 { - /// @notice Query if a contract implements an interface - /// @param interfaceID The interface identifier, as specified in ERC-165 - /// @dev Interface identification is specified in ERC-165. This function - /// uses less than 30,000 gas. - /// @return `true` if the contract implements `interfaceID` and - /// `interfaceID` is not 0xffffffff, `false` otherwise - function supportsInterface(bytes4 interfaceID) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol deleted file mode 100644 index ae8b6af..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockOVMCrossDomainMessenger.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.7.6 <0.9.0; - -import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; - -/** - * @title iOVM_CrossDomainMessenger - */ -interface iOVM_CrossDomainMessenger { - /********** - * Events * - **********/ - - event SentMessage(bytes message); - event RelayedMessage(bytes32 msgHash); - event FailedRelayedMessage(bytes32 msgHash); - - /************* - * Variables * - *************/ - - function xDomainMessageSender() external view returns (address); - - /******************** - * Public Functions * - ********************/ - - /** - * Sends a cross domain message to the target messenger. - * @param _target Target contract address. - * @param _message Message to send to the target. - * @param _gasLimit Gas limit for the provided message. - */ - function sendMessage( - address _target, - bytes calldata _message, - uint32 _gasLimit - ) external; -} - -contract MockOVMCrossDomainMessenger is iOVM_CrossDomainMessenger{ - address internal mockMessageSender; - - constructor(address sender) { - mockMessageSender = sender; - } - - function xDomainMessageSender() external view override returns (address) { - return mockMessageSender; - } - - function _setMockMessageSender(address sender) external { - mockMessageSender = sender; - } - - /******************** - * Public Functions * - ********************/ - - /** - * Sends a cross domain message to the target messenger. - * @param _target Target contract address. - * @param _message Message to send to the target. - * @param _gasLimit Gas limit for the provided message. - */ - function sendMessage( - address _target, - bytes calldata _message, - uint32 _gasLimit - ) external override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol deleted file mode 100644 index bb5390b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MockScrollCrossDomainMessenger.sol +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -import "./openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; - -/// sourced from: https://github.com/scroll-tech/scroll/blob/develop/contracts/src/libraries/IScrollMessenger.sol -interface IScrollMessenger { - /// ********** - /// * Events * - /// ********** - - /// @notice Emitted when a cross domain message is sent. - /// @param sender The address of the sender who initiates the message. - /// @param target The address of target contract to call. - /// @param value The amount of value passed to the target contract. - /// @param messageNonce The nonce of the message. - /// @param gasLimit The optional gas limit passed to L1 or L2. - /// @param message The calldata passed to the target contract. - event SentMessage( - address indexed sender, - address indexed target, - uint256 value, - uint256 messageNonce, - uint256 gasLimit, - bytes message - ); - - /// @notice Emitted when a cross domain message is relayed successfully. - /// @param messageHash The hash of the message. - event RelayedMessage(bytes32 indexed messageHash); - - /// @notice Emitted when a cross domain message is failed to relay. - /// @param messageHash The hash of the message. - event FailedRelayedMessage(bytes32 indexed messageHash); - - /// ************************* - /// * Public View Functions * - /// ************************* - - /// @notice Return the sender of a cross domain message. - function xDomainMessageSender() external view returns (address); - - /// ***************************** - /// * Public Mutating Functions * - /// ***************************** - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param target The address of account who receive the message. - /// @param value The amount of ether passed when call target contract. - /// @param message The content of the message. - /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. - function sendMessage(address target, uint256 value, bytes calldata message, uint256 gasLimit) external payable; - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param target The address of account who receive the message. - /// @param value The amount of ether passed when call target contract. - /// @param message The content of the message. - /// @param gasLimit Gas limit required to complete the message relay on corresponding chain. - /// @param refundAddress The address of account who will receive the refunded fee. - function sendMessage( - address target, - uint256 value, - bytes calldata message, - uint256 gasLimit, - address refundAddress - ) external payable; -} - -contract MockScrollCrossDomainMessenger is IScrollMessenger { - address internal mockMessageSender; - - constructor(address sender) { - mockMessageSender = sender; - } - - function xDomainMessageSender() external view override returns (address) { - return mockMessageSender; - } - - function _setMockMessageSender(address sender) external { - mockMessageSender = sender; - } - - /// ***************************** - /// * Public Mutating Functions * - /// ***************************** - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param _target The address of account who receive the message. - /// @param _message The content of the message. - function sendMessage(address _target, uint256, bytes calldata _message, uint256) external payable override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } - - /// @notice Send cross chain message from L1 to L2 or L2 to L1. - /// @param _target The address of account who receive the message. - /// @param _message The content of the message. - function sendMessage(address _target, uint256, bytes calldata _message, uint256, address) external payable override { - Address.functionCall(_target, _message, "sendMessage reverted"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol deleted file mode 100644 index 15a7d2f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/MultiSend.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.7.0 <0.9.0; - -/// @title Multi Send - Allows to batch multiple transactions into one. -/// @author Nick Dodson - -/// @author Gonçalo Sá - -/// @author Stefan George - -/// @author Richard Meissner - -contract MultiSend { - address private immutable multisendSingleton; - - constructor() { - multisendSingleton = address(this); - } - - /// @dev Sends multiple transactions and reverts all if one fails. - /// @param transactions Encoded transactions. Each transaction is encoded as a packed bytes of - /// operation as a uint8 with 0 for a call or 1 for a delegatecall (=> 1 byte), - /// to as a address (=> 20 bytes), - /// value as a uint256 (=> 32 bytes), - /// data length as a uint256 (=> 32 bytes), - /// data as bytes. - /// see abi.encodePacked for more information on packed encoding - /// @notice This method is payable as delegatecalls keep the msg.value from the previous call - /// If the calling method (e.g. execTransaction) received ETH this would revert otherwise - function multiSend(bytes memory transactions) public payable { - require(address(this) != multisendSingleton, "MultiSend should only be called via delegatecall"); - // solhint-disable-next-line no-inline-assembly - assembly { - let length := mload(transactions) - let i := 0x20 - for { - // Pre block is not used in "while mode" - } lt(i, length) { - // Post block is not used in "while mode" - } { - // First byte of the data is the operation. - // We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a word). - // This will also zero out unused data. - let operation := shr(0xf8, mload(add(transactions, i))) - // We offset the load address by 1 byte (operation byte) - // We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data. - let to := shr(0x60, mload(add(transactions, add(i, 0x01)))) - // We offset the load address by 21 byte (operation byte + 20 address bytes) - let value := mload(add(transactions, add(i, 0x15))) - // We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes) - let dataLength := mload(add(transactions, add(i, 0x35))) - // We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data length bytes) - let data := add(transactions, add(i, 0x55)) - let success := 0 - switch operation - case 0 { - success := call(gas(), to, value, data, dataLength, 0, 0) - } - case 1 { - success := delegatecall(gas(), to, data, dataLength, 0, 0) - } - if eq(success, 0) { - revert(0, 0) - } - // Next entry starts at 85 byte + data length - i := add(i, add(0x55, dataLength)) - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol deleted file mode 100644 index 4a17bd9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/Strings.sol +++ /dev/null @@ -1,842 +0,0 @@ -// SPDX-License-Identifier: Apache 2.0 - -/* - * @title String & slice utility library for Solidity contracts. - * @author Nick Johnson - * - * @dev Functionality in this library is largely implemented using an - * abstraction called a 'slice'. A slice represents a part of a string - - * anything from the entire string to a single character, or even no - * characters at all (a 0-length slice). Since a slice only has to specify - * an offset and a length, copying and manipulating slices is a lot less - * expensive than copying and manipulating the strings they reference. - * - * To further reduce gas costs, most functions on slice that need to return - * a slice modify the original one instead of allocating a new one; for - * instance, `s.split(".")` will return the text up to the first '.', - * modifying s to only contain the remainder of the string after the '.'. - * In situations where you do not want to modify the original slice, you - * can make a copy first with `.copy()`, for example: - * `s.copy().split(".")`. Try and avoid using this idiom in loops; since - * Solidity has no memory management, it will result in allocating many - * short-lived slices that are later discarded. - * - * Functions that return two slices come in two versions: a non-allocating - * version that takes the second slice as an argument, modifying it in - * place, and an allocating version that allocates and returns the second - * slice; see `nextRune` for example. - * - * Functions that have to copy string data will return strings rather than - * slices; these can be cast back to slices for further processing if - * required. - * - * For convenience, some functions are provided with non-modifying - * variants that create a new slice and return both; for instance, - * `s.splitNew('.')` leaves s unmodified, and returns two values - * corresponding to the left and right parts of the string. - */ - -pragma solidity ^0.8.0; - -library strings { - struct slice { - uint256 _len; - uint256 _ptr; - } - - function memcpy( - uint256 dest, - uint256 src, - uint256 len - ) private pure { - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - uint256 mask = type(uint256).max; - if (len > 0) { - mask = 256**(32 - len) - 1; - } - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - } - - /* - * @dev Returns a slice containing the entire string. - * @param self The string to make a slice from. - * @return A newly allocated slice containing the entire string. - */ - function toSlice(string memory self) internal pure returns (slice memory) { - uint256 ptr; - assembly { - ptr := add(self, 0x20) - } - return slice(bytes(self).length, ptr); - } - - /* - * @dev Returns the length of a null-terminated bytes32 string. - * @param self The value to find the length of. - * @return The length of the string, from 0 to 32. - */ - function len(bytes32 self) internal pure returns (uint256) { - uint256 ret; - if (self == 0) return 0; - if (uint256(self) & type(uint128).max == 0) { - ret += 16; - self = bytes32(uint256(self) / 0x100000000000000000000000000000000); - } - if (uint256(self) & type(uint64).max == 0) { - ret += 8; - self = bytes32(uint256(self) / 0x10000000000000000); - } - if (uint256(self) & type(uint32).max == 0) { - ret += 4; - self = bytes32(uint256(self) / 0x100000000); - } - if (uint256(self) & type(uint16).max == 0) { - ret += 2; - self = bytes32(uint256(self) / 0x10000); - } - if (uint256(self) & type(uint8).max == 0) { - ret += 1; - } - return 32 - ret; - } - - /* - * @dev Returns a slice containing the entire bytes32, interpreted as a - * null-terminated utf-8 string. - * @param self The bytes32 value to convert to a slice. - * @return A new slice containing the value of the input argument up to the - * first null. - */ - function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { - // Allocate space for `self` in memory, copy it there, and point ret at it - assembly { - let ptr := mload(0x40) - mstore(0x40, add(ptr, 0x20)) - mstore(ptr, self) - mstore(add(ret, 0x20), ptr) - } - ret._len = len(self); - } - - /* - * @dev Returns a new slice containing the same data as the current slice. - * @param self The slice to copy. - * @return A new slice containing the same data as `self`. - */ - function copy(slice memory self) internal pure returns (slice memory) { - return slice(self._len, self._ptr); - } - - /* - * @dev Copies a slice to a new string. - * @param self The slice to copy. - * @return A newly allocated string containing the slice's text. - */ - function toString(slice memory self) internal pure returns (string memory) { - string memory ret = new string(self._len); - uint256 retptr; - assembly { - retptr := add(ret, 32) - } - - memcpy(retptr, self._ptr, self._len); - return ret; - } - - /* - * @dev Returns the length in runes of the slice. Note that this operation - * takes time proportional to the length of the slice; avoid using it - * in loops, and call `slice.empty()` if you only need to know whether - * the slice is empty or not. - * @param self The slice to operate on. - * @return The length of the slice in runes. - */ - function len(slice memory self) internal pure returns (uint256 l) { - // Starting at ptr-31 means the LSB will be the byte we care about - uint256 ptr = self._ptr - 31; - uint256 end = ptr + self._len; - for (l = 0; ptr < end; l++) { - uint8 b; - assembly { - b := and(mload(ptr), 0xFF) - } - if (b < 0x80) { - ptr += 1; - } else if (b < 0xE0) { - ptr += 2; - } else if (b < 0xF0) { - ptr += 3; - } else if (b < 0xF8) { - ptr += 4; - } else if (b < 0xFC) { - ptr += 5; - } else { - ptr += 6; - } - } - } - - /* - * @dev Returns true if the slice is empty (has a length of 0). - * @param self The slice to operate on. - * @return True if the slice is empty, False otherwise. - */ - function empty(slice memory self) internal pure returns (bool) { - return self._len == 0; - } - - /* - * @dev Returns a positive number if `other` comes lexicographically after - * `self`, a negative number if it comes before, or zero if the - * contents of the two slices are equal. Comparison is done per-rune, - * on unicode codepoints. - * @param self The first slice to compare. - * @param other The second slice to compare. - * @return The result of the comparison. - */ - function compare(slice memory self, slice memory other) - internal - pure - returns (int256) - { - uint256 shortest = self._len; - if (other._len < self._len) shortest = other._len; - - uint256 selfptr = self._ptr; - uint256 otherptr = other._ptr; - for (uint256 idx = 0; idx < shortest; idx += 32) { - uint256 a; - uint256 b; - assembly { - a := mload(selfptr) - b := mload(otherptr) - } - if (a != b) { - // Mask out irrelevant bytes and check again - uint256 mask = type(uint256).max; // 0xffff... - if (shortest < 32) { - mask = ~(2**(8 * (32 - shortest + idx)) - 1); - } - unchecked { - uint256 diff = (a & mask) - (b & mask); - if (diff != 0) return int256(diff); - } - } - selfptr += 32; - otherptr += 32; - } - return int256(self._len) - int256(other._len); - } - - /* - * @dev Returns true if the two slices contain the same text. - * @param self The first slice to compare. - * @param self The second slice to compare. - * @return True if the slices are equal, false otherwise. - */ - function equals(slice memory self, slice memory other) - internal - pure - returns (bool) - { - return compare(self, other) == 0; - } - - /* - * @dev Extracts the first rune in the slice into `rune`, advancing the - * slice to point to the next rune and returning `self`. - * @param self The slice to operate on. - * @param rune The slice that will contain the first rune. - * @return `rune`. - */ - function nextRune(slice memory self, slice memory rune) - internal - pure - returns (slice memory) - { - rune._ptr = self._ptr; - - if (self._len == 0) { - rune._len = 0; - return rune; - } - - uint256 l; - uint256 b; - // Load the first byte of the rune into the LSBs of b - assembly { - b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) - } - if (b < 0x80) { - l = 1; - } else if (b < 0xE0) { - l = 2; - } else if (b < 0xF0) { - l = 3; - } else { - l = 4; - } - - // Check for truncated codepoints - if (l > self._len) { - rune._len = self._len; - self._ptr += self._len; - self._len = 0; - return rune; - } - - self._ptr += l; - self._len -= l; - rune._len = l; - return rune; - } - - /* - * @dev Returns the first rune in the slice, advancing the slice to point - * to the next rune. - * @param self The slice to operate on. - * @return A slice containing only the first rune from `self`. - */ - function nextRune(slice memory self) - internal - pure - returns (slice memory ret) - { - nextRune(self, ret); - } - - /* - * @dev Returns the number of the first codepoint in the slice. - * @param self The slice to operate on. - * @return The number of the first codepoint in the slice. - */ - function ord(slice memory self) internal pure returns (uint256 ret) { - if (self._len == 0) { - return 0; - } - - uint256 word; - uint256 length; - uint256 divisor = 2**248; - - // Load the rune into the MSBs of b - assembly { - word := mload(mload(add(self, 32))) - } - uint256 b = word / divisor; - if (b < 0x80) { - ret = b; - length = 1; - } else if (b < 0xE0) { - ret = b & 0x1F; - length = 2; - } else if (b < 0xF0) { - ret = b & 0x0F; - length = 3; - } else { - ret = b & 0x07; - length = 4; - } - - // Check for truncated codepoints - if (length > self._len) { - return 0; - } - - for (uint256 i = 1; i < length; i++) { - divisor = divisor / 256; - b = (word / divisor) & 0xFF; - if (b & 0xC0 != 0x80) { - // Invalid UTF-8 sequence - return 0; - } - ret = (ret * 64) | (b & 0x3F); - } - - return ret; - } - - /* - * @dev Returns the keccak-256 hash of the slice. - * @param self The slice to hash. - * @return The hash of the slice. - */ - function keccak(slice memory self) internal pure returns (bytes32 ret) { - assembly { - ret := keccak256(mload(add(self, 32)), mload(self)) - } - } - - /* - * @dev Returns true if `self` starts with `needle`. - * @param self The slice to operate on. - * @param needle The slice to search for. - * @return True if the slice starts with the provided text, false otherwise. - */ - function startsWith(slice memory self, slice memory needle) - internal - pure - returns (bool) - { - if (self._len < needle._len) { - return false; - } - - if (self._ptr == needle._ptr) { - return true; - } - - bool equal; - assembly { - let length := mload(needle) - let selfptr := mload(add(self, 0x20)) - let needleptr := mload(add(needle, 0x20)) - equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) - } - return equal; - } - - /* - * @dev If `self` starts with `needle`, `needle` is removed from the - * beginning of `self`. Otherwise, `self` is unmodified. - * @param self The slice to operate on. - * @param needle The slice to search for. - * @return `self` - */ - function beyond(slice memory self, slice memory needle) - internal - pure - returns (slice memory) - { - if (self._len < needle._len) { - return self; - } - - bool equal = true; - if (self._ptr != needle._ptr) { - assembly { - let length := mload(needle) - let selfptr := mload(add(self, 0x20)) - let needleptr := mload(add(needle, 0x20)) - equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) - } - } - - if (equal) { - self._len -= needle._len; - self._ptr += needle._len; - } - - return self; - } - - /* - * @dev Returns true if the slice ends with `needle`. - * @param self The slice to operate on. - * @param needle The slice to search for. - * @return True if the slice starts with the provided text, false otherwise. - */ - function endsWith(slice memory self, slice memory needle) - internal - pure - returns (bool) - { - if (self._len < needle._len) { - return false; - } - - uint256 selfptr = self._ptr + self._len - needle._len; - - if (selfptr == needle._ptr) { - return true; - } - - bool equal; - assembly { - let length := mload(needle) - let needleptr := mload(add(needle, 0x20)) - equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) - } - - return equal; - } - - /* - * @dev If `self` ends with `needle`, `needle` is removed from the - * end of `self`. Otherwise, `self` is unmodified. - * @param self The slice to operate on. - * @param needle The slice to search for. - * @return `self` - */ - function until(slice memory self, slice memory needle) - internal - pure - returns (slice memory) - { - if (self._len < needle._len) { - return self; - } - - uint256 selfptr = self._ptr + self._len - needle._len; - bool equal = true; - if (selfptr != needle._ptr) { - assembly { - let length := mload(needle) - let needleptr := mload(add(needle, 0x20)) - equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) - } - } - - if (equal) { - self._len -= needle._len; - } - - return self; - } - - // Returns the memory address of the first byte of the first occurrence of - // `needle` in `self`, or the first byte after `self` if not found. - function findPtr( - uint256 selflen, - uint256 selfptr, - uint256 needlelen, - uint256 needleptr - ) private pure returns (uint256) { - uint256 ptr = selfptr; - uint256 idx; - - if (needlelen <= selflen) { - if (needlelen <= 32) { - bytes32 mask; - if (needlelen > 0) { - mask = bytes32(~(2**(8 * (32 - needlelen)) - 1)); - } - - bytes32 needledata; - assembly { - needledata := and(mload(needleptr), mask) - } - - uint256 end = selfptr + selflen - needlelen; - bytes32 ptrdata; - assembly { - ptrdata := and(mload(ptr), mask) - } - - while (ptrdata != needledata) { - if (ptr >= end) return selfptr + selflen; - ptr++; - assembly { - ptrdata := and(mload(ptr), mask) - } - } - return ptr; - } else { - // For long needles, use hashing - bytes32 hash; - assembly { - hash := keccak256(needleptr, needlelen) - } - - for (idx = 0; idx <= selflen - needlelen; idx++) { - bytes32 testHash; - assembly { - testHash := keccak256(ptr, needlelen) - } - if (hash == testHash) return ptr; - ptr += 1; - } - } - } - return selfptr + selflen; - } - - // Returns the memory address of the first byte after the last occurrence of - // `needle` in `self`, or the address of `self` if not found. - function rfindPtr( - uint256 selflen, - uint256 selfptr, - uint256 needlelen, - uint256 needleptr - ) private pure returns (uint256) { - uint256 ptr; - - if (needlelen <= selflen) { - if (needlelen <= 32) { - bytes32 mask; - if (needlelen > 0) { - mask = bytes32(~(2**(8 * (32 - needlelen)) - 1)); - } - - bytes32 needledata; - assembly { - needledata := and(mload(needleptr), mask) - } - - ptr = selfptr + selflen - needlelen; - bytes32 ptrdata; - assembly { - ptrdata := and(mload(ptr), mask) - } - - while (ptrdata != needledata) { - if (ptr <= selfptr) return selfptr; - ptr--; - assembly { - ptrdata := and(mload(ptr), mask) - } - } - return ptr + needlelen; - } else { - // For long needles, use hashing - bytes32 hash; - assembly { - hash := keccak256(needleptr, needlelen) - } - ptr = selfptr + (selflen - needlelen); - while (ptr >= selfptr) { - bytes32 testHash; - assembly { - testHash := keccak256(ptr, needlelen) - } - if (hash == testHash) return ptr + needlelen; - ptr -= 1; - } - } - } - return selfptr; - } - - /* - * @dev Modifies `self` to contain everything from the first occurrence of - * `needle` to the end of the slice. `self` is set to the empty slice - * if `needle` is not found. - * @param self The slice to search and modify. - * @param needle The text to search for. - * @return `self`. - */ - function find(slice memory self, slice memory needle) - internal - pure - returns (slice memory) - { - uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); - self._len -= ptr - self._ptr; - self._ptr = ptr; - return self; - } - - /* - * @dev Modifies `self` to contain the part of the string from the start of - * `self` to the end of the first occurrence of `needle`. If `needle` - * is not found, `self` is set to the empty slice. - * @param self The slice to search and modify. - * @param needle The text to search for. - * @return `self`. - */ - function rfind(slice memory self, slice memory needle) - internal - pure - returns (slice memory) - { - uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); - self._len = ptr - self._ptr; - return self; - } - - /* - * @dev Splits the slice, setting `self` to everything after the first - * occurrence of `needle`, and `token` to everything before it. If - * `needle` does not occur in `self`, `self` is set to the empty slice, - * and `token` is set to the entirety of `self`. - * @param self The slice to split. - * @param needle The text to search for in `self`. - * @param token An output parameter to which the first token is written. - * @return `token`. - */ - function split( - slice memory self, - slice memory needle, - slice memory token - ) internal pure returns (slice memory) { - uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); - token._ptr = self._ptr; - token._len = ptr - self._ptr; - if (ptr == self._ptr + self._len) { - // Not found - self._len = 0; - } else { - self._len -= token._len + needle._len; - self._ptr = ptr + needle._len; - } - return token; - } - - /* - * @dev Splits the slice, setting `self` to everything after the first - * occurrence of `needle`, and returning everything before it. If - * `needle` does not occur in `self`, `self` is set to the empty slice, - * and the entirety of `self` is returned. - * @param self The slice to split. - * @param needle The text to search for in `self`. - * @return The part of `self` up to the first occurrence of `delim`. - */ - function split(slice memory self, slice memory needle) - internal - pure - returns (slice memory token) - { - split(self, needle, token); - } - - /* - * @dev Splits the slice, setting `self` to everything before the last - * occurrence of `needle`, and `token` to everything after it. If - * `needle` does not occur in `self`, `self` is set to the empty slice, - * and `token` is set to the entirety of `self`. - * @param self The slice to split. - * @param needle The text to search for in `self`. - * @param token An output parameter to which the first token is written. - * @return `token`. - */ - function rsplit( - slice memory self, - slice memory needle, - slice memory token - ) internal pure returns (slice memory) { - uint256 ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); - token._ptr = ptr; - token._len = self._len - (ptr - self._ptr); - if (ptr == self._ptr) { - // Not found - self._len = 0; - } else { - self._len -= token._len + needle._len; - } - return token; - } - - /* - * @dev Splits the slice, setting `self` to everything before the last - * occurrence of `needle`, and returning everything after it. If - * `needle` does not occur in `self`, `self` is set to the empty slice, - * and the entirety of `self` is returned. - * @param self The slice to split. - * @param needle The text to search for in `self`. - * @return The part of `self` after the last occurrence of `delim`. - */ - function rsplit(slice memory self, slice memory needle) - internal - pure - returns (slice memory token) - { - rsplit(self, needle, token); - } - - /* - * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. - * @param self The slice to search. - * @param needle The text to search for in `self`. - * @return The number of occurrences of `needle` found in `self`. - */ - function count(slice memory self, slice memory needle) - internal - pure - returns (uint256 cnt) - { - uint256 ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + - needle._len; - while (ptr <= self._ptr + self._len) { - cnt++; - ptr = - findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + - needle._len; - } - } - - /* - * @dev Returns True if `self` contains `needle`. - * @param self The slice to search. - * @param needle The text to search for in `self`. - * @return True if `needle` is found in `self`, false otherwise. - */ - function contains(slice memory self, slice memory needle) - internal - pure - returns (bool) - { - return - rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; - } - - /* - * @dev Returns a newly allocated string containing the concatenation of - * `self` and `other`. - * @param self The first slice to concatenate. - * @param other The second slice to concatenate. - * @return The concatenation of the two strings. - */ - function concat(slice memory self, slice memory other) - internal - pure - returns (string memory) - { - string memory ret = new string(self._len + other._len); - uint256 retptr; - assembly { - retptr := add(ret, 32) - } - memcpy(retptr, self._ptr, self._len); - memcpy(retptr + self._len, other._ptr, other._len); - return ret; - } - - /* - * @dev Joins an array of slices, using `self` as a delimiter, returning a - * newly allocated string. - * @param self The delimiter to use. - * @param parts A list of slices to join. - * @return A newly allocated string containing all the slices in `parts`, - * joined with `self`. - */ - function join(slice memory self, slice[] memory parts) - internal - pure - returns (string memory) - { - if (parts.length == 0) return ""; - - uint256 length = self._len * (parts.length - 1); - for (uint256 i = 0; i < parts.length; i++) length += parts[i]._len; - - string memory ret = new string(length); - uint256 retptr; - assembly { - retptr := add(ret, 32) - } - - for (uint256 i = 0; i < parts.length; i++) { - memcpy(retptr, parts[i]._ptr, parts[i]._len); - retptr += parts[i]._len; - if (i < parts.length - 1) { - memcpy(retptr, self._ptr, self._len); - retptr += self._len; - } - } - - return ret; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol deleted file mode 100644 index 3d9e757..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IBridge.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// NOTICE: pragma change from original (^0.6.11) -pragma solidity ^0.8.0; - -interface IBridge { - event MessageDelivered( - uint256 indexed messageIndex, - bytes32 indexed beforeInboxAcc, - address inbox, - uint8 kind, - address sender, - bytes32 messageDataHash - ); - - function deliverMessageToInbox( - uint8 kind, - address sender, - bytes32 messageDataHash - ) external payable returns (uint256); - - function executeCall( - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (bool success, bytes memory returnData); - - // These are only callable by the admin - function setInbox(address inbox, bool enabled) external; - - function setOutbox(address inbox, bool enabled) external; - - // View functions - - function activeOutbox() external view returns (address); - - function allowedInboxes(address inbox) external view returns (bool); - - function allowedOutboxes(address outbox) external view returns (bool); - - function inboxAccs(uint256 index) external view returns (bytes32); - - function messageCount() external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol deleted file mode 100644 index b83fcec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// NOTICE: pragma change from original (^0.6.11) -pragma solidity ^0.8.0; - -import "./IBridge.sol"; -import "./IMessageProvider.sol"; - -interface IInbox is IMessageProvider { - function sendL2Message(bytes calldata messageData) external returns (uint256); - - function sendUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, - uint256 nonce, - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (uint256); - - function sendContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, - uint256 amount, - bytes calldata data - ) external returns (uint256); - - function sendL1FundedUnsignedTransaction( - uint256 maxGas, - uint256 gasPriceBid, - uint256 nonce, - address destAddr, - bytes calldata data - ) external payable returns (uint256); - - function sendL1FundedContractTransaction( - uint256 maxGas, - uint256 gasPriceBid, - address destAddr, - bytes calldata data - ) external payable returns (uint256); - - function createRetryableTicketNoRefundAliasRewrite( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes calldata data - ) external payable returns (uint256); - - function createRetryableTicket( - address destAddr, - uint256 arbTxCallValue, - uint256 maxSubmissionCost, - address submissionRefundAddress, - address valueRefundAddress, - uint256 maxGas, - uint256 gasPriceBid, - bytes calldata data - ) external payable returns (uint256); - - function depositEth(address destAddr) external payable returns (uint256); - - function depositEthRetryable( - address destAddr, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 maxGasPrice - ) external payable returns (uint256); - - function bridge() external view returns (IBridge); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol deleted file mode 100644 index a29dc65..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IMessageProvider.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// NOTICE: pragma change from original (^0.6.11) -pragma solidity ^0.8.0; - -interface IMessageProvider { - event InboxMessageDelivered(uint256 indexed messageNum, bytes data); - - event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol deleted file mode 100644 index dd3d544..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * Copyright 2019-2021, Offchain Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// NOTICE: pragma change from original (^0.6.11) -pragma solidity ^0.8.0; - -library AddressAliasHelper { - uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l1Address L2 address as viewed in msg.sender - /// @return l2Address the address in the L1 that triggered the tx to L2 - function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { - unchecked { - l2Address = address(uint160(l1Address) + offset); - } - } - - /// @notice Utility function that converts the msg.sender viewed in the L2 to the - /// address in the L1 that submitted a tx to the inbox - /// @param l2Address L2 address as viewed in msg.sender - /// @return l1Address the address in the L1 that triggered the tx to L2 - function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { - unchecked { - l1Address = address(uint160(l2Address) - offset); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol deleted file mode 100644 index 86a34b0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol +++ /dev/null @@ -1,861 +0,0 @@ -/** - ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. - ** Only one instance required on each chain. - **/ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable no-inline-assembly */ - -import "../interfaces/IAccount.sol"; -import "../interfaces/IPaymaster.sol"; -import "../interfaces/IEntryPoint.sol"; - -import "../utils/Exec.sol"; -import "./StakeManager.sol"; -import "./SenderCreator.sol"; -import "./Helpers.sol"; - -contract EntryPoint is IEntryPoint, StakeManager { - using UserOperationLib for UserOperation; - - SenderCreator private immutable senderCreator = new SenderCreator(); - - // internal value used during simulation: need to query aggregator. - address private constant SIMULATE_FIND_AGGREGATOR = address(1); - - // marker for inner call revert on out of gas - bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; - - uint256 private constant REVERT_REASON_MAX_LEN = 2048; - - /** - * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value - * in case of signature failure, instead of revert. - */ - uint256 public constant SIG_VALIDATION_FAILED = 1; - - /** - * compensate the caller's beneficiary address with the collected fees of all UserOperations. - * @param beneficiary the address to receive the fees - * @param amount amount to transfer. - */ - function _compensate(address payable beneficiary, uint256 amount) internal { - require(beneficiary != address(0), "AA90 invalid beneficiary"); - (bool success, ) = beneficiary.call{value: amount}(""); - require(success, "AA91 failed send to beneficiary"); - } - - /** - * execute a user op - * @param opIndex index into the opInfo array - * @param userOp the userOp to execute - * @param opInfo the opInfo filled by validatePrepayment for this userOp. - * @return collected the total amount this userOp paid. - */ - function _executeUserOp( - uint256 opIndex, - UserOperation calldata userOp, - UserOpInfo memory opInfo - ) private returns (uint256 collected) { - uint256 preGas = gasleft(); - bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); - - try this.innerHandleOp(userOp.callData, opInfo, context) returns ( - uint256 _actualGasCost - ) { - collected = _actualGasCost; - } catch { - bytes32 innerRevertCode; - assembly { - returndatacopy(0, 0, 32) - innerRevertCode := mload(0) - } - // handleOps was called with gas limit too low. abort entire bundle. - if (innerRevertCode == INNER_OUT_OF_GAS) { - //report paymaster, since if it is not deliberately caused by the bundler, - // it must be a revert caused by paymaster. - revert FailedOp(opIndex, "AA95 out of gas"); - } - - uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; - collected = _handlePostOp( - opIndex, - IPaymaster.PostOpMode.postOpReverted, - opInfo, - context, - actualGas - ); - } - } - - /** - * Execute a batch of UserOperations. - * no signature aggregator is used. - * if any account requires an aggregator (that is, it returned an aggregator when - * performing simulateValidation), then handleAggregatedOps() must be used instead. - * @param ops the operations to execute - * @param beneficiary the address to receive the fees - */ - function handleOps( - UserOperation[] calldata ops, - address payable beneficiary - ) public { - uint256 opslen = ops.length; - UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); - - unchecked { - for (uint256 i = 0; i < opslen; i++) { - UserOpInfo memory opInfo = opInfos[i]; - ( - uint256 validationData, - uint256 pmValidationData - ) = _validatePrepayment(i, ops[i], opInfo); - _validateAccountAndPaymasterValidationData( - i, - validationData, - pmValidationData, - address(0) - ); - } - - uint256 collected = 0; - - for (uint256 i = 0; i < opslen; i++) { - collected += _executeUserOp(i, ops[i], opInfos[i]); - } - - _compensate(beneficiary, collected); - } //unchecked - } - - /** - * Execute a batch of UserOperation with Aggregators - * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) - * @param beneficiary the address to receive the fees - */ - function handleAggregatedOps( - UserOpsPerAggregator[] calldata opsPerAggregator, - address payable beneficiary - ) public { - uint256 opasLen = opsPerAggregator.length; - uint256 totalOps = 0; - for (uint256 i = 0; i < opasLen; i++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[i]; - UserOperation[] calldata ops = opa.userOps; - IAggregator aggregator = opa.aggregator; - - //address(1) is special marker of "signature error" - require( - address(aggregator) != address(1), - "AA96 invalid aggregator" - ); - - if (address(aggregator) != address(0)) { - // solhint-disable-next-line no-empty-blocks - try aggregator.validateSignatures(ops, opa.signature) {} catch { - revert SignatureValidationFailed(address(aggregator)); - } - } - - totalOps += ops.length; - } - - UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps); - - uint256 opIndex = 0; - for (uint256 a = 0; a < opasLen; a++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[a]; - UserOperation[] calldata ops = opa.userOps; - IAggregator aggregator = opa.aggregator; - - uint256 opslen = ops.length; - for (uint256 i = 0; i < opslen; i++) { - UserOpInfo memory opInfo = opInfos[opIndex]; - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(opIndex, ops[i], opInfo); - _validateAccountAndPaymasterValidationData( - i, - validationData, - paymasterValidationData, - address(aggregator) - ); - opIndex++; - } - } - - uint256 collected = 0; - opIndex = 0; - for (uint256 a = 0; a < opasLen; a++) { - UserOpsPerAggregator calldata opa = opsPerAggregator[a]; - emit SignatureAggregatorChanged(address(opa.aggregator)); - UserOperation[] calldata ops = opa.userOps; - uint256 opslen = ops.length; - - for (uint256 i = 0; i < opslen; i++) { - collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); - opIndex++; - } - } - emit SignatureAggregatorChanged(address(0)); - - _compensate(beneficiary, collected); - } - - /// @inheritdoc IEntryPoint - function simulateHandleOp( - UserOperation calldata op, - address target, - bytes calldata targetCallData - ) external override { - UserOpInfo memory opInfo; - _simulationOnlyValidations(op); - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(0, op, opInfo); - ValidationData memory data = _intersectTimeRange( - validationData, - paymasterValidationData - ); - - numberMarker(); - uint256 paid = _executeUserOp(0, op, opInfo); - numberMarker(); - bool targetSuccess; - bytes memory targetResult; - if (target != address(0)) { - (targetSuccess, targetResult) = target.call(targetCallData); - } - revert ExecutionResult( - opInfo.preOpGas, - paid, - data.validAfter, - data.validUntil, - targetSuccess, - targetResult - ); - } - - // A memory copy of UserOp static fields only. - // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. - struct MemoryUserOp { - address sender; - uint256 nonce; - uint256 callGasLimit; - uint256 verificationGasLimit; - uint256 preVerificationGas; - address paymaster; - uint256 maxFeePerGas; - uint256 maxPriorityFeePerGas; - } - - struct UserOpInfo { - MemoryUserOp mUserOp; - bytes32 userOpHash; - uint256 prefund; - uint256 contextOffset; - uint256 preOpGas; - } - - /** - * inner function to handle a UserOperation. - * Must be declared "external" to open a call context, but it can only be called by handleOps. - */ - function innerHandleOp( - bytes memory callData, - UserOpInfo memory opInfo, - bytes calldata context - ) external returns (uint256 actualGasCost) { - uint256 preGas = gasleft(); - require(msg.sender == address(this), "AA92 internal call only"); - MemoryUserOp memory mUserOp = opInfo.mUserOp; - - uint256 callGasLimit = mUserOp.callGasLimit; - unchecked { - // handleOps was called with gas limit too low. abort entire bundle. - if ( - gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000 - ) { - assembly { - mstore(0, INNER_OUT_OF_GAS) - revert(0, 32) - } - } - } - - IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded; - if (callData.length > 0) { - bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); - if (!success) { - bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); - if (result.length > 0) { - emit UserOperationRevertReason( - opInfo.userOpHash, - mUserOp.sender, - mUserOp.nonce, - result - ); - } - mode = IPaymaster.PostOpMode.opReverted; - } - } - - unchecked { - uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; - //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp) - return _handlePostOp(0, mode, opInfo, context, actualGas); - } - } - - /** - * generate a request Id - unique identifier for this request. - * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. - */ - function getUserOpHash(UserOperation calldata userOp) - public - view - returns (bytes32) - { - return - keccak256(abi.encode(userOp.hash(), address(this), block.chainid)); - } - - /** - * copy general fields from userOp into the memory opInfo structure. - */ - function _copyUserOpToMemory( - UserOperation calldata userOp, - MemoryUserOp memory mUserOp - ) internal pure { - mUserOp.sender = userOp.sender; - mUserOp.nonce = userOp.nonce; - mUserOp.callGasLimit = userOp.callGasLimit; - mUserOp.verificationGasLimit = userOp.verificationGasLimit; - mUserOp.preVerificationGas = userOp.preVerificationGas; - mUserOp.maxFeePerGas = userOp.maxFeePerGas; - mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; - bytes calldata paymasterAndData = userOp.paymasterAndData; - if (paymasterAndData.length > 0) { - require( - paymasterAndData.length >= 20, - "AA93 invalid paymasterAndData" - ); - mUserOp.paymaster = address(bytes20(paymasterAndData[:20])); - } else { - mUserOp.paymaster = address(0); - } - } - - /** - * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. - * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. - * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. - * @param userOp the user operation to validate. - */ - function simulateValidation(UserOperation calldata userOp) external { - UserOpInfo memory outOpInfo; - - _simulationOnlyValidations(userOp); - ( - uint256 validationData, - uint256 paymasterValidationData - ) = _validatePrepayment(0, userOp, outOpInfo); - StakeInfo memory paymasterInfo = _getStakeInfo( - outOpInfo.mUserOp.paymaster - ); - StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender); - StakeInfo memory factoryInfo; - { - bytes calldata initCode = userOp.initCode; - address factory = initCode.length >= 20 - ? address(bytes20(initCode[0:20])) - : address(0); - factoryInfo = _getStakeInfo(factory); - } - - ValidationData memory data = _intersectTimeRange( - validationData, - paymasterValidationData - ); - address aggregator = data.aggregator; - bool sigFailed = aggregator == address(1); - ReturnInfo memory returnInfo = ReturnInfo( - outOpInfo.preOpGas, - outOpInfo.prefund, - sigFailed, - data.validAfter, - data.validUntil, - getMemoryBytesFromOffset(outOpInfo.contextOffset) - ); - - if (aggregator != address(0) && aggregator != address(1)) { - AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo( - aggregator, - _getStakeInfo(aggregator) - ); - revert ValidationResultWithAggregation( - returnInfo, - senderInfo, - factoryInfo, - paymasterInfo, - aggregatorInfo - ); - } - revert ValidationResult( - returnInfo, - senderInfo, - factoryInfo, - paymasterInfo - ); - } - - function _getRequiredPrefund(MemoryUserOp memory mUserOp) - internal - pure - returns (uint256 requiredPrefund) - { - unchecked { - //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call. - // our security model might call postOp eventually twice - uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1; - uint256 requiredGas = mUserOp.callGasLimit + - mUserOp.verificationGasLimit * - mul + - mUserOp.preVerificationGas; - - requiredPrefund = requiredGas * mUserOp.maxFeePerGas; - } - } - - // create the sender's contract if needed. - function _createSenderIfNeeded( - uint256 opIndex, - UserOpInfo memory opInfo, - bytes calldata initCode - ) internal { - if (initCode.length != 0) { - address sender = opInfo.mUserOp.sender; - if (sender.code.length != 0) - revert FailedOp(opIndex, "AA10 sender already constructed"); - address sender1 = senderCreator.createSender{ - gas: opInfo.mUserOp.verificationGasLimit - }(initCode); - if (sender1 == address(0)) - revert FailedOp(opIndex, "AA13 initCode failed or OOG"); - if (sender1 != sender) - revert FailedOp(opIndex, "AA14 initCode must return sender"); - if (sender1.code.length == 0) - revert FailedOp(opIndex, "AA15 initCode must create sender"); - address factory = address(bytes20(initCode[0:20])); - emit AccountDeployed( - opInfo.userOpHash, - sender, - factory, - opInfo.mUserOp.paymaster - ); - } - } - - /** - * Get counterfactual sender address. - * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. - * this method always revert, and returns the address in SenderAddressResult error - * @param initCode the constructor code to be passed into the UserOperation. - */ - function getSenderAddress(bytes calldata initCode) public { - revert SenderAddressResult(senderCreator.createSender(initCode)); - } - - function _simulationOnlyValidations(UserOperation calldata userOp) - internal - view - { - // solhint-disable-next-line no-empty-blocks - try - this._validateSenderAndPaymaster( - userOp.initCode, - userOp.sender, - userOp.paymasterAndData - ) - {} catch Error(string memory revertReason) { - if (bytes(revertReason).length != 0) { - revert FailedOp(0, revertReason); - } - } - } - - /** - * Called only during simulation. - * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution. - */ - function _validateSenderAndPaymaster( - bytes calldata initCode, - address sender, - bytes calldata paymasterAndData - ) external view { - if (initCode.length == 0 && sender.code.length == 0) { - // it would revert anyway. but give a meaningful message - revert("AA20 account not deployed"); - } - if (paymasterAndData.length >= 20) { - address paymaster = address(bytes20(paymasterAndData[0:20])); - if (paymaster.code.length == 0) { - // it would revert anyway. but give a meaningful message - revert("AA30 paymaster not deployed"); - } - } - // always revert - revert(""); - } - - /** - * call account.validateUserOp. - * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. - * decrement account's deposit if needed - */ - function _validateAccountPrepayment( - uint256 opIndex, - UserOperation calldata op, - UserOpInfo memory opInfo, - uint256 requiredPrefund - ) - internal - returns ( - uint256 gasUsedByValidateAccountPrepayment, - uint256 validationData - ) - { - unchecked { - uint256 preGas = gasleft(); - MemoryUserOp memory mUserOp = opInfo.mUserOp; - address sender = mUserOp.sender; - _createSenderIfNeeded(opIndex, opInfo, op.initCode); - address paymaster = mUserOp.paymaster; - numberMarker(); - uint256 missingAccountFunds = 0; - if (paymaster == address(0)) { - uint256 bal = balanceOf(sender); - missingAccountFunds = bal > requiredPrefund - ? 0 - : requiredPrefund - bal; - } - try - IAccount(sender).validateUserOp{ - gas: mUserOp.verificationGasLimit - }(op, opInfo.userOpHash, missingAccountFunds) - returns (uint256 _validationData) { - validationData = _validationData; - } catch Error(string memory revertReason) { - revert FailedOp( - opIndex, - string.concat("AA23 reverted: ", revertReason) - ); - } catch { - revert FailedOp(opIndex, "AA23 reverted (or OOG)"); - } - if (paymaster == address(0)) { - DepositInfo storage senderInfo = deposits[sender]; - uint256 deposit = senderInfo.deposit; - if (requiredPrefund > deposit) { - revert FailedOp(opIndex, "AA21 didn't pay prefund"); - } - senderInfo.deposit = uint112(deposit - requiredPrefund); - } - gasUsedByValidateAccountPrepayment = preGas - gasleft(); - } - } - - /** - * In case the request has a paymaster: - * Validate paymaster has enough deposit. - * Call paymaster.validatePaymasterUserOp. - * Revert with proper FailedOp in case paymaster reverts. - * Decrement paymaster's deposit - */ - function _validatePaymasterPrepayment( - uint256 opIndex, - UserOperation calldata op, - UserOpInfo memory opInfo, - uint256 requiredPreFund, - uint256 gasUsedByValidateAccountPrepayment - ) internal returns (bytes memory context, uint256 validationData) { - unchecked { - MemoryUserOp memory mUserOp = opInfo.mUserOp; - uint256 verificationGasLimit = mUserOp.verificationGasLimit; - require( - verificationGasLimit > gasUsedByValidateAccountPrepayment, - "AA41 too little verificationGas" - ); - uint256 gas = verificationGasLimit - - gasUsedByValidateAccountPrepayment; - - address paymaster = mUserOp.paymaster; - DepositInfo storage paymasterInfo = deposits[paymaster]; - uint256 deposit = paymasterInfo.deposit; - if (deposit < requiredPreFund) { - revert FailedOp(opIndex, "AA31 paymaster deposit too low"); - } - paymasterInfo.deposit = uint112(deposit - requiredPreFund); - try - IPaymaster(paymaster).validatePaymasterUserOp{gas: gas}( - op, - opInfo.userOpHash, - requiredPreFund - ) - returns (bytes memory _context, uint256 _validationData) { - context = _context; - validationData = _validationData; - } catch Error(string memory revertReason) { - revert FailedOp( - opIndex, - string.concat("AA33 reverted: ", revertReason) - ); - } catch { - revert FailedOp(opIndex, "AA33 reverted (or OOG)"); - } - } - } - - /** - * revert if either account validationData or paymaster validationData is expired - */ - function _validateAccountAndPaymasterValidationData( - uint256 opIndex, - uint256 validationData, - uint256 paymasterValidationData, - address expectedAggregator - ) internal view { - (address aggregator, bool outOfTimeRange) = _getValidationData( - validationData - ); - if (expectedAggregator != aggregator) { - revert FailedOp(opIndex, "AA24 signature error"); - } - if (outOfTimeRange) { - revert FailedOp(opIndex, "AA22 expired or not due"); - } - //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address. - // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation) - address pmAggregator; - (pmAggregator, outOfTimeRange) = _getValidationData( - paymasterValidationData - ); - if (pmAggregator != address(0)) { - revert FailedOp(opIndex, "AA34 signature error"); - } - if (outOfTimeRange) { - revert FailedOp(opIndex, "AA32 paymaster expired or not due"); - } - } - - function _getValidationData(uint256 validationData) - internal - view - returns (address aggregator, bool outOfTimeRange) - { - if (validationData == 0) { - return (address(0), false); - } - ValidationData memory data = _parseValidationData(validationData); - // solhint-disable-next-line not-rely-on-time - outOfTimeRange = - block.timestamp > data.validUntil || - block.timestamp < data.validAfter; - aggregator = data.aggregator; - } - - /** - * validate account and paymaster (if defined). - * also make sure total validation doesn't exceed verificationGasLimit - * this method is called off-chain (simulateValidation()) and on-chain (from handleOps) - * @param opIndex the index of this userOp into the "opInfos" array - * @param userOp the userOp to validate - */ - function _validatePrepayment( - uint256 opIndex, - UserOperation calldata userOp, - UserOpInfo memory outOpInfo - ) - private - returns (uint256 validationData, uint256 paymasterValidationData) - { - uint256 preGas = gasleft(); - MemoryUserOp memory mUserOp = outOpInfo.mUserOp; - _copyUserOpToMemory(userOp, mUserOp); - outOpInfo.userOpHash = getUserOpHash(userOp); - - // validate all numeric values in userOp are well below 128 bit, so they can safely be added - // and multiplied without causing overflow - uint256 maxGasValues = mUserOp.preVerificationGas | - mUserOp.verificationGasLimit | - mUserOp.callGasLimit | - userOp.maxFeePerGas | - userOp.maxPriorityFeePerGas; - require(maxGasValues <= type(uint120).max, "AA94 gas values overflow"); - - uint256 gasUsedByValidateAccountPrepayment; - uint256 requiredPreFund = _getRequiredPrefund(mUserOp); - ( - gasUsedByValidateAccountPrepayment, - validationData - ) = _validateAccountPrepayment( - opIndex, - userOp, - outOpInfo, - requiredPreFund - ); - //a "marker" where account opcode validation is done and paymaster opcode validation is about to start - // (used only by off-chain simulateValidation) - numberMarker(); - - bytes memory context; - if (mUserOp.paymaster != address(0)) { - (context, paymasterValidationData) = _validatePaymasterPrepayment( - opIndex, - userOp, - outOpInfo, - requiredPreFund, - gasUsedByValidateAccountPrepayment - ); - } - unchecked { - uint256 gasUsed = preGas - gasleft(); - - if (userOp.verificationGasLimit < gasUsed) { - revert FailedOp(opIndex, "AA40 over verificationGasLimit"); - } - outOpInfo.prefund = requiredPreFund; - outOpInfo.contextOffset = getOffsetOfMemoryBytes(context); - outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas; - } - } - - /** - * process post-operation. - * called just after the callData is executed. - * if a paymaster is defined and its validation returned a non-empty context, its postOp is called. - * the excess amount is refunded to the account (or paymaster - if it was used in the request) - * @param opIndex index in the batch - * @param mode - whether is called from innerHandleOp, or outside (postOpReverted) - * @param opInfo userOp fields and info collected during validation - * @param context the context returned in validatePaymasterUserOp - * @param actualGas the gas used so far by this user operation - */ - function _handlePostOp( - uint256 opIndex, - IPaymaster.PostOpMode mode, - UserOpInfo memory opInfo, - bytes memory context, - uint256 actualGas - ) private returns (uint256 actualGasCost) { - uint256 preGas = gasleft(); - unchecked { - address refundAddress; - MemoryUserOp memory mUserOp = opInfo.mUserOp; - uint256 gasPrice = getUserOpGasPrice(mUserOp); - - address paymaster = mUserOp.paymaster; - if (paymaster == address(0)) { - refundAddress = mUserOp.sender; - } else { - refundAddress = paymaster; - if (context.length > 0) { - actualGasCost = actualGas * gasPrice; - if (mode != IPaymaster.PostOpMode.postOpReverted) { - IPaymaster(paymaster).postOp{ - gas: mUserOp.verificationGasLimit - }(mode, context, actualGasCost); - } else { - // solhint-disable-next-line no-empty-blocks - try - IPaymaster(paymaster).postOp{ - gas: mUserOp.verificationGasLimit - }(mode, context, actualGasCost) - {} catch Error(string memory reason) { - revert FailedOp( - opIndex, - string.concat("AA50 postOp reverted: ", reason) - ); - } catch { - revert FailedOp(opIndex, "AA50 postOp revert"); - } - } - } - } - actualGas += preGas - gasleft(); - actualGasCost = actualGas * gasPrice; - if (opInfo.prefund < actualGasCost) { - revert FailedOp(opIndex, "AA51 prefund below actualGasCost"); - } - uint256 refund = opInfo.prefund - actualGasCost; - _incrementDeposit(refundAddress, refund); - bool success = mode == IPaymaster.PostOpMode.opSucceeded; - emit UserOperationEvent( - opInfo.userOpHash, - mUserOp.sender, - mUserOp.paymaster, - mUserOp.nonce, - success, - actualGasCost, - actualGas - ); - } // unchecked - } - - /** - * the gas price this UserOp agrees to pay. - * relayer/block builder might submit the TX with higher priorityFee, but the user should not - */ - function getUserOpGasPrice(MemoryUserOp memory mUserOp) - internal - view - returns (uint256) - { - unchecked { - uint256 maxFeePerGas = mUserOp.maxFeePerGas; - uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; - if (maxFeePerGas == maxPriorityFeePerGas) { - //legacy mode (for networks that don't support basefee opcode) - return maxFeePerGas; - } - return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); - } - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } - - function getOffsetOfMemoryBytes(bytes memory data) - internal - pure - returns (uint256 offset) - { - assembly { - offset := data - } - } - - function getMemoryBytesFromOffset(uint256 offset) - internal - pure - returns (bytes memory data) - { - assembly { - data := offset - } - } - - //place the NUMBER opcode in the code. - // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the - // account and paymaster. - function numberMarker() internal view { - assembly { - mstore(0, number()) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol deleted file mode 100644 index 71a6dc3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/** - * returned data from validateUserOp. - * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` - * @param aggregator - address(0) - the account validated the signature by itself. - * address(1) - the account failed to validate the signature. - * otherwise - this is an address of a signature aggregator that must be used to validate the signature. - * @param validAfter - this UserOp is valid only after this timestamp. - * @param validaUntil - this UserOp is valid only up to this timestamp. - */ -struct ValidationData { - address aggregator; - uint48 validAfter; - uint48 validUntil; -} - -//extract sigFailed, validAfter, validUntil. -// also convert zero validUntil to type(uint48).max -function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { - address aggregator = address(uint160(validationData)); - uint48 validUntil = uint48(validationData >> 160); - if (validUntil == 0) { - validUntil = type(uint48).max; - } - uint48 validAfter = uint48(validationData >> (48 + 160)); - return ValidationData(aggregator, validAfter, validUntil); -} - -// intersect account and paymaster ranges. -function _intersectTimeRange( - uint256 validationData, - uint256 paymasterValidationData -) pure returns (ValidationData memory) { - ValidationData memory accountValidationData = _parseValidationData(validationData); - ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); - address aggregator = accountValidationData.aggregator; - if (aggregator == address(0)) { - aggregator = pmValidationData.aggregator; - } - uint48 validAfter = accountValidationData.validAfter; - uint48 validUntil = accountValidationData.validUntil; - uint48 pmValidAfter = pmValidationData.validAfter; - uint48 pmValidUntil = pmValidationData.validUntil; - - if (validAfter < pmValidAfter) validAfter = pmValidAfter; - if (validUntil > pmValidUntil) validUntil = pmValidUntil; - return ValidationData(aggregator, validAfter, validUntil); -} - -/** - * helper to pack the return value for validateUserOp - * @param data - the ValidationData to pack - */ -function _packValidationData(ValidationData memory data) pure returns (uint256) { - return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); -} - -/** - * helper to pack the return value for validateUserOp, when not using an aggregator - * @param sigFailed - true for signature failure, false for success - * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) - * @param validAfter first timestamp this UserOperation is valid - */ -function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { - return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol deleted file mode 100644 index 36fad7b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/** - * helper contract for EntryPoint, to call userOp.initCode from a "neutral" address, - * which is explicitly not the entryPoint itself. - */ -contract SenderCreator { - - /** - * call the "initCode" factory to create and return the sender account address - * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata - * @return sender the returned address of the created account, or zero address on failure. - */ - function createSender(bytes calldata initCode) external returns (address sender) { - address factory = address(bytes20(initCode[0 : 20])); - bytes memory initCallData = initCode[20 :]; - bool success; - /* solhint-disable no-inline-assembly */ - assembly { - success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32) - sender := mload(0) - } - if (!success) { - sender = address(0); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol deleted file mode 100644 index e5ca2b9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity ^0.8.12; - -import "../interfaces/IStakeManager.sol"; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable not-rely-on-time */ -/** - * manage deposits and stakes. - * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) - * stake is value locked for at least "unstakeDelay" by a paymaster. - */ -abstract contract StakeManager is IStakeManager { - - /// maps paymaster to their deposits and stakes - mapping(address => DepositInfo) public deposits; - - /// @inheritdoc IStakeManager - function getDepositInfo(address account) public view returns (DepositInfo memory info) { - return deposits[account]; - } - - // internal method to return just the stake info - function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) { - DepositInfo storage depositInfo = deposits[addr]; - info.stake = depositInfo.stake; - info.unstakeDelaySec = depositInfo.unstakeDelaySec; - } - - /// return the deposit (for gas payment) of the account - function balanceOf(address account) public view returns (uint256) { - return deposits[account].deposit; - } - - receive() external payable { - depositTo(msg.sender); - } - - function _incrementDeposit(address account, uint256 amount) internal { - DepositInfo storage info = deposits[account]; - uint256 newAmount = info.deposit + amount; - require(newAmount <= type(uint112).max, "deposit overflow"); - info.deposit = uint112(newAmount); - } - - /** - * add to the deposit of the given account - */ - function depositTo(address account) public payable { - _incrementDeposit(account, msg.value); - DepositInfo storage info = deposits[account]; - emit Deposited(account, info.deposit); - } - - /** - * add to the account's stake - amount and delay - * any pending unstake is first cancelled. - * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn. - */ - function addStake(uint32 unstakeDelaySec) public payable { - DepositInfo storage info = deposits[msg.sender]; - require(unstakeDelaySec > 0, "must specify unstake delay"); - require(unstakeDelaySec >= info.unstakeDelaySec, "cannot decrease unstake time"); - uint256 stake = info.stake + msg.value; - require(stake > 0, "no stake specified"); - require(stake <= type(uint112).max, "stake overflow"); - deposits[msg.sender] = DepositInfo( - info.deposit, - true, - uint112(stake), - unstakeDelaySec, - 0 - ); - emit StakeLocked(msg.sender, stake, unstakeDelaySec); - } - - /** - * attempt to unlock the stake. - * the value can be withdrawn (using withdrawStake) after the unstake delay. - */ - function unlockStake() external { - DepositInfo storage info = deposits[msg.sender]; - require(info.unstakeDelaySec != 0, "not staked"); - require(info.staked, "already unstaking"); - uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; - info.withdrawTime = withdrawTime; - info.staked = false; - emit StakeUnlocked(msg.sender, withdrawTime); - } - - - /** - * withdraw from the (unlocked) stake. - * must first call unlockStake and wait for the unstakeDelay to pass - * @param withdrawAddress the address to send withdrawn value. - */ - function withdrawStake(address payable withdrawAddress) external { - DepositInfo storage info = deposits[msg.sender]; - uint256 stake = info.stake; - require(stake > 0, "No stake to withdraw"); - require(info.withdrawTime > 0, "must call unlockStake() first"); - require(info.withdrawTime <= block.timestamp, "Stake withdrawal is not due"); - info.unstakeDelaySec = 0; - info.withdrawTime = 0; - info.stake = 0; - emit StakeWithdrawn(msg.sender, withdrawAddress, stake); - (bool success,) = withdrawAddress.call{value : stake}(""); - require(success, "failed to withdraw stake"); - } - - /** - * withdraw from the deposit. - * @param withdrawAddress the address to send withdrawn value. - * @param withdrawAmount the amount to withdraw. - */ - function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external { - DepositInfo storage info = deposits[msg.sender]; - require(withdrawAmount <= info.deposit, "Withdraw amount too large"); - info.deposit = uint112(info.deposit - withdrawAmount); - emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); - (bool success,) = withdrawAddress.call{value : withdrawAmount}(""); - require(success, "failed to withdraw"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol deleted file mode 100644 index 1600de3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -interface IAccount { - - /** - * Validate user's signature and nonce - * the entryPoint will make the call to the recipient only if this validation call returns successfully. - * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). - * This allows making a "simulation call" without a valid signature - * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. - * - * @dev Must validate caller is the entryPoint. - * Must validate the signature and nonce - * @param userOp the operation that is about to be executed. - * @param userOpHash hash of the user's request data. can be used as the basis for signature. - * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. - * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. - * The excess is left as a deposit in the entrypoint, for future calls. - * can be withdrawn anytime using "entryPoint.withdrawTo()" - * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. - * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode - * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, - * otherwise, an address of an "authorizer" contract. - * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" - * <6-byte> validAfter - first timestamp this operation is valid - * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. - * Note that the validation code cannot use block.timestamp (or block.number) directly. - */ - function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) - external returns (uint256 validationData); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol deleted file mode 100644 index 086c6f3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -/** - * Aggregated Signatures validator. - */ -interface IAggregator { - - /** - * validate aggregated signature. - * revert if the aggregated signature does not match the given list of operations. - */ - function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; - - /** - * validate signature of a single userOp - * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation - * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. - * @param userOp the userOperation received from the user. - * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. - * (usually empty, unless account and aggregator support some kind of "multisig" - */ - function validateUserOpSignature(UserOperation calldata userOp) - external view returns (bytes memory sigForUserOp); - - /** - * aggregate multiple signatures into a single value. - * This method is called off-chain to calculate the signature to pass with handleOps() - * bundler MAY use optimized custom code perform this aggregation - * @param userOps array of UserOperations to collect the signatures from. - * @return aggregatedSignature the aggregated signature - */ - function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol deleted file mode 100644 index 22bb1b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol +++ /dev/null @@ -1,197 +0,0 @@ -/** - ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. - ** Only one instance required on each chain. - **/ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable avoid-low-level-calls */ -/* solhint-disable no-inline-assembly */ -/* solhint-disable reason-string */ - -import "./UserOperation.sol"; -import "./IStakeManager.sol"; -import "./IAggregator.sol"; - -interface IEntryPoint is IStakeManager { - - /*** - * An event emitted after each successful request - * @param userOpHash - unique identifier for the request (hash its entire content, except signature). - * @param sender - the account that generates this request. - * @param paymaster - if non-null, the paymaster that pays for this request. - * @param nonce - the nonce value from the request. - * @param success - true if the sender transaction succeeded, false if reverted. - * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. - * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). - */ - event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); - - /** - * account "sender" was deployed. - * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. - * @param sender the account that is deployed - * @param factory the factory used to deploy this account (in the initCode) - * @param paymaster the paymaster used by this UserOp - */ - event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); - - /** - * An event emitted if the UserOperation "callData" reverted with non-zero length - * @param userOpHash the request unique identifier. - * @param sender the sender of this request - * @param nonce the nonce used in the request - * @param revertReason - the return bytes from the (reverted) call to "callData". - */ - event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); - - /** - * signature aggregator used by the following UserOperationEvents within this bundle. - */ - event SignatureAggregatorChanged(address indexed aggregator); - - /** - * a custom revert error of handleOps, to identify the offending op. - * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. - * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) - * @param reason - revert reason - * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, - * so a failure can be attributed to the correct entity. - * Should be caught in off-chain handleOps simulation and not happen on-chain. - * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. - */ - error FailedOp(uint256 opIndex, string reason); - - /** - * error case when a signature aggregator fails to verify the aggregated signature it had created. - */ - error SignatureValidationFailed(address aggregator); - - /** - * Successful result from simulateValidation. - * @param returnInfo gas and time-range returned values - * @param senderInfo stake information about the sender - * @param factoryInfo stake information about the factory (if any) - * @param paymasterInfo stake information about the paymaster (if any) - */ - error ValidationResult(ReturnInfo returnInfo, - StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); - - /** - * Successful result from simulateValidation, if the account returns a signature aggregator - * @param returnInfo gas and time-range returned values - * @param senderInfo stake information about the sender - * @param factoryInfo stake information about the factory (if any) - * @param paymasterInfo stake information about the paymaster (if any) - * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) - * bundler MUST use it to verify the signature, or reject the UserOperation - */ - error ValidationResultWithAggregation(ReturnInfo returnInfo, - StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, - AggregatorStakeInfo aggregatorInfo); - - /** - * return value of getSenderAddress - */ - error SenderAddressResult(address sender); - - /** - * return value of simulateHandleOp - */ - error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); - - //UserOps handled, per aggregator - struct UserOpsPerAggregator { - UserOperation[] userOps; - - // aggregator address - IAggregator aggregator; - // aggregated signature - bytes signature; - } - - /** - * Execute a batch of UserOperation. - * no signature aggregator is used. - * if any account requires an aggregator (that is, it returned an aggregator when - * performing simulateValidation), then handleAggregatedOps() must be used instead. - * @param ops the operations to execute - * @param beneficiary the address to receive the fees - */ - function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; - - /** - * Execute a batch of UserOperation with Aggregators - * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) - * @param beneficiary the address to receive the fees - */ - function handleAggregatedOps( - UserOpsPerAggregator[] calldata opsPerAggregator, - address payable beneficiary - ) external; - - /** - * generate a request Id - unique identifier for this request. - * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. - */ - function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32); - - /** - * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. - * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. - * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. - * @param userOp the user operation to validate. - */ - function simulateValidation(UserOperation calldata userOp) external; - - /** - * gas and return values during simulation - * @param preOpGas the gas used for validation (including preValidationGas) - * @param prefund the required prefund for this operation - * @param sigFailed validateUserOp's (or paymaster's) signature check failed - * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) - * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) - * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) - */ - struct ReturnInfo { - uint256 preOpGas; - uint256 prefund; - bool sigFailed; - uint48 validAfter; - uint48 validUntil; - bytes paymasterContext; - } - - /** - * returned aggregated signature info. - * the aggregator returned by the account, and its current stake. - */ - struct AggregatorStakeInfo { - address aggregator; - StakeInfo stakeInfo; - } - - /** - * Get counterfactual sender address. - * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. - * this method always revert, and returns the address in SenderAddressResult error - * @param initCode the constructor code to be passed into the UserOperation. - */ - function getSenderAddress(bytes memory initCode) external; - - - /** - * simulate full execution of a UserOperation (including both validation and target execution) - * this method will always revert with "ExecutionResult". - * it performs full validation of the UserOperation, but ignores signature error. - * an optional target address is called after the userop succeeds, and its value is returned - * (before the entire call is reverted) - * Note that in order to collect the the success/failure of the target call, it must be executed - * with trace enabled to track the emitted events. - * @param op the UserOperation to simulate - * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult - * are set to the return from that call. - * @param targetCallData callData to pass to target address - */ - function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol deleted file mode 100644 index af50367..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -import "./UserOperation.sol"; - -/** - * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. - * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. - */ -interface IPaymaster { - - enum PostOpMode { - opSucceeded, // user op succeeded - opReverted, // user op reverted. still has to pay for gas. - postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. - } - - /** - * payment validation: check if paymaster agrees to pay. - * Must verify sender is the entryPoint. - * Revert to reject this request. - * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) - * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. - * @param userOp the user operation - * @param userOpHash hash of the user's request data. - * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) - * @return context value to send to a postOp - * zero length to signify postOp is not required. - * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation - * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, - * otherwise, an address of an "authorizer" contract. - * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" - * <6-byte> validAfter - first timestamp this operation is valid - * Note that the validation code cannot use block.timestamp (or block.number) directly. - */ - function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) - external returns (bytes memory context, uint256 validationData); - - /** - * post-operation handler. - * Must verify sender is the entryPoint - * @param mode enum with the following options: - * opSucceeded - user operation succeeded. - * opReverted - user op reverted. still has to pay for gas. - * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. - * Now this is the 2nd call, after user's op was deliberately reverted. - * @param context - the context value returned by validatePaymasterUserOp - * @param actualGasCost - actual gas used so far (without this postOp call). - */ - function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol deleted file mode 100644 index c19c1ba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity ^0.8.12; - -/** - * manage deposits and stakes. - * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) - * stake is value locked for at least "unstakeDelay" by the staked entity. - */ -interface IStakeManager { - - event Deposited( - address indexed account, - uint256 totalDeposit - ); - - event Withdrawn( - address indexed account, - address withdrawAddress, - uint256 amount - ); - - /// Emitted when stake or unstake delay are modified - event StakeLocked( - address indexed account, - uint256 totalStaked, - uint256 unstakeDelaySec - ); - - /// Emitted once a stake is scheduled for withdrawal - event StakeUnlocked( - address indexed account, - uint256 withdrawTime - ); - - event StakeWithdrawn( - address indexed account, - address withdrawAddress, - uint256 amount - ); - - /** - * @param deposit the entity's deposit - * @param staked true if this entity is staked. - * @param stake actual amount of ether staked for this entity. - * @param unstakeDelaySec minimum delay to withdraw the stake. - * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked - * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) - * and the rest fit into a 2nd cell. - * 112 bit allows for 10^15 eth - * 48 bit for full timestamp - * 32 bit allows 150 years for unstake delay - */ - struct DepositInfo { - uint112 deposit; - bool staked; - uint112 stake; - uint32 unstakeDelaySec; - uint48 withdrawTime; - } - - //API struct used by getStakeInfo and simulateValidation - struct StakeInfo { - uint256 stake; - uint256 unstakeDelaySec; - } - - /// @return info - full deposit information of given account - function getDepositInfo(address account) external view returns (DepositInfo memory info); - - /// @return the deposit (for gas payment) of the account - function balanceOf(address account) external view returns (uint256); - - /** - * add to the deposit of the given account - */ - function depositTo(address account) external payable; - - /** - * add to the account's stake - amount and delay - * any pending unstake is first cancelled. - * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. - */ - function addStake(uint32 _unstakeDelaySec) external payable; - - /** - * attempt to unlock the stake. - * the value can be withdrawn (using withdrawStake) after the unstake delay. - */ - function unlockStake() external; - - /** - * withdraw from the (unlocked) stake. - * must first call unlockStake and wait for the unstakeDelay to pass - * @param withdrawAddress the address to send withdrawn value. - */ - function withdrawStake(address payable withdrawAddress) external; - - /** - * withdraw from the deposit. - * @param withdrawAddress the address to send withdrawn value. - * @param withdrawAmount the amount to withdraw. - */ - function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol deleted file mode 100644 index dfff427..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.12; - -/* solhint-disable no-inline-assembly */ - - /** - * User Operation struct - * @param sender the sender account of this request. - * @param nonce unique value the sender uses to verify it is not a replay. - * @param initCode if set, the account contract will be created by this constructor/ - * @param callData the method call to execute on this account. - * @param callGasLimit the gas limit passed to the callData method call. - * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. - * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. - * @param maxFeePerGas same as EIP-1559 gas parameter. - * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. - * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. - * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. - */ - struct UserOperation { - - address sender; - uint256 nonce; - bytes initCode; - bytes callData; - uint256 callGasLimit; - uint256 verificationGasLimit; - uint256 preVerificationGas; - uint256 maxFeePerGas; - uint256 maxPriorityFeePerGas; - bytes paymasterAndData; - bytes signature; - } - -/** - * Utility functions helpful when working with UserOperation structs. - */ -library UserOperationLib { - - function getSender(UserOperation calldata userOp) internal pure returns (address) { - address data; - //read sender from userOp, which is first userOp member (saves 800 gas...) - assembly {data := calldataload(userOp)} - return address(uint160(data)); - } - - //relayer/block builder might submit the TX with higher priorityFee, but the user should not - // pay above what he signed for. - function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { - unchecked { - uint256 maxFeePerGas = userOp.maxFeePerGas; - uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; - if (maxFeePerGas == maxPriorityFeePerGas) { - //legacy mode (for networks that don't support basefee opcode) - return maxFeePerGas; - } - return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); - } - } - - function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { - //lighter signature scheme. must match UserOp.ts#packUserOp - bytes calldata sig = userOp.signature; - // copy directly the userOp from calldata up to (but not including) the signature. - // this encoding depends on the ABI encoding of calldata, but is much lighter to copy - // than referencing each field separately. - assembly { - let ofs := userOp - let len := sub(sub(sig.offset, ofs), 32) - ret := mload(0x40) - mstore(0x40, add(ret, add(len, 32))) - mstore(ret, len) - calldatacopy(add(ret, 32), ofs, len) - } - } - - function hash(UserOperation calldata userOp) internal pure returns (bytes32) { - return keccak256(pack(userOp)); - } - - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol deleted file mode 100644 index 69d653d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.7.5 <0.9.0; - -// solhint-disable no-inline-assembly - -/** - * Utility functions helpful when making different kinds of contract calls in Solidity. - */ -library Exec { - - function call( - address to, - uint256 value, - bytes memory data, - uint256 txGas - ) internal returns (bool success) { - assembly { - success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) - } - } - - function staticcall( - address to, - bytes memory data, - uint256 txGas - ) internal view returns (bool success) { - assembly { - success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0) - } - } - - function delegateCall( - address to, - bytes memory data, - uint256 txGas - ) internal returns (bool success) { - assembly { - success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) - } - } - - // get returned data from last call or calldelegate - function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) { - assembly { - let len := returndatasize() - if gt(len, maxLen) { - len := maxLen - } - let ptr := mload(0x40) - mstore(0x40, add(ptr, add(len, 0x20))) - mstore(ptr, len) - returndatacopy(add(ptr, 0x20), 0, len) - returnData := ptr - } - } - - // revert with explicit byte array (probably reverted info from call) - function revertWithData(bytes memory returnData) internal pure { - assembly { - revert(add(returnData, 32), mload(returnData)) - } - } - - function callAndRevert(address to, bytes memory data, uint256 maxLen) internal { - bool success = call(to,0,data,gasleft()); - if (!success) { - revertWithData(getReturnData(maxLen)); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol deleted file mode 100644 index 851ac0c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Base.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -import {StdStorage} from "./StdStorage.sol"; -import {Vm, VmSafe} from "./Vm.sol"; - -abstract contract CommonBase { - // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. - address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); - // console.sol and console2.sol work by executing a staticcall to this address. - address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; - // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. - address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. - address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); - // Address of the test contract, deployed by the DEFAULT_SENDER. - address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; - // Deterministic deployment address of the Multicall3 contract. - address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; - // The order of the secp256k1 curve. - uint256 internal constant SECP256K1_ORDER = - 115792089237316195423570985008687907852837564279074904382605163141518161494337; - - uint256 internal constant UINT256_MAX = - 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - Vm internal constant vm = Vm(VM_ADDRESS); - StdStorage internal stdstore; -} - -abstract contract TestBase is CommonBase {} - -abstract contract ScriptBase is CommonBase { - VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol deleted file mode 100644 index 94e75f6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Script.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -// 💬 ABOUT -// Forge Std's default Script. - -// 🧩 MODULES -import {console} from "./console.sol"; -import {console2} from "./console2.sol"; -import {safeconsole} from "./safeconsole.sol"; -import {StdChains} from "./StdChains.sol"; -import {StdCheatsSafe} from "./StdCheats.sol"; -import {stdJson} from "./StdJson.sol"; -import {stdMath} from "./StdMath.sol"; -import {StdStorage, stdStorageSafe} from "./StdStorage.sol"; -import {StdStyle} from "./StdStyle.sol"; -import {StdUtils} from "./StdUtils.sol"; -import {VmSafe} from "./Vm.sol"; - -// 📦 BOILERPLATE -import {ScriptBase} from "./Base.sol"; - -// ⭐️ SCRIPT -abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils { - // Note: IS_SCRIPT() must return true. - bool public IS_SCRIPT = true; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol deleted file mode 100644 index 857ecd5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdAssertions.sol +++ /dev/null @@ -1,669 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; -pragma experimental ABIEncoderV2; - -import {Vm} from "./Vm.sol"; - -abstract contract StdAssertions { - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - event log(string); - event logs(bytes); - - event log_address(address); - event log_bytes32(bytes32); - event log_int(int256); - event log_uint(uint256); - event log_bytes(bytes); - event log_string(string); - - event log_named_address(string key, address val); - event log_named_bytes32(string key, bytes32 val); - event log_named_decimal_int(string key, int256 val, uint256 decimals); - event log_named_decimal_uint(string key, uint256 val, uint256 decimals); - event log_named_int(string key, int256 val); - event log_named_uint(string key, uint256 val); - event log_named_bytes(string key, bytes val); - event log_named_string(string key, string val); - - event log_array(uint256[] val); - event log_array(int256[] val); - event log_array(address[] val); - event log_named_array(string key, uint256[] val); - event log_named_array(string key, int256[] val); - event log_named_array(string key, address[] val); - - bool private _failed; - - function failed() public view returns (bool) { - if (_failed) { - return _failed; - } else { - return vm.load(address(vm), bytes32("failed")) != bytes32(0); - } - } - - function fail() internal virtual { - vm.store(address(vm), bytes32("failed"), bytes32(uint256(1))); - _failed = true; - } - - function assertTrue(bool data) internal pure virtual { - vm.assertTrue(data); - } - - function assertTrue(bool data, string memory err) internal pure virtual { - vm.assertTrue(data, err); - } - - function assertFalse(bool data) internal pure virtual { - vm.assertFalse(data); - } - - function assertFalse(bool data, string memory err) internal pure virtual { - vm.assertFalse(data, err); - } - - function assertEq(bool left, bool right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bool left, bool right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(uint256 left, uint256 right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertEqDecimal(left, right, decimals); - } - - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertEqDecimal(left, right, decimals, err); - } - - function assertEq(int256 left, int256 right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertEqDecimal(left, right, decimals); - } - - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertEqDecimal(left, right, decimals, err); - } - - function assertEq(address left, address right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(address left, address right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes32 left, bytes32 right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq32(bytes32 left, bytes32 right) internal pure virtual { - assertEq(left, right); - } - - function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { - assertEq(left, right, err); - } - - function assertEq(string memory left, string memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(string memory left, string memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes memory left, bytes memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(address[] memory left, address[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(string[] memory left, string[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { - vm.assertEq(left, right); - } - - function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { - vm.assertEq(left, right, err); - } - - // Legacy helper - function assertEqUint(uint256 left, uint256 right) internal pure virtual { - assertEq(left, right); - } - - function assertNotEq(bool left, bool right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bool left, bool right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(uint256 left, uint256 right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals); - } - - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) - internal - pure - virtual - { - vm.assertNotEqDecimal(left, right, decimals, err); - } - - function assertNotEq(int256 left, int256 right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals); - } - - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertNotEqDecimal(left, right, decimals, err); - } - - function assertNotEq(address left, address right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(address left, address right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { - assertNotEq(left, right); - } - - function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { - assertNotEq(left, right, err); - } - - function assertNotEq(string memory left, string memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { - vm.assertNotEq(left, right); - } - - function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { - vm.assertNotEq(left, right, err); - } - - function assertLt(uint256 left, uint256 right) internal pure virtual { - vm.assertLt(left, right); - } - - function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertLt(left, right, err); - } - - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertLtDecimal(left, right, decimals); - } - - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLtDecimal(left, right, decimals, err); - } - - function assertLt(int256 left, int256 right) internal pure virtual { - vm.assertLt(left, right); - } - - function assertLt(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertLt(left, right, err); - } - - function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertLtDecimal(left, right, decimals); - } - - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLtDecimal(left, right, decimals, err); - } - - function assertGt(uint256 left, uint256 right) internal pure virtual { - vm.assertGt(left, right); - } - - function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertGt(left, right, err); - } - - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertGtDecimal(left, right, decimals); - } - - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGtDecimal(left, right, decimals, err); - } - - function assertGt(int256 left, int256 right) internal pure virtual { - vm.assertGt(left, right); - } - - function assertGt(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertGt(left, right, err); - } - - function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertGtDecimal(left, right, decimals); - } - - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGtDecimal(left, right, decimals, err); - } - - function assertLe(uint256 left, uint256 right) internal pure virtual { - vm.assertLe(left, right); - } - - function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertLe(left, right, err); - } - - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertLeDecimal(left, right, decimals); - } - - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLeDecimal(left, right, decimals, err); - } - - function assertLe(int256 left, int256 right) internal pure virtual { - vm.assertLe(left, right); - } - - function assertLe(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertLe(left, right, err); - } - - function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertLeDecimal(left, right, decimals); - } - - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertLeDecimal(left, right, decimals, err); - } - - function assertGe(uint256 left, uint256 right) internal pure virtual { - vm.assertGe(left, right); - } - - function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { - vm.assertGe(left, right, err); - } - - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { - vm.assertGeDecimal(left, right, decimals); - } - - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGeDecimal(left, right, decimals, err); - } - - function assertGe(int256 left, int256 right) internal pure virtual { - vm.assertGe(left, right); - } - - function assertGe(int256 left, int256 right, string memory err) internal pure virtual { - vm.assertGe(left, right, err); - } - - function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { - vm.assertGeDecimal(left, right, decimals); - } - - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { - vm.assertGeDecimal(left, right, decimals, err); - } - - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta); - } - - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) - internal - pure - virtual - { - vm.assertApproxEqAbs(left, right, maxDelta, err); - } - - function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); - } - - function assertApproxEqAbsDecimal( - uint256 left, - uint256 right, - uint256 maxDelta, - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); - } - - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta); - } - - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { - vm.assertApproxEqAbs(left, right, maxDelta, err); - } - - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); - } - - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) - internal - pure - virtual - { - vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); - } - - function assertApproxEqRel( - uint256 left, - uint256 right, - uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta); - } - - function assertApproxEqRel( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - string memory err - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta, err); - } - - function assertApproxEqRelDecimal( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); - } - - function assertApproxEqRelDecimal( - uint256 left, - uint256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); - } - - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta); - } - - function assertApproxEqRel( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - string memory err - ) internal pure virtual { - vm.assertApproxEqRel(left, right, maxPercentDelta, err); - } - - function assertApproxEqRelDecimal( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); - } - - function assertApproxEqRelDecimal( - int256 left, - int256 right, - uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% - uint256 decimals, - string memory err - ) internal pure virtual { - vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); - } - - // Inherited from DSTest, not used but kept for backwards-compatibility - function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { - return keccak256(left) == keccak256(right); - } - - function assertEq0(bytes memory left, bytes memory right) internal pure virtual { - assertEq(left, right); - } - - function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { - assertEq(left, right, err); - } - - function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { - assertNotEq(left, right); - } - - function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { - assertNotEq(left, right, err); - } - - function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { - assertEqCall(target, callDataA, target, callDataB, true); - } - - function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) - internal - virtual - { - assertEqCall(targetA, callDataA, targetB, callDataB, true); - } - - function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) - internal - virtual - { - assertEqCall(target, callDataA, target, callDataB, strictRevertData); - } - - function assertEqCall( - address targetA, - bytes memory callDataA, - address targetB, - bytes memory callDataB, - bool strictRevertData - ) internal virtual { - (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); - (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); - - if (successA && successB) { - assertEq(returnDataA, returnDataB, "Call return data does not match"); - } - - if (!successA && !successB && strictRevertData) { - assertEq(returnDataA, returnDataB, "Call revert data does not match"); - } - - if (!successA && successB) { - emit log("Error: Calls were not equal"); - emit log_named_bytes(" Left call revert data", returnDataA); - emit log_named_bytes(" Right call return data", returnDataB); - revert("assertion failed"); - } - - if (successA && !successB) { - emit log("Error: Calls were not equal"); - emit log_named_bytes(" Left call return data", returnDataA); - emit log_named_bytes(" Right call revert data", returnDataB); - revert("assertion failed"); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol deleted file mode 100644 index 9ca1b82..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdChains.sol +++ /dev/null @@ -1,263 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -import {VmSafe} from "./Vm.sol"; - -/** - * StdChains provides information about EVM compatible chains that can be used in scripts/tests. - * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are - * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of - * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the - * alias used in this contract, which can be found as the first argument to the - * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. - * - * There are two main ways to use this contract: - * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or - * `setChain(string memory chainAlias, Chain memory chain)` - * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. - * - * The first time either of those are used, chains are initialized with the default set of RPC URLs. - * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in - * `defaultRpcUrls`. - * - * The `setChain` function is straightforward, and it simply saves off the given chain data. - * - * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say - * we want to retrieve the RPC URL for `mainnet`: - * - If you have specified data with `setChain`, it will return that. - * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it - * is valid (e.g. a URL is specified, or an environment variable is given and exists). - * - If neither of the above conditions is met, the default data is returned. - * - * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. - */ -abstract contract StdChains { - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - - bool private stdChainsInitialized; - - struct ChainData { - string name; - uint256 chainId; - string rpcUrl; - } - - struct Chain { - // The chain name. - string name; - // The chain's Chain ID. - uint256 chainId; - // The chain's alias. (i.e. what gets specified in `foundry.toml`). - string chainAlias; - // A default RPC endpoint for this chain. - // NOTE: This default RPC URL is included for convenience to facilitate quick tests and - // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy - // usage as you will be throttled and this is a disservice to others who need this endpoint. - string rpcUrl; - } - - // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. - mapping(string => Chain) private chains; - // Maps from the chain's alias to it's default RPC URL. - mapping(string => string) private defaultRpcUrls; - // Maps from a chain ID to it's alias. - mapping(uint256 => string) private idToAlias; - - bool private fallbackToDefaultRpcUrls = true; - - // The RPC URL will be fetched from config or defaultRpcUrls if possible. - function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { - require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); - - initializeStdChains(); - chain = chains[chainAlias]; - require( - chain.chainId != 0, - string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) - ); - - chain = getChainWithUpdatedRpcUrl(chainAlias, chain); - } - - function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { - require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); - initializeStdChains(); - string memory chainAlias = idToAlias[chainId]; - - chain = chains[chainAlias]; - - require( - chain.chainId != 0, - string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) - ); - - chain = getChainWithUpdatedRpcUrl(chainAlias, chain); - } - - // set chain info, with priority to argument's rpcUrl field. - function setChain(string memory chainAlias, ChainData memory chain) internal virtual { - require( - bytes(chainAlias).length != 0, - "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." - ); - - require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); - - initializeStdChains(); - string memory foundAlias = idToAlias[chain.chainId]; - - require( - bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), - string( - abi.encodePacked( - "StdChains setChain(string,ChainData): Chain ID ", - vm.toString(chain.chainId), - " already used by \"", - foundAlias, - "\"." - ) - ) - ); - - uint256 oldChainId = chains[chainAlias].chainId; - delete idToAlias[oldChainId]; - - chains[chainAlias] = - Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); - idToAlias[chain.chainId] = chainAlias; - } - - // set chain info, with priority to argument's rpcUrl field. - function setChain(string memory chainAlias, Chain memory chain) internal virtual { - setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); - } - - function _toUpper(string memory str) private pure returns (string memory) { - bytes memory strb = bytes(str); - bytes memory copy = new bytes(strb.length); - for (uint256 i = 0; i < strb.length; i++) { - bytes1 b = strb[i]; - if (b >= 0x61 && b <= 0x7A) { - copy[i] = bytes1(uint8(b) - 32); - } else { - copy[i] = b; - } - } - return string(copy); - } - - // lookup rpcUrl, in descending order of priority: - // current -> config (foundry.toml) -> environment variable -> default - function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) - private - view - returns (Chain memory) - { - if (bytes(chain.rpcUrl).length == 0) { - try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { - chain.rpcUrl = configRpcUrl; - } catch (bytes memory err) { - string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); - if (fallbackToDefaultRpcUrls) { - chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); - } else { - chain.rpcUrl = vm.envString(envName); - } - // Distinguish 'not found' from 'cannot read' - // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions - bytes memory oldNotFoundError = - abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); - bytes memory newNotFoundError = abi.encodeWithSignature( - "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) - ); - bytes32 errHash = keccak256(err); - if ( - (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) - || bytes(chain.rpcUrl).length == 0 - ) { - /// @solidity memory-safe-assembly - assembly { - revert(add(32, err), mload(err)) - } - } - } - } - return chain; - } - - function setFallbackToDefaultRpcUrls(bool useDefault) internal { - fallbackToDefaultRpcUrls = useDefault; - } - - function initializeStdChains() private { - if (stdChainsInitialized) return; - - stdChainsInitialized = true; - - // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` - setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); - setChainWithDefaultRpcUrl( - "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") - ); - setChainWithDefaultRpcUrl( - "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") - ); - setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); - setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); - setChainWithDefaultRpcUrl( - "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") - ); - setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); - setChainWithDefaultRpcUrl( - "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") - ); - setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); - setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); - setChainWithDefaultRpcUrl( - "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") - ); - setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); - setChainWithDefaultRpcUrl( - "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") - ); - setChainWithDefaultRpcUrl( - "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") - ); - setChainWithDefaultRpcUrl( - "bnb_smart_chain_testnet", - ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") - ); - setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); - setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); - setChainWithDefaultRpcUrl( - "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") - ); - setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); - setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); - setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); - setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); - setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); - setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); - setChainWithDefaultRpcUrl( - "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") - ); - setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); - setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); - setChainWithDefaultRpcUrl( - "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") - ); - setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); - setChainWithDefaultRpcUrl( - "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") - ); - } - - // set chain info, with priority to chainAlias' rpc url in foundry.toml - function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { - string memory rpcUrl = chain.rpcUrl; - defaultRpcUrls[chainAlias] = rpcUrl; - chain.rpcUrl = ""; - setChain(chainAlias, chain); - chain.rpcUrl = rpcUrl; // restore argument - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol deleted file mode 100644 index 95850d1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdCheats.sol +++ /dev/null @@ -1,817 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; - -import {StdStorage, stdStorage} from "./StdStorage.sol"; -import {console2} from "./console2.sol"; -import {Vm} from "./Vm.sol"; - -abstract contract StdCheatsSafe { - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - uint256 private constant UINT256_MAX = - 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - bool private gasMeteringOff; - - // Data structures to parse Transaction objects from the broadcast artifact - // that conform to EIP1559. The Raw structs is what is parsed from the JSON - // and then converted to the one that is used by the user for better UX. - - struct RawTx1559 { - string[] arguments; - address contractAddress; - string contractName; - // json value name = function - string functionSig; - bytes32 hash; - // json value name = tx - RawTx1559Detail txDetail; - // json value name = type - string opcode; - } - - struct RawTx1559Detail { - AccessList[] accessList; - bytes data; - address from; - bytes gas; - bytes nonce; - address to; - bytes txType; - bytes value; - } - - struct Tx1559 { - string[] arguments; - address contractAddress; - string contractName; - string functionSig; - bytes32 hash; - Tx1559Detail txDetail; - string opcode; - } - - struct Tx1559Detail { - AccessList[] accessList; - bytes data; - address from; - uint256 gas; - uint256 nonce; - address to; - uint256 txType; - uint256 value; - } - - // Data structures to parse Transaction objects from the broadcast artifact - // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON - // and then converted to the one that is used by the user for better UX. - - struct TxLegacy { - string[] arguments; - address contractAddress; - string contractName; - string functionSig; - string hash; - string opcode; - TxDetailLegacy transaction; - } - - struct TxDetailLegacy { - AccessList[] accessList; - uint256 chainId; - bytes data; - address from; - uint256 gas; - uint256 gasPrice; - bytes32 hash; - uint256 nonce; - bytes1 opcode; - bytes32 r; - bytes32 s; - uint256 txType; - address to; - uint8 v; - uint256 value; - } - - struct AccessList { - address accessAddress; - bytes32[] storageKeys; - } - - // Data structures to parse Receipt objects from the broadcast artifact. - // The Raw structs is what is parsed from the JSON - // and then converted to the one that is used by the user for better UX. - - struct RawReceipt { - bytes32 blockHash; - bytes blockNumber; - address contractAddress; - bytes cumulativeGasUsed; - bytes effectiveGasPrice; - address from; - bytes gasUsed; - RawReceiptLog[] logs; - bytes logsBloom; - bytes status; - address to; - bytes32 transactionHash; - bytes transactionIndex; - } - - struct Receipt { - bytes32 blockHash; - uint256 blockNumber; - address contractAddress; - uint256 cumulativeGasUsed; - uint256 effectiveGasPrice; - address from; - uint256 gasUsed; - ReceiptLog[] logs; - bytes logsBloom; - uint256 status; - address to; - bytes32 transactionHash; - uint256 transactionIndex; - } - - // Data structures to parse the entire broadcast artifact, assuming the - // transactions conform to EIP1559. - - struct EIP1559ScriptArtifact { - string[] libraries; - string path; - string[] pending; - Receipt[] receipts; - uint256 timestamp; - Tx1559[] transactions; - TxReturn[] txReturns; - } - - struct RawEIP1559ScriptArtifact { - string[] libraries; - string path; - string[] pending; - RawReceipt[] receipts; - TxReturn[] txReturns; - uint256 timestamp; - RawTx1559[] transactions; - } - - struct RawReceiptLog { - // json value = address - address logAddress; - bytes32 blockHash; - bytes blockNumber; - bytes data; - bytes logIndex; - bool removed; - bytes32[] topics; - bytes32 transactionHash; - bytes transactionIndex; - bytes transactionLogIndex; - } - - struct ReceiptLog { - // json value = address - address logAddress; - bytes32 blockHash; - uint256 blockNumber; - bytes data; - uint256 logIndex; - bytes32[] topics; - uint256 transactionIndex; - uint256 transactionLogIndex; - bool removed; - } - - struct TxReturn { - string internalType; - string value; - } - - struct Account { - address addr; - uint256 key; - } - - enum AddressType { - Payable, - NonPayable, - ZeroAddress, - Precompile, - ForgeAddress - } - - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. - function assumeNotBlacklisted(address token, address addr) internal view virtual { - // Nothing to check if `token` is not a contract. - uint256 tokenCodeSize; - assembly { - tokenCodeSize := extcodesize(token) - } - require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); - - bool success; - bytes memory returnData; - - // 4-byte selector for `isBlacklisted(address)`, used by USDC. - (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); - vm.assume(!success || abi.decode(returnData, (bool)) == false); - - // 4-byte selector for `isBlackListed(address)`, used by USDT. - (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); - vm.assume(!success || abi.decode(returnData, (bool)) == false); - } - - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. - // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for - // backwards compatibility, since this name was used in the original PR which already has - // a release. This function can be removed in a future release once we want a breaking change. - function assumeNoBlacklisted(address token, address addr) internal view virtual { - assumeNotBlacklisted(token, addr); - } - - function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { - if (addressType == AddressType.Payable) { - assumeNotPayable(addr); - } else if (addressType == AddressType.NonPayable) { - assumePayable(addr); - } else if (addressType == AddressType.ZeroAddress) { - assumeNotZeroAddress(addr); - } else if (addressType == AddressType.Precompile) { - assumeNotPrecompile(addr); - } else if (addressType == AddressType.ForgeAddress) { - assumeNotForgeAddress(addr); - } - } - - function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { - assumeAddressIsNot(addr, addressType1); - assumeAddressIsNot(addr, addressType2); - } - - function assumeAddressIsNot( - address addr, - AddressType addressType1, - AddressType addressType2, - AddressType addressType3 - ) internal virtual { - assumeAddressIsNot(addr, addressType1); - assumeAddressIsNot(addr, addressType2); - assumeAddressIsNot(addr, addressType3); - } - - function assumeAddressIsNot( - address addr, - AddressType addressType1, - AddressType addressType2, - AddressType addressType3, - AddressType addressType4 - ) internal virtual { - assumeAddressIsNot(addr, addressType1); - assumeAddressIsNot(addr, addressType2); - assumeAddressIsNot(addr, addressType3); - assumeAddressIsNot(addr, addressType4); - } - - // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to - // `addr` and checking the `success` return value. - // NOTE: This function may result in state changes depending on the fallback/receive logic - // implemented by `addr`, which should be taken into account when this function is used. - function _isPayable(address addr) private returns (bool) { - require( - addr.balance < UINT256_MAX, - "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" - ); - uint256 origBalanceTest = address(this).balance; - uint256 origBalanceAddr = address(addr).balance; - - vm.deal(address(this), 1); - (bool success,) = payable(addr).call{value: 1}(""); - - // reset balances - vm.deal(address(this), origBalanceTest); - vm.deal(addr, origBalanceAddr); - - return success; - } - - // NOTE: This function may result in state changes depending on the fallback/receive logic - // implemented by `addr`, which should be taken into account when this function is used. See the - // `_isPayable` method for more information. - function assumePayable(address addr) internal virtual { - vm.assume(_isPayable(addr)); - } - - function assumeNotPayable(address addr) internal virtual { - vm.assume(!_isPayable(addr)); - } - - function assumeNotZeroAddress(address addr) internal pure virtual { - vm.assume(addr != address(0)); - } - - function assumeNotPrecompile(address addr) internal pure virtual { - assumeNotPrecompile(addr, _pureChainId()); - } - - function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { - // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific - // address), but the same rationale for excluding them applies so we include those too. - - // These are reserved by Ethereum and may be on all EVM-compatible chains. - vm.assume(addr < address(0x1) || addr > address(0xff)); - - // forgefmt: disable-start - if (chainId == 10 || chainId == 420) { - // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 - vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); - } else if (chainId == 42161 || chainId == 421613) { - // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains - vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); - } else if (chainId == 43114 || chainId == 43113) { - // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 - vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); - vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); - vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); - } - // forgefmt: disable-end - } - - function assumeNotForgeAddress(address addr) internal pure virtual { - // vm, console, and Create2Deployer addresses - vm.assume( - addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 - && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C - ); - } - - function readEIP1559ScriptArtifact(string memory path) - internal - view - virtual - returns (EIP1559ScriptArtifact memory) - { - string memory data = vm.readFile(path); - bytes memory parsedData = vm.parseJson(data); - RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); - EIP1559ScriptArtifact memory artifact; - artifact.libraries = rawArtifact.libraries; - artifact.path = rawArtifact.path; - artifact.timestamp = rawArtifact.timestamp; - artifact.pending = rawArtifact.pending; - artifact.txReturns = rawArtifact.txReturns; - artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); - artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); - return artifact; - } - - function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { - Tx1559[] memory txs = new Tx1559[](rawTxs.length); - for (uint256 i; i < rawTxs.length; i++) { - txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); - } - return txs; - } - - function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { - Tx1559 memory transaction; - transaction.arguments = rawTx.arguments; - transaction.contractName = rawTx.contractName; - transaction.functionSig = rawTx.functionSig; - transaction.hash = rawTx.hash; - transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); - transaction.opcode = rawTx.opcode; - return transaction; - } - - function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) - internal - pure - virtual - returns (Tx1559Detail memory) - { - Tx1559Detail memory txDetail; - txDetail.data = rawDetail.data; - txDetail.from = rawDetail.from; - txDetail.to = rawDetail.to; - txDetail.nonce = _bytesToUint(rawDetail.nonce); - txDetail.txType = _bytesToUint(rawDetail.txType); - txDetail.value = _bytesToUint(rawDetail.value); - txDetail.gas = _bytesToUint(rawDetail.gas); - txDetail.accessList = rawDetail.accessList; - return txDetail; - } - - function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { - string memory deployData = vm.readFile(path); - bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); - RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); - return rawToConvertedEIPTx1559s(rawTxs); - } - - function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { - string memory deployData = vm.readFile(path); - string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); - bytes memory parsedDeployData = vm.parseJson(deployData, key); - RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); - return rawToConvertedEIPTx1559(rawTx); - } - - // Analogous to readTransactions, but for receipts. - function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { - string memory deployData = vm.readFile(path); - bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); - RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); - return rawToConvertedReceipts(rawReceipts); - } - - function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { - string memory deployData = vm.readFile(path); - string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); - bytes memory parsedDeployData = vm.parseJson(deployData, key); - RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); - return rawToConvertedReceipt(rawReceipt); - } - - function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { - Receipt[] memory receipts = new Receipt[](rawReceipts.length); - for (uint256 i; i < rawReceipts.length; i++) { - receipts[i] = rawToConvertedReceipt(rawReceipts[i]); - } - return receipts; - } - - function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { - Receipt memory receipt; - receipt.blockHash = rawReceipt.blockHash; - receipt.to = rawReceipt.to; - receipt.from = rawReceipt.from; - receipt.contractAddress = rawReceipt.contractAddress; - receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); - receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); - receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); - receipt.status = _bytesToUint(rawReceipt.status); - receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); - receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); - receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); - receipt.logsBloom = rawReceipt.logsBloom; - receipt.transactionHash = rawReceipt.transactionHash; - return receipt; - } - - function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) - internal - pure - virtual - returns (ReceiptLog[] memory) - { - ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); - for (uint256 i; i < rawLogs.length; i++) { - logs[i].logAddress = rawLogs[i].logAddress; - logs[i].blockHash = rawLogs[i].blockHash; - logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); - logs[i].data = rawLogs[i].data; - logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); - logs[i].topics = rawLogs[i].topics; - logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); - logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); - logs[i].removed = rawLogs[i].removed; - } - return logs; - } - - // Deploy a contract by fetching the contract bytecode from - // the artifacts directory - // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` - function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { - bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); - /// @solidity memory-safe-assembly - assembly { - addr := create(0, add(bytecode, 0x20), mload(bytecode)) - } - - require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); - } - - function deployCode(string memory what) internal virtual returns (address addr) { - bytes memory bytecode = vm.getCode(what); - /// @solidity memory-safe-assembly - assembly { - addr := create(0, add(bytecode, 0x20), mload(bytecode)) - } - - require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); - } - - /// @dev deploy contract with value on construction - function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { - bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); - /// @solidity memory-safe-assembly - assembly { - addr := create(val, add(bytecode, 0x20), mload(bytecode)) - } - - require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); - } - - function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { - bytes memory bytecode = vm.getCode(what); - /// @solidity memory-safe-assembly - assembly { - addr := create(val, add(bytecode, 0x20), mload(bytecode)) - } - - require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); - } - - // creates a labeled address and the corresponding private key - function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { - privateKey = uint256(keccak256(abi.encodePacked(name))); - addr = vm.addr(privateKey); - vm.label(addr, name); - } - - // creates a labeled address - function makeAddr(string memory name) internal virtual returns (address addr) { - (addr,) = makeAddrAndKey(name); - } - - // Destroys an account immediately, sending the balance to beneficiary. - // Destroying means: balance will be zero, code will be empty, and nonce will be 0 - // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce - // only after tx ends, this will run immediately. - function destroyAccount(address who, address beneficiary) internal virtual { - uint256 currBalance = who.balance; - vm.etch(who, abi.encode()); - vm.deal(who, 0); - vm.resetNonce(who); - - uint256 beneficiaryBalance = beneficiary.balance; - vm.deal(beneficiary, currBalance + beneficiaryBalance); - } - - // creates a struct containing both a labeled address and the corresponding private key - function makeAccount(string memory name) internal virtual returns (Account memory account) { - (account.addr, account.key) = makeAddrAndKey(name); - } - - function deriveRememberKey(string memory mnemonic, uint32 index) - internal - virtual - returns (address who, uint256 privateKey) - { - privateKey = vm.deriveKey(mnemonic, index); - who = vm.rememberKey(privateKey); - } - - function _bytesToUint(bytes memory b) private pure returns (uint256) { - require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); - return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); - } - - function isFork() internal view virtual returns (bool status) { - try vm.activeFork() { - status = true; - } catch (bytes memory) {} - } - - modifier skipWhenForking() { - if (!isFork()) { - _; - } - } - - modifier skipWhenNotForking() { - if (isFork()) { - _; - } - } - - modifier noGasMetering() { - vm.pauseGasMetering(); - // To prevent turning gas monitoring back on with nested functions that use this modifier, - // we check if gasMetering started in the off position. If it did, we don't want to turn - // it back on until we exit the top level function that used the modifier - // - // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. - // funcA will have `gasStartedOff` as false, funcB will have it as true, - // so we only turn metering back on at the end of the funcA - bool gasStartedOff = gasMeteringOff; - gasMeteringOff = true; - - _; - - // if gas metering was on when this modifier was called, turn it back on at the end - if (!gasStartedOff) { - gasMeteringOff = false; - vm.resumeGasMetering(); - } - } - - // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no - // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We - // can't simply access the chain ID in a normal view or pure function because the solc View Pure - // Checker changed `chainid` from pure to view in 0.8.0. - function _viewChainId() private view returns (uint256 chainId) { - // Assembly required since `block.chainid` was introduced in 0.8.0. - assembly { - chainId := chainid() - } - - address(this); // Silence warnings in older Solc versions. - } - - function _pureChainId() private pure returns (uint256 chainId) { - function() internal view returns (uint256) fnIn = _viewChainId; - function() internal pure returns (uint256) pureChainId; - assembly { - pureChainId := fnIn - } - chainId = pureChainId(); - } -} - -// Wrappers around cheatcodes to avoid footguns -abstract contract StdCheats is StdCheatsSafe { - using stdStorage for StdStorage; - - StdStorage private stdstore; - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; - - // Skip forward or rewind time by the specified number of seconds - function skip(uint256 time) internal virtual { - vm.warp(block.timestamp + time); - } - - function rewind(uint256 time) internal virtual { - vm.warp(block.timestamp - time); - } - - // Setup a prank from an address that has some ether - function hoax(address msgSender) internal virtual { - vm.deal(msgSender, 1 << 128); - vm.prank(msgSender); - } - - function hoax(address msgSender, uint256 give) internal virtual { - vm.deal(msgSender, give); - vm.prank(msgSender); - } - - function hoax(address msgSender, address origin) internal virtual { - vm.deal(msgSender, 1 << 128); - vm.prank(msgSender, origin); - } - - function hoax(address msgSender, address origin, uint256 give) internal virtual { - vm.deal(msgSender, give); - vm.prank(msgSender, origin); - } - - // Start perpetual prank from an address that has some ether - function startHoax(address msgSender) internal virtual { - vm.deal(msgSender, 1 << 128); - vm.startPrank(msgSender); - } - - function startHoax(address msgSender, uint256 give) internal virtual { - vm.deal(msgSender, give); - vm.startPrank(msgSender); - } - - // Start perpetual prank from an address that has some ether - // tx.origin is set to the origin parameter - function startHoax(address msgSender, address origin) internal virtual { - vm.deal(msgSender, 1 << 128); - vm.startPrank(msgSender, origin); - } - - function startHoax(address msgSender, address origin, uint256 give) internal virtual { - vm.deal(msgSender, give); - vm.startPrank(msgSender, origin); - } - - function changePrank(address msgSender) internal virtual { - console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); - vm.stopPrank(); - vm.startPrank(msgSender); - } - - function changePrank(address msgSender, address txOrigin) internal virtual { - vm.stopPrank(); - vm.startPrank(msgSender, txOrigin); - } - - // The same as Vm's `deal` - // Use the alternative signature for ERC20 tokens - function deal(address to, uint256 give) internal virtual { - vm.deal(to, give); - } - - // Set the balance of an account for any ERC20 token - // Use the alternative signature to update `totalSupply` - function deal(address token, address to, uint256 give) internal virtual { - deal(token, to, give, false); - } - - // Set the balance of an account for any ERC1155 token - // Use the alternative signature to update `totalSupply` - function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { - dealERC1155(token, to, id, give, false); - } - - function deal(address token, address to, uint256 give, bool adjust) internal virtual { - // get current balance - (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); - uint256 prevBal = abi.decode(balData, (uint256)); - - // update balance - stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); - - // update total supply - if (adjust) { - (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); - uint256 totSup = abi.decode(totSupData, (uint256)); - if (give < prevBal) { - totSup -= (prevBal - give); - } else { - totSup += (give - prevBal); - } - stdstore.target(token).sig(0x18160ddd).checked_write(totSup); - } - } - - function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { - // get current balance - (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); - uint256 prevBal = abi.decode(balData, (uint256)); - - // update balance - stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); - - // update total supply - if (adjust) { - (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); - require( - totSupData.length != 0, - "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." - ); - uint256 totSup = abi.decode(totSupData, (uint256)); - if (give < prevBal) { - totSup -= (prevBal - give); - } else { - totSup += (give - prevBal); - } - stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); - } - } - - function dealERC721(address token, address to, uint256 id) internal virtual { - // check if token id is already minted and the actual owner. - (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); - require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); - - // get owner current balance - (, bytes memory fromBalData) = - token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); - uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); - - // get new user current balance - (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); - uint256 toPrevBal = abi.decode(toBalData, (uint256)); - - // update balances - stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); - stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); - - // update owner - stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); - } - - function deployCodeTo(string memory what, address where) internal virtual { - deployCodeTo(what, "", 0, where); - } - - function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { - deployCodeTo(what, args, 0, where); - } - - function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { - bytes memory creationCode = vm.getCode(what); - vm.etch(where, abi.encodePacked(creationCode, args)); - (bool success, bytes memory runtimeBytecode) = where.call{value: value}(""); - require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); - vm.etch(where, runtimeBytecode); - } - - // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. - function console2_log_StdCheats(string memory p0) private view { - (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); - status; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol deleted file mode 100644 index a302191..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdError.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test -pragma solidity >=0.6.2 <0.9.0; - -library stdError { - bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); - bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); - bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); - bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); - bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); - bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); - bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); - bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); - bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol deleted file mode 100644 index 056db98..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdInvariant.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; - -abstract contract StdInvariant { - struct FuzzSelector { - address addr; - bytes4[] selectors; - } - - struct FuzzArtifactSelector { - string artifact; - bytes4[] selectors; - } - - struct FuzzInterface { - address addr; - string[] artifacts; - } - - address[] private _excludedContracts; - address[] private _excludedSenders; - address[] private _targetedContracts; - address[] private _targetedSenders; - - string[] private _excludedArtifacts; - string[] private _targetedArtifacts; - - FuzzArtifactSelector[] private _targetedArtifactSelectors; - - FuzzSelector[] private _excludedSelectors; - FuzzSelector[] private _targetedSelectors; - - FuzzInterface[] private _targetedInterfaces; - - // Functions for users: - // These are intended to be called in tests. - - function excludeContract(address newExcludedContract_) internal { - _excludedContracts.push(newExcludedContract_); - } - - function excludeSelector(FuzzSelector memory newExcludedSelector_) internal { - _excludedSelectors.push(newExcludedSelector_); - } - - function excludeSender(address newExcludedSender_) internal { - _excludedSenders.push(newExcludedSender_); - } - - function excludeArtifact(string memory newExcludedArtifact_) internal { - _excludedArtifacts.push(newExcludedArtifact_); - } - - function targetArtifact(string memory newTargetedArtifact_) internal { - _targetedArtifacts.push(newTargetedArtifact_); - } - - function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal { - _targetedArtifactSelectors.push(newTargetedArtifactSelector_); - } - - function targetContract(address newTargetedContract_) internal { - _targetedContracts.push(newTargetedContract_); - } - - function targetSelector(FuzzSelector memory newTargetedSelector_) internal { - _targetedSelectors.push(newTargetedSelector_); - } - - function targetSender(address newTargetedSender_) internal { - _targetedSenders.push(newTargetedSender_); - } - - function targetInterface(FuzzInterface memory newTargetedInterface_) internal { - _targetedInterfaces.push(newTargetedInterface_); - } - - // Functions for forge: - // These are called by forge to run invariant tests and don't need to be called in tests. - - function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { - excludedArtifacts_ = _excludedArtifacts; - } - - function excludeContracts() public view returns (address[] memory excludedContracts_) { - excludedContracts_ = _excludedContracts; - } - - function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) { - excludedSelectors_ = _excludedSelectors; - } - - function excludeSenders() public view returns (address[] memory excludedSenders_) { - excludedSenders_ = _excludedSenders; - } - - function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { - targetedArtifacts_ = _targetedArtifacts; - } - - function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) { - targetedArtifactSelectors_ = _targetedArtifactSelectors; - } - - function targetContracts() public view returns (address[] memory targetedContracts_) { - targetedContracts_ = _targetedContracts; - } - - function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { - targetedSelectors_ = _targetedSelectors; - } - - function targetSenders() public view returns (address[] memory targetedSenders_) { - targetedSenders_ = _targetedSenders; - } - - function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { - targetedInterfaces_ = _targetedInterfaces; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol deleted file mode 100644 index 2a033c0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdJson.sol +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.0 <0.9.0; - -pragma experimental ABIEncoderV2; - -import {VmSafe} from "./Vm.sol"; - -// Helpers for parsing and writing JSON files -// To parse: -// ``` -// using stdJson for string; -// string memory json = vm.readFile(""); -// json.readUint(""); -// ``` -// To write: -// ``` -// using stdJson for string; -// string memory json = "json"; -// json.serialize("a", uint256(123)); -// string memory semiFinal = json.serialize("b", string("test")); -// string memory finalJson = json.serialize("c", semiFinal); -// finalJson.write(""); -// ``` - -library stdJson { - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - - function keyExists(string memory json, string memory key) internal view returns (bool) { - return vm.keyExistsJson(json, key); - } - - function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { - return vm.parseJson(json, key); - } - - function readUint(string memory json, string memory key) internal pure returns (uint256) { - return vm.parseJsonUint(json, key); - } - - function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { - return vm.parseJsonUintArray(json, key); - } - - function readInt(string memory json, string memory key) internal pure returns (int256) { - return vm.parseJsonInt(json, key); - } - - function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { - return vm.parseJsonIntArray(json, key); - } - - function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { - return vm.parseJsonBytes32(json, key); - } - - function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { - return vm.parseJsonBytes32Array(json, key); - } - - function readString(string memory json, string memory key) internal pure returns (string memory) { - return vm.parseJsonString(json, key); - } - - function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { - return vm.parseJsonStringArray(json, key); - } - - function readAddress(string memory json, string memory key) internal pure returns (address) { - return vm.parseJsonAddress(json, key); - } - - function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { - return vm.parseJsonAddressArray(json, key); - } - - function readBool(string memory json, string memory key) internal pure returns (bool) { - return vm.parseJsonBool(json, key); - } - - function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { - return vm.parseJsonBoolArray(json, key); - } - - function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { - return vm.parseJsonBytes(json, key); - } - - function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { - return vm.parseJsonBytesArray(json, key); - } - - function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { - return keyExists(json, key) ? readUint(json, key) : defaultValue; - } - - function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) - internal - view - returns (uint256[] memory) - { - return keyExists(json, key) ? readUintArray(json, key) : defaultValue; - } - - function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { - return keyExists(json, key) ? readInt(json, key) : defaultValue; - } - - function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) - internal - view - returns (int256[] memory) - { - return keyExists(json, key) ? readIntArray(json, key) : defaultValue; - } - - function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) - internal - view - returns (bytes32) - { - return keyExists(json, key) ? readBytes32(json, key) : defaultValue; - } - - function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) - internal - view - returns (bytes32[] memory) - { - return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; - } - - function readStringOr(string memory json, string memory key, string memory defaultValue) - internal - view - returns (string memory) - { - return keyExists(json, key) ? readString(json, key) : defaultValue; - } - - function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) - internal - view - returns (string[] memory) - { - return keyExists(json, key) ? readStringArray(json, key) : defaultValue; - } - - function readAddressOr(string memory json, string memory key, address defaultValue) - internal - view - returns (address) - { - return keyExists(json, key) ? readAddress(json, key) : defaultValue; - } - - function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) - internal - view - returns (address[] memory) - { - return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; - } - - function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { - return keyExists(json, key) ? readBool(json, key) : defaultValue; - } - - function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) - internal - view - returns (bool[] memory) - { - return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; - } - - function readBytesOr(string memory json, string memory key, bytes memory defaultValue) - internal - view - returns (bytes memory) - { - return keyExists(json, key) ? readBytes(json, key) : defaultValue; - } - - function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) - internal - view - returns (bytes[] memory) - { - return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; - } - - function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { - return vm.serializeJson(jsonKey, rootObject); - } - - function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { - return vm.serializeBool(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bool[] memory value) - internal - returns (string memory) - { - return vm.serializeBool(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { - return vm.serializeUint(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, uint256[] memory value) - internal - returns (string memory) - { - return vm.serializeUint(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { - return vm.serializeInt(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, int256[] memory value) - internal - returns (string memory) - { - return vm.serializeInt(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { - return vm.serializeAddress(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, address[] memory value) - internal - returns (string memory) - { - return vm.serializeAddress(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { - return vm.serializeBytes32(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes32[] memory value) - internal - returns (string memory) - { - return vm.serializeBytes32(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { - return vm.serializeBytes(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes[] memory value) - internal - returns (string memory) - { - return vm.serializeBytes(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, string memory value) - internal - returns (string memory) - { - return vm.serializeString(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, string[] memory value) - internal - returns (string memory) - { - return vm.serializeString(jsonKey, key, value); - } - - function write(string memory jsonKey, string memory path) internal { - vm.writeJson(jsonKey, path); - } - - function write(string memory jsonKey, string memory path, string memory valueKey) internal { - vm.writeJson(jsonKey, path, valueKey); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol deleted file mode 100644 index 459523b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdMath.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -library stdMath { - int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; - - function abs(int256 a) internal pure returns (uint256) { - // Required or it will fail when `a = type(int256).min` - if (a == INT256_MIN) { - return 57896044618658097711785492504343953926634992332820282019728792003956564819968; - } - - return uint256(a > 0 ? a : -a); - } - - function delta(uint256 a, uint256 b) internal pure returns (uint256) { - return a > b ? a - b : b - a; - } - - function delta(int256 a, int256 b) internal pure returns (uint256) { - // a and b are of the same sign - // this works thanks to two's complement, the left-most bit is the sign bit - if ((a ^ b) > -1) { - return delta(abs(a), abs(b)); - } - - // a and b are of opposite signs - return abs(a) + abs(b); - } - - function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 absDelta = delta(a, b); - - return absDelta * 1e18 / b; - } - - function percentDelta(int256 a, int256 b) internal pure returns (uint256) { - uint256 absDelta = delta(a, b); - uint256 absB = abs(b); - - return absDelta * 1e18 / absB; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol deleted file mode 100644 index bf3223d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStorage.sol +++ /dev/null @@ -1,473 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -import {Vm} from "./Vm.sol"; - -struct FindData { - uint256 slot; - uint256 offsetLeft; - uint256 offsetRight; - bool found; -} - -struct StdStorage { - mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; - bytes32[] _keys; - bytes4 _sig; - uint256 _depth; - address _target; - bytes32 _set; - bool _enable_packed_slots; - bytes _calldata; -} - -library stdStorageSafe { - event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); - event WARNING_UninitedSlot(address who, uint256 slot); - - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - function sigs(string memory sigStr) internal pure returns (bytes4) { - return bytes4(keccak256(bytes(sigStr))); - } - - function getCallParams(StdStorage storage self) internal view returns (bytes memory) { - if (self._calldata.length == 0) { - return flatten(self._keys); - } else { - return self._calldata; - } - } - - // Calls target contract with configured parameters - function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { - bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); - (bool success, bytes memory rdat) = self._target.staticcall(cald); - bytes32 result = bytesToBytes32(rdat, 32 * self._depth); - - return (success, result); - } - - // Tries mutating slot value to determine if the targeted value is stored in it. - // If current value is 0, then we are setting slot value to type(uint256).max - // Otherwise, we set it to 0. That way, return value should always be affected. - function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { - bytes32 prevSlotValue = vm.load(self._target, slot); - (bool success, bytes32 prevReturnValue) = callTarget(self); - - bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); - vm.store(self._target, slot, testVal); - - (, bytes32 newReturnValue) = callTarget(self); - - vm.store(self._target, slot, prevSlotValue); - - return (success && (prevReturnValue != newReturnValue)); - } - - // Tries setting one of the bits in slot to 1 until return value changes. - // Index of resulted bit is an offset packed slot has from left/right side - function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { - for (uint256 offset = 0; offset < 256; offset++) { - uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); - vm.store(self._target, slot, bytes32(valueToPut)); - - (bool success, bytes32 data) = callTarget(self); - - if (success && (uint256(data) > 0)) { - return (true, offset); - } - } - return (false, 0); - } - - function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { - bytes32 prevSlotValue = vm.load(self._target, slot); - - (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); - (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); - - // `findOffset` may mutate slot value, so we are setting it to initial value - vm.store(self._target, slot, prevSlotValue); - return (foundLeft && foundRight, offsetLeft, offsetRight); - } - - function find(StdStorage storage self) internal returns (FindData storage) { - return find(self, true); - } - - /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against - // slot complexity: - // if flat, will be bytes32(uint256(uint)); - // if map, will be keccak256(abi.encode(key, uint(slot))); - // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); - // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); - function find(StdStorage storage self, bool _clear) internal returns (FindData storage) { - address who = self._target; - bytes4 fsig = self._sig; - uint256 field_depth = self._depth; - bytes memory params = getCallParams(self); - - // calldata to test against - if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { - if (_clear) { - clear(self); - } - return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; - } - vm.record(); - (, bytes32 callResult) = callTarget(self); - (bytes32[] memory reads,) = vm.accesses(address(who)); - - if (reads.length == 0) { - revert("stdStorage find(StdStorage): No storage use detected for target."); - } else { - for (uint256 i = reads.length; --i >= 0;) { - bytes32 prev = vm.load(who, reads[i]); - if (prev == bytes32(0)) { - emit WARNING_UninitedSlot(who, uint256(reads[i])); - } - - if (!checkSlotMutatesCall(self, reads[i])) { - continue; - } - - (uint256 offsetLeft, uint256 offsetRight) = (0, 0); - - if (self._enable_packed_slots) { - bool found; - (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); - if (!found) { - continue; - } - } - - // Check that value between found offsets is equal to the current call result - uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; - - if (uint256(callResult) != curVal) { - continue; - } - - emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); - self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = - FindData(uint256(reads[i]), offsetLeft, offsetRight, true); - break; - } - } - - require( - self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, - "stdStorage find(StdStorage): Slot(s) not found." - ); - - if (_clear) { - clear(self); - } - return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; - } - - function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { - self._target = _target; - return self; - } - - function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { - self._sig = _sig; - return self; - } - - function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { - self._sig = sigs(_sig); - return self; - } - - function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { - self._calldata = _calldata; - return self; - } - - function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { - self._keys.push(bytes32(uint256(uint160(who)))); - return self; - } - - function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { - self._keys.push(bytes32(amt)); - return self; - } - - function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { - self._keys.push(key); - return self; - } - - function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { - self._enable_packed_slots = true; - return self; - } - - function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { - self._depth = _depth; - return self; - } - - function read(StdStorage storage self) private returns (bytes memory) { - FindData storage data = find(self, false); - uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); - uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; - clear(self); - return abi.encode(value); - } - - function read_bytes32(StdStorage storage self) internal returns (bytes32) { - return abi.decode(read(self), (bytes32)); - } - - function read_bool(StdStorage storage self) internal returns (bool) { - int256 v = read_int(self); - if (v == 0) return false; - if (v == 1) return true; - revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); - } - - function read_address(StdStorage storage self) internal returns (address) { - return abi.decode(read(self), (address)); - } - - function read_uint(StdStorage storage self) internal returns (uint256) { - return abi.decode(read(self), (uint256)); - } - - function read_int(StdStorage storage self) internal returns (int256) { - return abi.decode(read(self), (int256)); - } - - function parent(StdStorage storage self) internal returns (uint256, bytes32) { - address who = self._target; - uint256 field_depth = self._depth; - vm.startMappingRecording(); - uint256 child = find(self, true).slot - field_depth; - (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); - if (!found) { - revert( - "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." - ); - } - return (uint256(parent_slot), key); - } - - function root(StdStorage storage self) internal returns (uint256) { - address who = self._target; - uint256 field_depth = self._depth; - vm.startMappingRecording(); - uint256 child = find(self, true).slot - field_depth; - bool found; - bytes32 root_slot; - bytes32 parent_slot; - (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); - if (!found) { - revert( - "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." - ); - } - while (found) { - root_slot = parent_slot; - (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); - } - return uint256(root_slot); - } - - function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { - bytes32 out; - - uint256 max = b.length > 32 ? 32 : b.length; - for (uint256 i = 0; i < max; i++) { - out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); - } - return out; - } - - function flatten(bytes32[] memory b) private pure returns (bytes memory) { - bytes memory result = new bytes(b.length * 32); - for (uint256 i = 0; i < b.length; i++) { - bytes32 k = b[i]; - /// @solidity memory-safe-assembly - assembly { - mstore(add(result, add(32, mul(32, i))), k) - } - } - - return result; - } - - function clear(StdStorage storage self) internal { - delete self._target; - delete self._sig; - delete self._keys; - delete self._depth; - delete self._enable_packed_slots; - delete self._calldata; - } - - // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` - // (slotValue & mask) >> offsetRight will be the value of the given packed variable - function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { - // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; - // using assembly because (1 << 256) causes overflow - assembly { - mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) - } - } - - // Returns slot value with updated packed variable. - function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) - internal - pure - returns (bytes32 newValue) - { - return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); - } -} - -library stdStorage { - Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - - function sigs(string memory sigStr) internal pure returns (bytes4) { - return stdStorageSafe.sigs(sigStr); - } - - function find(StdStorage storage self) internal returns (uint256) { - return find(self, true); - } - - function find(StdStorage storage self, bool _clear) internal returns (uint256) { - return stdStorageSafe.find(self, _clear).slot; - } - - function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { - return stdStorageSafe.target(self, _target); - } - - function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { - return stdStorageSafe.sig(self, _sig); - } - - function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { - return stdStorageSafe.sig(self, _sig); - } - - function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { - return stdStorageSafe.with_key(self, who); - } - - function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { - return stdStorageSafe.with_key(self, amt); - } - - function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { - return stdStorageSafe.with_key(self, key); - } - - function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { - return stdStorageSafe.with_calldata(self, _calldata); - } - - function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { - return stdStorageSafe.enable_packed_slots(self); - } - - function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { - return stdStorageSafe.depth(self, _depth); - } - - function clear(StdStorage storage self) internal { - stdStorageSafe.clear(self); - } - - function checked_write(StdStorage storage self, address who) internal { - checked_write(self, bytes32(uint256(uint160(who)))); - } - - function checked_write(StdStorage storage self, uint256 amt) internal { - checked_write(self, bytes32(amt)); - } - - function checked_write_int(StdStorage storage self, int256 val) internal { - checked_write(self, bytes32(uint256(val))); - } - - function checked_write(StdStorage storage self, bool write) internal { - bytes32 t; - /// @solidity memory-safe-assembly - assembly { - t := write - } - checked_write(self, t); - } - - function checked_write(StdStorage storage self, bytes32 set) internal { - address who = self._target; - bytes4 fsig = self._sig; - uint256 field_depth = self._depth; - bytes memory params = stdStorageSafe.getCallParams(self); - - if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { - find(self, false); - } - FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; - if ((data.offsetLeft + data.offsetRight) > 0) { - uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); - require( - uint256(set) < maxVal, - string( - abi.encodePacked( - "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", - vm.toString(maxVal) - ) - ) - ); - } - bytes32 curVal = vm.load(who, bytes32(data.slot)); - bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); - - vm.store(who, bytes32(data.slot), valToSet); - - (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); - - if (!success || callResult != set) { - vm.store(who, bytes32(data.slot), curVal); - revert("stdStorage find(StdStorage): Failed to write value."); - } - clear(self); - } - - function read_bytes32(StdStorage storage self) internal returns (bytes32) { - return stdStorageSafe.read_bytes32(self); - } - - function read_bool(StdStorage storage self) internal returns (bool) { - return stdStorageSafe.read_bool(self); - } - - function read_address(StdStorage storage self) internal returns (address) { - return stdStorageSafe.read_address(self); - } - - function read_uint(StdStorage storage self) internal returns (uint256) { - return stdStorageSafe.read_uint(self); - } - - function read_int(StdStorage storage self) internal returns (int256) { - return stdStorageSafe.read_int(self); - } - - function parent(StdStorage storage self) internal returns (uint256, bytes32) { - return stdStorageSafe.parent(self); - } - - function root(StdStorage storage self) internal returns (uint256) { - return stdStorageSafe.root(self); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol deleted file mode 100644 index d371e0c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdStyle.sol +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; - -import {VmSafe} from "./Vm.sol"; - -library StdStyle { - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - - string constant RED = "\u001b[91m"; - string constant GREEN = "\u001b[92m"; - string constant YELLOW = "\u001b[93m"; - string constant BLUE = "\u001b[94m"; - string constant MAGENTA = "\u001b[95m"; - string constant CYAN = "\u001b[96m"; - string constant BOLD = "\u001b[1m"; - string constant DIM = "\u001b[2m"; - string constant ITALIC = "\u001b[3m"; - string constant UNDERLINE = "\u001b[4m"; - string constant INVERSE = "\u001b[7m"; - string constant RESET = "\u001b[0m"; - - function styleConcat(string memory style, string memory self) private pure returns (string memory) { - return string(abi.encodePacked(style, self, RESET)); - } - - function red(string memory self) internal pure returns (string memory) { - return styleConcat(RED, self); - } - - function red(uint256 self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function red(int256 self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function red(address self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function red(bool self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function redBytes(bytes memory self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function redBytes32(bytes32 self) internal pure returns (string memory) { - return red(vm.toString(self)); - } - - function green(string memory self) internal pure returns (string memory) { - return styleConcat(GREEN, self); - } - - function green(uint256 self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function green(int256 self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function green(address self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function green(bool self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function greenBytes(bytes memory self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function greenBytes32(bytes32 self) internal pure returns (string memory) { - return green(vm.toString(self)); - } - - function yellow(string memory self) internal pure returns (string memory) { - return styleConcat(YELLOW, self); - } - - function yellow(uint256 self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function yellow(int256 self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function yellow(address self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function yellow(bool self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function yellowBytes(bytes memory self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function yellowBytes32(bytes32 self) internal pure returns (string memory) { - return yellow(vm.toString(self)); - } - - function blue(string memory self) internal pure returns (string memory) { - return styleConcat(BLUE, self); - } - - function blue(uint256 self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function blue(int256 self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function blue(address self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function blue(bool self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function blueBytes(bytes memory self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function blueBytes32(bytes32 self) internal pure returns (string memory) { - return blue(vm.toString(self)); - } - - function magenta(string memory self) internal pure returns (string memory) { - return styleConcat(MAGENTA, self); - } - - function magenta(uint256 self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function magenta(int256 self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function magenta(address self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function magenta(bool self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function magentaBytes(bytes memory self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function magentaBytes32(bytes32 self) internal pure returns (string memory) { - return magenta(vm.toString(self)); - } - - function cyan(string memory self) internal pure returns (string memory) { - return styleConcat(CYAN, self); - } - - function cyan(uint256 self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function cyan(int256 self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function cyan(address self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function cyan(bool self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function cyanBytes(bytes memory self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function cyanBytes32(bytes32 self) internal pure returns (string memory) { - return cyan(vm.toString(self)); - } - - function bold(string memory self) internal pure returns (string memory) { - return styleConcat(BOLD, self); - } - - function bold(uint256 self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function bold(int256 self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function bold(address self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function bold(bool self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function boldBytes(bytes memory self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function boldBytes32(bytes32 self) internal pure returns (string memory) { - return bold(vm.toString(self)); - } - - function dim(string memory self) internal pure returns (string memory) { - return styleConcat(DIM, self); - } - - function dim(uint256 self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function dim(int256 self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function dim(address self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function dim(bool self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function dimBytes(bytes memory self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function dimBytes32(bytes32 self) internal pure returns (string memory) { - return dim(vm.toString(self)); - } - - function italic(string memory self) internal pure returns (string memory) { - return styleConcat(ITALIC, self); - } - - function italic(uint256 self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function italic(int256 self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function italic(address self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function italic(bool self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function italicBytes(bytes memory self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function italicBytes32(bytes32 self) internal pure returns (string memory) { - return italic(vm.toString(self)); - } - - function underline(string memory self) internal pure returns (string memory) { - return styleConcat(UNDERLINE, self); - } - - function underline(uint256 self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function underline(int256 self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function underline(address self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function underline(bool self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function underlineBytes(bytes memory self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function underlineBytes32(bytes32 self) internal pure returns (string memory) { - return underline(vm.toString(self)); - } - - function inverse(string memory self) internal pure returns (string memory) { - return styleConcat(INVERSE, self); - } - - function inverse(uint256 self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } - - function inverse(int256 self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } - - function inverse(address self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } - - function inverse(bool self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } - - function inverseBytes(bytes memory self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } - - function inverseBytes32(bytes32 self) internal pure returns (string memory) { - return inverse(vm.toString(self)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol deleted file mode 100644 index 7ad3be2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdToml.sol +++ /dev/null @@ -1,283 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.0 <0.9.0; - -pragma experimental ABIEncoderV2; - -import {VmSafe} from "./Vm.sol"; - -// Helpers for parsing and writing TOML files -// To parse: -// ``` -// using stdToml for string; -// string memory toml = vm.readFile(""); -// toml.readUint(""); -// ``` -// To write: -// ``` -// using stdToml for string; -// string memory json = "json"; -// json.serialize("a", uint256(123)); -// string memory semiFinal = json.serialize("b", string("test")); -// string memory finalJson = json.serialize("c", semiFinal); -// finalJson.write(""); -// ``` - -library stdToml { - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - - function keyExists(string memory toml, string memory key) internal view returns (bool) { - return vm.keyExistsToml(toml, key); - } - - function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { - return vm.parseToml(toml, key); - } - - function readUint(string memory toml, string memory key) internal pure returns (uint256) { - return vm.parseTomlUint(toml, key); - } - - function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { - return vm.parseTomlUintArray(toml, key); - } - - function readInt(string memory toml, string memory key) internal pure returns (int256) { - return vm.parseTomlInt(toml, key); - } - - function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { - return vm.parseTomlIntArray(toml, key); - } - - function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { - return vm.parseTomlBytes32(toml, key); - } - - function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { - return vm.parseTomlBytes32Array(toml, key); - } - - function readString(string memory toml, string memory key) internal pure returns (string memory) { - return vm.parseTomlString(toml, key); - } - - function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { - return vm.parseTomlStringArray(toml, key); - } - - function readAddress(string memory toml, string memory key) internal pure returns (address) { - return vm.parseTomlAddress(toml, key); - } - - function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { - return vm.parseTomlAddressArray(toml, key); - } - - function readBool(string memory toml, string memory key) internal pure returns (bool) { - return vm.parseTomlBool(toml, key); - } - - function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { - return vm.parseTomlBoolArray(toml, key); - } - - function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { - return vm.parseTomlBytes(toml, key); - } - - function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { - return vm.parseTomlBytesArray(toml, key); - } - - function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { - return keyExists(toml, key) ? readUint(toml, key) : defaultValue; - } - - function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) - internal - view - returns (uint256[] memory) - { - return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; - } - - function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { - return keyExists(toml, key) ? readInt(toml, key) : defaultValue; - } - - function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) - internal - view - returns (int256[] memory) - { - return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; - } - - function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) - internal - view - returns (bytes32) - { - return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; - } - - function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) - internal - view - returns (bytes32[] memory) - { - return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; - } - - function readStringOr(string memory toml, string memory key, string memory defaultValue) - internal - view - returns (string memory) - { - return keyExists(toml, key) ? readString(toml, key) : defaultValue; - } - - function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) - internal - view - returns (string[] memory) - { - return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; - } - - function readAddressOr(string memory toml, string memory key, address defaultValue) - internal - view - returns (address) - { - return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; - } - - function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) - internal - view - returns (address[] memory) - { - return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; - } - - function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { - return keyExists(toml, key) ? readBool(toml, key) : defaultValue; - } - - function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) - internal - view - returns (bool[] memory) - { - return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; - } - - function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) - internal - view - returns (bytes memory) - { - return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; - } - - function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) - internal - view - returns (bytes[] memory) - { - return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; - } - - function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { - return vm.serializeJson(jsonKey, rootObject); - } - - function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { - return vm.serializeBool(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bool[] memory value) - internal - returns (string memory) - { - return vm.serializeBool(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { - return vm.serializeUint(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, uint256[] memory value) - internal - returns (string memory) - { - return vm.serializeUint(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { - return vm.serializeInt(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, int256[] memory value) - internal - returns (string memory) - { - return vm.serializeInt(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { - return vm.serializeAddress(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, address[] memory value) - internal - returns (string memory) - { - return vm.serializeAddress(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { - return vm.serializeBytes32(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes32[] memory value) - internal - returns (string memory) - { - return vm.serializeBytes32(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { - return vm.serializeBytes(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, bytes[] memory value) - internal - returns (string memory) - { - return vm.serializeBytes(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, string memory value) - internal - returns (string memory) - { - return vm.serializeString(jsonKey, key, value); - } - - function serialize(string memory jsonKey, string memory key, string[] memory value) - internal - returns (string memory) - { - return vm.serializeString(jsonKey, key, value); - } - - function write(string memory jsonKey, string memory path) internal { - vm.writeToml(jsonKey, path); - } - - function write(string memory jsonKey, string memory path, string memory valueKey) internal { - vm.writeToml(jsonKey, path, valueKey); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol deleted file mode 100644 index 5d12043..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/StdUtils.sol +++ /dev/null @@ -1,226 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; - -import {IMulticall3} from "./interfaces/IMulticall3.sol"; -import {MockERC20} from "./mocks/MockERC20.sol"; -import {MockERC721} from "./mocks/MockERC721.sol"; -import {VmSafe} from "./Vm.sol"; - -abstract contract StdUtils { - /*////////////////////////////////////////////////////////////////////////// - CONSTANTS - //////////////////////////////////////////////////////////////////////////*/ - - IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); - VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; - uint256 private constant INT256_MIN_ABS = - 57896044618658097711785492504343953926634992332820282019728792003956564819968; - uint256 private constant SECP256K1_ORDER = - 115792089237316195423570985008687907852837564279074904382605163141518161494337; - uint256 private constant UINT256_MAX = - 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. - address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - - /*////////////////////////////////////////////////////////////////////////// - INTERNAL FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { - require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); - // If x is between min and max, return x directly. This is to ensure that dictionary values - // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 - if (x >= min && x <= max) return x; - - uint256 size = max - min + 1; - - // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. - // This helps ensure coverage of the min/max values. - if (x <= 3 && size > x) return min + x; - if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); - - // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. - if (x > max) { - uint256 diff = x - max; - uint256 rem = diff % size; - if (rem == 0) return max; - result = min + rem - 1; - } else if (x < min) { - uint256 diff = min - x; - uint256 rem = diff % size; - if (rem == 0) return min; - result = max - rem + 1; - } - } - - function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { - result = _bound(x, min, max); - console2_log_StdUtils("Bound result", result); - } - - function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { - require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); - - // Shifting all int256 values to uint256 to use _bound function. The range of two types are: - // int256 : -(2**255) ~ (2**255 - 1) - // uint256: 0 ~ (2**256 - 1) - // So, add 2**255, INT256_MIN_ABS to the integer values. - // - // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. - // So, use `~uint256(x) + 1` instead. - uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); - uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); - uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); - - uint256 y = _bound(_x, _min, _max); - - // To move it back to int256 value, subtract INT256_MIN_ABS at here. - result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); - } - - function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { - result = _bound(x, min, max); - console2_log_StdUtils("Bound result", vm.toString(result)); - } - - function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { - result = _bound(privateKey, 1, SECP256K1_ORDER - 1); - } - - function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { - require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); - return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); - } - - /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce - /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) - function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { - console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); - return vm.computeCreateAddress(deployer, nonce); - } - - function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) - internal - pure - virtual - returns (address) - { - console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); - return vm.computeCreate2Address(salt, initcodeHash, deployer); - } - - /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer - function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { - console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); - return vm.computeCreate2Address(salt, initCodeHash); - } - - /// @dev returns an initialized mock ERC20 contract - function deployMockERC20(string memory name, string memory symbol, uint8 decimals) - internal - returns (MockERC20 mock) - { - mock = new MockERC20(); - mock.initialize(name, symbol, decimals); - } - - /// @dev returns an initialized mock ERC721 contract - function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { - mock = new MockERC721(); - mock.initialize(name, symbol); - } - - /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments - /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode - function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { - return hashInitCode(creationCode, ""); - } - - /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 - /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode - /// @param args the ABI-encoded arguments to the constructor of C - function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(creationCode, args)); - } - - // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. - function getTokenBalances(address token, address[] memory addresses) - internal - virtual - returns (uint256[] memory balances) - { - uint256 tokenCodeSize; - assembly { - tokenCodeSize := extcodesize(token) - } - require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); - - // ABI encode the aggregate call to Multicall3. - uint256 length = addresses.length; - IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); - for (uint256 i = 0; i < length; ++i) { - // 0x70a08231 = bytes4("balanceOf(address)")) - calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); - } - - // Make the aggregate call. - (, bytes[] memory returnData) = multicall.aggregate(calls); - - // ABI decode the return data and return the balances. - balances = new uint256[](length); - for (uint256 i = 0; i < length; ++i) { - balances[i] = abi.decode(returnData[i], (uint256)); - } - } - - /*////////////////////////////////////////////////////////////////////////// - PRIVATE FUNCTIONS - //////////////////////////////////////////////////////////////////////////*/ - - function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { - return address(uint160(uint256(bytesValue))); - } - - // This section is used to prevent the compilation of console, which shortens the compilation time when console is - // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid - // any breaking changes to function signatures. - function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) - internal - pure - returns (function(bytes memory) internal pure fnOut) - { - assembly { - fnOut := fnIn - } - } - - function _sendLogPayload(bytes memory payload) internal pure { - _castLogPayloadViewToPure(_sendLogPayloadView)(payload); - } - - function _sendLogPayloadView(bytes memory payload) private view { - uint256 payloadLength = payload.length; - address consoleAddress = CONSOLE2_ADDRESS; - /// @solidity memory-safe-assembly - assembly { - let payloadStart := add(payload, 32) - let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) - } - } - - function console2_log_StdUtils(string memory p0) private pure { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function console2_log_StdUtils(string memory p0, uint256 p1) private pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); - } - - function console2_log_StdUtils(string memory p0, string memory p1) private pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol deleted file mode 100644 index 5ff60ea..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Test.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; - -// 💬 ABOUT -// Forge Std's default Test. - -// 🧩 MODULES -import {console} from "./console.sol"; -import {console2} from "./console2.sol"; -import {safeconsole} from "./safeconsole.sol"; -import {StdAssertions} from "./StdAssertions.sol"; -import {StdChains} from "./StdChains.sol"; -import {StdCheats} from "./StdCheats.sol"; -import {stdError} from "./StdError.sol"; -import {StdInvariant} from "./StdInvariant.sol"; -import {stdJson} from "./StdJson.sol"; -import {stdMath} from "./StdMath.sol"; -import {StdStorage, stdStorage} from "./StdStorage.sol"; -import {StdStyle} from "./StdStyle.sol"; -import {stdToml} from "./StdToml.sol"; -import {StdUtils} from "./StdUtils.sol"; -import {Vm} from "./Vm.sol"; - -// 📦 BOILERPLATE -import {TestBase} from "./Base.sol"; - -// ⭐️ TEST -abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils { - // Note: IS_TEST() must return true. - bool public IS_TEST = true; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol deleted file mode 100644 index 591508c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/Vm.sol +++ /dev/null @@ -1,1968 +0,0 @@ -// Automatically @generated by scripts/vm.py. Do not modify manually. - -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity >=0.6.2 <0.9.0; -pragma experimental ABIEncoderV2; - -/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may -/// result in Script simulations differing from on-chain execution. It is recommended to only use -/// these cheats in scripts. -interface VmSafe { - /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. - enum CallerMode { - // No caller modification is currently active. - None, - // A one time broadcast triggered by a `vm.broadcast()` call is currently active. - Broadcast, - // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. - RecurrentBroadcast, - // A one time prank triggered by a `vm.prank()` call is currently active. - Prank, - // A recurrent prank triggered by a `vm.startPrank()` call is currently active. - RecurrentPrank - } - - /// The kind of account access that occurred. - enum AccountAccessKind { - // The account was called. - Call, - // The account was called via delegatecall. - DelegateCall, - // The account was called via callcode. - CallCode, - // The account was called via staticcall. - StaticCall, - // The account was created. - Create, - // The account was selfdestructed. - SelfDestruct, - // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). - Resume, - // The account's balance was read. - Balance, - // The account's codesize was read. - Extcodesize, - // The account's codehash was read. - Extcodehash, - // The account's code was copied. - Extcodecopy - } - - /// Forge execution contexts. - enum ForgeContext { - // Test group execution context (test, coverage or snapshot). - TestGroup, - // `forge test` execution context. - Test, - // `forge coverage` execution context. - Coverage, - // `forge snapshot` execution context. - Snapshot, - // Script group execution context (dry run, broadcast or resume). - ScriptGroup, - // `forge script` execution context. - ScriptDryRun, - // `forge script --broadcast` execution context. - ScriptBroadcast, - // `forge script --resume` execution context. - ScriptResume, - // Unknown `forge` execution context. - Unknown - } - - /// An Ethereum log. Returned by `getRecordedLogs`. - struct Log { - // The topics of the log, including the signature, if any. - bytes32[] topics; - // The raw data of the log. - bytes data; - // The address of the log's emitter. - address emitter; - } - - /// An RPC URL and its alias. Returned by `rpcUrlStructs`. - struct Rpc { - // The alias of the RPC URL. - string key; - // The RPC URL. - string url; - } - - /// An RPC log object. Returned by `eth_getLogs`. - struct EthGetLogs { - // The address of the log's emitter. - address emitter; - // The topics of the log, including the signature, if any. - bytes32[] topics; - // The raw data of the log. - bytes data; - // The block hash. - bytes32 blockHash; - // The block number. - uint64 blockNumber; - // The transaction hash. - bytes32 transactionHash; - // The transaction index in the block. - uint64 transactionIndex; - // The log index. - uint256 logIndex; - // Whether the log was removed. - bool removed; - } - - /// A single entry in a directory listing. Returned by `readDir`. - struct DirEntry { - // The error message, if any. - string errorMessage; - // The path of the entry. - string path; - // The depth of the entry. - uint64 depth; - // Whether the entry is a directory. - bool isDir; - // Whether the entry is a symlink. - bool isSymlink; - } - - /// Metadata information about a file. - /// This structure is returned from the `fsMetadata` function and represents known - /// metadata about a file such as its permissions, size, modification - /// times, etc. - struct FsMetadata { - // True if this metadata is for a directory. - bool isDir; - // True if this metadata is for a symlink. - bool isSymlink; - // The size of the file, in bytes, this metadata is for. - uint256 length; - // True if this metadata is for a readonly (unwritable) file. - bool readOnly; - // The last modification time listed in this metadata. - uint256 modified; - // The last access time of this metadata. - uint256 accessed; - // The creation time listed in this metadata. - uint256 created; - } - - /// A wallet with a public and private key. - struct Wallet { - // The wallet's address. - address addr; - // The wallet's public key `X`. - uint256 publicKeyX; - // The wallet's public key `Y`. - uint256 publicKeyY; - // The wallet's private key. - uint256 privateKey; - } - - /// The result of a `tryFfi` call. - struct FfiResult { - // The exit code of the call. - int32 exitCode; - // The optionally hex-decoded `stdout` data. - bytes stdout; - // The `stderr` data. - bytes stderr; - } - - /// Information on the chain and fork. - struct ChainInfo { - // The fork identifier. Set to zero if no fork is active. - uint256 forkId; - // The chain ID of the current fork. - uint256 chainId; - } - - /// The result of a `stopAndReturnStateDiff` call. - struct AccountAccess { - // The chain and fork the access occurred. - ChainInfo chainInfo; - // The kind of account access that determines what the account is. - // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. - // If kind is Create, then the account is the newly created account. - // If kind is SelfDestruct, then the account is the selfdestruct recipient. - // If kind is a Resume, then account represents a account context that has resumed. - AccountAccessKind kind; - // The account that was accessed. - // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. - address account; - // What accessed the account. - address accessor; - // If the account was initialized or empty prior to the access. - // An account is considered initialized if it has code, a - // non-zero nonce, or a non-zero balance. - bool initialized; - // The previous balance of the accessed account. - uint256 oldBalance; - // The potential new balance of the accessed account. - // That is, all balance changes are recorded here, even if reverts occurred. - uint256 newBalance; - // Code of the account deployed by CREATE. - bytes deployedCode; - // Value passed along with the account access - uint256 value; - // Input data provided to the CREATE or CALL - bytes data; - // If this access reverted in either the current or parent context. - bool reverted; - // An ordered list of storage accesses made during an account access operation. - StorageAccess[] storageAccesses; - // Call depth traversed during the recording of state differences - uint64 depth; - } - - /// The storage accessed during an `AccountAccess`. - struct StorageAccess { - // The account whose storage was accessed. - address account; - // The slot that was accessed. - bytes32 slot; - // If the access was a write. - bool isWrite; - // The previous value of the slot. - bytes32 previousValue; - // The new value of the slot. - bytes32 newValue; - // If the access was reverted. - bool reverted; - } - - /// Gas used. Returned by `lastCallGas`. - struct Gas { - // The gas limit of the call. - uint64 gasLimit; - // The total gas used. - uint64 gasTotalUsed; - // DEPRECATED: The amount of gas used for memory expansion. Ref: - uint64 gasMemoryUsed; - // The amount of gas refunded. - int64 gasRefunded; - // The amount of gas remaining. - uint64 gasRemaining; - } - - // ======== Crypto ======== - - /// Derives a private key from the name, labels the account with that name, and returns the wallet. - function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); - - /// Generates a wallet from the private key and returns the wallet. - function createWallet(uint256 privateKey) external returns (Wallet memory wallet); - - /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. - function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); - - /// Derive a private key from a provided mnenomic string (or mnenomic file path) - /// at the derivation path `m/44'/60'/0'/0/{index}`. - function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); - - /// Derive a private key from a provided mnenomic string (or mnenomic file path) - /// at `{derivationPath}{index}`. - function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) - external - pure - returns (uint256 privateKey); - - /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language - /// at the derivation path `m/44'/60'/0'/0/{index}`. - function deriveKey(string calldata mnemonic, uint32 index, string calldata language) - external - pure - returns (uint256 privateKey); - - /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language - /// at `{derivationPath}{index}`. - function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) - external - pure - returns (uint256 privateKey); - - /// Derives secp256r1 public key from the provided `privateKey`. - function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); - - /// Adds a private key to the local forge wallet and returns the address. - function rememberKey(uint256 privateKey) external returns (address keyAddr); - - /// Signs data with a `Wallet`. - /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the - /// signature's `s` value, and the recovery id `v` in a single bytes32. - /// This format reduces the signature size from 65 to 64 bytes. - function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); - - /// Signs `digest` with `privateKey` using the secp256k1 curve. - /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the - /// signature's `s` value, and the recovery id `v` in a single bytes32. - /// This format reduces the signature size from 65 to 64 bytes. - function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the - /// signature's `s` value, and the recovery id `v` in a single bytes32. - /// This format reduces the signature size from 65 to 64 bytes. - /// If `--sender` is provided, the signer with provided address is used, otherwise, - /// if exactly one signer is provided to the script, that signer is used. - /// Raises error if signer passed through `--sender` does not match any unlocked signers or - /// if `--sender` is not provided and not exactly one signer is passed to the script. - function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the - /// signature's `s` value, and the recovery id `v` in a single bytes32. - /// This format reduces the signature size from 65 to 64 bytes. - /// Raises error if none of the signers passed into the script have provided address. - function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); - - /// Signs `digest` with `privateKey` using the secp256r1 curve. - function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); - - /// Signs data with a `Wallet`. - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); - - /// Signs `digest` with `privateKey` using the secp256k1 curve. - function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// If `--sender` is provided, the signer with provided address is used, otherwise, - /// if exactly one signer is provided to the script, that signer is used. - /// Raises error if signer passed through `--sender` does not match any unlocked signers or - /// if `--sender` is not provided and not exactly one signer is passed to the script. - function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); - - /// Signs `digest` with signer provided to script using the secp256k1 curve. - /// Raises error if none of the signers passed into the script have provided address. - function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); - - // ======== Environment ======== - - /// Gets the environment variable `name` and parses it as `address`. - /// Reverts if the variable was not found or could not be parsed. - function envAddress(string calldata name) external view returns (address value); - - /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); - - /// Gets the environment variable `name` and parses it as `bool`. - /// Reverts if the variable was not found or could not be parsed. - function envBool(string calldata name) external view returns (bool value); - - /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); - - /// Gets the environment variable `name` and parses it as `bytes32`. - /// Reverts if the variable was not found or could not be parsed. - function envBytes32(string calldata name) external view returns (bytes32 value); - - /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); - - /// Gets the environment variable `name` and parses it as `bytes`. - /// Reverts if the variable was not found or could not be parsed. - function envBytes(string calldata name) external view returns (bytes memory value); - - /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); - - /// Gets the environment variable `name` and returns true if it exists, else returns false. - function envExists(string calldata name) external view returns (bool result); - - /// Gets the environment variable `name` and parses it as `int256`. - /// Reverts if the variable was not found or could not be parsed. - function envInt(string calldata name) external view returns (int256 value); - - /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); - - /// Gets the environment variable `name` and parses it as `bool`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, bool defaultValue) external view returns (bool value); - - /// Gets the environment variable `name` and parses it as `uint256`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); - - /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) - external - view - returns (address[] memory value); - - /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) - external - view - returns (bytes32[] memory value); - - /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) - external - view - returns (string[] memory value); - - /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) - external - view - returns (bytes[] memory value); - - /// Gets the environment variable `name` and parses it as `int256`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); - - /// Gets the environment variable `name` and parses it as `address`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, address defaultValue) external view returns (address value); - - /// Gets the environment variable `name` and parses it as `bytes32`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); - - /// Gets the environment variable `name` and parses it as `string`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); - - /// Gets the environment variable `name` and parses it as `bytes`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); - - /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) - external - view - returns (bool[] memory value); - - /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) - external - view - returns (uint256[] memory value); - - /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. - /// Reverts if the variable could not be parsed. - /// Returns `defaultValue` if the variable was not found. - function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) - external - view - returns (int256[] memory value); - - /// Gets the environment variable `name` and parses it as `string`. - /// Reverts if the variable was not found or could not be parsed. - function envString(string calldata name) external view returns (string memory value); - - /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envString(string calldata name, string calldata delim) external view returns (string[] memory value); - - /// Gets the environment variable `name` and parses it as `uint256`. - /// Reverts if the variable was not found or could not be parsed. - function envUint(string calldata name) external view returns (uint256 value); - - /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. - /// Reverts if the variable was not found or could not be parsed. - function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); - - /// Returns true if `forge` command was executed in given context. - function isContext(ForgeContext context) external view returns (bool result); - - /// Sets environment variables. - function setEnv(string calldata name, string calldata value) external; - - // ======== EVM ======== - - /// Gets all accessed reads and write slot from a `vm.record` session, for a given address. - function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); - - /// Gets the address for a given private key. - function addr(uint256 privateKey) external pure returns (address keyAddr); - - /// Gets all the logs according to specified filter. - function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) - external - returns (EthGetLogs[] memory logs); - - /// Gets the current `block.blobbasefee`. - /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, - /// and as a result will get optimized out by the compiler. - /// See https://github.com/foundry-rs/foundry/issues/6180 - function getBlobBaseFee() external view returns (uint256 blobBaseFee); - - /// Gets the current `block.number`. - /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, - /// and as a result will get optimized out by the compiler. - /// See https://github.com/foundry-rs/foundry/issues/6180 - function getBlockNumber() external view returns (uint256 height); - - /// Gets the current `block.timestamp`. - /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, - /// and as a result will get optimized out by the compiler. - /// See https://github.com/foundry-rs/foundry/issues/6180 - function getBlockTimestamp() external view returns (uint256 timestamp); - - /// Gets the map key and parent of a mapping at a given slot, for a given address. - function getMappingKeyAndParentOf(address target, bytes32 elementSlot) - external - returns (bool found, bytes32 key, bytes32 parent); - - /// Gets the number of elements in the mapping at the given slot, for a given address. - function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); - - /// Gets the elements at index idx of the mapping at the given slot, for a given address. The - /// index must be less than the length of the mapping (i.e. the number of keys in the mapping). - function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); - - /// Gets the nonce of an account. - function getNonce(address account) external view returns (uint64 nonce); - - /// Get the nonce of a `Wallet`. - function getNonce(Wallet calldata wallet) external returns (uint64 nonce); - - /// Gets all the recorded logs. - function getRecordedLogs() external returns (Log[] memory logs); - - /// Gets the gas used in the last call. - function lastCallGas() external view returns (Gas memory gas); - - /// Loads a storage slot from an address. - function load(address target, bytes32 slot) external view returns (bytes32 data); - - /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. - function pauseGasMetering() external; - - /// Records all storage reads and writes. - function record() external; - - /// Record all the transaction logs. - function recordLogs() external; - - /// Reset gas metering (i.e. gas usage is set to gas limit). - function resetGasMetering() external; - - /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. - function resumeGasMetering() external; - - /// Performs an Ethereum JSON-RPC request to the current fork URL. - function rpc(string calldata method, string calldata params) external returns (bytes memory data); - - /// Performs an Ethereum JSON-RPC request to the given endpoint. - function rpc(string calldata urlOrAlias, string calldata method, string calldata params) - external - returns (bytes memory data); - - /// Starts recording all map SSTOREs for later retrieval. - function startMappingRecording() external; - - /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, - /// along with the context of the calls - function startStateDiffRecording() external; - - /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. - function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); - - /// Stops recording all map SSTOREs for later retrieval and clears the recorded data. - function stopMappingRecording() external; - - // ======== Filesystem ======== - - /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. - /// `path` is relative to the project root. - function closeFile(string calldata path) external; - - /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. - /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. - /// Both `from` and `to` are relative to the project root. - function copyFile(string calldata from, string calldata to) external returns (uint64 copied); - - /// Creates a new, empty directory at the provided path. - /// This cheatcode will revert in the following situations, but is not limited to just these cases: - /// - User lacks permissions to modify `path`. - /// - A parent of the given path doesn't exist and `recursive` is false. - /// - `path` already exists and `recursive` is false. - /// `path` is relative to the project root. - function createDir(string calldata path, bool recursive) external; - - /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. - function deployCode(string calldata artifactPath) external returns (address deployedAddress); - - /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. - /// Additionally accepts abi-encoded constructor arguments. - function deployCode(string calldata artifactPath, bytes calldata constructorArgs) - external - returns (address deployedAddress); - - /// Returns true if the given path points to an existing entity, else returns false. - function exists(string calldata path) external returns (bool result); - - /// Performs a foreign function call via the terminal. - function ffi(string[] calldata commandInput) external returns (bytes memory result); - - /// Given a path, query the file system to get information about a file, directory, etc. - function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); - - /// Gets the artifact path from code (aka. creation code). - function getArtifactPathByCode(bytes calldata code) external view returns (string memory path); - - /// Gets the artifact path from deployed code (aka. runtime code). - function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path); - - /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. - function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); - - /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the - /// artifact in the form of :: where and parts are optional. - function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); - - /// Returns true if the path exists on disk and is pointing at a directory, else returns false. - function isDir(string calldata path) external returns (bool result); - - /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. - function isFile(string calldata path) external returns (bool result); - - /// Get the path of the current project root. - function projectRoot() external view returns (string memory path); - - /// Prompts the user for a string value in the terminal. - function prompt(string calldata promptText) external returns (string memory input); - - /// Prompts the user for an address in the terminal. - function promptAddress(string calldata promptText) external returns (address); - - /// Prompts the user for a hidden string value in the terminal. - function promptSecret(string calldata promptText) external returns (string memory input); - - /// Prompts the user for hidden uint256 in the terminal (usually pk). - function promptSecretUint(string calldata promptText) external returns (uint256); - - /// Prompts the user for uint256 in the terminal. - function promptUint(string calldata promptText) external returns (uint256); - - /// Reads the directory at the given path recursively, up to `maxDepth`. - /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. - /// Follows symbolic links if `followLinks` is true. - function readDir(string calldata path) external view returns (DirEntry[] memory entries); - - /// See `readDir(string)`. - function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); - - /// See `readDir(string)`. - function readDir(string calldata path, uint64 maxDepth, bool followLinks) - external - view - returns (DirEntry[] memory entries); - - /// Reads the entire content of file to string. `path` is relative to the project root. - function readFile(string calldata path) external view returns (string memory data); - - /// Reads the entire content of file as binary. `path` is relative to the project root. - function readFileBinary(string calldata path) external view returns (bytes memory data); - - /// Reads next line of file to string. - function readLine(string calldata path) external view returns (string memory line); - - /// Reads a symbolic link, returning the path that the link points to. - /// This cheatcode will revert in the following situations, but is not limited to just these cases: - /// - `path` is not a symbolic link. - /// - `path` does not exist. - function readLink(string calldata linkPath) external view returns (string memory targetPath); - - /// Removes a directory at the provided path. - /// This cheatcode will revert in the following situations, but is not limited to just these cases: - /// - `path` doesn't exist. - /// - `path` isn't a directory. - /// - User lacks permissions to modify `path`. - /// - The directory is not empty and `recursive` is false. - /// `path` is relative to the project root. - function removeDir(string calldata path, bool recursive) external; - - /// Removes a file from the filesystem. - /// This cheatcode will revert in the following situations, but is not limited to just these cases: - /// - `path` points to a directory. - /// - The file doesn't exist. - /// - The user lacks permissions to remove the file. - /// `path` is relative to the project root. - function removeFile(string calldata path) external; - - /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. - function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); - - /// Returns the time since unix epoch in milliseconds. - function unixTime() external returns (uint256 milliseconds); - - /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. - /// `path` is relative to the project root. - function writeFile(string calldata path, string calldata data) external; - - /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. - /// `path` is relative to the project root. - function writeFileBinary(string calldata path, bytes calldata data) external; - - /// Writes line to file, creating a file if it does not exist. - /// `path` is relative to the project root. - function writeLine(string calldata path, string calldata data) external; - - // ======== JSON ======== - - /// Checks if `key` exists in a JSON object. - function keyExistsJson(string calldata json, string calldata key) external view returns (bool); - - /// Parses a string of JSON data at `key` and coerces it to `address`. - function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); - - /// Parses a string of JSON data at `key` and coerces it to `address[]`. - function parseJsonAddressArray(string calldata json, string calldata key) - external - pure - returns (address[] memory); - - /// Parses a string of JSON data at `key` and coerces it to `bool`. - function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); - - /// Parses a string of JSON data at `key` and coerces it to `bool[]`. - function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); - - /// Parses a string of JSON data at `key` and coerces it to `bytes`. - function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); - - /// Parses a string of JSON data at `key` and coerces it to `bytes32`. - function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); - - /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. - function parseJsonBytes32Array(string calldata json, string calldata key) - external - pure - returns (bytes32[] memory); - - /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. - function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); - - /// Parses a string of JSON data at `key` and coerces it to `int256`. - function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); - - /// Parses a string of JSON data at `key` and coerces it to `int256[]`. - function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); - - /// Returns an array of all the keys in a JSON object. - function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); - - /// Parses a string of JSON data at `key` and coerces it to `string`. - function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); - - /// Parses a string of JSON data at `key` and coerces it to `string[]`. - function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); - - /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. - function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. - function parseJsonType(string calldata json, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. - function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of JSON data at `key` and coerces it to `uint256`. - function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); - - /// Parses a string of JSON data at `key` and coerces it to `uint256[]`. - function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); - - /// ABI-encodes a JSON object. - function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); - - /// ABI-encodes a JSON object at `key`. - function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); - - /// See `serializeJson`. - function serializeAddress(string calldata objectKey, string calldata valueKey, address value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBool(string calldata objectKey, string calldata valueKey, bool value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) - external - returns (string memory json); - - /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. - /// Returns the stringified version of the specific JSON file up to that moment. - function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); - - /// See `serializeJson`. - function serializeJsonType(string calldata typeDescription, bytes calldata value) - external - pure - returns (string memory json); - - /// See `serializeJson`. - function serializeJsonType( - string calldata objectKey, - string calldata valueKey, - string calldata typeDescription, - bytes calldata value - ) external returns (string memory json); - - /// See `serializeJson`. - function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) - external - returns (string memory json); - - /// See `serializeJson`. - function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) - external - returns (string memory json); - - /// Write a serialized JSON object to a file. If the file exists, it will be overwritten. - function writeJson(string calldata json, string calldata path) external; - - /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = - /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. - function writeJson(string calldata json, string calldata path, string calldata valueKey) external; - - /// Checks if `key` exists in a JSON object - /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. - function keyExists(string calldata json, string calldata key) external view returns (bool); - - // ======== Scripting ======== - - /// Takes a signed transaction and broadcasts it to the network. - function broadcastRawTransaction(bytes calldata data) external; - - /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. - /// Broadcasting address is determined by checking the following in order: - /// 1. If `--sender` argument was provided, that address is used. - /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. - /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. - function broadcast() external; - - /// Has the next call (at this call depth only) create a transaction with the address provided - /// as the sender that can later be signed and sent onchain. - function broadcast(address signer) external; - - /// Has the next call (at this call depth only) create a transaction with the private key - /// provided as the sender that can later be signed and sent onchain. - function broadcast(uint256 privateKey) external; - - /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. - /// Broadcasting address is determined by checking the following in order: - /// 1. If `--sender` argument was provided, that address is used. - /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. - /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. - function startBroadcast() external; - - /// Has all subsequent calls (at this call depth only) create transactions with the address - /// provided that can later be signed and sent onchain. - function startBroadcast(address signer) external; - - /// Has all subsequent calls (at this call depth only) create transactions with the private key - /// provided that can later be signed and sent onchain. - function startBroadcast(uint256 privateKey) external; - - /// Stops collecting onchain transactions. - function stopBroadcast() external; - - // ======== String ======== - - /// Returns the index of the first occurrence of a `key` in an `input` string. - /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. - /// Returns 0 in case of an empty `key`. - function indexOf(string calldata input, string calldata key) external pure returns (uint256); - - /// Parses the given `string` into an `address`. - function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); - - /// Parses the given `string` into a `bool`. - function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); - - /// Parses the given `string` into `bytes`. - function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); - - /// Parses the given `string` into a `bytes32`. - function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); - - /// Parses the given `string` into a `int256`. - function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); - - /// Parses the given `string` into a `uint256`. - function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); - - /// Replaces occurrences of `from` in the given `string` with `to`. - function replace(string calldata input, string calldata from, string calldata to) - external - pure - returns (string memory output); - - /// Splits the given `string` into an array of strings divided by the `delimiter`. - function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); - - /// Converts the given `string` value to Lowercase. - function toLowercase(string calldata input) external pure returns (string memory output); - - /// Converts the given value to a `string`. - function toString(address value) external pure returns (string memory stringifiedValue); - - /// Converts the given value to a `string`. - function toString(bytes calldata value) external pure returns (string memory stringifiedValue); - - /// Converts the given value to a `string`. - function toString(bytes32 value) external pure returns (string memory stringifiedValue); - - /// Converts the given value to a `string`. - function toString(bool value) external pure returns (string memory stringifiedValue); - - /// Converts the given value to a `string`. - function toString(uint256 value) external pure returns (string memory stringifiedValue); - - /// Converts the given value to a `string`. - function toString(int256 value) external pure returns (string memory stringifiedValue); - - /// Converts the given `string` value to Uppercase. - function toUppercase(string calldata input) external pure returns (string memory output); - - /// Trims leading and trailing whitespace from the given `string` value. - function trim(string calldata input) external pure returns (string memory output); - - // ======== Testing ======== - - /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. - /// Formats values with decimals in failure message. - function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; - - /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertApproxEqAbsDecimal( - uint256 left, - uint256 right, - uint256 maxDelta, - uint256 decimals, - string calldata error - ) external pure; - - /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. - /// Formats values with decimals in failure message. - function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; - - /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertApproxEqAbsDecimal( - int256 left, - int256 right, - uint256 maxDelta, - uint256 decimals, - string calldata error - ) external pure; - - /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; - - /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. - /// Includes error message into revert string on failure. - function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; - - /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; - - /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. - /// Includes error message into revert string on failure. - function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; - - /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Formats values with decimals in failure message. - function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) - external - pure; - - /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertApproxEqRelDecimal( - uint256 left, - uint256 right, - uint256 maxPercentDelta, - uint256 decimals, - string calldata error - ) external pure; - - /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Formats values with decimals in failure message. - function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) - external - pure; - - /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertApproxEqRelDecimal( - int256 left, - int256 right, - uint256 maxPercentDelta, - uint256 decimals, - string calldata error - ) external pure; - - /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; - - /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Includes error message into revert string on failure. - function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) - external - pure; - - /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; - - /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. - /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% - /// Includes error message into revert string on failure. - function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) - external - pure; - - /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. - /// Includes error message into revert string on failure. - function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. - function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. - /// Includes error message into revert string on failure. - function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Asserts that two `bool` values are equal. - function assertEq(bool left, bool right) external pure; - - /// Asserts that two `bool` values are equal and includes error message into revert string on failure. - function assertEq(bool left, bool right, string calldata error) external pure; - - /// Asserts that two `string` values are equal. - function assertEq(string calldata left, string calldata right) external pure; - - /// Asserts that two `string` values are equal and includes error message into revert string on failure. - function assertEq(string calldata left, string calldata right, string calldata error) external pure; - - /// Asserts that two `bytes` values are equal. - function assertEq(bytes calldata left, bytes calldata right) external pure; - - /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. - function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bool` values are equal. - function assertEq(bool[] calldata left, bool[] calldata right) external pure; - - /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. - function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `uint256 values are equal. - function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; - - /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. - function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `int256` values are equal. - function assertEq(int256[] calldata left, int256[] calldata right) external pure; - - /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. - function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; - - /// Asserts that two `uint256` values are equal. - function assertEq(uint256 left, uint256 right) external pure; - - /// Asserts that two arrays of `address` values are equal. - function assertEq(address[] calldata left, address[] calldata right) external pure; - - /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. - function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bytes32` values are equal. - function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - - /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. - function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `string` values are equal. - function assertEq(string[] calldata left, string[] calldata right) external pure; - - /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. - function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bytes` values are equal. - function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; - - /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. - function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - - /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. - function assertEq(uint256 left, uint256 right, string calldata error) external pure; - - /// Asserts that two `int256` values are equal. - function assertEq(int256 left, int256 right) external pure; - - /// Asserts that two `int256` values are equal and includes error message into revert string on failure. - function assertEq(int256 left, int256 right, string calldata error) external pure; - - /// Asserts that two `address` values are equal. - function assertEq(address left, address right) external pure; - - /// Asserts that two `address` values are equal and includes error message into revert string on failure. - function assertEq(address left, address right, string calldata error) external pure; - - /// Asserts that two `bytes32` values are equal. - function assertEq(bytes32 left, bytes32 right) external pure; - - /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. - function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; - - /// Asserts that the given condition is false. - function assertFalse(bool condition) external pure; - - /// Asserts that the given condition is false and includes error message into revert string on failure. - function assertFalse(bool condition, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than or equal to second. - /// Formats values with decimals in failure message. - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than or equal to second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be greater than or equal to second. - /// Formats values with decimals in failure message. - function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Compares two `int256` values. Expects first value to be greater than or equal to second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than or equal to second. - function assertGe(uint256 left, uint256 right) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than or equal to second. - /// Includes error message into revert string on failure. - function assertGe(uint256 left, uint256 right, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be greater than or equal to second. - function assertGe(int256 left, int256 right) external pure; - - /// Compares two `int256` values. Expects first value to be greater than or equal to second. - /// Includes error message into revert string on failure. - function assertGe(int256 left, int256 right, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than second. - /// Formats values with decimals in failure message. - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be greater than second. - /// Formats values with decimals in failure message. - function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Compares two `int256` values. Expects first value to be greater than second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than second. - function assertGt(uint256 left, uint256 right) external pure; - - /// Compares two `uint256` values. Expects first value to be greater than second. - /// Includes error message into revert string on failure. - function assertGt(uint256 left, uint256 right, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be greater than second. - function assertGt(int256 left, int256 right) external pure; - - /// Compares two `int256` values. Expects first value to be greater than second. - /// Includes error message into revert string on failure. - function assertGt(int256 left, int256 right, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be less than or equal to second. - /// Formats values with decimals in failure message. - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Compares two `uint256` values. Expects first value to be less than or equal to second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be less than or equal to second. - /// Formats values with decimals in failure message. - function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Compares two `int256` values. Expects first value to be less than or equal to second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be less than or equal to second. - function assertLe(uint256 left, uint256 right) external pure; - - /// Compares two `uint256` values. Expects first value to be less than or equal to second. - /// Includes error message into revert string on failure. - function assertLe(uint256 left, uint256 right, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be less than or equal to second. - function assertLe(int256 left, int256 right) external pure; - - /// Compares two `int256` values. Expects first value to be less than or equal to second. - /// Includes error message into revert string on failure. - function assertLe(int256 left, int256 right, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be less than second. - /// Formats values with decimals in failure message. - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Compares two `uint256` values. Expects first value to be less than second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be less than second. - /// Formats values with decimals in failure message. - function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Compares two `int256` values. Expects first value to be less than second. - /// Formats values with decimals in failure message. Includes error message into revert string on failure. - function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Compares two `uint256` values. Expects first value to be less than second. - function assertLt(uint256 left, uint256 right) external pure; - - /// Compares two `uint256` values. Expects first value to be less than second. - /// Includes error message into revert string on failure. - function assertLt(uint256 left, uint256 right, string calldata error) external pure; - - /// Compares two `int256` values. Expects first value to be less than second. - function assertLt(int256 left, int256 right) external pure; - - /// Compares two `int256` values. Expects first value to be less than second. - /// Includes error message into revert string on failure. - function assertLt(int256 left, int256 right, string calldata error) external pure; - - /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; - - /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. - /// Includes error message into revert string on failure. - function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; - - /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; - - /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. - /// Includes error message into revert string on failure. - function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; - - /// Asserts that two `bool` values are not equal. - function assertNotEq(bool left, bool right) external pure; - - /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. - function assertNotEq(bool left, bool right, string calldata error) external pure; - - /// Asserts that two `string` values are not equal. - function assertNotEq(string calldata left, string calldata right) external pure; - - /// Asserts that two `string` values are not equal and includes error message into revert string on failure. - function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; - - /// Asserts that two `bytes` values are not equal. - function assertNotEq(bytes calldata left, bytes calldata right) external pure; - - /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bool` values are not equal. - function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; - - /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. - function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `uint256` values are not equal. - function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; - - /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. - function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `int256` values are not equal. - function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; - - /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. - function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; - - /// Asserts that two `uint256` values are not equal. - function assertNotEq(uint256 left, uint256 right) external pure; - - /// Asserts that two arrays of `address` values are not equal. - function assertNotEq(address[] calldata left, address[] calldata right) external pure; - - /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. - function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bytes32` values are not equal. - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; - - /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `string` values are not equal. - function assertNotEq(string[] calldata left, string[] calldata right) external pure; - - /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. - function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; - - /// Asserts that two arrays of `bytes` values are not equal. - function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; - - /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; - - /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. - function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; - - /// Asserts that two `int256` values are not equal. - function assertNotEq(int256 left, int256 right) external pure; - - /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. - function assertNotEq(int256 left, int256 right, string calldata error) external pure; - - /// Asserts that two `address` values are not equal. - function assertNotEq(address left, address right) external pure; - - /// Asserts that two `address` values are not equal and includes error message into revert string on failure. - function assertNotEq(address left, address right, string calldata error) external pure; - - /// Asserts that two `bytes32` values are not equal. - function assertNotEq(bytes32 left, bytes32 right) external pure; - - /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. - function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; - - /// Asserts that the given condition is true. - function assertTrue(bool condition) external pure; - - /// Asserts that the given condition is true and includes error message into revert string on failure. - function assertTrue(bool condition, string calldata error) external pure; - - /// If the condition is false, discard this run's fuzz inputs and generate new ones. - function assume(bool condition) external pure; - - /// Discard this run's fuzz inputs and generate new ones if next call reverted. - function assumeNoRevert() external pure; - - /// Writes a breakpoint to jump to in the debugger. - function breakpoint(string calldata char) external; - - /// Writes a conditional breakpoint to jump to in the debugger. - function breakpoint(string calldata char, bool value) external; - - /// Returns the Foundry version. - /// Format: ++ - /// Sample output: 0.2.0+faa94c384+202407110019 - /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. - /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) - /// to compare timestamps while ignoring minor time differences. - function getFoundryVersion() external view returns (string memory version); - - /// Returns the RPC url for the given alias. - function rpcUrl(string calldata rpcAlias) external view returns (string memory json); - - /// Returns all rpc urls and their aliases as structs. - function rpcUrlStructs() external view returns (Rpc[] memory urls); - - /// Returns all rpc urls and their aliases `[alias, url][]`. - function rpcUrls() external view returns (string[2][] memory urls); - - /// Suspends execution of the main thread for `duration` milliseconds. - function sleep(uint256 duration) external; - - // ======== Toml ======== - - /// Checks if `key` exists in a TOML table. - function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); - - /// Parses a string of TOML data at `key` and coerces it to `address`. - function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); - - /// Parses a string of TOML data at `key` and coerces it to `address[]`. - function parseTomlAddressArray(string calldata toml, string calldata key) - external - pure - returns (address[] memory); - - /// Parses a string of TOML data at `key` and coerces it to `bool`. - function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); - - /// Parses a string of TOML data at `key` and coerces it to `bool[]`. - function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); - - /// Parses a string of TOML data at `key` and coerces it to `bytes`. - function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); - - /// Parses a string of TOML data at `key` and coerces it to `bytes32`. - function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); - - /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. - function parseTomlBytes32Array(string calldata toml, string calldata key) - external - pure - returns (bytes32[] memory); - - /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. - function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); - - /// Parses a string of TOML data at `key` and coerces it to `int256`. - function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); - - /// Parses a string of TOML data at `key` and coerces it to `int256[]`. - function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); - - /// Returns an array of all the keys in a TOML table. - function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); - - /// Parses a string of TOML data at `key` and coerces it to `string`. - function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); - - /// Parses a string of TOML data at `key` and coerces it to `string[]`. - function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); - - /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`. - function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. - function parseTomlType(string calldata toml, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. - function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) - external - pure - returns (bytes memory); - - /// Parses a string of TOML data at `key` and coerces it to `uint256`. - function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); - - /// Parses a string of TOML data at `key` and coerces it to `uint256[]`. - function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); - - /// ABI-encodes a TOML table. - function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); - - /// ABI-encodes a TOML table at `key`. - function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); - - /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. - function writeToml(string calldata json, string calldata path) external; - - /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = - /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. - function writeToml(string calldata json, string calldata path, string calldata valueKey) external; - - // ======== Utilities ======== - - /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. - function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) - external - pure - returns (address); - - /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. - function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); - - /// Compute the address a contract will be deployed at for a given deployer address and nonce. - function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); - - /// Utility cheatcode to copy storage of `from` contract to another `to` contract. - function copyStorage(address from, address to) external; - - /// Returns ENS namehash for provided string. - function ensNamehash(string calldata name) external pure returns (bytes32); - - /// Gets the label for the specified address. - function getLabel(address account) external view returns (string memory currentLabel); - - /// Labels an address in call traces. - function label(address account, string calldata newLabel) external; - - /// Pauses collection of call traces. Useful in cases when you want to skip tracing of - /// complex calls which are not useful for debugging. - function pauseTracing() external view; - - /// Returns a random `address`. - function randomAddress() external returns (address); - - /// Returns an random `bool`. - function randomBool() external view returns (bool); - - /// Returns an random byte array value of the given length. - function randomBytes(uint256 len) external view returns (bytes memory); - - /// Returns an random `int256` value. - function randomInt() external view returns (int256); - - /// Returns an random `int256` value of given bits. - function randomInt(uint256 bits) external view returns (int256); - - /// Returns a random uint256 value. - function randomUint() external returns (uint256); - - /// Returns random uint256 value between the provided range (=min..=max). - function randomUint(uint256 min, uint256 max) external returns (uint256); - - /// Returns an random `uint256` value of given bits. - function randomUint(uint256 bits) external view returns (uint256); - - /// Unpauses collection of call traces. - function resumeTracing() external view; - - /// Utility cheatcode to set arbitrary storage for given target address. - function setArbitraryStorage(address target) external; - - /// Encodes a `bytes` value to a base64url string. - function toBase64URL(bytes calldata data) external pure returns (string memory); - - /// Encodes a `string` value to a base64url string. - function toBase64URL(string calldata data) external pure returns (string memory); - - /// Encodes a `bytes` value to a base64 string. - function toBase64(bytes calldata data) external pure returns (string memory); - - /// Encodes a `string` value to a base64 string. - function toBase64(string calldata data) external pure returns (string memory); -} - -/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used -/// in tests, but it is not recommended to use these cheats in scripts. -interface Vm is VmSafe { - // ======== EVM ======== - - /// Returns the identifier of the currently active fork. Reverts if no fork is currently active. - function activeFork() external view returns (uint256 forkId); - - /// In forking mode, explicitly grant the given address cheatcode access. - function allowCheatcodes(address account) external; - - /// Sets `block.blobbasefee` - function blobBaseFee(uint256 newBlobBaseFee) external; - - /// Sets the blobhashes in the transaction. - /// Not available on EVM versions before Cancun. - /// If used on unsupported EVM versions it will revert. - function blobhashes(bytes32[] calldata hashes) external; - - /// Sets `block.chainid`. - function chainId(uint256 newChainId) external; - - /// Clears all mocked calls. - function clearMockedCalls() external; - - /// Sets `block.coinbase`. - function coinbase(address newCoinbase) external; - - /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. - function createFork(string calldata urlOrAlias) external returns (uint256 forkId); - - /// Creates a new fork with the given endpoint and block and returns the identifier of the fork. - function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); - - /// Creates a new fork with the given endpoint and at the block the given transaction was mined in, - /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. - function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); - - /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. - function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); - - /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. - function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); - - /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, - /// replays all transaction mined in the block before the transaction, returns the identifier of the fork. - function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); - - /// Sets an address' balance. - function deal(address account, uint256 newBalance) external; - - /// Removes the snapshot with the given ID created by `snapshot`. - /// Takes the snapshot ID to delete. - /// Returns `true` if the snapshot was successfully deleted. - /// Returns `false` if the snapshot does not exist. - function deleteSnapshot(uint256 snapshotId) external returns (bool success); - - /// Removes _all_ snapshots previously created by `snapshot`. - function deleteSnapshots() external; - - /// Sets `block.difficulty`. - /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. - /// Reverts if used on unsupported EVM versions. - function difficulty(uint256 newDifficulty) external; - - /// Dump a genesis JSON file's `allocs` to disk. - function dumpState(string calldata pathToStateJson) external; - - /// Sets an address' code. - function etch(address target, bytes calldata newRuntimeBytecode) external; - - /// Sets `block.basefee`. - function fee(uint256 newBasefee) external; - - /// Gets the blockhashes from the current transaction. - /// Not available on EVM versions before Cancun. - /// If used on unsupported EVM versions it will revert. - function getBlobhashes() external view returns (bytes32[] memory hashes); - - /// Returns true if the account is marked as persistent. - function isPersistent(address account) external view returns (bool persistent); - - /// Load a genesis JSON file's `allocs` into the in-memory revm state. - function loadAllocs(string calldata pathToAllocsJson) external; - - /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup - /// Meaning, changes made to the state of this account will be kept when switching forks. - function makePersistent(address account) external; - - /// See `makePersistent(address)`. - function makePersistent(address account0, address account1) external; - - /// See `makePersistent(address)`. - function makePersistent(address account0, address account1, address account2) external; - - /// See `makePersistent(address)`. - function makePersistent(address[] calldata accounts) external; - - /// Reverts a call to an address with specified revert data. - function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; - - /// Reverts a call to an address with a specific `msg.value`, with specified revert data. - function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) - external; - - /// Mocks a call to an address, returning specified data. - /// Calldata can either be strict or a partial match, e.g. if you only - /// pass a Solidity selector to the expected calldata, then the entire Solidity - /// function will be mocked. - function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; - - /// Mocks a call to an address with a specific `msg.value`, returning specified data. - /// Calldata match takes precedence over `msg.value` in case of ambiguity. - function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; - - /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls - /// `target` with the same calldata. This functionality is similar to a delegate call made to - /// `target` contract from `callee`. - /// Can be used to substitute a call to a function with another implementation that captures - /// the primary logic of the original function but is easier to reason about. - /// If calldata is not a strict match then partial match by selector is attempted. - function mockFunction(address callee, address target, bytes calldata data) external; - - /// Sets the *next* call's `msg.sender` to be the input address. - function prank(address msgSender) external; - - /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. - function prank(address msgSender, address txOrigin) external; - - /// Sets `block.prevrandao`. - /// Not available on EVM versions before Paris. Use `difficulty` instead. - /// If used on unsupported EVM versions it will revert. - function prevrandao(bytes32 newPrevrandao) external; - - /// Sets `block.prevrandao`. - /// Not available on EVM versions before Paris. Use `difficulty` instead. - /// If used on unsupported EVM versions it will revert. - function prevrandao(uint256 newPrevrandao) external; - - /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. - function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); - - /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. - function resetNonce(address account) external; - - /// Revert the state of the EVM to a previous snapshot - /// Takes the snapshot ID to revert to. - /// Returns `true` if the snapshot was successfully reverted. - /// Returns `false` if the snapshot does not exist. - /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. - function revertTo(uint256 snapshotId) external returns (bool success); - - /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots - /// Takes the snapshot ID to revert to. - /// Returns `true` if the snapshot was successfully reverted and deleted. - /// Returns `false` if the snapshot does not exist. - function revertToAndDelete(uint256 snapshotId) external returns (bool success); - - /// Revokes persistent status from the address, previously added via `makePersistent`. - function revokePersistent(address account) external; - - /// See `revokePersistent(address)`. - function revokePersistent(address[] calldata accounts) external; - - /// Sets `block.height`. - function roll(uint256 newHeight) external; - - /// Updates the currently active fork to given block number - /// This is similar to `roll` but for the currently active fork. - function rollFork(uint256 blockNumber) external; - - /// Updates the currently active fork to given transaction. This will `rollFork` with the number - /// of the block the transaction was mined in and replays all transaction mined before it in the block. - function rollFork(bytes32 txHash) external; - - /// Updates the given fork to given block number. - function rollFork(uint256 forkId, uint256 blockNumber) external; - - /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. - function rollFork(uint256 forkId, bytes32 txHash) external; - - /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. - function selectFork(uint256 forkId) external; - - /// Set blockhash for the current block. - /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. - function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; - - /// Sets the nonce of an account. Must be higher than the current nonce of the account. - function setNonce(address account, uint64 newNonce) external; - - /// Sets the nonce of an account to an arbitrary value. - function setNonceUnsafe(address account, uint64 newNonce) external; - - /// Snapshot the current state of the evm. - /// Returns the ID of the snapshot that was created. - /// To revert a snapshot use `revertTo`. - function snapshot() external returns (uint256 snapshotId); - - /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. - function startPrank(address msgSender) external; - - /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. - function startPrank(address msgSender, address txOrigin) external; - - /// Resets subsequent calls' `msg.sender` to be `address(this)`. - function stopPrank() external; - - /// Stores a value to an address' storage slot. - function store(address target, bytes32 slot, bytes32 value) external; - - /// Fetches the given transaction from the active fork and executes it on the current state. - function transact(bytes32 txHash) external; - - /// Fetches the given transaction from the given fork and executes it on the current state. - function transact(uint256 forkId, bytes32 txHash) external; - - /// Sets `tx.gasprice`. - function txGasPrice(uint256 newGasPrice) external; - - /// Sets `block.timestamp`. - function warp(uint256 newTimestamp) external; - - // ======== Testing ======== - - /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. - function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; - - /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. - function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) - external; - - /// Expects a call to an address with the specified calldata. - /// Calldata can either be a strict or a partial match. - function expectCall(address callee, bytes calldata data) external; - - /// Expects given number of calls to an address with the specified calldata. - function expectCall(address callee, bytes calldata data, uint64 count) external; - - /// Expects a call to an address with the specified `msg.value` and calldata. - function expectCall(address callee, uint256 msgValue, bytes calldata data) external; - - /// Expects given number of calls to an address with the specified `msg.value` and calldata. - function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; - - /// Expect a call to an address with the specified `msg.value`, gas, and calldata. - function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; - - /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. - function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; - - /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). - /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if - /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). - function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) - external; - - /// Same as the previous method, but also checks supplied address against emitting contract. - function expectEmitAnonymous( - bool checkTopic0, - bool checkTopic1, - bool checkTopic2, - bool checkTopic3, - bool checkData, - address emitter - ) external; - - /// Prepare an expected anonymous log with all topic and data checks enabled. - /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if - /// logs were emitted in the expected order with the expected topics and data. - function expectEmitAnonymous() external; - - /// Same as the previous method, but also checks supplied address against emitting contract. - function expectEmitAnonymous(address emitter) external; - - /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). - /// Call this function, then emit an event, then call a function. Internally after the call, we check if - /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). - function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; - - /// Same as the previous method, but also checks supplied address against emitting contract. - function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) - external; - - /// Prepare an expected log with all topic and data checks enabled. - /// Call this function, then emit an event, then call a function. Internally after the call, we check if - /// logs were emitted in the expected order with the expected topics and data. - function expectEmit() external; - - /// Same as the previous method, but also checks supplied address against emitting contract. - function expectEmit(address emitter) external; - - /// Expects an error on next call that starts with the revert data. - function expectPartialRevert(bytes4 revertData) external; - - /// Expects an error on next call to reverter address, that starts with the revert data. - function expectPartialRevert(bytes4 revertData, address reverter) external; - - /// Expects an error on next call with any revert data. - function expectRevert() external; - - /// Expects an error on next call that exactly matches the revert data. - function expectRevert(bytes4 revertData) external; - - /// Expects an error on next call that exactly matches the revert data. - function expectRevert(bytes calldata revertData) external; - - /// Expects an error with any revert data on next call to reverter address. - function expectRevert(address reverter) external; - - /// Expects an error from reverter address on next call, with any revert data. - function expectRevert(bytes4 revertData, address reverter) external; - - /// Expects an error from reverter address on next call, that exactly matches the revert data. - function expectRevert(bytes calldata revertData, address reverter) external; - - /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other - /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. - function expectSafeMemory(uint64 min, uint64 max) external; - - /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. - /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges - /// to the set. - function expectSafeMemoryCall(uint64 min, uint64 max) external; - - /// Marks a test as skipped. Must be called at the top level of a test. - function skip(bool skipTest) external; - - /// Marks a test as skipped with a reason. Must be called at the top level of a test. - function skip(bool skipTest, string calldata reason) external; - - /// Stops all safe memory expectation in the current subcontext. - function stopExpectSafeMemory() external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol deleted file mode 100644 index 4fdb667..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console.sol +++ /dev/null @@ -1,1560 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; - -library console { - address constant CONSOLE_ADDRESS = - 0x000000000000000000636F6e736F6c652e6c6f67; - - function _sendLogPayloadImplementation(bytes memory payload) internal view { - address consoleAddress = CONSOLE_ADDRESS; - /// @solidity memory-safe-assembly - assembly { - pop( - staticcall( - gas(), - consoleAddress, - add(payload, 32), - mload(payload), - 0, - 0 - ) - ) - } - } - - function _castToPure( - function(bytes memory) internal view fnIn - ) internal pure returns (function(bytes memory) pure fnOut) { - assembly { - fnOut := fnIn - } - } - - function _sendLogPayload(bytes memory payload) internal pure { - _castToPure(_sendLogPayloadImplementation)(payload); - } - - function log() internal pure { - _sendLogPayload(abi.encodeWithSignature("log()")); - } - - function logInt(int256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); - } - - function logUint(uint256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function logString(string memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function logBool(bool p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function logAddress(address p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function logBytes(bytes memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); - } - - function logBytes1(bytes1 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); - } - - function logBytes2(bytes2 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); - } - - function logBytes3(bytes3 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); - } - - function logBytes4(bytes4 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); - } - - function logBytes5(bytes5 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); - } - - function logBytes6(bytes6 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); - } - - function logBytes7(bytes7 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); - } - - function logBytes8(bytes8 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); - } - - function logBytes9(bytes9 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); - } - - function logBytes10(bytes10 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); - } - - function logBytes11(bytes11 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); - } - - function logBytes12(bytes12 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); - } - - function logBytes13(bytes13 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); - } - - function logBytes14(bytes14 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); - } - - function logBytes15(bytes15 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); - } - - function logBytes16(bytes16 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); - } - - function logBytes17(bytes17 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); - } - - function logBytes18(bytes18 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); - } - - function logBytes19(bytes19 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); - } - - function logBytes20(bytes20 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); - } - - function logBytes21(bytes21 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); - } - - function logBytes22(bytes22 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); - } - - function logBytes23(bytes23 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); - } - - function logBytes24(bytes24 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); - } - - function logBytes25(bytes25 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); - } - - function logBytes26(bytes26 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); - } - - function logBytes27(bytes27 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); - } - - function logBytes28(bytes28 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); - } - - function logBytes29(bytes29 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); - } - - function logBytes30(bytes30 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); - } - - function logBytes31(bytes31 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); - } - - function logBytes32(bytes32 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); - } - - function log(uint256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); - } - - function log(int256 p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); - } - - function log(string memory p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); - } - - function log(bool p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); - } - - function log(address p0) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); - } - - function log(uint256 p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); - } - - function log(uint256 p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); - } - - function log(uint256 p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); - } - - function log(uint256 p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); - } - - function log(string memory p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); - } - - function log(string memory p0, int256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); - } - - function log(string memory p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); - } - - function log(string memory p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); - } - - function log(string memory p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); - } - - function log(bool p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); - } - - function log(bool p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); - } - - function log(bool p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); - } - - function log(bool p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); - } - - function log(address p0, uint256 p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); - } - - function log(address p0, string memory p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); - } - - function log(address p0, bool p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); - } - - function log(address p0, address p1) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); - } - - function log(uint256 p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); - } - - function log(uint256 p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); - } - - function log(uint256 p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); - } - - function log(uint256 p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); - } - - function log(string memory p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); - } - - function log(string memory p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); - } - - function log(string memory p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); - } - - function log(string memory p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); - } - - function log(string memory p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); - } - - function log(string memory p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); - } - - function log(string memory p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); - } - - function log(bool p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); - } - - function log(bool p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); - } - - function log(bool p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); - } - - function log(bool p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); - } - - function log(bool p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); - } - - function log(bool p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); - } - - function log(bool p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); - } - - function log(bool p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); - } - - function log(bool p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); - } - - function log(bool p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); - } - - function log(address p0, uint256 p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); - } - - function log(address p0, string memory p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); - } - - function log(address p0, string memory p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); - } - - function log(address p0, string memory p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); - } - - function log(address p0, string memory p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); - } - - function log(address p0, bool p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); - } - - function log(address p0, bool p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); - } - - function log(address p0, bool p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); - } - - function log(address p0, bool p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); - } - - function log(address p0, address p1, uint256 p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); - } - - function log(address p0, address p1, string memory p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); - } - - function log(address p0, address p1, bool p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); - } - - function log(address p0, address p1, address p2) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); - } - - function log(uint256 p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); - } - - function log(string memory p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); - } - - function log(bool p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, uint256 p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, string memory p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, bool p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, uint256 p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, string memory p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, bool p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, uint256 p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, string memory p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, bool p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); - } - - function log(address p0, address p1, address p2, address p3) internal pure { - _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol deleted file mode 100644 index 03531d9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/console2.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.22 <0.9.0; - -import {console as console2} from "./console.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol deleted file mode 100644 index f7dd2b4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC1155.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -import "./IERC165.sol"; - -/// @title ERC-1155 Multi Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-1155 -/// Note: The ERC-165 identifier for this interface is 0xd9b67a26. -interface IERC1155 is IERC165 { - /// @dev - /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). - /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). - /// - The `_from` argument MUST be the address of the holder whose balance is decreased. - /// - The `_to` argument MUST be the address of the recipient whose balance is increased. - /// - The `_id` argument MUST be the token type being transferred. - /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. - /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). - /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). - event TransferSingle( - address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value - ); - - /// @dev - /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). - /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). - /// - The `_from` argument MUST be the address of the holder whose balance is decreased. - /// - The `_to` argument MUST be the address of the recipient whose balance is increased. - /// - The `_ids` argument MUST be the list of tokens being transferred. - /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. - /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). - /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). - event TransferBatch( - address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values - ); - - /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). - event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); - - /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. - /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". - event URI(string _value, uint256 indexed _id); - - /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). - /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). - /// - MUST revert if `_to` is the zero address. - /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent. - /// - MUST revert on any other error. - /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). - /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). - /// @param _from Source address - /// @param _to Target address - /// @param _id ID of the token type - /// @param _value Transfer amount - /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` - function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; - - /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). - /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). - /// - MUST revert if `_to` is the zero address. - /// - MUST revert if length of `_ids` is not the same as length of `_values`. - /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. - /// - MUST revert on any other error. - /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). - /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). - /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). - /// @param _from Source address - /// @param _to Target address - /// @param _ids IDs of each token type (order and length must match _values array) - /// @param _values Transfer amounts per token type (order and length must match _ids array) - /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` - function safeBatchTransferFrom( - address _from, - address _to, - uint256[] calldata _ids, - uint256[] calldata _values, - bytes calldata _data - ) external; - - /// @notice Get the balance of an account's tokens. - /// @param _owner The address of the token holder - /// @param _id ID of the token - /// @return The _owner's balance of the token type requested - function balanceOf(address _owner, uint256 _id) external view returns (uint256); - - /// @notice Get the balance of multiple account/token pairs - /// @param _owners The addresses of the token holders - /// @param _ids ID of the tokens - /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) - function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) - external - view - returns (uint256[] memory); - - /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. - /// @dev MUST emit the ApprovalForAll event on success. - /// @param _operator Address to add to the set of authorized operators - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Queries the approval status of an operator for a given owner. - /// @param _owner The owner of the tokens - /// @param _operator Address of authorized operator - /// @return True if the operator is approved, false if not - function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol deleted file mode 100644 index 9af4bf8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC165.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -interface IERC165 { - /// @notice Query if a contract implements an interface - /// @param interfaceID The interface identifier, as specified in ERC-165 - /// @dev Interface identification is specified in ERC-165. This function - /// uses less than 30,000 gas. - /// @return `true` if the contract implements `interfaceID` and - /// `interfaceID` is not 0xffffffff, `false` otherwise - function supportsInterface(bytes4 interfaceID) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol deleted file mode 100644 index ba40806..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC20.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -/// @dev Interface of the ERC20 standard as defined in the EIP. -/// @dev This includes the optional name, symbol, and decimals metadata. -interface IERC20 { - /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). - event Transfer(address indexed from, address indexed to, uint256 value); - - /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` - /// is the new allowance. - event Approval(address indexed owner, address indexed spender, uint256 value); - - /// @notice Returns the amount of tokens in existence. - function totalSupply() external view returns (uint256); - - /// @notice Returns the amount of tokens owned by `account`. - function balanceOf(address account) external view returns (uint256); - - /// @notice Moves `amount` tokens from the caller's account to `to`. - function transfer(address to, uint256 amount) external returns (bool); - - /// @notice Returns the remaining number of tokens that `spender` is allowed - /// to spend on behalf of `owner` - function allowance(address owner, address spender) external view returns (uint256); - - /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. - /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - function approve(address spender, uint256 amount) external returns (bool); - - /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. - /// `amount` is then deducted from the caller's allowance. - function transferFrom(address from, address to, uint256 amount) external returns (bool); - - /// @notice Returns the name of the token. - function name() external view returns (string memory); - - /// @notice Returns the symbol of the token. - function symbol() external view returns (string memory); - - /// @notice Returns the decimals places of the token. - function decimals() external view returns (uint8); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol deleted file mode 100644 index 391eeb4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC4626.sol +++ /dev/null @@ -1,190 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -import "./IERC20.sol"; - -/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in -/// https://eips.ethereum.org/EIPS/eip-4626 -interface IERC4626 is IERC20 { - event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); - - event Withdraw( - address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares - ); - - /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. - /// @dev - /// - MUST be an ERC-20 token contract. - /// - MUST NOT revert. - function asset() external view returns (address assetTokenAddress); - - /// @notice Returns the total amount of the underlying asset that is “managed” by Vault. - /// @dev - /// - SHOULD include any compounding that occurs from yield. - /// - MUST be inclusive of any fees that are charged against assets in the Vault. - /// - MUST NOT revert. - function totalAssets() external view returns (uint256 totalManagedAssets); - - /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal - /// scenario where all the conditions are met. - /// @dev - /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. - /// - MUST NOT show any variations depending on the caller. - /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. - /// - MUST NOT revert. - /// - /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the - /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and - /// from. - function convertToShares(uint256 assets) external view returns (uint256 shares); - - /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal - /// scenario where all the conditions are met. - /// @dev - /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. - /// - MUST NOT show any variations depending on the caller. - /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. - /// - MUST NOT revert. - /// - /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the - /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and - /// from. - function convertToAssets(uint256 shares) external view returns (uint256 assets); - - /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, - /// through a deposit call. - /// @dev - /// - MUST return a limited value if receiver is subject to some deposit limit. - /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. - /// - MUST NOT revert. - function maxDeposit(address receiver) external view returns (uint256 maxAssets); - - /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given - /// current on-chain conditions. - /// @dev - /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit - /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called - /// in the same transaction. - /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the - /// deposit would be accepted, regardless if the user has enough tokens approved, etc. - /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. - /// - MUST NOT revert. - /// - /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in - /// share price or some other type of condition, meaning the depositor will lose assets by depositing. - function previewDeposit(uint256 assets) external view returns (uint256 shares); - - /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. - /// @dev - /// - MUST emit the Deposit event. - /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the - /// deposit execution, and are accounted for during deposit. - /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not - /// approving enough underlying tokens to the Vault contract, etc). - /// - /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. - function deposit(uint256 assets, address receiver) external returns (uint256 shares); - - /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. - /// @dev - /// - MUST return a limited value if receiver is subject to some mint limit. - /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. - /// - MUST NOT revert. - function maxMint(address receiver) external view returns (uint256 maxShares); - - /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given - /// current on-chain conditions. - /// @dev - /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call - /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the - /// same transaction. - /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint - /// would be accepted, regardless if the user has enough tokens approved, etc. - /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. - /// - MUST NOT revert. - /// - /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in - /// share price or some other type of condition, meaning the depositor will lose assets by minting. - function previewMint(uint256 shares) external view returns (uint256 assets); - - /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. - /// @dev - /// - MUST emit the Deposit event. - /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint - /// execution, and are accounted for during mint. - /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not - /// approving enough underlying tokens to the Vault contract, etc). - /// - /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. - function mint(uint256 shares, address receiver) external returns (uint256 assets); - - /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the - /// Vault, through a withdrawal call. - /// @dev - /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. - /// - MUST NOT revert. - function maxWithdraw(address owner) external view returns (uint256 maxAssets); - - /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, - /// given current on-chain conditions. - /// @dev - /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw - /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if - /// called - /// in the same transaction. - /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though - /// the withdrawal would be accepted, regardless if the user has enough shares, etc. - /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. - /// - MUST NOT revert. - /// - /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in - /// share price or some other type of condition, meaning the depositor will lose assets by depositing. - function previewWithdraw(uint256 assets) external view returns (uint256 shares); - - /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. - /// @dev - /// - MUST emit the Withdraw event. - /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the - /// withdraw execution, and are accounted for during withdrawal. - /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner - /// not having enough shares, etc). - /// - /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. - /// Those methods should be performed separately. - function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); - - /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, - /// through a redeem call. - /// @dev - /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. - /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. - /// - MUST NOT revert. - function maxRedeem(address owner) external view returns (uint256 maxShares); - - /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, - /// given current on-chain conditions. - /// @dev - /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call - /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the - /// same transaction. - /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the - /// redemption would be accepted, regardless if the user has enough shares, etc. - /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. - /// - MUST NOT revert. - /// - /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in - /// share price or some other type of condition, meaning the depositor will lose assets by redeeming. - function previewRedeem(uint256 shares) external view returns (uint256 assets); - - /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. - /// @dev - /// - MUST emit the Withdraw event. - /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the - /// redeem execution, and are accounted for during redeem. - /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner - /// not having enough shares, etc). - /// - /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. - /// Those methods should be performed separately. - function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol deleted file mode 100644 index 0a16f45..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IERC721.sol +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2; - -import "./IERC165.sol"; - -/// @title ERC-721 Non-Fungible Token Standard -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x80ac58cd. -interface IERC721 is IERC165 { - /// @dev This emits when ownership of any NFT changes by any mechanism. - /// This event emits when NFTs are created (`from` == 0) and destroyed - /// (`to` == 0). Exception: during contract creation, any number of NFTs - /// may be created and assigned without emitting Transfer. At the time of - /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); - - /// @dev This emits when the approved address for an NFT is changed or - /// reaffirmed. The zero address indicates there is no approved address. - /// When a Transfer event emits, this also indicates that the approved - /// address for that NFT (if any) is reset to none. - event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); - - /// @dev This emits when an operator is enabled or disabled for an owner. - /// The operator can manage all NFTs of the owner. - event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); - - /// @notice Count all NFTs assigned to an owner - /// @dev NFTs assigned to the zero address are considered invalid, and this - /// function throws for queries about the zero address. - /// @param _owner An address for whom to query the balance - /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) external view returns (uint256); - - /// @notice Find the owner of an NFT - /// @dev NFTs assigned to zero address are considered invalid, and queries - /// about them do throw. - /// @param _tokenId The identifier for an NFT - /// @return The address of the owner of the NFT - function ownerOf(uint256 _tokenId) external view returns (address); - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. When transfer is complete, this function - /// checks if `_to` is a smart contract (code size > 0). If so, it calls - /// `onERC721Received` on `_to` and throws if the return value is not - /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; - - /// @notice Transfers the ownership of an NFT from one address to another address - /// @dev This works identically to the other function with an extra data parameter, - /// except this function just sets data to "". - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; - - /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE - /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE - /// THEY MAY BE PERMANENTLY LOST - /// @dev Throws unless `msg.sender` is the current owner, an authorized - /// operator, or the approved address for this NFT. Throws if `_from` is - /// not the current owner. Throws if `_to` is the zero address. Throws if - /// `_tokenId` is not a valid NFT. - /// @param _from The current owner of the NFT - /// @param _to The new owner - /// @param _tokenId The NFT to transfer - function transferFrom(address _from, address _to, uint256 _tokenId) external payable; - - /// @notice Change or reaffirm the approved address for an NFT - /// @dev The zero address indicates there is no approved address. - /// Throws unless `msg.sender` is the current NFT owner, or an authorized - /// operator of the current owner. - /// @param _approved The new approved NFT controller - /// @param _tokenId The NFT to approve - function approve(address _approved, uint256 _tokenId) external payable; - - /// @notice Enable or disable approval for a third party ("operator") to manage - /// all of `msg.sender`'s assets - /// @dev Emits the ApprovalForAll event. The contract MUST allow - /// multiple operators per owner. - /// @param _operator Address to add to the set of authorized operators - /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external; - - /// @notice Get the approved address for a single NFT - /// @dev Throws if `_tokenId` is not a valid NFT. - /// @param _tokenId The NFT to find the approved address for - /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint256 _tokenId) external view returns (address); - - /// @notice Query if an address is an authorized operator for another address - /// @param _owner The address that owns the NFTs - /// @param _operator The address that acts on behalf of the owner - /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} - -/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. -interface IERC721TokenReceiver { - /// @notice Handle the receipt of an NFT - /// @dev The ERC721 smart contract calls this function on the recipient - /// after a `transfer`. This function MAY throw to revert and reject the - /// transfer. Return of other than the magic value MUST result in the - /// transaction being reverted. - /// Note: the contract address is always the message sender. - /// @param _operator The address which called `safeTransferFrom` function - /// @param _from The address which previously owned the token - /// @param _tokenId The NFT identifier which is being transferred - /// @param _data Additional data with no specified format - /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` - /// unless throwing - function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) - external - returns (bytes4); -} - -/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x5b5e139f. -interface IERC721Metadata is IERC721 { - /// @notice A descriptive name for a collection of NFTs in this contract - function name() external view returns (string memory _name); - - /// @notice An abbreviated name for NFTs in this contract - function symbol() external view returns (string memory _symbol); - - /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. - /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC - /// 3986. The URI may point to a JSON file that conforms to the "ERC721 - /// Metadata JSON Schema". - function tokenURI(uint256 _tokenId) external view returns (string memory); -} - -/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension -/// @dev See https://eips.ethereum.org/EIPS/eip-721 -/// Note: the ERC-165 identifier for this interface is 0x780e9d63. -interface IERC721Enumerable is IERC721 { - /// @notice Count NFTs tracked by this contract - /// @return A count of valid NFTs tracked by this contract, where each one of - /// them has an assigned and queryable owner not equal to the zero address - function totalSupply() external view returns (uint256); - - /// @notice Enumerate valid NFTs - /// @dev Throws if `_index` >= `totalSupply()`. - /// @param _index A counter less than `totalSupply()` - /// @return The token identifier for the `_index`th NFT, - /// (sort order not specified) - function tokenByIndex(uint256 _index) external view returns (uint256); - - /// @notice Enumerate NFTs assigned to an owner - /// @dev Throws if `_index` >= `balanceOf(_owner)` or if - /// `_owner` is the zero address, representing invalid NFTs. - /// @param _owner An address where we are interested in NFTs owned by them - /// @param _index A counter less than `balanceOf(_owner)` - /// @return The token identifier for the `_index`th NFT assigned to `_owner`, - /// (sort order not specified) - function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol deleted file mode 100644 index 0d031b7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/interfaces/IMulticall3.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -pragma experimental ABIEncoderV2; - -interface IMulticall3 { - struct Call { - address target; - bytes callData; - } - - struct Call3 { - address target; - bool allowFailure; - bytes callData; - } - - struct Call3Value { - address target; - bool allowFailure; - uint256 value; - bytes callData; - } - - struct Result { - bool success; - bytes returnData; - } - - function aggregate(Call[] calldata calls) - external - payable - returns (uint256 blockNumber, bytes[] memory returnData); - - function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); - - function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); - - function blockAndAggregate(Call[] calldata calls) - external - payable - returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); - - function getBasefee() external view returns (uint256 basefee); - - function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); - - function getBlockNumber() external view returns (uint256 blockNumber); - - function getChainId() external view returns (uint256 chainid); - - function getCurrentBlockCoinbase() external view returns (address coinbase); - - function getCurrentBlockDifficulty() external view returns (uint256 difficulty); - - function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); - - function getCurrentBlockTimestamp() external view returns (uint256 timestamp); - - function getEthBalance(address addr) external view returns (uint256 balance); - - function getLastBlockHash() external view returns (bytes32 blockHash); - - function tryAggregate(bool requireSuccess, Call[] calldata calls) - external - payable - returns (Result[] memory returnData); - - function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) - external - payable - returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol deleted file mode 100644 index 2a022fa..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC20.sol +++ /dev/null @@ -1,234 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -import {IERC20} from "../interfaces/IERC20.sol"; - -/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. -/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol -contract MockERC20 is IERC20 { - /*////////////////////////////////////////////////////////////// - METADATA STORAGE - //////////////////////////////////////////////////////////////*/ - - string internal _name; - - string internal _symbol; - - uint8 internal _decimals; - - function name() external view override returns (string memory) { - return _name; - } - - function symbol() external view override returns (string memory) { - return _symbol; - } - - function decimals() external view override returns (uint8) { - return _decimals; - } - - /*////////////////////////////////////////////////////////////// - ERC20 STORAGE - //////////////////////////////////////////////////////////////*/ - - uint256 internal _totalSupply; - - mapping(address => uint256) internal _balanceOf; - - mapping(address => mapping(address => uint256)) internal _allowance; - - function totalSupply() external view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address owner) external view override returns (uint256) { - return _balanceOf[owner]; - } - - function allowance(address owner, address spender) external view override returns (uint256) { - return _allowance[owner][spender]; - } - - /*////////////////////////////////////////////////////////////// - EIP-2612 STORAGE - //////////////////////////////////////////////////////////////*/ - - uint256 internal INITIAL_CHAIN_ID; - - bytes32 internal INITIAL_DOMAIN_SEPARATOR; - - mapping(address => uint256) public nonces; - - /*////////////////////////////////////////////////////////////// - INITIALIZE - //////////////////////////////////////////////////////////////*/ - - /// @dev A bool to track whether the contract has been initialized. - bool private initialized; - - /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and - /// syntaxes, we add an initialization function that can be called only once. - function initialize(string memory name_, string memory symbol_, uint8 decimals_) public { - require(!initialized, "ALREADY_INITIALIZED"); - - _name = name_; - _symbol = symbol_; - _decimals = decimals_; - - INITIAL_CHAIN_ID = _pureChainId(); - INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); - - initialized = true; - } - - /*////////////////////////////////////////////////////////////// - ERC20 LOGIC - //////////////////////////////////////////////////////////////*/ - - function approve(address spender, uint256 amount) public virtual override returns (bool) { - _allowance[msg.sender][spender] = amount; - - emit Approval(msg.sender, spender, amount); - - return true; - } - - function transfer(address to, uint256 amount) public virtual override returns (bool) { - _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); - _balanceOf[to] = _add(_balanceOf[to], amount); - - emit Transfer(msg.sender, to, amount); - - return true; - } - - function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { - uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. - - if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); - - _balanceOf[from] = _sub(_balanceOf[from], amount); - _balanceOf[to] = _add(_balanceOf[to], amount); - - emit Transfer(from, to, amount); - - return true; - } - - /*////////////////////////////////////////////////////////////// - EIP-2612 LOGIC - //////////////////////////////////////////////////////////////*/ - - function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) - public - virtual - { - require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); - - address recoveredAddress = ecrecover( - keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR(), - keccak256( - abi.encode( - keccak256( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ), - owner, - spender, - value, - nonces[owner]++, - deadline - ) - ) - ) - ), - v, - r, - s - ); - - require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); - - _allowance[recoveredAddress][spender] = value; - - emit Approval(owner, spender, value); - } - - function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { - return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); - } - - function computeDomainSeparator() internal view virtual returns (bytes32) { - return keccak256( - abi.encode( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), - keccak256(bytes(_name)), - keccak256("1"), - _pureChainId(), - address(this) - ) - ); - } - - /*////////////////////////////////////////////////////////////// - INTERNAL MINT/BURN LOGIC - //////////////////////////////////////////////////////////////*/ - - function _mint(address to, uint256 amount) internal virtual { - _totalSupply = _add(_totalSupply, amount); - _balanceOf[to] = _add(_balanceOf[to], amount); - - emit Transfer(address(0), to, amount); - } - - function _burn(address from, uint256 amount) internal virtual { - _balanceOf[from] = _sub(_balanceOf[from], amount); - _totalSupply = _sub(_totalSupply, amount); - - emit Transfer(from, address(0), amount); - } - - /*////////////////////////////////////////////////////////////// - INTERNAL SAFE MATH LOGIC - //////////////////////////////////////////////////////////////*/ - - function _add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "ERC20: addition overflow"); - return c; - } - - function _sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(a >= b, "ERC20: subtraction underflow"); - return a - b; - } - - /*////////////////////////////////////////////////////////////// - HELPERS - //////////////////////////////////////////////////////////////*/ - - // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no - // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We - // can't simply access the chain ID in a normal view or pure function because the solc View Pure - // Checker changed `chainid` from pure to view in 0.8.0. - function _viewChainId() private view returns (uint256 chainId) { - // Assembly required since `block.chainid` was introduced in 0.8.0. - assembly { - chainId := chainid() - } - - address(this); // Silence warnings in older Solc versions. - } - - function _pureChainId() private pure returns (uint256 chainId) { - function() internal view returns (uint256) fnIn = _viewChainId; - function() internal pure returns (uint256) pureChainId; - assembly { - pureChainId := fnIn - } - chainId = pureChainId(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol deleted file mode 100644 index 7a4909e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/mocks/MockERC721.sol +++ /dev/null @@ -1,231 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol"; - -/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. -/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol -contract MockERC721 is IERC721Metadata { - /*////////////////////////////////////////////////////////////// - METADATA STORAGE/LOGIC - //////////////////////////////////////////////////////////////*/ - - string internal _name; - - string internal _symbol; - - function name() external view override returns (string memory) { - return _name; - } - - function symbol() external view override returns (string memory) { - return _symbol; - } - - function tokenURI(uint256 id) public view virtual override returns (string memory) {} - - /*////////////////////////////////////////////////////////////// - ERC721 BALANCE/OWNER STORAGE - //////////////////////////////////////////////////////////////*/ - - mapping(uint256 => address) internal _ownerOf; - - mapping(address => uint256) internal _balanceOf; - - function ownerOf(uint256 id) public view virtual override returns (address owner) { - require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); - } - - function balanceOf(address owner) public view virtual override returns (uint256) { - require(owner != address(0), "ZERO_ADDRESS"); - - return _balanceOf[owner]; - } - - /*////////////////////////////////////////////////////////////// - ERC721 APPROVAL STORAGE - //////////////////////////////////////////////////////////////*/ - - mapping(uint256 => address) internal _getApproved; - - mapping(address => mapping(address => bool)) internal _isApprovedForAll; - - function getApproved(uint256 id) public view virtual override returns (address) { - return _getApproved[id]; - } - - function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { - return _isApprovedForAll[owner][operator]; - } - - /*////////////////////////////////////////////////////////////// - INITIALIZE - //////////////////////////////////////////////////////////////*/ - - /// @dev A bool to track whether the contract has been initialized. - bool private initialized; - - /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and - /// syntaxes, we add an initialization function that can be called only once. - function initialize(string memory name_, string memory symbol_) public { - require(!initialized, "ALREADY_INITIALIZED"); - - _name = name_; - _symbol = symbol_; - - initialized = true; - } - - /*////////////////////////////////////////////////////////////// - ERC721 LOGIC - //////////////////////////////////////////////////////////////*/ - - function approve(address spender, uint256 id) public payable virtual override { - address owner = _ownerOf[id]; - - require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); - - _getApproved[id] = spender; - - emit Approval(owner, spender, id); - } - - function setApprovalForAll(address operator, bool approved) public virtual override { - _isApprovedForAll[msg.sender][operator] = approved; - - emit ApprovalForAll(msg.sender, operator, approved); - } - - function transferFrom(address from, address to, uint256 id) public payable virtual override { - require(from == _ownerOf[id], "WRONG_FROM"); - - require(to != address(0), "INVALID_RECIPIENT"); - - require( - msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], - "NOT_AUTHORIZED" - ); - - // Underflow of the sender's balance is impossible because we check for - // ownership above and the recipient's balance can't realistically overflow. - _balanceOf[from]--; - - _balanceOf[to]++; - - _ownerOf[id] = to; - - delete _getApproved[id]; - - emit Transfer(from, to, id); - } - - function safeTransferFrom(address from, address to, uint256 id) public payable virtual override { - transferFrom(from, to, id); - - require( - !_isContract(to) - || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") - == IERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); - } - - function safeTransferFrom(address from, address to, uint256 id, bytes memory data) - public - payable - virtual - override - { - transferFrom(from, to, id); - - require( - !_isContract(to) - || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) - == IERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); - } - - /*////////////////////////////////////////////////////////////// - ERC165 LOGIC - //////////////////////////////////////////////////////////////*/ - - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 - || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 - || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata - } - - /*////////////////////////////////////////////////////////////// - INTERNAL MINT/BURN LOGIC - //////////////////////////////////////////////////////////////*/ - - function _mint(address to, uint256 id) internal virtual { - require(to != address(0), "INVALID_RECIPIENT"); - - require(_ownerOf[id] == address(0), "ALREADY_MINTED"); - - // Counter overflow is incredibly unrealistic. - - _balanceOf[to]++; - - _ownerOf[id] = to; - - emit Transfer(address(0), to, id); - } - - function _burn(uint256 id) internal virtual { - address owner = _ownerOf[id]; - - require(owner != address(0), "NOT_MINTED"); - - _balanceOf[owner]--; - - delete _ownerOf[id]; - - delete _getApproved[id]; - - emit Transfer(owner, address(0), id); - } - - /*////////////////////////////////////////////////////////////// - INTERNAL SAFE MINT LOGIC - //////////////////////////////////////////////////////////////*/ - - function _safeMint(address to, uint256 id) internal virtual { - _mint(to, id); - - require( - !_isContract(to) - || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") - == IERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); - } - - function _safeMint(address to, uint256 id, bytes memory data) internal virtual { - _mint(to, id); - - require( - !_isContract(to) - || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) - == IERC721TokenReceiver.onERC721Received.selector, - "UNSAFE_RECIPIENT" - ); - } - - /*////////////////////////////////////////////////////////////// - HELPERS - //////////////////////////////////////////////////////////////*/ - - function _isContract(address _addr) private view returns (bool) { - uint256 codeLength; - - // Assembly required for versions < 0.8.0 to check extcodesize. - assembly { - codeLength := extcodesize(_addr) - } - - return codeLength > 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol deleted file mode 100644 index 87c475a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/forge-std/src/safeconsole.sol +++ /dev/null @@ -1,13937 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.6.2 <0.9.0; - -/// @author philogy -/// @dev Code generated automatically by script. -library safeconsole { - uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; - - // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) - // for the view-to-pure log trick. - function _sendLogPayload(uint256 offset, uint256 size) private pure { - function(uint256, uint256) internal view fnIn = _sendLogPayloadView; - function(uint256, uint256) internal pure pureSendLogPayload; - /// @solidity memory-safe-assembly - assembly { - pureSendLogPayload := fnIn - } - pureSendLogPayload(offset, size); - } - - function _sendLogPayloadView(uint256 offset, uint256 size) private view { - /// @solidity memory-safe-assembly - assembly { - pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) - } - } - - function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { - function(uint256, uint256, uint256) internal view fnIn = _memcopyView; - function(uint256, uint256, uint256) internal pure pureMemcopy; - /// @solidity memory-safe-assembly - assembly { - pureMemcopy := fnIn - } - pureMemcopy(fromOffset, toOffset, length); - } - - function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { - /// @solidity memory-safe-assembly - assembly { - pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) - } - } - - function logMemory(uint256 offset, uint256 length) internal pure { - if (offset >= 0x60) { - // Sufficient memory before slice to prepare call header. - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(sub(offset, 0x60)) - m1 := mload(sub(offset, 0x40)) - m2 := mload(sub(offset, 0x20)) - // Selector of `log(bytes)`. - mstore(sub(offset, 0x60), 0x0be77f56) - mstore(sub(offset, 0x40), 0x20) - mstore(sub(offset, 0x20), length) - } - _sendLogPayload(offset - 0x44, length + 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(sub(offset, 0x60), m0) - mstore(sub(offset, 0x40), m1) - mstore(sub(offset, 0x20), m2) - } - } else { - // Insufficient space, so copy slice forward, add header and reverse. - bytes32 m0; - bytes32 m1; - bytes32 m2; - uint256 endOffset = offset + length; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(add(endOffset, 0x00)) - m1 := mload(add(endOffset, 0x20)) - m2 := mload(add(endOffset, 0x40)) - } - _memcopy(offset, offset + 0x60, length); - /// @solidity memory-safe-assembly - assembly { - // Selector of `log(bytes)`. - mstore(add(offset, 0x00), 0x0be77f56) - mstore(add(offset, 0x20), 0x20) - mstore(add(offset, 0x40), length) - } - _sendLogPayload(offset + 0x1c, length + 0x44); - _memcopy(offset + 0x60, offset, length); - /// @solidity memory-safe-assembly - assembly { - mstore(add(endOffset, 0x00), m0) - mstore(add(endOffset, 0x20), m1) - mstore(add(endOffset, 0x40), m2) - } - } - } - - function log(address p0) internal pure { - bytes32 m0; - bytes32 m1; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - // Selector of `log(address)`. - mstore(0x00, 0x2c2ecbc2) - mstore(0x20, p0) - } - _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - } - } - - function log(bool p0) internal pure { - bytes32 m0; - bytes32 m1; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - // Selector of `log(bool)`. - mstore(0x00, 0x32458eed) - mstore(0x20, p0) - } - _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - } - } - - function log(uint256 p0) internal pure { - bytes32 m0; - bytes32 m1; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - // Selector of `log(uint256)`. - mstore(0x00, 0xf82c50f1) - mstore(0x20, p0) - } - _sendLogPayload(0x1c, 0x24); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - } - } - - function log(bytes32 p0) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(string)`. - mstore(0x00, 0x41304fac) - mstore(0x20, 0x20) - writeString(0x40, p0) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, address p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(address,address)`. - mstore(0x00, 0xdaf0d4aa) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(address p0, bool p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(address,bool)`. - mstore(0x00, 0x75b605d3) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(address p0, uint256 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(address,uint256)`. - mstore(0x00, 0x8309e8a8) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(address p0, bytes32 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,string)`. - mstore(0x00, 0x759f86bb) - mstore(0x20, p0) - mstore(0x40, 0x40) - writeString(0x60, p1) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(bool,address)`. - mstore(0x00, 0x853c4849) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(bool p0, bool p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(bool,bool)`. - mstore(0x00, 0x2a110e83) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(bool p0, uint256 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(bool,uint256)`. - mstore(0x00, 0x399174d3) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(bool p0, bytes32 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,string)`. - mstore(0x00, 0x8feac525) - mstore(0x20, p0) - mstore(0x40, 0x40) - writeString(0x60, p1) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(uint256,address)`. - mstore(0x00, 0x69276c86) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(uint256 p0, bool p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(uint256,bool)`. - mstore(0x00, 0x1c9d7eb3) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(uint256 p0, uint256 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - // Selector of `log(uint256,uint256)`. - mstore(0x00, 0xf666715a) - mstore(0x20, p0) - mstore(0x40, p1) - } - _sendLogPayload(0x1c, 0x44); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - } - } - - function log(uint256 p0, bytes32 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,string)`. - mstore(0x00, 0x643fd0df) - mstore(0x20, p0) - mstore(0x40, 0x40) - writeString(0x60, p1) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bytes32 p0, address p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(string,address)`. - mstore(0x00, 0x319af333) - mstore(0x20, 0x40) - mstore(0x40, p1) - writeString(0x60, p0) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bytes32 p0, bool p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(string,bool)`. - mstore(0x00, 0xc3b55635) - mstore(0x20, 0x40) - mstore(0x40, p1) - writeString(0x60, p0) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bytes32 p0, uint256 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(string,uint256)`. - mstore(0x00, 0xb60e72cc) - mstore(0x20, 0x40) - mstore(0x40, p1) - writeString(0x60, p0) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bytes32 p0, bytes32 p1) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,string)`. - mstore(0x00, 0x4b5c4277) - mstore(0x20, 0x40) - mstore(0x40, 0x80) - writeString(0x60, p0) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,address,address)`. - mstore(0x00, 0x018c84c2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, address p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,address,bool)`. - mstore(0x00, 0xf2a66286) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, address p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,address,uint256)`. - mstore(0x00, 0x17fe6185) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, address p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,address,string)`. - mstore(0x00, 0x007150be) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, bool p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,bool,address)`. - mstore(0x00, 0xf11699ed) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, bool p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,bool,bool)`. - mstore(0x00, 0xeb830c92) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, bool p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,bool,uint256)`. - mstore(0x00, 0x9c4f99fb) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, bool p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,bool,string)`. - mstore(0x00, 0x212255cc) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, uint256 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,uint256,address)`. - mstore(0x00, 0x7bc0d848) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, uint256 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,uint256,bool)`. - mstore(0x00, 0x678209a8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, uint256 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(address,uint256,uint256)`. - mstore(0x00, 0xb69bcaf6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(address p0, uint256 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,uint256,string)`. - mstore(0x00, 0xa1f2e8aa) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, bytes32 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,string,address)`. - mstore(0x00, 0xf08744e8) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, bytes32 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,string,bool)`. - mstore(0x00, 0xcf020fb1) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, bytes32 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(address,string,uint256)`. - mstore(0x00, 0x67dd6ff1) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(address p0, bytes32 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(address,string,string)`. - mstore(0x00, 0xfb772265) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, 0xa0) - writeString(0x80, p1) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bool p0, address p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,address,address)`. - mstore(0x00, 0xd2763667) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, address p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,address,bool)`. - mstore(0x00, 0x18c9c746) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, address p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,address,uint256)`. - mstore(0x00, 0x5f7b9afb) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, address p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,address,string)`. - mstore(0x00, 0xde9a9270) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, bool p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,bool,address)`. - mstore(0x00, 0x1078f68d) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, bool p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,bool,bool)`. - mstore(0x00, 0x50709698) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, bool p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,bool,uint256)`. - mstore(0x00, 0x12f21602) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, bool p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,bool,string)`. - mstore(0x00, 0x2555fa46) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, uint256 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,uint256,address)`. - mstore(0x00, 0x088ef9d2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, uint256 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,uint256,bool)`. - mstore(0x00, 0xe8defba9) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, uint256 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(bool,uint256,uint256)`. - mstore(0x00, 0x37103367) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(bool p0, uint256 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,uint256,string)`. - mstore(0x00, 0xc3fc3970) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, bytes32 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,string,address)`. - mstore(0x00, 0x9591b953) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, bytes32 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,string,bool)`. - mstore(0x00, 0xdbb4c247) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, bytes32 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(bool,string,uint256)`. - mstore(0x00, 0x1093ee11) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bool p0, bytes32 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(bool,string,string)`. - mstore(0x00, 0xb076847f) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, 0xa0) - writeString(0x80, p1) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(uint256 p0, address p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,address,address)`. - mstore(0x00, 0xbcfd9be0) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, address p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,address,bool)`. - mstore(0x00, 0x9b6ec042) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, address p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,address,uint256)`. - mstore(0x00, 0x5a9b5ed5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, address p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,address,string)`. - mstore(0x00, 0x63cb41f9) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, bool p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,bool,address)`. - mstore(0x00, 0x35085f7b) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, bool p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,bool,bool)`. - mstore(0x00, 0x20718650) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, bool p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,bool,uint256)`. - mstore(0x00, 0x20098014) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, bool p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,bool,string)`. - mstore(0x00, 0x85775021) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, uint256 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,uint256,address)`. - mstore(0x00, 0x5c96b331) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, uint256 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,uint256,bool)`. - mstore(0x00, 0x4766da72) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, uint256 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - // Selector of `log(uint256,uint256,uint256)`. - mstore(0x00, 0xd1ed7a3c) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - } - _sendLogPayload(0x1c, 0x64); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - } - } - - function log(uint256 p0, uint256 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,uint256,string)`. - mstore(0x00, 0x71d04af2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x60) - writeString(0x80, p2) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, bytes32 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,string,address)`. - mstore(0x00, 0x7afac959) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, bytes32 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,string,bool)`. - mstore(0x00, 0x4ceda75a) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, bytes32 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(uint256,string,uint256)`. - mstore(0x00, 0x37aa7d4c) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, p2) - writeString(0x80, p1) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(uint256,string,string)`. - mstore(0x00, 0xb115611f) - mstore(0x20, p0) - mstore(0x40, 0x60) - mstore(0x60, 0xa0) - writeString(0x80, p1) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, address p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,address,address)`. - mstore(0x00, 0xfcec75e0) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, address p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,address,bool)`. - mstore(0x00, 0xc91d5ed4) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, address p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,address,uint256)`. - mstore(0x00, 0x0d26b925) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, address p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,address,string)`. - mstore(0x00, 0xe0e9ad4f) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, 0xa0) - writeString(0x80, p0) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, bool p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,bool,address)`. - mstore(0x00, 0x932bbb38) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, bool p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,bool,bool)`. - mstore(0x00, 0x850b7ad6) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, bool p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,bool,uint256)`. - mstore(0x00, 0xc95958d6) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, bool p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,bool,string)`. - mstore(0x00, 0xe298f47d) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, 0xa0) - writeString(0x80, p0) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, uint256 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,uint256,address)`. - mstore(0x00, 0x1c7ec448) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, uint256 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,uint256,bool)`. - mstore(0x00, 0xca7733b1) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, uint256 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - // Selector of `log(string,uint256,uint256)`. - mstore(0x00, 0xca47c4eb) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, p2) - writeString(0x80, p0) - } - _sendLogPayload(0x1c, 0xa4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - } - } - - function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,uint256,string)`. - mstore(0x00, 0x5970e089) - mstore(0x20, 0x60) - mstore(0x40, p1) - mstore(0x60, 0xa0) - writeString(0x80, p0) - writeString(0xc0, p2) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, bytes32 p1, address p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,string,address)`. - mstore(0x00, 0x95ed0195) - mstore(0x20, 0x60) - mstore(0x40, 0xa0) - mstore(0x60, p2) - writeString(0x80, p0) - writeString(0xc0, p1) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, bytes32 p1, bool p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,string,bool)`. - mstore(0x00, 0xb0e0f9b5) - mstore(0x20, 0x60) - mstore(0x40, 0xa0) - mstore(0x60, p2) - writeString(0x80, p0) - writeString(0xc0, p1) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - // Selector of `log(string,string,uint256)`. - mstore(0x00, 0x5821efa1) - mstore(0x20, 0x60) - mstore(0x40, 0xa0) - mstore(0x60, p2) - writeString(0x80, p0) - writeString(0xc0, p1) - } - _sendLogPayload(0x1c, 0xe4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - } - } - - function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - // Selector of `log(string,string,string)`. - mstore(0x00, 0x2ced7cef) - mstore(0x20, 0x60) - mstore(0x40, 0xa0) - mstore(0x60, 0xe0) - writeString(0x80, p0) - writeString(0xc0, p1) - writeString(0x100, p2) - } - _sendLogPayload(0x1c, 0x124); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - } - } - - function log(address p0, address p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,address,address)`. - mstore(0x00, 0x665bf134) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,address,bool)`. - mstore(0x00, 0x0e378994) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,address,uint256)`. - mstore(0x00, 0x94250d77) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,address,string)`. - mstore(0x00, 0xf808da20) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,bool,address)`. - mstore(0x00, 0x9f1bc36e) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,bool,bool)`. - mstore(0x00, 0x2cd4134a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,bool,uint256)`. - mstore(0x00, 0x3971e78c) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,bool,string)`. - mstore(0x00, 0xaa6540c8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,uint256,address)`. - mstore(0x00, 0x8da6def5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,uint256,bool)`. - mstore(0x00, 0x9b4254e2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,address,uint256,uint256)`. - mstore(0x00, 0xbe553481) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,uint256,string)`. - mstore(0x00, 0xfdb4f990) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,string,address)`. - mstore(0x00, 0x8f736d16) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,string,bool)`. - mstore(0x00, 0x6f1a594e) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,address,string,uint256)`. - mstore(0x00, 0xef1cefe7) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,address,string,string)`. - mstore(0x00, 0x21bdaf25) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bool p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,address,address)`. - mstore(0x00, 0x660375dd) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,address,bool)`. - mstore(0x00, 0xa6f50b0f) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,address,uint256)`. - mstore(0x00, 0xa75c59de) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,address,string)`. - mstore(0x00, 0x2dd778e6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,bool,address)`. - mstore(0x00, 0xcf394485) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,bool,bool)`. - mstore(0x00, 0xcac43479) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,bool,uint256)`. - mstore(0x00, 0x8c4e5de6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,bool,string)`. - mstore(0x00, 0xdfc4a2e8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,uint256,address)`. - mstore(0x00, 0xccf790a1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,uint256,bool)`. - mstore(0x00, 0xc4643e20) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,bool,uint256,uint256)`. - mstore(0x00, 0x386ff5f4) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,uint256,string)`. - mstore(0x00, 0x0aa6cfad) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,string,address)`. - mstore(0x00, 0x19fd4956) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,string,bool)`. - mstore(0x00, 0x50ad461d) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,bool,string,uint256)`. - mstore(0x00, 0x80e6a20b) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,bool,string,string)`. - mstore(0x00, 0x475c5c33) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, uint256 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,address,address)`. - mstore(0x00, 0x478d1c62) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,address,bool)`. - mstore(0x00, 0xa1bcc9b3) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,address,uint256)`. - mstore(0x00, 0x100f650e) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,address,string)`. - mstore(0x00, 0x1da986ea) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,bool,address)`. - mstore(0x00, 0xa31bfdcc) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,bool,bool)`. - mstore(0x00, 0x3bf5e537) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,bool,uint256)`. - mstore(0x00, 0x22f6b999) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,bool,string)`. - mstore(0x00, 0xc5ad85f9) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,uint256,address)`. - mstore(0x00, 0x20e3984d) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,uint256,bool)`. - mstore(0x00, 0x66f1bc67) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(address,uint256,uint256,uint256)`. - mstore(0x00, 0x34f0e636) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,uint256,string)`. - mstore(0x00, 0x4a28c017) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,string,address)`. - mstore(0x00, 0x5c430d47) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,string,bool)`. - mstore(0x00, 0xcf18105c) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,uint256,string,uint256)`. - mstore(0x00, 0xbf01f891) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,uint256,string,string)`. - mstore(0x00, 0x88a8c406) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,address,address)`. - mstore(0x00, 0x0d36fa20) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,address,bool)`. - mstore(0x00, 0x0df12b76) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,address,uint256)`. - mstore(0x00, 0x457fe3cf) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,address,string)`. - mstore(0x00, 0xf7e36245) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,bool,address)`. - mstore(0x00, 0x205871c2) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,bool,bool)`. - mstore(0x00, 0x5f1d5c9f) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,bool,uint256)`. - mstore(0x00, 0x515e38b6) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,bool,string)`. - mstore(0x00, 0xbc0b61fe) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,uint256,address)`. - mstore(0x00, 0x63183678) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,uint256,bool)`. - mstore(0x00, 0x0ef7e050) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(address,string,uint256,uint256)`. - mstore(0x00, 0x1dc8e1b8) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,uint256,string)`. - mstore(0x00, 0x448830a8) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,string,address)`. - mstore(0x00, 0xa04e2f87) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,string,bool)`. - mstore(0x00, 0x35a5071f) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(address,string,string,uint256)`. - mstore(0x00, 0x159f8927) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(address,string,string,string)`. - mstore(0x00, 0x5d02c50b) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p1) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bool p0, address p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,address,address)`. - mstore(0x00, 0x1d14d001) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,address,bool)`. - mstore(0x00, 0x46600be0) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,address,uint256)`. - mstore(0x00, 0x0c66d1be) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,address,string)`. - mstore(0x00, 0xd812a167) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,bool,address)`. - mstore(0x00, 0x1c41a336) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,bool,bool)`. - mstore(0x00, 0x6a9c478b) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,bool,uint256)`. - mstore(0x00, 0x07831502) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,bool,string)`. - mstore(0x00, 0x4a66cb34) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,uint256,address)`. - mstore(0x00, 0x136b05dd) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,uint256,bool)`. - mstore(0x00, 0xd6019f1c) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,address,uint256,uint256)`. - mstore(0x00, 0x7bf181a1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,uint256,string)`. - mstore(0x00, 0x51f09ff8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,string,address)`. - mstore(0x00, 0x6f7c603e) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,string,bool)`. - mstore(0x00, 0xe2bfd60b) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,address,string,uint256)`. - mstore(0x00, 0xc21f64c7) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,address,string,string)`. - mstore(0x00, 0xa73c1db6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bool p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,address,address)`. - mstore(0x00, 0xf4880ea4) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,address,bool)`. - mstore(0x00, 0xc0a302d8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,address,uint256)`. - mstore(0x00, 0x4c123d57) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,address,string)`. - mstore(0x00, 0xa0a47963) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,bool,address)`. - mstore(0x00, 0x8c329b1a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,bool,bool)`. - mstore(0x00, 0x3b2a5ce0) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,bool,uint256)`. - mstore(0x00, 0x6d7045c1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,bool,string)`. - mstore(0x00, 0x2ae408d4) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,uint256,address)`. - mstore(0x00, 0x54a7a9a0) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,uint256,bool)`. - mstore(0x00, 0x619e4d0e) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,bool,uint256,uint256)`. - mstore(0x00, 0x0bb00eab) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,uint256,string)`. - mstore(0x00, 0x7dd4d0e0) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,string,address)`. - mstore(0x00, 0xf9ad2b89) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,string,bool)`. - mstore(0x00, 0xb857163a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,bool,string,uint256)`. - mstore(0x00, 0xe3a9ca2f) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,bool,string,string)`. - mstore(0x00, 0x6d1e8751) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, uint256 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,address,address)`. - mstore(0x00, 0x26f560a8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,address,bool)`. - mstore(0x00, 0xb4c314ff) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,address,uint256)`. - mstore(0x00, 0x1537dc87) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,address,string)`. - mstore(0x00, 0x1bb3b09a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,bool,address)`. - mstore(0x00, 0x9acd3616) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,bool,bool)`. - mstore(0x00, 0xceb5f4d7) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,bool,uint256)`. - mstore(0x00, 0x7f9bbca2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,bool,string)`. - mstore(0x00, 0x9143dbb1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,uint256,address)`. - mstore(0x00, 0x00dd87b9) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,uint256,bool)`. - mstore(0x00, 0xbe984353) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(bool,uint256,uint256,uint256)`. - mstore(0x00, 0x374bb4b2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,uint256,string)`. - mstore(0x00, 0x8e69fb5d) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,string,address)`. - mstore(0x00, 0xfedd1fff) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,string,bool)`. - mstore(0x00, 0xe5e70b2b) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,uint256,string,uint256)`. - mstore(0x00, 0x6a1199e2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,uint256,string,string)`. - mstore(0x00, 0xf5bc2249) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,address,address)`. - mstore(0x00, 0x2b2b18dc) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,address,bool)`. - mstore(0x00, 0x6dd434ca) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,address,uint256)`. - mstore(0x00, 0xa5cada94) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,address,string)`. - mstore(0x00, 0x12d6c788) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,bool,address)`. - mstore(0x00, 0x538e06ab) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,bool,bool)`. - mstore(0x00, 0xdc5e935b) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,bool,uint256)`. - mstore(0x00, 0x1606a393) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,bool,string)`. - mstore(0x00, 0x483d0416) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,uint256,address)`. - mstore(0x00, 0x1596a1ce) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,uint256,bool)`. - mstore(0x00, 0x6b0e5d53) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(bool,string,uint256,uint256)`. - mstore(0x00, 0x28863fcb) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,uint256,string)`. - mstore(0x00, 0x1ad96de6) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,string,address)`. - mstore(0x00, 0x97d394d8) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,string,bool)`. - mstore(0x00, 0x1e4b87e5) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(bool,string,string,uint256)`. - mstore(0x00, 0x7be0c3eb) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(bool,string,string,string)`. - mstore(0x00, 0x1762e32a) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p1) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(uint256 p0, address p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,address,address)`. - mstore(0x00, 0x2488b414) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,address,bool)`. - mstore(0x00, 0x091ffaf5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,address,uint256)`. - mstore(0x00, 0x736efbb6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,address,string)`. - mstore(0x00, 0x031c6f73) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,bool,address)`. - mstore(0x00, 0xef72c513) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,bool,bool)`. - mstore(0x00, 0xe351140f) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,bool,uint256)`. - mstore(0x00, 0x5abd992a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,bool,string)`. - mstore(0x00, 0x90fb06aa) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,uint256,address)`. - mstore(0x00, 0x15c127b5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,uint256,bool)`. - mstore(0x00, 0x5f743a7c) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,address,uint256,uint256)`. - mstore(0x00, 0x0c9cd9c1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,uint256,string)`. - mstore(0x00, 0xddb06521) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,string,address)`. - mstore(0x00, 0x9cba8fff) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,string,bool)`. - mstore(0x00, 0xcc32ab07) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,address,string,uint256)`. - mstore(0x00, 0x46826b5d) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,address,string,string)`. - mstore(0x00, 0x3e128ca3) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bool p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,address,address)`. - mstore(0x00, 0xa1ef4cbb) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,address,bool)`. - mstore(0x00, 0x454d54a5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,address,uint256)`. - mstore(0x00, 0x078287f5) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,address,string)`. - mstore(0x00, 0xade052c7) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,bool,address)`. - mstore(0x00, 0x69640b59) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,bool,bool)`. - mstore(0x00, 0xb6f577a1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,bool,uint256)`. - mstore(0x00, 0x7464ce23) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,bool,string)`. - mstore(0x00, 0xdddb9561) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,uint256,address)`. - mstore(0x00, 0x88cb6041) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,uint256,bool)`. - mstore(0x00, 0x91a02e2a) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,bool,uint256,uint256)`. - mstore(0x00, 0xc6acc7a8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,uint256,string)`. - mstore(0x00, 0xde03e774) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,string,address)`. - mstore(0x00, 0xef529018) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,string,bool)`. - mstore(0x00, 0xeb928d7f) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,bool,string,uint256)`. - mstore(0x00, 0x2c1d0746) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,bool,string,string)`. - mstore(0x00, 0x68c8b8bd) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,address,address)`. - mstore(0x00, 0x56a5d1b1) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,address,bool)`. - mstore(0x00, 0x15cac476) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,address,uint256)`. - mstore(0x00, 0x88f6e4b2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,address,string)`. - mstore(0x00, 0x6cde40b8) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,bool,address)`. - mstore(0x00, 0x9a816a83) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,bool,bool)`. - mstore(0x00, 0xab085ae6) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,bool,uint256)`. - mstore(0x00, 0xeb7f6fd2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,bool,string)`. - mstore(0x00, 0xa5b4fc99) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,uint256,address)`. - mstore(0x00, 0xfa8185af) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,uint256,bool)`. - mstore(0x00, 0xc598d185) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - /// @solidity memory-safe-assembly - assembly { - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - // Selector of `log(uint256,uint256,uint256,uint256)`. - mstore(0x00, 0x193fb800) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - } - _sendLogPayload(0x1c, 0x84); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - } - } - - function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,uint256,string)`. - mstore(0x00, 0x59cfcbe3) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0x80) - writeString(0xa0, p3) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,string,address)`. - mstore(0x00, 0x42d21db7) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,string,bool)`. - mstore(0x00, 0x7af6ab25) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,uint256,string,uint256)`. - mstore(0x00, 0x5da297eb) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, p3) - writeString(0xa0, p2) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,uint256,string,string)`. - mstore(0x00, 0x27d8afd2) - mstore(0x20, p0) - mstore(0x40, p1) - mstore(0x60, 0x80) - mstore(0x80, 0xc0) - writeString(0xa0, p2) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,address,address)`. - mstore(0x00, 0x6168ed61) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,address,bool)`. - mstore(0x00, 0x90c30a56) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,address,uint256)`. - mstore(0x00, 0xe8d3018d) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,address,string)`. - mstore(0x00, 0x9c3adfa1) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,bool,address)`. - mstore(0x00, 0xae2ec581) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,bool,bool)`. - mstore(0x00, 0xba535d9c) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,bool,uint256)`. - mstore(0x00, 0xcf009880) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,bool,string)`. - mstore(0x00, 0xd2d423cd) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,uint256,address)`. - mstore(0x00, 0x3b2279b4) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,uint256,bool)`. - mstore(0x00, 0x691a8f74) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(uint256,string,uint256,uint256)`. - mstore(0x00, 0x82c25b74) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p1) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,uint256,string)`. - mstore(0x00, 0xb7b914ca) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p1) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,string,address)`. - mstore(0x00, 0xd583c602) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,string,bool)`. - mstore(0x00, 0xb3a6b6bd) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(uint256,string,string,uint256)`. - mstore(0x00, 0xb028c9bd) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p1) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(uint256,string,string,string)`. - mstore(0x00, 0x21ad0683) - mstore(0x20, p0) - mstore(0x40, 0x80) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p1) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, address p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,address,address)`. - mstore(0x00, 0xed8f28f6) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,address,bool)`. - mstore(0x00, 0xb59dbd60) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,address,uint256)`. - mstore(0x00, 0x8ef3f399) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,address,string)`. - mstore(0x00, 0x800a1c67) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,bool,address)`. - mstore(0x00, 0x223603bd) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,bool,bool)`. - mstore(0x00, 0x79884c2b) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,bool,uint256)`. - mstore(0x00, 0x3e9f866a) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,bool,string)`. - mstore(0x00, 0x0454c079) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,uint256,address)`. - mstore(0x00, 0x63fb8bc5) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,uint256,bool)`. - mstore(0x00, 0xfc4845f0) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,address,uint256,uint256)`. - mstore(0x00, 0xf8f51b1e) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,uint256,string)`. - mstore(0x00, 0x5a477632) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,string,address)`. - mstore(0x00, 0xaabc9a31) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,string,bool)`. - mstore(0x00, 0x5f15d28c) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,address,string,uint256)`. - mstore(0x00, 0x91d1112e) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,address,string,string)`. - mstore(0x00, 0x245986f2) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bool p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,address,address)`. - mstore(0x00, 0x33e9dd1d) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,address,bool)`. - mstore(0x00, 0x958c28c6) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,address,uint256)`. - mstore(0x00, 0x5d08bb05) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,address,string)`. - mstore(0x00, 0x2d8e33a4) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,bool,address)`. - mstore(0x00, 0x7190a529) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,bool,bool)`. - mstore(0x00, 0x895af8c5) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,bool,uint256)`. - mstore(0x00, 0x8e3f78a9) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,bool,string)`. - mstore(0x00, 0x9d22d5dd) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,uint256,address)`. - mstore(0x00, 0x935e09bf) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,uint256,bool)`. - mstore(0x00, 0x8af7cf8a) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,bool,uint256,uint256)`. - mstore(0x00, 0x64b5bb67) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,uint256,string)`. - mstore(0x00, 0x742d6ee7) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,string,address)`. - mstore(0x00, 0xe0625b29) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,string,bool)`. - mstore(0x00, 0x3f8a701d) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,bool,string,uint256)`. - mstore(0x00, 0x24f91465) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,bool,string,string)`. - mstore(0x00, 0xa826caeb) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,address,address)`. - mstore(0x00, 0x5ea2b7ae) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,address,bool)`. - mstore(0x00, 0x82112a42) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,address,uint256)`. - mstore(0x00, 0x4f04fdc6) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,address,string)`. - mstore(0x00, 0x9ffb2f93) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,bool,address)`. - mstore(0x00, 0xe0e95b98) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,bool,bool)`. - mstore(0x00, 0x354c36d6) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,bool,uint256)`. - mstore(0x00, 0xe41b6f6f) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,bool,string)`. - mstore(0x00, 0xabf73a98) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,uint256,address)`. - mstore(0x00, 0xe21de278) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,uint256,bool)`. - mstore(0x00, 0x7626db92) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - // Selector of `log(string,uint256,uint256,uint256)`. - mstore(0x00, 0xa7a87853) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - } - _sendLogPayload(0x1c, 0xc4); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - } - } - - function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,uint256,string)`. - mstore(0x00, 0x854b3496) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, p2) - mstore(0x80, 0xc0) - writeString(0xa0, p0) - writeString(0xe0, p3) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,string,address)`. - mstore(0x00, 0x7c4632a4) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,string,bool)`. - mstore(0x00, 0x7d24491d) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,uint256,string,uint256)`. - mstore(0x00, 0xc67ea9d1) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p2) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,uint256,string,string)`. - mstore(0x00, 0x5ab84e1f) - mstore(0x20, 0x80) - mstore(0x40, p1) - mstore(0x60, 0xc0) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p2) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,address,address)`. - mstore(0x00, 0x439c7bef) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,address,bool)`. - mstore(0x00, 0x5ccd4e37) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,address,uint256)`. - mstore(0x00, 0x7cc3c607) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,address,string)`. - mstore(0x00, 0xeb1bff80) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,bool,address)`. - mstore(0x00, 0xc371c7db) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,bool,bool)`. - mstore(0x00, 0x40785869) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,bool,uint256)`. - mstore(0x00, 0xd6aefad2) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,bool,string)`. - mstore(0x00, 0x5e84b0ea) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,uint256,address)`. - mstore(0x00, 0x1023f7b2) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,uint256,bool)`. - mstore(0x00, 0xc3a8a654) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - // Selector of `log(string,string,uint256,uint256)`. - mstore(0x00, 0xf45d7d2c) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - } - _sendLogPayload(0x1c, 0x104); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - } - } - - function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,uint256,string)`. - mstore(0x00, 0x5d1a971a) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, p2) - mstore(0x80, 0x100) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p3) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,string,address)`. - mstore(0x00, 0x6d572f44) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, 0x100) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p2) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,string,bool)`. - mstore(0x00, 0x2c1754ed) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, 0x100) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p2) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - // Selector of `log(string,string,string,uint256)`. - mstore(0x00, 0x8eafb02b) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, 0x100) - mstore(0x80, p3) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p2) - } - _sendLogPayload(0x1c, 0x144); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - } - } - - function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { - bytes32 m0; - bytes32 m1; - bytes32 m2; - bytes32 m3; - bytes32 m4; - bytes32 m5; - bytes32 m6; - bytes32 m7; - bytes32 m8; - bytes32 m9; - bytes32 m10; - bytes32 m11; - bytes32 m12; - /// @solidity memory-safe-assembly - assembly { - function writeString(pos, w) { - let length := 0 - for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } - mstore(pos, length) - let shift := sub(256, shl(3, length)) - mstore(add(pos, 0x20), shl(shift, shr(shift, w))) - } - m0 := mload(0x00) - m1 := mload(0x20) - m2 := mload(0x40) - m3 := mload(0x60) - m4 := mload(0x80) - m5 := mload(0xa0) - m6 := mload(0xc0) - m7 := mload(0xe0) - m8 := mload(0x100) - m9 := mload(0x120) - m10 := mload(0x140) - m11 := mload(0x160) - m12 := mload(0x180) - // Selector of `log(string,string,string,string)`. - mstore(0x00, 0xde68f20a) - mstore(0x20, 0x80) - mstore(0x40, 0xc0) - mstore(0x60, 0x100) - mstore(0x80, 0x140) - writeString(0xa0, p0) - writeString(0xe0, p1) - writeString(0x120, p2) - writeString(0x160, p3) - } - _sendLogPayload(0x1c, 0x184); - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, m0) - mstore(0x20, m1) - mstore(0x40, m2) - mstore(0x60, m3) - mstore(0x80, m4) - mstore(0xa0, m5) - mstore(0xc0, m6) - mstore(0xe0, m7) - mstore(0x100, m8) - mstore(0x120, m9) - mstore(0x140, m10) - mstore(0x160, m11) - mstore(0x180, m12) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol deleted file mode 100644 index 988cf72..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/proxy/Proxy.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) - -pragma solidity ^0.8.0; - -/** - * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM - * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to - * be specified by overriding the virtual {_implementation} function. - * - * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a - * different contract through the {_delegate} function. - * - * The success and return data of the delegated call will be returned back to the caller of the proxy. - */ -abstract contract Proxy { - /** - * @dev Delegates the current call to `implementation`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _delegate(address implementation) internal virtual { - assembly { - // Copy msg.data. We take full control of memory in this inline assembly - // block because it will not return to Solidity code. We overwrite the - // Solidity scratch pad at memory position 0. - calldatacopy(0, 0, calldatasize()) - - // Call the implementation. - // out and outsize are 0 because we don't know the size yet. - let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) - - // Copy the returned data. - returndatacopy(0, 0, returndatasize()) - - switch result - // delegatecall returns 0 on error. - case 0 { - revert(0, returndatasize()) - } - default { - return(0, returndatasize()) - } - } - } - - /** - * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function - * and {_fallback} should delegate. - */ - function _implementation() internal view virtual returns (address); - - /** - * @dev Delegates the current call to the address returned by `_implementation()`. - * - * This function does not return to its internal call site, it will return directly to the external caller. - */ - function _fallback() internal virtual { - _beforeFallback(); - _delegate(_implementation()); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other - * function in the contract matches the call data. - */ - fallback() external payable virtual { - _fallback(); - } - - /** - * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data - * is empty. - */ - receive() external payable virtual { - _fallback(); - } - - /** - * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` - * call, or as part of the Solidity `fallback` or `receive` functions. - * - * If overridden should call `super._beforeFallback()`. - */ - function _beforeFallback() internal virtual {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol deleted file mode 100644 index 69f3bf8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol +++ /dev/null @@ -1,244 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol deleted file mode 100644 index f304065..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Context.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol deleted file mode 100644 index 3557f36..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableMap.sol +++ /dev/null @@ -1,529 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol) - -pragma solidity ^0.8.0; - -import "./EnumerableSet.sol"; - -/** - * @dev Library for managing an enumerable variant of Solidity's - * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] - * type. - * - * Maps have the following properties: - * - * - Entries are added, removed, and checked for existence in constant time - * (O(1)). - * - Entries are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableMap for EnumerableMap.UintToAddressMap; - * - * // Declare a set state variable - * EnumerableMap.UintToAddressMap private myMap; - * } - * ``` - * - * The following map types are supported: - * - * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0 - * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 - * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an array of EnumerableMap. - * ==== - */ -library EnumerableMap { - using EnumerableSet for EnumerableSet.Bytes32Set; - - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Map type with - // bytes32 keys and values. - // The Map implementation uses private functions, and user-facing - // implementations (such as Uint256ToAddressMap) are just wrappers around - // the underlying Map. - // This means that we can only create new EnumerableMaps for types that fit - // in bytes32. - - struct Bytes32ToBytes32Map { - // Storage of keys - EnumerableSet.Bytes32Set _keys; - mapping(bytes32 => bytes32) _values; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - Bytes32ToBytes32Map storage map, - bytes32 key, - bytes32 value - ) internal returns (bool) { - map._values[key] = value; - return map._keys.add(key); - } - - /** - * @dev Removes a key-value pair from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { - delete map._values[key]; - return map._keys.remove(key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { - return map._keys.contains(key); - } - - /** - * @dev Returns the number of key-value pairs in the map. O(1). - */ - function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { - return map._keys.length(); - } - - /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). - * - * Note that there are no guarantees on the ordering of entries inside the - * array, and it may change when more entries are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { - bytes32 key = map._keys.at(index); - return (key, map._values[key]); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { - bytes32 value = map._values[key]; - if (value == bytes32(0)) { - return (contains(map, key), bytes32(0)); - } else { - return (true, value); - } - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { - bytes32 value = map._values[key]; - require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); - return value; - } - - /** - * @dev Same as {_get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {_tryGet}. - */ - function get( - Bytes32ToBytes32Map storage map, - bytes32 key, - string memory errorMessage - ) internal view returns (bytes32) { - bytes32 value = map._values[key]; - require(value != 0 || contains(map, key), errorMessage); - return value; - } - - // UintToUintMap - - struct UintToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - UintToUintMap storage map, - uint256 key, - uint256 value - ) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - UintToUintMap storage map, - uint256 key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key), errorMessage)); - } - - // UintToAddressMap - - struct UintToAddressMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - UintToAddressMap storage map, - uint256 key, - address value - ) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToAddressMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), address(uint160(uint256(value)))); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - * - * _Available since v3.4._ - */ - function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, address(uint160(uint256(value)))); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key))))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - UintToAddressMap storage map, - uint256 key, - string memory errorMessage - ) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); - } - - // AddressToUintMap - - struct AddressToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - AddressToUintMap storage map, - address key, - uint256 value - ) internal returns (bool) { - return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(AddressToUintMap storage map, address key) internal returns (bool) { - return remove(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(AddressToUintMap storage map, address key) internal view returns (bool) { - return contains(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(AddressToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (address(uint160(uint256(key))), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(AddressToUintMap storage map, address key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - AddressToUintMap storage map, - address key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); - } - - // Bytes32ToUintMap - - struct Bytes32ToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - Bytes32ToUintMap storage map, - bytes32 key, - uint256 value - ) internal returns (bool) { - return set(map._inner, key, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { - return remove(map._inner, key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { - return contains(map._inner, key); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(Bytes32ToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (key, uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, key); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { - return uint256(get(map._inner, key)); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - Bytes32ToUintMap storage map, - bytes32 key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, key, errorMessage)); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol deleted file mode 100644 index 1d8029e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol +++ /dev/null @@ -1,376 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. - -pragma solidity ^0.8.0; - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - bytes32[] memory store = _values(set._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol deleted file mode 100644 index 4e388f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol +++ /dev/null @@ -1,247 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) - -pragma solidity ^0.8.0; - -import "./IAccessControl.sol"; -import "../utils/Context.sol"; -import "../utils/Strings.sol"; -import "../utils/introspection/ERC165.sol"; - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ``` - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ``` - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address => bool) members; - bytes32 adminRole; - } - - mapping(bytes32 => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with a standardized message including the required role. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - * - * _Available since v4.1._ - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual override returns (bool) { - return _roles[role].members[account]; - } - - /** - * @dev Revert with a standard message if `_msgSender()` is missing `role`. - * Overriding this function changes the behavior of the {onlyRole} modifier. - * - * Format of the revert message is described in {_checkRole}. - * - * _Available since v4.6._ - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Revert with a standard message if `account` is missing `role`. - * - * The format of the revert reason is given by the following regular expression: - * - * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert( - string( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(account), - " is missing role ", - Strings.toHexString(uint256(role), 32) - ) - ) - ); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address account) public virtual override { - require(account == _msgSender(), "AccessControl: can only renounce roles for self"); - - _revokeRole(role, account); - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. Note that unlike {grantRole}, this function doesn't perform any - * checks on the calling account. - * - * May emit a {RoleGranted} event. - * - * [WARNING] - * ==== - * This function should only be called from the constructor when setting - * up the initial roles for the system. - * - * Using this function in any other way is effectively circumventing the admin - * system imposed by {AccessControl}. - * ==== - * - * NOTE: This function is deprecated in favor of {_grantRole}. - */ - function _setupRole(bytes32 role, address account) internal virtual { - _grantRole(role, account); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Grants `role` to `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual { - if (!hasRole(role, account)) { - _roles[role].members[account] = true; - emit RoleGranted(role, account, _msgSender()); - } - } - - /** - * @dev Revokes `role` from `account`. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual { - if (hasRole(role, account)) { - _roles[role].members[account] = false; - emit RoleRevoked(role, account, _msgSender()); - } - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol deleted file mode 100644 index efb82a3..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) - -pragma solidity ^0.8.0; - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - * - * _Available since v3.1._ - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `account`. - */ - function renounceRole(bytes32 role, address account) external; -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol deleted file mode 100644 index 91bb8f8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) - -pragma solidity ^0.8.0; - -import "../utils/introspection/IERC165.sol"; \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol deleted file mode 100644 index 7c95dfc..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC20.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) - -pragma solidity ^0.8.0; - -import "../token/ERC20/IERC20.sol"; \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol deleted file mode 100644 index 84ac72c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/draft-IERC20Permit.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** - * @dev Standard ERC20 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. - */ -interface IERC20Errors { - /** - * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param balance Current balance for the interacting account. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC20InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC20InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. - * @param spender Address that may be allowed to operate on tokens without being their owner. - * @param allowance Amount of tokens a `spender` is allowed to operate with. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC20InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `spender` to be approved. Used in approvals. - * @param spender Address that may be allowed to operate on tokens without being their owner. - */ - error ERC20InvalidSpender(address spender); -} - -/** - * @dev Standard ERC721 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. - */ -interface IERC721Errors { - /** - * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. - * Used in balance queries. - * @param owner Address of the current owner of a token. - */ - error ERC721InvalidOwner(address owner); - - /** - * @dev Indicates a `tokenId` whose `owner` is the zero address. - * @param tokenId Identifier number of a token. - */ - error ERC721NonexistentToken(uint256 tokenId); - - /** - * @dev Indicates an error related to the ownership over a particular token. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param tokenId Identifier number of a token. - * @param owner Address of the current owner of a token. - */ - error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC721InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC721InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `operator`’s approval. Used in transfers. - * @param operator Address that may be allowed to operate on tokens without being their owner. - * @param tokenId Identifier number of a token. - */ - error ERC721InsufficientApproval(address operator, uint256 tokenId); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC721InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `operator` to be approved. Used in approvals. - * @param operator Address that may be allowed to operate on tokens without being their owner. - */ - error ERC721InvalidOperator(address operator); -} - -/** - * @dev Standard ERC1155 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. - */ -interface IERC1155Errors { - /** - * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param balance Current balance for the interacting account. - * @param needed Minimum amount required to perform a transfer. - * @param tokenId Identifier number of a token. - */ - error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC1155InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC1155InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `operator`’s approval. Used in transfers. - * @param operator Address that may be allowed to operate on tokens without being their owner. - * @param owner Address of the current owner of a token. - */ - error ERC1155MissingApprovalForAll(address operator, address owner); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC1155InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `operator` to be approved. Used in approvals. - * @param operator Address that may be allowed to operate on tokens without being their owner. - */ - error ERC1155InvalidOperator(address operator); - - /** - * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. - * Used in batch transfers. - * @param idsLength Length of the array of token identifiers - * @param valuesLength Length of the array of token amounts - */ - error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol deleted file mode 100644 index 4db5eb2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -import "../token/ERC20/ERC20.sol"; - -// mock class using ERC20 -contract ERC20Mock is ERC20 { - constructor( - string memory name, - string memory symbol, - address initialAccount, - uint256 initialBalance - ) payable ERC20(name, symbol) { - _mint(initialAccount, initialBalance); - } - - function mint(address account, uint256 amount) public { - _mint(account, amount); - } - - function burn(address account, uint256 amount) public { - _burn(account, amount); - } - - function transferInternal( - address from, - address to, - uint256 value - ) public { - _transfer(from, to, value); - } - - function approveInternal( - address owner, - address spender, - uint256 value - ) public { - _approve(owner, spender, value); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol deleted file mode 100644 index 8cc49ec..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/security/Pausable.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) - -pragma solidity ^0.8.0; - -import "../utils/Context.sol"; - -/** - * @dev Contract module which allows children to implement an emergency stop - * mechanism that can be triggered by an authorized account. - * - * This module is used through inheritance. It will make available the - * modifiers `whenNotPaused` and `whenPaused`, which can be applied to - * the functions of your contract. Note that they will not be pausable by - * simply including this module, only once the modifiers are put in place. - */ -abstract contract Pausable is Context { - /** - * @dev Emitted when the pause is triggered by `account`. - */ - event Paused(address account); - - /** - * @dev Emitted when the pause is lifted by `account`. - */ - event Unpaused(address account); - - bool private _paused; - - /** - * @dev Initializes the contract in unpaused state. - */ - constructor() { - _paused = false; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - _requireNotPaused(); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - * - * Requirements: - * - * - The contract must be paused. - */ - modifier whenPaused() { - _requirePaused(); - _; - } - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() public view virtual returns (bool) { - return _paused; - } - - /** - * @dev Throws if the contract is paused. - */ - function _requireNotPaused() internal view virtual { - require(!paused(), "Pausable: paused"); - } - - /** - * @dev Throws if the contract is not paused. - */ - function _requirePaused() internal view virtual { - require(paused(), "Pausable: not paused"); - } - - /** - * @dev Triggers stopped state. - * - * Requirements: - * - * - The contract must not be paused. - */ - function _pause() internal virtual whenNotPaused { - _paused = true; - emit Paused(_msgSender()); - } - - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _unpause() internal virtual whenPaused { - _paused = false; - emit Unpaused(_msgSender()); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol deleted file mode 100644 index 0e9b077..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol) - -pragma solidity ^0.8.0; - -import "./IERC20.sol"; -import "./extensions/IERC20Metadata.sol"; -import "../../utils/Context.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * For a generic mechanism see {ERC20PresetMinterPauser}. - * - * TIP: For a detailed writeup see our guide - * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -contract ERC20 is Context, IERC20, IERC20Metadata { - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * The default value of {decimals} is 18. To select a different value for - * {decimals} you should overload it. - * - * All two of these values are immutable: they can only be set once during - * construction. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view virtual override returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view virtual override returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5.05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the value {ERC20} uses, unless this function is - * overridden; - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view virtual override returns (uint8) { - return 18; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual override returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public view virtual override returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - the caller must have a balance of at least `amount`. - */ - function transfer(address to, uint256 amount) public virtual override returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, amount); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) public view virtual override returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 amount) public virtual override returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, amount); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - * - the caller must have allowance for ``from``'s tokens of at least - * `amount`. - */ - function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { - address spender = _msgSender(); - _spendAllowance(from, spender, amount); - _transfer(from, to, amount); - return true; - } - - /** - * @dev Atomically increases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, allowance(owner, spender) + addedValue); - return true; - } - - /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least - * `subtractedValue`. - */ - function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { - address owner = _msgSender(); - uint256 currentAllowance = allowance(owner, spender); - require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); - unchecked { - _approve(owner, spender, currentAllowance - subtractedValue); - } - - return true; - } - - /** - * @dev Moves `amount` of tokens from `from` to `to`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - */ - function _transfer(address from, address to, uint256 amount) internal virtual { - require(from != address(0), "ERC20: transfer from the zero address"); - require(to != address(0), "ERC20: transfer to the zero address"); - - _beforeTokenTransfer(from, to, amount); - - uint256 fromBalance = _balances[from]; - require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); - unchecked { - _balances[from] = fromBalance - amount; - // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by - // decrementing then incrementing. - _balances[to] += amount; - } - - emit Transfer(from, to, amount); - - _afterTokenTransfer(from, to, amount); - } - - /** @dev Creates `amount` tokens and assigns them to `account`, increasing - * the total supply. - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function _mint(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: mint to the zero address"); - - _beforeTokenTransfer(address(0), account, amount); - - _totalSupply += amount; - unchecked { - // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. - _balances[account] += amount; - } - emit Transfer(address(0), account, amount); - - _afterTokenTransfer(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, reducing the - * total supply. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * Requirements: - * - * - `account` cannot be the zero address. - * - `account` must have at least `amount` tokens. - */ - function _burn(address account, uint256 amount) internal virtual { - require(account != address(0), "ERC20: burn from the zero address"); - - _beforeTokenTransfer(account, address(0), amount); - - uint256 accountBalance = _balances[account]; - require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); - unchecked { - _balances[account] = accountBalance - amount; - // Overflow not possible: amount <= accountBalance <= totalSupply. - _totalSupply -= amount; - } - - emit Transfer(account, address(0), amount); - - _afterTokenTransfer(account, address(0), amount); - } - - /** - * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - */ - function _approve(address owner, address spender, uint256 amount) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `amount`. - * - * Does not update the allowance amount in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Might emit an {Approval} event. - */ - function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - require(currentAllowance >= amount, "ERC20: insufficient allowance"); - unchecked { - _approve(owner, spender, currentAllowance - amount); - } - } - } - - /** - * @dev Hook that is called before any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * will be transferred to `to`. - * - when `from` is zero, `amount` tokens will be minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} - - /** - * @dev Hook that is called after any transfer of tokens. This includes - * minting and burning. - * - * Calling conditions: - * - * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens - * has been transferred to `to`. - * - when `from` is zero, `amount` tokens have been minted for `to`. - * - when `to` is zero, `amount` of ``from``'s tokens have been burned. - * - `from` and `to` are never both zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol deleted file mode 100644 index 536ba0b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `from` to `to` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address from, address to, uint256 amount) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol deleted file mode 100644 index e775272..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol) - -pragma solidity ^0.8.0; - -import "../ERC20.sol"; -import "../../../utils/Context.sol"; - -/** - * @dev Extension of {ERC20} that allows token holders to destroy both their own - * tokens and those that they have an allowance for, in a way that can be - * recognized off-chain (via event analysis). - */ -abstract contract ERC20Burnable is Context, ERC20 { - /** - * @dev Destroys `amount` tokens from the caller. - * - * See {ERC20-_burn}. - */ - function burn(uint256 amount) public virtual { - _burn(_msgSender(), amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, deducting from the caller's - * allowance. - * - * See {ERC20-_burn} and {ERC20-allowance}. - * - * Requirements: - * - * - the caller must have allowance for ``accounts``'s tokens of at least - * `amount`. - */ - function burnFrom(address account, uint256 amount) public virtual { - _spendAllowance(account, _msgSender(), amount); - _burn(account, amount); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol deleted file mode 100644 index 6e29892..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) - -pragma solidity ^0.8.0; - -import "../IERC20.sol"; - -/** - * @dev Interface for the optional metadata functions from the ERC20 standard. - * - * _Available since v4.1._ - */ -interface IERC20Metadata is IERC20 { - /** - * @dev Returns the name of the token. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the symbol of the token. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the decimals places of the token. - */ - function decimals() external view returns (uint8); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol deleted file mode 100644 index 3c29ed0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20Permit.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol) - -pragma solidity ^0.8.0; - -import "./draft-IERC20Permit.sol"; -import "../ERC20.sol"; -import "../../../utils/cryptography/ECDSA.sol"; -import "../../../utils/cryptography/EIP712.sol"; -import "../../../utils/Counters.sol"; - -/** - * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - * - * _Available since v3.4._ - */ -abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { - using Counters for Counters.Counter; - - mapping(address => Counters.Counter) private _nonces; - - // solhint-disable-next-line var-name-mixedcase - bytes32 private constant _PERMIT_TYPEHASH = - keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - /** - * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. - * However, to ensure consistency with the upgradeable transpiler, we will continue - * to reserve a slot. - * @custom:oz-renamed-from _PERMIT_TYPEHASH - */ - // solhint-disable-next-line var-name-mixedcase - bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; - - /** - * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. - * - * It's a good idea to use the same `name` that is defined as the ERC20 token name. - */ - constructor(string memory name) EIP712(name, "1") {} - - /** - * @dev See {IERC20Permit-permit}. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) public virtual override { - require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); - - bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); - - bytes32 hash = _hashTypedDataV4(structHash); - - address signer = ECDSA.recover(hash, v, r, s); - require(signer == owner, "ERC20Permit: invalid signature"); - - _approve(owner, spender, value); - } - - /** - * @dev See {IERC20Permit-nonces}. - */ - function nonces(address owner) public view virtual override returns (uint256) { - return _nonces[owner].current(); - } - - /** - * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view override returns (bytes32) { - return _domainSeparatorV4(); - } - - /** - * @dev "Consume a nonce": return the current value and increment. - * - * _Available since v4.1._ - */ - function _useNonce(address owner) internal virtual returns (uint256 current) { - Counters.Counter storage nonce = _nonces[owner]; - current = nonce.current(); - nonce.increment(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol deleted file mode 100644 index b14bbfe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/draft-IERC20Permit.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol deleted file mode 100644 index 2a6939e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) - -pragma solidity ^0.8.0; - -import "../IERC20.sol"; -import "../extensions/draft-IERC20Permit.sol"; -import "../../../utils/Address.sol"; - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - function safeTransfer(IERC20 token, address to, uint256 value) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); - } - - function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { - _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); - } - - /** - * @dev Deprecated. This function has issues similar to the ones found in - * {IERC20-approve}, and its usage is discouraged. - * - * Whenever possible, use {safeIncreaseAllowance} and - * {safeDecreaseAllowance} instead. - */ - function safeApprove(IERC20 token, address spender, uint256 value) internal { - // safeApprove should only be called when setting an initial allowance, - // or when resetting it to zero. To increase and decrease it, use - // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' - require( - (value == 0) || (token.allowance(address(this), spender) == 0), - "SafeERC20: approve from non-zero to non-zero allowance" - ); - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); - } - - function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { - uint256 newAllowance = token.allowance(address(this), spender) + value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - - function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { - unchecked { - uint256 oldAllowance = token.allowance(address(this), spender); - require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); - uint256 newAllowance = oldAllowance - value; - _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); - } - } - - function safePermit( - IERC20Permit token, - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - uint256 nonceBefore = token.nonces(owner); - token.permit(owner, spender, value, deadline, v, r, s); - uint256 nonceAfter = token.nonces(owner); - require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); - if (returndata.length > 0) { - // Return data is optional - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol deleted file mode 100644 index d966c06..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) - -pragma solidity ^0.8.1; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - * - * [IMPORTANT] - * ==== - * You shouldn't rely on `isContract` to protect against flash loan attacks! - * - * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets - * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract - * constructor. - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize/address.code.length, which returns 0 - // for contracts in construction, since the code is only stored at the end - // of the constructor execution. - - return account.code.length > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata, errorMessage); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling - * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. - * - * _Available since v4.8._ - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata, - string memory errorMessage - ) internal view returns (bytes memory) { - if (success) { - if (returndata.length == 0) { - // only check isContract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - require(isContract(target), "Address: call to non-contract"); - } - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - /** - * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the - * revert reason or using the provided one. - * - * _Available since v4.3._ - */ - function verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) internal pure returns (bytes memory) { - if (success) { - return returndata; - } else { - _revert(returndata, errorMessage); - } - } - - function _revert(bytes memory returndata, string memory errorMessage) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol deleted file mode 100644 index 357980f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Context.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/Context.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol deleted file mode 100644 index ea330e9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Counters.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) - -pragma solidity ^0.8.0; - -/** - * @title Counters - * @author Matt Condon (@shrugs) - * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number - * of elements in a mapping, issuing ERC721 ids, or counting request ids. - * - * Include with `using Counters for Counters.Counter;` - */ -library Counters { - struct Counter { - // This variable should never be directly accessed by users of the library: interactions must be restricted to - // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add - // this feature: see https://github.com/ethereum/solidity/issues/4637 - uint256 _value; // default: 0 - } - - function current(Counter storage counter) internal view returns (uint256) { - return counter._value; - } - - function increment(Counter storage counter) internal { - unchecked { - counter._value += 1; - } - } - - function decrement(Counter storage counter) internal { - uint256 value = counter._value; - require(value > 0, "Counter: decrement overflow"); - unchecked { - counter._value = value - 1; - } - } - - function reset(Counter storage counter) internal { - counter._value = 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol deleted file mode 100644 index 7e91bc6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/StorageSlot.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Library for reading and writing primitive types to specific storage slots. - * - * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. - * This library helps with reading and writing to such slots without the need for inline assembly. - * - * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. - * - * Example usage to set ERC1967 implementation slot: - * ``` - * contract ERC1967 { - * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - * - * function _getImplementation() internal view returns (address) { - * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - * } - * - * function _setImplementation(address newImplementation) internal { - * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); - * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - * } - * } - * ``` - * - * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ - */ -library StorageSlot { - struct AddressSlot { - address value; - } - - struct BooleanSlot { - bool value; - } - - struct Bytes32Slot { - bytes32 value; - } - - struct Uint256Slot { - uint256 value; - } - - /** - * @dev Returns an `AddressSlot` with member `value` located at `slot`. - */ - function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `BooleanSlot` with member `value` located at `slot`. - */ - function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. - */ - function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Uint256Slot` with member `value` located at `slot`. - */ - function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol deleted file mode 100644 index 377ba46..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) - -pragma solidity ^0.8.0; - -import "./math/Math.sol"; - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant _SYMBOLS = "0123456789abcdef"; - uint8 private constant _ADDRESS_LENGTH = 20; - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - unchecked { - uint256 length = Math.log10(value) + 1; - string memory buffer = new string(length); - uint256 ptr; - /// @solidity memory-safe-assembly - assembly { - ptr := add(buffer, add(32, length)) - } - while (true) { - ptr--; - /// @solidity memory-safe-assembly - assembly { - mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) - } - value /= 10; - if (value == 0) break; - } - return buffer; - } - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - unchecked { - return toHexString(value, Math.log256(value) + 1); - } - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = _SYMBOLS[value & 0xf]; - value >>= 4; - } - require(value == 0, "Strings: hex length insufficient"); - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol deleted file mode 100644 index 65d4b81..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/ECDSA.sol +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) - -pragma solidity ^0.8.0; - -import "../Strings.sol"; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - enum RecoverError { - NoError, - InvalidSignature, - InvalidSignatureLength, - InvalidSignatureS, - InvalidSignatureV // Deprecated in v4.8 - } - - function _throwError(RecoverError error) private pure { - if (error == RecoverError.NoError) { - return; // no error: do nothing - } else if (error == RecoverError.InvalidSignature) { - revert("ECDSA: invalid signature"); - } else if (error == RecoverError.InvalidSignatureLength) { - revert("ECDSA: invalid signature length"); - } else if (error == RecoverError.InvalidSignatureS) { - revert("ECDSA: invalid signature 's' value"); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature` or error string. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - * - * Documentation for signature generation: - * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] - * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] - * - * _Available since v4.3._ - */ - function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { - if (signature.length == 65) { - bytes32 r; - bytes32 s; - uint8 v; - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - /// @solidity memory-safe-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - return tryRecover(hash, v, r, s); - } else { - return (address(0), RecoverError.InvalidSignatureLength); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {toEthSignedMessageHash} on it. - */ - function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, signature); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. - * - * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] - * - * _Available since v4.3._ - */ - function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { - bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - uint8 v = uint8((uint256(vs) >> 255) + 27); - return tryRecover(hash, v, r, s); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. - * - * _Available since v4.2._ - */ - function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, r, vs); - _throwError(error); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `v`, - * `r` and `s` signature fields separately. - * - * _Available since v4.3._ - */ - function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { - return (address(0), RecoverError.InvalidSignatureS); - } - - // If the signature is valid (and not malleable), return the signer address - address signer = ecrecover(hash, v, r, s); - if (signer == address(0)) { - return (address(0), RecoverError.InvalidSignature); - } - - return (signer, RecoverError.NoError); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `v`, - * `r` and `s` signature fields separately. - */ - function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { - (address recovered, RecoverError error) = tryRecover(hash, v, r, s); - _throwError(error); - return recovered; - } - - /** - * @dev Returns an Ethereum Signed Message, created from a `hash`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { - // 32 is the length in bytes of hash, - // enforced by the type signature above - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - } - - /** - * @dev Returns an Ethereum Signed Message, created from `s`. This - * produces hash corresponding to the one signed with the - * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] - * JSON-RPC method as part of EIP-191. - * - * See {recover}. - */ - function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); - } - - /** - * @dev Returns an Ethereum Signed Typed Data, created from a - * `domainSeparator` and a `structHash`. This produces hash corresponding - * to the one signed with the - * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] - * JSON-RPC method as part of EIP-712. - * - * See {recover}. - */ - function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol deleted file mode 100644 index 6924570..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/cryptography/EIP712.sol +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol) - -pragma solidity ^0.8.0; - -import "./ECDSA.sol"; - -/** - * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. - * - * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, - * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding - * they need in their contracts using a combination of `abi.encode` and `keccak256`. - * - * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding - * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA - * ({_hashTypedDataV4}). - * - * The implementation of the domain separator was designed to be as efficient as possible while still properly updating - * the chain id to protect against replay attacks on an eventual fork of the chain. - * - * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method - * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. - * - * _Available since v3.4._ - */ -abstract contract EIP712 { - /* solhint-disable var-name-mixedcase */ - // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to - // invalidate the cached domain separator if the chain id changes. - bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; - uint256 private immutable _CACHED_CHAIN_ID; - address private immutable _CACHED_THIS; - - bytes32 private immutable _HASHED_NAME; - bytes32 private immutable _HASHED_VERSION; - bytes32 private immutable _TYPE_HASH; - - /* solhint-enable var-name-mixedcase */ - - /** - * @dev Initializes the domain separator and parameter caches. - * - * The meaning of `name` and `version` is specified in - * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: - * - * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. - * - `version`: the current major version of the signing domain. - * - * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart - * contract upgrade]. - */ - constructor(string memory name, string memory version) { - bytes32 hashedName = keccak256(bytes(name)); - bytes32 hashedVersion = keccak256(bytes(version)); - bytes32 typeHash = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); - _HASHED_NAME = hashedName; - _HASHED_VERSION = hashedVersion; - _CACHED_CHAIN_ID = block.chainid; - _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); - _CACHED_THIS = address(this); - _TYPE_HASH = typeHash; - } - - /** - * @dev Returns the domain separator for the current chain. - */ - function _domainSeparatorV4() internal view returns (bytes32) { - if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { - return _CACHED_DOMAIN_SEPARATOR; - } else { - return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); - } - } - - function _buildDomainSeparator( - bytes32 typeHash, - bytes32 nameHash, - bytes32 versionHash - ) private view returns (bytes32) { - return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); - } - - /** - * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this - * function returns the hash of the fully encoded EIP712 message for this domain. - * - * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: - * - * ```solidity - * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( - * keccak256("Mail(address to,string contents)"), - * mailTo, - * keccak256(bytes(mailContents)) - * ))); - * address signer = ECDSA.recover(digest, signature); - * ``` - */ - function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { - return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol deleted file mode 100644 index c682b07..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) - -pragma solidity ^0.8.0; - -import "./IERC165.sol"; - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - * - * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol deleted file mode 100644 index 4daefc5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.2) (utils/introspection/ERC165Checker.sol) - -pragma solidity ^0.8.0; - -import "./IERC165.sol"; - -/** - * @dev Library used to query support of an interface declared via {IERC165}. - * - * Note that these functions return the actual result of the query: they do not - * `revert` if an interface is not supported. It is up to the caller to decide - * what to do in these cases. - */ -library ERC165Checker { - // As per the EIP-165 spec, no interface should ever match 0xffffffff - bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; - - /** - * @dev Returns true if `account` supports the {IERC165} interface. - */ - function supportsERC165(address account) internal view returns (bool) { - // Any contract that implements ERC165 must explicitly indicate support of - // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return - supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && - !supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID); - } - - /** - * @dev Returns true if `account` supports the interface defined by - * `interfaceId`. Support for {IERC165} itself is queried automatically. - * - * See {IERC165-supportsInterface}. - */ - function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { - // query support of both ERC165 as per the spec and support of _interfaceId - return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); - } - - /** - * @dev Returns a boolean array where each value corresponds to the - * interfaces passed in and whether they're supported or not. This allows - * you to batch check interfaces for a contract where your expectation - * is that some interfaces may not be supported. - * - * See {IERC165-supportsInterface}. - * - * _Available since v3.4._ - */ - function getSupportedInterfaces(address account, bytes4[] memory interfaceIds) - internal - view - returns (bool[] memory) - { - // an array of booleans corresponding to interfaceIds and whether they're supported or not - bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); - - // query support of ERC165 itself - if (supportsERC165(account)) { - // query support of each interface in interfaceIds - for (uint256 i = 0; i < interfaceIds.length; i++) { - interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); - } - } - - return interfaceIdsSupported; - } - - /** - * @dev Returns true if `account` supports all the interfaces defined in - * `interfaceIds`. Support for {IERC165} itself is queried automatically. - * - * Batch-querying can lead to gas savings by skipping repeated checks for - * {IERC165} support. - * - * See {IERC165-supportsInterface}. - */ - function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { - // query support of ERC165 itself - if (!supportsERC165(account)) { - return false; - } - - // query support of each interface in interfaceIds - for (uint256 i = 0; i < interfaceIds.length; i++) { - if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { - return false; - } - } - - // all interfaces supported - return true; - } - - /** - * @notice Query if a contract implements an interface, does not check ERC165 support - * @param account The address of the contract to query for support of an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @return true if the contract at account indicates support of the interface with - * identifier interfaceId, false otherwise - * @dev Assumes that account contains a contract that supports ERC165, otherwise - * the behavior of this method is undefined. This precondition can be checked - * with {supportsERC165}. - * - * Some precompiled contracts will falsely indicate support for a given interface, so caution - * should be exercised when using this function. - * - * Interface identification is specified in ERC-165. - */ - function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { - // prepare call - bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); - - // perform static call - bool success; - uint256 returnSize; - uint256 returnValue; - assembly { - success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) - returnSize := returndatasize() - returnValue := mload(0x00) - } - - return success && returnSize >= 0x20 && returnValue > 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol deleted file mode 100644 index 5fa6551..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol deleted file mode 100644 index 7a79329..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/Math.sol +++ /dev/null @@ -1,336 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Standard math utilities missing in the Solidity language. - */ -library Math { - enum Rounding { - Down, // Toward negative infinity - Up, // Toward infinity - Zero // Toward zero - } - - /** - * @dev Returns the largest of two numbers. - */ - function max(uint256 a, uint256 b) internal pure returns (uint256) { - return a > b ? a : b; - } - - /** - * @dev Returns the smallest of two numbers. - */ - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } - - /** - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow. - return (a & b) + (a ^ b) / 2; - } - - /** - * @dev Returns the ceiling of the division of two numbers. - * - * This differs from standard division with `/` in that it rounds up instead - * of rounding down. - */ - function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b - 1) / b can overflow on addition, so we distribute. - return a == 0 ? 0 : (a - 1) / b + 1; - } - - /** - * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 - * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) - * with further edits by Uniswap Labs also under MIT license. - */ - function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { - unchecked { - // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use - // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 - // variables such that product = prod1 * 2^256 + prod0. - uint256 prod0; // Least significant 256 bits of the product - uint256 prod1; // Most significant 256 bits of the product - assembly { - let mm := mulmod(x, y, not(0)) - prod0 := mul(x, y) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } - - // Handle non-overflow cases, 256 by 256 division. - if (prod1 == 0) { - return prod0 / denominator; - } - - // Make sure the result is less than 2^256. Also prevents denominator == 0. - require(denominator > prod1); - - /////////////////////////////////////////////// - // 512 by 256 division. - /////////////////////////////////////////////// - - // Make division exact by subtracting the remainder from [prod1 prod0]. - uint256 remainder; - assembly { - // Compute remainder using mulmod. - remainder := mulmod(x, y, denominator) - - // Subtract 256 bit number from 512 bit number. - prod1 := sub(prod1, gt(remainder, prod0)) - prod0 := sub(prod0, remainder) - } - - // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. - // See https://cs.stackexchange.com/q/138556/92363. - - // Does not overflow because the denominator cannot be zero at this stage in the function. - uint256 twos = denominator & (~denominator + 1); - assembly { - // Divide denominator by twos. - denominator := div(denominator, twos) - - // Divide [prod1 prod0] by twos. - prod0 := div(prod0, twos) - - // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. - twos := add(div(sub(0, twos), twos), 1) - } - - // Shift in bits from prod1 into prod0. - prod0 |= prod1 * twos; - - // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such - // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for - // four bits. That is, denominator * inv = 1 mod 2^4. - uint256 inverse = (3 * denominator) ^ 2; - - // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works - // in modular arithmetic, doubling the correct bits in each step. - inverse *= 2 - denominator * inverse; // inverse mod 2^8 - inverse *= 2 - denominator * inverse; // inverse mod 2^16 - inverse *= 2 - denominator * inverse; // inverse mod 2^32 - inverse *= 2 - denominator * inverse; // inverse mod 2^64 - inverse *= 2 - denominator * inverse; // inverse mod 2^128 - inverse *= 2 - denominator * inverse; // inverse mod 2^256 - - // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. - // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is - // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 - // is no longer required. - result = prod0 * inverse; - return result; - } - } - - /** - * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. - */ - function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { - uint256 result = mulDiv(x, y, denominator); - if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { - result += 1; - } - return result; - } - - /** - * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. - * - * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). - */ - function sqrt(uint256 a) internal pure returns (uint256) { - if (a == 0) { - return 0; - } - - // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. - // - // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have - // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. - // - // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` - // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` - // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` - // - // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. - uint256 result = 1 << (log2(a) >> 1); - - // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, - // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at - // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision - // into the expected uint128 result. - unchecked { - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - return min(result, a / result); - } - } - - /** - * @notice Calculates sqrt(a), following the selected rounding direction. - */ - function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = sqrt(a); - return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); - } - } - - /** - * @dev Return the log in base 2, rounded down, of a positive value. - * Returns 0 if given 0. - */ - function log2(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 128; - } - if (value >> 64 > 0) { - value >>= 64; - result += 64; - } - if (value >> 32 > 0) { - value >>= 32; - result += 32; - } - if (value >> 16 > 0) { - value >>= 16; - result += 16; - } - if (value >> 8 > 0) { - value >>= 8; - result += 8; - } - if (value >> 4 > 0) { - value >>= 4; - result += 4; - } - if (value >> 2 > 0) { - value >>= 2; - result += 2; - } - if (value >> 1 > 0) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 2, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log2(value); - return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); - } - } - - /** - * @dev Return the log in base 10, rounded down, of a positive value. - * Returns 0 if given 0. - */ - function log10(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >= 10 ** 64) { - value /= 10 ** 64; - result += 64; - } - if (value >= 10 ** 32) { - value /= 10 ** 32; - result += 32; - } - if (value >= 10 ** 16) { - value /= 10 ** 16; - result += 16; - } - if (value >= 10 ** 8) { - value /= 10 ** 8; - result += 8; - } - if (value >= 10 ** 4) { - value /= 10 ** 4; - result += 4; - } - if (value >= 10 ** 2) { - value /= 10 ** 2; - result += 2; - } - if (value >= 10 ** 1) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 10, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log10(value); - return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); - } - } - - /** - * @dev Return the log in base 256, rounded down, of a positive value. - * Returns 0 if given 0. - * - * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. - */ - function log256(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 16; - } - if (value >> 64 > 0) { - value >>= 64; - result += 8; - } - if (value >> 32 > 0) { - value >>= 32; - result += 4; - } - if (value >> 16 > 0) { - value >>= 16; - result += 2; - } - if (value >> 8 > 0) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 10, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log256(value); - return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol deleted file mode 100644 index 28c1111..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol +++ /dev/null @@ -1,1136 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) -// This file was procedurally generated from scripts/generate/templates/SafeCast.js. - -pragma solidity ^0.8.0; - -/** - * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow - * checks. - * - * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can - * easily result in undesired exploitation or bugs, since developers usually - * assume that overflows raise errors. `SafeCast` restores this intuition by - * reverting the transaction when such an operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - * - * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing - * all math on `uint256` and `int256` and then downcasting. - */ -library SafeCast { - /** - * @dev Returns the downcasted uint248 from uint256, reverting on - * overflow (when the input is greater than largest uint248). - * - * Counterpart to Solidity's `uint248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - * - * _Available since v4.7._ - */ - function toUint248(uint256 value) internal pure returns (uint248) { - require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); - return uint248(value); - } - - /** - * @dev Returns the downcasted uint240 from uint256, reverting on - * overflow (when the input is greater than largest uint240). - * - * Counterpart to Solidity's `uint240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - * - * _Available since v4.7._ - */ - function toUint240(uint256 value) internal pure returns (uint240) { - require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); - return uint240(value); - } - - /** - * @dev Returns the downcasted uint232 from uint256, reverting on - * overflow (when the input is greater than largest uint232). - * - * Counterpart to Solidity's `uint232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - * - * _Available since v4.7._ - */ - function toUint232(uint256 value) internal pure returns (uint232) { - require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); - return uint232(value); - } - - /** - * @dev Returns the downcasted uint224 from uint256, reverting on - * overflow (when the input is greater than largest uint224). - * - * Counterpart to Solidity's `uint224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - * - * _Available since v4.2._ - */ - function toUint224(uint256 value) internal pure returns (uint224) { - require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); - return uint224(value); - } - - /** - * @dev Returns the downcasted uint216 from uint256, reverting on - * overflow (when the input is greater than largest uint216). - * - * Counterpart to Solidity's `uint216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - * - * _Available since v4.7._ - */ - function toUint216(uint256 value) internal pure returns (uint216) { - require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); - return uint216(value); - } - - /** - * @dev Returns the downcasted uint208 from uint256, reverting on - * overflow (when the input is greater than largest uint208). - * - * Counterpart to Solidity's `uint208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - * - * _Available since v4.7._ - */ - function toUint208(uint256 value) internal pure returns (uint208) { - require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); - return uint208(value); - } - - /** - * @dev Returns the downcasted uint200 from uint256, reverting on - * overflow (when the input is greater than largest uint200). - * - * Counterpart to Solidity's `uint200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - * - * _Available since v4.7._ - */ - function toUint200(uint256 value) internal pure returns (uint200) { - require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); - return uint200(value); - } - - /** - * @dev Returns the downcasted uint192 from uint256, reverting on - * overflow (when the input is greater than largest uint192). - * - * Counterpart to Solidity's `uint192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - * - * _Available since v4.7._ - */ - function toUint192(uint256 value) internal pure returns (uint192) { - require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); - return uint192(value); - } - - /** - * @dev Returns the downcasted uint184 from uint256, reverting on - * overflow (when the input is greater than largest uint184). - * - * Counterpart to Solidity's `uint184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - * - * _Available since v4.7._ - */ - function toUint184(uint256 value) internal pure returns (uint184) { - require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); - return uint184(value); - } - - /** - * @dev Returns the downcasted uint176 from uint256, reverting on - * overflow (when the input is greater than largest uint176). - * - * Counterpart to Solidity's `uint176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - * - * _Available since v4.7._ - */ - function toUint176(uint256 value) internal pure returns (uint176) { - require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); - return uint176(value); - } - - /** - * @dev Returns the downcasted uint168 from uint256, reverting on - * overflow (when the input is greater than largest uint168). - * - * Counterpart to Solidity's `uint168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - * - * _Available since v4.7._ - */ - function toUint168(uint256 value) internal pure returns (uint168) { - require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); - return uint168(value); - } - - /** - * @dev Returns the downcasted uint160 from uint256, reverting on - * overflow (when the input is greater than largest uint160). - * - * Counterpart to Solidity's `uint160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - * - * _Available since v4.7._ - */ - function toUint160(uint256 value) internal pure returns (uint160) { - require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); - return uint160(value); - } - - /** - * @dev Returns the downcasted uint152 from uint256, reverting on - * overflow (when the input is greater than largest uint152). - * - * Counterpart to Solidity's `uint152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - * - * _Available since v4.7._ - */ - function toUint152(uint256 value) internal pure returns (uint152) { - require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); - return uint152(value); - } - - /** - * @dev Returns the downcasted uint144 from uint256, reverting on - * overflow (when the input is greater than largest uint144). - * - * Counterpart to Solidity's `uint144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - * - * _Available since v4.7._ - */ - function toUint144(uint256 value) internal pure returns (uint144) { - require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); - return uint144(value); - } - - /** - * @dev Returns the downcasted uint136 from uint256, reverting on - * overflow (when the input is greater than largest uint136). - * - * Counterpart to Solidity's `uint136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - * - * _Available since v4.7._ - */ - function toUint136(uint256 value) internal pure returns (uint136) { - require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); - return uint136(value); - } - - /** - * @dev Returns the downcasted uint128 from uint256, reverting on - * overflow (when the input is greater than largest uint128). - * - * Counterpart to Solidity's `uint128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - * - * _Available since v2.5._ - */ - function toUint128(uint256 value) internal pure returns (uint128) { - require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); - return uint128(value); - } - - /** - * @dev Returns the downcasted uint120 from uint256, reverting on - * overflow (when the input is greater than largest uint120). - * - * Counterpart to Solidity's `uint120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - * - * _Available since v4.7._ - */ - function toUint120(uint256 value) internal pure returns (uint120) { - require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); - return uint120(value); - } - - /** - * @dev Returns the downcasted uint112 from uint256, reverting on - * overflow (when the input is greater than largest uint112). - * - * Counterpart to Solidity's `uint112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - * - * _Available since v4.7._ - */ - function toUint112(uint256 value) internal pure returns (uint112) { - require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); - return uint112(value); - } - - /** - * @dev Returns the downcasted uint104 from uint256, reverting on - * overflow (when the input is greater than largest uint104). - * - * Counterpart to Solidity's `uint104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - * - * _Available since v4.7._ - */ - function toUint104(uint256 value) internal pure returns (uint104) { - require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); - return uint104(value); - } - - /** - * @dev Returns the downcasted uint96 from uint256, reverting on - * overflow (when the input is greater than largest uint96). - * - * Counterpart to Solidity's `uint96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - * - * _Available since v4.2._ - */ - function toUint96(uint256 value) internal pure returns (uint96) { - require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); - return uint96(value); - } - - /** - * @dev Returns the downcasted uint88 from uint256, reverting on - * overflow (when the input is greater than largest uint88). - * - * Counterpart to Solidity's `uint88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - * - * _Available since v4.7._ - */ - function toUint88(uint256 value) internal pure returns (uint88) { - require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); - return uint88(value); - } - - /** - * @dev Returns the downcasted uint80 from uint256, reverting on - * overflow (when the input is greater than largest uint80). - * - * Counterpart to Solidity's `uint80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - * - * _Available since v4.7._ - */ - function toUint80(uint256 value) internal pure returns (uint80) { - require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); - return uint80(value); - } - - /** - * @dev Returns the downcasted uint72 from uint256, reverting on - * overflow (when the input is greater than largest uint72). - * - * Counterpart to Solidity's `uint72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - * - * _Available since v4.7._ - */ - function toUint72(uint256 value) internal pure returns (uint72) { - require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); - return uint72(value); - } - - /** - * @dev Returns the downcasted uint64 from uint256, reverting on - * overflow (when the input is greater than largest uint64). - * - * Counterpart to Solidity's `uint64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - * - * _Available since v2.5._ - */ - function toUint64(uint256 value) internal pure returns (uint64) { - require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); - return uint64(value); - } - - /** - * @dev Returns the downcasted uint56 from uint256, reverting on - * overflow (when the input is greater than largest uint56). - * - * Counterpart to Solidity's `uint56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - * - * _Available since v4.7._ - */ - function toUint56(uint256 value) internal pure returns (uint56) { - require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); - return uint56(value); - } - - /** - * @dev Returns the downcasted uint48 from uint256, reverting on - * overflow (when the input is greater than largest uint48). - * - * Counterpart to Solidity's `uint48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - * - * _Available since v4.7._ - */ - function toUint48(uint256 value) internal pure returns (uint48) { - require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); - return uint48(value); - } - - /** - * @dev Returns the downcasted uint40 from uint256, reverting on - * overflow (when the input is greater than largest uint40). - * - * Counterpart to Solidity's `uint40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - * - * _Available since v4.7._ - */ - function toUint40(uint256 value) internal pure returns (uint40) { - require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); - return uint40(value); - } - - /** - * @dev Returns the downcasted uint32 from uint256, reverting on - * overflow (when the input is greater than largest uint32). - * - * Counterpart to Solidity's `uint32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - * - * _Available since v2.5._ - */ - function toUint32(uint256 value) internal pure returns (uint32) { - require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); - return uint32(value); - } - - /** - * @dev Returns the downcasted uint24 from uint256, reverting on - * overflow (when the input is greater than largest uint24). - * - * Counterpart to Solidity's `uint24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - * - * _Available since v4.7._ - */ - function toUint24(uint256 value) internal pure returns (uint24) { - require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); - return uint24(value); - } - - /** - * @dev Returns the downcasted uint16 from uint256, reverting on - * overflow (when the input is greater than largest uint16). - * - * Counterpart to Solidity's `uint16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - * - * _Available since v2.5._ - */ - function toUint16(uint256 value) internal pure returns (uint16) { - require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); - return uint16(value); - } - - /** - * @dev Returns the downcasted uint8 from uint256, reverting on - * overflow (when the input is greater than largest uint8). - * - * Counterpart to Solidity's `uint8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - * - * _Available since v2.5._ - */ - function toUint8(uint256 value) internal pure returns (uint8) { - require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); - return uint8(value); - } - - /** - * @dev Converts a signed int256 into an unsigned uint256. - * - * Requirements: - * - * - input must be greater than or equal to 0. - * - * _Available since v3.0._ - */ - function toUint256(int256 value) internal pure returns (uint256) { - require(value >= 0, "SafeCast: value must be positive"); - return uint256(value); - } - - /** - * @dev Returns the downcasted int248 from int256, reverting on - * overflow (when the input is less than smallest int248 or - * greater than largest int248). - * - * Counterpart to Solidity's `int248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - * - * _Available since v4.7._ - */ - function toInt248(int256 value) internal pure returns (int248 downcasted) { - downcasted = int248(value); - require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); - } - - /** - * @dev Returns the downcasted int240 from int256, reverting on - * overflow (when the input is less than smallest int240 or - * greater than largest int240). - * - * Counterpart to Solidity's `int240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - * - * _Available since v4.7._ - */ - function toInt240(int256 value) internal pure returns (int240 downcasted) { - downcasted = int240(value); - require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); - } - - /** - * @dev Returns the downcasted int232 from int256, reverting on - * overflow (when the input is less than smallest int232 or - * greater than largest int232). - * - * Counterpart to Solidity's `int232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - * - * _Available since v4.7._ - */ - function toInt232(int256 value) internal pure returns (int232 downcasted) { - downcasted = int232(value); - require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); - } - - /** - * @dev Returns the downcasted int224 from int256, reverting on - * overflow (when the input is less than smallest int224 or - * greater than largest int224). - * - * Counterpart to Solidity's `int224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - * - * _Available since v4.7._ - */ - function toInt224(int256 value) internal pure returns (int224 downcasted) { - downcasted = int224(value); - require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); - } - - /** - * @dev Returns the downcasted int216 from int256, reverting on - * overflow (when the input is less than smallest int216 or - * greater than largest int216). - * - * Counterpart to Solidity's `int216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - * - * _Available since v4.7._ - */ - function toInt216(int256 value) internal pure returns (int216 downcasted) { - downcasted = int216(value); - require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); - } - - /** - * @dev Returns the downcasted int208 from int256, reverting on - * overflow (when the input is less than smallest int208 or - * greater than largest int208). - * - * Counterpart to Solidity's `int208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - * - * _Available since v4.7._ - */ - function toInt208(int256 value) internal pure returns (int208 downcasted) { - downcasted = int208(value); - require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); - } - - /** - * @dev Returns the downcasted int200 from int256, reverting on - * overflow (when the input is less than smallest int200 or - * greater than largest int200). - * - * Counterpart to Solidity's `int200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - * - * _Available since v4.7._ - */ - function toInt200(int256 value) internal pure returns (int200 downcasted) { - downcasted = int200(value); - require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); - } - - /** - * @dev Returns the downcasted int192 from int256, reverting on - * overflow (when the input is less than smallest int192 or - * greater than largest int192). - * - * Counterpart to Solidity's `int192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - * - * _Available since v4.7._ - */ - function toInt192(int256 value) internal pure returns (int192 downcasted) { - downcasted = int192(value); - require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); - } - - /** - * @dev Returns the downcasted int184 from int256, reverting on - * overflow (when the input is less than smallest int184 or - * greater than largest int184). - * - * Counterpart to Solidity's `int184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - * - * _Available since v4.7._ - */ - function toInt184(int256 value) internal pure returns (int184 downcasted) { - downcasted = int184(value); - require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); - } - - /** - * @dev Returns the downcasted int176 from int256, reverting on - * overflow (when the input is less than smallest int176 or - * greater than largest int176). - * - * Counterpart to Solidity's `int176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - * - * _Available since v4.7._ - */ - function toInt176(int256 value) internal pure returns (int176 downcasted) { - downcasted = int176(value); - require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); - } - - /** - * @dev Returns the downcasted int168 from int256, reverting on - * overflow (when the input is less than smallest int168 or - * greater than largest int168). - * - * Counterpart to Solidity's `int168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - * - * _Available since v4.7._ - */ - function toInt168(int256 value) internal pure returns (int168 downcasted) { - downcasted = int168(value); - require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); - } - - /** - * @dev Returns the downcasted int160 from int256, reverting on - * overflow (when the input is less than smallest int160 or - * greater than largest int160). - * - * Counterpart to Solidity's `int160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - * - * _Available since v4.7._ - */ - function toInt160(int256 value) internal pure returns (int160 downcasted) { - downcasted = int160(value); - require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); - } - - /** - * @dev Returns the downcasted int152 from int256, reverting on - * overflow (when the input is less than smallest int152 or - * greater than largest int152). - * - * Counterpart to Solidity's `int152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - * - * _Available since v4.7._ - */ - function toInt152(int256 value) internal pure returns (int152 downcasted) { - downcasted = int152(value); - require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); - } - - /** - * @dev Returns the downcasted int144 from int256, reverting on - * overflow (when the input is less than smallest int144 or - * greater than largest int144). - * - * Counterpart to Solidity's `int144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - * - * _Available since v4.7._ - */ - function toInt144(int256 value) internal pure returns (int144 downcasted) { - downcasted = int144(value); - require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); - } - - /** - * @dev Returns the downcasted int136 from int256, reverting on - * overflow (when the input is less than smallest int136 or - * greater than largest int136). - * - * Counterpart to Solidity's `int136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - * - * _Available since v4.7._ - */ - function toInt136(int256 value) internal pure returns (int136 downcasted) { - downcasted = int136(value); - require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); - } - - /** - * @dev Returns the downcasted int128 from int256, reverting on - * overflow (when the input is less than smallest int128 or - * greater than largest int128). - * - * Counterpart to Solidity's `int128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - * - * _Available since v3.1._ - */ - function toInt128(int256 value) internal pure returns (int128 downcasted) { - downcasted = int128(value); - require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); - } - - /** - * @dev Returns the downcasted int120 from int256, reverting on - * overflow (when the input is less than smallest int120 or - * greater than largest int120). - * - * Counterpart to Solidity's `int120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - * - * _Available since v4.7._ - */ - function toInt120(int256 value) internal pure returns (int120 downcasted) { - downcasted = int120(value); - require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); - } - - /** - * @dev Returns the downcasted int112 from int256, reverting on - * overflow (when the input is less than smallest int112 or - * greater than largest int112). - * - * Counterpart to Solidity's `int112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - * - * _Available since v4.7._ - */ - function toInt112(int256 value) internal pure returns (int112 downcasted) { - downcasted = int112(value); - require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); - } - - /** - * @dev Returns the downcasted int104 from int256, reverting on - * overflow (when the input is less than smallest int104 or - * greater than largest int104). - * - * Counterpart to Solidity's `int104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - * - * _Available since v4.7._ - */ - function toInt104(int256 value) internal pure returns (int104 downcasted) { - downcasted = int104(value); - require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); - } - - /** - * @dev Returns the downcasted int96 from int256, reverting on - * overflow (when the input is less than smallest int96 or - * greater than largest int96). - * - * Counterpart to Solidity's `int96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - * - * _Available since v4.7._ - */ - function toInt96(int256 value) internal pure returns (int96 downcasted) { - downcasted = int96(value); - require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); - } - - /** - * @dev Returns the downcasted int88 from int256, reverting on - * overflow (when the input is less than smallest int88 or - * greater than largest int88). - * - * Counterpart to Solidity's `int88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - * - * _Available since v4.7._ - */ - function toInt88(int256 value) internal pure returns (int88 downcasted) { - downcasted = int88(value); - require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); - } - - /** - * @dev Returns the downcasted int80 from int256, reverting on - * overflow (when the input is less than smallest int80 or - * greater than largest int80). - * - * Counterpart to Solidity's `int80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - * - * _Available since v4.7._ - */ - function toInt80(int256 value) internal pure returns (int80 downcasted) { - downcasted = int80(value); - require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); - } - - /** - * @dev Returns the downcasted int72 from int256, reverting on - * overflow (when the input is less than smallest int72 or - * greater than largest int72). - * - * Counterpart to Solidity's `int72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - * - * _Available since v4.7._ - */ - function toInt72(int256 value) internal pure returns (int72 downcasted) { - downcasted = int72(value); - require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); - } - - /** - * @dev Returns the downcasted int64 from int256, reverting on - * overflow (when the input is less than smallest int64 or - * greater than largest int64). - * - * Counterpart to Solidity's `int64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - * - * _Available since v3.1._ - */ - function toInt64(int256 value) internal pure returns (int64 downcasted) { - downcasted = int64(value); - require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); - } - - /** - * @dev Returns the downcasted int56 from int256, reverting on - * overflow (when the input is less than smallest int56 or - * greater than largest int56). - * - * Counterpart to Solidity's `int56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - * - * _Available since v4.7._ - */ - function toInt56(int256 value) internal pure returns (int56 downcasted) { - downcasted = int56(value); - require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); - } - - /** - * @dev Returns the downcasted int48 from int256, reverting on - * overflow (when the input is less than smallest int48 or - * greater than largest int48). - * - * Counterpart to Solidity's `int48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - * - * _Available since v4.7._ - */ - function toInt48(int256 value) internal pure returns (int48 downcasted) { - downcasted = int48(value); - require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); - } - - /** - * @dev Returns the downcasted int40 from int256, reverting on - * overflow (when the input is less than smallest int40 or - * greater than largest int40). - * - * Counterpart to Solidity's `int40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - * - * _Available since v4.7._ - */ - function toInt40(int256 value) internal pure returns (int40 downcasted) { - downcasted = int40(value); - require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); - } - - /** - * @dev Returns the downcasted int32 from int256, reverting on - * overflow (when the input is less than smallest int32 or - * greater than largest int32). - * - * Counterpart to Solidity's `int32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - * - * _Available since v3.1._ - */ - function toInt32(int256 value) internal pure returns (int32 downcasted) { - downcasted = int32(value); - require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); - } - - /** - * @dev Returns the downcasted int24 from int256, reverting on - * overflow (when the input is less than smallest int24 or - * greater than largest int24). - * - * Counterpart to Solidity's `int24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - * - * _Available since v4.7._ - */ - function toInt24(int256 value) internal pure returns (int24 downcasted) { - downcasted = int24(value); - require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); - } - - /** - * @dev Returns the downcasted int16 from int256, reverting on - * overflow (when the input is less than smallest int16 or - * greater than largest int16). - * - * Counterpart to Solidity's `int16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - * - * _Available since v3.1._ - */ - function toInt16(int256 value) internal pure returns (int16 downcasted) { - downcasted = int16(value); - require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); - } - - /** - * @dev Returns the downcasted int8 from int256, reverting on - * overflow (when the input is less than smallest int8 or - * greater than largest int8). - * - * Counterpart to Solidity's `int8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - * - * _Available since v3.1._ - */ - function toInt8(int256 value) internal pure returns (int8 downcasted) { - downcasted = int8(value); - require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); - } - - /** - * @dev Converts an unsigned uint256 into a signed int256. - * - * Requirements: - * - * - input must be less than or equal to maxInt256. - * - * _Available since v3.0._ - */ - function toInt256(uint256 value) internal pure returns (int256) { - // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive - require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); - return int256(value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol deleted file mode 100644 index 93524bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SignedMath.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) - -pragma solidity ^0.8.0; - -/** - * @dev Standard signed math utilities missing in the Solidity language. - */ -library SignedMath { - /** - * @dev Returns the largest of two signed numbers. - */ - function max(int256 a, int256 b) internal pure returns (int256) { - return a > b ? a : b; - } - - /** - * @dev Returns the smallest of two signed numbers. - */ - function min(int256 a, int256 b) internal pure returns (int256) { - return a < b ? a : b; - } - - /** - * @dev Returns the average of two signed numbers without overflow. - * The result is rounded towards zero. - */ - function average(int256 a, int256 b) internal pure returns (int256) { - // Formula from the book "Hacker's Delight" - int256 x = (a & b) + ((a ^ b) >> 1); - return x + (int256(uint256(x) >> 255) & (a ^ b)); - } - - /** - * @dev Returns the absolute unsigned value of a signed value. - */ - function abs(int256 n) internal pure returns (uint256) { - unchecked { - // must be unchecked in order to support `n = type(int256).min` - return uint256(n >= 0 ? n : -n); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol deleted file mode 100644 index 7f4e911..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableMap.sol +++ /dev/null @@ -1,530 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableMap.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. - -pragma solidity ^0.8.0; - -import "./EnumerableSet.sol"; - -/** - * @dev Library for managing an enumerable variant of Solidity's - * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] - * type. - * - * Maps have the following properties: - * - * - Entries are added, removed, and checked for existence in constant time - * (O(1)). - * - Entries are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableMap for EnumerableMap.UintToAddressMap; - * - * // Declare a set state variable - * EnumerableMap.UintToAddressMap private myMap; - * } - * ``` - * - * The following map types are supported: - * - * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 - * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 - * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableMap. - * ==== - */ -library EnumerableMap { - using EnumerableSet for EnumerableSet.Bytes32Set; - - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Map type with - // bytes32 keys and values. - // The Map implementation uses private functions, and user-facing - // implementations (such as Uint256ToAddressMap) are just wrappers around - // the underlying Map. - // This means that we can only create new EnumerableMaps for types that fit - // in bytes32. - - struct Bytes32ToBytes32Map { - // Storage of keys - EnumerableSet.Bytes32Set _keys; - mapping(bytes32 => bytes32) _values; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - Bytes32ToBytes32Map storage map, - bytes32 key, - bytes32 value - ) internal returns (bool) { - map._values[key] = value; - return map._keys.add(key); - } - - /** - * @dev Removes a key-value pair from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { - delete map._values[key]; - return map._keys.remove(key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { - return map._keys.contains(key); - } - - /** - * @dev Returns the number of key-value pairs in the map. O(1). - */ - function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { - return map._keys.length(); - } - - /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). - * - * Note that there are no guarantees on the ordering of entries inside the - * array, and it may change when more entries are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { - bytes32 key = map._keys.at(index); - return (key, map._values[key]); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { - bytes32 value = map._values[key]; - if (value == bytes32(0)) { - return (contains(map, key), bytes32(0)); - } else { - return (true, value); - } - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { - bytes32 value = map._values[key]; - require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); - return value; - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - Bytes32ToBytes32Map storage map, - bytes32 key, - string memory errorMessage - ) internal view returns (bytes32) { - bytes32 value = map._values[key]; - require(value != 0 || contains(map, key), errorMessage); - return value; - } - - // UintToUintMap - - struct UintToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - UintToUintMap storage map, - uint256 key, - uint256 value - ) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - UintToUintMap storage map, - uint256 key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key), errorMessage)); - } - - // UintToAddressMap - - struct UintToAddressMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - UintToAddressMap storage map, - uint256 key, - address value - ) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToAddressMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), address(uint160(uint256(value)))); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, address(uint160(uint256(value)))); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key))))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - UintToAddressMap storage map, - uint256 key, - string memory errorMessage - ) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); - } - - // AddressToUintMap - - struct AddressToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - AddressToUintMap storage map, - address key, - uint256 value - ) internal returns (bool) { - return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(AddressToUintMap storage map, address key) internal returns (bool) { - return remove(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(AddressToUintMap storage map, address key) internal view returns (bool) { - return contains(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(AddressToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (address(uint160(uint256(key))), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(AddressToUintMap storage map, address key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))))); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - AddressToUintMap storage map, - address key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); - } - - // Bytes32ToUintMap - - struct Bytes32ToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set( - Bytes32ToUintMap storage map, - bytes32 key, - uint256 value - ) internal returns (bool) { - return set(map._inner, key, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { - return remove(map._inner, key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { - return contains(map._inner, key); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(Bytes32ToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the set. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (key, uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, key); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { - return uint256(get(map._inner, key)); - } - - /** - * @dev Same as {get}, with a custom error message when `key` is not in the map. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryGet}. - */ - function get( - Bytes32ToUintMap storage map, - bytes32 key, - string memory errorMessage - ) internal view returns (uint256) { - return uint256(get(map._inner, key, errorMessage)); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol deleted file mode 100644 index 0bcbefe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol +++ /dev/null @@ -1,378 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. - -pragma solidity ^0.8.0; - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ``` - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position of the value in the `values` array, plus 1 because index 0 - // means a value is not in the set. - mapping(bytes32 => uint256) _indexes; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._indexes[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We read and store the value's index to prevent multiple reads from the same storage slot - uint256 valueIndex = set._indexes[value]; - - if (valueIndex != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 toDeleteIndex = valueIndex - 1; - uint256 lastIndex = set._values.length - 1; - - if (lastIndex != toDeleteIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the last value to the index where the value to delete is - set._values[toDeleteIndex] = lastValue; - // Update the index for the moved value - set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the index for the deleted slot - delete set._indexes[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._indexes[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - bytes32[] memory store = _values(set._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol deleted file mode 100644 index 3e3341e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/AccessControl.sol +++ /dev/null @@ -1,209 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) - -pragma solidity ^0.8.20; - -import {IAccessControl} from "./IAccessControl.sol"; -import {Context} from "../utils/Context.sol"; -import {ERC165} from "../utils/introspection/ERC165.sol"; - -/** - * @dev Contract module that allows children to implement role-based access - * control mechanisms. This is a lightweight version that doesn't allow enumerating role - * members except through off-chain means by accessing the contract event logs. Some - * applications may benefit from on-chain enumerability, for those cases see - * {AccessControlEnumerable}. - * - * Roles are referred to by their `bytes32` identifier. These should be exposed - * in the external API and be unique. The best way to achieve this is by - * using `public constant` hash digests: - * - * ```solidity - * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); - * ``` - * - * Roles can be used to represent a set of permissions. To restrict access to a - * function call, use {hasRole}: - * - * ```solidity - * function foo() public { - * require(hasRole(MY_ROLE, msg.sender)); - * ... - * } - * ``` - * - * Roles can be granted and revoked dynamically via the {grantRole} and - * {revokeRole} functions. Each role has an associated admin role, and only - * accounts that have a role's admin role can call {grantRole} and {revokeRole}. - * - * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means - * that only accounts with this role will be able to grant or revoke other - * roles. More complex role relationships can be created by using - * {_setRoleAdmin}. - * - * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to - * grant and revoke this role. Extra precautions should be taken to secure - * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} - * to enforce additional security measures for this role. - */ -abstract contract AccessControl is Context, IAccessControl, ERC165 { - struct RoleData { - mapping(address account => bool) hasRole; - bytes32 adminRole; - } - - mapping(bytes32 role => RoleData) private _roles; - - bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - - /** - * @dev Modifier that checks that an account has a specific role. Reverts - * with an {AccessControlUnauthorizedAccount} error including the required role. - */ - modifier onlyRole(bytes32 role) { - _checkRole(role); - _; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); - } - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) public view virtual returns (bool) { - return _roles[role].hasRole[account]; - } - - /** - * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` - * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. - */ - function _checkRole(bytes32 role) internal view virtual { - _checkRole(role, _msgSender()); - } - - /** - * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` - * is missing `role`. - */ - function _checkRole(bytes32 role, address account) internal view virtual { - if (!hasRole(role, account)) { - revert AccessControlUnauthorizedAccount(account, role); - } - } - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { - return _roles[role].adminRole; - } - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleGranted} event. - */ - function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { - _grantRole(role, account); - } - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - * - * May emit a {RoleRevoked} event. - */ - function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { - _revokeRole(role, account); - } - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been revoked `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `callerConfirmation`. - * - * May emit a {RoleRevoked} event. - */ - function renounceRole(bytes32 role, address callerConfirmation) public virtual { - if (callerConfirmation != _msgSender()) { - revert AccessControlBadConfirmation(); - } - - _revokeRole(role, callerConfirmation); - } - - /** - * @dev Sets `adminRole` as ``role``'s admin role. - * - * Emits a {RoleAdminChanged} event. - */ - function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { - bytes32 previousAdminRole = getRoleAdmin(role); - _roles[role].adminRole = adminRole; - emit RoleAdminChanged(role, previousAdminRole, adminRole); - } - - /** - * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. - * - * Internal function without access restriction. - * - * May emit a {RoleGranted} event. - */ - function _grantRole(bytes32 role, address account) internal virtual returns (bool) { - if (!hasRole(role, account)) { - _roles[role].hasRole[account] = true; - emit RoleGranted(role, account, _msgSender()); - return true; - } else { - return false; - } - } - - /** - * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. - * - * Internal function without access restriction. - * - * May emit a {RoleRevoked} event. - */ - function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { - if (hasRole(role, account)) { - _roles[role].hasRole[account] = false; - emit RoleRevoked(role, account, _msgSender()); - return true; - } else { - return false; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol deleted file mode 100644 index 2ac89ca..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/access/IAccessControl.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) - -pragma solidity ^0.8.20; - -/** - * @dev External interface of AccessControl declared to support ERC165 detection. - */ -interface IAccessControl { - /** - * @dev The `account` is missing a role. - */ - error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); - - /** - * @dev The caller of a function is not the expected one. - * - * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. - */ - error AccessControlBadConfirmation(); - - /** - * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` - * - * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite - * {RoleAdminChanged} not being emitted signaling this. - */ - event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); - - /** - * @dev Emitted when `account` is granted `role`. - * - * `sender` is the account that originated the contract call, an admin role - * bearer except when using {AccessControl-_setupRole}. - */ - event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Emitted when `account` is revoked `role`. - * - * `sender` is the account that originated the contract call: - * - if using `revokeRole`, it is the admin role bearer - * - if using `renounceRole`, it is the role bearer (i.e. `account`) - */ - event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); - - /** - * @dev Returns `true` if `account` has been granted `role`. - */ - function hasRole(bytes32 role, address account) external view returns (bool); - - /** - * @dev Returns the admin role that controls `role`. See {grantRole} and - * {revokeRole}. - * - * To change a role's admin, use {AccessControl-_setRoleAdmin}. - */ - function getRoleAdmin(bytes32 role) external view returns (bytes32); - - /** - * @dev Grants `role` to `account`. - * - * If `account` had not been already granted `role`, emits a {RoleGranted} - * event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function grantRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from `account`. - * - * If `account` had been granted `role`, emits a {RoleRevoked} event. - * - * Requirements: - * - * - the caller must have ``role``'s admin role. - */ - function revokeRole(bytes32 role, address account) external; - - /** - * @dev Revokes `role` from the calling account. - * - * Roles are often managed via {grantRole} and {revokeRole}: this function's - * purpose is to provide a mechanism for accounts to lose their privileges - * if they are compromised (such as when a trusted device is misplaced). - * - * If the calling account had been granted `role`, emits a {RoleRevoked} - * event. - * - * Requirements: - * - * - the caller must be `callerConfirmation`. - */ - function renounceRole(bytes32 role, address callerConfirmation) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol deleted file mode 100644 index 944dd0d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) - -pragma solidity ^0.8.20; - -import {IERC165} from "../utils/introspection/IERC165.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol deleted file mode 100644 index 21d5a41..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC20.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) - -pragma solidity ^0.8.20; - -import {IERC20} from "../token/ERC20/IERC20.sol"; diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol deleted file mode 100644 index 47a9fd5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC5267.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol) - -pragma solidity ^0.8.20; - -interface IERC5267 { - /** - * @dev MAY be emitted to signal that the domain could have changed. - */ - event EIP712DomainChanged(); - - /** - * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 - * signature. - */ - function eip712Domain() - external - view - returns ( - bytes1 fields, - string memory name, - string memory version, - uint256 chainId, - address verifyingContract, - bytes32 salt, - uint256[] memory extensions - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol deleted file mode 100644 index f6990e6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/draft-IERC6093.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) -pragma solidity ^0.8.20; - -/** - * @dev Standard ERC20 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens. - */ -interface IERC20Errors { - /** - * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param balance Current balance for the interacting account. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC20InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC20InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. - * @param spender Address that may be allowed to operate on tokens without being their owner. - * @param allowance Amount of tokens a `spender` is allowed to operate with. - * @param needed Minimum amount required to perform a transfer. - */ - error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC20InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `spender` to be approved. Used in approvals. - * @param spender Address that may be allowed to operate on tokens without being their owner. - */ - error ERC20InvalidSpender(address spender); -} - -/** - * @dev Standard ERC721 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens. - */ -interface IERC721Errors { - /** - * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20. - * Used in balance queries. - * @param owner Address of the current owner of a token. - */ - error ERC721InvalidOwner(address owner); - - /** - * @dev Indicates a `tokenId` whose `owner` is the zero address. - * @param tokenId Identifier number of a token. - */ - error ERC721NonexistentToken(uint256 tokenId); - - /** - * @dev Indicates an error related to the ownership over a particular token. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param tokenId Identifier number of a token. - * @param owner Address of the current owner of a token. - */ - error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC721InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC721InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `operator`’s approval. Used in transfers. - * @param operator Address that may be allowed to operate on tokens without being their owner. - * @param tokenId Identifier number of a token. - */ - error ERC721InsufficientApproval(address operator, uint256 tokenId); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC721InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `operator` to be approved. Used in approvals. - * @param operator Address that may be allowed to operate on tokens without being their owner. - */ - error ERC721InvalidOperator(address operator); -} - -/** - * @dev Standard ERC1155 Errors - * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens. - */ -interface IERC1155Errors { - /** - * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - * @param balance Current balance for the interacting account. - * @param needed Minimum amount required to perform a transfer. - * @param tokenId Identifier number of a token. - */ - error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); - - /** - * @dev Indicates a failure with the token `sender`. Used in transfers. - * @param sender Address whose tokens are being transferred. - */ - error ERC1155InvalidSender(address sender); - - /** - * @dev Indicates a failure with the token `receiver`. Used in transfers. - * @param receiver Address to which tokens are being transferred. - */ - error ERC1155InvalidReceiver(address receiver); - - /** - * @dev Indicates a failure with the `operator`’s approval. Used in transfers. - * @param operator Address that may be allowed to operate on tokens without being their owner. - * @param owner Address of the current owner of a token. - */ - error ERC1155MissingApprovalForAll(address operator, address owner); - - /** - * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. - * @param approver Address initiating an approval operation. - */ - error ERC1155InvalidApprover(address approver); - - /** - * @dev Indicates a failure with the `operator` to be approved. Used in approvals. - * @param operator Address that may be allowed to operate on tokens without being their owner. - */ - error ERC1155InvalidOperator(address operator); - - /** - * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. - * Used in batch transfers. - * @param idsLength Length of the array of token identifiers - * @param valuesLength Length of the array of token amounts - */ - error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol deleted file mode 100644 index 1fde527..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/ERC20.sol +++ /dev/null @@ -1,316 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) - -pragma solidity ^0.8.20; - -import {IERC20} from "./IERC20.sol"; -import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; -import {Context} from "../../utils/Context.sol"; -import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; - -/** - * @dev Implementation of the {IERC20} interface. - * - * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using {_mint}. - * - * TIP: For a detailed writeup see our guide - * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How - * to implement supply mechanisms]. - * - * The default value of {decimals} is 18. To change this, you should override - * this function so it returns a different value. - * - * We have followed general OpenZeppelin Contracts guidelines: functions revert - * instead returning `false` on failure. This behavior is nonetheless - * conventional and does not conflict with the expectations of ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - */ -abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { - mapping(address account => uint256) private _balances; - - mapping(address account => mapping(address spender => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * All two of these values are immutable: they can only be set once during - * construction. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev Returns the name of the token. - */ - function name() public view virtual returns (string memory) { - return _name; - } - - /** - * @dev Returns the symbol of the token, usually a shorter version of the - * name. - */ - function symbol() public view virtual returns (string memory) { - return _symbol; - } - - /** - * @dev Returns the number of decimals used to get its user representation. - * For example, if `decimals` equals `2`, a balance of `505` tokens should - * be displayed to a user as `5.05` (`505 / 10 ** 2`). - * - * Tokens usually opt for a value of 18, imitating the relationship between - * Ether and Wei. This is the default value returned by this function, unless - * it's overridden. - * - * NOTE: This information is only used for _display_ purposes: it in - * no way affects any of the arithmetic of the contract, including - * {IERC20-balanceOf} and {IERC20-transfer}. - */ - function decimals() public view virtual returns (uint8) { - return 18; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - function balanceOf(address account) public view virtual returns (uint256) { - return _balances[account]; - } - - /** - * @dev See {IERC20-transfer}. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - the caller must have a balance of at least `value`. - */ - function transfer(address to, uint256 value) public virtual returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, value); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance(address owner, address spender) public view virtual returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve(address spender, uint256 value) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, value); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `value`. - * - the caller must have allowance for ``from``'s tokens of at least - * `value`. - */ - function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { - address spender = _msgSender(); - _spendAllowance(from, spender, value); - _transfer(from, to, value); - return true; - } - - /** - * @dev Moves a `value` amount of tokens from `from` to `to`. - * - * This internal function is equivalent to {transfer}, and can be used to - * e.g. implement automatic token fees, slashing mechanisms, etc. - * - * Emits a {Transfer} event. - * - * NOTE: This function is not virtual, {_update} should be overridden instead. - */ - function _transfer(address from, address to, uint256 value) internal { - if (from == address(0)) { - revert ERC20InvalidSender(address(0)); - } - if (to == address(0)) { - revert ERC20InvalidReceiver(address(0)); - } - _update(from, to, value); - } - - /** - * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` - * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding - * this function. - * - * Emits a {Transfer} event. - */ - function _update(address from, address to, uint256 value) internal virtual { - if (from == address(0)) { - // Overflow check required: The rest of the code assumes that totalSupply never overflows - _totalSupply += value; - } else { - uint256 fromBalance = _balances[from]; - if (fromBalance < value) { - revert ERC20InsufficientBalance(from, fromBalance, value); - } - unchecked { - // Overflow not possible: value <= fromBalance <= totalSupply. - _balances[from] = fromBalance - value; - } - } - - if (to == address(0)) { - unchecked { - // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. - _totalSupply -= value; - } - } else { - unchecked { - // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. - _balances[to] += value; - } - } - - emit Transfer(from, to, value); - } - - /** - * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). - * Relies on the `_update` mechanism - * - * Emits a {Transfer} event with `from` set to the zero address. - * - * NOTE: This function is not virtual, {_update} should be overridden instead. - */ - function _mint(address account, uint256 value) internal { - if (account == address(0)) { - revert ERC20InvalidReceiver(address(0)); - } - _update(address(0), account, value); - } - - /** - * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. - * Relies on the `_update` mechanism. - * - * Emits a {Transfer} event with `to` set to the zero address. - * - * NOTE: This function is not virtual, {_update} should be overridden instead - */ - function _burn(address account, uint256 value) internal { - if (account == address(0)) { - revert ERC20InvalidSender(address(0)); - } - _update(account, address(0), value); - } - - /** - * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens. - * - * This internal function is equivalent to `approve`, and can be used to - * e.g. set automatic allowances for certain subsystems, etc. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `owner` cannot be the zero address. - * - `spender` cannot be the zero address. - * - * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. - */ - function _approve(address owner, address spender, uint256 value) internal { - _approve(owner, spender, value, true); - } - - /** - * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. - * - * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by - * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any - * `Approval` event during `transferFrom` operations. - * - * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to - * true using the following override: - * ``` - * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { - * super._approve(owner, spender, value, true); - * } - * ``` - * - * Requirements are the same as {_approve}. - */ - function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { - if (owner == address(0)) { - revert ERC20InvalidApprover(address(0)); - } - if (spender == address(0)) { - revert ERC20InvalidSpender(address(0)); - } - _allowances[owner][spender] = value; - if (emitEvent) { - emit Approval(owner, spender, value); - } - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `value`. - * - * Does not update the allowance value in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Does not emit an {Approval} event. - */ - function _spendAllowance(address owner, address spender, uint256 value) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - if (currentAllowance < value) { - revert ERC20InsufficientAllowance(spender, currentAllowance, value); - } - unchecked { - _approve(owner, spender, currentAllowance - value, false); - } - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol deleted file mode 100644 index db01cf4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); - - /** - * @dev Returns the value of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the value of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves a `value` amount of tokens from the caller's account to `to`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address to, uint256 value) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets a `value` amount of tokens as the allowance of `spender` over the - * caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 value) external returns (bool); - - /** - * @dev Moves a `value` amount of tokens from `from` to `to` using the - * allowance mechanism. `value` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address from, address to, uint256 value) external returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol deleted file mode 100644 index 4d482d8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/ERC20Burnable.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) - -pragma solidity ^0.8.20; - -import {ERC20} from "../ERC20.sol"; -import {Context} from "../../../utils/Context.sol"; - -/** - * @dev Extension of {ERC20} that allows token holders to destroy both their own - * tokens and those that they have an allowance for, in a way that can be - * recognized off-chain (via event analysis). - */ -abstract contract ERC20Burnable is Context, ERC20 { - /** - * @dev Destroys a `value` amount of tokens from the caller. - * - * See {ERC20-_burn}. - */ - function burn(uint256 value) public virtual { - _burn(_msgSender(), value); - } - - /** - * @dev Destroys a `value` amount of tokens from `account`, deducting from - * the caller's allowance. - * - * See {ERC20-_burn} and {ERC20-allowance}. - * - * Requirements: - * - * - the caller must have allowance for ``accounts``'s tokens of at least - * `value`. - */ - function burnFrom(address account, uint256 value) public virtual { - _spendAllowance(account, _msgSender(), value); - _burn(account, value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol deleted file mode 100644 index 1a38cba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Metadata.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) - -pragma solidity ^0.8.20; - -import {IERC20} from "../IERC20.sol"; - -/** - * @dev Interface for the optional metadata functions from the ERC20 standard. - */ -interface IERC20Metadata is IERC20 { - /** - * @dev Returns the name of the token. - */ - function name() external view returns (string memory); - - /** - * @dev Returns the symbol of the token. - */ - function symbol() external view returns (string memory); - - /** - * @dev Returns the decimals places of the token. - */ - function decimals() external view returns (uint8); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol deleted file mode 100644 index 5af4810..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/extensions/IERC20Permit.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in - * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. - * - * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by - * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't - * need to send a transaction, and thus is not required to hold Ether at all. - * - * ==== Security Considerations - * - * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature - * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be - * considered as an intention to spend the allowance in any specific way. The second is that because permits have - * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should - * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be - * generally recommended is: - * - * ```solidity - * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { - * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} - * doThing(..., value); - * } - * - * function doThing(..., uint256 value) public { - * token.safeTransferFrom(msg.sender, address(this), value); - * ... - * } - * ``` - * - * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of - * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also - * {SafeERC20-safeTransferFrom}). - * - * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so - * contracts should have entry points that don't rely on permit. - */ -interface IERC20Permit { - /** - * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, - * given ``owner``'s signed approval. - * - * IMPORTANT: The same issues {IERC20-approve} has related to transaction - * ordering also apply here. - * - * Emits an {Approval} event. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `deadline` must be a timestamp in the future. - * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` - * over the EIP712-formatted function arguments. - * - the signature must use ``owner``'s current nonce (see {nonces}). - * - * For more information on the signature format, see the - * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP - * section]. - * - * CAUTION: See Security Considerations above. - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external; - - /** - * @dev Returns the current nonce for `owner`. This value must be - * included whenever a signature is generated for {permit}. - * - * Every successful call to {permit} increases ``owner``'s nonce by one. This - * prevents a signature from being used multiple times. - */ - function nonces(address owner) external view returns (uint256); - - /** - * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. - */ - // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol deleted file mode 100644 index bb65709..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/utils/SafeERC20.sol +++ /dev/null @@ -1,118 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) - -pragma solidity ^0.8.20; - -import {IERC20} from "../IERC20.sol"; -import {IERC20Permit} from "../extensions/IERC20Permit.sol"; -import {Address} from "../../../utils/Address.sol"; - -/** - * @title SafeERC20 - * @dev Wrappers around ERC20 operations that throw on failure (when the token - * contract returns false). Tokens that return no value (and instead revert or - * throw on failure) are also supported, non-reverting calls are assumed to be - * successful. - * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, - * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. - */ -library SafeERC20 { - using Address for address; - - /** - * @dev An operation with an ERC20 token failed. - */ - error SafeERC20FailedOperation(address token); - - /** - * @dev Indicates a failed `decreaseAllowance` request. - */ - error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); - - /** - * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, - * non-reverting calls are assumed to be successful. - */ - function safeTransfer(IERC20 token, address to, uint256 value) internal { - _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); - } - - /** - * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the - * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. - */ - function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { - _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); - } - - /** - * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, - * non-reverting calls are assumed to be successful. - */ - function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { - uint256 oldAllowance = token.allowance(address(this), spender); - forceApprove(token, spender, oldAllowance + value); - } - - /** - * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no - * value, non-reverting calls are assumed to be successful. - */ - function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { - unchecked { - uint256 currentAllowance = token.allowance(address(this), spender); - if (currentAllowance < requestedDecrease) { - revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); - } - forceApprove(token, spender, currentAllowance - requestedDecrease); - } - } - - /** - * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, - * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval - * to be set to zero before setting it to a non-zero value, such as USDT. - */ - function forceApprove(IERC20 token, address spender, uint256 value) internal { - bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); - - if (!_callOptionalReturnBool(token, approvalCall)) { - _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); - _callOptionalReturn(token, approvalCall); - } - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - */ - function _callOptionalReturn(IERC20 token, bytes memory data) private { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that - // the target address contains contract code and also asserts for success in the low-level call. - - bytes memory returndata = address(token).functionCall(data); - if (returndata.length != 0 && !abi.decode(returndata, (bool))) { - revert SafeERC20FailedOperation(address(token)); - } - } - - /** - * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement - * on the return value: the return value is optional (but if data is returned, it must not be false). - * @param token The token targeted by the call. - * @param data The call data (encoded using abi.encode or one of its variants). - * - * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. - */ - function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { - // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since - // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false - // and not revert is the subcall reverts. - - (bool success, bytes memory returndata) = address(token).call(data); - return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol deleted file mode 100644 index b7e3059..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Address.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev The ETH balance of the account is not enough to perform the operation. - */ - error AddressInsufficientBalance(address account); - - /** - * @dev There's no code at `target` (it is not a contract). - */ - error AddressEmptyCode(address target); - - /** - * @dev A call to an address target failed. The target may have reverted. - */ - error FailedInnerCall(); - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - if (address(this).balance < amount) { - revert AddressInsufficientBalance(address(this)); - } - - (bool success, ) = recipient.call{value: amount}(""); - if (!success) { - revert FailedInnerCall(); - } - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain `call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason or custom error, it is bubbled - * up by this function (like regular Solidity function calls). However, if - * the call reverted with no returned reason, this function reverts with a - * {FailedInnerCall} error. - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - */ - function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { - if (address(this).balance < value) { - revert AddressInsufficientBalance(address(this)); - } - (bool success, bytes memory returndata) = target.call{value: value}(data); - return verifyCallResultFromTarget(target, success, returndata); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - (bool success, bytes memory returndata) = target.staticcall(data); - return verifyCallResultFromTarget(target, success, returndata); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - (bool success, bytes memory returndata) = target.delegatecall(data); - return verifyCallResultFromTarget(target, success, returndata); - } - - /** - * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target - * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an - * unsuccessful call. - */ - function verifyCallResultFromTarget( - address target, - bool success, - bytes memory returndata - ) internal view returns (bytes memory) { - if (!success) { - _revert(returndata); - } else { - // only check if target is a contract if the call was successful and the return data is empty - // otherwise we already know that it was a contract - if (returndata.length == 0 && target.code.length == 0) { - revert AddressEmptyCode(target); - } - return returndata; - } - } - - /** - * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the - * revert reason or with a default {FailedInnerCall} error. - */ - function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { - if (!success) { - _revert(returndata); - } else { - return returndata; - } - } - - /** - * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. - */ - function _revert(bytes memory returndata) private pure { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - /// @solidity memory-safe-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert FailedInnerCall(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol deleted file mode 100644 index 4e535fe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Context.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes calldata) { - return msg.data; - } - - function _contextSuffixLength() internal view virtual returns (uint256) { - return 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol deleted file mode 100644 index 312f1cb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Pausable.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) - -pragma solidity ^0.8.20; - -import {Context} from "../utils/Context.sol"; - -/** - * @dev Contract module which allows children to implement an emergency stop - * mechanism that can be triggered by an authorized account. - * - * This module is used through inheritance. It will make available the - * modifiers `whenNotPaused` and `whenPaused`, which can be applied to - * the functions of your contract. Note that they will not be pausable by - * simply including this module, only once the modifiers are put in place. - */ -abstract contract Pausable is Context { - bool private _paused; - - /** - * @dev Emitted when the pause is triggered by `account`. - */ - event Paused(address account); - - /** - * @dev Emitted when the pause is lifted by `account`. - */ - event Unpaused(address account); - - /** - * @dev The operation failed because the contract is paused. - */ - error EnforcedPause(); - - /** - * @dev The operation failed because the contract is not paused. - */ - error ExpectedPause(); - - /** - * @dev Initializes the contract in unpaused state. - */ - constructor() { - _paused = false; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - _requireNotPaused(); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - * - * Requirements: - * - * - The contract must be paused. - */ - modifier whenPaused() { - _requirePaused(); - _; - } - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() public view virtual returns (bool) { - return _paused; - } - - /** - * @dev Throws if the contract is paused. - */ - function _requireNotPaused() internal view virtual { - if (paused()) { - revert EnforcedPause(); - } - } - - /** - * @dev Throws if the contract is not paused. - */ - function _requirePaused() internal view virtual { - if (!paused()) { - revert ExpectedPause(); - } - } - - /** - * @dev Triggers stopped state. - * - * Requirements: - * - * - The contract must not be paused. - */ - function _pause() internal virtual whenNotPaused { - _paused = true; - emit Paused(_msgSender()); - } - - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _unpause() internal virtual whenPaused { - _paused = false; - emit Unpaused(_msgSender()); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol deleted file mode 100644 index fdfe774..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/ShortStrings.sol +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol) - -pragma solidity ^0.8.20; - -import {StorageSlot} from "./StorageSlot.sol"; - -// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | -// | length | 0x BB | -type ShortString is bytes32; - -/** - * @dev This library provides functions to convert short memory strings - * into a `ShortString` type that can be used as an immutable variable. - * - * Strings of arbitrary length can be optimized using this library if - * they are short enough (up to 31 bytes) by packing them with their - * length (1 byte) in a single EVM word (32 bytes). Additionally, a - * fallback mechanism can be used for every other case. - * - * Usage example: - * - * ```solidity - * contract Named { - * using ShortStrings for *; - * - * ShortString private immutable _name; - * string private _nameFallback; - * - * constructor(string memory contractName) { - * _name = contractName.toShortStringWithFallback(_nameFallback); - * } - * - * function name() external view returns (string memory) { - * return _name.toStringWithFallback(_nameFallback); - * } - * } - * ``` - */ -library ShortStrings { - // Used as an identifier for strings longer than 31 bytes. - bytes32 private constant FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; - - error StringTooLong(string str); - error InvalidShortString(); - - /** - * @dev Encode a string of at most 31 chars into a `ShortString`. - * - * This will trigger a `StringTooLong` error is the input string is too long. - */ - function toShortString(string memory str) internal pure returns (ShortString) { - bytes memory bstr = bytes(str); - if (bstr.length > 31) { - revert StringTooLong(str); - } - return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); - } - - /** - * @dev Decode a `ShortString` back to a "normal" string. - */ - function toString(ShortString sstr) internal pure returns (string memory) { - uint256 len = byteLength(sstr); - // using `new string(len)` would work locally but is not memory safe. - string memory str = new string(32); - /// @solidity memory-safe-assembly - assembly { - mstore(str, len) - mstore(add(str, 0x20), sstr) - } - return str; - } - - /** - * @dev Return the length of a `ShortString`. - */ - function byteLength(ShortString sstr) internal pure returns (uint256) { - uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; - if (result > 31) { - revert InvalidShortString(); - } - return result; - } - - /** - * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. - */ - function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { - if (bytes(value).length < 32) { - return toShortString(value); - } else { - StorageSlot.getStringSlot(store).value = value; - return ShortString.wrap(FALLBACK_SENTINEL); - } - } - - /** - * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. - */ - function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { - if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { - return toString(value); - } else { - return store; - } - } - - /** - * @dev Return the length of a string that was encoded to `ShortString` or written to storage using - * {setWithFallback}. - * - * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of - * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. - */ - function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { - if (ShortString.unwrap(value) != FALLBACK_SENTINEL) { - return byteLength(value); - } else { - return bytes(store).length; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol deleted file mode 100644 index 0841832..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/StorageSlot.sol +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) -// This file was procedurally generated from scripts/generate/templates/StorageSlot.js. - -pragma solidity ^0.8.20; - -/** - * @dev Library for reading and writing primitive types to specific storage slots. - * - * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. - * This library helps with reading and writing to such slots without the need for inline assembly. - * - * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. - * - * Example usage to set ERC1967 implementation slot: - * ```solidity - * contract ERC1967 { - * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - * - * function _getImplementation() internal view returns (address) { - * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; - * } - * - * function _setImplementation(address newImplementation) internal { - * require(newImplementation.code.length > 0); - * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; - * } - * } - * ``` - */ -library StorageSlot { - struct AddressSlot { - address value; - } - - struct BooleanSlot { - bool value; - } - - struct Bytes32Slot { - bytes32 value; - } - - struct Uint256Slot { - uint256 value; - } - - struct StringSlot { - string value; - } - - struct BytesSlot { - bytes value; - } - - /** - * @dev Returns an `AddressSlot` with member `value` located at `slot`. - */ - function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `BooleanSlot` with member `value` located at `slot`. - */ - function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. - */ - function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `Uint256Slot` with member `value` located at `slot`. - */ - function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `StringSlot` with member `value` located at `slot`. - */ - function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `StringSlot` representation of the string storage pointer `store`. - */ - function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := store.slot - } - } - - /** - * @dev Returns an `BytesSlot` with member `value` located at `slot`. - */ - function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := slot - } - } - - /** - * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. - */ - function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { - /// @solidity memory-safe-assembly - assembly { - r.slot := store.slot - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol deleted file mode 100644 index b2c0a40..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Strings.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) - -pragma solidity ^0.8.20; - -import {Math} from "./math/Math.sol"; -import {SignedMath} from "./math/SignedMath.sol"; - -/** - * @dev String operations. - */ -library Strings { - bytes16 private constant HEX_DIGITS = "0123456789abcdef"; - uint8 private constant ADDRESS_LENGTH = 20; - - /** - * @dev The `value` string doesn't fit in the specified `length`. - */ - error StringsInsufficientHexLength(uint256 value, uint256 length); - - /** - * @dev Converts a `uint256` to its ASCII `string` decimal representation. - */ - function toString(uint256 value) internal pure returns (string memory) { - unchecked { - uint256 length = Math.log10(value) + 1; - string memory buffer = new string(length); - uint256 ptr; - /// @solidity memory-safe-assembly - assembly { - ptr := add(buffer, add(32, length)) - } - while (true) { - ptr--; - /// @solidity memory-safe-assembly - assembly { - mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) - } - value /= 10; - if (value == 0) break; - } - return buffer; - } - } - - /** - * @dev Converts a `int256` to its ASCII `string` decimal representation. - */ - function toStringSigned(int256 value) internal pure returns (string memory) { - return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. - */ - function toHexString(uint256 value) internal pure returns (string memory) { - unchecked { - return toHexString(value, Math.log256(value) + 1); - } - } - - /** - * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. - */ - function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { - uint256 localValue = value; - bytes memory buffer = new bytes(2 * length + 2); - buffer[0] = "0"; - buffer[1] = "x"; - for (uint256 i = 2 * length + 1; i > 1; --i) { - buffer[i] = HEX_DIGITS[localValue & 0xf]; - localValue >>= 4; - } - if (localValue != 0) { - revert StringsInsufficientHexLength(value, length); - } - return string(buffer); - } - - /** - * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal - * representation. - */ - function toHexString(address addr) internal pure returns (string memory) { - return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); - } - - /** - * @dev Returns true if the two strings are equal. - */ - function equal(string memory a, string memory b) internal pure returns (bool) { - return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol deleted file mode 100644 index 04b3e5e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/ECDSA.sol +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. - * - * These functions can be used to verify that a message was signed by the holder - * of the private keys of a given address. - */ -library ECDSA { - enum RecoverError { - NoError, - InvalidSignature, - InvalidSignatureLength, - InvalidSignatureS - } - - /** - * @dev The signature derives the `address(0)`. - */ - error ECDSAInvalidSignature(); - - /** - * @dev The signature has an invalid length. - */ - error ECDSAInvalidSignatureLength(uint256 length); - - /** - * @dev The signature has an S value that is in the upper half order. - */ - error ECDSAInvalidSignatureS(bytes32 s); - - /** - * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not - * return address(0) without also returning an error description. Errors are documented using an enum (error type) - * and a bytes32 providing additional information about the error. - * - * If no error is returned, then the address can be used for verification purposes. - * - * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. - * - * Documentation for signature generation: - * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] - * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] - */ - function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { - if (signature.length == 65) { - bytes32 r; - bytes32 s; - uint8 v; - // ecrecover takes the signature parameters, and the only way to get them - // currently is to use assembly. - /// @solidity memory-safe-assembly - assembly { - r := mload(add(signature, 0x20)) - s := mload(add(signature, 0x40)) - v := byte(0, mload(add(signature, 0x60))) - } - return tryRecover(hash, v, r, s); - } else { - return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); - } - } - - /** - * @dev Returns the address that signed a hashed message (`hash`) with - * `signature`. This address can then be used for verification purposes. - * - * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: - * this function rejects them by requiring the `s` value to be in the lower - * half order, and the `v` value to be either 27 or 28. - * - * IMPORTANT: `hash` _must_ be the result of a hash operation for the - * verification to be secure: it is possible to craft signatures that - * recover to arbitrary addresses for non-hashed data. A safe way to ensure - * this is by receiving a hash of the original message (which may otherwise - * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. - */ - function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { - (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); - _throwError(error, errorArg); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. - * - * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] - */ - function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { - unchecked { - bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); - // We do not check for an overflow here since the shift operation results in 0 or 1. - uint8 v = uint8((uint256(vs) >> 255) + 27); - return tryRecover(hash, v, r, s); - } - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. - */ - function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { - (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); - _throwError(error, errorArg); - return recovered; - } - - /** - * @dev Overload of {ECDSA-tryRecover} that receives the `v`, - * `r` and `s` signature fields separately. - */ - function tryRecover( - bytes32 hash, - uint8 v, - bytes32 r, - bytes32 s - ) internal pure returns (address, RecoverError, bytes32) { - // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature - // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines - // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most - // signatures from current libraries generate a unique signature with an s-value in the lower half order. - // - // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value - // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or - // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept - // these malleable signatures as well. - if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { - return (address(0), RecoverError.InvalidSignatureS, s); - } - - // If the signature is valid (and not malleable), return the signer address - address signer = ecrecover(hash, v, r, s); - if (signer == address(0)) { - return (address(0), RecoverError.InvalidSignature, bytes32(0)); - } - - return (signer, RecoverError.NoError, bytes32(0)); - } - - /** - * @dev Overload of {ECDSA-recover} that receives the `v`, - * `r` and `s` signature fields separately. - */ - function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { - (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); - _throwError(error, errorArg); - return recovered; - } - - /** - * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. - */ - function _throwError(RecoverError error, bytes32 errorArg) private pure { - if (error == RecoverError.NoError) { - return; // no error: do nothing - } else if (error == RecoverError.InvalidSignature) { - revert ECDSAInvalidSignature(); - } else if (error == RecoverError.InvalidSignatureLength) { - revert ECDSAInvalidSignatureLength(uint256(errorArg)); - } else if (error == RecoverError.InvalidSignatureS) { - revert ECDSAInvalidSignatureS(errorArg); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol deleted file mode 100644 index 8e548cd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/EIP712.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol) - -pragma solidity ^0.8.20; - -import {MessageHashUtils} from "./MessageHashUtils.sol"; -import {ShortStrings, ShortString} from "../ShortStrings.sol"; -import {IERC5267} from "../../interfaces/IERC5267.sol"; - -/** - * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. - * - * The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose - * encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract - * does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to - * produce the hash of their typed data using a combination of `abi.encode` and `keccak256`. - * - * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding - * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA - * ({_hashTypedDataV4}). - * - * The implementation of the domain separator was designed to be as efficient as possible while still properly updating - * the chain id to protect against replay attacks on an eventual fork of the chain. - * - * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method - * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. - * - * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain - * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the - * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. - * - * @custom:oz-upgrades-unsafe-allow state-variable-immutable - */ -abstract contract EIP712 is IERC5267 { - using ShortStrings for *; - - bytes32 private constant TYPE_HASH = - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); - - // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to - // invalidate the cached domain separator if the chain id changes. - bytes32 private immutable _cachedDomainSeparator; - uint256 private immutable _cachedChainId; - address private immutable _cachedThis; - - bytes32 private immutable _hashedName; - bytes32 private immutable _hashedVersion; - - ShortString private immutable _name; - ShortString private immutable _version; - string private _nameFallback; - string private _versionFallback; - - /** - * @dev Initializes the domain separator and parameter caches. - * - * The meaning of `name` and `version` is specified in - * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: - * - * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. - * - `version`: the current major version of the signing domain. - * - * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart - * contract upgrade]. - */ - constructor(string memory name, string memory version) { - _name = name.toShortStringWithFallback(_nameFallback); - _version = version.toShortStringWithFallback(_versionFallback); - _hashedName = keccak256(bytes(name)); - _hashedVersion = keccak256(bytes(version)); - - _cachedChainId = block.chainid; - _cachedDomainSeparator = _buildDomainSeparator(); - _cachedThis = address(this); - } - - /** - * @dev Returns the domain separator for the current chain. - */ - function _domainSeparatorV4() internal view returns (bytes32) { - if (address(this) == _cachedThis && block.chainid == _cachedChainId) { - return _cachedDomainSeparator; - } else { - return _buildDomainSeparator(); - } - } - - function _buildDomainSeparator() private view returns (bytes32) { - return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); - } - - /** - * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this - * function returns the hash of the fully encoded EIP712 message for this domain. - * - * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: - * - * ```solidity - * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( - * keccak256("Mail(address to,string contents)"), - * mailTo, - * keccak256(bytes(mailContents)) - * ))); - * address signer = ECDSA.recover(digest, signature); - * ``` - */ - function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { - return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); - } - - /** - * @dev See {IERC-5267}. - */ - function eip712Domain() - public - view - virtual - returns ( - bytes1 fields, - string memory name, - string memory version, - uint256 chainId, - address verifyingContract, - bytes32 salt, - uint256[] memory extensions - ) - { - return ( - hex"0f", // 01111 - _EIP712Name(), - _EIP712Version(), - block.chainid, - address(this), - bytes32(0), - new uint256[](0) - ); - } - - /** - * @dev The name parameter for the EIP712 domain. - * - * NOTE: By default this function reads _name which is an immutable value. - * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). - */ - // solhint-disable-next-line func-name-mixedcase - function _EIP712Name() internal view returns (string memory) { - return _name.toStringWithFallback(_nameFallback); - } - - /** - * @dev The version parameter for the EIP712 domain. - * - * NOTE: By default this function reads _version which is an immutable value. - * It only reads from storage if necessary (in case the value is too large to fit in a ShortString). - */ - // solhint-disable-next-line func-name-mixedcase - function _EIP712Version() internal view returns (string memory) { - return _version.toStringWithFallback(_versionFallback); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol deleted file mode 100644 index 8836693..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/cryptography/MessageHashUtils.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) - -pragma solidity ^0.8.20; - -import {Strings} from "../Strings.sol"; - -/** - * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. - * - * The library provides methods for generating a hash of a message that conforms to the - * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] - * specifications. - */ -library MessageHashUtils { - /** - * @dev Returns the keccak256 digest of an EIP-191 signed data with version - * `0x45` (`personal_sign` messages). - * - * The digest is calculated by prefixing a bytes32 `messageHash` with - * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the - * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. - * - * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with - * keccak256, although any bytes32 value can be safely used because the final digest will - * be re-hashed. - * - * See {ECDSA-recover}. - */ - function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash - mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix - digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) - } - } - - /** - * @dev Returns the keccak256 digest of an EIP-191 signed data with version - * `0x45` (`personal_sign` messages). - * - * The digest is calculated by prefixing an arbitrary `message` with - * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the - * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. - * - * See {ECDSA-recover}. - */ - function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { - return - keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); - } - - /** - * @dev Returns the keccak256 digest of an EIP-191 signed data with version - * `0x00` (data with intended validator). - * - * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended - * `validator` address. Then hashing the result. - * - * See {ECDSA-recover}. - */ - function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(hex"19_00", validator, data)); - } - - /** - * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). - * - * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with - * `\x19\x01` and hashing the result. It corresponds to the hash signed by the - * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. - * - * See {ECDSA-recover}. - */ - function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { - /// @solidity memory-safe-assembly - assembly { - let ptr := mload(0x40) - mstore(ptr, hex"19_01") - mstore(add(ptr, 0x02), domainSeparator) - mstore(add(ptr, 0x22), structHash) - digest := keccak256(ptr, 0x42) - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol deleted file mode 100644 index 1e77b60..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) - -pragma solidity ^0.8.20; - -import {IERC165} from "./IERC165.sol"; - -/** - * @dev Implementation of the {IERC165} interface. - * - * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check - * for the additional interface id that will be supported. For example: - * - * ```solidity - * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { - * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); - * } - * ``` - */ -abstract contract ERC165 is IERC165 { - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { - return interfaceId == type(IERC165).interfaceId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol deleted file mode 100644 index 7b52241..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol +++ /dev/null @@ -1,124 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165Checker.sol) - -pragma solidity ^0.8.20; - -import {IERC165} from "./IERC165.sol"; - -/** - * @dev Library used to query support of an interface declared via {IERC165}. - * - * Note that these functions return the actual result of the query: they do not - * `revert` if an interface is not supported. It is up to the caller to decide - * what to do in these cases. - */ -library ERC165Checker { - // As per the EIP-165 spec, no interface should ever match 0xffffffff - bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; - - /** - * @dev Returns true if `account` supports the {IERC165} interface. - */ - function supportsERC165(address account) internal view returns (bool) { - // Any contract that implements ERC165 must explicitly indicate support of - // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid - return - supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) && - !supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID); - } - - /** - * @dev Returns true if `account` supports the interface defined by - * `interfaceId`. Support for {IERC165} itself is queried automatically. - * - * See {IERC165-supportsInterface}. - */ - function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { - // query support of both ERC165 as per the spec and support of _interfaceId - return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId); - } - - /** - * @dev Returns a boolean array where each value corresponds to the - * interfaces passed in and whether they're supported or not. This allows - * you to batch check interfaces for a contract where your expectation - * is that some interfaces may not be supported. - * - * See {IERC165-supportsInterface}. - */ - function getSupportedInterfaces( - address account, - bytes4[] memory interfaceIds - ) internal view returns (bool[] memory) { - // an array of booleans corresponding to interfaceIds and whether they're supported or not - bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length); - - // query support of ERC165 itself - if (supportsERC165(account)) { - // query support of each interface in interfaceIds - for (uint256 i = 0; i < interfaceIds.length; i++) { - interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]); - } - } - - return interfaceIdsSupported; - } - - /** - * @dev Returns true if `account` supports all the interfaces defined in - * `interfaceIds`. Support for {IERC165} itself is queried automatically. - * - * Batch-querying can lead to gas savings by skipping repeated checks for - * {IERC165} support. - * - * See {IERC165-supportsInterface}. - */ - function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { - // query support of ERC165 itself - if (!supportsERC165(account)) { - return false; - } - - // query support of each interface in interfaceIds - for (uint256 i = 0; i < interfaceIds.length; i++) { - if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) { - return false; - } - } - - // all interfaces supported - return true; - } - - /** - * @notice Query if a contract implements an interface, does not check ERC165 support - * @param account The address of the contract to query for support of an interface - * @param interfaceId The interface identifier, as specified in ERC-165 - * @return true if the contract at account indicates support of the interface with - * identifier interfaceId, false otherwise - * @dev Assumes that account contains a contract that supports ERC165, otherwise - * the behavior of this method is undefined. This precondition can be checked - * with {supportsERC165}. - * - * Some precompiled contracts will falsely indicate support for a given interface, so caution - * should be exercised when using this function. - * - * Interface identification is specified in ERC-165. - */ - function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) { - // prepare call - bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId)); - - // perform static call - bool success; - uint256 returnSize; - uint256 returnValue; - assembly { - success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) - returnSize := returndatasize() - returnValue := mload(0x00) - } - - return success && returnSize >= 0x20 && returnValue > 0; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol deleted file mode 100644 index c09f31f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Interface of the ERC165 standard, as defined in the - * https://eips.ethereum.org/EIPS/eip-165[EIP]. - * - * Implementers can declare support of contract interfaces, which can then be - * queried by others ({ERC165Checker}). - * - * For an implementation, see {ERC165}. - */ -interface IERC165 { - /** - * @dev Returns true if this contract implements the interface defined by - * `interfaceId`. See the corresponding - * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] - * to learn more about how these ids are created. - * - * This function call must use less than 30 000 gas. - */ - function supportsInterface(bytes4 interfaceId) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol deleted file mode 100644 index 9681524..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/Math.sol +++ /dev/null @@ -1,415 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Standard math utilities missing in the Solidity language. - */ -library Math { - /** - * @dev Muldiv operation overflow. - */ - error MathOverflowedMulDiv(); - - enum Rounding { - Floor, // Toward negative infinity - Ceil, // Toward positive infinity - Trunc, // Toward zero - Expand // Away from zero - } - - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the subtraction of two unsigned integers, with an overflow flag. - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b > a) return (false, 0); - return (true, a - b); - } - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a / b); - } - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - unchecked { - if (b == 0) return (false, 0); - return (true, a % b); - } - } - - /** - * @dev Returns the largest of two numbers. - */ - function max(uint256 a, uint256 b) internal pure returns (uint256) { - return a > b ? a : b; - } - - /** - * @dev Returns the smallest of two numbers. - */ - function min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } - - /** - * @dev Returns the average of two numbers. The result is rounded towards - * zero. - */ - function average(uint256 a, uint256 b) internal pure returns (uint256) { - // (a + b) / 2 can overflow. - return (a & b) + (a ^ b) / 2; - } - - /** - * @dev Returns the ceiling of the division of two numbers. - * - * This differs from standard division with `/` in that it rounds towards infinity instead - * of rounding towards zero. - */ - function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { - if (b == 0) { - // Guarantee the same behavior as in a regular Solidity division. - return a / b; - } - - // (a + b - 1) / b can overflow on addition, so we distribute. - return a == 0 ? 0 : (a - 1) / b + 1; - } - - /** - * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or - * denominator == 0. - * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by - * Uniswap Labs also under MIT license. - */ - function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { - unchecked { - // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use - // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 - // variables such that product = prod1 * 2^256 + prod0. - uint256 prod0 = x * y; // Least significant 256 bits of the product - uint256 prod1; // Most significant 256 bits of the product - assembly { - let mm := mulmod(x, y, not(0)) - prod1 := sub(sub(mm, prod0), lt(mm, prod0)) - } - - // Handle non-overflow cases, 256 by 256 division. - if (prod1 == 0) { - // Solidity will revert if denominator == 0, unlike the div opcode on its own. - // The surrounding unchecked block does not change this fact. - // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. - return prod0 / denominator; - } - - // Make sure the result is less than 2^256. Also prevents denominator == 0. - if (denominator <= prod1) { - revert MathOverflowedMulDiv(); - } - - /////////////////////////////////////////////// - // 512 by 256 division. - /////////////////////////////////////////////// - - // Make division exact by subtracting the remainder from [prod1 prod0]. - uint256 remainder; - assembly { - // Compute remainder using mulmod. - remainder := mulmod(x, y, denominator) - - // Subtract 256 bit number from 512 bit number. - prod1 := sub(prod1, gt(remainder, prod0)) - prod0 := sub(prod0, remainder) - } - - // Factor powers of two out of denominator and compute largest power of two divisor of denominator. - // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. - - uint256 twos = denominator & (0 - denominator); - assembly { - // Divide denominator by twos. - denominator := div(denominator, twos) - - // Divide [prod1 prod0] by twos. - prod0 := div(prod0, twos) - - // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. - twos := add(div(sub(0, twos), twos), 1) - } - - // Shift in bits from prod1 into prod0. - prod0 |= prod1 * twos; - - // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such - // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for - // four bits. That is, denominator * inv = 1 mod 2^4. - uint256 inverse = (3 * denominator) ^ 2; - - // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also - // works in modular arithmetic, doubling the correct bits in each step. - inverse *= 2 - denominator * inverse; // inverse mod 2^8 - inverse *= 2 - denominator * inverse; // inverse mod 2^16 - inverse *= 2 - denominator * inverse; // inverse mod 2^32 - inverse *= 2 - denominator * inverse; // inverse mod 2^64 - inverse *= 2 - denominator * inverse; // inverse mod 2^128 - inverse *= 2 - denominator * inverse; // inverse mod 2^256 - - // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. - // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is - // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 - // is no longer required. - result = prod0 * inverse; - return result; - } - } - - /** - * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. - */ - function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { - uint256 result = mulDiv(x, y, denominator); - if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { - result += 1; - } - return result; - } - - /** - * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded - * towards zero. - * - * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). - */ - function sqrt(uint256 a) internal pure returns (uint256) { - if (a == 0) { - return 0; - } - - // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. - // - // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have - // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. - // - // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` - // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` - // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` - // - // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. - uint256 result = 1 << (log2(a) >> 1); - - // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, - // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at - // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision - // into the expected uint128 result. - unchecked { - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - result = (result + a / result) >> 1; - return min(result, a / result); - } - } - - /** - * @notice Calculates sqrt(a), following the selected rounding direction. - */ - function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = sqrt(a); - return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); - } - } - - /** - * @dev Return the log in base 2 of a positive value rounded towards zero. - * Returns 0 if given 0. - */ - function log2(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 128; - } - if (value >> 64 > 0) { - value >>= 64; - result += 64; - } - if (value >> 32 > 0) { - value >>= 32; - result += 32; - } - if (value >> 16 > 0) { - value >>= 16; - result += 16; - } - if (value >> 8 > 0) { - value >>= 8; - result += 8; - } - if (value >> 4 > 0) { - value >>= 4; - result += 4; - } - if (value >> 2 > 0) { - value >>= 2; - result += 2; - } - if (value >> 1 > 0) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 2, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log2(value); - return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); - } - } - - /** - * @dev Return the log in base 10 of a positive value rounded towards zero. - * Returns 0 if given 0. - */ - function log10(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >= 10 ** 64) { - value /= 10 ** 64; - result += 64; - } - if (value >= 10 ** 32) { - value /= 10 ** 32; - result += 32; - } - if (value >= 10 ** 16) { - value /= 10 ** 16; - result += 16; - } - if (value >= 10 ** 8) { - value /= 10 ** 8; - result += 8; - } - if (value >= 10 ** 4) { - value /= 10 ** 4; - result += 4; - } - if (value >= 10 ** 2) { - value /= 10 ** 2; - result += 2; - } - if (value >= 10 ** 1) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 10, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log10(value); - return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); - } - } - - /** - * @dev Return the log in base 256 of a positive value rounded towards zero. - * Returns 0 if given 0. - * - * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. - */ - function log256(uint256 value) internal pure returns (uint256) { - uint256 result = 0; - unchecked { - if (value >> 128 > 0) { - value >>= 128; - result += 16; - } - if (value >> 64 > 0) { - value >>= 64; - result += 8; - } - if (value >> 32 > 0) { - value >>= 32; - result += 4; - } - if (value >> 16 > 0) { - value >>= 16; - result += 2; - } - if (value >> 8 > 0) { - result += 1; - } - } - return result; - } - - /** - * @dev Return the log in base 256, following the selected rounding direction, of a positive value. - * Returns 0 if given 0. - */ - function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { - unchecked { - uint256 result = log256(value); - return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); - } - } - - /** - * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. - */ - function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { - return uint8(rounding) % 2 == 1; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol deleted file mode 100644 index 0ed458b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SafeCast.sol +++ /dev/null @@ -1,1153 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) -// This file was procedurally generated from scripts/generate/templates/SafeCast.js. - -pragma solidity ^0.8.20; - -/** - * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow - * checks. - * - * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can - * easily result in undesired exploitation or bugs, since developers usually - * assume that overflows raise errors. `SafeCast` restores this intuition by - * reverting the transaction when such an operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeCast { - /** - * @dev Value doesn't fit in an uint of `bits` size. - */ - error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); - - /** - * @dev An int value doesn't fit in an uint of `bits` size. - */ - error SafeCastOverflowedIntToUint(int256 value); - - /** - * @dev Value doesn't fit in an int of `bits` size. - */ - error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); - - /** - * @dev An uint value doesn't fit in an int of `bits` size. - */ - error SafeCastOverflowedUintToInt(uint256 value); - - /** - * @dev Returns the downcasted uint248 from uint256, reverting on - * overflow (when the input is greater than largest uint248). - * - * Counterpart to Solidity's `uint248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - */ - function toUint248(uint256 value) internal pure returns (uint248) { - if (value > type(uint248).max) { - revert SafeCastOverflowedUintDowncast(248, value); - } - return uint248(value); - } - - /** - * @dev Returns the downcasted uint240 from uint256, reverting on - * overflow (when the input is greater than largest uint240). - * - * Counterpart to Solidity's `uint240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - */ - function toUint240(uint256 value) internal pure returns (uint240) { - if (value > type(uint240).max) { - revert SafeCastOverflowedUintDowncast(240, value); - } - return uint240(value); - } - - /** - * @dev Returns the downcasted uint232 from uint256, reverting on - * overflow (when the input is greater than largest uint232). - * - * Counterpart to Solidity's `uint232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - */ - function toUint232(uint256 value) internal pure returns (uint232) { - if (value > type(uint232).max) { - revert SafeCastOverflowedUintDowncast(232, value); - } - return uint232(value); - } - - /** - * @dev Returns the downcasted uint224 from uint256, reverting on - * overflow (when the input is greater than largest uint224). - * - * Counterpart to Solidity's `uint224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - */ - function toUint224(uint256 value) internal pure returns (uint224) { - if (value > type(uint224).max) { - revert SafeCastOverflowedUintDowncast(224, value); - } - return uint224(value); - } - - /** - * @dev Returns the downcasted uint216 from uint256, reverting on - * overflow (when the input is greater than largest uint216). - * - * Counterpart to Solidity's `uint216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - */ - function toUint216(uint256 value) internal pure returns (uint216) { - if (value > type(uint216).max) { - revert SafeCastOverflowedUintDowncast(216, value); - } - return uint216(value); - } - - /** - * @dev Returns the downcasted uint208 from uint256, reverting on - * overflow (when the input is greater than largest uint208). - * - * Counterpart to Solidity's `uint208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - */ - function toUint208(uint256 value) internal pure returns (uint208) { - if (value > type(uint208).max) { - revert SafeCastOverflowedUintDowncast(208, value); - } - return uint208(value); - } - - /** - * @dev Returns the downcasted uint200 from uint256, reverting on - * overflow (when the input is greater than largest uint200). - * - * Counterpart to Solidity's `uint200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - */ - function toUint200(uint256 value) internal pure returns (uint200) { - if (value > type(uint200).max) { - revert SafeCastOverflowedUintDowncast(200, value); - } - return uint200(value); - } - - /** - * @dev Returns the downcasted uint192 from uint256, reverting on - * overflow (when the input is greater than largest uint192). - * - * Counterpart to Solidity's `uint192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - */ - function toUint192(uint256 value) internal pure returns (uint192) { - if (value > type(uint192).max) { - revert SafeCastOverflowedUintDowncast(192, value); - } - return uint192(value); - } - - /** - * @dev Returns the downcasted uint184 from uint256, reverting on - * overflow (when the input is greater than largest uint184). - * - * Counterpart to Solidity's `uint184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - */ - function toUint184(uint256 value) internal pure returns (uint184) { - if (value > type(uint184).max) { - revert SafeCastOverflowedUintDowncast(184, value); - } - return uint184(value); - } - - /** - * @dev Returns the downcasted uint176 from uint256, reverting on - * overflow (when the input is greater than largest uint176). - * - * Counterpart to Solidity's `uint176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - */ - function toUint176(uint256 value) internal pure returns (uint176) { - if (value > type(uint176).max) { - revert SafeCastOverflowedUintDowncast(176, value); - } - return uint176(value); - } - - /** - * @dev Returns the downcasted uint168 from uint256, reverting on - * overflow (when the input is greater than largest uint168). - * - * Counterpart to Solidity's `uint168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - */ - function toUint168(uint256 value) internal pure returns (uint168) { - if (value > type(uint168).max) { - revert SafeCastOverflowedUintDowncast(168, value); - } - return uint168(value); - } - - /** - * @dev Returns the downcasted uint160 from uint256, reverting on - * overflow (when the input is greater than largest uint160). - * - * Counterpart to Solidity's `uint160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - */ - function toUint160(uint256 value) internal pure returns (uint160) { - if (value > type(uint160).max) { - revert SafeCastOverflowedUintDowncast(160, value); - } - return uint160(value); - } - - /** - * @dev Returns the downcasted uint152 from uint256, reverting on - * overflow (when the input is greater than largest uint152). - * - * Counterpart to Solidity's `uint152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - */ - function toUint152(uint256 value) internal pure returns (uint152) { - if (value > type(uint152).max) { - revert SafeCastOverflowedUintDowncast(152, value); - } - return uint152(value); - } - - /** - * @dev Returns the downcasted uint144 from uint256, reverting on - * overflow (when the input is greater than largest uint144). - * - * Counterpart to Solidity's `uint144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - */ - function toUint144(uint256 value) internal pure returns (uint144) { - if (value > type(uint144).max) { - revert SafeCastOverflowedUintDowncast(144, value); - } - return uint144(value); - } - - /** - * @dev Returns the downcasted uint136 from uint256, reverting on - * overflow (when the input is greater than largest uint136). - * - * Counterpart to Solidity's `uint136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - */ - function toUint136(uint256 value) internal pure returns (uint136) { - if (value > type(uint136).max) { - revert SafeCastOverflowedUintDowncast(136, value); - } - return uint136(value); - } - - /** - * @dev Returns the downcasted uint128 from uint256, reverting on - * overflow (when the input is greater than largest uint128). - * - * Counterpart to Solidity's `uint128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - */ - function toUint128(uint256 value) internal pure returns (uint128) { - if (value > type(uint128).max) { - revert SafeCastOverflowedUintDowncast(128, value); - } - return uint128(value); - } - - /** - * @dev Returns the downcasted uint120 from uint256, reverting on - * overflow (when the input is greater than largest uint120). - * - * Counterpart to Solidity's `uint120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - */ - function toUint120(uint256 value) internal pure returns (uint120) { - if (value > type(uint120).max) { - revert SafeCastOverflowedUintDowncast(120, value); - } - return uint120(value); - } - - /** - * @dev Returns the downcasted uint112 from uint256, reverting on - * overflow (when the input is greater than largest uint112). - * - * Counterpart to Solidity's `uint112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - */ - function toUint112(uint256 value) internal pure returns (uint112) { - if (value > type(uint112).max) { - revert SafeCastOverflowedUintDowncast(112, value); - } - return uint112(value); - } - - /** - * @dev Returns the downcasted uint104 from uint256, reverting on - * overflow (when the input is greater than largest uint104). - * - * Counterpart to Solidity's `uint104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - */ - function toUint104(uint256 value) internal pure returns (uint104) { - if (value > type(uint104).max) { - revert SafeCastOverflowedUintDowncast(104, value); - } - return uint104(value); - } - - /** - * @dev Returns the downcasted uint96 from uint256, reverting on - * overflow (when the input is greater than largest uint96). - * - * Counterpart to Solidity's `uint96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - */ - function toUint96(uint256 value) internal pure returns (uint96) { - if (value > type(uint96).max) { - revert SafeCastOverflowedUintDowncast(96, value); - } - return uint96(value); - } - - /** - * @dev Returns the downcasted uint88 from uint256, reverting on - * overflow (when the input is greater than largest uint88). - * - * Counterpart to Solidity's `uint88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - */ - function toUint88(uint256 value) internal pure returns (uint88) { - if (value > type(uint88).max) { - revert SafeCastOverflowedUintDowncast(88, value); - } - return uint88(value); - } - - /** - * @dev Returns the downcasted uint80 from uint256, reverting on - * overflow (when the input is greater than largest uint80). - * - * Counterpart to Solidity's `uint80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - */ - function toUint80(uint256 value) internal pure returns (uint80) { - if (value > type(uint80).max) { - revert SafeCastOverflowedUintDowncast(80, value); - } - return uint80(value); - } - - /** - * @dev Returns the downcasted uint72 from uint256, reverting on - * overflow (when the input is greater than largest uint72). - * - * Counterpart to Solidity's `uint72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - */ - function toUint72(uint256 value) internal pure returns (uint72) { - if (value > type(uint72).max) { - revert SafeCastOverflowedUintDowncast(72, value); - } - return uint72(value); - } - - /** - * @dev Returns the downcasted uint64 from uint256, reverting on - * overflow (when the input is greater than largest uint64). - * - * Counterpart to Solidity's `uint64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - */ - function toUint64(uint256 value) internal pure returns (uint64) { - if (value > type(uint64).max) { - revert SafeCastOverflowedUintDowncast(64, value); - } - return uint64(value); - } - - /** - * @dev Returns the downcasted uint56 from uint256, reverting on - * overflow (when the input is greater than largest uint56). - * - * Counterpart to Solidity's `uint56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - */ - function toUint56(uint256 value) internal pure returns (uint56) { - if (value > type(uint56).max) { - revert SafeCastOverflowedUintDowncast(56, value); - } - return uint56(value); - } - - /** - * @dev Returns the downcasted uint48 from uint256, reverting on - * overflow (when the input is greater than largest uint48). - * - * Counterpart to Solidity's `uint48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - */ - function toUint48(uint256 value) internal pure returns (uint48) { - if (value > type(uint48).max) { - revert SafeCastOverflowedUintDowncast(48, value); - } - return uint48(value); - } - - /** - * @dev Returns the downcasted uint40 from uint256, reverting on - * overflow (when the input is greater than largest uint40). - * - * Counterpart to Solidity's `uint40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - */ - function toUint40(uint256 value) internal pure returns (uint40) { - if (value > type(uint40).max) { - revert SafeCastOverflowedUintDowncast(40, value); - } - return uint40(value); - } - - /** - * @dev Returns the downcasted uint32 from uint256, reverting on - * overflow (when the input is greater than largest uint32). - * - * Counterpart to Solidity's `uint32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - */ - function toUint32(uint256 value) internal pure returns (uint32) { - if (value > type(uint32).max) { - revert SafeCastOverflowedUintDowncast(32, value); - } - return uint32(value); - } - - /** - * @dev Returns the downcasted uint24 from uint256, reverting on - * overflow (when the input is greater than largest uint24). - * - * Counterpart to Solidity's `uint24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - */ - function toUint24(uint256 value) internal pure returns (uint24) { - if (value > type(uint24).max) { - revert SafeCastOverflowedUintDowncast(24, value); - } - return uint24(value); - } - - /** - * @dev Returns the downcasted uint16 from uint256, reverting on - * overflow (when the input is greater than largest uint16). - * - * Counterpart to Solidity's `uint16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - */ - function toUint16(uint256 value) internal pure returns (uint16) { - if (value > type(uint16).max) { - revert SafeCastOverflowedUintDowncast(16, value); - } - return uint16(value); - } - - /** - * @dev Returns the downcasted uint8 from uint256, reverting on - * overflow (when the input is greater than largest uint8). - * - * Counterpart to Solidity's `uint8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - */ - function toUint8(uint256 value) internal pure returns (uint8) { - if (value > type(uint8).max) { - revert SafeCastOverflowedUintDowncast(8, value); - } - return uint8(value); - } - - /** - * @dev Converts a signed int256 into an unsigned uint256. - * - * Requirements: - * - * - input must be greater than or equal to 0. - */ - function toUint256(int256 value) internal pure returns (uint256) { - if (value < 0) { - revert SafeCastOverflowedIntToUint(value); - } - return uint256(value); - } - - /** - * @dev Returns the downcasted int248 from int256, reverting on - * overflow (when the input is less than smallest int248 or - * greater than largest int248). - * - * Counterpart to Solidity's `int248` operator. - * - * Requirements: - * - * - input must fit into 248 bits - */ - function toInt248(int256 value) internal pure returns (int248 downcasted) { - downcasted = int248(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(248, value); - } - } - - /** - * @dev Returns the downcasted int240 from int256, reverting on - * overflow (when the input is less than smallest int240 or - * greater than largest int240). - * - * Counterpart to Solidity's `int240` operator. - * - * Requirements: - * - * - input must fit into 240 bits - */ - function toInt240(int256 value) internal pure returns (int240 downcasted) { - downcasted = int240(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(240, value); - } - } - - /** - * @dev Returns the downcasted int232 from int256, reverting on - * overflow (when the input is less than smallest int232 or - * greater than largest int232). - * - * Counterpart to Solidity's `int232` operator. - * - * Requirements: - * - * - input must fit into 232 bits - */ - function toInt232(int256 value) internal pure returns (int232 downcasted) { - downcasted = int232(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(232, value); - } - } - - /** - * @dev Returns the downcasted int224 from int256, reverting on - * overflow (when the input is less than smallest int224 or - * greater than largest int224). - * - * Counterpart to Solidity's `int224` operator. - * - * Requirements: - * - * - input must fit into 224 bits - */ - function toInt224(int256 value) internal pure returns (int224 downcasted) { - downcasted = int224(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(224, value); - } - } - - /** - * @dev Returns the downcasted int216 from int256, reverting on - * overflow (when the input is less than smallest int216 or - * greater than largest int216). - * - * Counterpart to Solidity's `int216` operator. - * - * Requirements: - * - * - input must fit into 216 bits - */ - function toInt216(int256 value) internal pure returns (int216 downcasted) { - downcasted = int216(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(216, value); - } - } - - /** - * @dev Returns the downcasted int208 from int256, reverting on - * overflow (when the input is less than smallest int208 or - * greater than largest int208). - * - * Counterpart to Solidity's `int208` operator. - * - * Requirements: - * - * - input must fit into 208 bits - */ - function toInt208(int256 value) internal pure returns (int208 downcasted) { - downcasted = int208(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(208, value); - } - } - - /** - * @dev Returns the downcasted int200 from int256, reverting on - * overflow (when the input is less than smallest int200 or - * greater than largest int200). - * - * Counterpart to Solidity's `int200` operator. - * - * Requirements: - * - * - input must fit into 200 bits - */ - function toInt200(int256 value) internal pure returns (int200 downcasted) { - downcasted = int200(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(200, value); - } - } - - /** - * @dev Returns the downcasted int192 from int256, reverting on - * overflow (when the input is less than smallest int192 or - * greater than largest int192). - * - * Counterpart to Solidity's `int192` operator. - * - * Requirements: - * - * - input must fit into 192 bits - */ - function toInt192(int256 value) internal pure returns (int192 downcasted) { - downcasted = int192(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(192, value); - } - } - - /** - * @dev Returns the downcasted int184 from int256, reverting on - * overflow (when the input is less than smallest int184 or - * greater than largest int184). - * - * Counterpart to Solidity's `int184` operator. - * - * Requirements: - * - * - input must fit into 184 bits - */ - function toInt184(int256 value) internal pure returns (int184 downcasted) { - downcasted = int184(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(184, value); - } - } - - /** - * @dev Returns the downcasted int176 from int256, reverting on - * overflow (when the input is less than smallest int176 or - * greater than largest int176). - * - * Counterpart to Solidity's `int176` operator. - * - * Requirements: - * - * - input must fit into 176 bits - */ - function toInt176(int256 value) internal pure returns (int176 downcasted) { - downcasted = int176(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(176, value); - } - } - - /** - * @dev Returns the downcasted int168 from int256, reverting on - * overflow (when the input is less than smallest int168 or - * greater than largest int168). - * - * Counterpart to Solidity's `int168` operator. - * - * Requirements: - * - * - input must fit into 168 bits - */ - function toInt168(int256 value) internal pure returns (int168 downcasted) { - downcasted = int168(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(168, value); - } - } - - /** - * @dev Returns the downcasted int160 from int256, reverting on - * overflow (when the input is less than smallest int160 or - * greater than largest int160). - * - * Counterpart to Solidity's `int160` operator. - * - * Requirements: - * - * - input must fit into 160 bits - */ - function toInt160(int256 value) internal pure returns (int160 downcasted) { - downcasted = int160(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(160, value); - } - } - - /** - * @dev Returns the downcasted int152 from int256, reverting on - * overflow (when the input is less than smallest int152 or - * greater than largest int152). - * - * Counterpart to Solidity's `int152` operator. - * - * Requirements: - * - * - input must fit into 152 bits - */ - function toInt152(int256 value) internal pure returns (int152 downcasted) { - downcasted = int152(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(152, value); - } - } - - /** - * @dev Returns the downcasted int144 from int256, reverting on - * overflow (when the input is less than smallest int144 or - * greater than largest int144). - * - * Counterpart to Solidity's `int144` operator. - * - * Requirements: - * - * - input must fit into 144 bits - */ - function toInt144(int256 value) internal pure returns (int144 downcasted) { - downcasted = int144(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(144, value); - } - } - - /** - * @dev Returns the downcasted int136 from int256, reverting on - * overflow (when the input is less than smallest int136 or - * greater than largest int136). - * - * Counterpart to Solidity's `int136` operator. - * - * Requirements: - * - * - input must fit into 136 bits - */ - function toInt136(int256 value) internal pure returns (int136 downcasted) { - downcasted = int136(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(136, value); - } - } - - /** - * @dev Returns the downcasted int128 from int256, reverting on - * overflow (when the input is less than smallest int128 or - * greater than largest int128). - * - * Counterpart to Solidity's `int128` operator. - * - * Requirements: - * - * - input must fit into 128 bits - */ - function toInt128(int256 value) internal pure returns (int128 downcasted) { - downcasted = int128(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(128, value); - } - } - - /** - * @dev Returns the downcasted int120 from int256, reverting on - * overflow (when the input is less than smallest int120 or - * greater than largest int120). - * - * Counterpart to Solidity's `int120` operator. - * - * Requirements: - * - * - input must fit into 120 bits - */ - function toInt120(int256 value) internal pure returns (int120 downcasted) { - downcasted = int120(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(120, value); - } - } - - /** - * @dev Returns the downcasted int112 from int256, reverting on - * overflow (when the input is less than smallest int112 or - * greater than largest int112). - * - * Counterpart to Solidity's `int112` operator. - * - * Requirements: - * - * - input must fit into 112 bits - */ - function toInt112(int256 value) internal pure returns (int112 downcasted) { - downcasted = int112(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(112, value); - } - } - - /** - * @dev Returns the downcasted int104 from int256, reverting on - * overflow (when the input is less than smallest int104 or - * greater than largest int104). - * - * Counterpart to Solidity's `int104` operator. - * - * Requirements: - * - * - input must fit into 104 bits - */ - function toInt104(int256 value) internal pure returns (int104 downcasted) { - downcasted = int104(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(104, value); - } - } - - /** - * @dev Returns the downcasted int96 from int256, reverting on - * overflow (when the input is less than smallest int96 or - * greater than largest int96). - * - * Counterpart to Solidity's `int96` operator. - * - * Requirements: - * - * - input must fit into 96 bits - */ - function toInt96(int256 value) internal pure returns (int96 downcasted) { - downcasted = int96(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(96, value); - } - } - - /** - * @dev Returns the downcasted int88 from int256, reverting on - * overflow (when the input is less than smallest int88 or - * greater than largest int88). - * - * Counterpart to Solidity's `int88` operator. - * - * Requirements: - * - * - input must fit into 88 bits - */ - function toInt88(int256 value) internal pure returns (int88 downcasted) { - downcasted = int88(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(88, value); - } - } - - /** - * @dev Returns the downcasted int80 from int256, reverting on - * overflow (when the input is less than smallest int80 or - * greater than largest int80). - * - * Counterpart to Solidity's `int80` operator. - * - * Requirements: - * - * - input must fit into 80 bits - */ - function toInt80(int256 value) internal pure returns (int80 downcasted) { - downcasted = int80(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(80, value); - } - } - - /** - * @dev Returns the downcasted int72 from int256, reverting on - * overflow (when the input is less than smallest int72 or - * greater than largest int72). - * - * Counterpart to Solidity's `int72` operator. - * - * Requirements: - * - * - input must fit into 72 bits - */ - function toInt72(int256 value) internal pure returns (int72 downcasted) { - downcasted = int72(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(72, value); - } - } - - /** - * @dev Returns the downcasted int64 from int256, reverting on - * overflow (when the input is less than smallest int64 or - * greater than largest int64). - * - * Counterpart to Solidity's `int64` operator. - * - * Requirements: - * - * - input must fit into 64 bits - */ - function toInt64(int256 value) internal pure returns (int64 downcasted) { - downcasted = int64(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(64, value); - } - } - - /** - * @dev Returns the downcasted int56 from int256, reverting on - * overflow (when the input is less than smallest int56 or - * greater than largest int56). - * - * Counterpart to Solidity's `int56` operator. - * - * Requirements: - * - * - input must fit into 56 bits - */ - function toInt56(int256 value) internal pure returns (int56 downcasted) { - downcasted = int56(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(56, value); - } - } - - /** - * @dev Returns the downcasted int48 from int256, reverting on - * overflow (when the input is less than smallest int48 or - * greater than largest int48). - * - * Counterpart to Solidity's `int48` operator. - * - * Requirements: - * - * - input must fit into 48 bits - */ - function toInt48(int256 value) internal pure returns (int48 downcasted) { - downcasted = int48(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(48, value); - } - } - - /** - * @dev Returns the downcasted int40 from int256, reverting on - * overflow (when the input is less than smallest int40 or - * greater than largest int40). - * - * Counterpart to Solidity's `int40` operator. - * - * Requirements: - * - * - input must fit into 40 bits - */ - function toInt40(int256 value) internal pure returns (int40 downcasted) { - downcasted = int40(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(40, value); - } - } - - /** - * @dev Returns the downcasted int32 from int256, reverting on - * overflow (when the input is less than smallest int32 or - * greater than largest int32). - * - * Counterpart to Solidity's `int32` operator. - * - * Requirements: - * - * - input must fit into 32 bits - */ - function toInt32(int256 value) internal pure returns (int32 downcasted) { - downcasted = int32(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(32, value); - } - } - - /** - * @dev Returns the downcasted int24 from int256, reverting on - * overflow (when the input is less than smallest int24 or - * greater than largest int24). - * - * Counterpart to Solidity's `int24` operator. - * - * Requirements: - * - * - input must fit into 24 bits - */ - function toInt24(int256 value) internal pure returns (int24 downcasted) { - downcasted = int24(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(24, value); - } - } - - /** - * @dev Returns the downcasted int16 from int256, reverting on - * overflow (when the input is less than smallest int16 or - * greater than largest int16). - * - * Counterpart to Solidity's `int16` operator. - * - * Requirements: - * - * - input must fit into 16 bits - */ - function toInt16(int256 value) internal pure returns (int16 downcasted) { - downcasted = int16(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(16, value); - } - } - - /** - * @dev Returns the downcasted int8 from int256, reverting on - * overflow (when the input is less than smallest int8 or - * greater than largest int8). - * - * Counterpart to Solidity's `int8` operator. - * - * Requirements: - * - * - input must fit into 8 bits - */ - function toInt8(int256 value) internal pure returns (int8 downcasted) { - downcasted = int8(value); - if (downcasted != value) { - revert SafeCastOverflowedIntDowncast(8, value); - } - } - - /** - * @dev Converts an unsigned uint256 into a signed int256. - * - * Requirements: - * - * - input must be less than or equal to maxInt256. - */ - function toInt256(uint256 value) internal pure returns (int256) { - // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive - if (value > uint256(type(int256).max)) { - revert SafeCastOverflowedUintToInt(value); - } - return int256(value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol deleted file mode 100644 index 66a6151..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/math/SignedMath.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) - -pragma solidity ^0.8.20; - -/** - * @dev Standard signed math utilities missing in the Solidity language. - */ -library SignedMath { - /** - * @dev Returns the largest of two signed numbers. - */ - function max(int256 a, int256 b) internal pure returns (int256) { - return a > b ? a : b; - } - - /** - * @dev Returns the smallest of two signed numbers. - */ - function min(int256 a, int256 b) internal pure returns (int256) { - return a < b ? a : b; - } - - /** - * @dev Returns the average of two signed numbers without overflow. - * The result is rounded towards zero. - */ - function average(int256 a, int256 b) internal pure returns (int256) { - // Formula from the book "Hacker's Delight" - int256 x = (a & b) + ((a ^ b) >> 1); - return x + (int256(uint256(x) >> 255) & (a ^ b)); - } - - /** - * @dev Returns the absolute unsigned value of a signed value. - */ - function abs(int256 n) internal pure returns (uint256) { - unchecked { - // must be unchecked in order to support `n = type(int256).min` - return uint256(n >= 0 ? n : -n); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol deleted file mode 100644 index 929ae7c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableMap.sol +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableMap.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. - -pragma solidity ^0.8.20; - -import {EnumerableSet} from "./EnumerableSet.sol"; - -/** - * @dev Library for managing an enumerable variant of Solidity's - * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] - * type. - * - * Maps have the following properties: - * - * - Entries are added, removed, and checked for existence in constant time - * (O(1)). - * - Entries are enumerated in O(n). No guarantees are made on the ordering. - * - * ```solidity - * contract Example { - * // Add the library methods - * using EnumerableMap for EnumerableMap.UintToAddressMap; - * - * // Declare a set state variable - * EnumerableMap.UintToAddressMap private myMap; - * } - * ``` - * - * The following map types are supported: - * - * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 - * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 - * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 - * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 - * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableMap. - * ==== - */ -library EnumerableMap { - using EnumerableSet for EnumerableSet.Bytes32Set; - - // To implement this library for multiple types with as little code repetition as possible, we write it in - // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, - // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. - // This means that we can only create new EnumerableMaps for types that fit in bytes32. - - /** - * @dev Query for a nonexistent map key. - */ - error EnumerableMapNonexistentKey(bytes32 key); - - struct Bytes32ToBytes32Map { - // Storage of keys - EnumerableSet.Bytes32Set _keys; - mapping(bytes32 key => bytes32) _values; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { - map._values[key] = value; - return map._keys.add(key); - } - - /** - * @dev Removes a key-value pair from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { - delete map._values[key]; - return map._keys.remove(key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { - return map._keys.contains(key); - } - - /** - * @dev Returns the number of key-value pairs in the map. O(1). - */ - function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { - return map._keys.length(); - } - - /** - * @dev Returns the key-value pair stored at position `index` in the map. O(1). - * - * Note that there are no guarantees on the ordering of entries inside the - * array, and it may change when more entries are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { - bytes32 key = map._keys.at(index); - return (key, map._values[key]); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { - bytes32 value = map._values[key]; - if (value == bytes32(0)) { - return (contains(map, key), bytes32(0)); - } else { - return (true, value); - } - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { - bytes32 value = map._values[key]; - if (value == 0 && !contains(map, key)) { - revert EnumerableMapNonexistentKey(key); - } - return value; - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { - return map._keys.values(); - } - - // UintToUintMap - - struct UintToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(key))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { - bytes32[] memory store = keys(map._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintToAddressMap - - struct UintToAddressMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { - return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { - return remove(map._inner, bytes32(key)); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { - return contains(map._inner, bytes32(key)); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(UintToAddressMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (uint256(key), address(uint160(uint256(value)))); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); - return (success, address(uint160(uint256(value)))); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { - return address(uint160(uint256(get(map._inner, bytes32(key))))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { - bytes32[] memory store = keys(map._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressToUintMap - - struct AddressToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { - return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(AddressToUintMap storage map, address key) internal returns (bool) { - return remove(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(AddressToUintMap storage map, address key) internal view returns (bool) { - return contains(map._inner, bytes32(uint256(uint160(key)))); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(AddressToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (address(uint160(uint256(key))), uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(AddressToUintMap storage map, address key) internal view returns (uint256) { - return uint256(get(map._inner, bytes32(uint256(uint160(key))))); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(AddressToUintMap storage map) internal view returns (address[] memory) { - bytes32[] memory store = keys(map._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // Bytes32ToUintMap - - struct Bytes32ToUintMap { - Bytes32ToBytes32Map _inner; - } - - /** - * @dev Adds a key-value pair to a map, or updates the value for an existing - * key. O(1). - * - * Returns true if the key was added to the map, that is if it was not - * already present. - */ - function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { - return set(map._inner, key, bytes32(value)); - } - - /** - * @dev Removes a value from a map. O(1). - * - * Returns true if the key was removed from the map, that is if it was present. - */ - function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { - return remove(map._inner, key); - } - - /** - * @dev Returns true if the key is in the map. O(1). - */ - function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { - return contains(map._inner, key); - } - - /** - * @dev Returns the number of elements in the map. O(1). - */ - function length(Bytes32ToUintMap storage map) internal view returns (uint256) { - return length(map._inner); - } - - /** - * @dev Returns the element stored at position `index` in the map. O(1). - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { - (bytes32 key, bytes32 value) = at(map._inner, index); - return (key, uint256(value)); - } - - /** - * @dev Tries to returns the value associated with `key`. O(1). - * Does not revert if `key` is not in the map. - */ - function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { - (bool success, bytes32 value) = tryGet(map._inner, key); - return (success, uint256(value)); - } - - /** - * @dev Returns the value associated with `key`. O(1). - * - * Requirements: - * - * - `key` must be in the map. - */ - function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { - return uint256(get(map._inner, key)); - } - - /** - * @dev Return the an array containing all the keys - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { - bytes32[] memory store = keys(map._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol deleted file mode 100644 index 4c7fc5e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol +++ /dev/null @@ -1,378 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) -// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. - -pragma solidity ^0.8.20; - -/** - * @dev Library for managing - * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive - * types. - * - * Sets have the following properties: - * - * - Elements are added, removed, and checked for existence in constant time - * (O(1)). - * - Elements are enumerated in O(n). No guarantees are made on the ordering. - * - * ```solidity - * contract Example { - * // Add the library methods - * using EnumerableSet for EnumerableSet.AddressSet; - * - * // Declare a set state variable - * EnumerableSet.AddressSet private mySet; - * } - * ``` - * - * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) - * and `uint256` (`UintSet`) are supported. - * - * [WARNING] - * ==== - * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure - * unusable. - * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. - * - * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an - * array of EnumerableSet. - * ==== - */ -library EnumerableSet { - // To implement this library for multiple types with as little code - // repetition as possible, we write it in terms of a generic Set type with - // bytes32 values. - // The Set implementation uses private functions, and user-facing - // implementations (such as AddressSet) are just wrappers around the - // underlying Set. - // This means that we can only create new EnumerableSets for types that fit - // in bytes32. - - struct Set { - // Storage of set values - bytes32[] _values; - // Position is the index of the value in the `values` array plus 1. - // Position 0 is used to mean a value is not in the set. - mapping(bytes32 value => uint256) _positions; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function _add(Set storage set, bytes32 value) private returns (bool) { - if (!_contains(set, value)) { - set._values.push(value); - // The value is stored at length-1, but we add 1 to all indexes - // and use 0 as a sentinel value - set._positions[value] = set._values.length; - return true; - } else { - return false; - } - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function _remove(Set storage set, bytes32 value) private returns (bool) { - // We cache the value's position to prevent multiple reads from the same storage slot - uint256 position = set._positions[value]; - - if (position != 0) { - // Equivalent to contains(set, value) - // To delete an element from the _values array in O(1), we swap the element to delete with the last one in - // the array, and then remove the last element (sometimes called as 'swap and pop'). - // This modifies the order of the array, as noted in {at}. - - uint256 valueIndex = position - 1; - uint256 lastIndex = set._values.length - 1; - - if (valueIndex != lastIndex) { - bytes32 lastValue = set._values[lastIndex]; - - // Move the lastValue to the index where the value to delete is - set._values[valueIndex] = lastValue; - // Update the tracked position of the lastValue (that was just moved) - set._positions[lastValue] = position; - } - - // Delete the slot where the moved value was stored - set._values.pop(); - - // Delete the tracked position for the deleted slot - delete set._positions[value]; - - return true; - } else { - return false; - } - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function _contains(Set storage set, bytes32 value) private view returns (bool) { - return set._positions[value] != 0; - } - - /** - * @dev Returns the number of values on the set. O(1). - */ - function _length(Set storage set) private view returns (uint256) { - return set._values.length; - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function _at(Set storage set, uint256 index) private view returns (bytes32) { - return set._values[index]; - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function _values(Set storage set) private view returns (bytes32[] memory) { - return set._values; - } - - // Bytes32Set - - struct Bytes32Set { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _add(set._inner, value); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { - return _remove(set._inner, value); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { - return _contains(set._inner, value); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(Bytes32Set storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { - return _at(set._inner, index); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { - bytes32[] memory store = _values(set._inner); - bytes32[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // AddressSet - - struct AddressSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(AddressSet storage set, address value) internal returns (bool) { - return _add(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(AddressSet storage set, address value) internal returns (bool) { - return _remove(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(AddressSet storage set, address value) internal view returns (bool) { - return _contains(set._inner, bytes32(uint256(uint160(value)))); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(AddressSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(AddressSet storage set, uint256 index) internal view returns (address) { - return address(uint160(uint256(_at(set._inner, index)))); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(AddressSet storage set) internal view returns (address[] memory) { - bytes32[] memory store = _values(set._inner); - address[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } - - // UintSet - - struct UintSet { - Set _inner; - } - - /** - * @dev Add a value to a set. O(1). - * - * Returns true if the value was added to the set, that is if it was not - * already present. - */ - function add(UintSet storage set, uint256 value) internal returns (bool) { - return _add(set._inner, bytes32(value)); - } - - /** - * @dev Removes a value from a set. O(1). - * - * Returns true if the value was removed from the set, that is if it was - * present. - */ - function remove(UintSet storage set, uint256 value) internal returns (bool) { - return _remove(set._inner, bytes32(value)); - } - - /** - * @dev Returns true if the value is in the set. O(1). - */ - function contains(UintSet storage set, uint256 value) internal view returns (bool) { - return _contains(set._inner, bytes32(value)); - } - - /** - * @dev Returns the number of values in the set. O(1). - */ - function length(UintSet storage set) internal view returns (uint256) { - return _length(set._inner); - } - - /** - * @dev Returns the value stored at position `index` in the set. O(1). - * - * Note that there are no guarantees on the ordering of values inside the - * array, and it may change when more values are added or removed. - * - * Requirements: - * - * - `index` must be strictly less than {length}. - */ - function at(UintSet storage set, uint256 index) internal view returns (uint256) { - return uint256(_at(set._inner, index)); - } - - /** - * @dev Return the entire set in an array - * - * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed - * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that - * this function has an unbounded cost, and using it as part of a state-changing function may render the function - * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. - */ - function values(UintSet storage set) internal view returns (uint256[] memory) { - bytes32[] memory store = _values(set._inner); - uint256[] memory result; - - /// @solidity memory-safe-assembly - assembly { - result := store - } - - return result; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol deleted file mode 100644 index 5c11137..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vendor/solidity-cborutils/v2.0.0/CBOR.sol +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import "../../@ensdomains/buffer/v0.1.0/Buffer.sol"; - -/** -* @dev A library for populating CBOR encoded payload in Solidity. -* -* https://datatracker.ietf.org/doc/html/rfc7049 -* -* The library offers various write* and start* methods to encode values of different types. -* The resulted buffer can be obtained with data() method. -* Encoding of primitive types is staightforward, whereas encoding of sequences can result -* in an invalid CBOR if start/write/end flow is violated. -* For the purpose of gas saving, the library does not verify start/write/end flow internally, -* except for nested start/end pairs. -*/ - -library CBOR { - using Buffer for Buffer.buffer; - - struct CBORBuffer { - Buffer.buffer buf; - uint256 depth; - } - - uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; - uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; - uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; - uint8 private constant MAJOR_TYPE_TAG = 6; - uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - - uint8 private constant TAG_TYPE_BIGNUM = 2; - uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; - - uint8 private constant CBOR_FALSE = 20; - uint8 private constant CBOR_TRUE = 21; - uint8 private constant CBOR_NULL = 22; - uint8 private constant CBOR_UNDEFINED = 23; - - function create(uint256 capacity) internal pure returns(CBORBuffer memory cbor) { - Buffer.init(cbor.buf, capacity); - cbor.depth = 0; - return cbor; - } - - function data(CBORBuffer memory buf) internal pure returns(bytes memory) { - require(buf.depth == 0, "Invalid CBOR"); - return buf.buf.buf; - } - - function writeUInt256(CBORBuffer memory buf, uint256 value) internal pure { - buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); - writeBytes(buf, abi.encode(value)); - } - - function writeInt256(CBORBuffer memory buf, int256 value) internal pure { - if (value < 0) { - buf.buf.appendUint8( - uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM) - ); - writeBytes(buf, abi.encode(uint256(-1 - value))); - } else { - writeUInt256(buf, uint256(value)); - } - } - - function writeUInt64(CBORBuffer memory buf, uint64 value) internal pure { - writeFixedNumeric(buf, MAJOR_TYPE_INT, value); - } - - function writeInt64(CBORBuffer memory buf, int64 value) internal pure { - if(value >= 0) { - writeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); - } else{ - writeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value)); - } - } - - function writeBytes(CBORBuffer memory buf, bytes memory value) internal pure { - writeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); - buf.buf.append(value); - } - - function writeString(CBORBuffer memory buf, string memory value) internal pure { - writeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); - buf.buf.append(bytes(value)); - } - - function writeBool(CBORBuffer memory buf, bool value) internal pure { - writeContentFree(buf, value ? CBOR_TRUE : CBOR_FALSE); - } - - function writeNull(CBORBuffer memory buf) internal pure { - writeContentFree(buf, CBOR_NULL); - } - - function writeUndefined(CBORBuffer memory buf) internal pure { - writeContentFree(buf, CBOR_UNDEFINED); - } - - function startArray(CBORBuffer memory buf) internal pure { - writeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); - buf.depth += 1; - } - - function startFixedArray(CBORBuffer memory buf, uint64 length) internal pure { - writeDefiniteLengthType(buf, MAJOR_TYPE_ARRAY, length); - } - - function startMap(CBORBuffer memory buf) internal pure { - writeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); - buf.depth += 1; - } - - function startFixedMap(CBORBuffer memory buf, uint64 length) internal pure { - writeDefiniteLengthType(buf, MAJOR_TYPE_MAP, length); - } - - function endSequence(CBORBuffer memory buf) internal pure { - writeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); - buf.depth -= 1; - } - - function writeKVString(CBORBuffer memory buf, string memory key, string memory value) internal pure { - writeString(buf, key); - writeString(buf, value); - } - - function writeKVBytes(CBORBuffer memory buf, string memory key, bytes memory value) internal pure { - writeString(buf, key); - writeBytes(buf, value); - } - - function writeKVUInt256(CBORBuffer memory buf, string memory key, uint256 value) internal pure { - writeString(buf, key); - writeUInt256(buf, value); - } - - function writeKVInt256(CBORBuffer memory buf, string memory key, int256 value) internal pure { - writeString(buf, key); - writeInt256(buf, value); - } - - function writeKVUInt64(CBORBuffer memory buf, string memory key, uint64 value) internal pure { - writeString(buf, key); - writeUInt64(buf, value); - } - - function writeKVInt64(CBORBuffer memory buf, string memory key, int64 value) internal pure { - writeString(buf, key); - writeInt64(buf, value); - } - - function writeKVBool(CBORBuffer memory buf, string memory key, bool value) internal pure { - writeString(buf, key); - writeBool(buf, value); - } - - function writeKVNull(CBORBuffer memory buf, string memory key) internal pure { - writeString(buf, key); - writeNull(buf); - } - - function writeKVUndefined(CBORBuffer memory buf, string memory key) internal pure { - writeString(buf, key); - writeUndefined(buf); - } - - function writeKVMap(CBORBuffer memory buf, string memory key) internal pure { - writeString(buf, key); - startMap(buf); - } - - function writeKVArray(CBORBuffer memory buf, string memory key) internal pure { - writeString(buf, key); - startArray(buf); - } - - function writeFixedNumeric( - CBORBuffer memory buf, - uint8 major, - uint64 value - ) private pure { - if (value <= 23) { - buf.buf.appendUint8(uint8((major << 5) | value)); - } else if (value <= 0xFF) { - buf.buf.appendUint8(uint8((major << 5) | 24)); - buf.buf.appendInt(value, 1); - } else if (value <= 0xFFFF) { - buf.buf.appendUint8(uint8((major << 5) | 25)); - buf.buf.appendInt(value, 2); - } else if (value <= 0xFFFFFFFF) { - buf.buf.appendUint8(uint8((major << 5) | 26)); - buf.buf.appendInt(value, 4); - } else { - buf.buf.appendUint8(uint8((major << 5) | 27)); - buf.buf.appendInt(value, 8); - } - } - - function writeIndefiniteLengthType(CBORBuffer memory buf, uint8 major) - private - pure - { - buf.buf.appendUint8(uint8((major << 5) | 31)); - } - - function writeDefiniteLengthType(CBORBuffer memory buf, uint8 major, uint64 length) - private - pure - { - writeFixedNumeric(buf, major, length); - } - - function writeContentFree(CBORBuffer memory buf, uint8 value) private pure { - buf.buf.appendUint8(uint8((MAJOR_TYPE_CONTENT_FREE << 5) | value)); - } -} \ No newline at end of file diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol deleted file mode 100644 index 4d49cf2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/AuthorizedReceiver.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {IAuthorizedReceiver} from "./interfaces/IAuthorizedReceiver.sol"; - -abstract contract AuthorizedReceiver is IAuthorizedReceiver { - using EnumerableSet for EnumerableSet.AddressSet; - - event AuthorizedSendersChanged(address[] senders, address changedBy); - - error EmptySendersList(); - error UnauthorizedSender(); - error NotAllowedToSetSenders(); - - EnumerableSet.AddressSet private s_authorizedSenders; - address[] private s_authorizedSendersList; - - /** - * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. - * @param senders The addresses of the authorized Chainlink node - */ - function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter { - if (senders.length == 0) { - revert EmptySendersList(); - } - for (uint256 i = 0; i < s_authorizedSendersList.length; i++) { - s_authorizedSenders.remove(s_authorizedSendersList[i]); - } - for (uint256 i = 0; i < senders.length; i++) { - s_authorizedSenders.add(senders[i]); - } - s_authorizedSendersList = senders; - emit AuthorizedSendersChanged(senders, msg.sender); - } - - /** - * @notice Retrieve a list of authorized senders - * @return array of addresses - */ - function getAuthorizedSenders() public view override returns (address[] memory) { - return s_authorizedSendersList; - } - - /** - * @notice Use this to check if a node is authorized for fulfilling requests - * @param sender The address of the Chainlink node - * @return The authorization status of the node - */ - function isAuthorizedSender(address sender) public view override returns (bool) { - return s_authorizedSenders.contains(sender); - } - - /** - * @notice customizable guard of who can update the authorized sender list - * @return bool whether sender can update authorized sender list - */ - function _canSetAuthorizedSenders() internal virtual returns (bool); - - /** - * @notice validates the sender is an authorized sender - */ - function _validateIsAuthorizedSender() internal view { - if (!isAuthorizedSender(msg.sender)) { - revert UnauthorizedSender(); - } - } - - /** - * @notice prevents non-authorized addresses from calling this method - */ - modifier validateAuthorizedSender() { - _validateIsAuthorizedSender(); - _; - } - - /** - * @notice prevents non-authorized addresses from calling this method - */ - modifier validateAuthorizedSenderSetter() { - if (!_canSetAuthorizedSenders()) { - revert NotAllowedToSetSenders(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol deleted file mode 100644 index cf29f14..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchBlockhashStore.sol +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity 0.8.19; - -import {ChainSpecificUtil} from "../ChainSpecificUtil.sol"; - -/** - * @title BatchBlockhashStore - * @notice The BatchBlockhashStore contract acts as a proxy to write many blockhashes to the - * provided BlockhashStore contract efficiently in a single transaction. This results - * in plenty of gas savings and higher throughput of blockhash storage, which is desirable - * in times of high network congestion. - */ -contract BatchBlockhashStore { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - BlockhashStore public immutable BHS; - - constructor(address blockhashStoreAddr) { - BHS = BlockhashStore(blockhashStoreAddr); - } - - /** - * @notice stores blockhashes of the given block numbers in the configured blockhash store, assuming - * they are availble though the blockhash() instruction. - * @param blockNumbers the block numbers to store the blockhashes of. Must be available via the - * blockhash() instruction, otherwise this function call will revert. - */ - function store(uint256[] memory blockNumbers) public { - for (uint256 i = 0; i < blockNumbers.length; i++) { - // skip the block if it's not storeable, the caller will have to check - // after the transaction is mined to see if the blockhash was truly stored. - if (!_storeableBlock(blockNumbers[i])) { - continue; - } - BHS.store(blockNumbers[i]); - } - } - - /** - * @notice stores blockhashes after verifying blockheader of child/subsequent block - * @param blockNumbers the block numbers whose blockhashes should be stored, in decreasing order - * @param headers the rlp-encoded block headers of blockNumbers[i] + 1. - */ - function storeVerifyHeader(uint256[] memory blockNumbers, bytes[] memory headers) public { - // solhint-disable-next-line gas-custom-errors - require(blockNumbers.length == headers.length, "input array arg lengths mismatch"); - for (uint256 i = 0; i < blockNumbers.length; i++) { - BHS.storeVerifyHeader(blockNumbers[i], headers[i]); - } - } - - /** - * @notice retrieves blockhashes of all the given block numbers from the blockhash store, if available. - * @param blockNumbers array of block numbers to fetch blockhashes for - * @return blockhashes array of block hashes corresponding to each block number provided in the `blockNumbers` - * param. If the blockhash is not found, 0x0 is returned instead of the real blockhash, indicating - * that it is not in the blockhash store. - */ - function getBlockhashes(uint256[] memory blockNumbers) external view returns (bytes32[] memory) { - bytes32[] memory blockHashes = new bytes32[](blockNumbers.length); - for (uint256 i = 0; i < blockNumbers.length; i++) { - try BHS.getBlockhash(blockNumbers[i]) returns (bytes32 bh) { - blockHashes[i] = bh; - } catch Error(string memory /* reason */) { - blockHashes[i] = 0x0; - } - } - return blockHashes; - } - - /** - * @notice returns true if and only if the given block number's blockhash can be retrieved - * using the blockhash() instruction. - * @param blockNumber the block number to check if it's storeable with blockhash() - */ - function _storeableBlock(uint256 blockNumber) private view returns (bool) { - // handle edge case on simulated chains which possibly have < 256 blocks total. - return - ChainSpecificUtil._getBlockNumber() <= 256 ? true : blockNumber >= (ChainSpecificUtil._getBlockNumber() - 256); - } -} - -// solhint-disable-next-line interface-starts-with-i -interface BlockhashStore { - function storeVerifyHeader(uint256 n, bytes memory header) external; - - function store(uint256 n) external; - - function getBlockhash(uint256 n) external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol deleted file mode 100644 index bcea106..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/BatchVRFCoordinatorV2.sol +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity 0.8.6; - -import {VRFTypes} from "./VRFTypes.sol"; - -/** - * @title BatchVRFCoordinatorV2 - * @notice The BatchVRFCoordinatorV2 contract acts as a proxy to write many random responses to the - * provided VRFCoordinatorV2 contract efficiently in a single transaction. - */ -contract BatchVRFCoordinatorV2 { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - VRFCoordinatorV2 public immutable COORDINATOR; - - event ErrorReturned(uint256 indexed requestId, string reason); - event RawErrorReturned(uint256 indexed requestId, bytes lowLevelData); - - constructor(address coordinatorAddr) { - COORDINATOR = VRFCoordinatorV2(coordinatorAddr); - } - - /** - * @notice fulfills multiple randomness requests with the provided proofs and commitments. - * @param proofs the randomness proofs generated by the VRF provider. - * @param rcs the request commitments corresponding to the randomness proofs. - */ - function fulfillRandomWords(VRFTypes.Proof[] calldata proofs, VRFTypes.RequestCommitment[] memory rcs) external { - // solhint-disable-next-line gas-custom-errors - require(proofs.length == rcs.length, "input array arg lengths mismatch"); - for (uint256 i = 0; i < proofs.length; i++) { - try COORDINATOR.fulfillRandomWords(proofs[i], rcs[i]) returns (uint96 /* payment */) { - continue; - } catch Error(string memory reason) { - uint256 requestId = _getRequestIdFromProof(proofs[i]); - emit ErrorReturned(requestId, reason); - } catch (bytes memory lowLevelData) { - uint256 requestId = _getRequestIdFromProof(proofs[i]); - emit RawErrorReturned(requestId, lowLevelData); - } - } - } - - /** - * @notice Returns the proving key hash associated with this public key. - * @param publicKey the key to return the hash of. - */ - function _hashOfKey(uint256[2] memory publicKey) internal pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Returns the request ID of the request associated with the given proof. - * @param proof the VRF proof provided by the VRF oracle. - */ - function _getRequestIdFromProof(VRFTypes.Proof memory proof) internal pure returns (uint256) { - bytes32 keyHash = _hashOfKey(proof.pk); - return uint256(keccak256(abi.encode(keyHash, proof.seed))); - } -} - -// solhint-disable-next-line interface-starts-with-i -interface VRFCoordinatorV2 { - function fulfillRandomWords( - VRFTypes.Proof calldata proof, - VRFTypes.RequestCommitment memory rc - ) external returns (uint96); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol deleted file mode 100644 index 161800f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/KeepersVRFConsumer.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "../automation/interfaces/AutomationCompatibleInterface.sol"; -import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; -import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; - -// solhint-disable chainlink-solidity/prefix-immutable-variables-with-i - -/** - * @title KeepersVRFConsumer - * @notice KeepersVRFConsumer is a Chainlink Keepers compatible contract that also acts as a - * VRF V2 requester and consumer. In particular, a random words request is made when `performUpkeep` - * is called in a cadence provided by the upkeep interval. - */ -contract KeepersVRFConsumer is KeeperCompatibleInterface, VRFConsumerBaseV2 { - // Upkeep interval in seconds. This contract's performUpkeep method will - // be called by the Keepers network roughly every UPKEEP_INTERVAL seconds. - uint256 public immutable UPKEEP_INTERVAL; - - // VRF V2 information, provided upon contract construction. - VRFCoordinatorV2Interface public immutable COORDINATOR; - uint64 public immutable SUBSCRIPTION_ID; - uint16 public immutable REQUEST_CONFIRMATIONS; - bytes32 public immutable KEY_HASH; - - // Contract state, updated in performUpkeep and fulfillRandomWords. - uint256 public s_lastTimeStamp; - uint256 public s_vrfRequestCounter; - uint256 public s_vrfResponseCounter; - - struct RequestRecord { - uint256 requestId; - bool fulfilled; - uint32 callbackGasLimit; - uint256 randomness; - } - mapping(uint256 => RequestRecord) public s_requests; /* request ID */ /* request record */ - - constructor( - address vrfCoordinator, - uint64 subscriptionId, - bytes32 keyHash, - uint16 requestConfirmations, - uint256 upkeepInterval - ) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - SUBSCRIPTION_ID = subscriptionId; - REQUEST_CONFIRMATIONS = requestConfirmations; - KEY_HASH = keyHash; - UPKEEP_INTERVAL = upkeepInterval; - - s_lastTimeStamp = block.timestamp; - s_vrfRequestCounter = 0; - s_vrfResponseCounter = 0; - } - - /** - * @notice Returns true if and only if at least UPKEEP_INTERVAL seconds have elapsed - * since the last upkeep or since construction of the contract. - * @return upkeepNeeded true if and only if at least UPKEEP_INTERVAL seconds have elapsed since the last upkeep or since construction - * of the contract. - */ - // solhint-disable-next-line chainlink-solidity/explicit-returns - function checkUpkeep( - bytes calldata /* checkData */ - ) external view override returns (bool upkeepNeeded, bytes memory /* performData */) { - upkeepNeeded = (block.timestamp - s_lastTimeStamp) > UPKEEP_INTERVAL; - } - - /** - * @notice Requests random words from the VRF coordinator if UPKEEP_INTERVAL seconds have elapsed - * since the last upkeep or since construction of the contract. - */ - function performUpkeep(bytes calldata /* performData */) external override { - if ((block.timestamp - s_lastTimeStamp) > UPKEEP_INTERVAL) { - s_lastTimeStamp = block.timestamp; - - _requestRandomWords(); - } - } - - /** - * @notice VRF callback implementation - * @param requestId the VRF V2 request ID, provided at request time. - * @param randomWords the randomness provided by Chainlink VRF. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - // Check that the request exists. If not, revert. - RequestRecord memory record = s_requests[requestId]; - // solhint-disable-next-line gas-custom-errors - require(record.requestId == requestId, "request ID not found in map"); - - // Update the randomness in the record, and increment the response counter. - s_requests[requestId].randomness = randomWords[0]; - s_vrfResponseCounter++; - } - - /** - * @notice Requests random words from Chainlink VRF. - */ - function _requestRandomWords() internal { - uint256 requestId = COORDINATOR.requestRandomWords( - KEY_HASH, - SUBSCRIPTION_ID, - REQUEST_CONFIRMATIONS, - 150000, // callback gas limit - 1 // num words - ); - s_requests[requestId] = RequestRecord({ - requestId: requestId, - fulfilled: false, - callbackGasLimit: 150000, - randomness: 0 - }); - s_vrfRequestCounter++; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol deleted file mode 100644 index 7f11569..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRF.sol +++ /dev/null @@ -1,588 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** **************************************************************************** - * @notice Verification of verifiable-random-function (VRF) proofs, following - * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. - - * @dev Bibliographic references: - - * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft - * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 - - * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology - * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf - * **************************************************************************** - * @dev USAGE - - * @dev The main entry point is _randomValueFromVRFProof. See its docstring. - * **************************************************************************** - * @dev PURPOSE - - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is computationally indistinguishable to her from a uniform - * @dev random sample from the output space. - - * @dev The purpose of this contract is to perform that verification. - * **************************************************************************** - * @dev DESIGN NOTES - - * @dev The VRF algorithm verified here satisfies the full uniqueness, full - * @dev collision resistance, and full pseudo-randomness security properties. - * @dev See "SECURITY PROPERTIES" below, and - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 - - * @dev An elliptic curve point is generally represented in the solidity code - * @dev as a uint256[2], corresponding to its affine coordinates in - * @dev GF(FIELD_SIZE). - - * @dev For the sake of efficiency, this implementation deviates from the spec - * @dev in some minor ways: - - * @dev - Keccak hash rather than the SHA256 hash recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev Keccak costs much less gas on the EVM, and provides similar security. - - * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER - - * @dev - _hashToCurve recursively hashes until it finds a curve x-ordinate. On - * @dev the EVM, this is slightly more efficient than the recommendation in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - * @dev step 5, to concatenate with a nonce then hash, and rehash with the - * @dev nonce updated until a valid x-ordinate is found. - - * @dev - _hashToCurve does not include a cipher version string or the byte 0x1 - * @dev in the hash message, as recommended in step 5.B of the draft - * @dev standard. They are unnecessary here because no variation in the - * @dev cipher suite is allowed. - - * @dev - Similarly, the hash input in _scalarFromCurvePoints does not include a - * @dev commitment to the cipher suite, either, which differs from step 2 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - * @dev . Also, the hash input is the concatenation of the uncompressed - * @dev points, not the compressed points as recommended in step 3. - - * @dev - In the calculation of the challenge value "c", the "u" value (i.e. - * @dev the value computed by Reggie as the nonce times the secp256k1 - * @dev generator point, see steps 5 and 7 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the - * @dev keccak hash of the original u. This is because we only verify the - * @dev calculation of u up to its address, by abusing ECRECOVER. - * **************************************************************************** - * @dev SECURITY PROPERTIES - - * @dev Here are the security properties for this VRF: - - * @dev Full uniqueness: For any seed and valid VRF public key, there is - * @dev exactly one VRF output which can be proved to come from that seed, in - * @dev the sense that the proof will pass _verifyVRFProof. - - * @dev Full collision resistance: It's cryptographically infeasible to find - * @dev two seeds with same VRF output from a fixed, valid VRF key - - * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are - * @dev derived from a given seed, the outputs are computationally - * @dev indistinguishable from randomness. - - * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs - * @dev for these properties. - - * @dev For secp256k1, the key validation described in section - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 - * @dev is unnecessary, because secp256k1 has cofactor 1, and the - * @dev representation of the public key used here (affine x- and y-ordinates - * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to - * @dev the point at infinity. - * **************************************************************************** - * @dev OTHER SECURITY CONSIDERATIONS - * - * @dev The seed input to the VRF could in principle force an arbitrary amount - * @dev of work in _hashToCurve, by requiring extra rounds of hashing and - * @dev checking whether that's yielded the x ordinate of a secp256k1 point. - * @dev However, under the Random Oracle Model the probability of choosing a - * @dev point which forces n extra rounds in _hashToCurve is 2⁻ⁿ. The base cost - * @dev for calling _hashToCurve is about 25,000 gas, and each round of checking - * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for - * @dev which _hashToCurve would cost more than 2,017,000 gas, one would have to - * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any - * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) - - * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, - * @dev this means it is infeasible for an adversary to prevent correct - * @dev operation of this contract by choosing an adverse seed. - - * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for - * @dev _hashToCurve.) - - * @dev It may be possible to make a secure constant-time _hashToCurve function. - * @dev See notes in _hashToCurve docstring. -*/ -contract VRF { - // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. - // Number of points in Secp256k1 - uint256 private constant GROUP_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; - // Prime characteristic of the galois field over which Secp256k1 is defined - uint256 private constant FIELD_SIZE = - // solium-disable-next-line indentation - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; - uint256 private constant WORD_LENGTH_BYTES = 0x20; - - // (base^exponent) % FIELD_SIZE - // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 - function _bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { - uint256 callResult; - uint256[6] memory bigModExpContractInputs; - bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base - bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent - bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus - bigModExpContractInputs[3] = base; - bigModExpContractInputs[4] = exponent; - bigModExpContractInputs[5] = FIELD_SIZE; - uint256[1] memory output; - assembly { - callResult := staticcall( - not(0), // Gas cost: no limit - 0x05, // Bigmodexp contract address - bigModExpContractInputs, - 0xc0, // Length of input segment: 6*0x20-bytes - output, - 0x20 // Length of output segment - ) - } - if (callResult == 0) { - // solhint-disable-next-line gas-custom-errors - revert("bigModExp failure!"); - } - return output[0]; - } - - // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See - // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus - uint256 private constant SQRT_POWER = (FIELD_SIZE + 1) >> 2; - - // Computes a s.t. a^2 = x in the field. Assumes a exists - function _squareRoot(uint256 x) internal view returns (uint256) { - return _bigModExp(x, SQRT_POWER); - } - - // The value of y^2 given that (x,y) is on secp256k1. - function _ySquared(uint256 x) internal pure returns (uint256) { - // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf - uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); - return addmod(xCubed, 7, FIELD_SIZE); - } - - // True iff p is on secp256k1 - function _isOnCurve(uint256[2] memory p) internal pure returns (bool) { - // Section 2.3.6. in https://www.secg.org/sec1-v2.pdf - // requires each ordinate to be in [0, ..., FIELD_SIZE-1] - // solhint-disable-next-line gas-custom-errors - require(p[0] < FIELD_SIZE, "invalid x-ordinate"); - // solhint-disable-next-line gas-custom-errors - require(p[1] < FIELD_SIZE, "invalid y-ordinate"); - return _ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); - } - - // Hash x uniformly into {0, ..., FIELD_SIZE-1}. - function _fieldHash(bytes memory b) internal pure returns (uint256 x_) { - x_ = uint256(keccak256(b)); - // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of - // http://www.secg.org/sec1-v2.pdf , which is part of the definition of - // string_to_point in the IETF draft - while (x_ >= FIELD_SIZE) { - x_ = uint256(keccak256(abi.encodePacked(x_))); - } - return x_; - } - - // Hash b to a random point which hopefully lies on secp256k1. The y ordinate - // is always even, due to - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - // step 5.C, which references arbitrary_string_to_point, defined in - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as - // returning the point with given x ordinate, and even y ordinate. - function _newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { - unchecked { - p[0] = _fieldHash(b); - p[1] = _squareRoot(_ySquared(p[0])); - if (p[1] % 2 == 1) { - // Note that 0 <= p[1] < FIELD_SIZE - // so this cannot wrap, we use unchecked to save gas. - p[1] = FIELD_SIZE - p[1]; - } - } - return p; - } - - // Domain-separation tag for initial hash in _hashToCurve. Corresponds to - // vrf.go/hashToCurveHashPrefix - uint256 internal constant HASH_TO_CURVE_HASH_PREFIX = 1; - - // Cryptographic hash function onto the curve. - // - // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see - // DESIGN NOTES above for slight differences.) - // - // TODO(alx): Implement a bounded-computation hash-to-curve, as described in - // "Construction of Rational Points on Elliptic Curves over Finite Fields" - // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf - // and suggested by - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 - // (Though we can't used exactly that because secp256k1's j-invariant is 0.) - // - // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" - // https://www.pivotaltracker.com/story/show/171120900 - function _hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { - rv = _newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); - while (!_isOnCurve(rv)) { - rv = _newCandidateSecp256k1Point(abi.encodePacked(rv[0])); - } - return rv; - } - - /** ********************************************************************* - * @notice Check that product==scalar*multiplicand - * - * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. - * - * @param multiplicand: secp256k1 point - * @param scalar: non-zero GF(GROUP_ORDER) scalar - * @param product: secp256k1 expected to be multiplier * multiplicand - * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability - */ - function _ecmulVerify( - uint256[2] memory multiplicand, - uint256 scalar, - uint256[2] memory product - ) internal pure returns (bool verifies) { - // solhint-disable-next-line gas-custom-errors - require(scalar != 0, "zero scalar"); // Rules out an ecrecover failure case - uint256 x = multiplicand[0]; // x ordinate of multiplicand - uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is - // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. - // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 - bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); - address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); - // Explicit conversion to address takes bottom 160 bits - address expected = address(uint160(uint256(keccak256(abi.encodePacked(product))))); - return (actual == expected); - } - - // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) - function _projectiveSub( - uint256 x1, - uint256 z1, - uint256 x2, - uint256 z2 - ) internal pure returns (uint256 x3, uint256 z3) { - unchecked { - uint256 num1 = mulmod(z2, x1, FIELD_SIZE); - // Note this cannot wrap since x2 is a point in [0, FIELD_SIZE-1] - // we use unchecked to save gas. - uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); - (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - } - return (x3, z3); - } - - // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) - function _projectiveMul( - uint256 x1, - uint256 z1, - uint256 x2, - uint256 z2 - ) internal pure returns (uint256 x3, uint256 z3) { - (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - return (x3, z3); - } - - /** ************************************************************************** - @notice Computes elliptic-curve sum, in projective co-ordinates - - @dev Using projective coordinates avoids costly divisions - - @dev To use this with p and q in affine coordinates, call - @dev _projectiveECAdd(px, py, qx, qy). This will return - @dev the addition of (px, py, 1) and (qx, qy, 1), in the - @dev secp256k1 group. - - @dev This can be used to calculate the z which is the inverse to zInv - @dev in isValidVRFOutput. But consider using a faster - @dev re-implementation such as ProjectiveECAdd in the golang vrf package. - - @dev This function assumes [px,py,1],[qx,qy,1] are valid projective - coordinates of secp256k1 points. That is safe in this contract, - because this method is only used by _linearCombination, which checks - points are on the curve via ecrecover. - ************************************************************************** - @param px The first affine coordinate of the first summand - @param py The second affine coordinate of the first summand - @param qx The first affine coordinate of the second summand - @param qy The second affine coordinate of the second summand - - (px,py) and (qx,qy) must be distinct, valid secp256k1 points. - ************************************************************************** - Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points - on secp256k1, in P²(𝔽ₙ) - @return sx - @return sy - @return sz - */ - function _projectiveECAdd( - uint256 px, - uint256 py, - uint256 qx, - uint256 qy - ) internal pure returns (uint256 sx, uint256 sy, uint256 sz) { - unchecked { - // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, - // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone - // We take the equations there for (sx,sy), and homogenize them to - // projective coordinates. That way, no inverses are required, here, and we - // only need the one inverse in _affineECAdd. - - // We only need the "point addition" equations from Hankerson et al. Can - // skip the "point doubling" equations because p1 == p2 is cryptographically - // impossible, and required not to be the case in _linearCombination. - - // Add extra "projective coordinate" to the two points - (uint256 z1, uint256 z2) = (1, 1); - - // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. - // Cannot wrap since px and py are in [0, FIELD_SIZE-1] - uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); - uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); - - uint256 dx; // Accumulates denominator from sx calculation - // sx=((qy-py)/(qx-px))^2-px-qx - (sx, dx) = _projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 - (sx, dx) = _projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px - (sx, dx) = _projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx - - uint256 dy; // Accumulates denominator from sy calculation - // sy=((qy-py)/(qx-px))(px-sx)-py - (sy, dy) = _projectiveSub(px, z1, sx, dx); // px-sx - (sy, dy) = _projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) - (sy, dy) = _projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py - - if (dx != dy) { - // Cross-multiply to put everything over a common denominator - sx = mulmod(sx, dy, FIELD_SIZE); - sy = mulmod(sy, dx, FIELD_SIZE); - sz = mulmod(dx, dy, FIELD_SIZE); - } else { - // Already over a common denominator, use that for z ordinate - sz = dx; - } - } - return (sx, sy, sz); - } - - // p1+p2, as affine points on secp256k1. - // - // invZ must be the inverse of the z returned by _projectiveECAdd(p1, p2). - // It is computed off-chain to save gas. - // - // p1 and p2 must be distinct, because _projectiveECAdd doesn't handle - // point doubling. - function _affineECAdd( - uint256[2] memory p1, - uint256[2] memory p2, - uint256 invZ - ) internal pure returns (uint256[2] memory) { - uint256 x; - uint256 y; - uint256 z; - (x, y, z) = _projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); - // solhint-disable-next-line gas-custom-errors - require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); - // Clear the z ordinate of the projective representation by dividing through - // by it, to obtain the affine representation - return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; - } - - // True iff address(c*p+s*g) == lcWitness, where g is generator. (With - // cryptographically high probability.) - function _verifyLinearCombinationWithGenerator( - uint256 c, - uint256[2] memory p, - uint256 s, - address lcWitness - ) internal pure returns (bool) { - // Rule out ecrecover failure modes which return address 0. - unchecked { - // solhint-disable-next-line gas-custom-errors - require(lcWitness != address(0), "bad witness"); - uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p - // Note this cannot wrap (X - Y % X), but we use unchecked to save - // gas. - bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] - bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // The point corresponding to the address returned by - // ecrecover(-s*p[0],v,p[0],c*p[0]) is - // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. - // See https://crypto.stackexchange.com/a/18106 - // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v - address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); - return computed == lcWitness; - } - } - - // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also - // requires cp1Witness != sp2Witness (which is fine for this application, - // since it is cryptographically impossible for them to be equal. In the - // (cryptographically impossible) case that a prover accidentally derives - // a proof with equal c*p1 and s*p2, they should retry with a different - // proof nonce.) Assumes that all points are on secp256k1 - // (which is checked in _verifyVRFProof below.) - function _linearCombination( - uint256 c, - uint256[2] memory p1, - uint256[2] memory cp1Witness, - uint256 s, - uint256[2] memory p2, - uint256[2] memory sp2Witness, - uint256 zInv - ) internal pure returns (uint256[2] memory) { - unchecked { - // Note we are relying on the wrap around here - // solhint-disable-next-line gas-custom-errors - require((cp1Witness[0] % FIELD_SIZE) != (sp2Witness[0] % FIELD_SIZE), "points in sum must be distinct"); - // solhint-disable-next-line gas-custom-errors - require(_ecmulVerify(p1, c, cp1Witness), "First mul check failed"); - // solhint-disable-next-line gas-custom-errors - require(_ecmulVerify(p2, s, sp2Witness), "Second mul check failed"); - return _affineECAdd(cp1Witness, sp2Witness, zInv); - } - } - - // Domain-separation tag for the hash taken in _scalarFromCurvePoints. - // Corresponds to scalarFromCurveHashPrefix in vrf.go - uint256 internal constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; - - // Pseudo-random number from inputs. Matches vrf.go/_scalarFromCurvePoints, and - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - // The draft calls (in step 7, via the definition of string_to_int, in - // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the - // first hash without checking that it corresponds to a number less than the - // group order, which will lead to a slight bias in the sample. - // - // TODO(alx): We could save a bit of gas by following the standard here and - // using the compressed representation of the points, if we collated the y - // parities into a single bytes32. - // https://www.pivotaltracker.com/story/show/171120588 - function _scalarFromCurvePoints( - uint256[2] memory hash, - uint256[2] memory pk, - uint256[2] memory gamma, - address uWitness, - uint256[2] memory v - ) internal pure returns (uint256 s) { - return uint256(keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); - } - - // True if (gamma, c, s) is a correctly constructed randomness proof from pk - // and seed. zInv must be the inverse of the third ordinate from - // _projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to - // section 5.3 of the IETF draft. - // - // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass - // the x ordinate, and the parity of the y ordinate in the top bit of uWitness - // (which I could make a uint256 without using any extra space.) Would save - // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 - function _verifyVRFProof( - uint256[2] memory pk, - uint256[2] memory gamma, - uint256 c, - uint256 s, - uint256 seed, - address uWitness, - uint256[2] memory cGammaWitness, - uint256[2] memory sHashWitness, - uint256 zInv - ) internal view { - unchecked { - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(pk), "public key is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(gamma), "gamma is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(sHashWitness), "sHashWitness is not on curve"); - // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here - // we use the address of u instead of u itself. Also, here we add the - // terms instead of taking the difference, and in the proof construction in - // vrf.GenerateProof, we correspondingly take the difference instead of - // taking the sum as they do in step 7 of section 5.1.) - // solhint-disable-next-line gas-custom-errors - require(_verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)!=_uWitness"); - // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) - uint256[2] memory hash = _hashToCurve(pk, seed); - // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms - uint256[2] memory v = _linearCombination(c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); - // Steps 7. and 8. of IETF draft section 5.3 - uint256 derivedC = _scalarFromCurvePoints(hash, pk, gamma, uWitness, v); - // solhint-disable-next-line gas-custom-errors - require(c == derivedC, "invalid proof"); - } - } - - // Domain-separation tag for the hash used as the final VRF output. - // Corresponds to vrfRandomOutputHashPrefix in vrf.go - uint256 internal constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; - - struct Proof { - uint256[2] pk; - uint256[2] gamma; - uint256 c; - uint256 s; - uint256 seed; - address uWitness; - uint256[2] cGammaWitness; - uint256[2] sHashWitness; - uint256 zInv; - } - - /* *************************************************************************** - * @notice Returns proof's output, if proof is valid. Otherwise reverts - - * @param proof vrf proof components - * @param seed seed used to generate the vrf output - * - * Throws if proof is invalid, otherwise: - * @return output i.e., the random output implied by the proof - * *************************************************************************** - */ - function _randomValueFromVRFProof(Proof calldata proof, uint256 seed) internal view returns (uint256 output) { - _verifyVRFProof( - proof.pk, - proof.gamma, - proof.c, - proof.s, - seed, - proof.uWitness, - proof.cGammaWitness, - proof.sHashWitness, - proof.zInv - ); - output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, proof.gamma))); - return output; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol deleted file mode 100644 index 3d73b70..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBase.sol +++ /dev/null @@ -1,200 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; - -import {VRFRequestIDBase} from "./VRFRequestIDBase.sol"; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBase, and can - * @dev initialize VRFConsumerBase's attributes in their constructor as - * @dev shown: - * - * @dev contract VRFConsumer { - * @dev constructor(, address _vrfCoordinator, address _link) - * @dev VRFConsumerBase(_vrfCoordinator, _link) public { - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash), and have told you the minimum LINK - * @dev price for VRF service. Make sure your contract has sufficient LINK, and - * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you - * @dev want to generate randomness from. - * - * @dev Once the VRFCoordinator has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomness method. - * - * @dev The randomness argument to fulfillRandomness is the actual random value - * @dev generated from your seed. - * - * @dev The requestId argument is generated from the keyHash and the seed by - * @dev makeRequestId(keyHash, seed). If your contract could have concurrent - * @dev requests open, you can use the requestId to track which seed is - * @dev associated with which randomness. See VRFRequestIDBase.sol for more - * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously.) - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. (Which is critical to making unpredictable randomness! See the - * @dev next section.) - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the ultimate input to the VRF is mixed with the block hash of the - * @dev block in which the request is made, user-provided seeds have no impact - * @dev on its economic security properties. They are only included for API - * @dev compatability with previous versions of this contract. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. - */ -abstract contract VRFConsumerBase is VRFRequestIDBase { - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBase expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomness the VRF output - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual; - - /** - * @dev In order to keep backwards compatibility we have kept the user - * seed field around. We remove the use of it because given that the blockhash - * enters later, it overrides whatever randomness the used seed provides. - * Given that it adds no security, and can easily lead to misunderstandings, - * we have removed it from usage and can now provide a simpler API. - */ - uint256 private constant USER_SEED_PLACEHOLDER = 0; - - /** - * @notice requestRandomness initiates a request for VRF output given _seed - * - * @dev The fulfillRandomness method receives the output, once it's provided - * @dev by the Oracle, and verified by the vrfCoordinator. - * - * @dev The _keyHash must already be registered with the VRFCoordinator, and - * @dev the _fee must exceed the fee specified during registration of the - * @dev _keyHash. - * - * @dev The _seed parameter is vestigial, and is kept only for API - * @dev compatibility with older versions. It can't *hurt* to mix in some of - * @dev your own randomness, here, but it's not necessary because the VRF - * @dev oracle will mix the hash of the block containing your request into the - * @dev VRF seed it ultimately uses. - * - * @param _keyHash ID of public key against which randomness is generated - * @param _fee The amount of LINK to send with the request - * - * @return requestId unique ID for this request - * - * @dev The returned requestId can be used to distinguish responses to - * @dev concurrent requests. It is passed as the first argument to - * @dev fulfillRandomness. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function requestRandomness(bytes32 _keyHash, uint256 _fee) internal returns (bytes32 requestId) { - LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); - // This is the seed passed to VRFCoordinator. The oracle will mix this with - // the hash of the block containing this request to obtain the seed/input - // which is finally passed to the VRF cryptographic machinery. - uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); - // nonces[_keyHash] must stay in sync with - // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above - // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). - // This provides protection against the user repeating their input seed, - // which would result in a predictable/duplicate output, if multiple such - // requests appeared in the same block. - nonces[_keyHash] = nonces[_keyHash] + 1; - return makeRequestId(_keyHash, vRFSeed); - } - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - LinkTokenInterface internal immutable LINK; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address private immutable vrfCoordinator; - - // Nonces for each VRF key from which randomness has been requested. - // - // Must stay in sync with VRFCoordinator[_keyHash][this] - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - mapping(bytes32 => uint256) /* keyHash */ /* nonce */ private nonces; - - /** - * @param _vrfCoordinator address of VRFCoordinator contract - * @param _link address of LINK token contract - * - * @dev https://docs.chain.link/docs/link-token-contracts - */ - constructor(address _vrfCoordinator, address _link) { - vrfCoordinator = _vrfCoordinator; - LINK = LinkTokenInterface(_link); - } - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); - fulfillRandomness(requestId, randomness); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol deleted file mode 100644 index ad7025f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. It ensures 2 things: - * @dev 1. The fulfillment came from the VRFCoordinator - * @dev 2. The consumer contract implements fulfillRandomWords. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBase, and can - * @dev initialize VRFConsumerBase's attributes in their constructor as - * @dev shown: - * - * @dev contract VRFConsumer { - * @dev constructor(, address _vrfCoordinator, address _link) - * @dev VRFConsumerBase(_vrfCoordinator) public { - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash). Create subscription, fund it - * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface - * @dev subscription management functions). - * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, - * @dev callbackGasLimit, numWords), - * @dev see (VRFCoordinatorInterface for a description of the arguments). - * - * @dev Once the VRFCoordinator has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomWords method. - * - * @dev The randomness argument to fulfillRandomWords is a set of random words - * @dev generated from your requestId and the blockHash of the request. - * - * @dev If your contract could have concurrent requests open, you can use the - * @dev requestId returned from requestRandomWords to track which response is associated - * @dev with which randomness request. - * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously. - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. It is for this reason that - * @dev that you can signal to an oracle you'd like them to wait longer before - * @dev responding to the request (however this is not enforced in the contract - * @dev and so remains effective only in the case of unmodified oracle software). - */ -abstract contract VRFConsumerBaseV2 { - error OnlyCoordinatorCanFulfill(address have, address want); - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address private immutable vrfCoordinator; - - /** - * @param _vrfCoordinator address of VRFCoordinator contract - */ - constructor(address _vrfCoordinator) { - vrfCoordinator = _vrfCoordinator; - } - - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomWords the VRF output expanded to the requested number of words - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { - if (msg.sender != vrfCoordinator) { - revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); - } - fulfillRandomWords(requestId, randomWords); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol deleted file mode 100644 index 717826a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol +++ /dev/null @@ -1,840 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; -import {BlockhashStoreInterface} from "./interfaces/BlockhashStoreInterface.sol"; -import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; -import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; -import {IERC677Receiver} from "../shared/interfaces/IERC677Receiver.sol"; -import {VRF} from "./VRF.sol"; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; -import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; -contract VRFCoordinatorV2 is VRF, ConfirmedOwner, TypeAndVersionInterface, VRFCoordinatorV2Interface, IERC677Receiver { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - LinkTokenInterface public immutable LINK; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - AggregatorV3Interface public immutable LINK_ETH_FEED; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - BlockhashStoreInterface public immutable BLOCKHASH_STORE; - - // We need to maintain a list of consuming addresses. - // This bound ensures we are able to loop over them as needed. - // Should a user require more consumers, they can use multiple subscriptions. - uint16 public constant MAX_CONSUMERS = 100; - error TooManyConsumers(); - error InsufficientBalance(); - error InvalidConsumer(uint64 subId, address consumer); - error InvalidSubscription(); - error OnlyCallableFromLink(); - error InvalidCalldata(); - error MustBeSubOwner(address owner); - error PendingRequestExists(); - error MustBeRequestedOwner(address proposedOwner); - error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen - event FundsRecovered(address to, uint256 amount); - // We use the subscription struct (1 word) - // at fulfillment time. - struct Subscription { - // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) - uint96 balance; // Common link balance used for all consumer requests. - uint64 reqCount; // For fee tiers - } - // We use the config for the mgmt APIs - struct SubscriptionConfig { - address owner; // Owner can fund/withdraw/cancel the sub. - address requestedOwner; // For safely transferring sub ownership. - // Maintains the list of keys in s_consumers. - // We do this for 2 reasons: - // 1. To be able to clean up all keys from s_consumers when canceling a subscription. - // 2. To be able to return the list of all consumers in getSubscription. - // Note that we need the s_consumers map to be able to directly check if a - // consumer is valid without reading all the consumers from storage. - address[] consumers; - } - // Note a nonce of 0 indicates an the consumer is not assigned to that subscription. - mapping(address => mapping(uint64 => uint64)) /* consumer */ /* subId */ /* nonce */ private s_consumers; - mapping(uint64 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ private s_subscriptionConfigs; - mapping(uint64 => Subscription) /* subId */ /* subscription */ private s_subscriptions; - // We make the sub count public so that its possible to - // get all the current subscriptions via getSubscription. - uint64 private s_currentSubId; - // s_totalBalance tracks the total link sent to/from - // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. - // A discrepancy with this contract's link balance indicates someone - // sent tokens using transfer and so we may need to use recoverFunds. - uint96 private s_totalBalance; - event SubscriptionCreated(uint64 indexed subId, address owner); - event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionConsumerAdded(uint64 indexed subId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subId, address consumer); - event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); - event SubscriptionOwnerTransferRequested(uint64 indexed subId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subId, address from, address to); - - // Set this maximum to 200 to give us a 56 block window to fulfill - // the request before requiring the block hash feeder. - uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; - uint32 public constant MAX_NUM_WORDS = 500; - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); - error GasLimitTooBig(uint32 have, uint32 want); - error NumWordsTooBig(uint32 have, uint32 want); - error ProvingKeyAlreadyRegistered(bytes32 keyHash); - error NoSuchProvingKey(bytes32 keyHash); - error InvalidLinkWeiPrice(int256 linkWei); - error InsufficientGasForConsumer(uint256 have, uint256 want); - error NoCorrespondingRequest(); - error IncorrectCommitment(); - error BlockhashNotInStore(uint256 blockNum); - error PaymentTooLarge(); - error Reentrant(); - struct RequestCommitment { - uint64 blockNum; - uint64 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - } - mapping(bytes32 => address) /* keyHash */ /* oracle */ private s_provingKeys; - bytes32[] private s_provingKeyHashes; - mapping(address => uint96) /* oracle */ /* LINK balance */ private s_withdrawableTokens; - mapping(uint256 => bytes32) /* requestID */ /* commitment */ private s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); - event ProvingKeyDeregistered(bytes32 keyHash, address indexed oracle); - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint64 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address indexed sender - ); - event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); - - struct Config { - uint16 minimumRequestConfirmations; - uint32 maxGasLimit; - // Reentrancy protection. - bool reentrancyLock; - // stalenessSeconds is how long before we consider the feed price to be stale - // and fallback to fallbackWeiPerUnitLink. - uint32 stalenessSeconds; - // Gas to cover oracle payment after we calculate the payment. - // We make it configurable in case those operations are repriced. - uint32 gasAfterPaymentCalculation; - } - int256 private s_fallbackWeiPerUnitLink; - Config private s_config; - FeeConfig private s_feeConfig; - struct FeeConfig { - // Flat fee charged per fulfillment in millionths of link - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeLinkPPMTier1; - uint32 fulfillmentFlatFeeLinkPPMTier2; - uint32 fulfillmentFlatFeeLinkPPMTier3; - uint32 fulfillmentFlatFeeLinkPPMTier4; - uint32 fulfillmentFlatFeeLinkPPMTier5; - uint24 reqsForTier2; - uint24 reqsForTier3; - uint24 reqsForTier4; - uint24 reqsForTier5; - } - event ConfigSet( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig feeConfig - ); - - constructor(address link, address blockhashStore, address linkEthFeed) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(link); - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); - } - - /** - * @notice Registers a proving key to an oracle. - * @param oracle address of the oracle - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh] != address(0)) { - revert ProvingKeyAlreadyRegistered(kh); - } - s_provingKeys[kh] = oracle; - s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, oracle); - } - - /** - * @notice Deregisters a proving key to an oracle. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - address oracle = s_provingKeys[kh]; - if (oracle == address(0)) { - revert NoSuchProvingKey(kh); - } - delete s_provingKeys[kh]; - for (uint256 i = 0; i < s_provingKeyHashes.length; i++) { - if (s_provingKeyHashes[i] == kh) { - bytes32 last = s_provingKeyHashes[s_provingKeyHashes.length - 1]; - // Copy last element and overwrite kh to be deleted with it - s_provingKeyHashes[i] = last; - s_provingKeyHashes.pop(); - } - } - emit ProvingKeyDeregistered(kh, oracle); - } - - /** - * @notice Returns the proving key hash key associated with this public key - * @param publicKey the key to return the hash of - */ - function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed - * @param feeConfig fee tier configuration - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig memory feeConfig - ) external onlyOwner { - if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { - revert InvalidRequestConfirmations( - minimumRequestConfirmations, - minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - if (fallbackWeiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); - } - s_config = Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - reentrancyLock: false - }); - s_feeConfig = feeConfig; - s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; - emit ConfigSet( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - s_feeConfig - ); - } - - function getConfig() - external - view - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ) - { - return ( - s_config.minimumRequestConfirmations, - s_config.maxGasLimit, - s_config.stalenessSeconds, - s_config.gasAfterPaymentCalculation - ); - } - - function getFeeConfig() - external - view - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ) - { - return ( - s_feeConfig.fulfillmentFlatFeeLinkPPMTier1, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier2, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier3, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier4, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier5, - s_feeConfig.reqsForTier2, - s_feeConfig.reqsForTier3, - s_feeConfig.reqsForTier4, - s_feeConfig.reqsForTier5 - ); - } - - function getTotalBalance() external view returns (uint256) { - return s_totalBalance; - } - - function getFallbackWeiPerUnitLink() external view returns (int256) { - return s_fallbackWeiPerUnitLink; - } - - /** - * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - * @param subId subscription id - * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - */ - function ownerCancelSubscription(uint64 subId) external onlyOwner { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - _cancelSubscriptionHelper(subId, s_subscriptionConfigs[subId].owner); - } - - /** - * @notice Recover link sent with transfer instead of transferAndCall. - * @param to address to send link to - */ - function recoverFunds(address to) external onlyOwner { - uint256 externalBalance = LINK.balanceOf(address(this)); - uint256 internalBalance = uint256(s_totalBalance); - if (internalBalance > externalBalance) { - revert BalanceInvariantViolated(internalBalance, externalBalance); - } - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - LINK.transfer(to, amount); - emit FundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function getRequestConfig() external view override returns (uint16, uint32, bytes32[] memory) { - return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function requestRandomWords( - bytes32 keyHash, - uint64 subId, - uint16 requestConfirmations, - uint32 callbackGasLimit, - uint32 numWords - ) external override nonReentrant returns (uint256) { - // Input validation using the subscription storage. - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // Its important to ensure that the consumer is in fact who they say they - // are, otherwise they could use someone else's subscription balance. - // A nonce of 0 indicates consumer is not allocated to the sub. - uint64 currentNonce = s_consumers[msg.sender][subId]; - if (currentNonce == 0) { - revert InvalidConsumer(subId, msg.sender); - } - // Input validation using the config storage word. - if ( - requestConfirmations < s_config.minimumRequestConfirmations || requestConfirmations > MAX_REQUEST_CONFIRMATIONS - ) { - revert InvalidRequestConfirmations( - requestConfirmations, - s_config.minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - // No lower bound on the requested gas limit. A user could request 0 - // and they would simply be billed for the proof verification and wouldn't be - // able to do anything with the random value. - if (callbackGasLimit > s_config.maxGasLimit) { - revert GasLimitTooBig(callbackGasLimit, s_config.maxGasLimit); - } - if (numWords > MAX_NUM_WORDS) { - revert NumWordsTooBig(numWords, MAX_NUM_WORDS); - } - // Note we do not check whether the keyHash is valid to save gas. - // The consequence for users is that they can send requests - // for invalid keyHashes which will simply not be fulfilled. - uint64 nonce = currentNonce + 1; - (uint256 requestId, uint256 preSeed) = _computeRequestId(keyHash, msg.sender, subId, nonce); - - s_requestCommitments[requestId] = keccak256( - abi.encode(requestId, ChainSpecificUtil._getBlockNumber(), subId, callbackGasLimit, numWords, msg.sender) - ); - emit RandomWordsRequested( - keyHash, - requestId, - preSeed, - subId, - requestConfirmations, - callbackGasLimit, - numWords, - msg.sender - ); - s_consumers[msg.sender][subId] = nonce; - - return requestId; - } - - /** - * @notice Get request commitment - * @param requestId id of request - * @dev used to determine if a request is fulfilled or not - */ - function getCommitment(uint256 requestId) external view returns (bytes32) { - return s_requestCommitments[requestId]; - } - - function _computeRequestId( - bytes32 keyHash, - address sender, - uint64 subId, - uint64 nonce - ) private pure returns (uint256, uint256) { - uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); - return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - function _getRandomnessFromProof( - Proof calldata proof, - RequestCommitment memory rc - ) private view returns (bytes32 keyHash, uint256 requestId, uint256 randomness) { - keyHash = hashOfKey(proof.pk); - // Only registered proving keys are permitted. - address oracle = s_provingKeys[keyHash]; - if (oracle == address(0)) { - revert NoSuchProvingKey(keyHash); - } - requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); - bytes32 commitment = s_requestCommitments[requestId]; - if (commitment == 0) { - revert NoCorrespondingRequest(); - } - if ( - commitment != keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender)) - ) { - revert IncorrectCommitment(); - } - - bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - revert BlockhashNotInStore(rc.blockNum); - } - } - - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); - randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - return (keyHash, requestId, randomness); - } - - /* - * @notice Compute fee based on the request count - * @param reqCount number of requests - * @return feePPM fee in LINK PPM - */ - function getFeeTier(uint64 reqCount) public view returns (uint32) { - FeeConfig memory fc = s_feeConfig; - if (0 <= reqCount && reqCount <= fc.reqsForTier2) { - return fc.fulfillmentFlatFeeLinkPPMTier1; - } - if (fc.reqsForTier2 < reqCount && reqCount <= fc.reqsForTier3) { - return fc.fulfillmentFlatFeeLinkPPMTier2; - } - if (fc.reqsForTier3 < reqCount && reqCount <= fc.reqsForTier4) { - return fc.fulfillmentFlatFeeLinkPPMTier3; - } - if (fc.reqsForTier4 < reqCount && reqCount <= fc.reqsForTier5) { - return fc.fulfillmentFlatFeeLinkPPMTier4; - } - return fc.fulfillmentFlatFeeLinkPPMTier5; - } - - /* - * @notice Fulfill a randomness request - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - * @return payment amount billed to the subscription - * @dev simulated offchain to determine if sufficient balance is present to fulfill the request - */ - function fulfillRandomWords( - Proof calldata proof, - RequestCommitment memory rc - ) external nonReentrant returns (uint96) { - uint256 startGas = gasleft(); - (bytes32 keyHash, uint256 requestId, uint256 randomness) = _getRandomnessFromProof(proof, rc); - - uint256[] memory randomWords = new uint256[](rc.numWords); - for (uint256 i = 0; i < rc.numWords; i++) { - randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); - } - - delete s_requestCommitments[requestId]; - VRFConsumerBaseV2 v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that _callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - bool success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; - - // Increment the req count for fee tier selection. - uint64 reqCount = s_subscriptions[rc.subId].reqCount; - s_subscriptions[rc.subId].reqCount += 1; - - // We want to charge users exactly for how much gas they use in their callback. - // The gasAfterPaymentCalculation is meant to cover these additional operations where we - // decrement the subscription balance and increment the oracles withdrawable balance. - // We also add the flat link fee to the payment amount. - // Its specified in millionths of link, if s_config.fulfillmentFlatFeeLinkPPM = 1 - // 1 link / 1e6 = 1e18 juels / 1e6 = 1e12 juels. - uint96 payment = _calculatePaymentAmount( - startGas, - s_config.gasAfterPaymentCalculation, - getFeeTier(reqCount), - tx.gasprice - ); - if (s_subscriptions[rc.subId].balance < payment) { - revert InsufficientBalance(); - } - s_subscriptions[rc.subId].balance -= payment; - s_withdrawableTokens[s_provingKeys[keyHash]] += payment; - // Include payment in the event for tracking costs. - emit RandomWordsFulfilled(requestId, randomness, payment, success); - return payment; - } - - // Get the amount of gas used for fulfillment - function _calculatePaymentAmount( - uint256 startGas, - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeeLinkPPM, - uint256 weiPerUnitGas - ) internal view returns (uint96) { - int256 weiPerUnitLink; - weiPerUnitLink = _getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); - // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / - uint256(weiPerUnitLink); - uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); - if (paymentNoFee > (1e27 - fee)) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return uint96(paymentNoFee + fee); - } - - function _getFeedData() private view returns (int256) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return weiPerUnitLink; - } - - /* - * @notice Oracle withdraw LINK earned through fulfilling requests - * @param recipient where to send the funds - * @param amount amount to withdraw - */ - function oracleWithdraw(address recipient, uint96 amount) external nonReentrant { - if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - s_totalBalance -= amount; - if (!LINK.transfer(recipient, amount)) { - revert InsufficientBalance(); - } - } - - function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { - if (msg.sender != address(LINK)) { - revert OnlyCallableFromLink(); - } - if (data.length != 32) { - revert InvalidCalldata(); - } - uint64 subId = abi.decode(data, (uint64)); - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // We do not check that the msg.sender is the subscription owner, - // anyone can fund a subscription. - uint256 oldBalance = s_subscriptions[subId].balance; - s_subscriptions[subId].balance += uint96(amount); - s_totalBalance += uint96(amount); - emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); - } - - function getCurrentSubId() external view returns (uint64) { - return s_currentSubId; - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function getSubscription( - uint64 subId - ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - return ( - s_subscriptions[subId].balance, - s_subscriptions[subId].reqCount, - s_subscriptionConfigs[subId].owner, - s_subscriptionConfigs[subId].consumers - ); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function createSubscription() external override nonReentrant returns (uint64) { - s_currentSubId++; - uint64 currentSubId = s_currentSubId; - address[] memory consumers = new address[](0); - s_subscriptions[currentSubId] = Subscription({balance: 0, reqCount: 0}); - s_subscriptionConfigs[currentSubId] = SubscriptionConfig({ - owner: msg.sender, - requestedOwner: address(0), - consumers: consumers - }); - - emit SubscriptionCreated(currentSubId, msg.sender); - return currentSubId; - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function requestSubscriptionOwnerTransfer( - uint64 subId, - address newOwner - ) external override onlySubOwner(subId) nonReentrant { - // Proposing to address(0) would never be claimable so don't need to check. - if (s_subscriptionConfigs[subId].requestedOwner != newOwner) { - s_subscriptionConfigs[subId].requestedOwner = newOwner; - emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); - } - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function acceptSubscriptionOwnerTransfer(uint64 subId) external override nonReentrant { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { - revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); - } - address oldOwner = s_subscriptionConfigs[subId].owner; - s_subscriptionConfigs[subId].owner = msg.sender; - s_subscriptionConfigs[subId].requestedOwner = address(0); - emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function removeConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - if (s_consumers[consumer][subId] == 0) { - revert InvalidConsumer(subId, consumer); - } - // Note bounded by MAX_CONSUMERS - address[] memory consumers = s_subscriptionConfigs[subId].consumers; - uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; i++) { - if (consumers[i] == consumer) { - address last = consumers[lastConsumerIndex]; - // Storage write to preserve last element - s_subscriptionConfigs[subId].consumers[i] = last; - // Storage remove last element - s_subscriptionConfigs[subId].consumers.pop(); - break; - } - } - delete s_consumers[consumer][subId]; - emit SubscriptionConsumerRemoved(subId, consumer); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function addConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - // Already maxed, cannot add any more consumers. - if (s_subscriptionConfigs[subId].consumers.length == MAX_CONSUMERS) { - revert TooManyConsumers(); - } - if (s_consumers[consumer][subId] != 0) { - // Idempotence - do nothing if already added. - // Ensures uniqueness in s_subscriptions[subId].consumers. - return; - } - // Initialize the nonce to 1, indicating the consumer is allocated. - s_consumers[consumer][subId] = 1; - s_subscriptionConfigs[subId].consumers.push(consumer); - - emit SubscriptionConsumerAdded(subId, consumer); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function cancelSubscription(uint64 subId, address to) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - _cancelSubscriptionHelper(subId, to); - } - - function _cancelSubscriptionHelper(uint64 subId, address to) private nonReentrant { - SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; - Subscription memory sub = s_subscriptions[subId]; - uint96 balance = sub.balance; - // Note bounded by MAX_CONSUMERS; - // If no consumers, does nothing. - for (uint256 i = 0; i < subConfig.consumers.length; i++) { - delete s_consumers[subConfig.consumers[i]][subId]; - } - delete s_subscriptionConfigs[subId]; - delete s_subscriptions[subId]; - s_totalBalance -= balance; - if (!LINK.transfer(to, uint256(balance))) { - revert InsufficientBalance(); - } - emit SubscriptionCanceled(subId, to, balance); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - * @dev Looping is bounded to MAX_CONSUMERS*(number of keyhashes). - * @dev Used to disable subscription canceling while outstanding request are present. - */ - function pendingRequestExists(uint64 subId) public view override returns (bool) { - SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; - for (uint256 i = 0; i < subConfig.consumers.length; i++) { - for (uint256 j = 0; j < s_provingKeyHashes.length; j++) { - (uint256 reqId, ) = _computeRequestId( - s_provingKeyHashes[j], - subConfig.consumers[i], - subId, - s_consumers[subConfig.consumers[i]][subId] - ); - if (s_requestCommitments[reqId] != 0) { - return true; - } - } - } - return false; - } - - modifier onlySubOwner(uint64 subId) { - address owner = s_subscriptionConfigs[subId].owner; - if (owner == address(0)) { - revert InvalidSubscription(); - } - if (msg.sender != owner) { - revert MustBeSubOwner(owner); - } - _; - } - - modifier nonReentrant() { - if (s_config.reentrancyLock) { - revert Reentrant(); - } - _; - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "VRFCoordinatorV2 1.0.0"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol deleted file mode 100644 index 6b6b22b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFOwner.sol +++ /dev/null @@ -1,348 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity ^0.8.6; - -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {AuthorizedReceiver} from "./AuthorizedReceiver.sol"; -import {VRFTypes} from "./VRFTypes.sol"; - -// Taken from VRFCoordinatorV2.sol -// Must be abi-compatible with what's there -struct FeeConfig { - // Flat fee charged per fulfillment in millionths of link - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeLinkPPMTier1; - uint32 fulfillmentFlatFeeLinkPPMTier2; - uint32 fulfillmentFlatFeeLinkPPMTier3; - uint32 fulfillmentFlatFeeLinkPPMTier4; - uint32 fulfillmentFlatFeeLinkPPMTier5; - uint24 reqsForTier2; - uint24 reqsForTier3; - uint24 reqsForTier4; - uint24 reqsForTier5; -} - -// Taken from VRFCoordinatorV2.sol -// Must be abi-compatible with what's there -struct Config { - uint16 minimumRequestConfirmations; - uint32 maxGasLimit; - // stalenessSeconds is how long before we consider the feed price to be stale - // and fallback to fallbackWeiPerUnitLink. - uint32 stalenessSeconds; - // Gas to cover oracle payment after we calculate the payment. - // We make it configurable in case those operations are repriced. - uint32 gasAfterPaymentCalculation; - int256 fallbackWeiPerUnitLink; - FeeConfig feeConfig; -} - -/// @dev IVRFCoordinatorV2 is the set of functions on the VRF coordinator V2 -/// @dev that are used in the VRF Owner contract below. -interface IVRFCoordinatorV2 { - function acceptOwnership() external; - - function transferOwnership(address to) external; - - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external; - - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external; - - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig memory feeConfig - ) external; - - function getConfig() - external - view - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ); - - function getFeeConfig() - external - view - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ); - - function getFallbackWeiPerUnitLink() external view returns (int256); - - function ownerCancelSubscription(uint64 subId) external; - - function recoverFunds(address to) external; - - function hashOfKey(uint256[2] memory publicKey) external pure returns (bytes32); - - function fulfillRandomWords( - VRFTypes.Proof calldata proof, - VRFTypes.RequestCommitment memory rc - ) external returns (uint96); -} - -/** - * @notice VRFOwner is a contract that acts as the owner of the VRF - * @notice coordinator, with some useful utilities in the event extraordinary - * @notice things happen on-chain (i.e ETH/LINK price wildly fluctuates, and - * @notice a VRF fulfillment reverts on-chain). - */ -contract VRFOwner is ConfirmedOwner, AuthorizedReceiver { - int256 private constant MAX_INT256 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; - - IVRFCoordinatorV2 internal s_vrfCoordinator; - - event RandomWordsForced(uint256 indexed requestId, uint64 indexed subId, address indexed sender); - - constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) { - // solhint-disable-next-line gas-custom-errors - require(_vrfCoordinator != address(0), "vrf coordinator address must be non-zero"); - s_vrfCoordinator = IVRFCoordinatorV2(_vrfCoordinator); - } - - /** - * @notice Accepts ownership of the VRF coordinator if transferred to us. - */ - function acceptVRFOwnership() external onlyOwner { - s_vrfCoordinator.acceptOwnership(); - } - - /** - * @notice Transfers ownership of the VRF coordinator to the specified address. - * @param to the address to transfer ownership of the VRF Coordinator to. - */ - function transferVRFOwnership(address to) external onlyOwner { - s_vrfCoordinator.transferOwnership(to); - } - - /** - * @notice Returns the address of the VRF coordinator reference in this contract. - * @return The address of the VRF coordinator reference in this contract. - */ - function getVRFCoordinator() public view returns (address) { - return address(s_vrfCoordinator); - } - - /** - * @notice Registers a proving key to an oracle. - * @param oracle address of the oracle - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { - s_vrfCoordinator.registerProvingKey(oracle, publicProvingKey); - } - - /** - * @notice Deregisters a proving key to an oracle. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { - s_vrfCoordinator.deregisterProvingKey(publicProvingKey); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed - * @param feeConfig fee tier configuration - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig memory feeConfig - ) public onlyOwner { - s_vrfCoordinator.setConfig( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - feeConfig - ); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - only to be used from within fulfillRandomWords. - * @dev The reason plain setConfig cannot be used is that it is marked as onlyOwner. Since fulfillRandomWords - * @dev is gated by authorized senders, and the authorized senders are not necessarily owners, the call will - * @dev always fail if the caller of fulfillRandomWords is not the owner, which is not what we want. - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed - * @param feeConfig fee tier configuration - */ - function _setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig memory feeConfig - ) private { - s_vrfCoordinator.setConfig( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - feeConfig - ); - } - - /** - * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - * @param subId subscription id - * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - */ - function ownerCancelSubscription(uint64 subId) external onlyOwner { - s_vrfCoordinator.ownerCancelSubscription(subId); - } - - /** - * @notice Recover link sent with transfer instead of transferAndCall. - * @param to address to send link to - */ - function recoverFunds(address to) external onlyOwner { - s_vrfCoordinator.recoverFunds(to); - } - - /** - * @notice Get all relevant configs from the VRF coordinator. - * @dev This is done in a separate function to avoid the "stack too deep" issue - * @dev when too many local variables are in the same scope. - * @return Config struct containing all relevant configs from the VRF coordinator. - */ - function _getConfigs() private view returns (Config memory) { - ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ) = s_vrfCoordinator.getConfig(); - ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ) = s_vrfCoordinator.getFeeConfig(); - int256 fallbackWeiPerUnitLink = s_vrfCoordinator.getFallbackWeiPerUnitLink(); - return - Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - fallbackWeiPerUnitLink: fallbackWeiPerUnitLink, - feeConfig: FeeConfig({ - fulfillmentFlatFeeLinkPPMTier1: fulfillmentFlatFeeLinkPPMTier1, - fulfillmentFlatFeeLinkPPMTier2: fulfillmentFlatFeeLinkPPMTier2, - fulfillmentFlatFeeLinkPPMTier3: fulfillmentFlatFeeLinkPPMTier3, - fulfillmentFlatFeeLinkPPMTier4: fulfillmentFlatFeeLinkPPMTier4, - fulfillmentFlatFeeLinkPPMTier5: fulfillmentFlatFeeLinkPPMTier5, - reqsForTier2: reqsForTier2, - reqsForTier3: reqsForTier3, - reqsForTier4: reqsForTier4, - reqsForTier5: reqsForTier5 - }) - }); - } - - /** - * @notice Fulfill a randomness request - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - */ - function fulfillRandomWords( - VRFTypes.Proof calldata proof, - VRFTypes.RequestCommitment memory rc - ) external validateAuthorizedSender { - uint256 requestId = _requestIdFromProof(proof.pk, proof.seed); - - // Get current configs to restore them to original values after - // calling _setConfig. - Config memory cfg = _getConfigs(); - - // call _setConfig with the appropriate params in order to fulfill - // an accidentally-underfunded request. - _setConfig( - cfg.minimumRequestConfirmations, - cfg.maxGasLimit, - 1, // stalenessSeconds - 0, // gasAfterPaymentCalculation - MAX_INT256, // fallbackWeiPerUnitLink - FeeConfig({ - fulfillmentFlatFeeLinkPPMTier1: 0, - fulfillmentFlatFeeLinkPPMTier2: 0, - fulfillmentFlatFeeLinkPPMTier3: 0, - fulfillmentFlatFeeLinkPPMTier4: 0, - fulfillmentFlatFeeLinkPPMTier5: 0, - reqsForTier2: 0, - reqsForTier3: 0, - reqsForTier4: 0, - reqsForTier5: 0 - }) - ); - - s_vrfCoordinator.fulfillRandomWords(proof, rc); - - // reset configuration back to old values. - _setConfig( - cfg.minimumRequestConfirmations, - cfg.maxGasLimit, - cfg.stalenessSeconds, - cfg.gasAfterPaymentCalculation, - cfg.fallbackWeiPerUnitLink, - cfg.feeConfig - ); - - emit RandomWordsForced(requestId, rc.subId, rc.sender); - } - - /** - * @notice Concrete implementation of AuthorizedReceiver - * @return bool of whether sender is authorized - */ - function _canSetAuthorizedSenders() internal view override returns (bool) { - return owner() == msg.sender; - } - - /** - * @notice Returns the request for corresponding to the given public key and proof seed. - * @param publicKey the VRF public key associated with the proof - * @param proofSeed the proof seed - * @dev Refer to VRFCoordinatorV2.getRandomnessFromProof for original implementation. - */ - function _requestIdFromProof(uint256[2] memory publicKey, uint256 proofSeed) private view returns (uint256) { - bytes32 keyHash = s_vrfCoordinator.hashOfKey(publicKey); - uint256 requestId = uint256(keccak256(abi.encode(keyHash, proofSeed))); - return requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol deleted file mode 100644 index ce0f6b1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFRequestIDBase.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -contract VRFRequestIDBase { - /** - * @notice returns the seed which is actually input to the VRF coordinator - * - * @dev To prevent repetition of VRF output due to repetition of the - * @dev user-supplied seed, that seed is combined in a hash with the - * @dev user-specific nonce, and the address of the consuming contract. The - * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in - * @dev the final seed, but the nonce does protect against repetition in - * @dev requests which are included in a single block. - * - * @param _userSeed VRF seed input provided by user - * @param _requester Address of the requesting contract - * @param _nonce User-specific nonce at the time of the request - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function makeVRFInputSeed( - bytes32 _keyHash, - uint256 _userSeed, - address _requester, - uint256 _nonce - ) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); - } - - /** - * @notice Returns the id for this request - * @param _keyHash The serviceAgreement ID to be used for this request - * @param _vRFInputSeed The seed to be passed directly to the VRF - * @return The id for this request - * - * @dev Note that _vRFInputSeed is not the seed passed by the consuming - * @dev contract, but the one generated by makeVRFInputSeed - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function makeRequestId(bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol deleted file mode 100644 index d1b35a2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFTypes.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -/** - * @title VRFTypes - * @notice The VRFTypes library is a collection of types that is required to fulfill VRF requests - * on-chain. They must be ABI-compatible with the types used by the coordinator contracts. - */ -library VRFTypes { - // ABI-compatible with VRF.Proof. - // This proof is used for VRF V2 and V2Plus. - struct Proof { - uint256[2] pk; - uint256[2] gamma; - uint256 c; - uint256 s; - uint256 seed; - address uWitness; - uint256[2] cGammaWitness; - uint256[2] sHashWitness; - uint256 zInv; - } - - // ABI-compatible with VRFCoordinatorV2.RequestCommitment. - // This is only used for VRF V2. - struct RequestCommitment { - uint64 blockNum; - uint64 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - } - - // ABI-compatible with VRFCoordinatorV2Plus.RequestCommitment. - // This is only used for VRF V2Plus. - struct RequestCommitmentV2Plus { - uint64 blockNum; - uint256 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - bytes extraArgs; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol deleted file mode 100644 index a656ef0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2Wrapper.sol +++ /dev/null @@ -1,450 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity ^0.8.6; - -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; -import {VRFConsumerBaseV2} from "./VRFConsumerBaseV2.sol"; -import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; -import {AggregatorV3Interface} from "../shared/interfaces/AggregatorV3Interface.sol"; -import {VRFCoordinatorV2Interface} from "./interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol"; -import {VRFV2WrapperConsumerBase} from "./VRFV2WrapperConsumerBase.sol"; -import {ChainSpecificUtil} from "../ChainSpecificUtil_v0_8_6.sol"; - -/** - * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off - * @notice requests for randomness. - */ -contract VRFV2Wrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2, VRFV2WrapperInterface { - event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - LinkTokenInterface public immutable LINK; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - AggregatorV3Interface public immutable LINK_ETH_FEED; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - ExtendedVRFCoordinatorV2Interface public immutable COORDINATOR; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - uint64 public immutable SUBSCRIPTION_ID; - /// @dev this is the size of a VRF v2 fulfillment's calldata abi-encoded in bytes. - /// @dev proofSize = 13 words = 13 * 256 = 3328 bits - /// @dev commitmentSize = 5 words = 5 * 256 = 1280 bits - /// @dev dataSize = proofSize + commitmentSize = 4608 bits - /// @dev selector = 32 bits - /// @dev total data size = 4608 bits + 32 bits = 4640 bits = 580 bytes - uint32 public s_fulfillmentTxSizeBytes = 580; - - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - - // lastRequestId is the request ID of the most recent VRF V2 request made by this wrapper. This - // should only be relied on within the same transaction the request was made. - uint256 public override lastRequestId; - - // Configuration fetched from VRFCoordinatorV2 - - // s_configured tracks whether this contract has been configured. If not configured, randomness - // requests cannot be made. - bool public s_configured; - - // s_disabled disables the contract when true. When disabled, new VRF requests cannot be made - // but existing ones can still be fulfilled. - bool public s_disabled; - - // s_fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed is - // stale. - int256 private s_fallbackWeiPerUnitLink; - - // s_stalenessSeconds is the number of seconds before we consider the feed price to be stale and - // fallback to fallbackWeiPerUnitLink. - uint32 private s_stalenessSeconds; - - // s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 - // charges. - uint32 private s_fulfillmentFlatFeeLinkPPM; - - // Other configuration - - // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - // function. The cost for this gas is passed to the user. - uint32 private s_wrapperGasOverhead; - - // s_coordinatorGasOverhead reflects the gas overhead of the coordinator's fulfillRandomWords - // function. The cost for this gas is billed to the subscription, and must therefor be included - // in the pricing for wrapped requests. This includes the gas costs of proof verification and - // payment calculation in the coordinator. - uint32 private s_coordinatorGasOverhead; - - // s_wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 - // indicates no premium. A value of 15 indicates a 15 percent premium. - uint8 private s_wrapperPremiumPercentage; - - // s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas - // fees, so this should be set to the highest gas lane on the network. - bytes32 internal s_keyHash; - - // s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request. - uint8 internal s_maxNumWords; - - struct Callback { - address callbackAddress; - uint32 callbackGasLimit; - uint256 requestGasPrice; - int256 requestWeiPerUnitLink; - uint256 juelsPaid; - } - mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; - - constructor( - address _link, - address _linkEthFeed, - address _coordinator - ) ConfirmedOwner(msg.sender) VRFConsumerBaseV2(_coordinator) { - LINK = LinkTokenInterface(_link); - LINK_ETH_FEED = AggregatorV3Interface(_linkEthFeed); - COORDINATOR = ExtendedVRFCoordinatorV2Interface(_coordinator); - - // Create this wrapper's subscription and add itself as a consumer. - uint64 subId = ExtendedVRFCoordinatorV2Interface(_coordinator).createSubscription(); - SUBSCRIPTION_ID = subId; - ExtendedVRFCoordinatorV2Interface(_coordinator).addConsumer(subId, address(this)); - } - - /** - * @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes. - * @param size is the size of the fulfillment transaction in bytes. - */ - function setFulfillmentTxSize(uint32 size) external onlyOwner { - s_fulfillmentTxSizeBytes = size; - } - - /** - * @notice setConfig configures VRFV2Wrapper. - * - * @dev Sets wrapper-specific configuration based on the given parameters, and fetches any needed - * @dev VRFCoordinatorV2 configuration from the coordinator. - * - * @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - * function. - * - * @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's - * fulfillRandomWords function. - * - * @param _wrapperPremiumPercentage is the premium ratio in percentage for wrapper requests. - * - * @param _keyHash to use for requesting randomness. - */ - function setConfig( - uint32 _wrapperGasOverhead, - uint32 _coordinatorGasOverhead, - uint8 _wrapperPremiumPercentage, - bytes32 _keyHash, - uint8 _maxNumWords - ) external onlyOwner { - s_wrapperGasOverhead = _wrapperGasOverhead; - s_coordinatorGasOverhead = _coordinatorGasOverhead; - s_wrapperPremiumPercentage = _wrapperPremiumPercentage; - s_keyHash = _keyHash; - s_maxNumWords = _maxNumWords; - s_configured = true; - - // Get other configuration from coordinator - (, , s_stalenessSeconds, ) = COORDINATOR.getConfig(); - s_fallbackWeiPerUnitLink = COORDINATOR.getFallbackWeiPerUnitLink(); - (s_fulfillmentFlatFeeLinkPPM, , , , , , , , ) = COORDINATOR.getFeeConfig(); - } - - /** - * @notice getConfig returns the current VRFV2Wrapper configuration. - * - * @return fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed - * is stale. - * - * @return stalenessSeconds is the number of seconds before we consider the feed price to be stale - * and fallback to fallbackWeiPerUnitLink. - * - * @return fulfillmentFlatFeeLinkPPM is the flat fee in millionths of LINK that VRFCoordinatorV2 - * charges. - * - * @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - * function. The cost for this gas is passed to the user. - * - * @return coordinatorGasOverhead reflects the gas overhead of the coordinator's - * fulfillRandomWords function. - * - * @return wrapperPremiumPercentage is the premium ratio in percentage. For example, a value of 0 - * indicates no premium. A value of 15 indicates a 15 percent premium. - * - * @return keyHash is the key hash to use when requesting randomness. Fees are paid based on - * current gas fees, so this should be set to the highest gas lane on the network. - * - * @return maxNumWords is the max number of words that can be requested in a single wrapped VRF - * request. - */ - function getConfig() - external - view - returns ( - int256 fallbackWeiPerUnitLink, - uint32 stalenessSeconds, - uint32 fulfillmentFlatFeeLinkPPM, - uint32 wrapperGasOverhead, - uint32 coordinatorGasOverhead, - uint8 wrapperPremiumPercentage, - bytes32 keyHash, - uint8 maxNumWords - ) - { - return ( - s_fallbackWeiPerUnitLink, - s_stalenessSeconds, - s_fulfillmentFlatFeeLinkPPM, - s_wrapperGasOverhead, - s_coordinatorGasOverhead, - s_wrapperPremiumPercentage, - s_keyHash, - s_maxNumWords - ); - } - - /** - * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current - * @notice block. - * - * @dev This function relies on the transaction gas price which is not automatically set during - * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - */ - function calculateRequestPrice( - uint32 _callbackGasLimit - ) external view override onlyConfiguredNotDisabled returns (uint256) { - int256 weiPerUnitLink = _getFeedData(); - return _calculateRequestPrice(_callbackGasLimit, tx.gasprice, weiPerUnitLink); - } - - /** - * @notice Estimates the price of a VRF request with a specific gas limit and gas price. - * - * @dev This is a convenience function that can be called in simulation to better understand - * @dev pricing. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _requestGasPriceWei is the gas price in wei used for the estimation. - */ - function estimateRequestPrice( - uint32 _callbackGasLimit, - uint256 _requestGasPriceWei - ) external view override onlyConfiguredNotDisabled returns (uint256) { - int256 weiPerUnitLink = _getFeedData(); - return _calculateRequestPrice(_callbackGasLimit, _requestGasPriceWei, weiPerUnitLink); - } - - function _calculateRequestPrice( - uint256 _gas, - uint256 _requestGasPrice, - int256 _weiPerUnitLink - ) internal view returns (uint256) { - // costWei is the base fee denominated in wei (native) - // costWei takes into account the L1 posting costs of the VRF fulfillment - // transaction, if we are on an L2. - uint256 costWei = (_requestGasPrice * - (_gas + s_wrapperGasOverhead + s_coordinatorGasOverhead) + - ChainSpecificUtil._getL1CalldataGasCost(s_fulfillmentTxSizeBytes)); - // (1e18 juels/link) * ((wei/gas * (gas)) + l1wei) / (wei/link) == 1e18 juels * wei/link / (wei/link) == 1e18 juels * wei/link * link/wei == juels - // baseFee is the base fee denominated in juels (link) - uint256 baseFee = (1e18 * costWei) / uint256(_weiPerUnitLink); - // feeWithPremium is the fee after the percentage premium is applied - uint256 feeWithPremium = (baseFee * (s_wrapperPremiumPercentage + 100)) / 100; - // feeWithFlatFee is the fee after the flat fee is applied on top of the premium - uint256 feeWithFlatFee = feeWithPremium + (1e12 * uint256(s_fulfillmentFlatFeeLinkPPM)); - - return feeWithFlatFee; - } - - /** - * @notice onTokenTransfer is called by LinkToken upon payment for a VRF request. - * - * @dev Reverts if payment is too low. - * - * @param _sender is the sender of the payment, and the address that will receive a VRF callback - * upon fulfillment. - * - * @param _amount is the amount of LINK paid in Juels. - * - * @param _data is the abi-encoded VRF request parameters: uint32 callbackGasLimit, - * uint16 requestConfirmations, and uint32 numWords. - */ - function onTokenTransfer(address _sender, uint256 _amount, bytes calldata _data) external onlyConfiguredNotDisabled { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == address(LINK), "only callable from LINK"); - - (uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords) = abi.decode( - _data, - (uint32, uint16, uint32) - ); - uint32 eip150Overhead = _getEIP150Overhead(callbackGasLimit); - int256 weiPerUnitLink = _getFeedData(); - uint256 price = _calculateRequestPrice(callbackGasLimit, tx.gasprice, weiPerUnitLink); - // solhint-disable-next-line gas-custom-errors - require(_amount >= price, "fee too low"); - // solhint-disable-next-line gas-custom-errors - require(numWords <= s_maxNumWords, "numWords too high"); - - uint256 requestId = COORDINATOR.requestRandomWords( - s_keyHash, - SUBSCRIPTION_ID, - requestConfirmations, - callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, - numWords - ); - s_callbacks[requestId] = Callback({ - callbackAddress: _sender, - callbackGasLimit: callbackGasLimit, - requestGasPrice: tx.gasprice, - requestWeiPerUnitLink: weiPerUnitLink, - juelsPaid: _amount - }); - lastRequestId = requestId; - } - - /** - * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw LINK revenue. - * - * @param _recipient is the address that should receive the LINK funds. - * - * @param _amount is the amount of LINK in Juels that should be withdrawn. - */ - function withdraw(address _recipient, uint256 _amount) external onlyOwner { - LINK.transfer(_recipient, _amount); - } - - /** - * @notice enable this contract so that new requests can be accepted. - */ - function enable() external onlyOwner { - s_disabled = false; - } - - /** - * @notice disable this contract so that new requests will be rejected. When disabled, new requests - * @notice will revert but existing requests can still be fulfilled. - */ - function disable() external onlyOwner { - s_disabled = true; - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - Callback memory callback = s_callbacks[_requestId]; - delete s_callbacks[_requestId]; - // solhint-disable-next-line gas-custom-errors - require(callback.callbackAddress != address(0), "request not found"); // This should never happen - - VRFV2WrapperConsumerBase c; - bytes memory resp = abi.encodeWithSelector(c.rawFulfillRandomWords.selector, _requestId, _randomWords); - - bool success = _callWithExactGas(callback.callbackGasLimit, callback.callbackAddress, resp); - if (!success) { - emit WrapperFulfillmentFailed(_requestId, callback.callbackAddress); - } - } - - function _getFeedData() private view returns (int256) { - bool staleFallback = s_stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (staleFallback && s_stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - // solhint-disable-next-line gas-custom-errors - require(weiPerUnitLink >= 0, "Invalid LINK wei price"); - return weiPerUnitLink; - } - - /** - * @dev Calculates extra amount of gas required for running an assembly call() post-EIP150. - */ - function _getEIP150Overhead(uint32 gas) private pure returns (uint32) { - return gas / 63 + 1; - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - function typeAndVersion() external pure virtual override returns (string memory) { - return "VRFV2Wrapper 1.0.0"; - } - - modifier onlyConfiguredNotDisabled() { - // solhint-disable-next-line gas-custom-errors - require(s_configured, "wrapper is not configured"); - // solhint-disable-next-line gas-custom-errors - require(!s_disabled, "wrapper is disabled"); - _; - } -} - -// solhint-disable-next-line interface-starts-with-i -interface ExtendedVRFCoordinatorV2Interface is VRFCoordinatorV2Interface { - function getConfig() - external - view - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ); - - function getFallbackWeiPerUnitLink() external view returns (int256); - - function getFeeConfig() - external - view - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol deleted file mode 100644 index 7910431..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/VRFV2WrapperConsumerBase.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../shared/interfaces/LinkTokenInterface.sol"; -import {VRFV2WrapperInterface} from "./interfaces/VRFV2WrapperInterface.sol"; - -/** ******************************************************************************* - * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper - * ******************************************************************************** - * @dev PURPOSE - * - * @dev Create VRF V2 requests without the need for subscription management. Rather than creating - * @dev and funding a VRF V2 subscription, a user can use this wrapper to create one off requests, - * @dev paying up front rather than at fulfillment. - * - * @dev Since the price is determined using the gas price of the request transaction rather than - * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas - * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFV2WrapperConsumerBase. The consumer must be funded - * @dev with enough LINK to make the request, otherwise requests will revert. To request randomness, - * @dev call the 'requestRandomness' function with the desired VRF parameters. This function handles - * @dev paying for the request based on the current pricing. - * - * @dev Consumers must implement the fullfillRandomWords function, which will be called during - * @dev fulfillment with the randomness result. - */ -abstract contract VRFV2WrapperConsumerBase { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - LinkTokenInterface internal immutable LINK; - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; - - /** - * @param _link is the address of LinkToken - * @param _vrfV2Wrapper is the address of the VRFV2Wrapper contract - */ - constructor(address _link, address _vrfV2Wrapper) { - LINK = LinkTokenInterface(_link); - VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); - } - - /** - * @dev Requests randomness from the VRF V2 wrapper. - * - * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's - * fulfillRandomWords function. - * @param _requestConfirmations is the number of confirmations to wait before fulfilling the - * request. A higher number of confirmations increases security by reducing the likelihood - * that a chain re-org changes a published randomness outcome. - * @param _numWords is the number of random words to request. - * - * @return requestId is the VRF V2 request ID of the newly created randomness request. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function requestRandomness( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) internal returns (uint256 requestId) { - LINK.transferAndCall( - address(VRF_V2_WRAPPER), - VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit), - abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) - ); - return VRF_V2_WRAPPER.lastRequestId(); - } - - /** - * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must - * @notice implement it. - * - * @param _requestId is the VRF V2 request ID. - * @param _randomWords is the randomness result. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; - - function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == address(VRF_V2_WRAPPER), "only VRF V2 wrapper can fulfill"); - fulfillRandomWords(_requestId, _randomWords); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol deleted file mode 100644 index e03736d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/ArbitrumL1Fees.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; - -/// @dev An abstract contract that provides Arbitrum specific L1 fee calculations. -// solhint-disable-next-line contract-name-camelcase -abstract contract ArbitrumL1Fees { - /// @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); - - /** - * @notice Returns the L1 fees that will be paid for the current transaction, given any calldata - * @notice for the current transaction. It uses ArbGas.getCurrentTxL1GasFees to get the fees. - */ - function _getL1CostWeiForCalldata() internal view returns (uint256) { - return ARBGAS.getCurrentTxL1GasFees(); - } - - /** - * @notice Returns the gas cost in wei of calldataSizeBytes of calldata being posted to L1 - */ - function _getL1CostWeiForCalldataSize(uint256 calldataSizeBytes) internal view returns (uint256) { - (, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei(); - // see https://developer.arbitrum.io/devs-how-tos/how-to-estimate-gas#where-do-we-get-all-this-information-from - // for the justification behind the 140 number. - return l1PricePerByte * (calldataSizeBytes + 140); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol deleted file mode 100644 index 69e0c2a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BatchVRFCoordinatorV2Plus.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -// solhint-disable-next-line one-contract-per-file -pragma solidity 0.8.19; - -import {VRFTypes} from "../VRFTypes.sol"; - -/** - * @title BatchVRFCoordinatorV2Plus - * @notice The BatchVRFCoordinatorV2Plus contract acts as a proxy to write many random responses to the - * @notice provided VRFCoordinatorV2Plus contract efficiently in a single transaction. - */ -contract BatchVRFCoordinatorV2Plus { - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - IVRFCoordinatorV2PlusFulfill public immutable COORDINATOR; - - event ErrorReturned(uint256 indexed requestId, string reason); - event RawErrorReturned(uint256 indexed requestId, bytes lowLevelData); - - constructor(address coordinatorAddr) { - COORDINATOR = IVRFCoordinatorV2PlusFulfill(coordinatorAddr); - } - - /** - * @notice fulfills multiple randomness requests with the provided proofs and commitments. - * @param proofs the randomness proofs generated by the VRF provider. - * @param rcs the request commitments corresponding to the randomness proofs. - */ - function fulfillRandomWords( - VRFTypes.Proof[] calldata proofs, - VRFTypes.RequestCommitmentV2Plus[] calldata rcs - ) external { - // solhint-disable-next-line gas-custom-errors - require(proofs.length == rcs.length, "input array arg lengths mismatch"); - for (uint256 i = 0; i < proofs.length; ++i) { - try COORDINATOR.fulfillRandomWords(proofs[i], rcs[i], false) returns (uint96 /* payment */) { - continue; - } catch Error(string memory reason) { - uint256 requestId = _getRequestIdFromProof(proofs[i]); - emit ErrorReturned(requestId, reason); - } catch (bytes memory lowLevelData) { - uint256 requestId = _getRequestIdFromProof(proofs[i]); - emit RawErrorReturned(requestId, lowLevelData); - } - } - } - - /** - * @notice Returns the proving key hash associated with this public key. - * @param publicKey the key to return the hash of. - */ - function _hashOfKey(uint256[2] memory publicKey) internal pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Returns the request ID of the request associated with the given proof. - * @param proof the VRF proof provided by the VRF oracle. - */ - function _getRequestIdFromProof(VRFTypes.Proof memory proof) internal pure returns (uint256) { - bytes32 keyHash = _hashOfKey(proof.pk); - return uint256(keccak256(abi.encode(keyHash, proof.seed))); - } -} - -interface IVRFCoordinatorV2PlusFulfill { - function fulfillRandomWords( - VRFTypes.Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc, - bool onlyPremium - ) external returns (uint96); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol deleted file mode 100644 index 0bef7ae..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/BlockhashStore.sol +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; - -/** - * @title BlockhashStore - * @notice This contract provides a way to access blockhashes older than - * the 256 block limit imposed by the BLOCKHASH opcode. - * You may assume that any blockhash stored by the contract is correct. - * Note that the contract depends on the format of serialized Ethereum - * blocks. If a future hardfork of Ethereum changes that format, the - * logic in this contract may become incorrect and an updated version - * would have to be deployed. - */ -contract BlockhashStore { - mapping(uint256 => bytes32) internal s_blockhashes; - - /** - * @notice stores blockhash of a given block, assuming it is available through BLOCKHASH - * @param n the number of the block whose blockhash should be stored - */ - function store(uint256 n) public { - bytes32 h = ChainSpecificUtil._getBlockhash(uint64(n)); - // solhint-disable-next-line gas-custom-errors - require(h != 0x0, "blockhash(n) failed"); - s_blockhashes[n] = h; - } - - /** - * @notice stores blockhash of the earliest block still available through BLOCKHASH. - */ - function storeEarliest() external { - store(ChainSpecificUtil._getBlockNumber() - 256); - } - - /** - * @notice stores blockhash after verifying blockheader of child/subsequent block - * @param n the number of the block whose blockhash should be stored - * @param header the rlp-encoded blockheader of block n+1. We verify its correctness by checking - * that it hashes to a stored blockhash, and then extract parentHash to get the n-th blockhash. - */ - function storeVerifyHeader(uint256 n, bytes memory header) public { - // solhint-disable-next-line gas-custom-errors - require(keccak256(header) == s_blockhashes[n + 1], "header has unknown blockhash"); - - // At this point, we know that header is the correct blockheader for block n+1. - - // The header is an rlp-encoded list. The head item of that list is the 32-byte blockhash of the parent block. - // Based on how rlp works, we know that blockheaders always have the following form: - // 0xf9____a0PARENTHASH... - // ^ ^ ^ - // | | | - // | | +--- PARENTHASH is 32 bytes. rlpenc(PARENTHASH) is 0xa || PARENTHASH. - // | | - // | +--- 2 bytes containing the sum of the lengths of the encoded list items - // | - // +--- 0xf9 because we have a list and (sum of lengths of encoded list items) fits exactly into two bytes. - // - // As a consequence, the PARENTHASH is always at offset 4 of the rlp-encoded block header. - - bytes32 parentHash; - assembly { - parentHash := mload(add(header, 36)) // 36 = 32 byte offset for length prefix of ABI-encoded array - // + 4 byte offset of PARENTHASH (see above) - } - - s_blockhashes[n] = parentHash; - } - - /** - * @notice gets a blockhash from the store. If no hash is known, this function reverts. - * @param n the number of the block whose blockhash should be returned - */ - function getBlockhash(uint256 n) external view returns (bytes32) { - bytes32 h = s_blockhashes[n]; - // solhint-disable-next-line gas-custom-errors - require(h != 0x0, "blockhash not found in store"); - return h; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol deleted file mode 100644 index 999e181..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/OptimismL1Fees.sol +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; - -/// @dev An abstract contract that provides Optimism specific L1 fee calculations. -// solhint-disable-next-line contract-name-camelcase -abstract contract OptimismL1Fees is ConfirmedOwner { - /// @dev This is the padding size for unsigned RLP-encoded transaction without the signature data - /// @dev The padding size was estimated based on hypothetical max RLP-encoded transaction size - uint256 internal constant L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE = 71; - /// @dev Signature data size used in the GasPriceOracle predeploy - /// @dev reference: https://github.com/ethereum-optimism/optimism/blob/a96cbe7c8da144d79d4cec1303d8ae60a64e681e/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol#L145 - uint256 internal constant L1_TX_SIGNATURE_DATA_BYTES_SIZE = 68; - /// @dev L1_FEE_DATA_PADDING includes 71 bytes for L1 data padding for Optimism - bytes internal constant L1_FEE_DATA_PADDING = - hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload - /// @dev This option is only available for the Coordinator contract - uint8 internal constant L1_GAS_FEES_MODE = 0; - /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected - /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; - /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; - - uint8 public s_l1FeeCalculationMode = L1_GAS_FEES_MODE; - - /// @dev L1 fee coefficient can be applied to options 2 or 3 to reduce possibly inflated gas price - uint8 public s_l1FeeCoefficient = 100; - - error InvalidL1FeeCalculationMode(uint8 mode); - error InvalidL1FeeCoefficient(uint8 coefficient); - - event L1FeeCalculationSet(uint8 mode, uint8 coefficient); - - function setL1FeeCalculation(uint8 mode, uint8 coefficient) external virtual onlyOwner { - _setL1FeeCalculationInternal(mode, coefficient); - } - - function _setL1FeeCalculationInternal(uint8 mode, uint8 coefficient) internal { - if (mode >= 3) { - revert InvalidL1FeeCalculationMode(mode); - } - if (coefficient == 0 || coefficient > 100) { - revert InvalidL1FeeCoefficient(coefficient); - } - - s_l1FeeCalculationMode = mode; - s_l1FeeCoefficient = coefficient; - - emit L1FeeCalculationSet(mode, coefficient); - } - - function _getL1CostWeiForCalldata(bytes calldata data) internal view returns (uint256) { - if (s_l1FeeCalculationMode == L1_GAS_FEES_MODE) { - return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(data, L1_FEE_DATA_PADDING)); - } - return _getL1CostWeiForCalldataSize(data.length); - } - - function _getL1CostWeiForCalldataSize(uint256 calldataSizeBytes) internal view returns (uint256) { - uint8 l1FeeCalculationMode = s_l1FeeCalculationMode; - if (l1FeeCalculationMode == L1_CALLDATA_GAS_COST_MODE) { - // estimate based on unsigned fully RLP-encoded transaction size so we have to account for paddding bytes as well - return - (s_l1FeeCoefficient * _calculateOptimismL1DataFee(calldataSizeBytes + L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE)) / - 100; - } else if (l1FeeCalculationMode == L1_GAS_FEES_UPPER_BOUND_MODE) { - // getL1FeeUpperBound expects unsigned fully RLP-encoded transaction size so we have to account for paddding bytes as well - return - (s_l1FeeCoefficient * - OVM_GASPRICEORACLE.getL1FeeUpperBound(calldataSizeBytes + L1_UNSIGNED_RLP_ENC_TX_DATA_BYTES_SIZE)) / 100; - } - revert InvalidL1FeeCalculationMode(l1FeeCalculationMode); - } - - function _calculateOptimismL1DataFee(uint256 calldataSizeBytes) internal view returns (uint256) { - // reference: https://docs.optimism.io/stack/transactions/fees#ecotone - // also: https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/exec-engine.md#ecotone-l1-cost-fee-changes-eip-4844-da - // we treat all bytes in the calldata payload as non-zero bytes (cost: 16 gas) because accurate estimation is too expensive - // we also have to account for the signature data size - uint256 l1GasUsed = (calldataSizeBytes + L1_TX_SIGNATURE_DATA_BYTES_SIZE) * 16; - uint256 scaledBaseFee = OVM_GASPRICEORACLE.baseFeeScalar() * 16 * OVM_GASPRICEORACLE.l1BaseFee(); - uint256 scaledBlobBaseFee = OVM_GASPRICEORACLE.blobBaseFeeScalar() * OVM_GASPRICEORACLE.blobBaseFee(); - uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee); - return fee / (16 * 10 ** OVM_GASPRICEORACLE.decimals()); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol deleted file mode 100644 index 7614d7d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/SubscriptionAPI.sol +++ /dev/null @@ -1,475 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {IVRFSubscriptionV2Plus} from "./interfaces/IVRFSubscriptionV2Plus.sol"; - -abstract contract SubscriptionAPI is ConfirmedOwner, IERC677Receiver, IVRFSubscriptionV2Plus { - using EnumerableSet for EnumerableSet.UintSet; - - /// @dev may not be provided upon construction on some chains due to lack of availability - LinkTokenInterface public LINK; - /// @dev may not be provided upon construction on some chains due to lack of availability - AggregatorV3Interface public LINK_NATIVE_FEED; - - // We need to maintain a list of consuming addresses. - // This bound ensures we are able to loop over them as needed. - // Should a user require more consumers, they can use multiple subscriptions. - uint16 public constant MAX_CONSUMERS = 100; - error TooManyConsumers(); - error InsufficientBalance(); - error InvalidConsumer(uint256 subId, address consumer); - error InvalidSubscription(); - error OnlyCallableFromLink(); - error InvalidCalldata(); - error MustBeSubOwner(address owner); - error PendingRequestExists(); - error MustBeRequestedOwner(address proposedOwner); - error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen - event FundsRecovered(address to, uint256 amount); - event NativeFundsRecovered(address to, uint256 amount); - error LinkAlreadySet(); - error FailedToSendNative(); - error FailedToTransferLink(); - error IndexOutOfRange(); - error LinkNotSet(); - - // We use the subscription struct (1 word) - // at fulfillment time. - struct Subscription { - // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) - uint96 balance; // Common link balance used for all consumer requests. - // a uint96 is large enough to hold around ~8e28 wei, or 80 billion ether. - // That should be enough to cover most (if not all) subscriptions. - uint96 nativeBalance; // Common native balance used for all consumer requests. - uint64 reqCount; - } - // We use the config for the mgmt APIs - struct SubscriptionConfig { - address owner; // Owner can fund/withdraw/cancel the sub. - address requestedOwner; // For safely transferring sub ownership. - // Maintains the list of keys in s_consumers. - // We do this for 2 reasons: - // 1. To be able to clean up all keys from s_consumers when canceling a subscription. - // 2. To be able to return the list of all consumers in getSubscription. - // Note that we need the s_consumers map to be able to directly check if a - // consumer is valid without reading all the consumers from storage. - address[] consumers; - } - struct ConsumerConfig { - bool active; - uint64 nonce; - uint64 pendingReqCount; - } - // Note a nonce of 0 indicates the consumer is not assigned to that subscription. - mapping(address => mapping(uint256 => ConsumerConfig)) /* consumerAddress */ /* subId */ /* consumerConfig */ - internal s_consumers; - mapping(uint256 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ internal s_subscriptionConfigs; - mapping(uint256 => Subscription) /* subId */ /* subscription */ internal s_subscriptions; - // subscription nonce used to construct subId. Rises monotonically - uint64 public s_currentSubNonce; - // track all subscription id's that were created by this contract - // note: access should be through the getActiveSubscriptionIds() view function - // which takes a starting index and a max number to fetch in order to allow - // "pagination" of the subscription ids. in the event a very large number of - // subscription id's are stored in this set, they cannot be retrieved in a - // single RPC call without violating various size limits. - EnumerableSet.UintSet internal s_subIds; - // s_totalBalance tracks the total link sent to/from - // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. - // A discrepancy with this contract's link balance indicates someone - // sent tokens using transfer and so we may need to use recoverFunds. - uint96 public s_totalBalance; - // s_totalNativeBalance tracks the total native sent to/from - // this contract through fundSubscription, cancelSubscription and oracleWithdrawNative. - // A discrepancy with this contract's native balance indicates someone - // sent native using transfer and so we may need to use recoverNativeFunds. - uint96 public s_totalNativeBalance; - uint96 internal s_withdrawableTokens; - uint96 internal s_withdrawableNative; - - event SubscriptionCreated(uint256 indexed subId, address owner); - event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); - event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); - event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); - event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); - event SubscriptionOwnerTransferRequested(uint256 indexed subId, address from, address to); - event SubscriptionOwnerTransferred(uint256 indexed subId, address from, address to); - - struct Config { - uint16 minimumRequestConfirmations; - uint32 maxGasLimit; - // Reentrancy protection. - bool reentrancyLock; - // stalenessSeconds is how long before we consider the feed price to be stale - // and fallback to fallbackWeiPerUnitLink. - uint32 stalenessSeconds; - // Gas to cover oracle payment after we calculate the payment. - // We make it configurable in case those operations are repriced. - // The recommended number is below, though it may vary slightly - // if certain chains do not implement certain EIP's. - // 21000 + // base cost of the transaction - // 100 + 5000 + // warm subscription balance read and update. See https://eips.ethereum.org/EIPS/eip-2929 - // 2*2100 + 5000 - // cold read oracle address and oracle balance and first time oracle balance update, note first time will be 20k, but 5k subsequently - // 4800 + // request delete refund (refunds happen after execution), note pre-london fork was 15k. See https://eips.ethereum.org/EIPS/eip-3529 - // 6685 + // Positive static costs of argument encoding etc. note that it varies by +/- x*12 for every x bytes of non-zero data in the proof. - // Total: 37,185 gas. - uint32 gasAfterPaymentCalculation; - // Flat fee charged per fulfillment in millionths of native. - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeNativePPM; - // Discount relative to fulfillmentFlatFeeNativePPM for link payment in millionths of native - // Should not exceed fulfillmentFlatFeeNativePPM - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeLinkDiscountPPM; - // nativePremiumPercentage is the percentage of the total gas costs that is added to the final premium for native payment - // nativePremiumPercentage = 10 means 10% of the total gas costs is added. only integral percentage is allowed - uint8 nativePremiumPercentage; - // linkPremiumPercentage is the percentage of total gas costs that is added to the final premium for link payment - // linkPremiumPercentage = 10 means 10% of the total gas costs is added. only integral percentage is allowed - uint8 linkPremiumPercentage; - } - Config public s_config; - - error Reentrant(); - modifier nonReentrant() { - _nonReentrant(); - _; - } - - function _nonReentrant() internal view { - if (s_config.reentrancyLock) { - revert Reentrant(); - } - } - - function _requireSufficientBalance(bool condition) internal pure { - if (!condition) { - revert InsufficientBalance(); - } - } - - function _requireValidSubscription(address subOwner) internal pure { - if (subOwner == address(0)) { - revert InvalidSubscription(); - } - } - constructor() ConfirmedOwner(msg.sender) {} - - /** - * @notice set the LINK token contract and link native feed to be - * used by this coordinator - * @param link - address of link token - * @param linkNativeFeed address of the link native feed - */ - function setLINKAndLINKNativeFeed(address link, address linkNativeFeed) external onlyOwner { - // Disallow re-setting link token because the logic wouldn't really make sense - if (address(LINK) != address(0)) { - revert LinkAlreadySet(); - } - LINK = LinkTokenInterface(link); - LINK_NATIVE_FEED = AggregatorV3Interface(linkNativeFeed); - } - - /** - * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - * @param subId subscription id - * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - */ - function ownerCancelSubscription(uint256 subId) external onlyOwner { - address subOwner = s_subscriptionConfigs[subId].owner; - _requireValidSubscription(subOwner); - _cancelSubscriptionHelper(subId, subOwner); - } - - /** - * @notice Recover link sent with transfer instead of transferAndCall. - * @param to address to send link to - */ - function recoverFunds(address to) external onlyOwner { - // If LINK is not set, we cannot recover funds. - // It is possible that this coordinator address was funded with LINK - // by accident by a user but the LINK token needs to be set first - // before we can recover it. - if (address(LINK) == address(0)) { - revert LinkNotSet(); - } - - uint256 externalBalance = LINK.balanceOf(address(this)); - uint256 internalBalance = uint256(s_totalBalance); - if (internalBalance > externalBalance) { - revert BalanceInvariantViolated(internalBalance, externalBalance); - } - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - if (!LINK.transfer(to, amount)) { - revert FailedToTransferLink(); - } - emit FundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - /** - * @notice Recover native sent with transfer/call/send instead of fundSubscription. - * @param to address to send native to - */ - function recoverNativeFunds(address payable to) external onlyOwner { - uint256 externalBalance = address(this).balance; - uint256 internalBalance = uint256(s_totalNativeBalance); - if (internalBalance > externalBalance) { - revert BalanceInvariantViolated(internalBalance, externalBalance); - } - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - (bool sent, ) = to.call{value: amount}(""); - if (!sent) { - revert FailedToSendNative(); - } - emit NativeFundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - /* - * @notice withdraw LINK earned through fulfilling requests - * @param recipient where to send the funds - * @param amount amount to withdraw - */ - function withdraw(address recipient) external nonReentrant onlyOwner { - if (address(LINK) == address(0)) { - revert LinkNotSet(); - } - uint96 amount = s_withdrawableTokens; - _requireSufficientBalance(amount > 0); - s_withdrawableTokens = 0; - s_totalBalance -= amount; - _requireSufficientBalance(LINK.transfer(recipient, amount)); - } - - /* - * @notice withdraw native earned through fulfilling requests - * @param recipient where to send the funds - * @param amount amount to withdraw - */ - function withdrawNative(address payable recipient) external nonReentrant onlyOwner { - uint96 amount = s_withdrawableNative; - _requireSufficientBalance(amount > 0); - // Prevent re-entrancy by updating state before transfer. - s_withdrawableNative = 0; - s_totalNativeBalance -= amount; - _mustSendNative(recipient, amount); - } - - function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { - if (msg.sender != address(LINK)) { - revert OnlyCallableFromLink(); - } - if (data.length != 32) { - revert InvalidCalldata(); - } - uint256 subId = abi.decode(data, (uint256)); - _requireValidSubscription(s_subscriptionConfigs[subId].owner); - // We do not check that the sender is the subscription owner, - // anyone can fund a subscription. - uint256 oldBalance = s_subscriptions[subId].balance; - s_subscriptions[subId].balance += uint96(amount); - s_totalBalance += uint96(amount); - emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function fundSubscriptionWithNative(uint256 subId) external payable override nonReentrant { - _requireValidSubscription(s_subscriptionConfigs[subId].owner); - // We do not check that the msg.sender is the subscription owner, - // anyone can fund a subscription. - // We also do not check that msg.value > 0, since that's just a no-op - // and would be a waste of gas on the caller's part. - uint256 oldNativeBalance = s_subscriptions[subId].nativeBalance; - s_subscriptions[subId].nativeBalance += uint96(msg.value); - s_totalNativeBalance += uint96(msg.value); - emit SubscriptionFundedWithNative(subId, oldNativeBalance, oldNativeBalance + msg.value); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function getSubscription( - uint256 subId - ) - public - view - override - returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address subOwner, address[] memory consumers) - { - subOwner = s_subscriptionConfigs[subId].owner; - _requireValidSubscription(subOwner); - return ( - s_subscriptions[subId].balance, - s_subscriptions[subId].nativeBalance, - s_subscriptions[subId].reqCount, - subOwner, - s_subscriptionConfigs[subId].consumers - ); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function getActiveSubscriptionIds( - uint256 startIndex, - uint256 maxCount - ) external view override returns (uint256[] memory ids) { - uint256 numSubs = s_subIds.length(); - if (startIndex >= numSubs) revert IndexOutOfRange(); - uint256 endIndex = startIndex + maxCount; - endIndex = endIndex > numSubs || maxCount == 0 ? numSubs : endIndex; - uint256 idsLength = endIndex - startIndex; - ids = new uint256[](idsLength); - for (uint256 idx = 0; idx < idsLength; ++idx) { - ids[idx] = s_subIds.at(idx + startIndex); - } - return ids; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function createSubscription() external override nonReentrant returns (uint256 subId) { - // Generate a subscription id that is globally unique. - uint64 currentSubNonce = s_currentSubNonce; - subId = uint256( - keccak256(abi.encodePacked(msg.sender, blockhash(block.number - 1), address(this), currentSubNonce)) - ); - // Increment the subscription nonce counter. - s_currentSubNonce = currentSubNonce + 1; - // Initialize storage variables. - address[] memory consumers = new address[](0); - s_subscriptions[subId] = Subscription({balance: 0, nativeBalance: 0, reqCount: 0}); - s_subscriptionConfigs[subId] = SubscriptionConfig({ - owner: msg.sender, - requestedOwner: address(0), - consumers: consumers - }); - // Update the s_subIds set, which tracks all subscription ids created in this contract. - s_subIds.add(subId); - - emit SubscriptionCreated(subId, msg.sender); - return subId; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function requestSubscriptionOwnerTransfer( - uint256 subId, - address newOwner - ) external override onlySubOwner(subId) nonReentrant { - // Proposing to address(0) would never be claimable so don't need to check. - SubscriptionConfig storage subscriptionConfig = s_subscriptionConfigs[subId]; - if (subscriptionConfig.requestedOwner != newOwner) { - subscriptionConfig.requestedOwner = newOwner; - emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); - } - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function acceptSubscriptionOwnerTransfer(uint256 subId) external override nonReentrant { - address oldOwner = s_subscriptionConfigs[subId].owner; - _requireValidSubscription(oldOwner); - if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { - revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); - } - s_subscriptionConfigs[subId].owner = msg.sender; - s_subscriptionConfigs[subId].requestedOwner = address(0); - emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function addConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - ConsumerConfig storage consumerConfig = s_consumers[consumer][subId]; - if (consumerConfig.active) { - // Idempotence - do nothing if already added. - // Ensures uniqueness in s_subscriptions[subId].consumers. - return; - } - // Already maxed, cannot add any more consumers. - address[] storage consumers = s_subscriptionConfigs[subId].consumers; - if (consumers.length == MAX_CONSUMERS) { - revert TooManyConsumers(); - } - // consumerConfig.nonce is 0 if the consumer had never sent a request to this subscription - // otherwise, consumerConfig.nonce is non-zero - // in both cases, use consumerConfig.nonce as is and set active status to true - consumerConfig.active = true; - consumers.push(consumer); - - emit SubscriptionConsumerAdded(subId, consumer); - } - - function _deleteSubscription(uint256 subId) internal returns (uint96 balance, uint96 nativeBalance) { - address[] storage consumers = s_subscriptionConfigs[subId].consumers; - balance = s_subscriptions[subId].balance; - nativeBalance = s_subscriptions[subId].nativeBalance; - // Note bounded by MAX_CONSUMERS; - // If no consumers, does nothing. - uint256 consumersLength = consumers.length; - for (uint256 i = 0; i < consumersLength; ++i) { - delete s_consumers[consumers[i]][subId]; - } - delete s_subscriptionConfigs[subId]; - delete s_subscriptions[subId]; - s_subIds.remove(subId); - if (balance != 0) { - s_totalBalance -= balance; - } - if (nativeBalance != 0) { - s_totalNativeBalance -= nativeBalance; - } - return (balance, nativeBalance); - } - - function _cancelSubscriptionHelper(uint256 subId, address to) internal { - (uint96 balance, uint96 nativeBalance) = _deleteSubscription(subId); - - // Only withdraw LINK if the token is active and there is a balance. - if (address(LINK) != address(0) && balance != 0) { - _requireSufficientBalance(LINK.transfer(to, uint256(balance))); - } - - // send native to the "to" address using call - _mustSendNative(to, uint256(nativeBalance)); - emit SubscriptionCanceled(subId, to, balance, nativeBalance); - } - - modifier onlySubOwner(uint256 subId) { - _onlySubOwner(subId); - _; - } - - function _onlySubOwner(uint256 subId) internal view { - address subOwner = s_subscriptionConfigs[subId].owner; - _requireValidSubscription(subOwner); - if (msg.sender != subOwner) { - revert MustBeSubOwner(subOwner); - } - } - - function _mustSendNative(address to, uint256 amount) internal { - (bool success, ) = to.call{value: amount}(""); - if (!success) { - revert FailedToSendNative(); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol deleted file mode 100644 index b3b77c8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/TrustedBlockhashStore.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ChainSpecificUtil} from "../../ChainSpecificUtil.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {BlockhashStore} from "./BlockhashStore.sol"; - -contract TrustedBlockhashStore is ConfirmedOwner, BlockhashStore { - error NotInWhitelist(); - error InvalidTrustedBlockhashes(); - error InvalidRecentBlockhash(); - - mapping(address => bool) public s_whitelistStatus; - address[] public s_whitelist; - - constructor(address[] memory whitelist) ConfirmedOwner(msg.sender) { - setWhitelist(whitelist); - } - - /** - * @notice sets the whitelist of addresses that can store blockhashes - * @param whitelist the whitelist of addresses that can store blockhashes - */ - function setWhitelist(address[] memory whitelist) public onlyOwner { - address[] memory previousWhitelist = s_whitelist; - s_whitelist = whitelist; - - // Unset whitelist status for all addresses in the previous whitelist, - // and set whitelist status for all addresses in the new whitelist. - for (uint256 i = 0; i < previousWhitelist.length; i++) { - s_whitelistStatus[previousWhitelist[i]] = false; - } - for (uint256 i = 0; i < whitelist.length; i++) { - s_whitelistStatus[whitelist[i]] = true; - } - } - - /** - * @notice stores a list of blockhashes and their respective blocks, only callable - * by a whitelisted address - * @param blockhashes the list of blockhashes and their respective blocks - */ - function storeTrusted( - uint256[] calldata blockNums, - bytes32[] calldata blockhashes, - uint256 recentBlockNumber, - bytes32 recentBlockhash - ) external { - bytes32 onChainHash = ChainSpecificUtil._getBlockhash(uint64(recentBlockNumber)); - if (onChainHash != recentBlockhash) { - revert InvalidRecentBlockhash(); - } - - if (!s_whitelistStatus[msg.sender]) { - revert NotInWhitelist(); - } - - if (blockNums.length != blockhashes.length) { - revert InvalidTrustedBlockhashes(); - } - - for (uint256 i = 0; i < blockNums.length; i++) { - s_blockhashes[blockNums[i]] = blockhashes[i]; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol deleted file mode 100644 index 83600b6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol +++ /dev/null @@ -1,165 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IVRFCoordinatorV2Plus} from "./interfaces/IVRFCoordinatorV2Plus.sol"; -import {IVRFMigratableConsumerV2Plus} from "./interfaces/IVRFMigratableConsumerV2Plus.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. It ensures 2 things: - * @dev 1. The fulfillment came from the VRFCoordinatorV2Plus. - * @dev 2. The consumer contract implements fulfillRandomWords. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBaseV2Plus, and can - * @dev initialize VRFConsumerBaseV2Plus's attributes in their constructor as - * @dev shown: - * - * @dev contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { - * @dev constructor(, address _vrfCoordinator, address _subOwner) - * @dev VRFConsumerBaseV2Plus(_vrfCoordinator, _subOwner) public { - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash). Create a subscription, fund it - * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface - * @dev subscription management functions). - * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, - * @dev callbackGasLimit, numWords, extraArgs), - * @dev see (IVRFCoordinatorV2Plus for a description of the arguments). - * - * @dev Once the VRFCoordinatorV2Plus has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomWords method. - * - * @dev The randomness argument to fulfillRandomWords is a set of random words - * @dev generated from your requestId and the blockHash of the request. - * - * @dev If your contract could have concurrent requests open, you can use the - * @dev requestId returned from requestRandomWords to track which response is associated - * @dev with which randomness request. - * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously. - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBaseV2Plus.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. It is for this reason that - * @dev that you can signal to an oracle you'd like them to wait longer before - * @dev responding to the request (however this is not enforced in the contract - * @dev and so remains effective only in the case of unmodified oracle software). - */ -abstract contract VRFConsumerBaseV2Plus is IVRFMigratableConsumerV2Plus, ConfirmedOwner { - error OnlyCoordinatorCanFulfill(address have, address want); - error OnlyOwnerOrCoordinator(address have, address owner, address coordinator); - error ZeroAddress(); - - // s_vrfCoordinator should be used by consumers to make requests to vrfCoordinator - // so that coordinator reference is updated after migration - IVRFCoordinatorV2Plus public s_vrfCoordinator; - - /** - * @param _vrfCoordinator address of VRFCoordinator contract - */ - constructor(address _vrfCoordinator) ConfirmedOwner(msg.sender) { - if (_vrfCoordinator == address(0)) { - revert ZeroAddress(); - } - s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); - } - - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBaseV2Plus expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomWords the VRF output expanded to the requested number of words - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal virtual; - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) external { - if (msg.sender != address(s_vrfCoordinator)) { - revert OnlyCoordinatorCanFulfill(msg.sender, address(s_vrfCoordinator)); - } - fulfillRandomWords(requestId, randomWords); - } - - /** - * @inheritdoc IVRFMigratableConsumerV2Plus - */ - function setCoordinator(address _vrfCoordinator) external override onlyOwnerOrCoordinator { - if (_vrfCoordinator == address(0)) { - revert ZeroAddress(); - } - s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); - - emit CoordinatorSet(_vrfCoordinator); - } - - modifier onlyOwnerOrCoordinator() { - if (msg.sender != owner() && msg.sender != address(s_vrfCoordinator)) { - revert OnlyOwnerOrCoordinator(msg.sender, owner(), address(s_vrfCoordinator)); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol deleted file mode 100644 index 0de1b42..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Upgradeable.sol +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. It ensures 2 things: - * @dev 1. The fulfillment came from the VRFCoordinator - * @dev 2. The consumer contract implements fulfillRandomWords. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBase, and can - * @dev initialize VRFConsumerBase's attributes in their respective initializer as - * @dev shown: - * - * @dev import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - * @dev contract VRFConsumer is Initializable, VRFConsumerBaseV2Upgradeable { - * @dev initialize(, address _vrfCoordinator) public initializer { - * @dev __VRFConsumerBaseV2_init(_vrfCoordinator); - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash). Create subscription, fund it - * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface - * @dev subscription management functions). - * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, - * @dev callbackGasLimit, numWords), - * @dev see (VRFCoordinatorInterface for a description of the arguments). - * - * @dev Once the VRFCoordinator has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomWords method. - * - * @dev The randomness argument to fulfillRandomWords is a set of random words - * @dev generated from your requestId and the blockHash of the request. - * - * @dev If your contract could have concurrent requests open, you can use the - * @dev requestId returned from requestRandomWords to track which response is associated - * @dev with which randomness request. - * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously. - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. It is for this reason that - * @dev that you can signal to an oracle you'd like them to wait longer before - * @dev responding to the request (however this is not enforced in the contract - * @dev and so remains effective only in the case of unmodified oracle software). - */ - -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - -/** - * @dev The VRFConsumerBaseV2Upgradable is an upgradable variant of VRFConsumerBaseV2 - * @dev (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable). - * @dev It's semantics are identical to VRFConsumerBaseV2 and can be inherited from - * @dev to create an upgradeable VRF consumer contract. - */ -abstract contract VRFConsumerBaseV2Upgradeable is Initializable { - error OnlyCoordinatorCanFulfill(address have, address want); - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - address private vrfCoordinator; - - // See https://github.com/OpenZeppelin/openzeppelin-sdk/issues/37. - // Each uint256 covers a single storage slot, see https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html. - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - uint256[49] private __gap; - - /** - * @param _vrfCoordinator the VRFCoordinatorV2 address. - * @dev See https://docs.chain.link/docs/vrf/v2/supported-networks/ for coordinator - * @dev addresses on your preferred network. - */ - // solhint-disable-next-line func-name-mixedcase - function __VRFConsumerBaseV2_init(address _vrfCoordinator) internal onlyInitializing { - if (_vrfCoordinator == address(0)) { - // solhint-disable-next-line gas-custom-errors - revert("must give valid coordinator address"); - } - - vrfCoordinator = _vrfCoordinator; - } - - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomWords the VRF output expanded to the requested number of words - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { - if (msg.sender != vrfCoordinator) { - revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); - } - fulfillRandomWords(requestId, randomWords); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol deleted file mode 100644 index 53d19c1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol +++ /dev/null @@ -1,791 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BlockhashStoreInterface} from "../interfaces/BlockhashStoreInterface.sol"; -import {VRF} from "../../vrf/VRF.sol"; -import {VRFTypes} from "../VRFTypes.sol"; -import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "./VRFConsumerBaseV2Plus.sol"; -import {SubscriptionAPI} from "./SubscriptionAPI.sol"; -import {VRFV2PlusClient} from "./libraries/VRFV2PlusClient.sol"; -import {IVRFCoordinatorV2PlusMigration} from "./interfaces/IVRFCoordinatorV2PlusMigration.sol"; -// solhint-disable-next-line no-unused-import -import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "./interfaces/IVRFCoordinatorV2Plus.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract VRFCoordinatorV2_5 is VRF, SubscriptionAPI, IVRFCoordinatorV2Plus { - /// @dev should always be available - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - BlockhashStoreInterface public immutable BLOCKHASH_STORE; - - // Set this maximum to 200 to give us a 56 block window to fulfill - // the request before requiring the block hash feeder. - uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; - uint32 public constant MAX_NUM_WORDS = 500; - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - // upper bound limit for premium percentages to make sure fee calculations don't overflow - uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; - error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); - error GasLimitTooBig(uint32 have, uint32 want); - error NumWordsTooBig(uint32 have, uint32 want); - error MsgDataTooBig(uint256 have, uint32 max); - error ProvingKeyAlreadyRegistered(bytes32 keyHash); - error NoSuchProvingKey(bytes32 keyHash); - error InvalidLinkWeiPrice(int256 linkWei); - error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); - error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); - error NoCorrespondingRequest(); - error IncorrectCommitment(); - error BlockhashNotInStore(uint256 blockNum); - error PaymentTooLarge(); - error InvalidExtraArgsTag(); - error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); - - struct ProvingKey { - bool exists; // proving key exists - uint64 maxGas; // gas lane max gas price for fulfilling requests - } - - mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; - bytes32[] public s_provingKeyHashes; - mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); - event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - - event L1GasFee(uint256 fee); - - int256 public s_fallbackWeiPerUnitLink; - - event ConfigSet( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ); - - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - - constructor(address blockhashStore) SubscriptionAPI() { - BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); - } - - /** - * @notice Registers a proving key to. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh].exists) { - revert ProvingKeyAlreadyRegistered(kh); - } - s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); - s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, maxGas); - } - - /** - * @notice Deregisters a proving key. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - ProvingKey memory key = s_provingKeys[kh]; - if (!key.exists) { - revert NoSuchProvingKey(kh); - } - delete s_provingKeys[kh]; - uint256 s_provingKeyHashesLength = s_provingKeyHashes.length; - for (uint256 i = 0; i < s_provingKeyHashesLength; ++i) { - if (s_provingKeyHashes[i] == kh) { - // Copy last element and overwrite kh to be deleted with it - s_provingKeyHashes[i] = s_provingKeyHashes[s_provingKeyHashesLength - 1]; - s_provingKeyHashes.pop(); - break; - } - } - emit ProvingKeyDeregistered(kh, key.maxGas); - } - - /** - * @notice Returns the proving key hash key associated with this public key - * @param publicKey the key to return the hash of - */ - function hashOfKey(uint256[2] calldata publicKey) public pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed - * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment - * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native - * @param nativePremiumPercentage native premium percentage - * @param linkPremiumPercentage link premium percentage - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ) external onlyOwner { - if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { - revert InvalidRequestConfirmations( - minimumRequestConfirmations, - minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - if (fallbackWeiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); - } - if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { - revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); - } - if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - s_config = Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - reentrancyLock: false, - fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage: nativePremiumPercentage, - linkPremiumPercentage: linkPremiumPercentage - }); - s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; - emit ConfigSet( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage, - linkPremiumPercentage - ); - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @return The extra args struct - function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { - if (extraArgs.length == 0) { - return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); - } - if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); - } - - /** - * @notice Request a set of random words. - * @param req - a struct containing following fiels for randomness request: - * keyHash - Corresponds to a particular oracle job which uses - * that key for generating the VRF proof. Different keyHash's have different gas price - * ceilings, so you can select a specific one to bound your maximum per request cost. - * subId - The ID of the VRF subscription. Must be funded - * with the minimum subscription balance required for the selected keyHash. - * requestConfirmations - How many blocks you'd like the - * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS - * for why you may want to request more. The acceptable range is - * [minimumRequestBlockConfirmations, 200]. - * callbackGasLimit - How much gas you'd like to receive in your - * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords - * may be slightly less than this amount because of gas used calling the function - * (argument decoding etc.), so you may need to request slightly more than you expect - * to have inside fulfillRandomWords. The acceptable range is - * [0, maxGasLimit] - * numWords - The number of uint256 random values you'd like to receive - * in your fulfillRandomWords callback. Note these numbers are expanded in a - * secure way by the VRFCoordinator from a single random value supplied by the oracle. - * extraArgs - Encoded extra arguments that has a boolean flag for whether payment - * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. - * @return requestId - A unique identifier of the request. Can be used to match - * a request to a response in fulfillRandomWords. - */ - function requestRandomWords( - VRFV2PlusClient.RandomWordsRequest calldata req - ) external override nonReentrant returns (uint256 requestId) { - // Input validation using the subscription storage. - uint256 subId = req.subId; - _requireValidSubscription(s_subscriptionConfigs[subId].owner); - // Its important to ensure that the consumer is in fact who they say they - // are, otherwise they could use someone else's subscription balance. - mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; - ConsumerConfig memory consumerConfig = consumerConfigs[subId]; - if (!consumerConfig.active) { - revert InvalidConsumer(subId, msg.sender); - } - // Input validation using the config storage word. - if ( - req.requestConfirmations < s_config.minimumRequestConfirmations || - req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS - ) { - revert InvalidRequestConfirmations( - req.requestConfirmations, - s_config.minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - // No lower bound on the requested gas limit. A user could request 0 - // and they would simply be billed for the proof verification and wouldn't be - // able to do anything with the random value. - if (req.callbackGasLimit > s_config.maxGasLimit) { - revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); - } - if (req.numWords > MAX_NUM_WORDS) { - revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); - } - - // Note we do not check whether the keyHash is valid to save gas. - // The consequence for users is that they can send requests - // for invalid keyHashes which will simply not be fulfilled. - ++consumerConfig.nonce; - ++consumerConfig.pendingReqCount; - uint256 preSeed; - (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); - - bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); - s_requestCommitments[requestId] = keccak256( - abi.encode(requestId, _getBlockNumber(), subId, req.callbackGasLimit, req.numWords, msg.sender, extraArgsBytes) - ); - emit RandomWordsRequested( - req.keyHash, - requestId, - preSeed, - subId, - req.requestConfirmations, - req.callbackGasLimit, - req.numWords, - extraArgsBytes, - msg.sender - ); - consumerConfigs[subId] = consumerConfig; - - return requestId; - } - - function _computeRequestId( - bytes32 keyHash, - address sender, - uint256 subId, - uint64 nonce - ) internal pure returns (uint256, uint256) { - uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); - return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - struct Output { - ProvingKey provingKey; - uint256 requestId; - uint256 randomness; - } - - function _getRandomnessFromProof( - Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc - ) internal view returns (Output memory) { - bytes32 keyHash = hashOfKey(proof.pk); - ProvingKey memory key = s_provingKeys[keyHash]; - // Only registered proving keys are permitted. - if (!key.exists) { - revert NoSuchProvingKey(keyHash); - } - uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); - bytes32 commitment = s_requestCommitments[requestId]; - if (commitment == 0) { - revert NoCorrespondingRequest(); - } - if ( - commitment != - keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) - ) { - revert IncorrectCommitment(); - } - - bytes32 blockHash = _getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - revert BlockhashNotInStore(rc.blockNum); - } - } - - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); - uint256 randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - return Output(key, requestId, randomness); - } - - function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { - if (tx.gasprice > gasLaneMaxGas) { - if (onlyPremium) { - // if only the premium amount needs to be billed, then the premium is capped by the gas lane max - return uint256(gasLaneMaxGas); - } else { - // Ensure gas price does not exceed the gas lane max gas price - revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); - } - } - return tx.gasprice; - } - - function _deliverRandomness( - uint256 requestId, - VRFTypes.RequestCommitmentV2Plus calldata rc, - uint256[] memory randomWords - ) internal returns (bool success) { - VRFConsumerBaseV2Plus v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that _callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; - return success; - } - - /* - * @notice Fulfill a randomness request. - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - * @param onlyPremium only charge premium - * @return payment amount billed to the subscription - * @dev simulated offchain to determine if sufficient balance is present to fulfill the request - */ - function fulfillRandomWords( - Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc, - bool onlyPremium - ) external nonReentrant returns (uint96 payment) { - uint256 startGas = gasleft(); - // fulfillRandomWords msg.data has 772 bytes and with an additional - // buffer of 32 bytes, we get 804 bytes. - /* Data size split: - * fulfillRandomWords function signature - 4 bytes - * proof - 416 bytes - * pk - 64 bytes - * gamma - 64 bytes - * c - 32 bytes - * s - 32 bytes - * seed - 32 bytes - * uWitness - 32 bytes - * cGammaWitness - 64 bytes - * sHashWitness - 64 bytes - * zInv - 32 bytes - * requestCommitment - 320 bytes - * blockNum - 32 bytes - * subId - 32 bytes - * callbackGasLimit - 32 bytes - * numWords - 32 bytes - * sender - 32 bytes - * extraArgs - 128 bytes - * onlyPremium - 32 bytes - */ - if (msg.data.length > 804) { - revert MsgDataTooBig(msg.data.length, 804); - } - Output memory output = _getRandomnessFromProof(proof, rc); - uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); - - uint256[] memory randomWords; - uint256 randomness = output.randomness; - // stack too deep error - { - uint256 numWords = rc.numWords; - randomWords = new uint256[](numWords); - for (uint256 i = 0; i < numWords; ++i) { - randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); - } - } - - delete s_requestCommitments[output.requestId]; - bool success = _deliverRandomness(output.requestId, rc, randomWords); - - // Increment the req count for the subscription. - ++s_subscriptions[rc.subId].reqCount; - // Decrement the pending req count for the consumer. - --s_consumers[rc.sender][rc.subId].pendingReqCount; - - bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; - - // stack too deep error - { - // We want to charge users exactly for how much gas they use in their callback with - // an additional premium. If onlyPremium is true, only premium is charged without - // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional - // operations where we decrement the subscription balance and increment the - // withdrawable balance. - bool isFeedStale; - (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); - if (isFeedStale) { - emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); - } - } - - _chargePayment(payment, nativePayment, rc.subId); - - // Include payment in the event for tracking costs. - emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); - - return payment; - } - - function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { - Subscription storage subcription = s_subscriptions[subId]; - if (nativePayment) { - uint96 prevBal = subcription.nativeBalance; - _requireSufficientBalance(prevBal >= payment); - subcription.nativeBalance = prevBal - payment; - s_withdrawableNative += payment; - } else { - uint96 prevBal = subcription.balance; - _requireSufficientBalance(prevBal >= payment); - subcription.balance = prevBal - payment; - s_withdrawableTokens += payment; - } - } - - function _calculatePaymentAmount( - uint256 startGas, - uint256 weiPerUnitGas, - bool nativePayment, - bool onlyPremium - ) internal returns (uint96, bool) { - if (nativePayment) { - return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); - } - return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); - } - - function _calculatePaymentAmountNative( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal returns (uint96) { - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = _getL1CostWei(msg.data); - // calculate the payment without the premium - uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); - // calculate flat fee in native - uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); - // emit this event only if this is an L2 chain that needs to cover for L1 gas fees - if (l1CostWei > 0) { - emit L1GasFee(l1CostWei); - } - if (onlyPremium) { - return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } else { - return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } - } - - // Get the amount of gas used for fulfillment - function _calculatePaymentAmountLink( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal returns (uint96, bool) { - (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = _getL1CostWei(msg.data); - // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * - (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / - uint256(weiPerUnitLink); - // calculate the flat fee in wei - uint256 flatFeeWei = 1e12 * - uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); - uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); - // emit this event only if this is an L2 chain that needs to cover for L1 gas fees - if (l1CostWei > 0) { - emit L1GasFee(l1CostWei); - } - uint256 payment; - if (onlyPremium) { - payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } else { - payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } - if (payment > 1e27) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return (uint96(payment), isFeedStale); - } - - function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - uint256 timestamp; - (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; - if (isFeedStale) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return (weiPerUnitLink, isFeedStale); - } - - /** - * @notice Returns the block number of the current block by using specific opcode. - * @notice Override this function in chain specific way if needed (L2 chains). - */ - function _getBlockNumber() internal view virtual returns (uint256) { - return block.number; - } - - /** - * @notice Returns the blockhash for the given blockNumber by using specific opcode. - * @notice If the blockNumber is more than 256 blocks in the past, returns the empty string. - * @notice Override this function in chain specific way if needed (L2 chains). - */ - function _getBlockhash(uint64 blockNumber) internal view virtual returns (bytes32) { - return blockhash(blockNumber); - } - - /** - * @notice Returns the L1 fee for the calldata payload (always return 0 on L1 chains). - * @notice Override this function in chain specific way for L2 chains. - */ - function _getL1CostWei(bytes calldata /* data */) internal view virtual returns (uint256) { - return 0; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function pendingRequestExists(uint256 subId) public view override returns (bool) { - address[] storage consumers = s_subscriptionConfigs[subId].consumers; - uint256 consumersLength = consumers.length; - for (uint256 i = 0; i < consumersLength; ++i) { - if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { - return true; - } - } - return false; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - if (!s_consumers[consumer][subId].active) { - revert InvalidConsumer(subId, consumer); - } - // Note bounded by MAX_CONSUMERS - address[] storage s_subscriptionConsumers = s_subscriptionConfigs[subId].consumers; - uint256 consumersLength = s_subscriptionConsumers.length; - for (uint256 i = 0; i < consumersLength; ++i) { - if (s_subscriptionConsumers[i] == consumer) { - // Storage write to preserve last element - s_subscriptionConsumers[i] = s_subscriptionConsumers[consumersLength - 1]; - // Storage remove last element - s_subscriptionConsumers.pop(); - break; - } - } - s_consumers[consumer][subId].active = false; - emit SubscriptionConsumerRemoved(subId, consumer); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - _cancelSubscriptionHelper(subId, to); - } - - /*************************************************************************** - * Section: Migration - ***************************************************************************/ - - address[] internal s_migrationTargets; - - /// @dev Emitted when new coordinator is registered as migratable target - event CoordinatorRegistered(address coordinatorAddress); - - /// @dev Emitted when new coordinator is deregistered - event CoordinatorDeregistered(address coordinatorAddress); - - /// @notice emitted when migration to new coordinator completes successfully - /// @param newCoordinator coordinator address after migration - /// @param subId subscription ID - event MigrationCompleted(address newCoordinator, uint256 subId); - - /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target - error CoordinatorNotRegistered(address coordinatorAddress); - - /// @notice emitted when migrate() is called and given coordinator is registered as migratable target - error CoordinatorAlreadyRegistered(address coordinatorAddress); - - /// @dev encapsulates data to be migrated from current coordinator - // solhint-disable-next-line gas-struct-packing - struct V1MigrationData { - uint8 fromVersion; - uint256 subId; - address subOwner; - address[] consumers; - uint96 linkBalance; - uint96 nativeBalance; - } - - function _isTargetRegistered(address target) internal view returns (bool) { - uint256 migrationTargetsLength = s_migrationTargets.length; - for (uint256 i = 0; i < migrationTargetsLength; ++i) { - if (s_migrationTargets[i] == target) { - return true; - } - } - return false; - } - - function registerMigratableCoordinator(address target) external onlyOwner { - if (_isTargetRegistered(target)) { - revert CoordinatorAlreadyRegistered(target); - } - s_migrationTargets.push(target); - emit CoordinatorRegistered(target); - } - - function deregisterMigratableCoordinator(address target) external onlyOwner { - uint256 nTargets = s_migrationTargets.length; - for (uint256 i = 0; i < nTargets; ++i) { - if (s_migrationTargets[i] == target) { - s_migrationTargets[i] = s_migrationTargets[nTargets - 1]; - s_migrationTargets.pop(); - emit CoordinatorDeregistered(target); - return; - } - } - revert CoordinatorNotRegistered(target); - } - - function migrate(uint256 subId, address newCoordinator) external nonReentrant { - if (!_isTargetRegistered(newCoordinator)) { - revert CoordinatorNotRegistered(newCoordinator); - } - (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); - if (subOwner != msg.sender) { - revert MustBeSubOwner(subOwner); - } - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - - V1MigrationData memory migrationData = V1MigrationData({ - fromVersion: 1, - subId: subId, - subOwner: subOwner, - consumers: consumers, - linkBalance: balance, - nativeBalance: nativeBalance - }); - bytes memory encodedData = abi.encode(migrationData); - _deleteSubscription(subId); - IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); - - // Only transfer LINK if the token is active and there is a balance. - if (address(LINK) != address(0) && balance != 0) { - _requireSufficientBalance(LINK.transfer(address(newCoordinator), balance)); - } - - // despite the fact that we follow best practices this is still probably safest - // to prevent any re-entrancy possibilities. - s_config.reentrancyLock = true; - uint256 consumersLength = consumers.length; - for (uint256 i = 0; i < consumersLength; ++i) { - IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); - } - s_config.reentrancyLock = false; - - emit MigrationCompleted(newCoordinator, subId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol deleted file mode 100644 index 9b2357c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Arbitrum.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {VRFCoordinatorV2_5} from "./VRFCoordinatorV2_5.sol"; -import {ArbitrumL1Fees} from "./ArbitrumL1Fees.sol"; - -/// @dev VRFCoordinatorV2_5_Arbitrum combines VRFCoordinatorV2_5 base contract with -/// @dev Arbitrum specific opcodes and L1 gas fee calculations. -// solhint-disable-next-line contract-name-camelcase -contract VRFCoordinatorV2_5_Arbitrum is VRFCoordinatorV2_5, ArbitrumL1Fees { - /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - - constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} - - /** - * @notice Override getBlockhash from VRFCoordinatorV2_5 - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockHash to get the blockhash. - */ - function _getBlockhash(uint64 blockNumber) internal view override returns (bytes32) { - uint64 currentBlockNumber = uint64(_getBlockNumber()); - if (blockNumber >= currentBlockNumber || (currentBlockNumber - blockNumber) > 256) { - return ""; - } - return ARBSYS.arbBlockHash(blockNumber); - } - - /** - * @notice Override getBlockNumber from VRFCoordinatorV2_5 - * @notice When on a known Arbitrum chain, it uses ArbSys.arbBlockNumber to get the block number. - */ - function _getBlockNumber() internal view override returns (uint256) { - return ARBSYS.arbBlockNumber(); - } - - /// @notice Override getL1CostWei function from VRFCoordinatorV2_5 to activate Arbitrum getL1Fee computation - function _getL1CostWei(bytes calldata /* data */) internal view override returns (uint256) { - return _getL1CostWeiForCalldata(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol deleted file mode 100644 index ce5abbe..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFCoordinatorV2_5_Optimism.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {VRFCoordinatorV2_5} from "./VRFCoordinatorV2_5.sol"; -import {OptimismL1Fees} from "./OptimismL1Fees.sol"; - -/// @dev VRFCoordinatorV2_5_Optimism combines VRFCoordinatorV2_5 base contract with -/// @dev Optimism specific opcodes and L1 gas fee calculations. -/// @dev This coordinator contract is used for all chains in the OP stack (e.g. Base). -// solhint-disable-next-line contract-name-camelcase -contract VRFCoordinatorV2_5_Optimism is VRFCoordinatorV2_5, OptimismL1Fees { - constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} - - /// @notice no need to override getBlockhash and getBlockNumber from VRFCoordinatorV2_5 - /// @notice on OP stack, they will work with the default implementation - - /// @notice Override getL1CostWei function from VRFCoordinatorV2_5 to activate Optimism getL1Fee computation - function _getL1CostWei(bytes calldata data) internal view override returns (uint256) { - return _getL1CostWeiForCalldata(data); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol deleted file mode 100644 index 58dd25c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFSubscriptionBalanceMonitor.sol +++ /dev/null @@ -1,281 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {AutomationCompatibleInterface as KeeperCompatibleInterface} from "../../automation/interfaces/AutomationCompatibleInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; - -/** - * @title The VRFSubscriptionBalanceMonitor contract. - * @notice A keeper-compatible contract that monitors and funds VRF subscriptions. - */ -contract VRFSubscriptionBalanceMonitor is ConfirmedOwner, Pausable, KeeperCompatibleInterface { - VRFCoordinatorV2Interface public COORDINATOR; - LinkTokenInterface public LINKTOKEN; - - uint256 private constant MIN_GAS_FOR_TRANSFER = 55_000; - - event FundsAdded(uint256 amountAdded, uint256 newBalance, address sender); - event FundsWithdrawn(uint256 amountWithdrawn, address payee); - event TopUpSucceeded(uint64 indexed subscriptionId); - event TopUpFailed(uint64 indexed subscriptionId); - event KeeperRegistryAddressUpdated(address oldAddress, address newAddress); - event VRFCoordinatorV2AddressUpdated(address oldAddress, address newAddress); - event LinkTokenAddressUpdated(address oldAddress, address newAddress); - event MinWaitPeriodUpdated(uint256 oldMinWaitPeriod, uint256 newMinWaitPeriod); - event OutOfGas(uint256 lastId); - - error InvalidWatchList(); - error OnlyKeeperRegistry(); - error DuplicateSubcriptionId(uint64 duplicate); - - struct Target { - bool isActive; - uint96 minBalanceJuels; - uint96 topUpAmountJuels; - uint56 lastTopUpTimestamp; - } - - address public s_keeperRegistryAddress; // the address of the keeper registry - uint256 public s_minWaitPeriodSeconds; // minimum time to wait between top-ups - uint64[] public s_watchList; // the watchlist on which subscriptions are stored - mapping(uint64 => Target) internal s_targets; - - /** - * @param linkTokenAddress the Link token address - * @param coordinatorAddress the address of the vrf coordinator contract - * @param keeperRegistryAddress the address of the keeper registry contract - * @param minWaitPeriodSeconds the minimum wait period for addresses between funding - */ - constructor( - address linkTokenAddress, - address coordinatorAddress, - address keeperRegistryAddress, - uint256 minWaitPeriodSeconds - ) ConfirmedOwner(msg.sender) { - setLinkTokenAddress(linkTokenAddress); - setVRFCoordinatorV2Address(coordinatorAddress); - setKeeperRegistryAddress(keeperRegistryAddress); - setMinWaitPeriodSeconds(minWaitPeriodSeconds); - } - - /** - * @notice Sets the list of subscriptions to watch and their funding parameters. - * @param subscriptionIds the list of subscription ids to watch - * @param minBalancesJuels the minimum balances for each subscription - * @param topUpAmountsJuels the amount to top up each subscription - */ - function setWatchList( - uint64[] calldata subscriptionIds, - uint96[] calldata minBalancesJuels, - uint96[] calldata topUpAmountsJuels - ) external onlyOwner { - if (subscriptionIds.length != minBalancesJuels.length || subscriptionIds.length != topUpAmountsJuels.length) { - revert InvalidWatchList(); - } - uint64[] memory oldWatchList = s_watchList; - for (uint256 idx = 0; idx < oldWatchList.length; idx++) { - s_targets[oldWatchList[idx]].isActive = false; - } - for (uint256 idx = 0; idx < subscriptionIds.length; idx++) { - if (s_targets[subscriptionIds[idx]].isActive) { - revert DuplicateSubcriptionId(subscriptionIds[idx]); - } - if (subscriptionIds[idx] == 0) { - revert InvalidWatchList(); - } - if (topUpAmountsJuels[idx] <= minBalancesJuels[idx]) { - revert InvalidWatchList(); - } - s_targets[subscriptionIds[idx]] = Target({ - isActive: true, - minBalanceJuels: minBalancesJuels[idx], - topUpAmountJuels: topUpAmountsJuels[idx], - lastTopUpTimestamp: 0 - }); - } - s_watchList = subscriptionIds; - } - - /** - * @notice Gets a list of subscriptions that are underfunded. - * @return list of subscriptions that are underfunded - */ - function getUnderfundedSubscriptions() public view returns (uint64[] memory) { - uint64[] memory watchList = s_watchList; - uint64[] memory needsFunding = new uint64[](watchList.length); - uint256 count = 0; - uint256 minWaitPeriod = s_minWaitPeriodSeconds; - uint256 contractBalance = LINKTOKEN.balanceOf(address(this)); - Target memory target; - for (uint256 idx = 0; idx < watchList.length; idx++) { - target = s_targets[watchList[idx]]; - (uint96 subscriptionBalance, , , ) = COORDINATOR.getSubscription(watchList[idx]); - if ( - target.lastTopUpTimestamp + minWaitPeriod <= block.timestamp && - contractBalance >= target.topUpAmountJuels && - subscriptionBalance < target.minBalanceJuels - ) { - needsFunding[count] = watchList[idx]; - count++; - contractBalance -= target.topUpAmountJuels; - } - } - if (count < watchList.length) { - assembly { - mstore(needsFunding, count) - } - } - return needsFunding; - } - - /** - * @notice Send funds to the subscriptions provided. - * @param needsFunding the list of subscriptions to fund - */ - function topUp(uint64[] memory needsFunding) public whenNotPaused { - uint256 minWaitPeriodSeconds = s_minWaitPeriodSeconds; - uint256 contractBalance = LINKTOKEN.balanceOf(address(this)); - Target memory target; - for (uint256 idx = 0; idx < needsFunding.length; idx++) { - target = s_targets[needsFunding[idx]]; - (uint96 subscriptionBalance, , , ) = COORDINATOR.getSubscription(needsFunding[idx]); - if ( - target.isActive && - target.lastTopUpTimestamp + minWaitPeriodSeconds <= block.timestamp && - subscriptionBalance < target.minBalanceJuels && - contractBalance >= target.topUpAmountJuels - ) { - bool success = LINKTOKEN.transferAndCall( - address(COORDINATOR), - target.topUpAmountJuels, - abi.encode(needsFunding[idx]) - ); - if (success) { - s_targets[needsFunding[idx]].lastTopUpTimestamp = uint56(block.timestamp); - contractBalance -= target.topUpAmountJuels; - emit TopUpSucceeded(needsFunding[idx]); - } else { - emit TopUpFailed(needsFunding[idx]); - } - } - if (gasleft() < MIN_GAS_FOR_TRANSFER) { - emit OutOfGas(idx); - return; - } - } - } - - /** - * @notice Gets list of subscription ids that are underfunded and returns a keeper-compatible payload. - * @return upkeepNeeded signals if upkeep is needed, performData is an abi encoded list of subscription ids that need funds - */ - function checkUpkeep( - bytes calldata - ) external view override whenNotPaused returns (bool upkeepNeeded, bytes memory performData) { - uint64[] memory needsFunding = getUnderfundedSubscriptions(); - upkeepNeeded = needsFunding.length > 0; - performData = abi.encode(needsFunding); - return (upkeepNeeded, performData); - } - - /** - * @notice Called by the keeper to send funds to underfunded addresses. - * @param performData the abi encoded list of addresses to fund - */ - function performUpkeep(bytes calldata performData) external override onlyKeeperRegistry whenNotPaused { - uint64[] memory needsFunding = abi.decode(performData, (uint64[])); - topUp(needsFunding); - } - - /** - * @notice Withdraws the contract balance in LINK. - * @param amount the amount of LINK (in juels) to withdraw - * @param payee the address to pay - */ - function withdraw(uint256 amount, address payable payee) external onlyOwner { - // solhint-disable-next-line gas-custom-errors, reason-string - require(payee != address(0)); - emit FundsWithdrawn(amount, payee); - LINKTOKEN.transfer(payee, amount); - } - - /** - * @notice Sets the LINK token address. - */ - function setLinkTokenAddress(address linkTokenAddress) public onlyOwner { - // solhint-disable-next-line gas-custom-errors, reason-string - require(linkTokenAddress != address(0)); - emit LinkTokenAddressUpdated(address(LINKTOKEN), linkTokenAddress); - LINKTOKEN = LinkTokenInterface(linkTokenAddress); - } - - /** - * @notice Sets the VRF coordinator address. - */ - function setVRFCoordinatorV2Address(address coordinatorAddress) public onlyOwner { - // solhint-disable-next-line gas-custom-errors, reason-string - require(coordinatorAddress != address(0)); - emit VRFCoordinatorV2AddressUpdated(address(COORDINATOR), coordinatorAddress); - COORDINATOR = VRFCoordinatorV2Interface(coordinatorAddress); - } - - /** - * @notice Sets the keeper registry address. - */ - function setKeeperRegistryAddress(address keeperRegistryAddress) public onlyOwner { - // solhint-disable-next-line gas-custom-errors, reason-string - require(keeperRegistryAddress != address(0)); - emit KeeperRegistryAddressUpdated(s_keeperRegistryAddress, keeperRegistryAddress); - s_keeperRegistryAddress = keeperRegistryAddress; - } - - /** - * @notice Sets the minimum wait period (in seconds) for subscription ids between funding. - */ - function setMinWaitPeriodSeconds(uint256 period) public onlyOwner { - emit MinWaitPeriodUpdated(s_minWaitPeriodSeconds, period); - s_minWaitPeriodSeconds = period; - } - - /** - * @notice Gets configuration information for a subscription on the watchlist. - */ - function getSubscriptionInfo( - uint64 subscriptionId - ) external view returns (bool isActive, uint96 minBalanceJuels, uint96 topUpAmountJuels, uint56 lastTopUpTimestamp) { - Target memory target = s_targets[subscriptionId]; - return (target.isActive, target.minBalanceJuels, target.topUpAmountJuels, target.lastTopUpTimestamp); - } - - /** - * @notice Gets the list of subscription ids being watched. - */ - function getWatchList() external view returns (uint64[] memory) { - return s_watchList; - } - - /** - * @notice Pause the contract, which prevents executing performUpkeep. - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice Unpause the contract. - */ - function unpause() external onlyOwner { - _unpause(); - } - - modifier onlyKeeperRegistry() { - if (msg.sender != s_keeperRegistryAddress) { - revert OnlyKeeperRegistry(); - } - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol deleted file mode 100644 index 40fd8a9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol +++ /dev/null @@ -1,725 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {VRFConsumerBaseV2Plus} from "./VRFConsumerBaseV2Plus.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {VRFV2PlusClient} from "./libraries/VRFV2PlusClient.sol"; -import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol"; -import {VRFV2PlusWrapperConsumerBase} from "./VRFV2PlusWrapperConsumerBase.sol"; - -/** - * @notice A wrapper for VRFCoordinatorV2 that provides an interface better suited to one-off - * @notice requests for randomness. - */ -// solhint-disable-next-line max-states-count -contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsumerBaseV2Plus, IVRFV2PlusWrapper { - event WrapperFulfillmentFailed(uint256 indexed requestId, address indexed consumer); - - // upper bound limit for premium percentages to make sure fee calculations don't overflow - uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; - - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - uint16 private constant EXPECTED_MIN_LENGTH = 36; - - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - uint256 public immutable SUBSCRIPTION_ID; - LinkTokenInterface internal immutable i_link; - AggregatorV3Interface internal immutable i_link_native_feed; - - event FulfillmentTxSizeSet(uint32 size); - event ConfigSet( - uint32 wrapperGasOverhead, - uint32 coordinatorGasOverheadNative, - uint32 coordinatorGasOverheadLink, - uint16 coordinatorGasOverheadPerWord, - uint8 coordinatorNativePremiumPercentage, - uint8 coordinatorLinkPremiumPercentage, - bytes32 keyHash, - uint8 maxNumWords, - uint32 stalenessSeconds, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM - ); - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - event Withdrawn(address indexed to, uint256 amount); - event NativeWithdrawn(address indexed to, uint256 amount); - event Enabled(); - event Disabled(); - - error LinkAlreadySet(); - error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); - error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); - error FailedToTransferLink(); - error IncorrectExtraArgsLength(uint16 expectedMinimumLength, uint16 actualLength); - error NativePaymentInOnTokenTransfer(); - error LINKPaymentInRequestRandomWordsInNative(); - error SubscriptionIdMissing(); - - /* Storage Slot 1: BEGIN */ - // 20 bytes used by VRFConsumerBaseV2Plus.s_vrfCoordinator - - // s_configured tracks whether this contract has been configured. If not configured, randomness - // requests cannot be made. - bool public s_configured; - - // s_disabled disables the contract when true. When disabled, new VRF requests cannot be made - // but existing ones can still be fulfilled. - bool public s_disabled; - - // s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request. - uint8 internal s_maxNumWords; - - // 9 bytes left - /* Storage Slot 1: END */ - - /* Storage Slot 2: BEGIN */ - // s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas - // fees, so this should be set to the highest gas lane on the network. - bytes32 internal s_keyHash; - /* Storage Slot 2: END */ - - /* Storage Slot 3: BEGIN */ - // lastRequestId is the request ID of the most recent VRF V2 request made by this wrapper. This - // should only be relied on within the same transaction the request was made. - uint256 public override lastRequestId; - /* Storage Slot 3: END */ - - /* Storage Slot 4: BEGIN */ - // s_fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed is - // stale. - int256 private s_fallbackWeiPerUnitLink; - /* Storage Slot 4: END */ - - /* Storage Slot 5: BEGIN */ - // s_stalenessSeconds is the number of seconds before we consider the feed price to be stale and - // fallback to fallbackWeiPerUnitLink. - uint32 private s_stalenessSeconds; - - // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - // function. The cost for this gas is passed to the user. - uint32 private s_wrapperGasOverhead; - - // Configuration fetched from VRFCoordinatorV2_5 - - /// @dev this is the size of a VRF v2plus fulfillment's calldata abi-encoded in bytes. - /// @dev proofSize = 13 words = 13 * 256 = 3328 bits - /// @dev commitmentSize = 10 words = 10 * 256 = 2560 bits - /// @dev onlyPremiumParameterSize = 256 bits - /// @dev dataSize = proofSize + commitmentSize + onlyPremiumParameterSize = 6144 bits - /// @dev function selector = 32 bits - /// @dev total data size = 6144 bits + 32 bits = 6176 bits = 772 bytes - uint32 public s_fulfillmentTxSizeBytes = 772; - - // s_coordinatorGasOverheadNative reflects the gas overhead of the coordinator's fulfillRandomWords - // function for native payment. The cost for this gas is billed to the subscription, and must therefor be included - // in the pricing for wrapped requests. This includes the gas costs of proof verification and - // payment calculation in the coordinator. - uint32 private s_coordinatorGasOverheadNative; - - // s_coordinatorGasOverheadLink reflects the gas overhead of the coordinator's fulfillRandomWords - // function for link payment. The cost for this gas is billed to the subscription, and must therefor be included - // in the pricing for wrapped requests. This includes the gas costs of proof verification and - // payment calculation in the coordinator. - uint32 private s_coordinatorGasOverheadLink; - - uint16 private s_coordinatorGasOverheadPerWord; - - // s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of native that VRFCoordinatorV2 - // charges for native payment. - uint32 private s_fulfillmentFlatFeeNativePPM; - - // s_fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2 - // charges for link payment. - uint32 private s_fulfillmentFlatFeeLinkDiscountPPM; - - // s_coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for native payment. - // For example, a value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. - // Wrapper has no premium. This premium is for VRFCoordinator. - uint8 private s_coordinatorNativePremiumPercentage; - - // s_coordinatorLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a - // value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. - // Wrapper has no premium. This premium is for VRFCoordinator. - uint8 private s_coordinatorLinkPremiumPercentage; - /* Storage Slot 5: END */ - - struct Callback { - address callbackAddress; - uint32 callbackGasLimit; - // Reducing requestGasPrice from uint256 to uint64 slots Callback struct - // into a single word, thus saving an entire SSTORE and leading to 21K - // gas cost saving. 18 ETH would be the max gas price we can process. - // GasPrice is unlikely to be more than 14 ETH on most chains - uint64 requestGasPrice; - } - /* Storage Slot 6: BEGIN */ - mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; - /* Storage Slot 6: END */ - - constructor( - address _link, - address _linkNativeFeed, - address _coordinator, - uint256 _subId - ) VRFConsumerBaseV2Plus(_coordinator) { - i_link = LinkTokenInterface(_link); - i_link_native_feed = AggregatorV3Interface(_linkNativeFeed); - - if (_subId == 0) { - revert SubscriptionIdMissing(); - } - - // Sanity check: should revert if the subscription does not exist - s_vrfCoordinator.getSubscription(_subId); - - // Subscription for the wrapper is created and managed by an external account. - // Expectation is that wrapper contract address will be added as a consumer - // to this subscription by the external account (owner of the subscription). - // Migration of the wrapper's subscription to the new coordinator has to be - // handled by the external account (owner of the subscription). - SUBSCRIPTION_ID = _subId; - } - - /** - * @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes. - * @param _size is the size of the fulfillment transaction in bytes. - */ - function setFulfillmentTxSize(uint32 _size) external onlyOwner { - s_fulfillmentTxSizeBytes = _size; - - emit FulfillmentTxSizeSet(_size); - } - - /** - * @notice setConfig configures VRFV2Wrapper. - * - * @dev Sets wrapper-specific configuration based on the given parameters, and fetches any needed - * @dev VRFCoordinatorV2 configuration from the coordinator. - * - * @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - * function. - * - * @param _coordinatorGasOverheadNative reflects the gas overhead of the coordinator's - * fulfillRandomWords function for native payment. - * - * @param _coordinatorGasOverheadLink reflects the gas overhead of the coordinator's - * fulfillRandomWords function for link payment. - * - * @param _coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's - * fulfillRandomWords function. - * - * @param _coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for requests paid in native. - * - * @param _coordinatorLinkPremiumPercentage is the coordinator's premium ratio in percentage for requests paid in link. - * - * @param _keyHash to use for requesting randomness. - * @param _maxNumWords is the max number of words that can be requested in a single wrapped VRF request - * @param _stalenessSeconds is the number of seconds before we consider the feed price to be stale - * and fallback to fallbackWeiPerUnitLink. - * - * @param _fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed - * is stale. - * - * @param _fulfillmentFlatFeeNativePPM is the flat fee in millionths of native that VRFCoordinatorV2Plus - * charges for native payment. - * - * @param _fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2Plus - * charges for link payment. - */ - /// @dev This function while having only 12 parameters is causing a Stack too deep error when running forge coverage. - function setConfig( - uint32 _wrapperGasOverhead, - uint32 _coordinatorGasOverheadNative, - uint32 _coordinatorGasOverheadLink, - uint16 _coordinatorGasOverheadPerWord, - uint8 _coordinatorNativePremiumPercentage, - uint8 _coordinatorLinkPremiumPercentage, - bytes32 _keyHash, - uint8 _maxNumWords, - uint32 _stalenessSeconds, - int256 _fallbackWeiPerUnitLink, - uint32 _fulfillmentFlatFeeNativePPM, - uint32 _fulfillmentFlatFeeLinkDiscountPPM - ) external onlyOwner { - if (_fulfillmentFlatFeeLinkDiscountPPM > _fulfillmentFlatFeeNativePPM) { - revert LinkDiscountTooHigh(_fulfillmentFlatFeeLinkDiscountPPM, _fulfillmentFlatFeeNativePPM); - } - if (_coordinatorNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(_coordinatorNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - if (_coordinatorLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(_coordinatorLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - - s_wrapperGasOverhead = _wrapperGasOverhead; - s_coordinatorGasOverheadNative = _coordinatorGasOverheadNative; - s_coordinatorGasOverheadLink = _coordinatorGasOverheadLink; - s_coordinatorGasOverheadPerWord = _coordinatorGasOverheadPerWord; - s_coordinatorNativePremiumPercentage = _coordinatorNativePremiumPercentage; - s_coordinatorLinkPremiumPercentage = _coordinatorLinkPremiumPercentage; - s_keyHash = _keyHash; - s_maxNumWords = _maxNumWords; - s_configured = true; - - // Get other configuration from coordinator - s_stalenessSeconds = _stalenessSeconds; - s_fallbackWeiPerUnitLink = _fallbackWeiPerUnitLink; - s_fulfillmentFlatFeeNativePPM = _fulfillmentFlatFeeNativePPM; - s_fulfillmentFlatFeeLinkDiscountPPM = _fulfillmentFlatFeeLinkDiscountPPM; - - emit ConfigSet( - _wrapperGasOverhead, - _coordinatorGasOverheadNative, - _coordinatorGasOverheadLink, - _coordinatorGasOverheadPerWord, - _coordinatorNativePremiumPercentage, - _coordinatorLinkPremiumPercentage, - _keyHash, - _maxNumWords, - _stalenessSeconds, - _fallbackWeiPerUnitLink, - _fulfillmentFlatFeeNativePPM, - s_fulfillmentFlatFeeLinkDiscountPPM - ); - } - - /** - * @notice getConfig returns the current VRFV2Wrapper configuration. - * - * @return fallbackWeiPerUnitLink is the backup LINK exchange rate used when the LINK/NATIVE feed - * is stale. - * - * @return stalenessSeconds is the number of seconds before we consider the feed price to be stale - * and fallback to fallbackWeiPerUnitLink. - * - * @return fulfillmentFlatFeeNativePPM is the flat fee in millionths of native that VRFCoordinatorV2Plus - * charges for native payment. - * - * @return fulfillmentFlatFeeLinkDiscountPPM is the flat fee discount in millionths of native that VRFCoordinatorV2Plus - * charges for link payment. - * - * @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords - * function. The cost for this gas is passed to the user. - * - * @return coordinatorGasOverheadNative reflects the gas overhead of the coordinator's - * fulfillRandomWords function for native payment. - * - * @return coordinatorGasOverheadLink reflects the gas overhead of the coordinator's - * fulfillRandomWords function for link payment. - * - * @return coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's - * fulfillRandomWords function. - * - * @return wrapperNativePremiumPercentage is the premium ratio in percentage for native payment. For example, a value of 0 - * indicates no premium. A value of 15 indicates a 15 percent premium. - * - * @return wrapperLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a value of 0 - * indicates no premium. A value of 15 indicates a 15 percent premium. - * - * @return keyHash is the key hash to use when requesting randomness. Fees are paid based on - * current gas fees, so this should be set to the highest gas lane on the network. - * - * @return maxNumWords is the max number of words that can be requested in a single wrapped VRF - * request. - */ - function getConfig() - external - view - returns ( - int256 fallbackWeiPerUnitLink, - uint32 stalenessSeconds, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint32 wrapperGasOverhead, - uint32 coordinatorGasOverheadNative, - uint32 coordinatorGasOverheadLink, - uint16 coordinatorGasOverheadPerWord, - uint8 wrapperNativePremiumPercentage, - uint8 wrapperLinkPremiumPercentage, - bytes32 keyHash, - uint8 maxNumWords - ) - { - return ( - s_fallbackWeiPerUnitLink, - s_stalenessSeconds, - s_fulfillmentFlatFeeNativePPM, - s_fulfillmentFlatFeeLinkDiscountPPM, - s_wrapperGasOverhead, - s_coordinatorGasOverheadNative, - s_coordinatorGasOverheadLink, - s_coordinatorGasOverheadPerWord, - s_coordinatorNativePremiumPercentage, - s_coordinatorLinkPremiumPercentage, - s_keyHash, - s_maxNumWords - ); - } - - /** - * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current - * @notice block. - * - * @dev This function relies on the transaction gas price which is not automatically set during - * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - */ - function calculateRequestPrice( - uint32 _callbackGasLimit, - uint32 _numWords - ) external view override onlyConfiguredNotDisabled returns (uint256) { - (int256 weiPerUnitLink, ) = _getFeedData(); - return _calculateRequestPrice(_callbackGasLimit, _numWords, tx.gasprice, weiPerUnitLink); - } - - function calculateRequestPriceNative( - uint32 _callbackGasLimit, - uint32 _numWords - ) external view override onlyConfiguredNotDisabled returns (uint256) { - return _calculateRequestPriceNative(_callbackGasLimit, _numWords, tx.gasprice); - } - - /** - * @notice Estimates the price of a VRF request with a specific gas limit and gas price. - * - * @dev This is a convenience function that can be called in simulation to better understand - * @dev pricing. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _requestGasPriceWei is the gas price in wei used for the estimation. - */ - function estimateRequestPrice( - uint32 _callbackGasLimit, - uint32 _numWords, - uint256 _requestGasPriceWei - ) external view override onlyConfiguredNotDisabled returns (uint256) { - (int256 weiPerUnitLink, ) = _getFeedData(); - return _calculateRequestPrice(_callbackGasLimit, _numWords, _requestGasPriceWei, weiPerUnitLink); - } - - function estimateRequestPriceNative( - uint32 _callbackGasLimit, - uint32 _numWords, - uint256 _requestGasPriceWei - ) external view override onlyConfiguredNotDisabled returns (uint256) { - return _calculateRequestPriceNative(_callbackGasLimit, _numWords, _requestGasPriceWei); - } - - /** - * @notice Returns the L1 fee for the fulfillment calldata payload (always return 0 on L1 chains). - * @notice Override this function in chain specific way for L2 chains. - */ - function _getL1CostWei() internal view virtual returns (uint256) { - return 0; - } - - function _calculateRequestPriceNative( - uint256 _gas, - uint32 _numWords, - uint256 _requestGasPrice - ) internal view returns (uint256) { - // costWei is the base fee denominated in wei (native) - // (wei/gas) * gas - uint256 wrapperCostWei = _requestGasPrice * s_wrapperGasOverhead; - - // coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2. - // (wei/gas) * gas + l1wei - uint256 coordinatorCostWei = _requestGasPrice * - (_gas + _getCoordinatorGasOverhead(_numWords, true)) + - _getL1CostWei(); - - // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied - // coordinator cost * premium multiplier + flat fee - uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * - (s_coordinatorNativePremiumPercentage + 100)) / 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM)); - - return wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei; - } - - function _calculateRequestPrice( - uint256 _gas, - uint32 _numWords, - uint256 _requestGasPrice, - int256 _weiPerUnitLink - ) internal view returns (uint256) { - // costWei is the base fee denominated in wei (native) - // (wei/gas) * gas - uint256 wrapperCostWei = _requestGasPrice * s_wrapperGasOverhead; - - // coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2. - // (wei/gas) * gas + l1wei - uint256 coordinatorCostWei = _requestGasPrice * - (_gas + _getCoordinatorGasOverhead(_numWords, false)) + - _getL1CostWei(); - - // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied - // coordinator cost * premium multiplier + flat fee - uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * - (s_coordinatorLinkPremiumPercentage + 100)) / 100) + - (1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM)); - - // requestPrice is denominated in juels (link) - // (1e18 juels/link) * wei / (wei/link) = juels - return (1e18 * (wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei)) / uint256(_weiPerUnitLink); - } - - /** - * @notice onTokenTransfer is called by LinkToken upon payment for a VRF request. - * - * @dev Reverts if payment is too low. - * - * @param _sender is the sender of the payment, and the address that will receive a VRF callback - * upon fulfillment. - * - * @param _amount is the amount of LINK paid in Juels. - * - * @param _data is the abi-encoded VRF request parameters: uint32 callbackGasLimit, - * uint16 requestConfirmations, and uint32 numWords. - */ - function onTokenTransfer(address _sender, uint256 _amount, bytes calldata _data) external onlyConfiguredNotDisabled { - // solhint-disable-next-line gas-custom-errors - require(msg.sender == address(i_link), "only callable from LINK"); - - (uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords, bytes memory extraArgs) = abi.decode( - _data, - (uint32, uint16, uint32, bytes) - ); - checkPaymentMode(extraArgs, true); - uint32 eip150Overhead = _getEIP150Overhead(callbackGasLimit); - (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); - uint256 price = _calculateRequestPrice(callbackGasLimit, numWords, tx.gasprice, weiPerUnitLink); - // solhint-disable-next-line gas-custom-errors - require(_amount >= price, "fee too low"); - // solhint-disable-next-line gas-custom-errors - require(numWords <= s_maxNumWords, "numWords too high"); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: s_keyHash, - subId: SUBSCRIPTION_ID, - requestConfirmations: requestConfirmations, - callbackGasLimit: callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, - numWords: numWords, - extraArgs: extraArgs // empty extraArgs defaults to link payment - }); - uint256 requestId = s_vrfCoordinator.requestRandomWords(req); - s_callbacks[requestId] = Callback({ - callbackAddress: _sender, - callbackGasLimit: callbackGasLimit, - requestGasPrice: uint64(tx.gasprice) - }); - lastRequestId = requestId; - - if (isFeedStale) { - emit FallbackWeiPerUnitLinkUsed(requestId, s_fallbackWeiPerUnitLink); - } - } - - function checkPaymentMode(bytes memory extraArgs, bool isLinkMode) public pure { - // If extraArgs is empty, payment mode is LINK by default - if (extraArgs.length == 0) { - if (!isLinkMode) { - revert LINKPaymentInRequestRandomWordsInNative(); - } - return; - } - if (extraArgs.length < EXPECTED_MIN_LENGTH) { - revert IncorrectExtraArgsLength(EXPECTED_MIN_LENGTH, uint16(extraArgs.length)); - } - // ExtraArgsV1 only has struct {bool nativePayment} as of now - // The following condition checks if nativePayment in abi.encode of - // ExtraArgsV1 matches the appropriate function call (onTokenTransfer - // for LINK and requestRandomWordsInNative for Native payment) - bool nativePayment = extraArgs[35] == hex"01"; - if (nativePayment && isLinkMode) { - revert NativePaymentInOnTokenTransfer(); - } - if (!nativePayment && !isLinkMode) { - revert LINKPaymentInRequestRandomWordsInNative(); - } - } - - function requestRandomWordsInNative( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - bytes calldata extraArgs - ) external payable override onlyConfiguredNotDisabled returns (uint256 requestId) { - checkPaymentMode(extraArgs, false); - - uint32 eip150Overhead = _getEIP150Overhead(_callbackGasLimit); - uint256 price = _calculateRequestPriceNative(_callbackGasLimit, _numWords, tx.gasprice); - // solhint-disable-next-line gas-custom-errors - require(msg.value >= price, "fee too low"); - // solhint-disable-next-line gas-custom-errors - require(_numWords <= s_maxNumWords, "numWords too high"); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: s_keyHash, - subId: SUBSCRIPTION_ID, - requestConfirmations: _requestConfirmations, - callbackGasLimit: _callbackGasLimit + eip150Overhead + s_wrapperGasOverhead, - numWords: _numWords, - extraArgs: extraArgs - }); - requestId = s_vrfCoordinator.requestRandomWords(req); - s_callbacks[requestId] = Callback({ - callbackAddress: msg.sender, - callbackGasLimit: _callbackGasLimit, - requestGasPrice: uint64(tx.gasprice) - }); - - return requestId; - } - - /** - * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw LINK revenue. - * - * @param _recipient is the address that should receive the LINK funds. - */ - function withdraw(address _recipient) external onlyOwner { - uint256 amount = i_link.balanceOf(address(this)); - if (!i_link.transfer(_recipient, amount)) { - revert FailedToTransferLink(); - } - - emit Withdrawn(_recipient, amount); - } - - /** - * @notice withdraw is used by the VRFV2Wrapper's owner to withdraw native revenue. - * - * @param _recipient is the address that should receive the native funds. - */ - function withdrawNative(address _recipient) external onlyOwner { - uint256 amount = address(this).balance; - (bool success, ) = payable(_recipient).call{value: amount}(""); - // solhint-disable-next-line gas-custom-errors - require(success, "failed to withdraw native"); - - emit NativeWithdrawn(_recipient, amount); - } - - /** - * @notice enable this contract so that new requests can be accepted. - */ - function enable() external onlyOwner { - s_disabled = false; - - emit Enabled(); - } - - /** - * @notice disable this contract so that new requests will be rejected. When disabled, new requests - * @notice will revert but existing requests can still be fulfilled. - */ - function disable() external onlyOwner { - s_disabled = true; - - emit Disabled(); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override { - Callback memory callback = s_callbacks[_requestId]; - delete s_callbacks[_requestId]; - - address callbackAddress = callback.callbackAddress; - // solhint-disable-next-line gas-custom-errors - require(callbackAddress != address(0), "request not found"); // This should never happen - - VRFV2PlusWrapperConsumerBase c; - bytes memory resp = abi.encodeWithSelector(c.rawFulfillRandomWords.selector, _requestId, _randomWords); - - bool success = _callWithExactGas(callback.callbackGasLimit, callbackAddress, resp); - if (!success) { - emit WrapperFulfillmentFailed(_requestId, callbackAddress); - } - } - - function link() external view override returns (address) { - return address(i_link); - } - - function linkNativeFeed() external view override returns (address) { - return address(i_link_native_feed); - } - - function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { - uint32 stalenessSeconds = s_stalenessSeconds; - uint256 timestamp; - (, weiPerUnitLink, , timestamp, ) = i_link_native_feed.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; - if (isFeedStale) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - // solhint-disable-next-line gas-custom-errors - require(weiPerUnitLink >= 0, "Invalid LINK wei price"); - return (weiPerUnitLink, isFeedStale); - } - - /** - * @dev Calculates extra amount of gas required for running an assembly call() post-EIP150. - */ - function _getEIP150Overhead(uint32 gas) private pure returns (uint32) { - return gas / 63 + 1; - } - - function _getCoordinatorGasOverhead(uint32 numWords, bool nativePayment) internal view returns (uint32) { - if (nativePayment) { - return s_coordinatorGasOverheadNative + numWords * s_coordinatorGasOverheadPerWord; - } else { - return s_coordinatorGasOverheadLink + numWords * s_coordinatorGasOverheadPerWord; - } - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - function typeAndVersion() external pure virtual override returns (string memory) { - return "VRFV2PlusWrapper 1.0.0"; - } - - modifier onlyConfiguredNotDisabled() { - // solhint-disable-next-line gas-custom-errors - require(s_configured, "wrapper is not configured"); - // solhint-disable-next-line gas-custom-errors - require(!s_disabled, "wrapper is disabled"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol deleted file mode 100644 index 89a7dcb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {IVRFV2PlusWrapper} from "./interfaces/IVRFV2PlusWrapper.sol"; - -/** - * - * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper - * ******************************************************************************** - * @dev PURPOSE - * - * @dev Create VRF V2+ requests without the need for subscription management. Rather than creating - * @dev and funding a VRF V2+ subscription, a user can use this wrapper to create one off requests, - * @dev paying up front rather than at fulfillment. - * - * @dev Since the price is determined using the gas price of the request transaction rather than - * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas - * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFV2PlusWrapperConsumerBase. The consumer must be funded - * @dev with enough LINK or ether to make the request, otherwise requests will revert. To request randomness, - * @dev call the 'requestRandomWords' function with the desired VRF parameters. This function handles - * @dev paying for the request based on the current pricing. - * - * @dev Consumers must implement the fullfillRandomWords function, which will be called during - * @dev fulfillment with the randomness result. - */ -abstract contract VRFV2PlusWrapperConsumerBase { - error OnlyVRFWrapperCanFulfill(address have, address want); - - LinkTokenInterface internal immutable i_linkToken; - IVRFV2PlusWrapper public immutable i_vrfV2PlusWrapper; - - /** - * @param _vrfV2PlusWrapper is the address of the VRFV2Wrapper contract - */ - constructor(address _vrfV2PlusWrapper) { - IVRFV2PlusWrapper vrfV2PlusWrapper = IVRFV2PlusWrapper(_vrfV2PlusWrapper); - - i_linkToken = LinkTokenInterface(vrfV2PlusWrapper.link()); - i_vrfV2PlusWrapper = vrfV2PlusWrapper; - } - - /** - * @dev Requests randomness from the VRF V2+ wrapper. - * - * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's - * fulfillRandomWords function. - * @param _requestConfirmations is the number of confirmations to wait before fulfilling the - * request. A higher number of confirmations increases security by reducing the likelihood - * that a chain re-org changes a published randomness outcome. - * @param _numWords is the number of random words to request. - * - * @return requestId is the VRF V2+ request ID of the newly created randomness request. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function requestRandomness( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - bytes memory extraArgs - ) internal returns (uint256 requestId, uint256 reqPrice) { - reqPrice = i_vrfV2PlusWrapper.calculateRequestPrice(_callbackGasLimit, _numWords); - i_linkToken.transferAndCall( - address(i_vrfV2PlusWrapper), - reqPrice, - abi.encode(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs) - ); - return (i_vrfV2PlusWrapper.lastRequestId(), reqPrice); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function requestRandomnessPayInNative( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - bytes memory extraArgs - ) internal returns (uint256 requestId, uint256 requestPrice) { - requestPrice = i_vrfV2PlusWrapper.calculateRequestPriceNative(_callbackGasLimit, _numWords); - return ( - i_vrfV2PlusWrapper.requestRandomWordsInNative{value: requestPrice}( - _callbackGasLimit, - _requestConfirmations, - _numWords, - extraArgs - ), - requestPrice - ); - } - - /** - * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must - * @notice implement it. - * - * @param _requestId is the VRF V2 request ID. - * @param _randomWords is the randomness result. - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; - - function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { - address vrfWrapperAddr = address(i_vrfV2PlusWrapper); - if (msg.sender != vrfWrapperAddr) { - revert OnlyVRFWrapperCanFulfill(msg.sender, vrfWrapperAddr); - } - fulfillRandomWords(_requestId, _randomWords); - } - - /// @notice getBalance returns the native balance of the consumer contract - function getBalance() public view returns (uint256) { - return address(this).balance; - } - - /// @notice getLinkToken returns the link token contract - function getLinkToken() public view returns (LinkTokenInterface) { - return i_linkToken; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol deleted file mode 100644 index 1ab5e8b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Arbitrum.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {ArbitrumL1Fees} from "./ArbitrumL1Fees.sol"; -import {VRFV2PlusWrapper} from "./VRFV2PlusWrapper.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract VRFV2PlusWrapper_Arbitrum is VRFV2PlusWrapper, ArbitrumL1Fees { - constructor( - address _link, - address _linkNativeFeed, - address _coordinator, - uint256 _subId - ) VRFV2PlusWrapper(_link, _linkNativeFeed, _coordinator, _subId) {} - - /** - * @notice Returns estimated L1 gas fee cost for fulfillment calldata payload once - * @notice the request has been made through VRFV2PlusWrapper (direct funding model). - */ - function _getL1CostWei() internal view override returns (uint256) { - return ArbitrumL1Fees._getL1CostWeiForCalldataSize(s_fulfillmentTxSizeBytes); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol deleted file mode 100644 index 6913b2f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper_Optimism.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import {OptimismL1Fees} from "./OptimismL1Fees.sol"; -import {VRFV2PlusWrapper} from "./VRFV2PlusWrapper.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract VRFV2PlusWrapper_Optimism is VRFV2PlusWrapper, OptimismL1Fees { - error UnsupportedL1FeeCalculationMode(uint8 mode); - - constructor( - address _link, - address _linkNativeFeed, - address _coordinator, - uint256 _subId - ) VRFV2PlusWrapper(_link, _linkNativeFeed, _coordinator, _subId) { - // default calculation mode from OptimismL1Fees is not supported on the wrapper - // switch to the next available one - s_l1FeeCalculationMode = L1_CALLDATA_GAS_COST_MODE; - } - - /** - * @notice Overriding the setL1FeeCalculation function in VRFV2PlusWrapper for Optimism - * @notice ensures that L1_GAS_FEES_MODE can't be set for the wrapper contract. - */ - function setL1FeeCalculation(uint8 mode, uint8 coefficient) external override onlyOwner { - if (mode == L1_GAS_FEES_MODE) { - revert UnsupportedL1FeeCalculationMode(mode); - } - OptimismL1Fees._setL1FeeCalculationInternal(mode, coefficient); - } - - /** - * @notice Returns estimated L1 gas fee cost for fulfillment calldata payload once - * @notice the request has been made through VRFV2PlusWrapper (direct funding model). - */ - function _getL1CostWei() internal view override returns (uint256) { - return OptimismL1Fees._getL1CostWeiForCalldataSize(s_fulfillmentTxSizeBytes); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol deleted file mode 100644 index b0d5a80..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; -import {IVRFSubscriptionV2Plus} from "./IVRFSubscriptionV2Plus.sol"; - -// Interface that enables consumers of VRFCoordinatorV2Plus to be future-proof for upgrades -// This interface is supported by subsequent versions of VRFCoordinatorV2Plus -interface IVRFCoordinatorV2Plus is IVRFSubscriptionV2Plus { - /** - * @notice Request a set of random words. - * @param req - a struct containing following fields for randomness request: - * keyHash - Corresponds to a particular oracle job which uses - * that key for generating the VRF proof. Different keyHash's have different gas price - * ceilings, so you can select a specific one to bound your maximum per request cost. - * subId - The ID of the VRF subscription. Must be funded - * with the minimum subscription balance required for the selected keyHash. - * requestConfirmations - How many blocks you'd like the - * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS - * for why you may want to request more. The acceptable range is - * [minimumRequestBlockConfirmations, 200]. - * callbackGasLimit - How much gas you'd like to receive in your - * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords - * may be slightly less than this amount because of gas used calling the function - * (argument decoding etc.), so you may need to request slightly more than you expect - * to have inside fulfillRandomWords. The acceptable range is - * [0, maxGasLimit] - * numWords - The number of uint256 random values you'd like to receive - * in your fulfillRandomWords callback. Note these numbers are expanded in a - * secure way by the VRFCoordinator from a single random value supplied by the oracle. - * extraArgs - abi-encoded extra args - * @return requestId - A unique identifier of the request. Can be used to match - * a request to a response in fulfillRandomWords. - */ - function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol deleted file mode 100644 index 22e714c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusInternal.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IVRFCoordinatorV2Plus} from "./IVRFCoordinatorV2Plus.sol"; - -// IVRFCoordinatorV2PlusInternal is the interface used by chainlink core and should -// not be used by consumer conracts -// Future versions of VRF V2plus must conform to this interface -// VRF coordinator doesn't directly inherit from this interface because solidity -// imposes interface methods be external, whereas methods implementated VRF coordinator -// are public. This is OK because IVRFCoordinatorV2PlusInternal doesn't have any solidity -// use case. It is only used to generate gethwrappers -interface IVRFCoordinatorV2PlusInternal is IVRFCoordinatorV2Plus { - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool success, - bool onlyPremium - ); - - struct RequestCommitment { - uint64 blockNum; - uint256 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - bytes extraArgs; - } - - struct Proof { - uint256[2] pk; - uint256[2] gamma; - uint256 c; - uint256 s; - uint256 seed; - address uWitness; - uint256[2] cGammaWitness; - uint256[2] sHashWitness; - uint256 zInv; - } - - // solhint-disable-next-line func-name-mixedcase - function s_requestCommitments(uint256 requestID) external view returns (bytes32); - - function fulfillRandomWords( - Proof calldata proof, - RequestCommitment memory rc, - bool onlyPremium - ) external returns (uint96); - - // solhint-disable-next-line func-name-mixedcase - function LINK_NATIVE_FEED() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol deleted file mode 100644 index f77aaa7..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2PlusMigration.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -// Future versions of VRFCoordinatorV2Plus must implement IVRFCoordinatorV2PlusMigration -// to support migrations from previous versions -interface IVRFCoordinatorV2PlusMigration { - /** - * @notice called by older versions of coordinator for migration. - * @notice only callable by older versions of coordinator - * @notice supports transfer of native currency - * @param encodedData - user data from older version of coordinator - */ - function onMigration(bytes calldata encodedData) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol deleted file mode 100644 index 67d12b8..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFMigratableConsumerV2Plus.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice The IVRFMigratableConsumerV2Plus interface defines the -/// @notice method required to be implemented by all V2Plus consumers. -/// @dev This interface is designed to be used in VRFConsumerBaseV2Plus. -interface IVRFMigratableConsumerV2Plus { - event CoordinatorSet(address vrfCoordinator); - - /// @notice Sets the VRF Coordinator address - /// @notice This method should only be callable by the coordinator or contract owner - function setCoordinator(address vrfCoordinator) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol deleted file mode 100644 index b178ffb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFSubscriptionV2Plus.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice The IVRFSubscriptionV2Plus interface defines the subscription -/// @notice related methods implemented by the V2Plus coordinator. -interface IVRFSubscriptionV2Plus { - /** - * @notice Add a consumer to a VRF subscription. - * @param subId - ID of the subscription - * @param consumer - New consumer which can use the subscription - */ - function addConsumer(uint256 subId, address consumer) external; - - /** - * @notice Remove a consumer from a VRF subscription. - * @param subId - ID of the subscription - * @param consumer - Consumer to remove from the subscription - */ - function removeConsumer(uint256 subId, address consumer) external; - - /** - * @notice Cancel a subscription - * @param subId - ID of the subscription - * @param to - Where to send the remaining LINK to - */ - function cancelSubscription(uint256 subId, address to) external; - - /** - * @notice Accept subscription owner transfer. - * @param subId - ID of the subscription - * @dev will revert if original owner of subId has - * not requested that msg.sender become the new owner. - */ - function acceptSubscriptionOwnerTransfer(uint256 subId) external; - - /** - * @notice Request subscription owner transfer. - * @param subId - ID of the subscription - * @param newOwner - proposed new owner of the subscription - */ - function requestSubscriptionOwnerTransfer(uint256 subId, address newOwner) external; - - /** - * @notice Create a VRF subscription. - * @return subId - A unique subscription id. - * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - * @dev Note to fund the subscription with LINK, use transferAndCall. For example - * @dev LINKTOKEN.transferAndCall( - * @dev address(COORDINATOR), - * @dev amount, - * @dev abi.encode(subId)); - * @dev Note to fund the subscription with Native, use fundSubscriptionWithNative. Be sure - * @dev to send Native with the call, for example: - * @dev COORDINATOR.fundSubscriptionWithNative{value: amount}(subId); - */ - function createSubscription() external returns (uint256 subId); - - /** - * @notice Get a VRF subscription. - * @param subId - ID of the subscription - * @return balance - LINK balance of the subscription in juels. - * @return nativeBalance - native balance of the subscription in wei. - * @return reqCount - Requests count of subscription. - * @return owner - owner of the subscription. - * @return consumers - list of consumer address which are able to use this subscription. - */ - function getSubscription( - uint256 subId - ) - external - view - returns (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers); - - /* - * @notice Check to see if there exists a request commitment consumers - * for all consumers and keyhashes for a given sub. - * @param subId - ID of the subscription - * @return true if there exists at least one unfulfilled request for the subscription, false - * otherwise. - */ - function pendingRequestExists(uint256 subId) external view returns (bool); - - /** - * @notice Paginate through all active VRF subscriptions. - * @param startIndex index of the subscription to start from - * @param maxCount maximum number of subscriptions to return, 0 to return all - * @dev the order of IDs in the list is **not guaranteed**, therefore, if making successive calls, one - * @dev should consider keeping the blockheight constant to ensure a holistic picture of the contract state - */ - function getActiveSubscriptionIds(uint256 startIndex, uint256 maxCount) external view returns (uint256[] memory); - - /** - * @notice Fund a subscription with native. - * @param subId - ID of the subscription - * @notice This method expects msg.value to be greater than or equal to 0. - */ - function fundSubscriptionWithNative(uint256 subId) external payable; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol deleted file mode 100644 index e1a755f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusMigrate.sol +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/// @notice This interface is implemented by all VRF V2+ coordinators that can -/// @notice migrate subscription data to new coordinators. -interface IVRFV2PlusMigrate { - /** - * @notice migrate the provided subscription ID to the provided VRF coordinator - * @notice msg.sender must be the subscription owner and newCoordinator must - * @notice implement IVRFCoordinatorV2PlusMigration. - * @param subId the subscription ID to migrate - * @param newCoordinator the vrf coordinator to migrate to - */ - function migrate(uint256 subId, address newCoordinator) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol deleted file mode 100644 index 85b0c47..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IVRFV2PlusWrapper { - /** - * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only - * be relied option within the same transaction that the request was made. - */ - function lastRequestId() external view returns (uint256); - - /** - * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current - * @notice block. - * - * @dev This function relies on the transaction gas price which is not automatically set during - * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _numWords is the number of words to request. - */ - function calculateRequestPrice(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256); - - /** - * @notice Calculates the price of a VRF request in native with the given callbackGasLimit at the current - * @notice block. - * - * @dev This function relies on the transaction gas price which is not automatically set during - * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _numWords is the number of words to request. - */ - function calculateRequestPriceNative(uint32 _callbackGasLimit, uint32 _numWords) external view returns (uint256); - - /** - * @notice Estimates the price of a VRF request with a specific gas limit and gas price. - * - * @dev This is a convenience function that can be called in simulation to better understand - * @dev pricing. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _numWords is the number of words to request. - * @param _requestGasPriceWei is the gas price in wei used for the estimation. - */ - function estimateRequestPrice( - uint32 _callbackGasLimit, - uint32 _numWords, - uint256 _requestGasPriceWei - ) external view returns (uint256); - - /** - * @notice Estimates the price of a VRF request in native with a specific gas limit and gas price. - * - * @dev This is a convenience function that can be called in simulation to better understand - * @dev pricing. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _numWords is the number of words to request. - * @param _requestGasPriceWei is the gas price in wei used for the estimation. - */ - function estimateRequestPriceNative( - uint32 _callbackGasLimit, - uint32 _numWords, - uint256 _requestGasPriceWei - ) external view returns (uint256); - - /** - * @notice Requests randomness from the VRF V2 wrapper, paying in native token. - * - * @param _callbackGasLimit is the gas limit for the request. - * @param _requestConfirmations number of request confirmations to wait before serving a request. - * @param _numWords is the number of words to request. - */ - function requestRandomWordsInNative( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - bytes calldata extraArgs - ) external payable returns (uint256 requestId); - - function link() external view returns (address); - function linkNativeFeed() external view returns (address); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol deleted file mode 100644 index 31ed4de..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -// End consumer library. -library VRFV2PlusClient { - // extraArgs will evolve to support new features - bytes4 public constant EXTRA_ARGS_V1_TAG = bytes4(keccak256("VRF ExtraArgsV1")); - struct ExtraArgsV1 { - bool nativePayment; - } - - struct RandomWordsRequest { - bytes32 keyHash; - uint256 subId; - uint16 requestConfirmations; - uint32 callbackGasLimit; - uint32 numWords; - bytes extraArgs; - } - - function _argsToBytes(ExtraArgsV1 memory extraArgs) internal pure returns (bytes memory bts) { - return abi.encodeWithSelector(EXTRA_ARGS_V1_TAG, extraArgs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol deleted file mode 100644 index 1e781d1..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {VRFCoordinatorV2_5} from "../VRFCoordinatorV2_5.sol"; -import {VRFTypes} from "../../VRFTypes.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract ExposedVRFCoordinatorV2_5 is VRFCoordinatorV2_5 { - using EnumerableSet for EnumerableSet.UintSet; - - constructor(address blockhashStore) VRFCoordinatorV2_5(blockhashStore) {} - - function computeRequestIdExternal( - bytes32 keyHash, - address sender, - uint256 subId, - uint64 nonce - ) external pure returns (uint256, uint256) { - return _computeRequestId(keyHash, sender, subId, nonce); - } - - function isTargetRegisteredExternal(address target) external view returns (bool) { - return _isTargetRegistered(target); - } - - function getRandomnessFromProofExternal( - Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc - ) external view returns (Output memory) { - return _getRandomnessFromProof(proof, rc); - } - - function getActiveSubscriptionIdsLength() external view returns (uint256) { - return s_subIds.length(); - } - - function getSubscriptionConfig(uint256 subId) external view returns (SubscriptionConfig memory) { - return s_subscriptionConfigs[subId]; - } - - function getSubscriptionStruct(uint256 subId) external view returns (Subscription memory) { - return s_subscriptions[subId]; - } - - function setTotalBalanceTestingOnlyXXX(uint96 newBalance) external { - s_totalBalance = newBalance; - } - - function setTotalNativeBalanceTestingOnlyXXX(uint96 newBalance) external { - s_totalNativeBalance = newBalance; - } - - function setWithdrawableTokensTestingOnlyXXX(uint96 newBalance) external { - s_withdrawableTokens = newBalance; - } - - function getWithdrawableTokensTestingOnlyXXX() external view returns (uint96) { - return s_withdrawableTokens; - } - - function setWithdrawableNativeTestingOnlyXXX(uint96 newBalance) external { - s_withdrawableNative = newBalance; - } - - function getWithdrawableNativeTestingOnlyXXX() external view returns (uint96) { - return s_withdrawableNative; - } - - function calculatePaymentAmount( - uint256 startGas, - uint256 weiPerUnitGas, - bool nativePayment, - bool onlyPremium - ) external returns (uint96, bool) { - return _calculatePaymentAmount(startGas, weiPerUnitGas, nativePayment, onlyPremium); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol deleted file mode 100644 index 4f816db..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {VRFCoordinatorV2_5_Arbitrum} from "../VRFCoordinatorV2_5_Arbitrum.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract ExposedVRFCoordinatorV2_5_Arbitrum is VRFCoordinatorV2_5_Arbitrum { - constructor(address blockhashStore) VRFCoordinatorV2_5_Arbitrum(blockhashStore) {} - - function getBlockNumberExternal() external view returns (uint256) { - return _getBlockNumber(); - } - - function getBlockhashExternal(uint64 blockNumber) external view returns (bytes32) { - return _getBlockhash(blockNumber); - } - - function calculatePaymentAmountNativeExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) external returns (uint96) { - return _calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium); - } - - function calculatePaymentAmountLinkExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) external returns (uint96, bool) { - return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol deleted file mode 100644 index 3732a1e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {VRFCoordinatorV2_5_Optimism} from "../VRFCoordinatorV2_5_Optimism.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract ExposedVRFCoordinatorV2_5_Optimism is VRFCoordinatorV2_5_Optimism { - constructor(address blockhashStore) VRFCoordinatorV2_5_Optimism(blockhashStore) {} - - function getBlockNumberExternal() external view returns (uint256) { - return _getBlockNumber(); - } - - function getBlockhashExternal(uint64 blockNumber) external view returns (bytes32) { - return _getBlockhash(blockNumber); - } - - function calculatePaymentAmountNativeExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) external returns (uint96) { - return _calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium); - } - - function calculatePaymentAmountLinkExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) external returns (uint96, bool) { - return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol deleted file mode 100644 index 65a88df..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFConsumerV2PlusUpgradeableExample.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRFConsumerBaseV2Upgradeable} from "../VRFConsumerBaseV2Upgradeable.sol"; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -contract VRFConsumerV2PlusUpgradeableExample is Initializable, VRFConsumerBaseV2Upgradeable { - uint256[] public s_randomWords; - uint256 public s_requestId; - IVRFCoordinatorV2Plus public COORDINATOR; - LinkTokenInterface public LINKTOKEN; - uint256 public s_subId; - uint256 public s_gasAvailable; - - function initialize(address _vrfCoordinator, address _link) public initializer { - __VRFConsumerBaseV2_init(_vrfCoordinator); - COORDINATOR = IVRFCoordinatorV2Plus(_vrfCoordinator); - LINKTOKEN = LinkTokenInterface(_link); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(requestId == s_requestId, "request ID is incorrect"); - - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness( - bytes32 keyHash, - uint256 subId, - uint16 minReqConfs, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256) { - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: keyHash, - subId: subId, - requestConfirmations: minReqConfs, - callbackGasLimit: callbackGasLimit, - numWords: numWords, - extraArgs: "" // empty extraArgs defaults to link payment - }); - s_requestId = COORDINATOR.requestRandomWords(req); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol deleted file mode 100644 index 2e9c4a2..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorTestV2_5.sol +++ /dev/null @@ -1,773 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface.sol"; -import {VRFOld} from "./VRFOld.sol"; -import {VRFTypes} from "../../VRFTypes.sol"; -import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; -import {SubscriptionAPI} from "../SubscriptionAPI.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; -import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; -// solhint-disable-next-line no-unused-import -import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; - -// solhint-disable-next-line contract-name-camelcase -contract VRFCoordinatorTestV2_5 is VRFOld, SubscriptionAPI, IVRFCoordinatorV2Plus { - /// @dev should always be available - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - BlockhashStoreInterface public immutable BLOCKHASH_STORE; - - // Set this maximum to 200 to give us a 56 block window to fulfill - // the request before requiring the block hash feeder. - uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; - uint32 public constant MAX_NUM_WORDS = 500; - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - // upper bound limit for premium percentages to make sure fee calculations don't overflow - uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; - error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); - error GasLimitTooBig(uint32 have, uint32 want); - error NumWordsTooBig(uint32 have, uint32 want); - error MsgDataTooBig(uint256 have, uint32 max); - error ProvingKeyAlreadyRegistered(bytes32 keyHash); - error NoSuchProvingKey(bytes32 keyHash); - error InvalidLinkWeiPrice(int256 linkWei); - error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); - error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); - error NoCorrespondingRequest(); - error IncorrectCommitment(); - error BlockhashNotInStore(uint256 blockNum); - error PaymentTooLarge(); - error InvalidExtraArgsTag(); - error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); - - struct ProvingKey { - bool exists; // proving key exists - uint64 maxGas; // gas lane max gas price for fulfilling requests - } - - mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; - bytes32[] public s_provingKeyHashes; - mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); - event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - - int256 public s_fallbackWeiPerUnitLink; - - event ConfigSet( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ); - - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - - constructor(address blockhashStore) SubscriptionAPI() { - BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); - } - - /** - * @notice Registers a proving key to. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh].exists) { - revert ProvingKeyAlreadyRegistered(kh); - } - s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); - s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, maxGas); - } - - /** - * @notice Deregisters a proving key. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - ProvingKey memory key = s_provingKeys[kh]; - if (!key.exists) { - revert NoSuchProvingKey(kh); - } - delete s_provingKeys[kh]; - uint256 s_provingKeyHashesLength = s_provingKeyHashes.length; - for (uint256 i = 0; i < s_provingKeyHashesLength; ++i) { - if (s_provingKeyHashes[i] == kh) { - // Copy last element and overwrite kh to be deleted with it - s_provingKeyHashes[i] = s_provingKeyHashes[s_provingKeyHashesLength - 1]; - s_provingKeyHashes.pop(); - break; - } - } - emit ProvingKeyDeregistered(kh, key.maxGas); - } - - /** - * @notice Returns the proving key hash key associated with this public key - * @param publicKey the key to return the hash of - */ - function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed - * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment - * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native - * @param nativePremiumPercentage native premium percentage - * @param linkPremiumPercentage link premium percentage - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ) external onlyOwner { - if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { - revert InvalidRequestConfirmations( - minimumRequestConfirmations, - minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - if (fallbackWeiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); - } - if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { - revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); - } - if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - s_config = Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - reentrancyLock: false, - fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage: nativePremiumPercentage, - linkPremiumPercentage: linkPremiumPercentage - }); - s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; - emit ConfigSet( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage, - linkPremiumPercentage - ); - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @return The extra args struct - function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { - if (extraArgs.length == 0) { - return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); - } - if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); - } - - /** - * @notice Request a set of random words. - * @param req - a struct containing following fiels for randomness request: - * keyHash - Corresponds to a particular oracle job which uses - * that key for generating the VRF proof. Different keyHash's have different gas price - * ceilings, so you can select a specific one to bound your maximum per request cost. - * subId - The ID of the VRF subscription. Must be funded - * with the minimum subscription balance required for the selected keyHash. - * requestConfirmations - How many blocks you'd like the - * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS - * for why you may want to request more. The acceptable range is - * [minimumRequestBlockConfirmations, 200]. - * callbackGasLimit - How much gas you'd like to receive in your - * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords - * may be slightly less than this amount because of gas used calling the function - * (argument decoding etc.), so you may need to request slightly more than you expect - * to have inside fulfillRandomWords. The acceptable range is - * [0, maxGasLimit] - * numWords - The number of uint256 random values you'd like to receive - * in your fulfillRandomWords callback. Note these numbers are expanded in a - * secure way by the VRFCoordinator from a single random value supplied by the oracle. - * extraArgs - Encoded extra arguments that has a boolean flag for whether payment - * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. - * @return requestId - A unique identifier of the request. Can be used to match - * a request to a response in fulfillRandomWords. - */ - function requestRandomWords( - VRFV2PlusClient.RandomWordsRequest calldata req - ) external override nonReentrant returns (uint256 requestId) { - // Input validation using the subscription storage. - uint256 subId = req.subId; - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // Its important to ensure that the consumer is in fact who they say they - // are, otherwise they could use someone else's subscription balance. - mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; - ConsumerConfig memory consumerConfig = consumerConfigs[subId]; - if (!consumerConfig.active) { - revert InvalidConsumer(subId, msg.sender); - } - // Input validation using the config storage word. - if ( - req.requestConfirmations < s_config.minimumRequestConfirmations || - req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS - ) { - revert InvalidRequestConfirmations( - req.requestConfirmations, - s_config.minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - // No lower bound on the requested gas limit. A user could request 0 - // and they would simply be billed for the proof verification and wouldn't be - // able to do anything with the random value. - if (req.callbackGasLimit > s_config.maxGasLimit) { - revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); - } - if (req.numWords > MAX_NUM_WORDS) { - revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); - } - - // Note we do not check whether the keyHash is valid to save gas. - // The consequence for users is that they can send requests - // for invalid keyHashes which will simply not be fulfilled. - ++consumerConfig.nonce; - ++consumerConfig.pendingReqCount; - uint256 preSeed; - (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); - - bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); - s_requestCommitments[requestId] = keccak256( - abi.encode( - requestId, - ChainSpecificUtil._getBlockNumber(), - subId, - req.callbackGasLimit, - req.numWords, - msg.sender, - extraArgsBytes - ) - ); - emit RandomWordsRequested( - req.keyHash, - requestId, - preSeed, - subId, - req.requestConfirmations, - req.callbackGasLimit, - req.numWords, - extraArgsBytes, - msg.sender - ); - consumerConfigs[subId] = consumerConfig; - - return requestId; - } - - function _computeRequestId( - bytes32 keyHash, - address sender, - uint256 subId, - uint64 nonce - ) internal pure returns (uint256, uint256) { - uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); - return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - struct Output { - ProvingKey provingKey; - uint256 requestId; - uint256 randomness; - } - - function _getRandomnessFromProof( - Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc - ) internal view returns (Output memory) { - bytes32 keyHash = hashOfKey(proof.pk); - ProvingKey memory key = s_provingKeys[keyHash]; - // Only registered proving keys are permitted. - if (!key.exists) { - revert NoSuchProvingKey(keyHash); - } - uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); - bytes32 commitment = s_requestCommitments[requestId]; - if (commitment == 0) { - revert NoCorrespondingRequest(); - } - if ( - commitment != - keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) - ) { - revert IncorrectCommitment(); - } - - bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - revert BlockhashNotInStore(rc.blockNum); - } - } - - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); - uint256 randomness = VRFOld._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - return Output(key, requestId, randomness); - } - - function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { - if (tx.gasprice > gasLaneMaxGas) { - if (onlyPremium) { - // if only the premium amount needs to be billed, then the premium is capped by the gas lane max - return uint256(gasLaneMaxGas); - } else { - // Ensure gas price does not exceed the gas lane max gas price - revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); - } - } - return tx.gasprice; - } - - function _deliverRandomness( - uint256 requestId, - VRFTypes.RequestCommitmentV2Plus memory rc, - uint256[] memory randomWords - ) internal returns (bool success) { - VRFConsumerBaseV2Plus v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that _callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; - return success; - } - - /* - * @notice Fulfill a randomness request. - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - * @param onlyPremium only charge premium - * @return payment amount billed to the subscription - * @dev simulated offchain to determine if sufficient balance is present to fulfill the request - */ - function fulfillRandomWords( - Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - bool onlyPremium - ) external nonReentrant returns (uint96 payment) { - uint256 startGas = gasleft(); - // fulfillRandomWords msg.data has 772 bytes and with an additional - // buffer of 32 bytes, we get 804 bytes. - /* Data size split: - * fulfillRandomWords function signature - 4 bytes - * proof - 416 bytes - * pk - 64 bytes - * gamma - 64 bytes - * c - 32 bytes - * s - 32 bytes - * seed - 32 bytes - * uWitness - 32 bytes - * cGammaWitness - 64 bytes - * sHashWitness - 64 bytes - * zInv - 32 bytes - * requestCommitment - 320 bytes - * blockNum - 32 bytes - * subId - 32 bytes - * callbackGasLimit - 32 bytes - * numWords - 32 bytes - * sender - 32 bytes - * extraArgs - 128 bytes - * onlyPremium - 32 bytes - */ - if (msg.data.length > 804) { - revert MsgDataTooBig(msg.data.length, 804); - } - Output memory output = _getRandomnessFromProof(proof, rc); - uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); - - uint256[] memory randomWords; - uint256 randomness = output.randomness; - // stack too deep error - { - uint256 numWords = rc.numWords; - randomWords = new uint256[](numWords); - for (uint256 i = 0; i < numWords; ++i) { - randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); - } - } - - delete s_requestCommitments[output.requestId]; - bool success = _deliverRandomness(output.requestId, rc, randomWords); - - // Increment the req count for the subscription. - ++s_subscriptions[rc.subId].reqCount; - // Decrement the pending req count for the consumer. - --s_consumers[rc.sender][rc.subId].pendingReqCount; - - bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; - - // stack too deep error - { - // We want to charge users exactly for how much gas they use in their callback with - // an additional premium. If onlyPremium is true, only premium is charged without - // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional - // operations where we decrement the subscription balance and increment the - // withdrawable balance. - bool isFeedStale; - (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); - if (isFeedStale) { - emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); - } - } - - _chargePayment(payment, nativePayment, rc.subId); - - // Include payment in the event for tracking costs. - emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); - - return payment; - } - - function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { - Subscription storage subcription = s_subscriptions[subId]; - if (nativePayment) { - uint96 prevBal = subcription.nativeBalance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.nativeBalance = prevBal - payment; - s_withdrawableNative += payment; - } else { - uint96 prevBal = subcription.balance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.balance = prevBal - payment; - s_withdrawableTokens += payment; - } - } - - function _calculatePaymentAmount( - uint256 startGas, - uint256 weiPerUnitGas, - bool nativePayment, - bool onlyPremium - ) internal view returns (uint96, bool) { - if (nativePayment) { - return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); - } - return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); - } - - function _calculatePaymentAmountNative( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal view returns (uint96) { - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); - // calculate the payment without the premium - uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); - // calculate flat fee in native - uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); - if (onlyPremium) { - return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } else { - return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } - } - - // Get the amount of gas used for fulfillment - function _calculatePaymentAmountLink( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal view returns (uint96, bool) { - (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); - // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * - (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / - uint256(weiPerUnitLink); - // calculate the flat fee in wei - uint256 flatFeeWei = 1e12 * - uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); - uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); - uint256 payment; - if (onlyPremium) { - payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } else { - payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } - if (payment > 1e27) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return (uint96(payment), isFeedStale); - } - - function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - uint256 timestamp; - (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; - if (isFeedStale) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return (weiPerUnitLink, isFeedStale); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function pendingRequestExists(uint256 subId) public view override returns (bool) { - address[] storage consumers = s_subscriptionConfigs[subId].consumers; - uint256 consumersLength = consumers.length; - if (consumersLength == 0) { - return false; - } - for (uint256 i = 0; i < consumersLength; ++i) { - if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { - return true; - } - } - return false; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - if (!s_consumers[consumer][subId].active) { - revert InvalidConsumer(subId, consumer); - } - // Note bounded by MAX_CONSUMERS - address[] memory consumers = s_subscriptionConfigs[subId].consumers; - uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; ++i) { - if (consumers[i] == consumer) { - address last = consumers[lastConsumerIndex]; - // Storage write to preserve last element - s_subscriptionConfigs[subId].consumers[i] = last; - // Storage remove last element - s_subscriptionConfigs[subId].consumers.pop(); - break; - } - } - s_consumers[consumer][subId].active = false; - emit SubscriptionConsumerRemoved(subId, consumer); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - _cancelSubscriptionHelper(subId, to); - } - - /*************************************************************************** - * Section: Migration - ***************************************************************************/ - - address[] internal s_migrationTargets; - - /// @dev Emitted when new coordinator is registered as migratable target - event CoordinatorRegistered(address coordinatorAddress); - - /// @dev Emitted when new coordinator is deregistered - event CoordinatorDeregistered(address coordinatorAddress); - - /// @notice emitted when migration to new coordinator completes successfully - /// @param newCoordinator coordinator address after migration - /// @param subId subscription ID - event MigrationCompleted(address newCoordinator, uint256 subId); - - /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target - error CoordinatorNotRegistered(address coordinatorAddress); - - /// @notice emitted when migrate() is called and given coordinator is registered as migratable target - error CoordinatorAlreadyRegistered(address coordinatorAddress); - - /// @dev encapsulates data to be migrated from current coordinator - // solhint-disable-next-line gas-struct-packing - struct V1MigrationData { - uint8 fromVersion; - uint256 subId; - address subOwner; - address[] consumers; - uint96 linkBalance; - uint96 nativeBalance; - } - - function _isTargetRegistered(address target) internal view returns (bool) { - uint256 migrationTargetsLength = s_migrationTargets.length; - for (uint256 i = 0; i < migrationTargetsLength; ++i) { - if (s_migrationTargets[i] == target) { - return true; - } - } - return false; - } - - function registerMigratableCoordinator(address target) external onlyOwner { - if (_isTargetRegistered(target)) { - revert CoordinatorAlreadyRegistered(target); - } - s_migrationTargets.push(target); - emit CoordinatorRegistered(target); - } - - function deregisterMigratableCoordinator(address target) external onlyOwner { - uint256 nTargets = s_migrationTargets.length; - for (uint256 i = 0; i < nTargets; ++i) { - if (s_migrationTargets[i] == target) { - s_migrationTargets[i] = s_migrationTargets[nTargets - 1]; - s_migrationTargets.pop(); - emit CoordinatorDeregistered(target); - return; - } - } - revert CoordinatorNotRegistered(target); - } - - function migrate(uint256 subId, address newCoordinator) external nonReentrant { - if (!_isTargetRegistered(newCoordinator)) { - revert CoordinatorNotRegistered(newCoordinator); - } - (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); - // solhint-disable-next-line gas-custom-errors - require(subOwner == msg.sender, "Not subscription owner"); - // solhint-disable-next-line gas-custom-errors - require(!pendingRequestExists(subId), "Pending request exists"); - - V1MigrationData memory migrationData = V1MigrationData({ - fromVersion: 1, - subId: subId, - subOwner: subOwner, - consumers: consumers, - linkBalance: balance, - nativeBalance: nativeBalance - }); - bytes memory encodedData = abi.encode(migrationData); - _deleteSubscription(subId); - IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); - - // Only transfer LINK if the token is active and there is a balance. - if (address(LINK) != address(0) && balance != 0) { - // solhint-disable-next-line gas-custom-errors - require(LINK.transfer(address(newCoordinator), balance), "insufficient funds"); - } - - // despite the fact that we follow best practices this is still probably safest - // to prevent any re-entrancy possibilities. - s_config.reentrancyLock = true; - for (uint256 i = 0; i < consumers.length; ++i) { - IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); - } - s_config.reentrancyLock = false; - - emit MigrationCompleted(newCoordinator, subId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol deleted file mode 100644 index af5c56b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol +++ /dev/null @@ -1,809 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface.sol"; -// solhint-disable-next-line no-unused-import -import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRF} from "../../../vrf/VRF.sol"; -import {VRFTypes} from "../../VRFTypes.sol"; -import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; -import {SubscriptionAPI} from "../SubscriptionAPI.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; -import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; - -contract VRFCoordinatorV2PlusUpgradedVersion is - VRF, - SubscriptionAPI, - IVRFCoordinatorV2PlusMigration, - IVRFCoordinatorV2Plus -{ - using EnumerableSet for EnumerableSet.UintSet; - /// @dev should always be available - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - BlockhashStoreInterface public immutable BLOCKHASH_STORE; - - // Set this maximum to 200 to give us a 56 block window to fulfill - // the request before requiring the block hash feeder. - uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; - uint32 public constant MAX_NUM_WORDS = 500; - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - // upper bound limit for premium percentages to make sure fee calculations don't overflow - uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; - error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); - error GasLimitTooBig(uint32 have, uint32 want); - error NumWordsTooBig(uint32 have, uint32 want); - error MsgDataTooBig(uint256 have, uint32 max); - error ProvingKeyAlreadyRegistered(bytes32 keyHash); - error NoSuchProvingKey(bytes32 keyHash); - error InvalidLinkWeiPrice(int256 linkWei); - error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); - error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); - error NoCorrespondingRequest(); - error IncorrectCommitment(); - error BlockhashNotInStore(uint256 blockNum); - error PaymentTooLarge(); - error InvalidExtraArgsTag(); - error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); - /// @notice emitted when version in the request doesn't match expected version - error InvalidVersion(uint8 requestVersion, uint8 expectedVersion); - /// @notice emitted when transferred balance (msg.value) does not match the metadata in V1MigrationData - error InvalidNativeBalance(uint256 transferredValue, uint96 expectedValue); - error SubscriptionIDCollisionFound(); - - struct ProvingKey { - bool exists; // proving key exists - uint64 maxGas; // gas lane max gas price for fulfilling requests - } - - mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; - bytes32[] public s_provingKeyHashes; - mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - - int256 public s_fallbackWeiPerUnitLink; - - event ConfigSet( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ); - - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - - constructor(address blockhashStore) SubscriptionAPI() { - BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); - } - - /** - * @notice Registers a proving key to. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh].exists) { - revert ProvingKeyAlreadyRegistered(kh); - } - s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); - s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, maxGas); - } - - /** - * @notice Returns the proving key hash key associated with this public key - * @param publicKey the key to return the hash of - */ - function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed - * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment - * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native - * @param nativePremiumPercentage native premium percentage - * @param linkPremiumPercentage link premium percentage - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM, - uint8 nativePremiumPercentage, - uint8 linkPremiumPercentage - ) external onlyOwner { - if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { - revert InvalidRequestConfirmations( - minimumRequestConfirmations, - minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - if (fallbackWeiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); - } - if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { - revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); - } - if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); - } - s_config = Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - reentrancyLock: false, - fulfillmentFlatFeeNativePPM: fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM: fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage: nativePremiumPercentage, - linkPremiumPercentage: linkPremiumPercentage - }); - s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; - emit ConfigSet( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - fulfillmentFlatFeeNativePPM, - fulfillmentFlatFeeLinkDiscountPPM, - nativePremiumPercentage, - linkPremiumPercentage - ); - } - - /** - * @notice Get configuration relevant for making requests - * @return minimumRequestConfirmations global min for request confirmations - * @return maxGasLimit global max for request gas limit - * @return s_provingKeyHashes list of registered key hashes - */ - function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory) { - return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @return The extra args struct - function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { - if (extraArgs.length == 0) { - return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); - } - if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); - } - - /** - * @notice Request a set of random words. - * @param req - a struct containing following fiels for randomness request: - * keyHash - Corresponds to a particular oracle job which uses - * that key for generating the VRF proof. Different keyHash's have different gas price - * ceilings, so you can select a specific one to bound your maximum per request cost. - * subId - The ID of the VRF subscription. Must be funded - * with the minimum subscription balance required for the selected keyHash. - * requestConfirmations - How many blocks you'd like the - * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS - * for why you may want to request more. The acceptable range is - * [minimumRequestBlockConfirmations, 200]. - * callbackGasLimit - How much gas you'd like to receive in your - * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords - * may be slightly less than this amount because of gas used calling the function - * (argument decoding etc.), so you may need to request slightly more than you expect - * to have inside fulfillRandomWords. The acceptable range is - * [0, maxGasLimit] - * numWords - The number of uint256 random values you'd like to receive - * in your fulfillRandomWords callback. Note these numbers are expanded in a - * secure way by the VRFCoordinator from a single random value supplied by the oracle. - * extraArgs - Encoded extra arguments that has a boolean flag for whether payment - * should be made in native or LINK. Payment in LINK is only available if the LINK token is available to this contract. - * @return requestId - A unique identifier of the request. Can be used to match - * a request to a response in fulfillRandomWords. - */ - function requestRandomWords( - VRFV2PlusClient.RandomWordsRequest calldata req - ) external override nonReentrant returns (uint256 requestId) { - // Input validation using the subscription storage. - uint256 subId = req.subId; - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // Its important to ensure that the consumer is in fact who they say they - // are, otherwise they could use someone else's subscription balance. - mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; - ConsumerConfig memory consumerConfig = consumerConfigs[subId]; - if (!consumerConfig.active) { - revert InvalidConsumer(subId, msg.sender); - } - // Input validation using the config storage word. - if ( - req.requestConfirmations < s_config.minimumRequestConfirmations || - req.requestConfirmations > MAX_REQUEST_CONFIRMATIONS - ) { - revert InvalidRequestConfirmations( - req.requestConfirmations, - s_config.minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - // No lower bound on the requested gas limit. A user could request 0 - // and they would simply be billed for the proof verification and wouldn't be - // able to do anything with the random value. - if (req.callbackGasLimit > s_config.maxGasLimit) { - revert GasLimitTooBig(req.callbackGasLimit, s_config.maxGasLimit); - } - if (req.numWords > MAX_NUM_WORDS) { - revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); - } - - // Note we do not check whether the keyHash is valid to save gas. - // The consequence for users is that they can send requests - // for invalid keyHashes which will simply not be fulfilled. - ++consumerConfig.nonce; - ++consumerConfig.pendingReqCount; - uint256 preSeed; - (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); - - bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); - s_requestCommitments[requestId] = keccak256( - abi.encode( - requestId, - ChainSpecificUtil._getBlockNumber(), - subId, - req.callbackGasLimit, - req.numWords, - msg.sender, - extraArgsBytes - ) - ); - emit RandomWordsRequested( - req.keyHash, - requestId, - preSeed, - subId, - req.requestConfirmations, - req.callbackGasLimit, - req.numWords, - extraArgsBytes, - msg.sender - ); - consumerConfigs[subId] = consumerConfig; - - return requestId; - } - - function _computeRequestId( - bytes32 keyHash, - address sender, - uint256 subId, - uint64 nonce - ) internal pure returns (uint256, uint256) { - uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); - return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function _callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - struct Output { - ProvingKey provingKey; - uint256 requestId; - uint256 randomness; - } - - function _getRandomnessFromProof( - Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc - ) internal view returns (Output memory) { - bytes32 keyHash = hashOfKey(proof.pk); - ProvingKey memory key = s_provingKeys[keyHash]; - // Only registered proving keys are permitted. - if (!key.exists) { - revert NoSuchProvingKey(keyHash); - } - uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); - bytes32 commitment = s_requestCommitments[requestId]; - if (commitment == 0) { - revert NoCorrespondingRequest(); - } - if ( - commitment != - keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender, rc.extraArgs)) - ) { - revert IncorrectCommitment(); - } - - bytes32 blockHash = ChainSpecificUtil._getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - revert BlockhashNotInStore(rc.blockNum); - } - } - - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); - uint256 randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - return Output(key, requestId, randomness); - } - - function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { - if (tx.gasprice > gasLaneMaxGas) { - if (onlyPremium) { - // if only the premium amount needs to be billed, then the premium is capped by the gas lane max - return uint256(gasLaneMaxGas); - } else { - // Ensure gas price does not exceed the gas lane max gas price - revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); - } - } - return tx.gasprice; - } - - function _deliverRandomness( - uint256 requestId, - VRFTypes.RequestCommitmentV2Plus calldata rc, - uint256[] memory randomWords - ) internal returns (bool success) { - VRFConsumerBaseV2Plus v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that _callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; - return success; - } - - /* - * @notice Fulfill a randomness request. - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - * @param onlyPremium only charge premium - * @return payment amount billed to the subscription - * @dev simulated offchain to determine if sufficient balance is present to fulfill the request - */ - function fulfillRandomWords( - Proof calldata proof, - VRFTypes.RequestCommitmentV2Plus calldata rc, - bool onlyPremium - ) external nonReentrant returns (uint96 payment) { - uint256 startGas = gasleft(); - // fulfillRandomWords msg.data has 772 bytes and with an additional - // buffer of 32 bytes, we get 804 bytes. - /* Data size split: - * fulfillRandomWords function signature - 4 bytes - * proof - 416 bytes - * pk - 64 bytes - * gamma - 64 bytes - * c - 32 bytes - * s - 32 bytes - * seed - 32 bytes - * uWitness - 32 bytes - * cGammaWitness - 64 bytes - * sHashWitness - 64 bytes - * zInv - 32 bytes - * requestCommitment - 320 bytes - * blockNum - 32 bytes - * subId - 32 bytes - * callbackGasLimit - 32 bytes - * numWords - 32 bytes - * sender - 32 bytes - * extraArgs - 128 bytes - * onlyPremium - 32 bytes - */ - if (msg.data.length > 804) { - revert MsgDataTooBig(msg.data.length, 804); - } - Output memory output = _getRandomnessFromProof(proof, rc); - uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); - - uint256[] memory randomWords; - uint256 randomness = output.randomness; - // stack too deep error - { - uint256 numWords = rc.numWords; - randomWords = new uint256[](numWords); - for (uint256 i = 0; i < numWords; ++i) { - randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); - } - } - - delete s_requestCommitments[output.requestId]; - bool success = _deliverRandomness(output.requestId, rc, randomWords); - - // Increment the req count for the subscription. - ++s_subscriptions[rc.subId].reqCount; - // Decrement the pending req count for the consumer. - --s_consumers[rc.sender][rc.subId].pendingReqCount; - - bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; - - // stack too deep error - { - // We want to charge users exactly for how much gas they use in their callback with - // an additional premium. If onlyPremium is true, only premium is charged without - // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional - // operations where we decrement the subscription balance and increment the - // withdrawable balance. - bool isFeedStale; - (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); - if (isFeedStale) { - emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); - } - } - - _chargePayment(payment, nativePayment, rc.subId); - - // Include payment in the event for tracking costs. - emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); - - return payment; - } - - function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { - Subscription storage subcription = s_subscriptions[subId]; - if (nativePayment) { - uint96 prevBal = subcription.nativeBalance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.nativeBalance = prevBal - payment; - s_withdrawableNative += payment; - } else { - uint96 prevBal = subcription.balance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.balance = prevBal - payment; - s_withdrawableTokens += payment; - } - } - - function _calculatePaymentAmount( - uint256 startGas, - uint256 weiPerUnitGas, - bool nativePayment, - bool onlyPremium - ) internal view returns (uint96, bool) { - if (nativePayment) { - return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); - } - return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); - } - - function _calculatePaymentAmountNative( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal view returns (uint96) { - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); - // calculate the payment without the premium - uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); - // calculate flat fee in native - uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); - if (onlyPremium) { - return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } else { - return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); - } - } - - // Get the amount of gas used for fulfillment - function _calculatePaymentAmountLink( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal view returns (uint96, bool) { - (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // Will return non-zero on chains that have this enabled - uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); - // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * - (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / - uint256(weiPerUnitLink); - // calculate the flat fee in wei - uint256 flatFeeWei = 1e12 * - uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); - uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); - uint256 payment; - if (onlyPremium) { - payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } else { - payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); - } - if (payment > 1e27) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return (uint96(payment), isFeedStale); - } - - function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - uint256 timestamp; - (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; - if (isFeedStale) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return (weiPerUnitLink, isFeedStale); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function pendingRequestExists(uint256 subId) public view override returns (bool) { - address[] storage consumers = s_subscriptionConfigs[subId].consumers; - uint256 consumersLength = consumers.length; - if (consumersLength == 0) { - return false; - } - for (uint256 i = 0; i < consumersLength; ++i) { - if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { - return true; - } - } - return false; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function removeConsumer(uint256 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - if (!s_consumers[consumer][subId].active) { - revert InvalidConsumer(subId, consumer); - } - // Note bounded by MAX_CONSUMERS - address[] memory consumers = s_subscriptionConfigs[subId].consumers; - uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; ++i) { - if (consumers[i] == consumer) { - address last = consumers[lastConsumerIndex]; - // Storage write to preserve last element - s_subscriptionConfigs[subId].consumers[i] = last; - // Storage remove last element - s_subscriptionConfigs[subId].consumers.pop(); - break; - } - } - s_consumers[consumer][subId].active = false; - emit SubscriptionConsumerRemoved(subId, consumer); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function cancelSubscription(uint256 subId, address to) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - _cancelSubscriptionHelper(subId, to); - } - - /*************************************************************************** - * Section: Migration - ***************************************************************************/ - - address[] internal s_migrationTargets; - - /// @dev Emitted when new coordinator is registered as migratable target - event CoordinatorRegistered(address coordinatorAddress); - - /// @notice emitted when migration to new coordinator completes successfully - /// @param newCoordinator coordinator address after migration - /// @param subId subscription ID - event MigrationCompleted(address newCoordinator, uint256 subId); - - /// @notice emitted when migrate() is called and given coordinator is not registered as migratable target - error CoordinatorNotRegistered(address coordinatorAddress); - - /// @notice emitted when migrate() is called and given coordinator is registered as migratable target - error CoordinatorAlreadyRegistered(address coordinatorAddress); - - /// @dev encapsulates data to be migrated from current coordinator - // solhint-disable-next-line gas-struct-packing - struct V1MigrationData { - uint8 fromVersion; - uint256 subId; - address subOwner; - address[] consumers; - uint96 linkBalance; - uint96 nativeBalance; - } - - function _isTargetRegistered(address target) internal view returns (bool) { - uint256 migrationTargetsLength = s_migrationTargets.length; - for (uint256 i = 0; i < migrationTargetsLength; ++i) { - if (s_migrationTargets[i] == target) { - return true; - } - } - return false; - } - - function registerMigratableCoordinator(address target) external onlyOwner { - if (_isTargetRegistered(target)) { - revert CoordinatorAlreadyRegistered(target); - } - s_migrationTargets.push(target); - emit CoordinatorRegistered(target); - } - - function migrate(uint256 subId, address newCoordinator) external nonReentrant { - if (!_isTargetRegistered(newCoordinator)) { - revert CoordinatorNotRegistered(newCoordinator); - } - (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); - // solhint-disable-next-line gas-custom-errors - require(subOwner == msg.sender, "Not subscription owner"); - // solhint-disable-next-line gas-custom-errors - require(!pendingRequestExists(subId), "Pending request exists"); - - V1MigrationData memory migrationData = V1MigrationData({ - fromVersion: 1, - subId: subId, - subOwner: subOwner, - consumers: consumers, - linkBalance: balance, - nativeBalance: nativeBalance - }); - bytes memory encodedData = abi.encode(migrationData); - _deleteSubscription(subId); - IVRFCoordinatorV2PlusMigration(newCoordinator).onMigration{value: nativeBalance}(encodedData); - - // Only transfer LINK if the token is active and there is a balance. - if (address(LINK) != address(0) && balance != 0) { - // solhint-disable-next-line gas-custom-errors - require(LINK.transfer(address(newCoordinator), balance), "insufficient funds"); - } - - // despite the fact that we follow best practices this is still probably safest - // to prevent any re-entrancy possibilities. - s_config.reentrancyLock = true; - for (uint256 i = 0; i < consumers.length; ++i) { - IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); - } - s_config.reentrancyLock = false; - - emit MigrationCompleted(newCoordinator, subId); - } - - function migrationVersion() public pure returns (uint8 version) { - return 2; - } - - /** - * @inheritdoc IVRFCoordinatorV2PlusMigration - */ - function onMigration(bytes calldata encodedData) external payable override { - V1MigrationData memory migrationData = abi.decode(encodedData, (V1MigrationData)); - - if (migrationData.fromVersion != 1) { - revert InvalidVersion(migrationData.fromVersion, 1); - } - - if (msg.value != uint256(migrationData.nativeBalance)) { - revert InvalidNativeBalance(msg.value, migrationData.nativeBalance); - } - - // it should be impossible to have a subscription id collision, for two reasons: - // 1. the subscription ID is calculated using inputs that cannot be replicated under different - // conditions. - // 2. once a subscription is migrated it is deleted from the previous coordinator, so it cannot - // be migrated again. - // however, we should have this check here in case the `migrate` function on - // future coordinators "forgets" to delete subscription data allowing re-migration of the same - // subscription. - if (s_subscriptionConfigs[migrationData.subId].owner != address(0)) { - revert SubscriptionIDCollisionFound(); - } - - for (uint256 i = 0; i < migrationData.consumers.length; i++) { - s_consumers[migrationData.consumers[i]][migrationData.subId] = ConsumerConfig({ - active: true, - nonce: 0, - pendingReqCount: 0 - }); - } - - s_subscriptions[migrationData.subId] = Subscription({ - nativeBalance: migrationData.nativeBalance, - balance: migrationData.linkBalance, - reqCount: 0 - }); - s_subscriptionConfigs[migrationData.subId] = SubscriptionConfig({ - owner: migrationData.subOwner, - consumers: migrationData.consumers, - requestedOwner: address(0) - }); - - s_totalBalance += uint96(migrationData.linkBalance); - s_totalNativeBalance += uint96(migrationData.nativeBalance); - - s_subIds.add(migrationData.subId); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol deleted file mode 100644 index 1a2ed50..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IVRFCoordinatorV2PlusMigration} from "../interfaces/IVRFCoordinatorV2PlusMigration.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -/// @dev this contract is only meant for testing migration -/// @dev it is a simplified example of future version (V2) of VRFCoordinatorV2Plus -// solhint-disable-next-line contract-name-camelcase -contract VRFCoordinatorV2Plus_V2Example is IVRFCoordinatorV2PlusMigration { - error SubscriptionIDCollisionFound(); - - struct Subscription { - uint96 linkBalance; - uint96 nativeBalance; - uint64 reqCount; - address owner; - address[] consumers; - } - - mapping(uint256 => Subscription) public s_subscriptions; /* subId */ /* subscription */ - mapping(uint256 => address) public s_requestConsumerMapping; /* RequestId */ /* consumer address */ - - uint96 public s_totalLinkBalance; - uint96 public s_totalNativeBalance; - // request ID nonce - uint256 public s_requestId = 0; - - // older version of coordinator, from which migration is supported - address public s_prevCoordinator; - address public s_link; - - constructor(address link, address prevCoordinator) { - s_link = link; - s_prevCoordinator = prevCoordinator; - } - - /*************************************************************************** - * Section: Subscription - **************************************************************************/ - - /// @dev Emitted when a subscription for a given ID cannot be found - error InvalidSubscription(); - - function getSubscription( - uint256 subId - ) - public - view - returns (uint96 linkBalance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers) - { - if (s_subscriptions[subId].owner == address(0)) { - revert InvalidSubscription(); - } - return ( - s_subscriptions[subId].linkBalance, - s_subscriptions[subId].nativeBalance, - s_subscriptions[subId].reqCount, - s_subscriptions[subId].owner, - s_subscriptions[subId].consumers - ); - } - - /*************************************************************************** - * Section: Migration - **************************************************************************/ - - /// @notice emitted when caller is not a previous version of VRF coordinator - /// @param sender caller - /// @param previousCoordinator expected coordinator address - error MustBePreviousCoordinator(address sender, address previousCoordinator); - - /// @notice emitted when version in the request doesn't match expected version - error InvalidVersion(uint8 requestVersion, uint8 expectedVersion); - - /// @notice emitted when transferred balance (msg.value) does not match the metadata in V1MigrationData - error InvalidNativeBalance(uint256 transferredValue, uint96 expectedValue); - - /// @dev encapsulates data migrated over from previous coordinator - // solhint-disable-next-line gas-struct-packing - struct V1MigrationData { - uint8 fromVersion; - uint256 subId; - address subOwner; - address[] consumers; - uint96 linkBalance; - uint96 nativeBalance; - } - - /** - * @inheritdoc IVRFCoordinatorV2PlusMigration - */ - function onMigration(bytes calldata encodedData) external payable override { - if (msg.sender != s_prevCoordinator) { - revert MustBePreviousCoordinator(msg.sender, s_prevCoordinator); - } - - V1MigrationData memory migrationData = abi.decode(encodedData, (V1MigrationData)); - - if (migrationData.fromVersion != 1) { - revert InvalidVersion(migrationData.fromVersion, 1); - } - - if (msg.value != uint256(migrationData.nativeBalance)) { - revert InvalidNativeBalance(msg.value, migrationData.nativeBalance); - } - - // it should be impossible to have a subscription id collision, for two reasons: - // 1. the subscription ID is calculated using inputs that cannot be replicated under different - // conditions. - // 2. once a subscription is migrated it is deleted from the previous coordinator, so it cannot - // be migrated again. - // however, we should have this check here in case the `migrate` function on - // future coordinators "forgets" to delete subscription data allowing re-migration of the same - // subscription. - if (s_subscriptions[migrationData.subId].owner != address(0)) { - revert SubscriptionIDCollisionFound(); - } - - s_subscriptions[migrationData.subId] = Subscription({ - nativeBalance: migrationData.nativeBalance, - linkBalance: migrationData.linkBalance, - reqCount: 0, - owner: migrationData.subOwner, - consumers: migrationData.consumers - }); - s_totalNativeBalance += migrationData.nativeBalance; - s_totalLinkBalance += migrationData.linkBalance; - } - - /*************************************************************************** - * Section: Request/Response - **************************************************************************/ - - function requestRandomWords(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256 requestId) { - Subscription memory sub = s_subscriptions[req.subId]; - sub.reqCount = sub.reqCount + 1; - return _handleRequest(msg.sender); - } - - function _handleRequest(address requester) private returns (uint256) { - s_requestId = s_requestId + 1; - uint256 requestId = s_requestId; - s_requestConsumerMapping[s_requestId] = requester; - return requestId; - } - - function generateFakeRandomness(uint256 requestID) public pure returns (uint256[] memory) { - uint256[] memory randomness = new uint256[](1); - randomness[0] = uint256(keccak256(abi.encode(requestID, "not random"))); - return randomness; - } - - function fulfillRandomWords(uint256 requestId) external { - VRFConsumerBaseV2Plus consumer = VRFConsumerBaseV2Plus(s_requestConsumerMapping[requestId]); - consumer.rawFulfillRandomWords(requestId, generateFakeRandomness(requestId)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol deleted file mode 100644 index f638b97..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFMaliciousConsumerV2Plus.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -contract VRFMaliciousConsumerV2Plus is VRFConsumerBaseV2Plus { - uint256[] public s_randomWords; - uint256 public s_requestId; - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - LinkTokenInterface internal LINKTOKEN; - uint256 public s_gasAvailable; - uint256 internal s_subId; - bytes32 internal s_keyHash; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { - LINKTOKEN = LinkTokenInterface(link); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - s_requestId = requestId; - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: s_keyHash, - subId: s_subId, - requestConfirmations: 1, - callbackGasLimit: 200000, - numWords: 1, - extraArgs: "" // empty extraArgs defaults to link payment - }); - // Should revert - s_vrfCoordinator.requestRandomWords(req); - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = s_vrfCoordinator.createSubscription(); - s_vrfCoordinator.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - s_vrfCoordinator.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness(bytes32 keyHash) external returns (uint256) { - s_keyHash = keyHash; - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: keyHash, - subId: s_subId, - requestConfirmations: 1, - callbackGasLimit: 500000, - numWords: 1, - extraArgs: "" // empty extraArgs defaults to link payment - }); - return s_vrfCoordinator.requestRandomWords(req); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol deleted file mode 100644 index 137235f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFOld.sol +++ /dev/null @@ -1,588 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -/** **************************************************************************** - * @notice Verification of verifiable-random-function (VRF) proofs, following - * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. - - * @dev Bibliographic references: - - * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft - * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 - - * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology - * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf - * **************************************************************************** - * @dev USAGE - - * @dev The main entry point is _randomValueFromVRFProof. See its docstring. - * **************************************************************************** - * @dev PURPOSE - - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is computationally indistinguishable to her from a uniform - * @dev random sample from the output space. - - * @dev The purpose of this contract is to perform that verification. - * **************************************************************************** - * @dev DESIGN NOTES - - * @dev The VRF algorithm verified here satisfies the full uniqueness, full - * @dev collision resistance, and full pseudo-randomness security properties. - * @dev See "SECURITY PROPERTIES" below, and - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 - - * @dev An elliptic curve point is generally represented in the solidity code - * @dev as a uint256[2], corresponding to its affine coordinates in - * @dev GF(FIELD_SIZE). - - * @dev For the sake of efficiency, this implementation deviates from the spec - * @dev in some minor ways: - - * @dev - Keccak hash rather than the SHA256 hash recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev Keccak costs much less gas on the EVM, and provides similar security. - - * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER - - * @dev - _hashToCurve recursively hashes until it finds a curve x-ordinate. On - * @dev the EVM, this is slightly more efficient than the recommendation in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - * @dev step 5, to concatenate with a nonce then hash, and rehash with the - * @dev nonce updated until a valid x-ordinate is found. - - * @dev - _hashToCurve does not include a cipher version string or the byte 0x1 - * @dev in the hash message, as recommended in step 5.B of the draft - * @dev standard. They are unnecessary here because no variation in the - * @dev cipher suite is allowed. - - * @dev - Similarly, the hash input in _scalarFromCurvePoints does not include a - * @dev commitment to the cipher suite, either, which differs from step 2 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - * @dev . Also, the hash input is the concatenation of the uncompressed - * @dev points, not the compressed points as recommended in step 3. - - * @dev - In the calculation of the challenge value "c", the "u" value (i.e. - * @dev the value computed by Reggie as the nonce times the secp256k1 - * @dev generator point, see steps 5 and 7 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the - * @dev keccak hash of the original u. This is because we only verify the - * @dev calculation of u up to its address, by abusing ECRECOVER. - * **************************************************************************** - * @dev SECURITY PROPERTIES - - * @dev Here are the security properties for this VRF: - - * @dev Full uniqueness: For any seed and valid VRF public key, there is - * @dev exactly one VRF output which can be proved to come from that seed, in - * @dev the sense that the proof will pass _verifyVRFProof. - - * @dev Full collision resistance: It's cryptographically infeasible to find - * @dev two seeds with same VRF output from a fixed, valid VRF key - - * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are - * @dev derived from a given seed, the outputs are computationally - * @dev indistinguishable from randomness. - - * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs - * @dev for these properties. - - * @dev For secp256k1, the key validation described in section - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 - * @dev is unnecessary, because secp256k1 has cofactor 1, and the - * @dev representation of the public key used here (affine x- and y-ordinates - * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to - * @dev the point at infinity. - * **************************************************************************** - * @dev OTHER SECURITY CONSIDERATIONS - * - * @dev The seed input to the VRF could in principle force an arbitrary amount - * @dev of work in _hashToCurve, by requiring extra rounds of hashing and - * @dev checking whether that's yielded the x ordinate of a secp256k1 point. - * @dev However, under the Random Oracle Model the probability of choosing a - * @dev point which forces n extra rounds in _hashToCurve is 2⁻ⁿ. The base cost - * @dev for calling _hashToCurve is about 25,000 gas, and each round of checking - * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for - * @dev which _hashToCurve would cost more than 2,017,000 gas, one would have to - * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any - * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) - - * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, - * @dev this means it is infeasible for an adversary to prevent correct - * @dev operation of this contract by choosing an adverse seed. - - * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for - * @dev _hashToCurve.) - - * @dev It may be possible to make a secure constant-time _hashToCurve function. - * @dev See notes in _hashToCurve docstring. -*/ -contract VRFOld { - // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. - // Number of points in Secp256k1 - uint256 private constant GROUP_ORDER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; - // Prime characteristic of the galois field over which Secp256k1 is defined - uint256 private constant FIELD_SIZE = - // solium-disable-next-line indentation - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; - uint256 private constant WORD_LENGTH_BYTES = 0x20; - - // (base^exponent) % FIELD_SIZE - // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 - function _bigModExp(uint256 base, uint256 exponent) internal view returns (uint256 exponentiation) { - uint256 callResult; - uint256[6] memory bigModExpContractInputs; - bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base - bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent - bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus - bigModExpContractInputs[3] = base; - bigModExpContractInputs[4] = exponent; - bigModExpContractInputs[5] = FIELD_SIZE; - uint256[1] memory output; - assembly { - callResult := staticcall( - not(0), // Gas cost: no limit - 0x05, // Bigmodexp contract address - bigModExpContractInputs, - 0xc0, // Length of input segment: 6*0x20-bytes - output, - 0x20 // Length of output segment - ) - } - if (callResult == 0) { - // solhint-disable-next-line gas-custom-errors - revert("bigModExp failure!"); - } - return output[0]; - } - - // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See - // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus - uint256 private constant SQRT_POWER = (FIELD_SIZE + 1) >> 2; - - // Computes a s.t. a^2 = x in the field. Assumes a exists - function _squareRoot(uint256 x) internal view returns (uint256) { - return _bigModExp(x, SQRT_POWER); - } - - // The value of y^2 given that (x,y) is on secp256k1. - function _ySquared(uint256 x) internal pure returns (uint256) { - // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf - uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); - return addmod(xCubed, 7, FIELD_SIZE); - } - - // True iff p is on secp256k1 - function _isOnCurve(uint256[2] memory p) internal pure returns (bool) { - // Section 2.3.6. in https://www.secg.org/sec1-v2.pdf - // requires each ordinate to be in [0, ..., FIELD_SIZE-1] - // solhint-disable-next-line gas-custom-errors - require(p[0] < FIELD_SIZE, "invalid x-ordinate"); - // solhint-disable-next-line gas-custom-errors - require(p[1] < FIELD_SIZE, "invalid y-ordinate"); - return _ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); - } - - // Hash x uniformly into {0, ..., FIELD_SIZE-1}. - function _fieldHash(bytes memory b) internal pure returns (uint256 x_) { - x_ = uint256(keccak256(b)); - // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of - // http://www.secg.org/sec1-v2.pdf , which is part of the definition of - // string_to_point in the IETF draft - while (x_ >= FIELD_SIZE) { - x_ = uint256(keccak256(abi.encodePacked(x_))); - } - return x_; - } - - // Hash b to a random point which hopefully lies on secp256k1. The y ordinate - // is always even, due to - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - // step 5.C, which references arbitrary_string_to_point, defined in - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as - // returning the point with given x ordinate, and even y ordinate. - function _newCandidateSecp256k1Point(bytes memory b) internal view returns (uint256[2] memory p) { - unchecked { - p[0] = _fieldHash(b); - p[1] = _squareRoot(_ySquared(p[0])); - if (p[1] % 2 == 1) { - // Note that 0 <= p[1] < FIELD_SIZE - // so this cannot wrap, we use unchecked to save gas. - p[1] = FIELD_SIZE - p[1]; - } - } - return p; - } - - // Domain-separation tag for initial hash in _hashToCurve. Corresponds to - // vrf.go/hashToCurveHashPrefix - uint256 internal constant HASH_TO_CURVE_HASH_PREFIX = 1; - - // Cryptographic hash function onto the curve. - // - // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see - // DESIGN NOTES above for slight differences.) - // - // TODO(alx): Implement a bounded-computation hash-to-curve, as described in - // "Construction of Rational Points on Elliptic Curves over Finite Fields" - // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf - // and suggested by - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 - // (Though we can't used exactly that because secp256k1's j-invariant is 0.) - // - // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" - // https://www.pivotaltracker.com/story/show/171120900 - function _hashToCurve(uint256[2] memory pk, uint256 input) internal view returns (uint256[2] memory rv) { - rv = _newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, pk, input)); - while (!_isOnCurve(rv)) { - rv = _newCandidateSecp256k1Point(abi.encodePacked(rv[0])); - } - return rv; - } - - /** ********************************************************************* - * @notice Check that product==scalar*multiplicand - * - * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. - * - * @param multiplicand: secp256k1 point - * @param scalar: non-zero GF(GROUP_ORDER) scalar - * @param product: secp256k1 expected to be multiplier * multiplicand - * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability - */ - function _ecmulVerify( - uint256[2] memory multiplicand, - uint256 scalar, - uint256[2] memory product - ) internal pure returns (bool verifies) { - // solhint-disable-next-line gas-custom-errors - require(scalar != 0, "zero scalar"); // Rules out an ecrecover failure case - uint256 x = multiplicand[0]; // x ordinate of multiplicand - uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is - // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. - // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 - bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); - address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); - // Explicit conversion to address takes bottom 160 bits - address expected = address(uint160(uint256(keccak256(abi.encodePacked(product))))); - return (actual == expected); - } - - // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) - function _projectiveSub( - uint256 x1, - uint256 z1, - uint256 x2, - uint256 z2 - ) internal pure returns (uint256 x3, uint256 z3) { - unchecked { - uint256 num1 = mulmod(z2, x1, FIELD_SIZE); - // Note this cannot wrap since x2 is a point in [0, FIELD_SIZE-1] - // we use unchecked to save gas. - uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); - (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - } - return (x3, z3); - } - - // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) - function _projectiveMul( - uint256 x1, - uint256 z1, - uint256 x2, - uint256 z2 - ) internal pure returns (uint256 x3, uint256 z3) { - (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - return (x3, z3); - } - - /** ************************************************************************** - @notice Computes elliptic-curve sum, in projective co-ordinates - - @dev Using projective coordinates avoids costly divisions - - @dev To use this with p and q in affine coordinates, call - @dev _projectiveECAdd(px, py, qx, qy). This will return - @dev the addition of (px, py, 1) and (qx, qy, 1), in the - @dev secp256k1 group. - - @dev This can be used to calculate the z which is the inverse to zInv - @dev in isValidVRFOutput. But consider using a faster - @dev re-implementation such as ProjectiveECAdd in the golang vrf package. - - @dev This function assumes [px,py,1],[qx,qy,1] are valid projective - coordinates of secp256k1 points. That is safe in this contract, - because this method is only used by _linearCombination, which checks - points are on the curve via ecrecover. - ************************************************************************** - @param px The first affine coordinate of the first summand - @param py The second affine coordinate of the first summand - @param qx The first affine coordinate of the second summand - @param qy The second affine coordinate of the second summand - - (px,py) and (qx,qy) must be distinct, valid secp256k1 points. - ************************************************************************** - Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points - on secp256k1, in P²(𝔽ₙ) - @return sx - @return sy - @return sz - */ - function _projectiveECAdd( - uint256 px, - uint256 py, - uint256 qx, - uint256 qy - ) internal pure returns (uint256 sx, uint256 sy, uint256 sz) { - unchecked { - // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, - // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone - // We take the equations there for (sx,sy), and homogenize them to - // projective coordinates. That way, no inverses are required, here, and we - // only need the one inverse in _affineECAdd. - - // We only need the "point addition" equations from Hankerson et al. Can - // skip the "point doubling" equations because p1 == p2 is cryptographically - // impossible, and required not to be the case in _linearCombination. - - // Add extra "projective coordinate" to the two points - (uint256 z1, uint256 z2) = (1, 1); - - // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. - // Cannot wrap since px and py are in [0, FIELD_SIZE-1] - uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); - uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); - - uint256 dx; // Accumulates denominator from sx calculation - // sx=((qy-py)/(qx-px))^2-px-qx - (sx, dx) = _projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 - (sx, dx) = _projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px - (sx, dx) = _projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx - - uint256 dy; // Accumulates denominator from sy calculation - // sy=((qy-py)/(qx-px))(px-sx)-py - (sy, dy) = _projectiveSub(px, z1, sx, dx); // px-sx - (sy, dy) = _projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) - (sy, dy) = _projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py - - if (dx != dy) { - // Cross-multiply to put everything over a common denominator - sx = mulmod(sx, dy, FIELD_SIZE); - sy = mulmod(sy, dx, FIELD_SIZE); - sz = mulmod(dx, dy, FIELD_SIZE); - } else { - // Already over a common denominator, use that for z ordinate - sz = dx; - } - } - return (sx, sy, sz); - } - - // p1+p2, as affine points on secp256k1. - // - // invZ must be the inverse of the z returned by _projectiveECAdd(p1, p2). - // It is computed off-chain to save gas. - // - // p1 and p2 must be distinct, because _projectiveECAdd doesn't handle - // point doubling. - function _affineECAdd( - uint256[2] memory p1, - uint256[2] memory p2, - uint256 invZ - ) internal pure returns (uint256[2] memory) { - uint256 x; - uint256 y; - uint256 z; - (x, y, z) = _projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); - // solhint-disable-next-line gas-custom-errors - require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); - // Clear the z ordinate of the projective representation by dividing through - // by it, to obtain the affine representation - return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; - } - - // True iff address(c*p+s*g) == lcWitness, where g is generator. (With - // cryptographically high probability.) - function _verifyLinearCombinationWithGenerator( - uint256 c, - uint256[2] memory p, - uint256 s, - address lcWitness - ) internal pure returns (bool) { - // Rule out ecrecover failure modes which return address 0. - unchecked { - // solhint-disable-next-line gas-custom-errors - require(lcWitness != address(0), "bad witness"); - uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p - // Note this cannot wrap (X - Y % X), but we use unchecked to save - // gas. - bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] - bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // The point corresponding to the address returned by - // ecrecover(-s*p[0],v,p[0],c*p[0]) is - // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. - // See https://crypto.stackexchange.com/a/18106 - // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v - address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); - return computed == lcWitness; - } - } - - // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also - // requires cp1Witness != sp2Witness (which is fine for this application, - // since it is cryptographically impossible for them to be equal. In the - // (cryptographically impossible) case that a prover accidentally derives - // a proof with equal c*p1 and s*p2, they should retry with a different - // proof nonce.) Assumes that all points are on secp256k1 - // (which is checked in _verifyVRFProof below.) - function _linearCombination( - uint256 c, - uint256[2] memory p1, - uint256[2] memory cp1Witness, - uint256 s, - uint256[2] memory p2, - uint256[2] memory sp2Witness, - uint256 zInv - ) internal pure returns (uint256[2] memory) { - unchecked { - // Note we are relying on the wrap around here - // solhint-disable-next-line gas-custom-errors - require((cp1Witness[0] % FIELD_SIZE) != (sp2Witness[0] % FIELD_SIZE), "points in sum must be distinct"); - // solhint-disable-next-line gas-custom-errors - require(_ecmulVerify(p1, c, cp1Witness), "First mul check failed"); - // solhint-disable-next-line gas-custom-errors - require(_ecmulVerify(p2, s, sp2Witness), "Second mul check failed"); - return _affineECAdd(cp1Witness, sp2Witness, zInv); - } - } - - // Domain-separation tag for the hash taken in _scalarFromCurvePoints. - // Corresponds to scalarFromCurveHashPrefix in vrf.go - uint256 internal constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; - - // Pseudo-random number from inputs. Matches vrf.go/_scalarFromCurvePoints, and - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - // The draft calls (in step 7, via the definition of string_to_int, in - // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the - // first hash without checking that it corresponds to a number less than the - // group order, which will lead to a slight bias in the sample. - // - // TODO(alx): We could save a bit of gas by following the standard here and - // using the compressed representation of the points, if we collated the y - // parities into a single bytes32. - // https://www.pivotaltracker.com/story/show/171120588 - function _scalarFromCurvePoints( - uint256[2] memory hash, - uint256[2] memory pk, - uint256[2] memory gamma, - address uWitness, - uint256[2] memory v - ) internal pure returns (uint256 s) { - return uint256(keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, hash, pk, gamma, v, uWitness))); - } - - // True if (gamma, c, s) is a correctly constructed randomness proof from pk - // and seed. zInv must be the inverse of the third ordinate from - // _projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to - // section 5.3 of the IETF draft. - // - // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass - // the x ordinate, and the parity of the y ordinate in the top bit of uWitness - // (which I could make a uint256 without using any extra space.) Would save - // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 - function _verifyVRFProof( - uint256[2] memory pk, - uint256[2] memory gamma, - uint256 c, - uint256 s, - uint256 seed, - address uWitness, - uint256[2] memory cGammaWitness, - uint256[2] memory sHashWitness, - uint256 zInv - ) internal view { - unchecked { - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(pk), "public key is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(gamma), "gamma is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); - // solhint-disable-next-line gas-custom-errors - require(_isOnCurve(sHashWitness), "sHashWitness is not on curve"); - // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here - // we use the address of u instead of u itself. Also, here we add the - // terms instead of taking the difference, and in the proof construction in - // vrf.GenerateProof, we correspondingly take the difference instead of - // taking the sum as they do in step 7 of section 5.1.) - // solhint-disable-next-line gas-custom-errors - require(_verifyLinearCombinationWithGenerator(c, pk, s, uWitness), "addr(c*pk+s*g)!=_uWitness"); - // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) - uint256[2] memory hash = _hashToCurve(pk, seed); - // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms - uint256[2] memory v = _linearCombination(c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); - // Steps 7. and 8. of IETF draft section 5.3 - uint256 derivedC = _scalarFromCurvePoints(hash, pk, gamma, uWitness, v); - // solhint-disable-next-line gas-custom-errors - require(c == derivedC, "invalid proof"); - } - } - - // Domain-separation tag for the hash used as the final VRF output. - // Corresponds to vrfRandomOutputHashPrefix in vrf.go - uint256 internal constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; - - struct Proof { - uint256[2] pk; - uint256[2] gamma; - uint256 c; - uint256 s; - uint256 seed; - address uWitness; - uint256[2] cGammaWitness; - uint256[2] sHashWitness; - uint256 zInv; - } - - /* *************************************************************************** - * @notice Returns proof's output, if proof is valid. Otherwise reverts - - * @param proof vrf proof components - * @param seed seed used to generate the vrf output - * - * Throws if proof is invalid, otherwise: - * @return output i.e., the random output implied by the proof - * *************************************************************************** - */ - function _randomValueFromVRFProof(Proof memory proof, uint256 seed) internal view returns (uint256 output) { - _verifyVRFProof( - proof.pk, - proof.gamma, - proof.c, - proof.s, - seed, - proof.uWitness, - proof.cGammaWitness, - proof.sHashWitness, - proof.zInv - ); - output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, proof.gamma))); - return output; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol deleted file mode 100644 index d142f50..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -/// @notice This contract is used for testing only and should not be used for production. -contract VRFV2PlusConsumerExample is ConfirmedOwner, VRFConsumerBaseV2Plus { - LinkTokenInterface public s_linkToken; - uint256 public s_recentRequestId; - IVRFCoordinatorV2Plus public s_vrfCoordinatorApiV1; - uint256 public s_subId; - - struct Response { - bool fulfilled; - address requester; - uint256 requestId; - uint256[] randomWords; - } - mapping(uint256 /* request id */ => Response /* response */) public s_requests; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { - s_vrfCoordinatorApiV1 = IVRFCoordinatorV2Plus(vrfCoordinator); - s_linkToken = LinkTokenInterface(link); - } - - function getRandomness(uint256 requestId, uint256 idx) public view returns (uint256 randomWord) { - Response memory resp = s_requests[requestId]; - // solhint-disable-next-line gas-custom-errors - require(resp.requestId != 0, "request ID is incorrect"); - return resp.randomWords[idx]; - } - - function _subscribe() internal returns (uint256) { - if (s_subId == 0) { - s_subId = s_vrfCoordinatorApiV1.createSubscription(); - s_vrfCoordinatorApiV1.addConsumer(s_subId, address(this)); - } - return s_subId; - } - - function createSubscriptionAndFundNative() external payable { - _subscribe(); - s_vrfCoordinatorApiV1.fundSubscriptionWithNative{value: msg.value}(s_subId); - } - - function createSubscriptionAndFund(uint96 amount) external { - _subscribe(); - // Approve the link transfer. - s_linkToken.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "sub not set"); - s_linkToken.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); - } - - function topUpSubscriptionNative() external payable { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "sub not set"); - s_vrfCoordinatorApiV1.fundSubscriptionWithNative{value: msg.value}(s_subId); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(requestId == s_recentRequestId, "request ID is incorrect"); - s_requests[requestId].randomWords = randomWords; - s_requests[requestId].fulfilled = true; - } - - function requestRandomWords( - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash, - bool nativePayment - ) external { - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: keyHash, - subId: s_subId, - requestConfirmations: requestConfirmations, - callbackGasLimit: callbackGasLimit, - numWords: numWords, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) - }); - uint256 requestId = s_vrfCoordinator.requestRandomWords(req); - Response memory resp = Response({ - requestId: requestId, - randomWords: new uint256[](0), - fulfilled: false, - requester: msg.sender - }); - s_requests[requestId] = resp; - s_recentRequestId = requestId; - } - - function updateSubscription(address[] memory consumers) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - s_vrfCoordinatorApiV1.addConsumer(s_subId, consumers[i]); - } - } - - function setSubId(uint256 subId) external { - s_subId = subId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol deleted file mode 100644 index 8eb2261..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusExternalSubOwnerExample.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -/// @notice This contract is used for testing only and should not be used for production. -contract VRFV2PlusExternalSubOwnerExample is VRFConsumerBaseV2Plus { - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - LinkTokenInterface internal LINKTOKEN; - - uint256[] public s_randomWords; - uint256 public s_requestId; - address internal s_owner; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { - LINKTOKEN = LinkTokenInterface(link); - s_owner = msg.sender; - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(requestId == s_requestId, "request ID is incorrect"); - s_randomWords = randomWords; - } - - function requestRandomWords( - uint256 subId, - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash, - bool nativePayment - ) external onlyOwner { - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: keyHash, - subId: subId, - requestConfirmations: requestConfirmations, - callbackGasLimit: callbackGasLimit, - numWords: numWords, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) - }); - // Will revert if subscription is not funded. - s_requestId = s_vrfCoordinator.requestRandomWords(req); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol deleted file mode 100644 index 87e70f6..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -/** - * @title The VRFLoadTestExternalSubOwner contract. - * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. - */ -contract VRFV2PlusLoadTestWithMetrics is VRFConsumerBaseV2Plus { - uint256 public s_responseCount; - uint256 public s_requestCount; - uint256 public s_averageResponseTimeInBlocksMillions = 0; // in millions for better precision - uint256 public s_slowestResponseTimeInBlocks = 0; - uint256 public s_fastestResponseTimeInBlocks = 999; - uint256 public s_slowestResponseTimeInSeconds = 0; - uint256 public s_fastestResponseTimeInSeconds = 999; - uint256 public s_averageResponseTimeInSecondsMillions = 0; - - uint256 public s_lastRequestId; - - uint32[] public s_requestBlockTimes; - - struct RequestStatus { - bool fulfilled; - uint256[] randomWords; - uint256 requestTimestamp; - uint256 fulfilmentTimestamp; - uint256 requestBlockNumber; - uint256 fulfilmentBlockNumber; - } - - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor(address _vrfCoordinator) VRFConsumerBaseV2Plus(_vrfCoordinator) {} - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] calldata _randomWords) internal override { - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - s_requests[_requestId].fulfilmentTimestamp = block.timestamp; - s_requests[_requestId].fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); - - uint256 responseTimeInBlocks = s_requests[_requestId].fulfilmentBlockNumber - - s_requests[_requestId].requestBlockNumber; - uint256 responseTimeInSeconds = s_requests[_requestId].fulfilmentTimestamp - - s_requests[_requestId].requestTimestamp; - - ( - s_slowestResponseTimeInBlocks, - s_fastestResponseTimeInBlocks, - s_averageResponseTimeInBlocksMillions - ) = _calculateMetrics( - responseTimeInBlocks, - s_fastestResponseTimeInBlocks, - s_slowestResponseTimeInBlocks, - s_averageResponseTimeInBlocksMillions, - s_responseCount - ); - ( - s_slowestResponseTimeInSeconds, - s_fastestResponseTimeInSeconds, - s_averageResponseTimeInSecondsMillions - ) = _calculateMetrics( - responseTimeInSeconds, - s_fastestResponseTimeInSeconds, - s_slowestResponseTimeInSeconds, - s_averageResponseTimeInSecondsMillions, - s_responseCount - ); - - s_responseCount++; - - s_requestBlockTimes.push(uint32(responseTimeInBlocks)); - } - - function requestRandomWords( - uint256 _subId, - uint16 _requestConfirmations, - bytes32 _keyHash, - uint32 _callbackGasLimit, - bool _nativePayment, - uint32 _numWords, - uint16 _requestCount - ) external { - for (uint16 i = 0; i < _requestCount; i++) { - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: _keyHash, - subId: _subId, - requestConfirmations: _requestConfirmations, - callbackGasLimit: _callbackGasLimit, - numWords: _numWords, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: _nativePayment})) - }); - // Will revert if subscription is not funded. - uint256 requestId = s_vrfCoordinator.requestRandomWords(req); - - s_lastRequestId = requestId; - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - s_requests[requestId] = RequestStatus({ - randomWords: new uint256[](0), - fulfilled: false, - requestTimestamp: block.timestamp, - fulfilmentTimestamp: 0, - requestBlockNumber: requestBlockNumber, - fulfilmentBlockNumber: 0 - }); - s_requestCount++; - } - } - - function reset() external { - s_averageResponseTimeInBlocksMillions = 0; // in millions for better precision - s_slowestResponseTimeInBlocks = 0; - s_fastestResponseTimeInBlocks = 999; - s_averageResponseTimeInSecondsMillions = 0; // in millions for better precision - s_slowestResponseTimeInSeconds = 0; - s_fastestResponseTimeInSeconds = 999; - s_requestCount = 0; - s_responseCount = 0; - delete s_requestBlockTimes; - } - - function getRequestStatus( - uint256 _requestId - ) - external - view - returns ( - bool fulfilled, - uint256[] memory randomWords, - uint256 requestTimestamp, - uint256 fulfilmentTimestamp, - uint256 requestBlockNumber, - uint256 fulfilmentBlockNumber - ) - { - RequestStatus memory request = s_requests[_requestId]; - return ( - request.fulfilled, - request.randomWords, - request.requestTimestamp, - request.fulfilmentTimestamp, - request.requestBlockNumber, - request.fulfilmentBlockNumber - ); - } - - function _calculateMetrics( - uint256 _responseTime, - uint256 _fastestResponseTime, - uint256 _slowestResponseTime, - uint256 _averageInMillions, - uint256 _responseCount - ) internal pure returns (uint256 slowest, uint256 fastest, uint256 average) { - uint256 _requestDelayInMillions = _responseTime * 1_000_000; - if (_responseTime > _slowestResponseTime) { - _slowestResponseTime = _responseTime; - } - _fastestResponseTime = _responseTime < _fastestResponseTime ? _responseTime : _fastestResponseTime; - uint256 averageInMillions = _responseCount > 0 - ? (_averageInMillions * _responseCount + _requestDelayInMillions) / (_responseCount + 1) - : _requestDelayInMillions; - - return (_slowestResponseTime, _fastestResponseTime, averageInMillions); - } - - function getRequestBlockTimes(uint256 offset, uint256 quantity) external view returns (uint32[] memory) { - uint256 end = offset + quantity; - if (end > s_requestBlockTimes.length) { - end = s_requestBlockTimes.length; - } - - uint32[] memory blockTimes = new uint32[](end - offset); - for (uint256 i = offset; i < end; i++) { - blockTimes[i - offset] = s_requestBlockTimes[i]; - } - - return blockTimes; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol deleted file mode 100644 index 16797bb..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; - -import {IVRFMigratableConsumerV2Plus} from "../interfaces/IVRFMigratableConsumerV2Plus.sol"; -import {IVRFCoordinatorV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -contract VRFV2PlusMaliciousMigrator is IVRFMigratableConsumerV2Plus { - IVRFCoordinatorV2Plus internal s_vrfCoordinator; - - constructor(address _vrfCoordinator) { - s_vrfCoordinator = IVRFCoordinatorV2Plus(_vrfCoordinator); - } - - /** - * @inheritdoc IVRFMigratableConsumerV2Plus - */ - function setCoordinator(address /* _vrfCoordinator */) public override { - // try to re-enter, should revert - // args don't really matter - s_vrfCoordinator.requestRandomWords( - VRFV2PlusClient.RandomWordsRequest({ - keyHash: bytes32(0), - subId: 0, - requestConfirmations: 0, - callbackGasLimit: 0, - numWords: 0, - extraArgs: "" - }) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol deleted file mode 100644 index e52369b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusRevertingExample.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -// VRFV2RevertingExample will always revert. Used for testing only, useless in prod. -contract VRFV2PlusRevertingExample is VRFConsumerBaseV2Plus { - uint256[] public s_randomWords; - uint256 public s_requestId; - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - LinkTokenInterface internal LINKTOKEN; - uint256 public s_subId; - uint256 public s_gasAvailable; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { - LINKTOKEN = LinkTokenInterface(link); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256, uint256[] calldata) internal pure override { - // solhint-disable-next-line gas-custom-errors, reason-string - revert(); - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = s_vrfCoordinator.createSubscription(); - s_vrfCoordinator.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - s_vrfCoordinator.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness( - bytes32 keyHash, - uint256 subId, - uint16 minReqConfs, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256) { - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: keyHash, - subId: subId, - requestConfirmations: minReqConfs, - callbackGasLimit: callbackGasLimit, - numWords: numWords, - extraArgs: "" // empty extraArgs defaults to link payment - }); - s_requestId = s_vrfCoordinator.requestRandomWords(req); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol deleted file mode 100644 index 2ae45db..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusSingleConsumerExample.sol +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: MIT -// Example of a single consumer contract which owns the subscription. -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFConsumerBaseV2Plus} from "../VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -/// @notice This contract is used for testing only and should not be used for production. -contract VRFV2PlusSingleConsumerExample is VRFConsumerBaseV2Plus { - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - LinkTokenInterface internal LINKTOKEN; - - // solhint-disable-next-line gas-struct-packing - struct RequestConfig { - uint256 subId; - uint32 callbackGasLimit; - uint16 requestConfirmations; - uint32 numWords; - bytes32 keyHash; - bool nativePayment; - } - RequestConfig public s_requestConfig; - uint256[] public s_randomWords; - uint256 public s_requestId; - address internal s_owner; - - constructor( - address vrfCoordinator, - address link, - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash, - bool nativePayment - ) VRFConsumerBaseV2Plus(vrfCoordinator) { - LINKTOKEN = LinkTokenInterface(link); - s_owner = msg.sender; - s_requestConfig = RequestConfig({ - subId: 0, // Unset initially - callbackGasLimit: callbackGasLimit, - requestConfirmations: requestConfirmations, - numWords: numWords, - keyHash: keyHash, - nativePayment: nativePayment - }); - subscribe(); - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(requestId == s_requestId, "request ID is incorrect"); - s_randomWords = randomWords; - } - - // Assumes the subscription is funded sufficiently. - function requestRandomWords() external onlyOwner { - RequestConfig memory rc = s_requestConfig; - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: rc.keyHash, - subId: rc.subId, - requestConfirmations: rc.requestConfirmations, - callbackGasLimit: rc.callbackGasLimit, - numWords: rc.numWords, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: rc.nativePayment})) - }); - // Will revert if subscription is not set and funded. - s_requestId = s_vrfCoordinator.requestRandomWords(req); - } - - // Assumes this contract owns link - // This method is analogous to VRFv1, except the amount - // should be selected based on the keyHash (each keyHash functions like a "gas lane" - // with different link costs). - function fundAndRequestRandomWords(uint256 amount) external onlyOwner { - RequestConfig memory rc = s_requestConfig; - LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_requestConfig.subId)); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: rc.keyHash, - subId: rc.subId, - requestConfirmations: rc.requestConfirmations, - callbackGasLimit: rc.callbackGasLimit, - numWords: rc.numWords, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: rc.nativePayment})) - }); - // Will revert if subscription is not set and funded. - s_requestId = s_vrfCoordinator.requestRandomWords(req); - } - - // Assumes this contract owns link - function topUpSubscription(uint256 amount) external onlyOwner { - LINKTOKEN.transferAndCall(address(s_vrfCoordinator), amount, abi.encode(s_requestConfig.subId)); - } - - function withdraw(uint256 amount, address to) external onlyOwner { - LINKTOKEN.transfer(to, amount); - } - - function unsubscribe(address to) external onlyOwner { - // Returns funds to this address - s_vrfCoordinator.cancelSubscription(s_requestConfig.subId, to); - s_requestConfig.subId = 0; - } - - // Keep this separate in case the contract want to unsubscribe and then - // resubscribe. - function subscribe() public onlyOwner { - // Create a subscription, current subId - address[] memory consumers = new address[](1); - consumers[0] = address(this); - s_requestConfig.subId = s_vrfCoordinator.createSubscription(); - s_vrfCoordinator.addConsumer(s_requestConfig.subId, consumers[0]); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol deleted file mode 100644 index 9510b1b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2PlusWrapperConsumerBase} from "../VRFV2PlusWrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -contract VRFV2PlusWrapperConsumerExample is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { - event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); - event WrapperRequestMade(uint256 indexed requestId, uint256 paid); - - // solhint-disable-next-line gas-struct-packing - struct RequestStatus { - uint256 paid; - bool fulfilled; - uint256[] randomWords; - bool native; - } - - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor(address _vrfV2Wrapper) ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(_vrfV2Wrapper) {} - - function makeRequest( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) external onlyOwner returns (uint256 requestId) { - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); - uint256 paid; - (requestId, paid) = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs); - s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: false}); - emit WrapperRequestMade(requestId, paid); - return requestId; - } - - function makeRequestNative( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) external onlyOwner returns (uint256 requestId) { - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); - uint256 paid; - (requestId, paid) = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs); - s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: true}); - emit WrapperRequestMade(requestId, paid); - return requestId; - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); - } - - function getRequestStatus( - uint256 _requestId - ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - RequestStatus memory request = s_requests[_requestId]; - return (request.paid, request.fulfilled, request.randomWords); - } - - /// @notice withdrawLink withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in juels - function withdrawLink(uint256 amount) external onlyOwner { - i_linkToken.transfer(owner(), amount); - } - - /// @notice withdrawNative withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in wei - function withdrawNative(uint256 amount) external onlyOwner { - (bool success, ) = payable(owner()).call{value: amount}(""); - // solhint-disable-next-line gas-custom-errors - require(success, "withdrawNative failed"); - } - - event Received(address, uint256); - - receive() external payable { - emit Received(msg.sender, msg.value); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol deleted file mode 100644 index 6935723..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperLoadTestConsumer.sol +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2PlusWrapperConsumerBase} from "../VRFV2PlusWrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; -import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol"; - -contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner { - uint256 public s_responseCount; - uint256 public s_requestCount; - uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision - uint256 public s_slowestFulfillment = 0; - uint256 public s_fastestFulfillment = 999; - uint256 public s_lastRequestId; - uint32[] public s_requestBlockTimes; - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made - - event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); - event WrapperRequestMade(uint256 indexed requestId, uint256 paid); - - // solhint-disable-next-line gas-struct-packing - struct RequestStatus { - uint256 paid; - bool fulfilled; - uint256[] randomWords; - uint256 requestTimestamp; - uint256 fulfilmentTimestamp; - uint256 requestBlockNumber; - uint256 fulfilmentBlockNumber; - bool native; - } - - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor(address _vrfV2PlusWrapper) ConfirmedOwner(msg.sender) VRFV2PlusWrapperConsumerBase(_vrfV2PlusWrapper) {} - - function makeRequests( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - uint16 _requestCount - ) external { - for (uint16 i = 0; i < _requestCount; i++) { - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); - (uint256 requestId, uint256 paid) = requestRandomness( - _callbackGasLimit, - _requestConfirmations, - _numWords, - extraArgs - ); - s_lastRequestId = requestId; - - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - s_requests[requestId] = RequestStatus({ - paid: paid, - fulfilled: false, - randomWords: new uint256[](0), - requestTimestamp: block.timestamp, - requestBlockNumber: requestBlockNumber, - fulfilmentTimestamp: 0, - fulfilmentBlockNumber: 0, - native: false - }); - s_requestCount++; - requestHeights[requestId] = requestBlockNumber; - emit WrapperRequestMade(requestId, paid); - } - } - - function makeRequestsNative( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - uint16 _requestCount - ) external { - for (uint16 i = 0; i < _requestCount; i++) { - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); - (uint256 requestId, uint256 paid) = requestRandomnessPayInNative( - _callbackGasLimit, - _requestConfirmations, - _numWords, - extraArgs - ); - s_lastRequestId = requestId; - - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - s_requests[requestId] = RequestStatus({ - paid: paid, - fulfilled: false, - randomWords: new uint256[](0), - requestTimestamp: block.timestamp, - requestBlockNumber: requestBlockNumber, - fulfilmentTimestamp: 0, - fulfilmentBlockNumber: 0, - native: true - }); - s_requestCount++; - requestHeights[requestId] = requestBlockNumber; - emit WrapperRequestMade(requestId, paid); - } - } - - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); - uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; - uint256 requestDelayInMillions = requestDelay * 1_000_000; - - if (requestDelay > s_slowestFulfillment) { - s_slowestFulfillment = requestDelay; - } - s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; - s_averageFulfillmentInMillions = s_responseCount > 0 - ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) - : requestDelayInMillions; - - s_responseCount++; - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - s_requests[_requestId].fulfilmentTimestamp = block.timestamp; - s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; - - s_requestBlockTimes.push(uint32(requestDelay)); - - emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); - } - - function getRequestStatus( - uint256 _requestId - ) - external - view - returns ( - uint256 paid, - bool fulfilled, - uint256[] memory randomWords, - uint256 requestTimestamp, - uint256 fulfilmentTimestamp, - uint256 requestBlockNumber, - uint256 fulfilmentBlockNumber - ) - { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - RequestStatus memory request = s_requests[_requestId]; - return ( - request.paid, - request.fulfilled, - request.randomWords, - request.requestTimestamp, - request.fulfilmentTimestamp, - request.requestBlockNumber, - request.fulfilmentBlockNumber - ); - } - - function getRequestBlockTimes(uint256 offset, uint256 quantity) external view returns (uint32[] memory) { - uint256 end = offset + quantity; - if (end > s_requestBlockTimes.length) { - end = s_requestBlockTimes.length; - } - - uint32[] memory blockTimes = new uint32[](end - offset); - for (uint256 i = offset; i < end; i++) { - blockTimes[i - offset] = s_requestBlockTimes[i]; - } - - return blockTimes; - } - - function reset() external { - s_averageFulfillmentInMillions = 0; // in millions for better precision - s_slowestFulfillment = 0; - s_fastestFulfillment = 999; - s_requestCount = 0; - s_responseCount = 0; - delete s_requestBlockTimes; - } - - /// @notice withdrawLink withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in juels - function withdrawLink(uint256 amount) external onlyOwner { - i_linkToken.transfer(owner(), amount); - } - - /// @notice withdrawNative withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in wei - function withdrawNative(uint256 amount) external onlyOwner { - (bool success, ) = payable(owner()).call{value: amount}(""); - // solhint-disable-next-line gas-custom-errors - require(success, "withdrawNative failed"); - } - - receive() external payable {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol deleted file mode 100644 index 6a42b5b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/BlockhashStoreInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface BlockhashStoreInterface { - function getBlockhash(uint256 number) external view returns (bytes32); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol deleted file mode 100644 index 78140d5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/IAuthorizedReceiver.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -interface IAuthorizedReceiver { - function isAuthorizedSender(address sender) external view returns (bool); - - function getAuthorizedSenders() external returns (address[] memory); - - function setAuthorizedSenders(address[] calldata senders) external; -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol deleted file mode 100644 index 3cb9934..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface VRFCoordinatorV2Interface { - /** - * @notice Get configuration relevant for making requests - * @return minimumRequestConfirmations global min for request confirmations - * @return maxGasLimit global max for request gas limit - * @return s_provingKeyHashes list of registered key hashes - */ - function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory); - - /** - * @notice Request a set of random words. - * @param keyHash - Corresponds to a particular oracle job which uses - * that key for generating the VRF proof. Different keyHash's have different gas price - * ceilings, so you can select a specific one to bound your maximum per request cost. - * @param subId - The ID of the VRF subscription. Must be funded - * with the minimum subscription balance required for the selected keyHash. - * @param minimumRequestConfirmations - How many blocks you'd like the - * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS - * for why you may want to request more. The acceptable range is - * [minimumRequestBlockConfirmations, 200]. - * @param callbackGasLimit - How much gas you'd like to receive in your - * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords - * may be slightly less than this amount because of gas used calling the function - * (argument decoding etc.), so you may need to request slightly more than you expect - * to have inside fulfillRandomWords. The acceptable range is - * [0, maxGasLimit] - * @param numWords - The number of uint256 random values you'd like to receive - * in your fulfillRandomWords callback. Note these numbers are expanded in a - * secure way by the VRFCoordinator from a single random value supplied by the oracle. - * @return requestId - A unique identifier of the request. Can be used to match - * a request to a response in fulfillRandomWords. - */ - function requestRandomWords( - bytes32 keyHash, - uint64 subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256 requestId); - - /** - * @notice Create a VRF subscription. - * @return subId - A unique subscription id. - * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. - * @dev Note to fund the subscription, use transferAndCall. For example - * @dev LINKTOKEN.transferAndCall( - * @dev address(COORDINATOR), - * @dev amount, - * @dev abi.encode(subId)); - */ - function createSubscription() external returns (uint64 subId); - - /** - * @notice Get a VRF subscription. - * @param subId - ID of the subscription - * @return balance - LINK balance of the subscription in juels. - * @return reqCount - number of requests for this subscription, determines fee tier. - * @return owner - owner of the subscription. - * @return consumers - list of consumer address which are able to use this subscription. - */ - function getSubscription( - uint64 subId - ) external view returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers); - - /** - * @notice Request subscription owner transfer. - * @param subId - ID of the subscription - * @param newOwner - proposed new owner of the subscription - */ - function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; - - /** - * @notice Request subscription owner transfer. - * @param subId - ID of the subscription - * @dev will revert if original owner of subId has - * not requested that msg.sender become the new owner. - */ - function acceptSubscriptionOwnerTransfer(uint64 subId) external; - - /** - * @notice Add a consumer to a VRF subscription. - * @param subId - ID of the subscription - * @param consumer - New consumer which can use the subscription - */ - function addConsumer(uint64 subId, address consumer) external; - - /** - * @notice Remove a consumer from a VRF subscription. - * @param subId - ID of the subscription - * @param consumer - Consumer to remove from the subscription - */ - function removeConsumer(uint64 subId, address consumer) external; - - /** - * @notice Cancel a subscription - * @param subId - ID of the subscription - * @param to - Where to send the remaining LINK to - */ - function cancelSubscription(uint64 subId, address to) external; - - /* - * @notice Check to see if there exists a request commitment consumers - * for all consumers and keyhashes for a given sub. - * @param subId - ID of the subscription - * @return true if there exists at least one unfulfilled request for the subscription, false - * otherwise. - */ - function pendingRequestExists(uint64 subId) external view returns (bool); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol deleted file mode 100644 index daac158..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/interfaces/VRFV2WrapperInterface.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// solhint-disable-next-line interface-starts-with-i -interface VRFV2WrapperInterface { - /** - * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only - * be relied option within the same transaction that the request was made. - */ - function lastRequestId() external view returns (uint256); - - /** - * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current - * @notice block. - * - * @dev This function relies on the transaction gas price which is not automatically set during - * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - */ - function calculateRequestPrice(uint32 _callbackGasLimit) external view returns (uint256); - - /** - * @notice Estimates the price of a VRF request with a specific gas limit and gas price. - * - * @dev This is a convenience function that can be called in simulation to better understand - * @dev pricing. - * - * @param _callbackGasLimit is the gas limit used to estimate the price. - * @param _requestGasPriceWei is the gas price in wei used for the estimation. - */ - function estimateRequestPrice(uint32 _callbackGasLimit, uint256 _requestGasPriceWei) external view returns (uint256); -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol deleted file mode 100644 index e192f74..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorMock.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFConsumerBase} from "../../vrf/VRFConsumerBase.sol"; - -// solhint-disable gas-custom-errors - -contract VRFCoordinatorMock { - LinkTokenInterface public LINK; - - event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); - - constructor(address linkAddress) { - LINK = LinkTokenInterface(linkAddress); - } - - function onTokenTransfer(address sender, uint256 fee, bytes memory _data) public onlyLINK { - (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); - emit RandomnessRequest(sender, keyHash, seed, fee); - } - - function callBackWithRandomness(bytes32 requestId, uint256 randomness, address consumerContract) public { - VRFConsumerBase v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomness.selector, requestId, randomness); - uint256 b = 206000; - require(gasleft() >= b, "not enough gas for consumer"); - // solhint-disable-next-line avoid-low-level-calls, no-unused-vars - (bool success, ) = consumerContract.call(resp); - } - - modifier onlyLINK() { - require(msg.sender == address(LINK), "Must use LINK token"); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol deleted file mode 100644 index 9617b76..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol +++ /dev/null @@ -1,323 +0,0 @@ -// SPDX-License-Identifier: MIT -// A mock for testing code that relies on VRFCoordinatorV2. -pragma solidity ^0.8.4; - -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -// solhint-disable chainlink-solidity/prefix-immutable-variables-with-i -// solhint-disable gas-custom-errors -// solhint-disable avoid-low-level-calls - -contract VRFCoordinatorV2Mock is VRFCoordinatorV2Interface, ConfirmedOwner { - uint96 public immutable BASE_FEE; - uint96 public immutable GAS_PRICE_LINK; - uint16 public immutable MAX_CONSUMERS = 100; - - error InvalidSubscription(); - error InsufficientBalance(); - error MustBeSubOwner(address owner); - error TooManyConsumers(); - error InvalidConsumer(); - error InvalidRandomWords(); - error Reentrant(); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint64 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address indexed sender - ); - event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); - event SubscriptionCreated(uint64 indexed subId, address owner); - event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); - event ConsumerAdded(uint64 indexed subId, address consumer); - event ConsumerRemoved(uint64 indexed subId, address consumer); - event ConfigSet(); - - struct Config { - // Reentrancy protection. - bool reentrancyLock; - } - Config private s_config; - uint64 internal s_currentSubId; - uint256 internal s_nextRequestId = 1; - uint256 internal s_nextPreSeed = 100; - struct Subscription { - address owner; - uint96 balance; - } - mapping(uint64 => Subscription) internal s_subscriptions; /* subId */ /* subscription */ - mapping(uint64 => address[]) internal s_consumers; /* subId */ /* consumers */ - - struct Request { - uint64 subId; - uint32 callbackGasLimit; - uint32 numWords; - } - mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ - - constructor(uint96 _baseFee, uint96 _gasPriceLink) ConfirmedOwner(msg.sender) { - BASE_FEE = _baseFee; - GAS_PRICE_LINK = _gasPriceLink; - setConfig(); - } - - /** - * @notice Sets the configuration of the vrfv2 mock coordinator - */ - function setConfig() public onlyOwner { - s_config = Config({reentrancyLock: false}); - emit ConfigSet(); - } - - function consumerIsAdded(uint64 _subId, address _consumer) public view returns (bool) { - address[] memory consumers = s_consumers[_subId]; - for (uint256 i = 0; i < consumers.length; i++) { - if (consumers[i] == _consumer) { - return true; - } - } - return false; - } - - modifier onlyValidConsumer(uint64 _subId, address _consumer) { - if (!consumerIsAdded(_subId, _consumer)) { - revert InvalidConsumer(); - } - _; - } - - /** - * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied - * @notice consumer. - * - * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does - * @dev not account for all edge cases handled in the real VRF coordinator. When making requests - * @dev against the real coordinator a small amount of additional LINK is required. - * - * @param _requestId the request to fulfill - * @param _consumer the VRF randomness consumer to send the result to - */ - function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { - fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); - } - - /** - * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. - * - * @param _requestId the request to fulfill - * @param _consumer the VRF randomness consumer to send the result to - * @param _words user-provided random words - */ - function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { - uint256 startGas = gasleft(); - if (s_requests[_requestId].subId == 0) { - revert("nonexistent request"); - } - Request memory req = s_requests[_requestId]; - - if (_words.length == 0) { - _words = new uint256[](req.numWords); - for (uint256 i = 0; i < req.numWords; i++) { - _words[i] = uint256(keccak256(abi.encode(_requestId, i))); - } - } else if (_words.length != req.numWords) { - revert InvalidRandomWords(); - } - - VRFConsumerBaseV2 v; - bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); - s_config.reentrancyLock = true; - (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); - s_config.reentrancyLock = false; - - uint96 payment = uint96(BASE_FEE + ((startGas - gasleft()) * GAS_PRICE_LINK)); - if (s_subscriptions[req.subId].balance < payment) { - revert InsufficientBalance(); - } - s_subscriptions[req.subId].balance -= payment; - delete (s_requests[_requestId]); - emit RandomWordsFulfilled(_requestId, _requestId, payment, success); - } - - /** - * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. - * - * @param _subId the subscription to fund - * @param _amount the amount to fund - */ - function fundSubscription(uint64 _subId, uint96 _amount) public { - if (s_subscriptions[_subId].owner == address(0)) { - revert InvalidSubscription(); - } - uint96 oldBalance = s_subscriptions[_subId].balance; - s_subscriptions[_subId].balance += _amount; - emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); - } - - function requestRandomWords( - bytes32 _keyHash, - uint64 _subId, - uint16 _minimumRequestConfirmations, - uint32 _callbackGasLimit, - uint32 _numWords - ) external override nonReentrant onlyValidConsumer(_subId, msg.sender) returns (uint256) { - if (s_subscriptions[_subId].owner == address(0)) { - revert InvalidSubscription(); - } - - uint256 requestId = s_nextRequestId++; - uint256 preSeed = s_nextPreSeed++; - - s_requests[requestId] = Request({subId: _subId, callbackGasLimit: _callbackGasLimit, numWords: _numWords}); - - emit RandomWordsRequested( - _keyHash, - requestId, - preSeed, - _subId, - _minimumRequestConfirmations, - _callbackGasLimit, - _numWords, - msg.sender - ); - return requestId; - } - - function createSubscription() external override returns (uint64 _subId) { - s_currentSubId++; - s_subscriptions[s_currentSubId] = Subscription({owner: msg.sender, balance: 0}); - emit SubscriptionCreated(s_currentSubId, msg.sender); - return s_currentSubId; - } - - function getSubscription( - uint64 _subId - ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { - if (s_subscriptions[_subId].owner == address(0)) { - revert InvalidSubscription(); - } - return (s_subscriptions[_subId].balance, 0, s_subscriptions[_subId].owner, s_consumers[_subId]); - } - - function cancelSubscription(uint64 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { - emit SubscriptionCanceled(_subId, _to, s_subscriptions[_subId].balance); - delete (s_subscriptions[_subId]); - } - - modifier onlySubOwner(uint64 _subId) { - address owner = s_subscriptions[_subId].owner; - if (owner == address(0)) { - revert InvalidSubscription(); - } - if (msg.sender != owner) { - revert MustBeSubOwner(owner); - } - _; - } - - function getRequestConfig() external pure override returns (uint16, uint32, bytes32[] memory) { - return (3, 2000000, new bytes32[](0)); - } - - function addConsumer(uint64 _subId, address _consumer) external override onlySubOwner(_subId) { - if (s_consumers[_subId].length == MAX_CONSUMERS) { - revert TooManyConsumers(); - } - - if (consumerIsAdded(_subId, _consumer)) { - return; - } - - s_consumers[_subId].push(_consumer); - emit ConsumerAdded(_subId, _consumer); - } - - function removeConsumer( - uint64 _subId, - address _consumer - ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { - address[] storage consumers = s_consumers[_subId]; - for (uint256 i = 0; i < consumers.length; i++) { - if (consumers[i] == _consumer) { - address last = consumers[consumers.length - 1]; - consumers[i] = last; - consumers.pop(); - break; - } - } - - emit ConsumerRemoved(_subId, _consumer); - } - - function getConfig() - external - pure - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ) - { - return (4, 2_500_000, 2_700, 33285); - } - - function getFeeConfig() - external - pure - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ) - { - return ( - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 100000, // 0.1 LINK - 0, - 0, - 0, - 0 - ); - } - - modifier nonReentrant() { - if (s_config.reentrancyLock) { - revert Reentrant(); - } - _; - } - - function getFallbackWeiPerUnitLink() external pure returns (int256) { - return 4000000000000000; // 0.004 Ether - } - - function requestSubscriptionOwnerTransfer(uint64 /*_subId*/, address /*_newOwner*/) external pure override { - revert("not implemented"); - } - - function acceptSubscriptionOwnerTransfer(uint64 /*_subId*/) external pure override { - revert("not implemented"); - } - - function pendingRequestExists(uint64 /*subId*/) public pure override returns (bool) { - revert("not implemented"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol deleted file mode 100644 index 823cd43..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol +++ /dev/null @@ -1,269 +0,0 @@ -// SPDX-License-Identifier: MIT -// A mock for testing code that relies on VRFCoordinatorV2_5. -pragma solidity ^0.8.19; - -// solhint-disable-next-line no-unused-import -import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; - -contract VRFCoordinatorV2_5Mock is SubscriptionAPI, IVRFCoordinatorV2Plus { - uint96 public immutable i_base_fee; - uint96 public immutable i_gas_price; - int256 public immutable i_wei_per_unit_link; - - error InvalidRequest(); - error InvalidRandomWords(); - error InvalidExtraArgsTag(); - error NotImplemented(); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - event ConfigSet(); - - uint64 internal s_currentSubId; - uint256 internal s_nextRequestId = 1; - uint256 internal s_nextPreSeed = 100; - - struct Request { - uint256 subId; - uint32 callbackGasLimit; - uint32 numWords; - bytes extraArgs; - } - mapping(uint256 => Request) internal s_requests; /* requestId */ /* request */ - - constructor(uint96 _baseFee, uint96 _gasPrice, int256 _weiPerUnitLink) SubscriptionAPI() { - i_base_fee = _baseFee; - i_gas_price = _gasPrice; - i_wei_per_unit_link = _weiPerUnitLink; - setConfig(); - } - - /** - * @notice Sets the configuration of the vrfv2 mock coordinator - */ - function setConfig() public onlyOwner { - s_config = Config({ - minimumRequestConfirmations: 0, - maxGasLimit: 0, - stalenessSeconds: 0, - gasAfterPaymentCalculation: 0, - reentrancyLock: false, - fulfillmentFlatFeeNativePPM: 0, - fulfillmentFlatFeeLinkDiscountPPM: 0, - nativePremiumPercentage: 0, - linkPremiumPercentage: 0 - }); - emit ConfigSet(); - } - - function consumerIsAdded(uint256 _subId, address _consumer) public view returns (bool) { - return s_consumers[_consumer][_subId].active; - } - - modifier onlyValidConsumer(uint256 _subId, address _consumer) { - if (!consumerIsAdded(_subId, _consumer)) { - revert InvalidConsumer(_subId, _consumer); - } - _; - } - - /** - * @notice fulfillRandomWords fulfills the given request, sending the random words to the supplied - * @notice consumer. - * - * @dev This mock uses a simplified formula for calculating payment amount and gas usage, and does - * @dev not account for all edge cases handled in the real VRF coordinator. When making requests - * @dev against the real coordinator a small amount of additional LINK is required. - * - * @param _requestId the request to fulfill - * @param _consumer the VRF randomness consumer to send the result to - */ - function fulfillRandomWords(uint256 _requestId, address _consumer) external nonReentrant { - fulfillRandomWordsWithOverride(_requestId, _consumer, new uint256[](0)); - } - - /** - * @notice fulfillRandomWordsWithOverride allows the user to pass in their own random words. - * - * @param _requestId the request to fulfill - * @param _consumer the VRF randomness consumer to send the result to - * @param _words user-provided random words - */ - function fulfillRandomWordsWithOverride(uint256 _requestId, address _consumer, uint256[] memory _words) public { - uint256 startGas = gasleft(); - if (s_requests[_requestId].subId == 0) { - revert InvalidRequest(); - } - Request memory req = s_requests[_requestId]; - - if (_words.length == 0) { - _words = new uint256[](req.numWords); - for (uint256 i = 0; i < req.numWords; i++) { - _words[i] = uint256(keccak256(abi.encode(_requestId, i))); - } - } else if (_words.length != req.numWords) { - revert InvalidRandomWords(); - } - - VRFConsumerBaseV2Plus v; - bytes memory callReq = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, _requestId, _words); - s_config.reentrancyLock = true; - // solhint-disable-next-line avoid-low-level-calls, no-unused-vars - (bool success, ) = _consumer.call{gas: req.callbackGasLimit}(callReq); - s_config.reentrancyLock = false; - - bool nativePayment = uint8(req.extraArgs[req.extraArgs.length - 1]) == 1; - - uint256 rawPayment = i_base_fee + ((startGas - gasleft()) * i_gas_price); - if (!nativePayment) { - rawPayment = (1e18 * rawPayment) / uint256(i_wei_per_unit_link); - } - uint96 payment = uint96(rawPayment); - - _chargePayment(payment, nativePayment, req.subId); - - delete (s_requests[_requestId]); - emit RandomWordsFulfilled(_requestId, _requestId, req.subId, payment, nativePayment, success, false); - } - - function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { - Subscription storage subcription = s_subscriptions[subId]; - if (nativePayment) { - uint96 prevBal = subcription.nativeBalance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.nativeBalance = prevBal - payment; - s_withdrawableNative += payment; - } else { - uint96 prevBal = subcription.balance; - if (prevBal < payment) { - revert InsufficientBalance(); - } - subcription.balance = prevBal - payment; - s_withdrawableTokens += payment; - } - } - - /** - * @notice fundSubscription allows funding a subscription with an arbitrary amount for testing. - * - * @param _subId the subscription to fund - * @param _amount the amount to fund - */ - function fundSubscription(uint256 _subId, uint256 _amount) public { - if (s_subscriptionConfigs[_subId].owner == address(0)) { - revert InvalidSubscription(); - } - uint256 oldBalance = s_subscriptions[_subId].balance; - s_subscriptions[_subId].balance += uint96(_amount); - s_totalBalance += uint96(_amount); - emit SubscriptionFunded(_subId, oldBalance, oldBalance + _amount); - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @return The extra args struct - function _fromBytes(bytes calldata extraArgs) internal pure returns (VRFV2PlusClient.ExtraArgsV1 memory) { - if (extraArgs.length == 0) { - return VRFV2PlusClient.ExtraArgsV1({nativePayment: false}); - } - if (bytes4(extraArgs) != VRFV2PlusClient.EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); - return abi.decode(extraArgs[4:], (VRFV2PlusClient.ExtraArgsV1)); - } - - function requestRandomWords( - VRFV2PlusClient.RandomWordsRequest calldata _req - ) external override nonReentrant onlyValidConsumer(_req.subId, msg.sender) returns (uint256) { - uint256 subId = _req.subId; - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - - uint256 requestId = s_nextRequestId++; - uint256 preSeed = s_nextPreSeed++; - - bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(_req.extraArgs)); - s_requests[requestId] = Request({ - subId: _req.subId, - callbackGasLimit: _req.callbackGasLimit, - numWords: _req.numWords, - extraArgs: _req.extraArgs - }); - - emit RandomWordsRequested( - _req.keyHash, - requestId, - preSeed, - _req.subId, - _req.requestConfirmations, - _req.callbackGasLimit, - _req.numWords, - extraArgsBytes, - msg.sender - ); - return requestId; - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function removeConsumer( - uint256 _subId, - address _consumer - ) external override onlySubOwner(_subId) onlyValidConsumer(_subId, _consumer) nonReentrant { - if (!s_consumers[_consumer][_subId].active) { - revert InvalidConsumer(_subId, _consumer); - } - address[] memory consumers = s_subscriptionConfigs[_subId].consumers; - uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; ++i) { - if (consumers[i] == _consumer) { - address last = consumers[lastConsumerIndex]; - s_subscriptionConfigs[_subId].consumers[i] = last; - s_subscriptionConfigs[_subId].consumers.pop(); - break; - } - } - s_consumers[_consumer][_subId].active = false; - emit SubscriptionConsumerRemoved(_subId, _consumer); - } - - /** - * @inheritdoc IVRFSubscriptionV2Plus - */ - function cancelSubscription(uint256 _subId, address _to) external override onlySubOwner(_subId) nonReentrant { - (uint96 balance, uint96 nativeBalance) = _deleteSubscription(_subId); - - (bool success, ) = _to.call{value: uint256(nativeBalance)}(""); - if (!success) { - revert FailedToSendNative(); - } - emit SubscriptionCanceled(_subId, _to, balance, nativeBalance); - } - - function pendingRequestExists(uint256 /*subId*/) public pure override returns (bool) { - revert NotImplemented(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol deleted file mode 100644 index 1ae2869..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BaseTest.t.sol +++ /dev/null @@ -1,34 +0,0 @@ -pragma solidity ^0.8.0; - -import {Test} from "forge-std/Test.sol"; - -contract BaseTest is Test { - bool private s_baseTestInitialized; - address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; - - function setUp() public virtual { - // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. - if (s_baseTestInitialized) return; - s_baseTestInitialized = true; - - // Set msg.sender to OWNER until changePrank or stopPrank is called - vm.startPrank(OWNER); - } - - function getRandomAddresses(uint256 length) internal returns (address[] memory) { - address[] memory addresses = new address[](length); - for (uint256 i = 0; i < length; ++i) { - addresses[i] = address(uint160(uint(keccak256(abi.encodePacked(i))))); - } - return addresses; - } - - function addressIsIn(address addr, address[] memory addresses) internal returns (bool) { - for (uint256 i = 0; i < addresses.length; ++i) { - if (addresses[i] == addr) { - return true; - } - } - return false; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol deleted file mode 100644 index 4197073..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol +++ /dev/null @@ -1,196 +0,0 @@ -pragma solidity 0.8.19; - -import {console} from "forge-std/console.sol"; -import {VRF} from "../VRF.sol"; -import {VRFTypes} from "../VRFTypes.sol"; -import {BatchVRFCoordinatorV2Plus} from "../dev/BatchVRFCoordinatorV2Plus.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; -import "./BaseTest.t.sol"; -import {FixtureVRFCoordinatorV2_5} from "./FixtureVRFCoordinatorV2_5.t.sol"; - -contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { - BatchVRFCoordinatorV2Plus private s_batchCoordinator; - - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - - function setUp() public override { - FixtureVRFCoordinatorV2_5.setUp(); - - s_batchCoordinator = new BatchVRFCoordinatorV2Plus(address(s_coordinator)); - } - - function test_fulfillRandomWords() public { - _setUpConfig(); - _setUpProvingKey(); - _setUpSubscription(); - - uint32 requestBlock = 10; - vm.roll(requestBlock); - - vm.startPrank(SUBSCRIPTION_OWNER); - vm.deal(SUBSCRIPTION_OWNER, 10 ether); - s_coordinator.fundSubscriptionWithNative{value: 10 ether}(s_subId); - - // Request random words. - s_consumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, true); - vm.stopPrank(); - - // Move on to the next block. - // Store the previous block's blockhash. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - - VRFTypes.Proof[] memory proofs = new VRFTypes.Proof[](2); - VRFTypes.RequestCommitmentV2Plus[] memory rcs = new VRFTypes.RequestCommitmentV2Plus[](2); - - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment the print command below and run the test to print the output. - // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); - // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 3rd step: copy the output from the 1st step and update the command below, then run the command - // and copy the command output in the proof section below - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 4430852740828987645228960511496023658059009607317025880962658187812299131155 \ - -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ - -block-num 10 \ - -sender 0xdc90e8ce61c1af8a638b95264037c8e67ee5765c \ - -native-payment true - - */ - proofs[0] = VRFTypes.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 26762213923453052192184693334574145607290366984305044804336172347176490943606, - 70503534560525619072578237689732581746976650376431765635714023643649039207077 - ], - c: 10992233996918874905152274435276937088064589467016709044984819613170049539489, - s: 79662863379962724455809192044326025082567113176696761949197261107120333769102, - seed: 4430852740828987645228960511496023658059009607317025880962658187812299131155, - uWitness: 0x421A52Fb797d76Fb610aA1a0c020346fC1Ee2DeB, - cGammaWitness: [ - 50748523246052507241857300891945475679319243536065937584940024494820365165901, - 85746856994474260612851047426766648416105284284185975301552792881940939754570 - ], - sHashWitness: [ - 78637275871978664522379716948105702461748200460627087255706483027519919611423, - 82219236913923465822780520561305604064850823877720616893986252854976640396959 - ], - zInv: 60547558497534848069125896511700272238016171243048151035528198622956754542730 - }); - rcs[0] = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: s_subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: 1, - sender: address(s_consumer), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) - }); - - VRFCoordinatorV2_5.Output memory output = s_coordinator.getRandomnessFromProofExternal( - abi.decode(abi.encode(proofs[0]), (VRF.Proof)), - rcs[0] - ); - - requestBlock = 20; - vm.roll(requestBlock); - - vm.startPrank(SUBSCRIPTION_OWNER); - s_linkToken.setBalance(address(SUBSCRIPTION_OWNER), 10 ether); - s_linkToken.transferAndCall(address(s_coordinator), 10 ether, abi.encode(s_subId)); - - // Request random words. - s_consumer1.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, VRF_KEY_HASH, false); - vm.stopPrank(); - - // Move on to the next block. - // Store the previous block's blockhash. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); - - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment the print command below and run the test to print the output. - // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); - // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 3rd step: copy the output from the 1st step and update the command below, then run the command - // and copy the command output in the proof section below - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 14541556911652758131165474365357244907354309169650401973525070879190071151266 \ - -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ - -block-num 20 \ - -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ - -native-payment false - */ - proofs[1] = VRFTypes.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 97658842840420719674383370910135023062422561858595941631054490821636116883585, - 44255438468488339528368406358785988551798314198954634050943346751039644360856 - ], - c: 5233652943248967403606766735502925802264855214922758107203237169366748118852, - s: 87931642435666855739510477620068257005869145374865238974094299759068218698655, - seed: 14541556911652758131165474365357244907354309169650401973525070879190071151266, - uWitness: 0x0A87a9CB71983cE0F2C4bA41D0c1A6Fb1785c46A, - cGammaWitness: [ - 54062743217909816783918413821204010151082432359411822104552882037459289383418, - 67491004534731980264926765871774299056809003077448271411776926359153820235981 - ], - sHashWitness: [ - 7745933951617569731026754652291310837540252155195826133994719499558406927394, - 58405861596456412358325504621101233475720292237067230796670629212111423924259 - ], - zInv: 44253513765558903217330502897662324213800000485156126961643960636269885275795 - }); - rcs[1] = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: s_subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: 1, - sender: address(s_consumer1), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) - }); - - VRFCoordinatorV2_5.Output memory output1 = s_coordinator.getRandomnessFromProofExternal( - abi.decode(abi.encode(proofs[1]), (VRF.Proof)), - rcs[1] - ); - - // The payments are NOT pre-calculated and simply copied from the actual event. - // We can assert and ignore the payment field but the code will be considerably longer. - vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143261, true, true, false); - vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000312358, false, true, false); - - // Fulfill the requests. - s_batchCoordinator.fulfillRandomWords(proofs, rcs); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol deleted file mode 100644 index efeb902..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol +++ /dev/null @@ -1,196 +0,0 @@ -pragma solidity 0.8.6; - -import "./BaseTest.t.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; - -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; - -contract ChainSpecificUtilTest is BaseTest { - // ------------ Start Arbitrum Constants ------------ - - /// @dev ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - - /// @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); - - uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; - uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; - uint256 private constant ARB_SEPOLIA_TESTNET_CHAIN_ID = 421614; - - // ------------ 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 OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - uint256 private constant OP_MAINNET_CHAIN_ID = 10; - uint256 private constant OP_GOERLI_CHAIN_ID = 420; - uint256 private constant OP_SEPOLIA_CHAIN_ID = 11155420; - - /// @dev Base is a OP stack based rollup and follows the same L1 pricing logic as Optimism. - uint256 private constant BASE_MAINNET_CHAIN_ID = 8453; - uint256 private constant BASE_GOERLI_CHAIN_ID = 84531; - - // ------------ End Optimism Constants ------------ - - function setUp() public override { - BaseTest.setUp(); - vm.clearMockedCalls(); - } - - function testGetBlockhashArbitrum() public { - uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; - bytes32[3] memory expectedBlockHashes = [keccak256("mainnet"), keccak256("goerli"), keccak256("sepolia")]; - uint256[3] memory expectedBlockNumbers = [uint256(10), 11, 12]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - bytes32 expectedBlockHash = expectedBlockHashes[i]; - uint256 expectedBlockNumber = expectedBlockNumbers[i]; - vm.mockCall( - ARBSYS_ADDR, - abi.encodeWithSelector(ArbSys.arbBlockNumber.selector), - abi.encode(expectedBlockNumber + 1) - ); - vm.mockCall( - ARBSYS_ADDR, - abi.encodeWithSelector(ArbSys.arbBlockHash.selector, expectedBlockNumber), - abi.encodePacked(expectedBlockHash) - ); - bytes32 actualBlockHash = ChainSpecificUtil._getBlockhash(uint64(expectedBlockNumber)); - assertEq(expectedBlockHash, actualBlockHash, "incorrect blockhash"); - } - } - - function testGetBlockhashOptimism() public { - // Optimism L2 block hash is simply blockhash() - bytes32 actualBlockhash = ChainSpecificUtil._getBlockhash(uint64(block.number - 1)); - assertEq(blockhash(block.number - 1), actualBlockhash); - } - - function testGetBlockNumberArbitrum() public { - uint256[2] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID]; - uint256[3] memory expectedBlockNumbers = [uint256(10), 11, 12]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - uint256 expectedBlockNumber = expectedBlockNumbers[i]; - vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ArbSys.arbBlockNumber.selector), abi.encode(expectedBlockNumber)); - uint256 actualBlockNumber = ChainSpecificUtil._getBlockNumber(); - assertEq(expectedBlockNumber, actualBlockNumber, "incorrect block number"); - } - } - - function testGetBlockNumberOptimism() public { - // Optimism L2 block number is simply block.number - uint256 actualBlockNumber = ChainSpecificUtil._getBlockNumber(); - assertEq(block.number, actualBlockNumber); - } - - function testGetCurrentTxL1GasFeesArbitrum() public { - uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; - uint256[3] memory expectedGasFees = [uint256(10 gwei), 12 gwei, 14 gwei]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - uint256 expectedGasFee = expectedGasFees[i]; - vm.mockCall( - ARBGAS_ADDR, - abi.encodeWithSelector(ArbGasInfo.getCurrentTxL1GasFees.selector), - abi.encode(expectedGasFee) - ); - uint256 actualGasFee = ChainSpecificUtil._getCurrentTxL1GasFees(""); - assertEq(expectedGasFee, actualGasFee, "incorrect gas fees"); - } - } - - function testGetCurrentTxL1GasFeesOptimism() public { - // set optimism chain id - uint256[5] memory chainIds = [ - OP_MAINNET_CHAIN_ID, - OP_GOERLI_CHAIN_ID, - OP_SEPOLIA_CHAIN_ID, - BASE_MAINNET_CHAIN_ID, - BASE_GOERLI_CHAIN_ID - ]; - uint256[5] memory expectedGasFees = [uint256(10 gwei), 12 gwei, 14 gwei, 16 gwei, 18 gwei]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - uint256 expectedL1Fee = expectedGasFees[i]; - bytes memory someCalldata = abi.encode(address(0), "blah", uint256(1)); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector, bytes.concat(someCalldata, L1_FEE_DATA_PADDING)), - abi.encode(expectedL1Fee) - ); - uint256 actualL1Fee = ChainSpecificUtil._getCurrentTxL1GasFees(someCalldata); - assertEq(expectedL1Fee, actualL1Fee, "incorrect gas fees"); - } - } - - function testGetL1CalldataGasCostArbitrum() public { - uint256[3] memory chainIds = [ARB_MAINNET_CHAIN_ID, ARB_GOERLI_TESTNET_CHAIN_ID, ARB_SEPOLIA_TESTNET_CHAIN_ID]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - vm.mockCall( - ARBGAS_ADDR, - abi.encodeWithSelector(ArbGasInfo.getPricesInWei.selector), - abi.encode(0, 10, 0, 0, 0, 0) - ); - - // fee = l1PricePerByte * (calldataSizeBytes + 140) - // fee = 10 * (10 + 140) = 1500 - uint256 dataFee = ChainSpecificUtil._getL1CalldataGasCost(10); - assertEq(dataFee, 1500); - } - } - - function testGetL1CalldataGasCostOptimism() public { - uint256[5] memory chainIds = [ - OP_MAINNET_CHAIN_ID, - OP_GOERLI_CHAIN_ID, - OP_SEPOLIA_CHAIN_ID, - BASE_MAINNET_CHAIN_ID, - BASE_GOERLI_CHAIN_ID - ]; - for (uint256 i = 0; i < chainIds.length; i++) { - vm.chainId(chainIds[i]); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(hex"519b4bd3")), // l1BaseFee() - abi.encode(10) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(hex"0c18c162")), // overhead() - abi.encode(160) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(hex"f45e65d8")), // scalar() - abi.encode(500_000) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(hex"313ce567")), // decimals() - abi.encode(6) - ); - - // tx_data_gas = count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16 - // tx_data_gas = 0 * 4 + 10 * 16 = 160 - // l1_data_fee = l1_gas_price * (tx_data_gas + fixed_overhead) * dynamic_overhead - // l1_data_fee = 10 * (160 + 160) * 500_000 / 1_000_000 = 1600 - uint256 dataFee = ChainSpecificUtil._getL1CalldataGasCost(10); - assertEq(dataFee, 1600); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol deleted file mode 100644 index c1c2c7e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/FixtureVRFCoordinatorV2_5.t.sol +++ /dev/null @@ -1,134 +0,0 @@ -pragma solidity ^0.8.19; - -import {console} from "forge-std/console.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; -import {VRF} from "../VRF.sol"; -import {VRFTypes} from "../VRFTypes.sol"; -import {BlockhashStore} from "../dev/BlockhashStore.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import "./BaseTest.t.sol"; - -contract FixtureVRFCoordinatorV2_5 is BaseTest, VRF { - address internal SUBSCRIPTION_OWNER = makeAddr("SUBSCRIPTION_OWNER"); - - uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; - uint16 internal constant MIN_CONFIRMATIONS = 0; - uint32 internal constant CALLBACK_GAS_LIMIT = 1_000_000; - uint32 internal constant NUM_WORDS = 1; - - // VRF KeyV2 generated from a node; not sensitive information. - // The secret key used to generate this key is: 10. - bytes internal constant VRF_UNCOMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; - bytes internal constant VRF_COMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; - bytes32 internal constant VRF_KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - - BlockhashStore internal s_bhs; - ExposedVRFCoordinatorV2_5 internal s_coordinator; - - // Use multiple consumers because VRFV2PlusConsumerExample cannot have multiple pending requests. - uint256 internal s_subId; - VRFV2PlusConsumerExample internal s_consumer; - VRFV2PlusConsumerExample internal s_consumer1; - - MockLinkToken internal s_linkToken; - MockV3Aggregator internal s_linkNativeFeed; - - function setUp() public virtual override { - BaseTest.setUp(); - vm.stopPrank(); - - vm.startPrank(OWNER); - s_bhs = new BlockhashStore(); - - // Deploy coordinator. - s_coordinator = new ExposedVRFCoordinatorV2_5(address(s_bhs)); - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Configure the coordinator. - s_coordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - vm.stopPrank(); - - // Deploy consumers. - vm.startPrank(SUBSCRIPTION_OWNER); - s_consumer = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); - s_consumer1 = new VRFV2PlusConsumerExample(address(s_coordinator), address(s_linkToken)); - vm.stopPrank(); - } - - function _setUpConfig() internal { - vm.prank(OWNER); - s_coordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - } - - function _setUpProvingKey() internal { - uint256[2] memory uncompressedKeyParts = this._getProvingKeyParts(VRF_UNCOMPRESSED_PUBLIC_KEY); - vm.prank(OWNER); - s_coordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); - } - - function _setUpSubscription() internal { - vm.startPrank(SUBSCRIPTION_OWNER); - s_subId = s_coordinator.createSubscription(); - s_coordinator.addConsumer(s_subId, address(s_consumer)); - s_consumer.setSubId(s_subId); - s_coordinator.addConsumer(s_subId, address(s_consumer1)); - s_consumer1.setSubId(s_subId); - vm.stopPrank(); - } - - // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and - // index over the byte array. - function _getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { - uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); - uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); - return [keyPart1, keyPart2]; - } - - /** - * Prints the command to generate a proof for a VRF request. - * - * This function provides a convenient way to generate the proof off-chain to be copied into the tests. - * - * An example of the command looks like this: - * go run . generate-proof-v2-plus \ - * -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - * -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ - * -block-hash 0x14 \ - * -block-num 20 \ - * -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ - * -native-payment false - */ - function _printGenerateProofV2PlusCommand( - address sender, - uint64 nonce, - uint256 requestBlock, - bool nativePayment - ) internal { - (, uint256 preSeed) = s_coordinator.computeRequestIdExternal(VRF_KEY_HASH, sender, s_subId, nonce); - - console.log("go run . generate-proof-v2-plus \\"); - console.log(string.concat(" -key-hash ", Strings.toHexString(uint256(VRF_KEY_HASH)), " \\")); - console.log(string.concat(" -pre-seed ", Strings.toString(preSeed), " \\")); - console.log(string.concat(" -block-hash ", Strings.toHexString(uint256(blockhash(requestBlock))), " \\")); - console.log(string.concat(" -block-num ", Strings.toString(requestBlock), " \\")); - console.log(string.concat(" -sender ", Strings.toHexString(sender), " \\")); - console.log(string.concat(" -native-payment ", nativePayment ? "true" : "false")); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol deleted file mode 100644 index ec47f48..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol +++ /dev/null @@ -1,89 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {TrustedBlockhashStore} from "../dev/TrustedBlockhashStore.sol"; -import {console} from "forge-std/console.sol"; - -contract TrustedBlockhashStoreTest is BaseTest { - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - address internal constant LINK_WHALE_2 = 0xe9b2C5A6D9bA93dD354783a9De0a265da7551a20; - TrustedBlockhashStore bhs; - uint256 unreachableBlockNumber = 5; - bytes32 unreachableBlockhash; - - function setUp() public override { - BaseTest.setUp(); - - // Get the blockhash for a block that later becomes unreachable in the EVM. - vm.roll(10); - unreachableBlockhash = blockhash(unreachableBlockNumber); - - // Fund our users. - vm.roll(1000); - vm.deal(LINK_WHALE, 10_000 ether); - changePrank(LINK_WHALE); - - address[] memory whitelist = new address[](1); - whitelist[0] = LINK_WHALE; - bhs = new TrustedBlockhashStore(whitelist); - } - - function testGenericBHSFunctions() public { - // Should store. - uint256 blockNumber = 999; - bhs.store(blockNumber); - assertEq(bhs.getBlockhash(blockNumber), blockhash(blockNumber)); - - // Should store earliest. - uint256 earliestBlockNumber = block.number - 256; - bhs.storeEarliest(); - assertEq(bhs.getBlockhash(earliestBlockNumber), blockhash(earliestBlockNumber)); - } - - function testTrustedBHSFunctions() public { - uint256 recentBlockNumber = 999; - - // Assume that the EVM cannot access the blockhash for block 5. - uint256 unreachableBlock = 5; - assertEq(blockhash(unreachableBlock), 0); - - // Store blockhash from whitelisted address; - uint256[] memory invalidBlockNums = new uint256[](0); - uint256[] memory blockNums = new uint256[](1); - blockNums[0] = unreachableBlock; - bytes32[] memory blockhashes = new bytes32[](1); - blockhashes[0] = unreachableBlockhash; - - // Should not be able to store with invalid recent blockhash - vm.expectRevert(TrustedBlockhashStore.InvalidRecentBlockhash.selector); - bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(998)); - - // Should not be able to store or change whitelist for non-whitelisted address. - changePrank(LINK_WHALE_2); - vm.expectRevert(TrustedBlockhashStore.NotInWhitelist.selector); - bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); - vm.expectRevert("Only callable by owner"); - bhs.setWhitelist(new address[](0)); - - // Should not store for a mismatched list of block numbers and hashes. - changePrank(LINK_WHALE); - vm.expectRevert(TrustedBlockhashStore.InvalidTrustedBlockhashes.selector); - bhs.storeTrusted(invalidBlockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); - - // Should store unreachable blocks via whitelisted address. - bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); - assertEq(bhs.getBlockhash(unreachableBlock), unreachableBlockhash); - - // Change whitelist. Assert that the old whitelisted address can no longer store, - // but the new one can. - address[] memory newWhitelist = new address[](1); - newWhitelist[0] = LINK_WHALE_2; - bhs.setWhitelist(newWhitelist); - - vm.expectRevert(TrustedBlockhashStore.NotInWhitelist.selector); - bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); - - changePrank(LINK_WHALE_2); - bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol deleted file mode 100644 index 1716118..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol +++ /dev/null @@ -1,381 +0,0 @@ -pragma solidity 0.8.6; - -import "./BaseTest.t.sol"; -import {VRF} from "../VRF.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {VRFCoordinatorV2Mock} from "../mocks/VRFCoordinatorV2Mock.sol"; -import {VRFConsumerV2} from "../testhelpers/VRFConsumerV2.sol"; - -contract VRFCoordinatorV2MockTest is BaseTest { - MockLinkToken internal s_linkToken; - MockV3Aggregator internal s_linkEthFeed; - VRFCoordinatorV2Mock internal s_vrfCoordinatorV2Mock; - VRFConsumerV2 internal s_vrfConsumerV2; - address internal s_subOwner = address(1234); - address internal s_randomOwner = address(4567); - - // VRF KeyV2 generated from a node; not sensitive information. - // The secret key used to generate this key is: 10. - bytes internal constant UNCOMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; - bytes internal constant COMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; - bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - - uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; - uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; - uint32 internal constant DEFAULT_NUM_WORDS = 1; - - uint96 pointOneLink = 0.1 ether; - uint96 oneLink = 1 ether; - - event SubscriptionCreated(uint64 indexed subId, address owner); - event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); - event ConsumerAdded(uint64 indexed subId, address consumer); - event ConsumerRemoved(uint64 indexed subId, address consumer); - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint64 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address indexed sender - ); - event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(OWNER, 10_000 ether); - vm.deal(s_subOwner, 20 ether); - - // Deploy link token and link/eth feed. - s_linkToken = new MockLinkToken(); - s_linkEthFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Deploy coordinator and consumer. - s_vrfCoordinatorV2Mock = new VRFCoordinatorV2Mock( - pointOneLink, - 1_000_000_000 // 0.000000001 LINK per gas - ); - address coordinatorAddr = address(s_vrfCoordinatorV2Mock); - s_vrfConsumerV2 = new VRFConsumerV2(coordinatorAddr, address(s_linkToken)); - - s_vrfCoordinatorV2Mock.setConfig(); - } - - function testCreateSubscription() public { - vm.startPrank(s_subOwner); - vm.expectEmit( - true, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - emit SubscriptionCreated(1, s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - assertEq(subId, 1); - - (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2Mock - .getSubscription(subId); - assertEq(balance, 0); - assertEq(reqCount, 0); - assertEq(owner, s_subOwner); - assertEq(consumers.length, 0); - // s_testCoordinator.fundSubscriptionWithEth{value: 10 ether}(subId); - - // Test if subId increments - vm.expectEmit(true, false, false, true); - emit SubscriptionCreated(2, s_subOwner); - subId = s_vrfCoordinatorV2Mock.createSubscription(); - assertEq(subId, 2); - vm.stopPrank(); - } - - function testAddConsumer() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - vm.expectEmit(true, false, false, true); - emit ConsumerAdded(subId, address(s_vrfConsumerV2)); - s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); - - (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2Mock - .getSubscription(subId); - assertEq(balance, 0); - assertEq(reqCount, 0); - assertEq(owner, s_subOwner); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2)); - vm.stopPrank(); - } - - // cannot add a consumer to a nonexistent subscription - function testAddConsumerToInvalidSub() public { - vm.startPrank(s_subOwner); - bytes4 reason = bytes4(keccak256("InvalidSubscription()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.addConsumer(1, address(s_vrfConsumerV2)); - vm.stopPrank(); - } - - // cannot add more than the consumer maximum - function testAddMaxConsumers() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - // Add 100 consumers - for (uint64 i = 101; i <= 200; ++i) { - s_vrfCoordinatorV2Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); - } - // Adding 101th consumer should revert - bytes4 reason = bytes4(keccak256("TooManyConsumers()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); - vm.stopPrank(); - } - - // can remove a consumer from a subscription - function testRemoveConsumerFromSub() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); - - (, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2)); - - vm.expectEmit(true, false, false, true); - emit ConsumerRemoved(subId, address(s_vrfConsumerV2)); - s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); - - vm.stopPrank(); - } - - // cannot remove a consumer from a nonexistent subscription - function testRemoveConsumerFromInvalidSub() public { - vm.startPrank(s_subOwner); - bytes4 reason = bytes4(keccak256("InvalidSubscription()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.removeConsumer(1, address(s_vrfConsumerV2)); - vm.stopPrank(); - } - - // cannot remove a consumer after it is already removed - function testRemoveConsumerAgain() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); - - (, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2)); - - vm.expectEmit(true, false, false, true); - emit ConsumerRemoved(subId, address(s_vrfConsumerV2)); - s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); - - // Removing consumer again should revert with InvalidConsumer - bytes4 reason = bytes4(keccak256("InvalidConsumer()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.removeConsumer(subId, address(s_vrfConsumerV2)); - vm.stopPrank(); - } - - // can fund a subscription - function testFundSubscription() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, oneLink); - s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); - - (uint96 balance, , , address[] memory consumers) = s_vrfCoordinatorV2Mock.getSubscription(subId); - assertEq(balance, oneLink); - assertEq(consumers.length, 0); - vm.stopPrank(); - } - - // cannot fund a nonexistent subscription - function testFundInvalidSubscription() public { - vm.startPrank(s_subOwner); - - // Removing consumer again should revert with InvalidConsumer - bytes4 reason = bytes4(keccak256("InvalidSubscription()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.removeConsumer(1, address(s_vrfConsumerV2)); - - vm.stopPrank(); - } - - // can cancel a subscription - function testCancelSubscription() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); - - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, s_subOwner, oneLink); - s_vrfCoordinatorV2Mock.cancelSubscription(subId, s_subOwner); - - bytes4 reason = bytes4(keccak256("InvalidSubscription()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.getSubscription(subId); - - vm.stopPrank(); - } - - // fails to fulfill without being a valid consumer - function testRequestRandomWordsInvalidConsumer() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); - - bytes4 reason = bytes4(keccak256("InvalidConsumer()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.requestRandomWords( - KEY_HASH, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS - ); - vm.stopPrank(); - } - - // fails to fulfill with insufficient funds - function testRequestRandomWordsInsufficientFunds() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - address consumerAddr = address(s_vrfConsumerV2); - s_vrfCoordinatorV2Mock.addConsumer(subId, address(s_vrfConsumerV2)); - - vm.stopPrank(); - - vm.startPrank(consumerAddr); - - vm.expectEmit(true, false, false, true); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS, - address(s_subOwner) - ); - uint256 reqId = s_vrfCoordinatorV2Mock.requestRandomWords( - KEY_HASH, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS - ); - - bytes4 reason = bytes4(keccak256("InsufficientBalance()")); - vm.expectRevert(toBytes(reason)); - s_vrfCoordinatorV2Mock.fulfillRandomWords(reqId, consumerAddr); - - vm.stopPrank(); - } - - // can request and fulfill [ @skip-coverage ] - function testRequestRandomWordsHappyPath() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); - - address consumerAddr = address(s_vrfConsumerV2); - s_vrfCoordinatorV2Mock.addConsumer(subId, consumerAddr); - - vm.expectEmit(true, false, false, true); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS, - address(s_subOwner) - ); - uint256 reqId = s_vrfConsumerV2.requestRandomness( - KEY_HASH, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS - ); - - vm.expectEmit(true, false, false, true); - emit RandomWordsFulfilled(reqId, 1, 100090236000000000, true); - s_vrfCoordinatorV2Mock.fulfillRandomWords(reqId, consumerAddr); - - vm.stopPrank(); - } - - // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] - function testRequestRandomWordsUserOverride() public { - vm.startPrank(s_subOwner); - uint64 subId = s_vrfCoordinatorV2Mock.createSubscription(); - - s_vrfCoordinatorV2Mock.fundSubscription(subId, oneLink); - - address consumerAddr = address(s_vrfConsumerV2); - s_vrfCoordinatorV2Mock.addConsumer(subId, consumerAddr); - - vm.expectEmit(true, false, false, true); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - 2, - address(s_subOwner) - ); - uint256 reqId = s_vrfConsumerV2.requestRandomness( - KEY_HASH, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - 2 - ); - - bytes4 reason = bytes4(keccak256("InvalidRandomWords()")); - vm.expectRevert(toBytes(reason)); - uint256[] memory words1 = new uint256[](5); - words1[0] = 1; - words1[1] = 2; - words1[2] = 3; - words1[3] = 4; - words1[4] = 5; - s_vrfCoordinatorV2Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); - - vm.expectEmit(true, false, false, true); - uint256[] memory words2 = new uint256[](2); - words1[0] = 2533; - words1[1] = 1768; - emit RandomWordsFulfilled(reqId, 1, 100072314000000000, true); - s_vrfCoordinatorV2Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); - - vm.stopPrank(); - } - - function toBytes(bytes4 _data) public pure returns (bytes memory) { - return abi.encodePacked(_data); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol deleted file mode 100644 index ad23959..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol +++ /dev/null @@ -1,352 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {VRFV2PlusMaliciousMigrator} from "../dev/testhelpers/VRFV2PlusMaliciousMigrator.sol"; - -contract VRFCoordinatorV2Plus_Migration is BaseTest { - uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 LINK - uint256 internal constant DEFAULT_NATIVE_FUNDING = 50 ether; // 50 ETH - uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 50_000; - uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; - uint32 internal constant DEFAULT_NUM_WORDS = 1; - // VRF KeyV2 generated from a node; not sensitive information. - // The secret key used to generate this key is: 10. - bytes internal constant UNCOMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; - bytes internal constant COMPRESSED_PUBLIC_KEY = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; - bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; - - ExposedVRFCoordinatorV2_5 v1Coordinator; - VRFCoordinatorV2Plus_V2Example v2Coordinator; - ExposedVRFCoordinatorV2_5 v1Coordinator_noLink; - VRFCoordinatorV2Plus_V2Example v2Coordinator_noLink; - uint256 subId; - uint256 subId_noLink; - VRFV2PlusConsumerExample testConsumer; - VRFV2PlusConsumerExample testConsumer_noLink; - MockLinkToken linkToken; - address linkTokenAddr; - MockV3Aggregator linkNativeFeed; - address v1CoordinatorAddr; - address v2CoordinatorAddr; - address v1CoordinatorAddr_noLink; - address v2CoordinatorAddr_noLink; - - event CoordinatorRegistered(address coordinatorAddress); - event CoordinatorDeregistered(address coordinatorAddress); - event MigrationCompleted(address newCoordinator, uint256 subId); - - function setUp() public override { - BaseTest.setUp(); - vm.deal(OWNER, 100 ether); - address bhs = makeAddr("bhs"); - v1Coordinator = new ExposedVRFCoordinatorV2_5(bhs); - v1Coordinator_noLink = new ExposedVRFCoordinatorV2_5(bhs); - subId = v1Coordinator.createSubscription(); - subId_noLink = v1Coordinator_noLink.createSubscription(); - linkToken = new MockLinkToken(); - linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - v1Coordinator.setLINKAndLINKNativeFeed(address(linkToken), address(linkNativeFeed)); - linkTokenAddr = address(linkToken); - v2Coordinator = new VRFCoordinatorV2Plus_V2Example(address(linkToken), address(v1Coordinator)); - v2Coordinator_noLink = new VRFCoordinatorV2Plus_V2Example(address(0), address(v1Coordinator_noLink)); - v1CoordinatorAddr = address(v1Coordinator); - v2CoordinatorAddr = address(v2Coordinator); - v1CoordinatorAddr_noLink = address(v1Coordinator_noLink); - v2CoordinatorAddr_noLink = address(v2Coordinator_noLink); - - vm.expectEmit( - false, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - emit CoordinatorRegistered(v2CoordinatorAddr); - v1Coordinator.registerMigratableCoordinator(v2CoordinatorAddr); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - - vm.expectEmit( - false, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - emit CoordinatorRegistered(v2CoordinatorAddr_noLink); - v1Coordinator_noLink.registerMigratableCoordinator(v2CoordinatorAddr_noLink); - assertTrue(v1Coordinator_noLink.isTargetRegisteredExternal(v2CoordinatorAddr_noLink)); - - testConsumer = new VRFV2PlusConsumerExample(address(v1Coordinator), address(linkToken)); - testConsumer_noLink = new VRFV2PlusConsumerExample(address(v1Coordinator_noLink), address(0)); - v1Coordinator.setConfig( - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - 600, - 10_000, - 20_000, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - v1Coordinator_noLink.setConfig( - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - 600, - 10_000, - 20_000, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - registerProvingKey(); - testConsumer.setCoordinator(v1CoordinatorAddr); - testConsumer_noLink.setCoordinator(v1CoordinatorAddr_noLink); - } - - function testDeregister() public { - vm.expectEmit( - false, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - emit CoordinatorDeregistered(v2CoordinatorAddr); - v1Coordinator.deregisterMigratableCoordinator(v2CoordinatorAddr); - assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.CoordinatorNotRegistered.selector, v2CoordinatorAddr)); - v1Coordinator.migrate(subId, v2CoordinatorAddr); - - // test register/deregister multiple coordinators - address v3CoordinatorAddr = makeAddr("v3Coordinator"); - v1Coordinator.registerMigratableCoordinator(v2CoordinatorAddr); - v1Coordinator.registerMigratableCoordinator(v3CoordinatorAddr); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); - - v1Coordinator.deregisterMigratableCoordinator(v3CoordinatorAddr); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - assertFalse(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); - - v1Coordinator.registerMigratableCoordinator(v3CoordinatorAddr); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); - - v1Coordinator.deregisterMigratableCoordinator(v2CoordinatorAddr); - assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - assertTrue(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); - - v1Coordinator.deregisterMigratableCoordinator(v3CoordinatorAddr); - assertFalse(v1Coordinator.isTargetRegisteredExternal(v2CoordinatorAddr)); - assertFalse(v1Coordinator.isTargetRegisteredExternal(v3CoordinatorAddr)); - } - - function testMigration() public { - linkToken.transferAndCall(v1CoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(subId)); - v1Coordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(subId); - v1Coordinator.addConsumer(subId, address(testConsumer)); - - // subscription exists in V1 coordinator before migration - (uint96 balance, uint96 nativeBalance, uint64 reqCount, address owner, address[] memory consumers) = v1Coordinator - .getSubscription(subId); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(owner, address(OWNER)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(testConsumer)); - - assertEq(v1Coordinator.s_totalBalance(), DEFAULT_LINK_FUNDING); - assertEq(v1Coordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - - // Update consumer to point to the new coordinator - vm.expectEmit( - false, // no first indexed field - false, // no second indexed field - false, // no third indexed field - true // check data fields - ); - emit MigrationCompleted(v2CoordinatorAddr, subId); - v1Coordinator.migrate(subId, v2CoordinatorAddr); - - // subscription no longer exists in v1 coordinator after migration - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - v1Coordinator.getSubscription(subId); - assertEq(v1Coordinator.s_totalBalance(), 0); - assertEq(v1Coordinator.s_totalNativeBalance(), 0); - assertEq(linkToken.balanceOf(v1CoordinatorAddr), 0); - assertEq(v1CoordinatorAddr.balance, 0); - - // subscription exists in v2 coordinator - (balance, nativeBalance, reqCount, owner, consumers) = v2Coordinator.getSubscription(subId); - assertEq(owner, address(OWNER)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(testConsumer)); - assertEq(reqCount, 0); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(v2Coordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); - assertEq(v2Coordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - assertEq(linkToken.balanceOf(v2CoordinatorAddr), DEFAULT_LINK_FUNDING); - assertEq(v2CoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); - - // calling migrate again on V1 coordinator should fail - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - v1Coordinator.migrate(subId, v2CoordinatorAddr); - - // test request still works after migration - testConsumer.requestRandomWords( - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_NUM_WORDS, - KEY_HASH, - false - ); - assertEq(testConsumer.s_recentRequestId(), 1); - - v2Coordinator.fulfillRandomWords(testConsumer.s_recentRequestId()); - assertEq( - testConsumer.getRandomness(testConsumer.s_recentRequestId(), 0), - v2Coordinator.generateFakeRandomness(testConsumer.s_recentRequestId())[0] - ); - } - - function testMigrationNoLink() public { - v1Coordinator_noLink.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(subId_noLink); - v1Coordinator_noLink.addConsumer(subId_noLink, address(testConsumer_noLink)); - - // subscription exists in V1 coordinator before migration - ( - uint96 balance, - uint96 nativeBalance, - uint64 reqCount, - address owner, - address[] memory consumers - ) = v1Coordinator_noLink.getSubscription(subId_noLink); - assertEq(balance, 0); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(owner, address(OWNER)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(testConsumer_noLink)); - - assertEq(v1Coordinator_noLink.s_totalBalance(), 0); - assertEq(v1Coordinator_noLink.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - - // Update consumer to point to the new coordinator - vm.expectEmit( - false, // no first indexed field - false, // no second indexed field - false, // no third indexed field - true // check data fields - ); - emit MigrationCompleted(v2CoordinatorAddr_noLink, subId_noLink); - v1Coordinator_noLink.migrate(subId_noLink, v2CoordinatorAddr_noLink); - - // subscription no longer exists in v1 coordinator after migration - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - v1Coordinator_noLink.getSubscription(subId); - assertEq(v1Coordinator_noLink.s_totalBalance(), 0); - assertEq(v1Coordinator_noLink.s_totalNativeBalance(), 0); - assertEq(linkToken.balanceOf(v1CoordinatorAddr_noLink), 0); - assertEq(v1CoordinatorAddr_noLink.balance, 0); - - // subscription exists in v2 coordinator - (balance, nativeBalance, reqCount, owner, consumers) = v2Coordinator_noLink.getSubscription(subId_noLink); - assertEq(owner, address(OWNER)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(testConsumer_noLink)); - assertEq(reqCount, 0); - assertEq(balance, 0); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(v2Coordinator_noLink.s_totalLinkBalance(), 0); - assertEq(v2Coordinator_noLink.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - assertEq(linkToken.balanceOf(v2CoordinatorAddr_noLink), 0); - assertEq(v2CoordinatorAddr_noLink.balance, DEFAULT_NATIVE_FUNDING); - - // calling migrate again on V1 coordinator should fail - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - v1Coordinator_noLink.migrate(subId_noLink, v2CoordinatorAddr_noLink); - - // test request still works after migration - testConsumer_noLink.requestRandomWords( - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_NUM_WORDS, - KEY_HASH, - false - ); - assertEq(testConsumer_noLink.s_recentRequestId(), 1); - - v2Coordinator_noLink.fulfillRandomWords(testConsumer_noLink.s_recentRequestId()); - assertEq( - testConsumer_noLink.getRandomness(testConsumer_noLink.s_recentRequestId(), 0), - v2Coordinator_noLink.generateFakeRandomness(testConsumer_noLink.s_recentRequestId())[0] - ); - } - - function testMigrateRevertsWhenInvalidCoordinator() external { - address invalidCoordinator = makeAddr("invalidCoordinator"); - - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.CoordinatorNotRegistered.selector, address(invalidCoordinator)) - ); - v1Coordinator.migrate(subId, invalidCoordinator); - } - - function testMigrateRevertsWhenInvalidCaller() external { - changePrank(makeAddr("invalidCaller")); - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.MustBeSubOwner.selector, OWNER)); - v1Coordinator.migrate(subId, v2CoordinatorAddr); - } - - function testMigrateRevertsWhenPendingFulfillment() external { - v1Coordinator.addConsumer(subId, address(testConsumer)); - testConsumer.setSubId(subId); - testConsumer.requestRandomWords( - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_NUM_WORDS, - KEY_HASH, - false - ); - - vm.expectRevert(SubscriptionAPI.PendingRequestExists.selector); - v1Coordinator.migrate(subId, v2CoordinatorAddr); - } - - function testMigrateRevertsWhenReentrant() public { - // deploy malicious contracts, subscriptions - address maliciousUser = makeAddr("maliciousUser"); - changePrank(maliciousUser); - uint256 maliciousSubId = v1Coordinator.createSubscription(); - VRFV2PlusMaliciousMigrator prankster = new VRFV2PlusMaliciousMigrator(address(v1Coordinator)); - v1Coordinator.addConsumer(maliciousSubId, address(prankster)); - - // try to migrate malicious subscription, should fail - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.Reentrant.selector)); - v1Coordinator.migrate(maliciousSubId, v2CoordinatorAddr); - } - - function registerProvingKey() public { - uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(UNCOMPRESSED_PUBLIC_KEY); - v1Coordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); - v1Coordinator_noLink.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); - } - - // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and - // index over the byte array. - function getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { - uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); - uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); - return [keyPart1, keyPart2]; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol deleted file mode 100644 index 75c763c..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5Mock.t.sol +++ /dev/null @@ -1,511 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {VRFCoordinatorV2_5Mock} from "../mocks/VRFCoordinatorV2_5Mock.sol"; -import {VRFConsumerV2Plus} from "../testhelpers/VRFConsumerV2Plus.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; - -contract VRFCoordinatorV2_5MockTest is BaseTest { - MockLinkToken internal s_linkToken; - VRFCoordinatorV2_5Mock internal s_vrfCoordinatorV2_5Mock; - VRFConsumerV2Plus internal s_vrfConsumerV2Plus; - address internal s_subOwner = address(1234); - - bytes32 internal constant KEY_HASH = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - - uint32 internal constant DEFAULT_CALLBACK_GAS_LIMIT = 500_000; - uint16 internal constant DEFAULT_REQUEST_CONFIRMATIONS = 3; - uint32 internal constant DEFAULT_NUM_WORDS = 1; - - uint96 internal constant oneNative = 1 ether; - uint96 internal constant twoLink = 2 ether; - - event SubscriptionCreated(uint256 indexed subId, address owner); - event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); - event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); - event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); - event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subId, - uint96 payment, - bool nativePayment, - bool success, - bool onlyPremium - ); - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(OWNER, 10_000 ether); - vm.deal(s_subOwner, 20 ether); - - // Deploy link token and link/eth feed. - s_linkToken = new MockLinkToken(); - - // Deploy coordinator and consumer. - s_vrfCoordinatorV2_5Mock = new VRFCoordinatorV2_5Mock(0.002 ether, 40 gwei, 0.004 ether); - address coordinatorAddr = address(s_vrfCoordinatorV2_5Mock); - s_vrfConsumerV2Plus = new VRFConsumerV2Plus(coordinatorAddr, address(s_linkToken)); - - s_vrfCoordinatorV2_5Mock.setConfig(); - } - - function test_CreateSubscription() public { - vm.startPrank(s_subOwner); - uint256 expectedSubId = uint256( - keccak256( - abi.encodePacked( - s_subOwner, - blockhash(block.number - 1), - address(s_vrfCoordinatorV2_5Mock), - s_vrfCoordinatorV2_5Mock.s_currentSubNonce() - ) - ) - ); - vm.expectEmit( - true, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - emit SubscriptionCreated(expectedSubId, s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - assertEq(subId, expectedSubId); - - ( - uint96 balance, - uint96 nativeBalance, - uint64 reqCount, - address owner, - address[] memory consumers - ) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); - assertEq(balance, 0); - assertEq(nativeBalance, 0); - assertEq(reqCount, 0); - assertEq(owner, s_subOwner); - assertEq(consumers.length, 0); - vm.stopPrank(); - } - - function test_AddConsumer() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerAdded(subId, address(s_vrfConsumerV2Plus)); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); - - (uint96 balance, , uint64 reqCount, address owner, address[] memory consumers) = s_vrfCoordinatorV2_5Mock - .getSubscription(subId); - assertEq(balance, 0); - assertEq(reqCount, 0); - assertEq(owner, s_subOwner); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2Plus)); - vm.stopPrank(); - } - - // cannot add a consumer to a nonexistent subscription - function test_AddConsumerToInvalidSub() public { - vm.startPrank(s_subOwner); - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.addConsumer(1, address(s_vrfConsumerV2Plus)); - vm.stopPrank(); - } - - // cannot add more than the consumer maximum - function test_AddMaxConsumers() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - // Add 100 consumers - for (uint64 i = 101; i <= 200; ++i) { - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(bytes20(keccak256(abi.encodePacked(i))))); - } - // Adding 101th consumer should revert - vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); - vm.stopPrank(); - } - - // can remove a consumer from a subscription - function test_RemoveConsumerFromSub() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); - - (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2Plus)); - - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); - s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); - - // Removing consumer again should revert with InvalidConsumer - vm.expectRevert( - abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) - ); - s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); - - vm.stopPrank(); - } - - // cannot remove a consumer from a nonexistent subscription - function test_RemoveConsumerFromInvalidSub() public { - vm.startPrank(s_subOwner); - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.removeConsumer(1, address(s_vrfConsumerV2Plus)); - vm.stopPrank(); - } - - // cannot remove a consumer after it is already removed - function test_RemoveConsumerAgain() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); - - (, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_vrfConsumerV2Plus)); - - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerRemoved(subId, address(s_vrfConsumerV2Plus)); - s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); - - // Removing consumer again should revert with InvalidConsumer - vm.expectRevert( - abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_vrfConsumerV2Plus)) - ); - s_vrfCoordinatorV2_5Mock.removeConsumer(subId, address(s_vrfConsumerV2Plus)); - vm.stopPrank(); - } - - // can fund a subscription - function test_FundSubscription() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, twoLink); - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - - (uint96 balance, , , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); - assertEq(balance, twoLink); - assertEq(consumers.length, 0); - - assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), twoLink); - - vm.stopPrank(); - } - - // cannot fund a nonexistent subscription - function testFuzz_FundSubscription_RevertIfInvalidSubscription(uint256 subId) public { - vm.startPrank(s_subOwner); - - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - - vm.stopPrank(); - } - - // can fund a subscription with native - function test_FundSubscriptionWithNative() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - vm.expectEmit(true, false, false, true); - emit SubscriptionFundedWithNative(subId, 0, oneNative); - s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); - - (, uint256 nativeBalance, , , address[] memory consumers) = s_vrfCoordinatorV2_5Mock.getSubscription(subId); - assertEq(nativeBalance, oneNative); - assertEq(consumers.length, 0); - - assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), oneNative); - - vm.stopPrank(); - } - - // cannot fund a nonexistent subscription - function testFuzz_FundSubscriptionWithNative_RevertIfInvalidSubscription(uint256 subId) public { - vm.startPrank(s_subOwner); - - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); - - vm.stopPrank(); - } - - // can cancel a subscription - function test_CancelSubscription_Link() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - - uint256 totalBalance = s_vrfCoordinatorV2_5Mock.s_totalBalance(); - - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, s_subOwner, twoLink, 0); - s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); - - // check coordinator balance decreased - assertEq(s_vrfCoordinatorV2_5Mock.s_totalBalance(), totalBalance - twoLink); - - // sub owner balance did not increase as no actual token is involved - - // check subscription removed - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.getSubscription(subId); - - vm.stopPrank(); - } - - // can cancel a subscription - function test_CancelSubscription_Native() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); - - uint256 balance = address(s_subOwner).balance; - uint256 totalNativeBalance = s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(); - - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, s_subOwner, 0, oneNative); - s_vrfCoordinatorV2_5Mock.cancelSubscription(subId, s_subOwner); - - // check coordinator balance decreased - assertEq(s_vrfCoordinatorV2_5Mock.s_totalNativeBalance(), totalNativeBalance - oneNative); - - // check sub owner balance increased - assertEq(address(s_subOwner).balance, balance + oneNative); - - // check subscription removed - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_vrfCoordinatorV2_5Mock.getSubscription(subId); - - vm.stopPrank(); - } - - // fails to fulfill without being a valid consumer - function testFuzz_RequestRandomWords_RevertIfInvalidConsumer(bool nativePayment) public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(s_subOwner))); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: KEY_HASH, - subId: subId, - requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, - callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, - numWords: DEFAULT_NUM_WORDS, - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})) - }); - s_vrfCoordinatorV2_5Mock.requestRandomWords(req); - vm.stopPrank(); - } - - // fails to fulfill with insufficient funds - function testFuzz_RequestRandomWords_RevertIfInsufficientFunds(bool nativePayment) public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - address consumerAddr = address(s_vrfConsumerV2Plus); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, address(s_vrfConsumerV2Plus)); - - vm.stopPrank(); - - vm.startPrank(consumerAddr); - - vm.expectEmit(true, false, false, true); - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS, - extraArgs, - address(s_subOwner) - ); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: KEY_HASH, - subId: subId, - requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, - callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, - numWords: DEFAULT_NUM_WORDS, - extraArgs: extraArgs - }); - uint256 reqId = s_vrfCoordinatorV2_5Mock.requestRandomWords(req); - - vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); - s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); - - vm.stopPrank(); - } - - // can request and fulfill [ @skip-coverage ] - function test_RequestRandomWords_Link_HappyPath() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - - address consumerAddr = address(s_vrfConsumerV2Plus); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); - - vm.expectEmit(true, false, false, true); - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS, - extraArgs, - address(s_subOwner) - ); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: KEY_HASH, - subId: subId, - requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, - callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, - numWords: DEFAULT_NUM_WORDS, - extraArgs: extraArgs - }); - uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); - - vm.expectEmit(true, false, false, true); - emit RandomWordsFulfilled(reqId, 1, subId, 1432960000000000000, false, true, false); - s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); - - vm.stopPrank(); - } - - // can request and fulfill [ @skip-coverage ] - function test_RequestRandomWords_Native_HappyPath() public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); - - address consumerAddr = address(s_vrfConsumerV2Plus); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); - - vm.expectEmit(true, false, false, true); - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - DEFAULT_NUM_WORDS, - extraArgs, - address(s_subOwner) - ); - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: KEY_HASH, - subId: subId, - requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, - callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, - numWords: DEFAULT_NUM_WORDS, - extraArgs: extraArgs - }); - uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); - - vm.expectEmit(true, false, false, true); - emit RandomWordsFulfilled(reqId, 1, subId, 5731840000000000, true, true, false); - s_vrfCoordinatorV2_5Mock.fulfillRandomWords(reqId, consumerAddr); - - vm.stopPrank(); - } - - // Correctly allows for user override of fulfillRandomWords [ @skip-coverage ] - function testFuzz_RequestRandomWordsUserOverride(bool nativePayment) public { - vm.startPrank(s_subOwner); - uint256 subId = s_vrfCoordinatorV2_5Mock.createSubscription(); - - uint96 expectedPayment; - if (nativePayment) { - expectedPayment = 5011440000000000; - s_vrfCoordinatorV2_5Mock.fundSubscriptionWithNative{value: oneNative}(subId); - } else { - expectedPayment = 1252860000000000000; - s_vrfCoordinatorV2_5Mock.fundSubscription(subId, twoLink); - } - - address consumerAddr = address(s_vrfConsumerV2Plus); - s_vrfCoordinatorV2_5Mock.addConsumer(subId, consumerAddr); - - bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: nativePayment})); - vm.expectEmit(true, false, false, true); - emit RandomWordsRequested( - KEY_HASH, - 1, - 100, - subId, - DEFAULT_REQUEST_CONFIRMATIONS, - DEFAULT_CALLBACK_GAS_LIMIT, - 2, - extraArgs, - address(s_subOwner) - ); - - VRFV2PlusClient.RandomWordsRequest memory req = VRFV2PlusClient.RandomWordsRequest({ - keyHash: KEY_HASH, - subId: subId, - requestConfirmations: DEFAULT_REQUEST_CONFIRMATIONS, - callbackGasLimit: DEFAULT_CALLBACK_GAS_LIMIT, - numWords: 2, - extraArgs: extraArgs - }); - uint256 reqId = s_vrfConsumerV2Plus.requestRandomness(req); - - vm.expectRevert(VRFCoordinatorV2_5Mock.InvalidRandomWords.selector); - uint256[] memory words1 = new uint256[](5); - words1[0] = 1; - words1[1] = 2; - words1[2] = 3; - words1[3] = 4; - words1[4] = 5; - s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, uint256[](words1)); - - vm.expectEmit(true, false, false, true); - uint256[] memory words2 = new uint256[](2); - words1[0] = 2533; - words1[1] = 1768; - emit RandomWordsFulfilled(reqId, 1, subId, expectedPayment, nativePayment, true, false); - s_vrfCoordinatorV2_5Mock.fulfillRandomWordsWithOverride(reqId, consumerAddr, words2); - - vm.stopPrank(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol deleted file mode 100644 index 8e47b80..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Arbitrum.t.sol +++ /dev/null @@ -1,179 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; -import {BlockhashStore} from "../dev/BlockhashStore.sol"; -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {VmSafe} from "forge-std/Vm.sol"; - -contract VRFV2CoordinatorV2_5_Arbitrum is BaseTest { - /// @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 ARBSYS_ADDR is the address of the ArbSys precompile on Arbitrum. - /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 - address private constant ARBSYS_ADDR = address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - - address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - - BlockhashStore s_bhs; - ExposedVRFCoordinatorV2_5_Arbitrum s_testCoordinator; - MockLinkToken s_linkToken; - MockV3Aggregator s_linkNativeFeed; - - uint256 s_startGas = 0.0038 gwei; - uint256 s_weiPerUnitGas = 0.003 gwei; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(DEPLOYER, 10_000 ether); - changePrank(DEPLOYER); - - vm.txGasPrice(100 gwei); - - // Instantiate BHS. - s_bhs = new BlockhashStore(); - - // Deploy coordinator, LINK token and LINK/Native feed. - s_testCoordinator = new ExposedVRFCoordinatorV2_5_Arbitrum(address(s_bhs)); - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Configure the coordinator. - s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - s_testCoordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - } - - function _encodeCalculatePaymentAmountNativeExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - ExposedVRFCoordinatorV2_5_Arbitrum.calculatePaymentAmountNativeExternal.selector, - startGas, - weiPerUnitGas, - onlyPremium - ); - } - - function _encodeCalculatePaymentAmountLinkExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - ExposedVRFCoordinatorV2_5_Arbitrum.calculatePaymentAmountLinkExternal.selector, - startGas, - weiPerUnitGas, - onlyPremium - ); - } - - function _checkL1GasFeeEmittedLogs(uint256 expectedL1GasFee) internal { - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 1); - assertEq(entries[0].topics.length, 1); - assertEq(entries[0].topics[0], keccak256("L1GasFee(uint256)")); - // 1e15 is less than 1 percent discrepancy - uint256 actualL1GasFee = abi.decode(entries[0].data, (uint256)); - assertApproxEqAbs(expectedL1GasFee, actualL1GasFee, 1e15); - } - - function test_getBlockNumber() public { - // sanity check that Arbitrum will use ArbSys to get the block number - vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockNumber.selector), abi.encode(33691)); - assertEq(33691, s_testCoordinator.getBlockNumberExternal()); - } - - function test_getBlockhash() public { - // for blocks within 256 blocks from the current block return the blockhash using ArbSys - bytes32 testBlockHash = bytes32(keccak256("testBlock")); - vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockNumber.selector), abi.encode(45830)); - vm.mockCall(ARBSYS_ADDR, abi.encodeWithSelector(ARBSYS.arbBlockHash.selector, 45825), abi.encode(testBlockHash)); - assertEq(testBlockHash, s_testCoordinator.getBlockhashExternal(45825)); - // for blocks outside 256 blocks from the current block return nothing - assertEq("", s_testCoordinator.getBlockhashExternal(33830)); - // for blocks greater than the current block return nothing - assertEq("", s_testCoordinator.getBlockhashExternal(50550)); - } - - function test_calculatePaymentAmountNative() public { - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - vm.mockCall(ARBGAS_ADDR, abi.encodeWithSelector(ARBGAS.getCurrentTxL1GasFees.selector), abi.encode(10 gwei)); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(10 gwei)); - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.000129 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(10 gwei)); - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.000017 * 1e17, 1e15); - } - - function test_calculatePaymentAmountLink() public { - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - vm.mockCall(ARBGAS_ADDR, abi.encodeWithSelector(ARBGAS.getCurrentTxL1GasFees.selector), abi.encode(10 gwei)); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(10 gwei)); - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.00024772 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(10 gwei)); - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.00002252 * 1e17, 1e15); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol deleted file mode 100644 index b54dbba..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFCoordinatorV2_5_Optimism.t.sol +++ /dev/null @@ -1,413 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; -import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; -import {BlockhashStore} from "../dev/BlockhashStore.sol"; -import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; -import {VmSafe} from "forge-std/Vm.sol"; - -contract VRFV2CoordinatorV2_5_Optimism is BaseTest { - /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - /// @dev L1_FEE_DATA_PADDING includes 71 bytes for L1 data padding for Optimism - bytes internal constant L1_FEE_DATA_PADDING = - hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; - - address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - - BlockhashStore s_bhs; - ExposedVRFCoordinatorV2_5_Optimism s_testCoordinator; - MockLinkToken s_linkToken; - MockV3Aggregator s_linkNativeFeed; - - uint256 s_startGas = 0.0038 gwei; - uint256 s_weiPerUnitGas = 0.003 gwei; - - /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload - /// @dev This option is only available for the Coordinator contract - uint8 internal constant L1_GAS_FEES_MODE = 0; - /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected - /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; - /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(DEPLOYER, 10_000 ether); - changePrank(DEPLOYER); - - vm.txGasPrice(100 gwei); - - // Instantiate BHS. - s_bhs = new BlockhashStore(); - - // Deploy coordinator, LINK token and LINK/Native feed. - s_testCoordinator = new ExposedVRFCoordinatorV2_5_Optimism(address(s_bhs)); - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Configure the coordinator. - s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - s_testCoordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - } - - function _encodeCalculatePaymentAmountNativeExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - ExposedVRFCoordinatorV2_5_Optimism.calculatePaymentAmountNativeExternal.selector, - startGas, - weiPerUnitGas, - onlyPremium - ); - } - - function _encodeCalculatePaymentAmountLinkExternal( - uint256 startGas, - uint256 weiPerUnitGas, - bool onlyPremium - ) internal pure returns (bytes memory) { - return - abi.encodeWithSelector( - ExposedVRFCoordinatorV2_5_Optimism.calculatePaymentAmountLinkExternal.selector, - startGas, - weiPerUnitGas, - onlyPremium - ); - } - - function _mockGasOraclePriceGetL1FeeUpperBoundCall() internal { - // 171 bytes is the size of tx.data we are sending in this test - // this is not expected fulfillment tx size! - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(OVM_GasPriceOracle.getL1FeeUpperBound.selector, 171), - abi.encode(uint256(0.02 ether)) - ); - } - - function _mockGasOraclePriceFeeMethods() internal { - // these values are taken from an example transaction on Base Sepolia - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("l1BaseFee()"))), - abi.encode(64273426165) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("baseFeeScalar()"))), - abi.encode(1101) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("blobBaseFeeScalar()"))), - abi.encode(659851) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("blobBaseFee()"))), - abi.encode(2126959908362) - ); - vm.mockCall(OVM_GASPRICEORACLE_ADDR, abi.encodeWithSelector(bytes4(keccak256("decimals()"))), abi.encode(6)); - } - - function _mockGasOraclePriceGetL1FeeCall(bytes memory txMsgData) internal { - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(OVM_GasPriceOracle.getL1Fee.selector, bytes.concat(txMsgData, L1_FEE_DATA_PADDING)), - abi.encode(uint256(0.001 ether)) - ); - } - - function _checkL1GasFeeEmittedLogs(uint256 expectedL1GasFee) internal { - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 1); - assertEq(entries[0].topics.length, 1); - assertEq(entries[0].topics[0], keccak256("L1GasFee(uint256)")); - // 1e15 is less than 1 percent discrepancy - uint256 actualL1GasFee = abi.decode(entries[0].data, (uint256)); - assertApproxEqAbs(expectedL1GasFee, actualL1GasFee, 1e15); - } - - function _checkL1FeeCalculationSetEmittedLogs(uint8 expectedMode, uint8 expectedCoefficient) internal { - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 1); - assertEq(entries[0].topics.length, 1); - assertEq(entries[0].topics[0], keccak256("L1FeeCalculationSet(uint8,uint8)")); - (uint8 actualMode, uint8 actualCoefficient) = abi.decode(entries[0].data, (uint8, uint8)); - assertEq(expectedMode, actualMode); - assertEq(expectedCoefficient, actualCoefficient); - } - - function test_setL1FeePaymentMethod() public { - // check default settings after contract deployment - assertEq(uint256(L1_GAS_FEES_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); - assertEq(100, uint256(s_testCoordinator.s_l1FeeCoefficient())); - vm.recordLogs(); - - s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); - - _checkL1FeeCalculationSetEmittedLogs(L1_CALLDATA_GAS_COST_MODE, 70); - assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); - assertEq(70, uint256(s_testCoordinator.s_l1FeeCoefficient())); - - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 30); - - _checkL1FeeCalculationSetEmittedLogs(L1_GAS_FEES_UPPER_BOUND_MODE, 30); - assertEq(uint256(L1_GAS_FEES_UPPER_BOUND_MODE), uint256(s_testCoordinator.s_l1FeeCalculationMode())); - assertEq(30, uint256(s_testCoordinator.s_l1FeeCoefficient())); - - // should revert if invalid L1 fee calculation mode is used - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCalculationMode.selector, 4)); - s_testCoordinator.setL1FeeCalculation(4, 100); - - // should revert if invalid coefficient is used (equal to zero, this would disable L1 fees completely) - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 0)); - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 0); - - // should revert if invalid coefficient is used (larger than 100%) - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 150)); - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 150); - } - - function test_getBlockNumber() public { - // sanity check that OP stack will use block.number directly - vm.roll(1589); - assertEq(1589, s_testCoordinator.getBlockNumberExternal()); - } - - function test_getBlockhash() public { - // sanity check that OP stack will use blockhash() directly - vm.roll(1589); - bytes32 blockHash = blockhash(1589); - assertEq(blockHash, s_testCoordinator.getBlockhashExternal(1589)); - } - - // payment calculation depends on the L1 gas cost for fulfillment transaction payload - // both calculatePayment functions use msg.data passed down from the fulfillRandomWords function and - // in that case, msg.data contains the fulfillment transaction payload (calldata) - // it's not easy to simulate this in tests below plus we only want to concentrate on the payment part - // since we don't have to test with the correct payload, we can use any kind of payload for msg.data - // in the case of tests below, msg.data will carry calculatePayment function selectors and parameters - - function test_calculatePaymentAmountNativeUsingL1GasFeesMode() public { - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeCall(txMsgData); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.0162937 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeCall(txMsgData); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.0015168 * 1e17, 1e15); - } - - function test_calculatePaymentAmountLinkUsingL1GasFeesMode() public { - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeCall(txMsgData); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.0222475 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeCall(txMsgData); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.001 ether)); - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.0020225 * 1e17, 1e15); - } - - function test_calculatePaymentAmountNativeUsingCalldataGasCostMode() public { - // for this type of cost calculation we are applying coefficient to reduce the inflated gas price - s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceFeeMethods(); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.002834 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceFeeMethods(); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.00037 * 1e17, 1e15); - } - - function test_calculatePaymentAmountLinkUsingCalldataGasCostMode() public { - // for this type of cost calculation we are applying coefficient to reduce the inflated gas price - s_testCoordinator.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceFeeMethods(); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.0054219 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceFeeMethods(); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.0002352 ether)); // 3.36e14 actual price times the coefficient (0.7) - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.0004929 * 1e17, 1e15); - } - - function test_calculatePaymentAmountNativeUsingL1GasFeesUpperBoundMode() public { - // for this type of cost calculation we are applying coefficient to reduce the inflated gas price - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 50); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.115129 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountNativeExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.015017 * 1e17, 1e15); - } - - function test_calculatePaymentAmountLinkUsingL1GasFeesUpperBoundMode() public { - // for this type of cost calculation we are applying coefficient to reduce the inflated gas price - s_testCoordinator.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 50); - - // first we test premium and flat fee payment combined - bool onlyPremium = false; - bytes memory txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - vm.recordLogs(); - - uint256 gasLimit = 0.0001 gwei; // needed because gasleft() is used in the payment calculation - (bool success, bytes memory returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) - - uint96 payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.2202475 * 1e17, 1e15); - - // now we test only premium payment - onlyPremium = true; - txMsgData = _encodeCalculatePaymentAmountLinkExternal(s_startGas, s_weiPerUnitGas, onlyPremium); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - - (success, returnData) = address(s_testCoordinator).call{gas: gasLimit}(txMsgData); - assertTrue(success); - _checkL1GasFeeEmittedLogs(uint256(0.01 ether)); // 2e16 actual price times the coefficient (0.5) - - payment = abi.decode(returnData, (uint96)); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.0200225 * 1e17, 1e15); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol deleted file mode 100644 index dd3f54b..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol +++ /dev/null @@ -1,1160 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {VRF} from "../VRF.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {BlockhashStore} from "../dev/BlockhashStore.sol"; -import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {VRFTypes} from "../VRFTypes.sol"; -import {console} from "forge-std/console.sol"; -import {VmSafe} from "forge-std/Vm.sol"; -import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; -import "@openzeppelin/contracts/utils/math/Math.sol"; // for Math.ceilDiv - -/* - * USAGE INSTRUCTIONS: - * To add new tests/proofs, uncomment the "console.sol" import from foundry, and gather key fields - * from your VRF request. - * Then, pass your request info into the generate-proof-v2-plus script command - * located in /core/scripts/vrfv2/testnet/proofs.go to generate a proof that can be tested on-chain. - **/ - -contract VRFV2Plus is BaseTest { - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - uint64 internal constant GAS_LANE_MAX_GAS = 5000 gwei; - uint16 internal constant MIN_CONFIRMATIONS = 0; - uint32 internal constant CALLBACK_GAS_LIMIT = 1_000_000; - uint32 internal constant NUM_WORDS = 1; - - // Bytecode for a VRFV2PlusConsumerExample contract. - // to calculate: console.logBytes(type(VRFV2PlusConsumerExample).creationCode); - bytes constant initializeCode = - hex"60806040523480156200001157600080fd5b5060405162001377380380620013778339810160408190526200003491620001cc565b8133806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000103565b5050600280546001600160a01b03199081166001600160a01b0394851617909155600580548216958416959095179094555060038054909316911617905562000204565b6001600160a01b0381163314156200015e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001c757600080fd5b919050565b60008060408385031215620001e057600080fd5b620001eb83620001af565b9150620001fb60208401620001af565b90509250929050565b61116380620002146000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80638098004311610097578063cf62c8ab11610066578063cf62c8ab14610242578063de367c8e14610255578063eff2701714610268578063f2fde38b1461027b57600080fd5b806380980043146101ab5780638da5cb5b146101be5780638ea98117146101cf578063a168fa89146101e257600080fd5b80635d7d53e3116100d35780635d7d53e314610166578063706da1ca1461016f5780637725135b1461017857806379ba5097146101a357600080fd5b80631fe543e31461010557806329e5d8311461011a5780632fa4e4421461014057806336bfffed14610153575b600080fd5b610118610113366004610e4e565b61028e565b005b61012d610128366004610ef2565b6102fa565b6040519081526020015b60405180910390f35b61011861014e366004610f7f565b610410565b610118610161366004610d5b565b6104bc565b61012d60045481565b61012d60065481565b60035461018b906001600160a01b031681565b6040516001600160a01b039091168152602001610137565b6101186105c0565b6101186101b9366004610e1c565b600655565b6000546001600160a01b031661018b565b6101186101dd366004610d39565b61067e565b61021d6101f0366004610e1c565b6007602052600090815260409020805460019091015460ff82169161010090046001600160a01b03169083565b6040805193151584526001600160a01b03909216602084015290820152606001610137565b610118610250366004610f7f565b61073d565b60055461018b906001600160a01b031681565b610118610276366004610f14565b610880565b610118610289366004610d39565b610a51565b6002546001600160a01b031633146102ec576002546040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911660248201526044015b60405180910390fd5b6102f68282610a65565b5050565b60008281526007602090815260408083208151608081018352815460ff81161515825261010090046001600160a01b0316818501526001820154818401526002820180548451818702810187019095528085528695929460608601939092919083018282801561038957602002820191906000526020600020905b815481526020019060010190808311610375575b50505050508152505090508060400151600014156103e95760405162461bcd60e51b815260206004820152601760248201527f7265717565737420494420697320696e636f727265637400000000000000000060448201526064016102e3565b806060015183815181106103ff576103ff61111c565b602002602001015191505092915050565b6003546002546006546040805160208101929092526001600160a01b0393841693634000aea09316918591015b6040516020818303038152906040526040518463ffffffff1660e01b815260040161046a93929190610ffa565b602060405180830381600087803b15801561048457600080fd5b505af1158015610498573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f69190610dff565b60065461050b5760405162461bcd60e51b815260206004820152600d60248201527f7375624944206e6f74207365740000000000000000000000000000000000000060448201526064016102e3565b60005b81518110156102f65760055460065483516001600160a01b039092169163bec4c08c91908590859081106105445761054461111c565b60200260200101516040518363ffffffff1660e01b815260040161057b9291909182526001600160a01b0316602082015260400190565b600060405180830381600087803b15801561059557600080fd5b505af11580156105a9573d6000803e3d6000fd5b5050505080806105b8906110f3565b91505061050e565b6001546001600160a01b0316331461061a5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016102e3565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000546001600160a01b031633148015906106a457506002546001600160a01b03163314155b1561070e57336106bc6000546001600160a01b031690565b6002546040517f061db9c10000000000000000000000000000000000000000000000000000000081526001600160a01b03938416600482015291831660248301529190911660448201526064016102e3565b6002805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60065461041057600560009054906101000a90046001600160a01b03166001600160a01b031663a21a23e46040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561079457600080fd5b505af11580156107a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107cc9190610e35565b60068190556005546040517fbec4c08c00000000000000000000000000000000000000000000000000000000815260048101929092523060248301526001600160a01b03169063bec4c08c90604401600060405180830381600087803b15801561083557600080fd5b505af1158015610849573d6000803e3d6000fd5b505050506003546002546006546040516001600160a01b0393841693634000aea0931691859161043d919060200190815260200190565b60006040518060c0016040528084815260200160065481526020018661ffff1681526020018763ffffffff1681526020018563ffffffff1681526020016108d66040518060200160405280861515815250610af8565b90526002546040517f9b1c385e0000000000000000000000000000000000000000000000000000000081529192506000916001600160a01b0390911690639b1c385e90610927908590600401611039565b602060405180830381600087803b15801561094157600080fd5b505af1158015610955573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109799190610e35565b604080516080810182526000808252336020808401918252838501868152855184815280830187526060860190815287855260078352959093208451815493517fffffffffffffffffffffff0000000000000000000000000000000000000000009094169015157fffffffffffffffffffffff0000000000000000000000000000000000000000ff16176101006001600160a01b039094169390930292909217825591516001820155925180519495509193849392610a3f926002850192910190610ca9565b50505060049190915550505050505050565b610a59610b96565b610a6281610bf2565b50565b6004548214610ab65760405162461bcd60e51b815260206004820152601760248201527f7265717565737420494420697320696e636f727265637400000000000000000060448201526064016102e3565b60008281526007602090815260409091208251610adb92600290920191840190610ca9565b50506000908152600760205260409020805460ff19166001179055565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401610b3191511515815260200190565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b6000546001600160a01b03163314610bf05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e3565b565b6001600160a01b038116331415610c4b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e3565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610ce4579160200282015b82811115610ce4578251825591602001919060010190610cc9565b50610cf0929150610cf4565b5090565b5b80821115610cf05760008155600101610cf5565b80356001600160a01b0381168114610d2057600080fd5b919050565b803563ffffffff81168114610d2057600080fd5b600060208284031215610d4b57600080fd5b610d5482610d09565b9392505050565b60006020808385031215610d6e57600080fd5b823567ffffffffffffffff811115610d8557600080fd5b8301601f81018513610d9657600080fd5b8035610da9610da4826110cf565b61109e565b80828252848201915084840188868560051b8701011115610dc957600080fd5b600094505b83851015610df357610ddf81610d09565b835260019490940193918501918501610dce565b50979650505050505050565b600060208284031215610e1157600080fd5b8151610d5481611148565b600060208284031215610e2e57600080fd5b5035919050565b600060208284031215610e4757600080fd5b5051919050565b60008060408385031215610e6157600080fd5b8235915060208084013567ffffffffffffffff811115610e8057600080fd5b8401601f81018613610e9157600080fd5b8035610e9f610da4826110cf565b80828252848201915084840189868560051b8701011115610ebf57600080fd5b600094505b83851015610ee2578035835260019490940193918501918501610ec4565b5080955050505050509250929050565b60008060408385031215610f0557600080fd5b50508035926020909101359150565b600080600080600060a08688031215610f2c57600080fd5b610f3586610d25565b9450602086013561ffff81168114610f4c57600080fd5b9350610f5a60408701610d25565b9250606086013591506080860135610f7181611148565b809150509295509295909350565b600060208284031215610f9157600080fd5b81356bffffffffffffffffffffffff81168114610d5457600080fd5b6000815180845260005b81811015610fd357602081850181015186830182015201610fb7565b81811115610fe5576000602083870101525b50601f01601f19169290920160200192915050565b6001600160a01b03841681526bffffffffffffffffffffffff831660208201526060604082015260006110306060830184610fad565b95945050505050565b60208152815160208201526020820151604082015261ffff60408301511660608201526000606083015163ffffffff80821660808501528060808601511660a0850152505060a083015160c08084015261109660e0840182610fad565b949350505050565b604051601f8201601f1916810167ffffffffffffffff811182821017156110c7576110c7611132565b604052919050565b600067ffffffffffffffff8211156110e9576110e9611132565b5060051b60200190565b600060001982141561111557634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610a6257600080fdfea164736f6c6343000806000a"; - - BlockhashStore s_bhs; - ExposedVRFCoordinatorV2_5 s_testCoordinator; - ExposedVRFCoordinatorV2_5 s_testCoordinator_noLink; - VRFV2PlusConsumerExample s_testConsumer; - MockLinkToken s_linkToken; - MockV3Aggregator s_linkNativeFeed; - - // VRF KeyV2 generated from a node; not sensitive information. - // The secret key used to generate this key is: 10. - bytes vrfUncompressedPublicKey = - hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7893aba425419bc27a3b6c7e693a24c696f794c2ed877a1593cbee53b037368d7"; - bytes vrfCompressedPublicKey = hex"a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c701"; - bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(LINK_WHALE, 10_000 ether); - changePrank(LINK_WHALE); - - vm.txGasPrice(100 gwei); - - // Instantiate BHS. - s_bhs = new BlockhashStore(); - - // Deploy coordinator and consumer. - // Note: adding contract deployments to this section will require the VRF proofs be regenerated. - s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(s_bhs)); - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Use create2 to deploy our consumer, so that its address is always the same - // and surrounding changes do not alter our generated proofs. - bytes memory consumerInitCode = bytes.concat( - initializeCode, - abi.encode(address(s_testCoordinator), address(s_linkToken)) - ); - bytes32 abiEncodedOwnerAddress = bytes32(uint256(uint160(LINK_WHALE)) << 96); - address consumerCreate2Address; - assembly { - consumerCreate2Address := create2( - 0, // value - left at zero here - add(0x20, consumerInitCode), // initialization bytecode (excluding first memory slot which contains its length) - mload(consumerInitCode), // length of initialization bytecode - abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses - ) - } - s_testConsumer = VRFV2PlusConsumerExample(consumerCreate2Address); - - s_testCoordinator_noLink = new ExposedVRFCoordinatorV2_5(address(s_bhs)); - - // Configure the coordinator. - s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - } - - function setConfig() internal { - s_testCoordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - } - - function testSetConfig() public { - // Should setConfig successfully. - setConfig(); - - // Test that setting requestConfirmations above MAX_REQUEST_CONFIRMATIONS reverts. - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidRequestConfirmations.selector, 500, 500, 200)); - s_testCoordinator.setConfig( - 500, - 2_500_000, - 1, - 50_000, - 50000000000000000, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - - // Test that setting fallbackWeiPerUnitLink to zero reverts. - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidLinkWeiPrice.selector, 0)); - - s_testCoordinator.setConfig( - 0, - 2_500_000, - 1, - 50_000, - 0, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - - // Test that setting link discount flat fee higher than native flat fee reverts - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.LinkDiscountTooHigh.selector, uint32(501), uint32(500))); - - s_testCoordinator.setConfig( - 0, - 2_500_000, - 1, - 50_000, - 500, - 500, // fulfillmentFlatFeeNativePPM - 501, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - - // // Test that setting link discount flat fee equal to native flat fee does not revert - s_testCoordinator.setConfig( - 0, - 2_500_000, - 1, - 50_000, - 500, - 450, // fulfillmentFlatFeeNativePPM - 450, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - - // Test that setting native premium percentage higher than 155 will revert - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155)) - ); - - s_testCoordinator.setConfig( - 0, - 2_500_000, - 1, - 50_000, - 500, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 156, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - - // Test that setting LINK premium percentage higher than 155 will revert - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155)) - ); - - s_testCoordinator.setConfig( - 0, - 2_500_000, - 1, - 50_000, - 500, - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 202 // linkPremiumPercentage - ); - } - - function testRegisterProvingKey() public { - // Should set the proving key successfully. - registerProvingKey(); - - // Should revert when already registered. - uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.ProvingKeyAlreadyRegistered.selector, vrfKeyHash)); - s_testCoordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); - } - - event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); - event ProvingKeyDeregistered(bytes32 keyHash, uint64 maxGas); - - function registerProvingKey() public { - uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); - bytes32 keyHash = keccak256(abi.encode(uncompressedKeyParts)); - vm.expectEmit( - false, // no indexed args to check for - false, // no indexed args to check for - false, // no indexed args to check for - true - ); // check data fields: keyHash and maxGas - emit ProvingKeyRegistered(keyHash, GAS_LANE_MAX_GAS); - s_testCoordinator.registerProvingKey(uncompressedKeyParts, GAS_LANE_MAX_GAS); - (bool exists, uint64 maxGas) = s_testCoordinator.s_provingKeys(keyHash); - assertTrue(exists); - assertEq(GAS_LANE_MAX_GAS, maxGas); - assertEq(s_testCoordinator.s_provingKeyHashes(0), keyHash); - assertEq(keyHash, vrfKeyHash); - } - - function testDeregisterProvingKey() public { - // Should set the proving key successfully. - registerProvingKey(); - - bytes - memory unregisteredPubKey = hex"6d919e4ed6add6c34b2af77eb6b2d2f5d27db11ba004e70734b23bd4321ea234ff8577a063314bead6d88c1b01849289a5542767a5138924f38fed551a7773db"; - - // Should revert when given pubkey is not registered - uint256[2] memory unregisteredKeyParts = this.getProvingKeyParts(unregisteredPubKey); - bytes32 unregisterdKeyHash = keccak256(abi.encode(unregisteredKeyParts)); - vm.expectRevert(abi.encodeWithSelector(VRFCoordinatorV2_5.NoSuchProvingKey.selector, unregisterdKeyHash)); - s_testCoordinator.deregisterProvingKey(unregisteredKeyParts); - - // correctly deregister pubkey - uint256[2] memory uncompressedKeyParts = this.getProvingKeyParts(vrfUncompressedPublicKey); - bytes32 keyHash = keccak256(abi.encode(uncompressedKeyParts)); - vm.expectEmit( - false, // no indexed args to check for - false, // no indexed args to check for - false, // no indexed args to check for - true - ); // check data fields: keyHash and maxGas - emit ProvingKeyDeregistered(keyHash, GAS_LANE_MAX_GAS); - s_testCoordinator.deregisterProvingKey(uncompressedKeyParts); - (bool exists, uint64 maxGas) = s_testCoordinator.s_provingKeys(keyHash); - assertFalse(exists); - assertEq(0, maxGas); - } - - // note: Call this function via this.getProvingKeyParts to be able to pass memory as calldata and - // index over the byte array. - function getProvingKeyParts(bytes calldata uncompressedKey) public pure returns (uint256[2] memory) { - uint256 keyPart1 = uint256(bytes32(uncompressedKey[0:32])); - uint256 keyPart2 = uint256(bytes32(uncompressedKey[32:64])); - return [keyPart1, keyPart2]; - } - - function testCreateSubscription() public { - uint256 subId = s_testCoordinator.createSubscription(); - s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); - } - - function testCancelSubWithNoLink() public { - uint256 subId = s_testCoordinator_noLink.createSubscription(); - s_testCoordinator_noLink.fundSubscriptionWithNative{value: 1000 ether}(subId); - - assertEq(LINK_WHALE.balance, 9000 ether); - s_testCoordinator_noLink.cancelSubscription(subId, LINK_WHALE); - assertEq(LINK_WHALE.balance, 10_000 ether); - - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_testCoordinator_noLink.getSubscription(subId); - } - - function testGetActiveSubscriptionIds() public { - uint numSubs = 40; - for (uint i = 0; i < numSubs; i++) { - s_testCoordinator.createSubscription(); - } - // get all subscriptions, assert length is correct - uint256[] memory allSubs = s_testCoordinator.getActiveSubscriptionIds(0, 0); - assertEq(allSubs.length, s_testCoordinator.getActiveSubscriptionIdsLength()); - - // paginate through subscriptions, batching by 10. - // we should eventually get all the subscriptions this way. - uint256[][] memory subIds = paginateSubscriptions(s_testCoordinator, 10); - // check that all subscriptions were returned - uint actualNumSubs = 0; - for (uint batchIdx = 0; batchIdx < subIds.length; batchIdx++) { - for (uint subIdx = 0; subIdx < subIds[batchIdx].length; subIdx++) { - s_testCoordinator.getSubscription(subIds[batchIdx][subIdx]); - actualNumSubs++; - } - } - assertEq(actualNumSubs, s_testCoordinator.getActiveSubscriptionIdsLength()); - - // cancel a bunch of subscriptions, assert that they are not returned - uint256[] memory subsToCancel = new uint256[](3); - for (uint i = 0; i < 3; i++) { - subsToCancel[i] = subIds[0][i]; - } - for (uint i = 0; i < subsToCancel.length; i++) { - s_testCoordinator.cancelSubscription(subsToCancel[i], LINK_WHALE); - } - uint256[][] memory newSubIds = paginateSubscriptions(s_testCoordinator, 10); - // check that all subscriptions were returned - // and assert that none of the canceled subscriptions are returned - actualNumSubs = 0; - for (uint batchIdx = 0; batchIdx < newSubIds.length; batchIdx++) { - for (uint subIdx = 0; subIdx < newSubIds[batchIdx].length; subIdx++) { - for (uint i = 0; i < subsToCancel.length; i++) { - assertFalse(newSubIds[batchIdx][subIdx] == subsToCancel[i]); - } - s_testCoordinator.getSubscription(newSubIds[batchIdx][subIdx]); - actualNumSubs++; - } - } - assertEq(actualNumSubs, s_testCoordinator.getActiveSubscriptionIdsLength()); - } - - function paginateSubscriptions( - ExposedVRFCoordinatorV2_5 coordinator, - uint256 batchSize - ) internal view returns (uint256[][] memory) { - uint arrIndex = 0; - uint startIndex = 0; - uint256 numSubs = coordinator.getActiveSubscriptionIdsLength(); - uint256[][] memory subIds = new uint256[][](Math.ceilDiv(numSubs, batchSize)); - while (startIndex < numSubs) { - subIds[arrIndex] = coordinator.getActiveSubscriptionIds(startIndex, batchSize); - startIndex += batchSize; - arrIndex++; - } - return subIds; - } - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - event RandomWordsFulfilled( - uint256 indexed requestId, - uint256 outputSeed, - uint256 indexed subID, - uint96 payment, - bytes extraArgs, - bool success - ); - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - - function testRequestAndFulfillRandomWordsNative() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - uint256 subId, - uint256 requestId - ) = setupSubAndRequestRandomnessNativePayment(); - (, uint96 nativeBalanceBefore, , , ) = s_testCoordinator.getSubscription(subId); - - uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; - vm.recordLogs(); - uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, false); - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries[0].topics[1], bytes32(uint256(requestId))); - assertEq(entries[0].topics[2], bytes32(uint256(subId))); - (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); - assertEq(loggedOutputSeed, outputSeed); - assertEq(loggedSuccess, true); - - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, true); - - // The cost of fulfillRandomWords is approximately 70_000 gas. - // gasAfterPaymentCalculation is 50_000. - // - // The cost of the VRF fulfillment charged to the user is: - // baseFeeWei = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) - // baseFeeWei = 1e11 * (50_000 + 70_000) - // baseFeeWei = 1.2e16 - // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM) - // flatFeeWei = 1e12 * 500_000 = 5e17 - // ... - // billed_fee = baseFeeWei * (100 + linkPremiumPercentage / 100) + 5e17 - // billed_fee = 1.2e16 * 1.15 + 5e17 - // billed_fee = 5.138e+17 - (, uint96 nativeBalanceAfter, , , ) = s_testCoordinator.getSubscription(subId); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.138 * 1e17, 1e15); - assertApproxEqAbs(nativeBalanceAfter, nativeBalanceBefore - 5.138 * 1e17, 1e15); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestAndFulfillRandomWordsLINK() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - uint256 subId, - uint256 requestId - ) = setupSubAndRequestRandomnessLINKPayment(); - (uint96 linkBalanceBefore, , , , ) = s_testCoordinator.getSubscription(subId); - - uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; - vm.recordLogs(); - uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, false); - - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries[0].topics[1], bytes32(uint256(requestId))); - assertEq(entries[0].topics[2], bytes32(uint256(subId))); - (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); - assertEq(loggedOutputSeed, outputSeed); - assertEq(loggedSuccess, true); - - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, true); - - // The cost of fulfillRandomWords is approximately 86_000 gas. - // gasAfterPaymentCalculation is 50_000. - // - // The cost of the VRF fulfillment charged to the user is: - // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) - // paymentNoFee = (1e11 * (50_000 + 86_000 + 0)) / .5 - // paymentNoFee = 2.72e16 - // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) - // flatFeeWei = 1e12 * (500_000 - 100_000) - // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio - // flatFeeJuels = 4e17 / 0.5 = 8e17 - // billed_fee = paymentNoFee * ((100 + 10) / 100) + 8e17 - // billed_fee = 2.72e16 * 1.1 + 8e17 - // billed_fee = 2.992e16 + 8e17 = 8.2992e17 - // note: delta is doubled from the native test to account for more variance due to the link/native ratio - (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 8.2992 * 1e17, 1e15); - assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 8.2992 * 1e17, 1e15); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestAndFulfillRandomWordsLINK_FallbackWeiPerUnitLinkUsed() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - , - uint256 requestId - ) = setupSubAndRequestRandomnessLINKPayment(); - - (, , , uint32 stalenessSeconds, , , , , ) = s_testCoordinator.s_config(); - int256 fallbackWeiPerUnitLink = s_testCoordinator.s_fallbackWeiPerUnitLink(); - - // Set the link feed to be stale. - (uint80 roundId, int256 answer, uint256 startedAt, , ) = s_linkNativeFeed.latestRoundData(); - uint256 timestamp = block.timestamp - stalenessSeconds - 1; - s_linkNativeFeed.updateRoundData(roundId, answer, timestamp, startedAt); - - vm.expectEmit(false, false, false, true, address(s_testCoordinator)); - emit FallbackWeiPerUnitLinkUsed(requestId, fallbackWeiPerUnitLink); - s_testCoordinator.fulfillRandomWords(proof, rc, false); - } - - function setupSubAndRequestRandomnessLINKPayment() - internal - returns (VRF.Proof memory proof, VRFTypes.RequestCommitmentV2Plus memory rc, uint256 subId, uint256 requestId) - { - uint32 requestBlock = 20; - vm.roll(requestBlock); - s_linkToken.transfer(address(s_testConsumer), 10 ether); - s_testConsumer.createSubscriptionAndFund(10 ether); - subId = s_testConsumer.s_subId(); - - // Apply basic configs to contract. - setConfig(); - registerProvingKey(); - - // Request random words. - vm.expectEmit(true, true, false, true); - uint256 preSeed; - (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(s_testConsumer), subId, 1); - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - subId, - MIN_CONFIRMATIONS, - CALLBACK_GAS_LIMIT, - NUM_WORDS, - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // nativePayment, // nativePayment - address(s_testConsumer) // requester - ); - s_testConsumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, vrfKeyHash, false); - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, false); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - - // Move on to the next block. - // Store the previous block's blockhash, and assert that it is as expected. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. - // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 4th step: run the command and copy the command output in the proof section below. - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 77134414723242246520332717536018735794426514244521954002798799849127623496871 \ - -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ - -block-num 20 \ - -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ - -native-payment false - */ - proof = VRF.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 103927982338770370318312316555080928288985522873495041111817988974598585393796, - 56789421278806198480964888112155620425048056183534931202752833185923411715624 - ], - c: 23645475075665525321781505993434124657388421977074956645288621921391376468128, - s: 106817081950846808215350231311242951539230271757396902089035477907017240898689, - seed: 77134414723242246520332717536018735794426514244521954002798799849127623496871, - uWitness: 0xD6899602060d574DE03FE1cf76fDf66afE12d549, - cGammaWitness: [ - 9892458071712426452033749279561067220589549155902380165087951541202159693388, - 61235995320721681444549354910430438435754757626312862714628885100042911955139 - ], - sHashWitness: [ - 101478618362722903511580105256015180591690884037598276249676652094434483808775, - 82512235485399822034680598942438982472006937353405384896956013889074719896188 - ], - zInv: 82281039329215616805111360985152709712368762415186906218863971780664103705723 - }); - rc = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: subId, - callbackGasLimit: 1000000, - numWords: 1, - sender: address(s_testConsumer), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})) - }); - return (proof, rc, subId, requestId); - } - - function setupSubAndRequestRandomnessNativePayment() - internal - returns (VRF.Proof memory proof, VRFTypes.RequestCommitmentV2Plus memory rc, uint256 subId, uint256 requestId) - { - uint32 requestBlock = 10; - vm.roll(requestBlock); - s_testConsumer.createSubscriptionAndFund(0); - subId = s_testConsumer.s_subId(); - s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); - - // Apply basic configs to contract. - setConfig(); - registerProvingKey(); - - // Request random words. - vm.expectEmit(true, true, true, true); - uint256 preSeed; - (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(s_testConsumer), subId, 1); - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - subId, - MIN_CONFIRMATIONS, - CALLBACK_GAS_LIMIT, - NUM_WORDS, - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), // nativePayment - address(s_testConsumer) // requester - ); - s_testConsumer.requestRandomWords(CALLBACK_GAS_LIMIT, MIN_CONFIRMATIONS, NUM_WORDS, vrfKeyHash, true); - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, false); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - - // Move on to the next block. - // Store the previous block's blockhash, and assert that it is as expected. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. - // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 4th step: run the command and copy the command output in the proof section below. - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 88177119495082281213609405072572269421661478022189589823108119237563684383163 \ - -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ - -block-num 10 \ - -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ - -native-payment true - */ - proof = VRF.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 102142782721757938350759722545721736888276217484353597703162772276193136052353, - 87167280284008869627768921028415708350806510214000539818296353518495698939660 - ], - c: 78738462581063211677832865654743924688552792392007862664964608134754001810280, - s: 97066881804257970453329086439696419448135613089654606517271688187030953014593, - seed: 88177119495082281213609405072572269421661478022189589823108119237563684383163, - uWitness: 0xa335ea8dF652d5331a276B60b16c9733435D4f73, - cGammaWitness: [ - 114435126227922602743444254494036972095649501991695809092954325430947992864624, - 63032211040463927862594425238691911311087931119674607521158894139074063158678 - ], - sHashWitness: [ - 105043781471073183057173130563345930784924139079040814418442661347864735908726, - 68696469914696211053833437482938344908217760552761185546164836556562945431554 - ], - zInv: 73325637847357165955904789471972164751975373195750497508525598331798833112175 - }); - rc = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: 1, - sender: address(s_testConsumer), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) - }); - - return (proof, rc, subId, requestId); - } - - function testRequestAndFulfillRandomWords_NetworkGasPriceExceedsGasLane() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - , - - ) = setupSubAndRequestRandomnessNativePayment(); - - // network gas is higher than gas lane max gas - uint256 networkGasPrice = GAS_LANE_MAX_GAS + 1; - vm.txGasPrice(networkGasPrice); - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.GasPriceExceeded.selector, networkGasPrice, GAS_LANE_MAX_GAS) - ); - s_testCoordinator.fulfillRandomWords(proof, rc, false); - } - - function testRequestAndFulfillRandomWords_OnlyPremium_NativePayment() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - uint256 subId, - uint256 requestId - ) = setupSubAndRequestRandomnessNativePayment(); - (, uint96 nativeBalanceBefore, , , ) = s_testCoordinator.getSubscription(subId); - - // network gas is twice the gas lane max gas - uint256 networkGasPrice = GAS_LANE_MAX_GAS * 2; - vm.txGasPrice(networkGasPrice); - - uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; - vm.recordLogs(); - uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries[0].topics[1], bytes32(uint256(requestId))); - assertEq(entries[0].topics[2], bytes32(uint256(subId))); - (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); - assertEq(loggedOutputSeed, outputSeed); - assertEq(loggedSuccess, true); - - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, true); - - // The cost of fulfillRandomWords is approximately 72_100 gas. - // gasAfterPaymentCalculation is 50_000. - // - // The cost of the VRF fulfillment charged to the user is: - // baseFeeWei = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) - // network gas price is capped at gas lane max gas (5000 gwei) - // baseFeeWei = 5e12 * (50_000 + 72_100) - // baseFeeWei = 6.11e17 - // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM) - // flatFeeWei = 1e12 * 500_000 = 5e17 - // ... - // billed_fee = baseFeeWei * (linkPremiumPercentage / 100) + 5e17 - // billed_fee = 6.11e17 * 0.15 + 5e17 - // billed_fee = 5.9157e+17 - (, uint96 nativeBalanceAfter, , , ) = s_testCoordinator.getSubscription(subId); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 5.9157 * 1e17, 1e15); - assertApproxEqAbs(nativeBalanceAfter, nativeBalanceBefore - 5.9157 * 1e17, 1e15); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestAndFulfillRandomWords_OnlyPremium_LinkPayment() public { - ( - VRF.Proof memory proof, - VRFTypes.RequestCommitmentV2Plus memory rc, - uint256 subId, - uint256 requestId - ) = setupSubAndRequestRandomnessLINKPayment(); - (uint96 linkBalanceBefore, , , , ) = s_testCoordinator.getSubscription(subId); - - // network gas is twice the gas lane max gas - uint256 networkGasPrice = GAS_LANE_MAX_GAS * 5; - vm.txGasPrice(networkGasPrice); - - uint256 outputSeed = s_testCoordinator.getRandomnessFromProofExternal(proof, rc).randomness; - vm.recordLogs(); - uint96 payment = s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); - - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries[0].topics[1], bytes32(uint256(requestId))); - assertEq(entries[0].topics[2], bytes32(uint256(subId))); - (uint256 loggedOutputSeed, , , bool loggedSuccess) = abi.decode(entries[0].data, (uint256, uint256, bool, bool)); - assertEq(loggedOutputSeed, outputSeed); - assertEq(loggedSuccess, true); - - (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); - assertEq(fulfilled, true); - - // The cost of fulfillRandomWords is approximately 89_100 gas. - // gasAfterPaymentCalculation is 50_000. - // - // The cost of the VRF fulfillment charged to the user is: - // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) - // network gas price is capped at gas lane max gas (5000 gwei) - // paymentNoFee = (5e12 * (50_000 + 89_100 + 0)) / .5 - // paymentNoFee = 1.391e+18 - // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) - // flatFeeWei = 1e12 * (500_000 - 100_000) - // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio - // flatFeeJuels = 4e17 / 0.5 = 8e17 - // billed_fee = paymentNoFee * (10 / 100) + 8e17 - // billed_fee = 1.391e+18 * 0.1 + 8e17 - // billed_fee = 9.391e+17 - // note: delta is doubled from the native test to account for more variance due to the link/native ratio - (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 9.391 * 1e17, 1e15); - assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.391 * 1e17, 1e15); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestRandomWords_InvalidConsumer() public { - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint256 subId = s_testCoordinator.createSubscription(); - VRFV2PlusLoadTestWithMetrics consumer = new VRFV2PlusLoadTestWithMetrics(address(s_testCoordinator)); - - // consumer is not added to the subscription - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); - consumer.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - true, - NUM_WORDS, - 1 /* requestCount */ - ); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestRandomWords_ReAddConsumer_AssertRequestID() public { - // 1. setup consumer and subscription - setConfig(); - registerProvingKey(); - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint256 subId = s_testCoordinator.createSubscription(); - VRFV2PlusLoadTestWithMetrics consumer = createAndAddLoadTestWithMetricsConsumer(subId); - uint32 requestBlock = 10; - vm.roll(requestBlock); - changePrank(LINK_WHALE); - s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); - - // 2. Request random words. - changePrank(subOwner); - vm.expectEmit(true, true, false, true); - uint256 requestId; - uint256 preSeed; - (requestId, preSeed) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(consumer), subId, 1); - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - subId, - MIN_CONFIRMATIONS, - CALLBACK_GAS_LIMIT, - NUM_WORDS, - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), - address(consumer) // requester - ); - consumer.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - true /* nativePayment */, - NUM_WORDS, - 1 /* requestCount */ - ); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - - // Move on to the next block. - // Store the previous block's blockhash, and assert that it is as expected. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - - // 3. Fulfill the request above - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. - // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 4th step: run the command and copy the command output in the proof section below. - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ - -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ - -block-num 10 \ - -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ - -native-payment true - */ - VRF.Proof memory proof = VRF.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 65913937398148449626792563067325648649534055460473988721938103219381973178278, - 63156327344180203180831822252171874192175272818200597638000091892096122362120 - ], - c: 96524997218413735279221574381819903278651909890109201564980667824986706861580, - s: 32941032142956097592442894642111025677491308239274769364799856748447418202313, - seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, - uWitness: 0xda613621Dc2347d9A6670a1cBA812d52A7ec3A3A, - cGammaWitness: [ - 6776842114900054689355891239487365968068230823400902903493665825747641410781, - 753482930067864853610521010650481816782338376846697006021590704037205560592 - ], - sHashWitness: [ - 76619528582417858778905184311764104068650968652636772643050945629834129417915, - 27947566794040118487986033070014357750801611688958204148187927873566412002355 - ], - zInv: 77351076831418813780936064446565588198113457019145030499544500588309236458362 - }); - VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: NUM_WORDS, - sender: address(consumer), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) - }); - s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - - // 4. remove consumer and verify request random words doesn't work - s_testCoordinator.removeConsumer(subId, address(consumer)); - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); - consumer.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - false /* nativePayment */, - NUM_WORDS, - 1 /* requestCount */ - ); - - // 5. re-add consumer and assert requestID nonce starts from 2 (nonce 1 was used before consumer removal) - s_testCoordinator.addConsumer(subId, address(consumer)); - vm.expectEmit(true, true, false, true); - uint256 requestId2; - uint256 preSeed2; - (requestId2, preSeed2) = s_testCoordinator.computeRequestIdExternal(vrfKeyHash, address(consumer), subId, 2); - emit RandomWordsRequested( - vrfKeyHash, - requestId2, - preSeed2, - subId, - MIN_CONFIRMATIONS, - CALLBACK_GAS_LIMIT, - NUM_WORDS, - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // nativePayment, // nativePayment - address(consumer) // requester - ); - consumer.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - false /* nativePayment */, - NUM_WORDS, - 1 /* requestCount */ - ); - assertNotEq(requestId, requestId2); - assertNotEq(preSeed, preSeed2); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - } - - function testRequestRandomWords_MultipleConsumers_PendingRequestExists() public { - // 1. setup consumer and subscription - setConfig(); - registerProvingKey(); - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint256 subId = s_testCoordinator.createSubscription(); - VRFV2PlusLoadTestWithMetrics consumer1 = createAndAddLoadTestWithMetricsConsumer(subId); - VRFV2PlusLoadTestWithMetrics consumer2 = createAndAddLoadTestWithMetricsConsumer(subId); - uint32 requestBlock = 10; - vm.roll(requestBlock); - changePrank(LINK_WHALE); - s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(subId); - - // 2. Request random words. - changePrank(subOwner); - (uint256 requestId1, uint256 preSeed1) = s_testCoordinator.computeRequestIdExternal( - vrfKeyHash, - address(consumer1), - subId, - 1 - ); - (uint256 requestId2, uint256 preSeed2) = s_testCoordinator.computeRequestIdExternal( - vrfKeyHash, - address(consumer2), - subId, - 1 - ); - assertNotEq(requestId1, requestId2); - assertNotEq(preSeed1, preSeed2); - consumer1.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - true /* nativePayment */, - NUM_WORDS, - 1 /* requestCount */ - ); - consumer2.requestRandomWords( - subId, - MIN_CONFIRMATIONS, - vrfKeyHash, - CALLBACK_GAS_LIMIT, - true /* nativePayment */, - NUM_WORDS, - 1 /* requestCount */ - ); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - - // Move on to the next block. - // Store the previous block's blockhash, and assert that it is as expected. - vm.roll(requestBlock + 1); - s_bhs.store(requestBlock); - assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - - // 3. Fulfill the 1st request above - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. - // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 4th step: run the command and copy the command output in the proof section below. - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ - -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ - -block-num 10 \ - -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ - -native-payment true - */ - VRF.Proof memory proof = VRF.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 65913937398148449626792563067325648649534055460473988721938103219381973178278, - 63156327344180203180831822252171874192175272818200597638000091892096122362120 - ], - c: 103296526941774692908067234360350834482645116475454593803823148315342533216203, - s: 50291245814080656739779812653411869801334231723444391096753849942661931376590, - seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, - uWitness: 0x38500711AdcB471ac1A566c4b915759eb9cBCE2F, - cGammaWitness: [ - 56476970720509547210740928951846471668018949971632948991136782499758110143588, - 44326075300781389077656415325167171692706436527877070415603658305817367373598 - ], - sHashWitness: [ - 109524696164787283409393383708118913934136014139634321235031691839206768278439, - 52690039857779635909051684567562068782378693408005554345469129234366171822741 - ], - zInv: 108537983043800425266290112227943788107669768716438017124275578856644517258573 - }); - VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: NUM_WORDS, - sender: address(consumer1), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) - }); - s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); - assertTrue(s_testCoordinator.pendingRequestExists(subId)); - - // 4. Fulfill the 2nd request - // Proof generated via the generate-proof-v2-plus script command. - // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. - // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. - // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer - // export ETH_CHAIN_ID=11155111 # or switch to any other chain - // export ACCOUNT_KEY= - // 4th step: run the command and copy the command output in the proof section below. - /* - Run from this folder: chainlink/core/scripts/vrfv2plus/testnet - go run . generate-proof-v2-plus \ - -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 53330100288105770463016865504321558518073051667771993294213115153676065708950 \ - -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ - -block-num 10 \ - -sender 0xf5a165378E120f93784395aDF1E08a437e902865 \ - -native-payment true - */ - proof = VRF.Proof({ - pk: [ - 72488970228380509287422715226575535698893157273063074627791787432852706183111, - 62070622898698443831883535403436258712770888294397026493185421712108624767191 - ], - gamma: [ - 7260273098301741284457725182313945178888499328441106869722941415453613782770, - 91648498042618923465107471165504200585847250228048015102713552756245653299952 - ], - c: 64987886290696558870328339791409334400119338012796549091587853494368167422332, - s: 69469162696695326295567645789624554797683340898724555794078876350372084267572, - seed: 53330100288105770463016865504321558518073051667771993294213115153676065708950, - uWitness: 0xa6ce21aD47eC5E90Ac7a2c6152D9710234Afe8ab, - cGammaWitness: [ - 57318358662553647785891634403735348577492991113152343207139729697842283565417, - 57942043484796308689103390068712967247519265087617809262260051163954389512396 - ], - sHashWitness: [ - 113345999157319332195230171660555736547709417795439282230372737104445523493539, - 113358219039155973560933190466797830695088313506343976960055230355894888727567 - ], - zInv: 68349552569605209428774574139615352877146713490794995768725549089572297658255 - }); - rc = VRFTypes.RequestCommitmentV2Plus({ - blockNum: requestBlock, - subId: subId, - callbackGasLimit: CALLBACK_GAS_LIMIT, - numWords: NUM_WORDS, - sender: address(consumer2), - extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})) - }); - s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); - assertFalse(s_testCoordinator.pendingRequestExists(subId)); - } - - function createAndAddLoadTestWithMetricsConsumer(uint256 subId) internal returns (VRFV2PlusLoadTestWithMetrics) { - VRFV2PlusLoadTestWithMetrics consumer = new VRFV2PlusLoadTestWithMetrics(address(s_testCoordinator)); - s_testCoordinator.addConsumer(subId, address(consumer)); - return consumer; - } - - function test_RemoveConsumer() public { - uint256 subId = s_testCoordinator.createSubscription(); - uint256 consumersLength = s_testCoordinator.MAX_CONSUMERS(); - address[] memory consumers = getRandomAddresses(consumersLength); - for (uint256 i = 0; i < consumersLength; ++i) { - s_testCoordinator.addConsumer(subId, consumers[i]); - } - - // test remove consumers from multiple positions to have better gas distribution - address earlyConsumerAddress = consumers[0]; - s_testCoordinator.removeConsumer(subId, earlyConsumerAddress); - (, , , , consumers) = s_testCoordinator.getSubscription(subId); - assertEq(consumers.length, consumersLength - 1); - assertFalse(addressIsIn(earlyConsumerAddress, consumers)); - - consumersLength = consumers.length; - address middleConsumerAddress = consumers[consumersLength / 2]; - s_testCoordinator.removeConsumer(subId, middleConsumerAddress); - (, , , , consumers) = s_testCoordinator.getSubscription(subId); - assertEq(consumers.length, consumersLength - 1); - assertFalse(addressIsIn(middleConsumerAddress, consumers)); - - consumersLength = consumers.length; - address lateConsumerAddress = consumers[consumersLength - 1]; - s_testCoordinator.removeConsumer(subId, lateConsumerAddress); - (, , , , consumers) = s_testCoordinator.getSubscription(subId); - assertEq(consumers.length, consumersLength - 1); - assertFalse(addressIsIn(lateConsumerAddress, consumers)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol deleted file mode 100644 index 4fbb44e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol +++ /dev/null @@ -1,649 +0,0 @@ -pragma solidity 0.8.19; - -import "./BaseTest.t.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; // for Strings.toString -import {VmSafe} from "forge-std/Vm.sol"; - -contract VRFV2PlusSubscriptionAPITest is BaseTest { - event SubscriptionFunded(uint256 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionFundedWithNative(uint256 indexed subId, uint256 oldNativeBalance, uint256 newNativeBalance); - event SubscriptionCanceled(uint256 indexed subId, address to, uint256 amountLink, uint256 amountNative); - event FundsRecovered(address to, uint256 amountLink); - event NativeFundsRecovered(address to, uint256 amountNative); - event SubscriptionOwnerTransferRequested(uint256 indexed subId, address from, address to); - event SubscriptionOwnerTransferred(uint256 indexed subId, address from, address to); - event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); - event SubscriptionConsumerRemoved(uint256 indexed subId, address consumer); - - ExposedVRFCoordinatorV2_5 s_subscriptionAPI; - - function setUp() public override { - BaseTest.setUp(); - address bhs = makeAddr("bhs"); - s_subscriptionAPI = new ExposedVRFCoordinatorV2_5(bhs); - } - - function testDefaultState() public { - assertEq(address(s_subscriptionAPI.LINK()), address(0)); - assertEq(address(s_subscriptionAPI.LINK_NATIVE_FEED()), address(0)); - assertEq(s_subscriptionAPI.s_currentSubNonce(), 0); - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); - assertEq(s_subscriptionAPI.s_totalBalance(), 0); - assertEq(s_subscriptionAPI.s_totalNativeBalance(), 0); - } - - function testSetLINKAndLINKNativeFeed() public { - address link = makeAddr("link"); - address linkNativeFeed = makeAddr("linkNativeFeed"); - s_subscriptionAPI.setLINKAndLINKNativeFeed(link, linkNativeFeed); - assertEq(address(s_subscriptionAPI.LINK()), link); - assertEq(address(s_subscriptionAPI.LINK_NATIVE_FEED()), linkNativeFeed); - - // try setting it again, should revert - vm.expectRevert(SubscriptionAPI.LinkAlreadySet.selector); - s_subscriptionAPI.setLINKAndLINKNativeFeed(link, linkNativeFeed); - } - - function testOwnerCancelSubscriptionNoFunds() public { - // CASE: new subscription w/ no funds at all - // Should cancel trivially - - // Note that the link token is not set, but this should still - // not fail in that case. - - // Create the subscription from a separate address - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // change back to owner and cancel the subscription - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, subOwner, 0, 0); - s_subscriptionAPI.ownerCancelSubscription(subId); - - // assert that the subscription no longer exists - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); - // no point in checking s_subscriptions because all fields are zeroed out - // due to no balance and no requests made - } - - function testOwnerCancelSubscriptionNativeFundsOnly() public { - // CASE: new subscription with native funds only - // no link funds. - // should cancel and return the native funds - - // Create the subscription from a separate address - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with ether - vm.deal(subOwner, 10 ether); - vm.expectEmit(true, false, false, true); - emit SubscriptionFundedWithNative(subId, 0, 5 ether); - s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); - - // change back to owner and cancel the subscription - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, subOwner, 0 /* link balance */, 5 ether /* native balance */); - s_subscriptionAPI.ownerCancelSubscription(subId); - - // assert that the subscription no longer exists - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 0); - - // check the native balance of the subOwner, should be 10 ether - assertEq(address(subOwner).balance, 10 ether); - } - - function testOwnerCancelSubscriptionLinkFundsOnly() public { - // CASE: new subscription with link funds only - // no native funds. - // should cancel and return the link funds - - // Create link token and set the link token on the subscription api object - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // Create the subscription from a separate address - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with link - // can do it from the owner acct because anyone can fund a subscription - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, 5 ether); - bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); - assertTrue(success, "failed link transfer and call"); - - // change back to owner and cancel the subscription - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, subOwner, 5 ether /* link balance */, 0 /* native balance */); - s_subscriptionAPI.ownerCancelSubscription(subId); - - // assert that the subscription no longer exists - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 0); - - // check the link balance of the sub owner, should be 5 LINK - assertEq(linkToken.balanceOf(subOwner), 5 ether); - } - - function testOwnerCancelSubscriptionNativeAndLinkFunds() public { - // CASE: new subscription with link and native funds - // should cancel and return both link and native funds - - // Create link token and set the link token on the subscription api object - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // Create the subscription from a separate address - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with link - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, 5 ether); - bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); - assertTrue(success, "failed link transfer and call"); - - // fund the subscription with ether - vm.deal(subOwner, 10 ether); - changePrank(subOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionFundedWithNative(subId, 0, 5 ether); - s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); - - // change back to owner and cancel the subscription - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionCanceled(subId, subOwner, 5 ether /* link balance */, 5 ether /* native balance */); - s_subscriptionAPI.ownerCancelSubscription(subId); - - // assert that the subscription no longer exists - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, address(0)); - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 0); - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 0); - - // check the link balance of the sub owner, should be 5 LINK - assertEq(linkToken.balanceOf(subOwner), 5 ether, "link balance incorrect"); - // check the ether balance of the sub owner, should be 10 ether - assertEq(address(subOwner).balance, 10 ether, "native balance incorrect"); - } - - function testRecoverFundsLINKNotSet() public { - // CASE: link token not set - // should revert with error LinkNotSet - - // call recoverFunds - vm.expectRevert(SubscriptionAPI.LinkNotSet.selector); - s_subscriptionAPI.recoverFunds(OWNER); - } - - function testRecoverFundsBalanceInvariantViolated() public { - // CASE: link token set - // and internal balance is greater than external balance - - // Create link token and set the link token on the subscription api object - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // set the total balance to be greater than the external balance - // so that we trigger the invariant violation - // note that this field is not modifiable in the actual contracts - // other than through onTokenTransfer or similar functions - s_subscriptionAPI.setTotalBalanceTestingOnlyXXX(100 ether); - - // call recoverFunds - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.BalanceInvariantViolated.selector, 100 ether, 0)); - s_subscriptionAPI.recoverFunds(OWNER); - } - - function testRecoverFundsAmountToTransfer() public { - // CASE: link token set - // and internal balance is less than external balance - // (i.e invariant is not violated) - // should recover funds successfully - - // Create link token and set the link token on the subscription api object - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // transfer 10 LINK to the contract to recover - bool success = linkToken.transfer(address(s_subscriptionAPI), 10 ether); - assertTrue(success, "failed link transfer"); - - // call recoverFunds - vm.expectEmit(true, false, false, true); - emit FundsRecovered(OWNER, 10 ether); - s_subscriptionAPI.recoverFunds(OWNER); - } - - function testRecoverFundsNothingToTransfer() public { - // CASE: link token set - // and there is nothing to transfer - // should do nothing at all - - // Create link token and set the link token on the subscription api object - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // create a subscription and fund it with 5 LINK - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with link - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, 5 ether); - bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); - assertTrue(success, "failed link transfer and call"); - - // call recoverFunds, nothing should happen because external balance == internal balance - s_subscriptionAPI.recoverFunds(OWNER); - assertEq(linkToken.balanceOf(address(s_subscriptionAPI)), s_subscriptionAPI.s_totalBalance()); - } - - function testRecoverNativeFundsBalanceInvariantViolated() public { - // set the total balance to be greater than the external balance - // so that we trigger the invariant violation - // note that this field is not modifiable in the actual contracts - // other than through onTokenTransfer or similar functions - s_subscriptionAPI.setTotalNativeBalanceTestingOnlyXXX(100 ether); - - // call recoverFunds - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.BalanceInvariantViolated.selector, 100 ether, 0)); - s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); - } - - function testRecoverNativeFundsAmountToTransfer() public { - // transfer 10 LINK to the contract to recover - vm.deal(address(s_subscriptionAPI), 10 ether); - - // call recoverFunds - vm.expectEmit(true, false, false, true); - emit NativeFundsRecovered(OWNER, 10 ether); - s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); - } - - function testRecoverNativeFundsNothingToTransfer() public { - // create a subscription and fund it with 5 ether - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with ether - vm.deal(subOwner, 5 ether); - changePrank(subOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionFundedWithNative(subId, 0, 5 ether); - s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); - - // call recoverNativeFunds, nothing should happen because external balance == internal balance - changePrank(OWNER); - s_subscriptionAPI.recoverNativeFunds(payable(OWNER)); - assertEq(address(s_subscriptionAPI).balance, s_subscriptionAPI.s_totalNativeBalance()); - } - - function testWithdrawNoLink() public { - // CASE: no link token set - vm.expectRevert(SubscriptionAPI.LinkNotSet.selector); - s_subscriptionAPI.withdraw(OWNER); - } - - function testWithdrawInsufficientBalance() public { - // CASE: link token set, trying to withdraw - // more than balance - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // call withdraw - vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); - s_subscriptionAPI.withdraw(OWNER); - } - - function testWithdrawSufficientBalanceLinkSet() public { - // CASE: link token set, trying to withdraw - // less than balance - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // transfer 10 LINK to the contract to withdraw - bool success = linkToken.transfer(address(s_subscriptionAPI), 10 ether); - assertTrue(success, "failed link transfer"); - - // set the withdrawable tokens of the contract to be 1 ether - s_subscriptionAPI.setWithdrawableTokensTestingOnlyXXX(1 ether); - assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 1 ether); - - // set the total balance to be the same as the link balance for consistency - // (this is not necessary for the test, but just to be sane) - s_subscriptionAPI.setTotalBalanceTestingOnlyXXX(10 ether); - - // call Withdraw from owner address - uint256 ownerBalance = linkToken.balanceOf(OWNER); - changePrank(OWNER); - s_subscriptionAPI.withdraw(OWNER); - // assert link balance of owner - assertEq(linkToken.balanceOf(OWNER) - ownerBalance, 1 ether, "owner link balance incorrect"); - // assert state of subscription api - assertEq(s_subscriptionAPI.getWithdrawableTokensTestingOnlyXXX(), 0, "owner withdrawable tokens incorrect"); - // assert that total balance is changed by the withdrawn amount - assertEq(s_subscriptionAPI.s_totalBalance(), 9 ether, "total balance incorrect"); - } - - function testWithdrawNativeInsufficientBalance() public { - // CASE: trying to withdraw more than balance - // should revert with InsufficientBalance - - // call WithdrawNative - changePrank(OWNER); - vm.expectRevert(SubscriptionAPI.InsufficientBalance.selector); - s_subscriptionAPI.withdrawNative(payable(OWNER)); - } - - function testWithdrawLinkInvalidOwner() public { - address invalidAddress = makeAddr("invalidAddress"); - changePrank(invalidAddress); - vm.expectRevert("Only callable by owner"); - s_subscriptionAPI.withdraw(payable(OWNER)); - } - - function testWithdrawNativeInvalidOwner() public { - address invalidAddress = makeAddr("invalidAddress"); - changePrank(invalidAddress); - vm.expectRevert("Only callable by owner"); - s_subscriptionAPI.withdrawNative(payable(OWNER)); - } - - function testWithdrawNativeSufficientBalance() public { - // CASE: trying to withdraw less than balance - // should withdraw successfully - - // transfer 10 ether to the contract to withdraw - vm.deal(address(s_subscriptionAPI), 10 ether); - - // set the withdrawable eth of the contract to be 1 ether - s_subscriptionAPI.setWithdrawableNativeTestingOnlyXXX(1 ether); - assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 1 ether); - - // set the total balance to be the same as the eth balance for consistency - // (this is not necessary for the test, but just to be sane) - s_subscriptionAPI.setTotalNativeBalanceTestingOnlyXXX(10 ether); - - // call WithdrawNative from owner address - changePrank(OWNER); - s_subscriptionAPI.withdrawNative(payable(OWNER)); - // assert native balance - assertEq(address(OWNER).balance, 1 ether, "owner native balance incorrect"); - // assert state of subscription api - assertEq(s_subscriptionAPI.getWithdrawableNativeTestingOnlyXXX(), 0, "owner withdrawable native incorrect"); - // assert that total balance is changed by the withdrawn amount - assertEq(s_subscriptionAPI.s_totalNativeBalance(), 9 ether, "total native balance incorrect"); - } - - function testOnTokenTransferCallerNotLink() public { - vm.expectRevert(SubscriptionAPI.OnlyCallableFromLink.selector); - s_subscriptionAPI.onTokenTransfer(makeAddr("someaddress"), 1 ether, abi.encode(uint256(1))); - } - - function testOnTokenTransferInvalidCalldata() public { - // create and set link token on subscription api - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // call link.transferAndCall with invalid calldata - vm.expectRevert(SubscriptionAPI.InvalidCalldata.selector); - linkToken.transferAndCall(address(s_subscriptionAPI), 1 ether, abi.encode(uint256(1), address(1))); - } - - function testOnTokenTransferInvalidSubscriptionId() public { - // create and set link token on subscription api - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // generate bogus sub id - uint256 subId = uint256(keccak256("idontexist")); - - // try to fund bogus sub id - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - linkToken.transferAndCall(address(s_subscriptionAPI), 1 ether, abi.encode(subId)); - } - - function testOnTokenTransferSuccess() public { - // happy path link funding test - // create and set link token on subscription api - MockLinkToken linkToken = new MockLinkToken(); - s_subscriptionAPI.setLINKAndLINKNativeFeed(address(linkToken), address(0)); - assertEq(address(s_subscriptionAPI.LINK()), address(linkToken)); - - // create a subscription and fund it with 5 LINK - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with link - changePrank(OWNER); - vm.expectEmit(true, false, false, true); - emit SubscriptionFunded(subId, 0, 5 ether); - bool success = linkToken.transferAndCall(address(s_subscriptionAPI), 5 ether, abi.encode(subId)); - assertTrue(success, "failed link transfer and call"); - - // assert that the subscription is funded - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).balance, 5 ether); - } - - function testFundSubscriptionWithNativeInvalidSubscriptionId() public { - // CASE: invalid subscription id - // should revert with InvalidSubscription - - uint256 subId = uint256(keccak256("idontexist")); - - // try to fund the subscription with native, should fail - address funder = makeAddr("funder"); - vm.deal(funder, 5 ether); - changePrank(funder); - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); - } - - function testFundSubscriptionWithNative() public { - // happy path test - // funding subscription with native - - // create a subscription and fund it with native - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - - // fund the subscription with native - vm.deal(subOwner, 5 ether); - changePrank(subOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionFundedWithNative(subId, 0, 5 ether); - s_subscriptionAPI.fundSubscriptionWithNative{value: 5 ether}(subId); - - // assert that the subscription is funded - assertEq(s_subscriptionAPI.getSubscriptionStruct(subId).nativeBalance, 5 ether); - } - - function testCreateSubscription() public { - // test that the subscription is created successfully - // and test the initial state of the subscription - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - assertEq(s_subscriptionAPI.getActiveSubscriptionIdsLength(), 1); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, subOwner); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).requestedOwner, address(0)); - } - - function testCreateSubscriptionRecreate() public { - // create two subscriptions from the same eoa - // they should never be the same due to nonce incrementation - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint64 nonceBefore = s_subscriptionAPI.s_currentSubNonce(); - uint256 subId1 = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 1); - uint256 subId2 = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.s_currentSubNonce(), nonceBefore + 2); - assertTrue(subId1 != subId2); - } - - function testSubscriptionOwnershipTransfer() public { - // create two eoa's, and create a subscription from one of them - // and transfer ownership to the other - // assert that the subscription is now owned by the other eoa - address oldOwner = makeAddr("oldOwner"); - address newOwner = makeAddr("newOwner"); - - // create sub - changePrank(oldOwner); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).owner, oldOwner); - - // request ownership transfer - changePrank(oldOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionOwnerTransferRequested(subId, oldOwner, newOwner); - s_subscriptionAPI.requestSubscriptionOwnerTransfer(subId, newOwner); - - // accept ownership transfer from newOwner - changePrank(newOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionOwnerTransferred(subId, oldOwner, newOwner); - s_subscriptionAPI.acceptSubscriptionOwnerTransfer(subId); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).requestedOwner, address(0)); - } - - function testAddConsumerTooManyConsumers() public { - // add 100 consumers to a sub and then - // try adding one more and see the revert - address subOwner = makeAddr("subOwner"); - changePrank(subOwner); - uint256 subId = s_subscriptionAPI.createSubscription(); - for (uint256 i = 0; i < 100; i++) { - address consumer = makeAddr(Strings.toString(i)); - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerAdded(subId, consumer); - s_subscriptionAPI.addConsumer(subId, consumer); - } - - // try adding one more consumer, should revert - address lastConsumer = makeAddr("consumer"); - changePrank(subOwner); - vm.expectRevert(SubscriptionAPI.TooManyConsumers.selector); - s_subscriptionAPI.addConsumer(subId, lastConsumer); - } - - function testAddConsumerReaddSameConsumer() public { - // try adding the same consumer twice - // should be a no-op - // assert state is unchanged after the 2nd add - address subOwner = makeAddr("subOwner"); - address consumer = makeAddr("consumer"); - changePrank(subOwner); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); - changePrank(subOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerAdded(subId, consumer); - s_subscriptionAPI.addConsumer(subId, consumer); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); - - // add consumer again, should be no-op - changePrank(subOwner); - VmSafe.Log[] memory events = vm.getRecordedLogs(); - s_subscriptionAPI.addConsumer(subId, consumer); - assertEq(events.length, 0); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); - - // remove consumer - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerRemoved(subId, consumer); - s_subscriptionAPI.removeConsumer(subId, consumer); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); - - // removing consumer twice should revert - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.InvalidConsumer.selector, subId, address(consumer))); - s_subscriptionAPI.removeConsumer(subId, consumer); - - //re-add consumer - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerAdded(subId, consumer); - s_subscriptionAPI.addConsumer(subId, consumer); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); - } - - function testAddConsumer() public { - // create a subscription and add a consumer - // assert subscription state afterwards - address subOwner = makeAddr("subOwner"); - address consumer = makeAddr("consumer"); - changePrank(subOwner); - uint256 subId = s_subscriptionAPI.createSubscription(); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 0); - - // only subscription owner can add a consumer - address notSubOwner = makeAddr("notSubOwner"); - changePrank(notSubOwner); - vm.expectRevert(abi.encodeWithSelector(SubscriptionAPI.MustBeSubOwner.selector, subOwner)); - s_subscriptionAPI.addConsumer(subId, consumer); - - // subscription owner is able to add a consumer - changePrank(subOwner); - vm.expectEmit(true, false, false, true); - emit SubscriptionConsumerAdded(subId, consumer); - s_subscriptionAPI.addConsumer(subId, consumer); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers.length, 1); - assertEq(s_subscriptionAPI.getSubscriptionConfig(subId).consumers[0], consumer); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol deleted file mode 100644 index 4b3a893..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol +++ /dev/null @@ -1,488 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; -import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; -import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; - -contract VRFV2PlusWrapperTest is BaseTest { - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint32 private wrapperGasOverhead = 100_000; - uint32 private coordinatorGasOverheadNative = 200_000; - uint32 private coordinatorGasOverheadLink = 220_000; - uint256 private s_wrapperSubscriptionId; - - ExposedVRFCoordinatorV2_5 private s_testCoordinator; - MockLinkToken private s_linkToken; - MockV3Aggregator private s_linkNativeFeed; - VRFV2PlusWrapper private s_wrapper; - VRFV2PlusWrapperConsumerExample private s_consumer; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(LINK_WHALE, 10_000 ether); - vm.stopPrank(); - vm.startPrank(LINK_WHALE); - - // Deploy link token and link/native feed. - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Deploy coordinator. - s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(0)); - - // Create subscription for all future wrapper contracts. - s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); - - // Deploy wrapper. - s_wrapper = new VRFV2PlusWrapper( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - assertEq(address(s_linkToken), address(s_wrapper.link())); - assertEq(address(s_linkNativeFeed), address(s_wrapper.linkNativeFeed())); - - // Add wrapper as a consumer to the wrapper's subscription. - s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); - - // Deploy consumer. - s_consumer = new VRFV2PlusWrapperConsumerExample(address(s_wrapper)); - - // Configure the coordinator. - s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - setConfigCoordinator(); - setConfigWrapper(); - - s_testCoordinator.s_config(); - } - - function setConfigCoordinator() internal { - s_testCoordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 0, // fulfillmentFlatFeeNativePPM - 0, // fulfillmentFlatFeeLinkDiscountPPM - 0, // nativePremiumPercentage - 0 // linkPremiumPercentage - ); - } - - function setConfigWrapper() internal { - vm.expectEmit(false, false, false, true, address(s_wrapper)); - emit ConfigSet( - wrapperGasOverhead, - coordinatorGasOverheadNative, - coordinatorGasOverheadLink, - 0, - 0, - 0, - vrfKeyHash, - 10, - 1, - 50000000000000000, - 0, - 0 - ); - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 0, // native premium percentage, - 0, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 0, // fulfillmentFlatFeeNativePPM - 0 // fulfillmentFlatFeeLinkDiscountPPM - ); - ( - , - , - , - , - uint32 _wrapperGasOverhead, - uint32 _coordinatorGasOverheadNative, - uint32 _coordinatorGasOverheadLink, - uint16 _coordinatorGasOverheadPerWord, - uint8 _coordinatorNativePremiumPercentage, - uint8 _coordinatorLinkPremiumPercentage, - bytes32 _keyHash, - uint8 _maxNumWords - ) = s_wrapper.getConfig(); - assertEq(_wrapperGasOverhead, wrapperGasOverhead); - assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative); - assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink); - assertEq(0, _coordinatorGasOverheadPerWord); - assertEq(0, _coordinatorNativePremiumPercentage); - assertEq(0, _coordinatorLinkPremiumPercentage); - assertEq(vrfKeyHash, _keyHash); - assertEq(10, _maxNumWords); - } - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - // IVRFV2PlusWrapper events - event LinkNativeFeedSet(address linkNativeFeed); - event FulfillmentTxSizeSet(uint32 size); - event ConfigSet( - uint32 wrapperGasOverhead, - uint32 coordinatorGasOverheadNative, - uint32 coordinatorGasOverheadLink, - uint16 coordinatorGasOverheadPerWord, - uint8 coordinatorNativePremiumPercentage, - uint8 coordinatorLinkPremiumPercentage, - bytes32 keyHash, - uint8 maxNumWords, - uint32 stalenessSeconds, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM - ); - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - event Withdrawn(address indexed to, uint256 amount); - event NativeWithdrawn(address indexed to, uint256 amount); - event Enabled(); - event Disabled(); - - // VRFV2PlusWrapperConsumerBase events - event LinkTokenSet(address link); - - // SubscriptionAPI events - event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); - - function testVRFV2PlusWrapperZeroAddress() public { - vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(0), uint256(0)); - } - - function testCreationOfANewVRFV2PlusWrapper() public { - // second wrapper contract will simply add itself to the same subscription - VRFV2PlusWrapper nextWrapper = new VRFV2PlusWrapper( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - s_wrapperSubscriptionId - ); - assertEq(s_wrapperSubscriptionId, nextWrapper.SUBSCRIPTION_ID()); - } - - function testVRFV2PlusWrapperWithZeroSubscriptionId() public { - vm.expectRevert(VRFV2PlusWrapper.SubscriptionIdMissing.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(0)); - } - - function testVRFV2PlusWrapperWithInvalidSubscriptionId() public { - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(123456)); - } - - function testSetFulfillmentTxSize() public { - uint32 fulfillmentTxSize = 100_000; - vm.expectEmit(false, false, false, true, address(s_wrapper)); - emit FulfillmentTxSizeSet(fulfillmentTxSize); - s_wrapper.setFulfillmentTxSize(fulfillmentTxSize); - assertEq(s_wrapper.s_fulfillmentTxSizeBytes(), fulfillmentTxSize); - } - - function testSetCoordinatorZeroAddress() public { - vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); - s_wrapper.setCoordinator(address(0)); - } - - function testRequestAndFulfillRandomWordsNativeWrapper() public { - // Fund subscription. - s_testCoordinator.fundSubscriptionWithNative{value: 10 ether}(s_wrapper.SUBSCRIPTION_ID()); - vm.deal(address(s_consumer), 10 ether); - - // Get type and version. - assertEq(s_wrapper.typeAndVersion(), "VRFV2PlusWrapper 1.0.0"); - - // Cannot make request while disabled. - vm.expectEmit(false, false, false, true, address(s_wrapper)); - emit Disabled(); - s_wrapper.disable(); - vm.expectRevert("wrapper is disabled"); - s_consumer.makeRequestNative(100_000, 0, 0); - vm.expectEmit(false, false, false, true, address(s_wrapper)); - emit Enabled(); - s_wrapper.enable(); - - // Request randomness from wrapper. - uint32 callbackGasLimit = 1_000_000; - vm.expectEmit(true, true, true, true); - (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( - vrfKeyHash, - address(s_wrapper), - s_wrapper.SUBSCRIPTION_ID(), - 1 - ); - uint32 EIP150Overhead = callbackGasLimit / 63 + 1; - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - s_wrapper.SUBSCRIPTION_ID(), // subId - 0, // minConfirmations - callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 - 1, // numWords - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true})), // extraArgs - address(s_wrapper) // requester - ); - requestId = s_consumer.makeRequestNative(callbackGasLimit, 0, 1); - - (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); - uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative; - uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice); - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0); - assertEq(paid, expectedPaid); - assertEq(uint256(paid), wrapperNativeCostEstimate); - assertEq(wrapperNativeCostEstimate, wrapperCostCalculation); - assertEq(fulfilled, false); - assertEq(native, true); - assertEq(address(s_consumer).balance, 10 ether - expectedPaid); - - (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); - assertEq(gasLimit, callbackGasLimit); - - changePrank(address(s_testCoordinator)); - uint256[] memory words = new uint256[](1); - words[0] = 123; - s_wrapper.rawFulfillRandomWords(requestId, words); - (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); - assertEq(nowFulfilled, true); - assertEq(storedWords[0], 123); - - // Withdraw funds from wrapper. - changePrank(LINK_WHALE); - uint256 priorWhaleBalance = LINK_WHALE.balance; - vm.expectEmit(true, false, false, true, address(s_wrapper)); - emit NativeWithdrawn(LINK_WHALE, paid); - s_wrapper.withdrawNative(LINK_WHALE); - assertEq(LINK_WHALE.balance, priorWhaleBalance + paid); - assertEq(address(s_wrapper).balance, 0); - } - - function testSetConfigFulfillmentFlatFee_LinkDiscountTooHigh() public { - // Test that setting link discount flat fee higher than native flat fee reverts - vm.expectRevert(abi.encodeWithSelector(VRFV2PlusWrapper.LinkDiscountTooHigh.selector, uint32(501), uint32(500))); - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 0, // native premium percentage, - 0, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 500, // fulfillmentFlatFeeNativePPM - 501 // fulfillmentFlatFeeLinkDiscountPPM - ); - } - - function testSetConfigFulfillmentFlatFee_LinkDiscountEqualsNative() public { - // Test that setting link discount flat fee equal to native flat fee does not revert - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 0, // native premium percentage, - 0, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 450, // fulfillmentFlatFeeNativePPM - 450 // fulfillmentFlatFeeLinkDiscountPPM - ); - } - - function testSetConfigNativePremiumPercentageInvalidPremiumPercentage() public { - // Test that setting native premium percentage higher than 155 will revert - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155)) - ); - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 156, // native premium percentage, - 0, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 0, // fulfillmentFlatFeeNativePPM - 0 // fulfillmentFlatFeeLinkDiscountPPM - ); - } - - function testSetConfigLinkPremiumPercentageInvalidPremiumPercentage() public { - // Test that setting LINK premium percentage higher than 155 will revert - vm.expectRevert( - abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155)) - ); - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 15, // native premium percentage, - 202, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 0, // fulfillmentFlatFeeNativePPM - 0 // fulfillmentFlatFeeLinkDiscountPPM - ); - } - - function testRequestAndFulfillRandomWordsLINKWrapper() public { - // Fund subscription. - s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID())); - s_linkToken.transfer(address(s_consumer), 10 ether); - - // Request randomness from wrapper. - uint32 callbackGasLimit = 1_000_000; - vm.expectEmit(true, true, true, true); - (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( - vrfKeyHash, - address(s_wrapper), - s_wrapper.SUBSCRIPTION_ID(), - 1 - ); - uint32 EIP150Overhead = callbackGasLimit / 63 + 1; - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - s_wrapper.SUBSCRIPTION_ID(), // subId - 0, // minConfirmations - callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 - 1, // numWords - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // extraArgs - address(s_wrapper) // requester - ); - s_consumer.makeRequest(callbackGasLimit, 0, 1); - - // Assert that the request was made correctly. - (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); - uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2; - uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice); - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); - assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio - assertEq(uint256(paid), wrapperCostEstimate); - assertEq(wrapperCostEstimate, wrapperCostCalculation); - assertEq(fulfilled, false); - assertEq(native, false); - assertEq(s_linkToken.balanceOf(address(s_consumer)), 10 ether - expectedPaid); - (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); - assertEq(gasLimit, callbackGasLimit); - - // Fulfill the request. - changePrank(address(s_testCoordinator)); - uint256[] memory words = new uint256[](1); - words[0] = 456; - s_wrapper.rawFulfillRandomWords(requestId, words); - (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); - assertEq(nowFulfilled, true); - assertEq(storedWords[0], 456); - - // Withdraw funds from wrapper. - changePrank(LINK_WHALE); - uint256 priorWhaleBalance = s_linkToken.balanceOf(LINK_WHALE); - vm.expectEmit(true, false, false, true, address(s_wrapper)); - emit Withdrawn(LINK_WHALE, paid); - s_wrapper.withdraw(LINK_WHALE); - assertEq(s_linkToken.balanceOf(LINK_WHALE), priorWhaleBalance + paid); - assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); - } - - function testRequestRandomWordsLINKWrapperFallbackWeiPerUnitLinkUsed() public { - // Fund subscription. - s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID())); - s_linkToken.transfer(address(s_consumer), 10 ether); - - // Set the link feed to be stale. - (, , , uint32 stalenessSeconds, , , , , ) = s_testCoordinator.s_config(); - int256 fallbackWeiPerUnitLink = s_testCoordinator.s_fallbackWeiPerUnitLink(); - (uint80 roundId, int256 answer, uint256 startedAt, , ) = s_linkNativeFeed.latestRoundData(); - uint256 timestamp = block.timestamp - stalenessSeconds - 1; - s_linkNativeFeed.updateRoundData(roundId, answer, timestamp, startedAt); - - // Request randomness from wrapper. - uint32 callbackGasLimit = 1_000_000; - (uint256 requestId, uint256 preSeed) = s_testCoordinator.computeRequestIdExternal( - vrfKeyHash, - address(s_wrapper), - s_wrapper.SUBSCRIPTION_ID(), - 1 - ); - uint32 EIP150Overhead = callbackGasLimit / 63 + 1; - vm.expectEmit(true, true, true, true); - emit FallbackWeiPerUnitLinkUsed(requestId, fallbackWeiPerUnitLink); - emit RandomWordsRequested( - vrfKeyHash, - requestId, - preSeed, - s_wrapper.SUBSCRIPTION_ID(), // subId - 0, // minConfirmations - callbackGasLimit + EIP150Overhead + wrapperGasOverhead, // callbackGasLimit - accounts for EIP 150 - 1, // numWords - VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false})), // extraArgs - address(s_wrapper) // requester - ); - s_consumer.makeRequest(callbackGasLimit, 0, 1); - } - - function testRequestRandomWordsInNativeNotConfigured() public { - VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - - vm.expectRevert("wrapper is not configured"); - wrapper.requestRandomWordsInNative(500_000, 0, 1, ""); - } - - function testRequestRandomWordsInNativeDisabled() public { - s_wrapper.disable(); - - vm.expectRevert("wrapper is disabled"); - s_wrapper.requestRandomWordsInNative(500_000, 0, 1, ""); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol deleted file mode 100644 index 96f1484..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Arbitrum.t.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5_Arbitrum} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Arbitrum.sol"; -import {VRFV2PlusWrapper_Arbitrum} from "../dev/VRFV2PlusWrapper_Arbitrum.sol"; -import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; - -contract VRFV2PlusWrapperArbitrumTest is BaseTest { - /// @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); - - address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint256 private s_wrapperSubscriptionId; - - ExposedVRFCoordinatorV2_5_Arbitrum private s_testCoordinator; - MockLinkToken private s_linkToken; - MockV3Aggregator private s_linkNativeFeed; - VRFV2PlusWrapper_Arbitrum private s_wrapper; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(DEPLOYER, 10_000 ether); - vm.stopPrank(); - vm.startPrank(DEPLOYER); - - // Deploy link token and link/native feed. - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Deploy coordinator. - s_testCoordinator = new ExposedVRFCoordinatorV2_5_Arbitrum(address(0)); - - // Create subscription for all future wrapper contracts. - s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); - - // Deploy wrapper. - s_wrapper = new VRFV2PlusWrapper_Arbitrum( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - - // Configure the wrapper. - s_wrapper.setConfig( - 100_000, // wrapper gas overhead - 200_000, // coordinator gas overhead native - 220_000, // coordinator gas overhead link - 500, // coordinator gas overhead per word - 15, // native premium percentage, - 10, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000 // fulfillmentFlatFeeLinkDiscountPPM - ); - - // Add wrapper as a consumer to the wrapper's subscription. - s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); - } - - function _mockArbGasGetPricesInWei() internal { - // return gas prices in wei, assuming the specified aggregator is used - // ( - // per L2 tx, - // per L1 calldata unit, (zero byte = 4 units, nonzero byte = 16 units) - // per storage allocation, - // per ArbGas base, - // per ArbGas congestion, - // per ArbGas total - // ) - vm.mockCall( - ARBGAS_ADDR, - abi.encodeWithSelector(ARBGAS.getPricesInWei.selector), - abi.encode(1 gwei, 250 gwei, 1 gwei, 1 gwei, 1 gwei, 1 gwei) - ); - } - - function test_calculateRequestPriceNativeOnArbitrumWrapper() public { - vm.txGasPrice(1 gwei); - _mockArbGasGetPricesInWei(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 5.01483 * 1e17, 1e15); - } - - function test_calculateRequestPriceLinkOnArbitrumWrapper() public { - vm.txGasPrice(1 gwei); - _mockArbGasGetPricesInWei(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 8.02846 * 1e17, 1e15); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol deleted file mode 100644 index ba77686..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol +++ /dev/null @@ -1,388 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; -import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; -import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; -import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; - -contract VRFV2PlusWrapper_MigrationTest is BaseTest { - address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - uint256 internal constant DEFAULT_NATIVE_FUNDING = 7 ether; // 7 ETH - uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 ETH - bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint32 private wrapperGasOverhead = 10_000; - uint32 private coordinatorGasOverheadNative = 20_000; - uint32 private coordinatorGasOverheadLink = 40_000; - uint256 private s_wrapperSubscriptionId; - - ExposedVRFCoordinatorV2_5 private s_testCoordinator; - MockLinkToken private s_linkToken; - MockV3Aggregator private s_linkNativeFeed; - VRFV2PlusWrapper private s_wrapper; - VRFV2PlusWrapperConsumerExample private s_consumer; - - VRFCoordinatorV2Plus_V2Example private s_newCoordinator; - - event CoordinatorRegistered(address coordinatorAddress); - event MigrationCompleted(address newCoordinator, uint256 subId); - event WrapperRequestMade(uint256 indexed requestId, uint256 paid); - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(LINK_WHALE, 10_000 ether); - changePrank(LINK_WHALE); - - // Deploy link token and link/native feed. - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Deploy coordinator. - s_testCoordinator = new ExposedVRFCoordinatorV2_5(address(0)); - - // Create subscription for all future wrapper contracts. - s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); - - // Deploy wrapper. - s_wrapper = new VRFV2PlusWrapper( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - - // Add wrapper as a consumer to the wrapper's subscription. - s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); - - // Deploy consumer. - s_consumer = new VRFV2PlusWrapperConsumerExample(address(s_wrapper)); - - // Configure the coordinator. - s_testCoordinator.setLINKAndLINKNativeFeed(address(s_linkToken), address(s_linkNativeFeed)); - setConfigCoordinator(); - setConfigWrapper(); - - s_testCoordinator.s_config(); - - // Data structures for Migrateable Wrapper - s_newCoordinator = new VRFCoordinatorV2Plus_V2Example(address(0), address(s_testCoordinator)); - vm.expectEmit( - false, // no first indexed topic - false, // no second indexed topic - false, // no third indexed topic - true // check data (target coordinator address) - ); - address newCoordinatorAddr = address(s_newCoordinator); - emit CoordinatorRegistered(newCoordinatorAddr); - s_testCoordinator.registerMigratableCoordinator(newCoordinatorAddr); - assertTrue(s_testCoordinator.isTargetRegisteredExternal(newCoordinatorAddr)); - } - - function setConfigCoordinator() internal { - s_testCoordinator.setConfig( - 0, // minRequestConfirmations - 2_500_000, // maxGasLimit - 1, // stalenessSeconds - 50_000, // gasAfterPaymentCalculation - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000, // fulfillmentFlatFeeLinkDiscountPPM - 15, // nativePremiumPercentage - 10 // linkPremiumPercentage - ); - } - - function setConfigWrapper() internal { - s_wrapper.setConfig( - wrapperGasOverhead, // wrapper gas overhead - coordinatorGasOverheadNative, // coordinator gas overhead native - coordinatorGasOverheadLink, // coordinator gas overhead link - 0, // coordinator gas overhead per word - 0, // native premium percentage, - 0, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 0, // fulfillmentFlatFeeNativePPM - 0 // fulfillmentFlatFeeLinkDiscountPPM - ); - ( - , - , - , - , - uint32 _wrapperGasOverhead, - uint32 _coordinatorGasOverheadNative, - uint32 _coordinatorGasOverheadLink, - uint16 _coordinatorGasOverheadPerWord, - uint8 _coordinatorNativePremiumPercentage, - uint8 _coordinatorLinkPremiumPercentage, - bytes32 _keyHash, - uint8 _maxNumWords - ) = s_wrapper.getConfig(); - assertEq(_wrapperGasOverhead, wrapperGasOverhead); - assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative); - assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink); - assertEq(0, _coordinatorGasOverheadPerWord); - assertEq(0, _coordinatorNativePremiumPercentage); - assertEq(0, _coordinatorLinkPremiumPercentage); - assertEq(vrfKeyHash, _keyHash); - assertEq(10, _maxNumWords); - } - - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint256 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - bytes extraArgs, - address indexed sender - ); - - // IVRFV2PlusWrapper events - event Withdrawn(address indexed to, uint256 amount); - event NativeWithdrawn(address indexed to, uint256 amount); - - // IVRFMigratableConsumerV2Plus events - event CoordinatorSet(address vrfCoordinator); - - function testMigrateWrapperLINKPayment() public { - s_linkToken.transfer(address(s_consumer), DEFAULT_LINK_FUNDING); - - assertEq(uint256(s_wrapperSubscriptionId), uint256(s_wrapper.SUBSCRIPTION_ID())); - address oldCoordinatorAddr = address(s_testCoordinator); - assertEq(address(oldCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); - - // Fund subscription with native and LINK payment to check - // if funds are transferred to new subscription after call - // migration to new coordinator - s_linkToken.transferAndCall(oldCoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(s_wrapperSubscriptionId)); - s_testCoordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(s_wrapperSubscriptionId); - - // subscription exists in V1 coordinator before migration - ( - uint96 balance, - uint96 nativeBalance, - uint64 reqCount, - address owner, - address[] memory consumers - ) = s_testCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(reqCount, 0); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(owner, address(LINK_WHALE)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_wrapper)); - - // Update wrapper to point to the new coordinator - vm.expectEmit( - false, // no first indexed field - false, // no second indexed field - false, // no third indexed field - true // check data fields - ); - address newCoordinatorAddr = address(s_newCoordinator); - emit MigrationCompleted(newCoordinatorAddr, s_wrapperSubscriptionId); - - // old coordinator has to migrate wrapper's subscription to the new coordinator - s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); - assertEq(address(newCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); - - // subscription no longer exists in v1 coordinator after migration - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_testCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(s_testCoordinator.s_totalBalance(), 0); - assertEq(s_testCoordinator.s_totalNativeBalance(), 0); - assertEq(s_linkToken.balanceOf(oldCoordinatorAddr), 0); - assertEq(oldCoordinatorAddr.balance, 0); - - // subscription exists in v2 coordinator - (balance, nativeBalance, reqCount, owner, consumers) = s_newCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(owner, address(LINK_WHALE)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_wrapper)); - assertEq(reqCount, 0); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(s_newCoordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); - assertEq(s_newCoordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - assertEq(s_linkToken.balanceOf(newCoordinatorAddr), DEFAULT_LINK_FUNDING); - assertEq(newCoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); - - // calling migrate again on V1 coordinator should fail - vm.expectRevert(); - s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); - - // Request randomness from wrapper. - uint32 callbackGasLimit = 1_000_000; - uint256 wrapperCost = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); - vm.expectEmit(true, true, true, true); - emit WrapperRequestMade(1, wrapperCost); - uint256 requestId = s_consumer.makeRequest(callbackGasLimit, 0, 1); - assertEq(requestId, 1); - - (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); - uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2; - uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice); - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0); - assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio - assertEq(uint256(paid), wrapperCostEstimate); - assertEq(wrapperCostEstimate, wrapperCostCalculation); - assertEq(fulfilled, false); - assertEq(native, false); - assertEq(s_linkToken.balanceOf(address(s_consumer)), DEFAULT_LINK_FUNDING - expectedPaid); - - (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); - assertEq(gasLimit, callbackGasLimit); - - vm.stopPrank(); - - vm.startPrank(newCoordinatorAddr); - - uint256[] memory words = new uint256[](1); - words[0] = 123; - s_wrapper.rawFulfillRandomWords(requestId, words); - (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); - assertEq(nowFulfilled, true); - assertEq(storedWords[0], 123); - - vm.stopPrank(); - - /// Withdraw funds from wrapper. - vm.startPrank(LINK_WHALE); - uint256 priorWhaleBalance = s_linkToken.balanceOf(LINK_WHALE); - vm.expectEmit(true, false, false, true, address(s_wrapper)); - emit Withdrawn(LINK_WHALE, paid); - s_wrapper.withdraw(LINK_WHALE); - assertEq(s_linkToken.balanceOf(LINK_WHALE), priorWhaleBalance + paid); - assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); - - vm.stopPrank(); - } - - function testMigrateWrapperNativePayment() public { - vm.deal(address(s_consumer), DEFAULT_NATIVE_FUNDING); - - assertEq(uint256(s_wrapperSubscriptionId), uint256(s_wrapper.SUBSCRIPTION_ID())); - address oldCoordinatorAddr = address(s_testCoordinator); - assertEq(address(oldCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); - - // Fund subscription with native and LINK payment to check - // if funds are transferred to new subscription after call - // migration to new coordinator - s_linkToken.transferAndCall(oldCoordinatorAddr, DEFAULT_LINK_FUNDING, abi.encode(s_wrapperSubscriptionId)); - s_testCoordinator.fundSubscriptionWithNative{value: DEFAULT_NATIVE_FUNDING}(s_wrapperSubscriptionId); - - // subscription exists in V1 coordinator before migration - ( - uint96 balance, - uint96 nativeBalance, - uint64 reqCount, - address owner, - address[] memory consumers - ) = s_testCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(reqCount, 0); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(owner, address(LINK_WHALE)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_wrapper)); - - // Update wrapper to point to the new coordinator - vm.expectEmit( - false, // no first indexed field - false, // no second indexed field - false, // no third indexed field - true // check data fields - ); - address newCoordinatorAddr = address(s_newCoordinator); - emit MigrationCompleted(newCoordinatorAddr, s_wrapperSubscriptionId); - - // old coordinator has to migrate wrapper's subscription to the new coordinator - s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); - assertEq(address(newCoordinatorAddr), address(s_wrapper.s_vrfCoordinator())); - - // subscription no longer exists in v1 coordinator after migration - vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - s_testCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(s_testCoordinator.s_totalBalance(), 0); - assertEq(s_testCoordinator.s_totalNativeBalance(), 0); - assertEq(s_linkToken.balanceOf(oldCoordinatorAddr), 0); - assertEq(oldCoordinatorAddr.balance, 0); - - // subscription exists in v2 coordinator - (balance, nativeBalance, reqCount, owner, consumers) = s_newCoordinator.getSubscription(s_wrapperSubscriptionId); - assertEq(owner, address(LINK_WHALE)); - assertEq(consumers.length, 1); - assertEq(consumers[0], address(s_wrapper)); - assertEq(reqCount, 0); - assertEq(balance, DEFAULT_LINK_FUNDING); - assertEq(nativeBalance, DEFAULT_NATIVE_FUNDING); - assertEq(s_newCoordinator.s_totalLinkBalance(), DEFAULT_LINK_FUNDING); - assertEq(s_newCoordinator.s_totalNativeBalance(), DEFAULT_NATIVE_FUNDING); - assertEq(s_linkToken.balanceOf(newCoordinatorAddr), DEFAULT_LINK_FUNDING); - assertEq(newCoordinatorAddr.balance, DEFAULT_NATIVE_FUNDING); - - // calling migrate again on V1 coordinator should fail - vm.expectRevert(); - s_testCoordinator.migrate(s_wrapperSubscriptionId, newCoordinatorAddr); - - // Request randomness from wrapper. - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 1; - vm.expectEmit(true, true, true, true); - uint256 wrapperCost = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); - emit WrapperRequestMade(1, wrapperCost); - uint256 requestId = s_consumer.makeRequestNative(callbackGasLimit, 0, numWords); - assertEq(requestId, 1); - - (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); - uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative; - uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice); - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0); - assertEq(paid, expectedPaid); - assertEq(uint256(paid), wrapperNativeCostEstimate); - assertEq(wrapperNativeCostEstimate, wrapperCostCalculation); - assertEq(fulfilled, false); - assertEq(native, true); - assertEq(address(s_consumer).balance, DEFAULT_NATIVE_FUNDING - expectedPaid); - - (, uint256 gasLimit, ) = s_wrapper.s_callbacks(requestId); - assertEq(gasLimit, callbackGasLimit); - - vm.stopPrank(); - - vm.startPrank(newCoordinatorAddr); - - uint256[] memory words = new uint256[](1); - words[0] = 123; - s_wrapper.rawFulfillRandomWords(requestId, words); - (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); - assertEq(nowFulfilled, true); - assertEq(storedWords[0], 123); - - vm.stopPrank(); - - // Withdraw funds from wrapper. - vm.startPrank(LINK_WHALE); - uint256 priorWhaleBalance = LINK_WHALE.balance; - vm.expectEmit(true, false, false, true, address(s_wrapper)); - emit NativeWithdrawn(LINK_WHALE, paid); - s_wrapper.withdrawNative(LINK_WHALE); - assertEq(LINK_WHALE.balance, priorWhaleBalance + paid); - assertEq(address(s_wrapper).balance, 0); - - vm.stopPrank(); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol deleted file mode 100644 index a8a97a5..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Optimism.t.sol +++ /dev/null @@ -1,216 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.19; - -import {BaseTest} from "./BaseTest.t.sol"; -import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5_Optimism} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5_Optimism.sol"; -import {VRFV2PlusWrapper_Optimism} from "../dev/VRFV2PlusWrapper_Optimism.sol"; -import {OptimismL1Fees} from "../dev/OptimismL1Fees.sol"; -import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; -import {VmSafe} from "forge-std/Vm.sol"; - -contract VRFV2PlusWrapperOptimismAndBaseTest is BaseTest { - /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); - OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); - - address internal constant DEPLOYER = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint256 private s_wrapperSubscriptionId; - - ExposedVRFCoordinatorV2_5_Optimism private s_testCoordinator; - MockLinkToken private s_linkToken; - MockV3Aggregator private s_linkNativeFeed; - VRFV2PlusWrapper_Optimism private s_wrapper; - - /// @dev Option 1: getL1Fee() function from predeploy GasPriceOracle contract with the fulfillment calldata payload - /// @dev This option is only available for the Coordinator contract - uint8 internal constant L1_GAS_FEES_MODE = 0; - /// @dev Option 2: our own implementation of getL1Fee() function (Ecotone version) with projected - /// @dev fulfillment calldata payload (number of non-zero bytes estimated based on historical data) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_CALLDATA_GAS_COST_MODE = 1; - /// @dev Option 3: getL1FeeUpperBound() function from predeploy GasPriceOracle contract (available after Fjord upgrade) - /// @dev This option is available for the Coordinator and the Wrapper contract - uint8 internal constant L1_GAS_FEES_UPPER_BOUND_MODE = 2; - - function setUp() public override { - BaseTest.setUp(); - - // Fund our users. - vm.roll(1); - vm.deal(DEPLOYER, 10_000 ether); - vm.stopPrank(); - vm.startPrank(DEPLOYER); - - // Deploy link token and link/native feed. - s_linkToken = new MockLinkToken(); - s_linkNativeFeed = new MockV3Aggregator(18, 500000000000000000); // .5 ETH (good for testing) - - // Deploy coordinator. - s_testCoordinator = new ExposedVRFCoordinatorV2_5_Optimism(address(0)); - - // Create subscription for all future wrapper contracts. - s_wrapperSubscriptionId = s_testCoordinator.createSubscription(); - - // Deploy wrapper. - s_wrapper = new VRFV2PlusWrapper_Optimism( - address(s_linkToken), - address(s_linkNativeFeed), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - - // Configure the wrapper. - s_wrapper.setConfig( - 100_000, // wrapper gas overhead - 200_000, // coordinator gas overhead native - 220_000, // coordinator gas overhead link - 500, // coordinator gas overhead per word - 15, // native premium percentage, - 10, // link premium percentage - vrfKeyHash, // keyHash - 10, // max number of words, - 1, // stalenessSeconds - 50000000000000000, // fallbackWeiPerUnitLink - 500_000, // fulfillmentFlatFeeNativePPM - 100_000 // fulfillmentFlatFeeLinkDiscountPPM - ); - - // Add wrapper as a consumer to the wrapper's subscription. - s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); - } - - function _mockGasOraclePriceGetL1FeeUpperBoundCall() internal { - // fullfillment tx calldata size = 772 bytes - // RLP-encoded unsigned tx headers (approx padding size) = 71 bytes - // total = 843 bytes - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(OVM_GasPriceOracle.getL1FeeUpperBound.selector, 843), - abi.encode(uint256(0.02 ether)) - ); - } - - function _mockGasOraclePriceFeeMethods() internal { - // these values are taken from an example transaction on Base Sepolia - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("l1BaseFee()"))), - abi.encode(64273426165) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("baseFeeScalar()"))), - abi.encode(1101) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("blobBaseFeeScalar()"))), - abi.encode(659851) - ); - vm.mockCall( - OVM_GASPRICEORACLE_ADDR, - abi.encodeWithSelector(bytes4(keccak256("blobBaseFee()"))), - abi.encode(2126959908362) - ); - vm.mockCall(OVM_GASPRICEORACLE_ADDR, abi.encodeWithSelector(bytes4(keccak256("decimals()"))), abi.encode(6)); - } - - function _checkL1FeeCalculationSetEmittedLogs(uint8 expectedMode, uint8 expectedCoefficient) internal { - VmSafe.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 1); - assertEq(entries[0].topics.length, 1); - assertEq(entries[0].topics[0], keccak256("L1FeeCalculationSet(uint8,uint8)")); - (uint8 actualMode, uint8 actualCoefficient) = abi.decode(entries[0].data, (uint8, uint8)); - assertEq(expectedMode, actualMode); - assertEq(expectedCoefficient, actualCoefficient); - } - - function test_setL1FeePaymentMethodOnOptimismWrapper() public { - // check default settings after contract deployment - assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); - assertEq(100, uint256(s_wrapper.s_l1FeeCoefficient())); - - vm.recordLogs(); - s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 70); - - _checkL1FeeCalculationSetEmittedLogs(L1_CALLDATA_GAS_COST_MODE, 70); - assertEq(uint256(L1_CALLDATA_GAS_COST_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); - assertEq(70, uint256(s_wrapper.s_l1FeeCoefficient())); - - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 30); - - _checkL1FeeCalculationSetEmittedLogs(L1_GAS_FEES_UPPER_BOUND_MODE, 30); - assertEq(uint256(L1_GAS_FEES_UPPER_BOUND_MODE), uint256(s_wrapper.s_l1FeeCalculationMode())); - assertEq(30, uint256(s_wrapper.s_l1FeeCoefficient())); - - // VRFWrapper doesn't support this mode - vm.expectRevert( - abi.encodeWithSelector(VRFV2PlusWrapper_Optimism.UnsupportedL1FeeCalculationMode.selector, L1_GAS_FEES_MODE) - ); - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_MODE, 100); - - // should revert if invalid L1 fee calculation mode is used - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCalculationMode.selector, 6)); - s_wrapper.setL1FeeCalculation(6, 100); - - // should revert if invalid coefficient is used (equal to zero, this would disable L1 fees completely) - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 0)); - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 0); - - // should revert if invalid coefficient is used (larger than 100%) - vm.expectRevert(abi.encodeWithSelector(OptimismL1Fees.InvalidL1FeeCoefficient.selector, 101)); - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 101); - } - - function test_calculateRequestPriceNativeOnOptimismWrapper_UsingCalldataCostCall() public { - s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 80); - - vm.txGasPrice(1 gwei); - _mockGasOraclePriceFeeMethods(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 5.02575 * 1e17, 1e15); - } - - function test_calculateRequestPriceLinkOnOptimismWrapper_UsingCalldataCostCall() public { - s_wrapper.setL1FeeCalculation(L1_CALLDATA_GAS_COST_MODE, 80); - - vm.txGasPrice(1 gwei); - _mockGasOraclePriceFeeMethods(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 8.04934 * 1e17, 1e15); - } - - function test_calculateRequestPriceNativeOnOptimismWrapper_UsingGetL1FeeUpperBoundCall() public { - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 60); - - vm.txGasPrice(1 gwei); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 5.15283 * 1e17, 1e15); - } - - function test_calculateRequestPriceLinkOnOptimismWrapper_UsingGetL1FeeUpperBoundCall() public { - s_wrapper.setL1FeeCalculation(L1_GAS_FEES_UPPER_BOUND_MODE, 60); - - vm.txGasPrice(1 gwei); - _mockGasOraclePriceGetL1FeeUpperBoundCall(); - uint32 callbackGasLimit = 1_000_000; - uint32 numWords = 5; - uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, numWords); - // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(wrapperCostCalculation, 8.29246 * 1e17, 1e15); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol deleted file mode 100644 index 16a157e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/ChainSpecificUtilHelper.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; - -/// @dev A helper contract that exposes ChainSpecificUtil methods for testing -contract ChainSpecificUtilHelper { - function getBlockhash(uint64 blockNumber) external view returns (bytes32) { - return ChainSpecificUtil._getBlockhash(blockNumber); - } - - function getBlockNumber() external view returns (uint256) { - return ChainSpecificUtil._getBlockNumber(); - } - - function getCurrentTxL1GasFees(string memory txCallData) external view returns (uint256) { - return ChainSpecificUtil._getCurrentTxL1GasFees(bytes(txCallData)); - } - - function getL1CalldataGasCost(uint256 calldataSize) external view returns (uint256) { - return ChainSpecificUtil._getL1CalldataGasCost(calldataSize); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol deleted file mode 100644 index 1ceb789..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/Counter.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -contract Counter { - error AlwaysRevert(); - - uint256 public count = 0; - - function increment() public returns (uint256) { - count += 1; - return count; - } - - function reset() public { - count = 0; - } - - function alwaysRevert() public pure { - revert AlwaysRevert(); - } - - function alwaysRevertWithString() public pure { - revert("always revert"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol deleted file mode 100644 index eaac0be..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumer.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFConsumerBase} from "../VRFConsumerBase.sol"; - -contract VRFConsumer is VRFConsumerBase { - uint256 public randomnessOutput; - bytes32 public requestId; - - constructor( - address vrfCoordinator, - address link - ) - // solhint-disable-next-line no-empty-blocks - VRFConsumerBase(vrfCoordinator, link) - { - /* empty */ - } - - function fulfillRandomness(bytes32 /* requestId */, uint256 randomness) internal override { - randomnessOutput = randomness; - requestId = requestId; - } - - function doRequestRandomness(bytes32 keyHash, uint256 fee) external returns (bytes32) { - return requestRandomness(keyHash, fee); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol deleted file mode 100644 index e2502fa..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -contract VRFConsumerV2 is VRFConsumerBaseV2 { - uint256[] public s_randomWords; - uint256 public s_requestId; - VRFCoordinatorV2Interface internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - uint64 public s_subId; - uint256 public s_gasAvailable; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - } - - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness( - bytes32 keyHash, - uint64 subId, - uint16 minReqConfs, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256) { - s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol deleted file mode 100644 index f0acade..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2Plus.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../dev/interfaces/IVRFCoordinatorV2Plus.sol"; -import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; -import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; - -contract VRFConsumerV2Plus is VRFConsumerBaseV2Plus { - uint256[] public s_randomWords; - uint256 public s_requestId; - IVRFCoordinatorV2Plus internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - uint256 public s_subId; - uint256 public s_gasAvailable; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2Plus(vrfCoordinator) { - COORDINATOR = IVRFCoordinatorV2Plus(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - } - - function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness(VRFV2PlusClient.RandomWordsRequest calldata req) external returns (uint256) { - s_requestId = COORDINATOR.requestRandomWords(req); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol deleted file mode 100644 index 930cebf..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFConsumerV2UpgradeableExample.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2Upgradeable} from "../dev/VRFConsumerBaseV2Upgradeable.sol"; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - -contract VRFConsumerV2UpgradeableExample is Initializable, VRFConsumerBaseV2Upgradeable { - uint256[] public s_randomWords; - uint256 public s_requestId; - VRFCoordinatorV2Interface public COORDINATOR; - LinkTokenInterface public LINKTOKEN; - uint64 public s_subId; - uint256 public s_gasAvailable; - - function initialize(address _vrfCoordinator, address _link) public initializer { - __VRFConsumerBaseV2_init(_vrfCoordinator); - COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); - LINKTOKEN = LinkTokenInterface(_link); - } - - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness( - bytes32 keyHash, - uint64 subId, - uint16 minReqConfs, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256) { - s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol deleted file mode 100644 index 5774b77..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorTestV2.sol +++ /dev/null @@ -1,840 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {BlockhashStoreInterface} from "../interfaces/BlockhashStoreInterface.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {TypeAndVersionInterface} from "../../interfaces/TypeAndVersionInterface.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; -import {VRF} from "../VRF.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -contract VRFCoordinatorTestV2 is - VRF, - ConfirmedOwner, - TypeAndVersionInterface, - VRFCoordinatorV2Interface, - IERC677Receiver -{ - LinkTokenInterface public immutable LINK; - AggregatorV3Interface public immutable LINK_ETH_FEED; - BlockhashStoreInterface public immutable BLOCKHASH_STORE; - - // We need to maintain a list of consuming addresses. - // This bound ensures we are able to loop over them as needed. - // Should a user require more consumers, they can use multiple subscriptions. - uint16 public constant MAX_CONSUMERS = 100; - - error TooManyConsumers(); - error InsufficientBalance(); - error InvalidConsumer(uint64 subId, address consumer); - error InvalidSubscription(); - error OnlyCallableFromLink(); - error InvalidCalldata(); - error MustBeSubOwner(address owner); - error PendingRequestExists(); - error MustBeRequestedOwner(address proposedOwner); - error BalanceInvariantViolated(uint256 internalBalance, uint256 externalBalance); // Should never happen - event FundsRecovered(address to, uint256 amount); - // We use the subscription struct (1 word) - // at fulfillment time. - struct Subscription { - // There are only 1e9*1e18 = 1e27 juels in existence, so the balance can fit in uint96 (2^96 ~ 7e28) - uint96 balance; // Common link balance used for all consumer requests. - uint64 reqCount; // For fee tiers - } - // We use the config for the mgmt APIs - struct SubscriptionConfig { - address owner; // Owner can fund/withdraw/cancel the sub. - address requestedOwner; // For safely transferring sub ownership. - // Maintains the list of keys in s_consumers. - // We do this for 2 reasons: - // 1. To be able to clean up all keys from s_consumers when canceling a subscription. - // 2. To be able to return the list of all consumers in getSubscription. - // Note that we need the s_consumers map to be able to directly check if a - // consumer is valid without reading all the consumers from storage. - address[] consumers; - } - // Note a nonce of 0 indicates an the consumer is not assigned to that subscription. - mapping(address => mapping(uint64 => uint64)) /* consumer */ /* subId */ /* nonce */ private s_consumers; - mapping(uint64 => SubscriptionConfig) /* subId */ /* subscriptionConfig */ private s_subscriptionConfigs; - mapping(uint64 => Subscription) /* subId */ /* subscription */ private s_subscriptions; - // We make the sub count public so that its possible to - // get all the current subscriptions via getSubscription. - uint64 private s_currentSubId; - // s_totalBalance tracks the total link sent to/from - // this contract through onTokenTransfer, cancelSubscription and oracleWithdraw. - // A discrepancy with this contract's link balance indicates someone - // sent tokens using transfer and so we may need to use recoverFunds. - uint96 private s_totalBalance; - event SubscriptionCreated(uint64 indexed subId, address owner); - event SubscriptionFunded(uint64 indexed subId, uint256 oldBalance, uint256 newBalance); - event SubscriptionConsumerAdded(uint64 indexed subId, address consumer); - event SubscriptionConsumerRemoved(uint64 indexed subId, address consumer); - event SubscriptionCanceled(uint64 indexed subId, address to, uint256 amount); - event SubscriptionOwnerTransferRequested(uint64 indexed subId, address from, address to); - event SubscriptionOwnerTransferred(uint64 indexed subId, address from, address to); - - // Set this maximum to 200 to give us a 56 block window to fulfill - // the request before requiring the block hash feeder. - uint16 public constant MAX_REQUEST_CONFIRMATIONS = 200; - uint32 public constant MAX_NUM_WORDS = 500; - // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) - // and some arithmetic operations. - uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); - error GasLimitTooBig(uint32 have, uint32 want); - error NumWordsTooBig(uint32 have, uint32 want); - error ProvingKeyAlreadyRegistered(bytes32 keyHash); - error NoSuchProvingKey(bytes32 keyHash); - error InvalidLinkWeiPrice(int256 linkWei); - error InsufficientGasForConsumer(uint256 have, uint256 want); - error NoCorrespondingRequest(); - error IncorrectCommitment(); - error BlockhashNotInStore(uint256 blockNum); - error PaymentTooLarge(); - error Reentrant(); - - struct RequestCommitment { - uint64 blockNum; - uint64 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - } - mapping(bytes32 => address) /* keyHash */ /* oracle */ private s_provingKeys; - bytes32[] private s_provingKeyHashes; - mapping(address => uint96) /* oracle */ /* LINK balance */ private s_withdrawableTokens; - mapping(uint256 => bytes32) /* requestID */ /* commitment */ private s_requestCommitments; - event ProvingKeyRegistered(bytes32 keyHash, address indexed oracle); - event ProvingKeyDeregistered(bytes32 keyHash, address indexed oracle); - event RandomWordsRequested( - bytes32 indexed keyHash, - uint256 requestId, - uint256 preSeed, - uint64 indexed subId, - uint16 minimumRequestConfirmations, - uint32 callbackGasLimit, - uint32 numWords, - address indexed sender - ); - event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bool success); - - struct Config { - uint16 minimumRequestConfirmations; - uint32 maxGasLimit; - // Reentrancy protection. - bool reentrancyLock; - // stalenessSeconds is how long before we consider the feed price to be stale - // and fallback to fallbackWeiPerUnitLink. - uint32 stalenessSeconds; - // Gas to cover oracle payment after we calculate the payment. - // We make it configurable in case those operations are repriced. - uint32 gasAfterPaymentCalculation; - } - int256 private s_fallbackWeiPerUnitLink; - Config private s_config; - FeeConfig private s_feeConfig; - struct FeeConfig { - // Flat fee charged per fulfillment in millionths of link - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeLinkPPMTier1; - uint32 fulfillmentFlatFeeLinkPPMTier2; - uint32 fulfillmentFlatFeeLinkPPMTier3; - uint32 fulfillmentFlatFeeLinkPPMTier4; - uint32 fulfillmentFlatFeeLinkPPMTier5; - uint24 reqsForTier2; - uint24 reqsForTier3; - uint24 reqsForTier4; - uint24 reqsForTier5; - } - event ConfigSet( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig feeConfig - ); - - constructor(address link, address blockhashStore, address linkEthFeed) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(link); - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); - } - - /** - * @notice Registers a proving key to an oracle. - * @param oracle address of the oracle - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function registerProvingKey(address oracle, uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh] != address(0)) { - revert ProvingKeyAlreadyRegistered(kh); - } - s_provingKeys[kh] = oracle; - s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh, oracle); - } - - /** - * @notice Deregisters a proving key to an oracle. - * @param publicProvingKey key that oracle can use to submit vrf fulfillments - */ - function deregisterProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { - bytes32 kh = hashOfKey(publicProvingKey); - address oracle = s_provingKeys[kh]; - if (oracle == address(0)) { - revert NoSuchProvingKey(kh); - } - delete s_provingKeys[kh]; - for (uint256 i = 0; i < s_provingKeyHashes.length; i++) { - if (s_provingKeyHashes[i] == kh) { - bytes32 last = s_provingKeyHashes[s_provingKeyHashes.length - 1]; - // Copy last element and overwrite kh to be deleted with it - s_provingKeyHashes[i] = last; - s_provingKeyHashes.pop(); - } - } - emit ProvingKeyDeregistered(kh, oracle); - } - - /** - * @notice Returns the proving key hash key associated with this public key - * @param publicKey the key to return the hash of - */ - function hashOfKey(uint256[2] memory publicKey) public pure returns (bytes32) { - return keccak256(abi.encode(publicKey)); - } - - /** - * @notice Sets the configuration of the vrfv2 coordinator - * @param minimumRequestConfirmations global min for request confirmations - * @param maxGasLimit global max for request gas limit - * @param stalenessSeconds if the eth/link feed is more stale then this, use the fallback price - * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement - * @param fallbackWeiPerUnitLink fallback eth/link price in the case of a stale feed - * @param feeConfig fee tier configuration - */ - function setConfig( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation, - int256 fallbackWeiPerUnitLink, - FeeConfig memory feeConfig - ) external onlyOwner { - if (minimumRequestConfirmations > MAX_REQUEST_CONFIRMATIONS) { - revert InvalidRequestConfirmations( - minimumRequestConfirmations, - minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - if (fallbackWeiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); - } - s_config = Config({ - minimumRequestConfirmations: minimumRequestConfirmations, - maxGasLimit: maxGasLimit, - stalenessSeconds: stalenessSeconds, - gasAfterPaymentCalculation: gasAfterPaymentCalculation, - reentrancyLock: false - }); - s_feeConfig = feeConfig; - s_fallbackWeiPerUnitLink = fallbackWeiPerUnitLink; - emit ConfigSet( - minimumRequestConfirmations, - maxGasLimit, - stalenessSeconds, - gasAfterPaymentCalculation, - fallbackWeiPerUnitLink, - s_feeConfig - ); - } - - function getConfig() - external - view - returns ( - uint16 minimumRequestConfirmations, - uint32 maxGasLimit, - uint32 stalenessSeconds, - uint32 gasAfterPaymentCalculation - ) - { - return ( - s_config.minimumRequestConfirmations, - s_config.maxGasLimit, - s_config.stalenessSeconds, - s_config.gasAfterPaymentCalculation - ); - } - - function getFeeConfig() - external - view - returns ( - uint32 fulfillmentFlatFeeLinkPPMTier1, - uint32 fulfillmentFlatFeeLinkPPMTier2, - uint32 fulfillmentFlatFeeLinkPPMTier3, - uint32 fulfillmentFlatFeeLinkPPMTier4, - uint32 fulfillmentFlatFeeLinkPPMTier5, - uint24 reqsForTier2, - uint24 reqsForTier3, - uint24 reqsForTier4, - uint24 reqsForTier5 - ) - { - return ( - s_feeConfig.fulfillmentFlatFeeLinkPPMTier1, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier2, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier3, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier4, - s_feeConfig.fulfillmentFlatFeeLinkPPMTier5, - s_feeConfig.reqsForTier2, - s_feeConfig.reqsForTier3, - s_feeConfig.reqsForTier4, - s_feeConfig.reqsForTier5 - ); - } - - function getTotalBalance() external view returns (uint256) { - return s_totalBalance; - } - - function getFallbackWeiPerUnitLink() external view returns (int256) { - return s_fallbackWeiPerUnitLink; - } - - /** - * @notice Owner cancel subscription, sends remaining link directly to the subscription owner. - * @param subId subscription id - * @dev notably can be called even if there are pending requests, outstanding ones may fail onchain - */ - function ownerCancelSubscription(uint64 subId) external onlyOwner { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - cancelSubscriptionHelper(subId, s_subscriptionConfigs[subId].owner); - } - - /** - * @notice Recover link sent with transfer instead of transferAndCall. - * @param to address to send link to - */ - function recoverFunds(address to) external onlyOwner { - uint256 externalBalance = LINK.balanceOf(address(this)); - uint256 internalBalance = uint256(s_totalBalance); - if (internalBalance > externalBalance) { - revert BalanceInvariantViolated(internalBalance, externalBalance); - } - if (internalBalance < externalBalance) { - uint256 amount = externalBalance - internalBalance; - LINK.transfer(to, amount); - emit FundsRecovered(to, amount); - } - // If the balances are equal, nothing to be done. - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function getRequestConfig() external view override returns (uint16, uint32, bytes32[] memory) { - return (s_config.minimumRequestConfirmations, s_config.maxGasLimit, s_provingKeyHashes); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function requestRandomWords( - bytes32 keyHash, - uint64 subId, - uint16 requestConfirmations, - uint32 callbackGasLimit, - uint32 numWords - ) external override nonReentrant returns (uint256) { - // Input validation using the subscription storage. - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // Its important to ensure that the consumer is in fact who they say they - // are, otherwise they could use someone else's subscription balance. - // A nonce of 0 indicates consumer is not allocated to the sub. - uint64 currentNonce = s_consumers[msg.sender][subId]; - if (currentNonce == 0) { - revert InvalidConsumer(subId, msg.sender); - } - // Input validation using the config storage word. - if ( - requestConfirmations < s_config.minimumRequestConfirmations || requestConfirmations > MAX_REQUEST_CONFIRMATIONS - ) { - revert InvalidRequestConfirmations( - requestConfirmations, - s_config.minimumRequestConfirmations, - MAX_REQUEST_CONFIRMATIONS - ); - } - // No lower bound on the requested gas limit. A user could request 0 - // and they would simply be billed for the proof verification and wouldn't be - // able to do anything with the random value. - if (callbackGasLimit > s_config.maxGasLimit) { - revert GasLimitTooBig(callbackGasLimit, s_config.maxGasLimit); - } - if (numWords > MAX_NUM_WORDS) { - revert NumWordsTooBig(numWords, MAX_NUM_WORDS); - } - // Note we do not check whether the keyHash is valid to save gas. - // The consequence for users is that they can send requests - // for invalid keyHashes which will simply not be fulfilled. - uint64 nonce = currentNonce + 1; - (uint256 requestId, uint256 preSeed) = computeRequestId(keyHash, msg.sender, subId, nonce); - - s_requestCommitments[requestId] = keccak256( - abi.encode(requestId, block.number, subId, callbackGasLimit, numWords, msg.sender) - ); - emit RandomWordsRequested( - keyHash, - requestId, - preSeed, - subId, - requestConfirmations, - callbackGasLimit, - numWords, - msg.sender - ); - s_consumers[msg.sender][subId] = nonce; - - return requestId; - } - - /** - * @notice Get request commitment - * @param requestId id of request - * @dev used to determine if a request is fulfilled or not - */ - function getCommitment(uint256 requestId) external view returns (bytes32) { - return s_requestCommitments[requestId]; - } - - function computeRequestId( - bytes32 keyHash, - address sender, - uint64 subId, - uint64 nonce - ) private pure returns (uint256, uint256) { - uint256 preSeed = uint256(keccak256(abi.encode(keyHash, sender, subId, nonce))); - return (uint256(keccak256(abi.encode(keyHash, preSeed))), preSeed); - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available. - */ - function callWithExactGas(uint256 gasAmount, address target, bytes memory data) private returns (bool success) { - // solhint-disable-next-line no-inline-assembly - assembly { - let g := gas() - // Compute g -= GAS_FOR_CALL_EXACT_CHECK and check for underflow - // The gas actually passed to the callee is min(gasAmount, 63//64*gas available). - // We want to ensure that we revert if gasAmount > 63//64*gas available - // as we do not want to provide them with less, however that check itself costs - // gas. GAS_FOR_CALL_EXACT_CHECK ensures we have at least enough gas to be able - // to revert if gasAmount > 63//64*gas available. - if lt(g, GAS_FOR_CALL_EXACT_CHECK) { - revert(0, 0) - } - g := sub(g, GAS_FOR_CALL_EXACT_CHECK) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - // call(gas,addr,value,argsOffset,argsLength,retOffset,retLength) - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - function getRandomnessFromProof( - Proof calldata proof, - RequestCommitment calldata rc - ) private view returns (bytes32 keyHash, uint256 requestId, uint256 randomness) { - keyHash = hashOfKey(proof.pk); - // Only registered proving keys are permitted. - address oracle = s_provingKeys[keyHash]; - if (oracle == address(0)) { - revert NoSuchProvingKey(keyHash); - } - requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); - bytes32 commitment = s_requestCommitments[requestId]; - if (commitment == 0) { - revert NoCorrespondingRequest(); - } - if ( - commitment != keccak256(abi.encode(requestId, rc.blockNum, rc.subId, rc.callbackGasLimit, rc.numWords, rc.sender)) - ) { - revert IncorrectCommitment(); - } - - bytes32 blockHash = blockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - blockHash = BLOCKHASH_STORE.getBlockhash(rc.blockNum); - if (blockHash == bytes32(0)) { - revert BlockhashNotInStore(rc.blockNum); - } - } - - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); - randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - } - - /* - * @notice Compute fee based on the request count - * @param reqCount number of requests - * @return feePPM fee in LINK PPM - */ - function getFeeTier(uint64 reqCount) public view returns (uint32) { - FeeConfig memory fc = s_feeConfig; - if (0 <= reqCount && reqCount <= fc.reqsForTier2) { - return fc.fulfillmentFlatFeeLinkPPMTier1; - } - if (fc.reqsForTier2 < reqCount && reqCount <= fc.reqsForTier3) { - return fc.fulfillmentFlatFeeLinkPPMTier2; - } - if (fc.reqsForTier3 < reqCount && reqCount <= fc.reqsForTier4) { - return fc.fulfillmentFlatFeeLinkPPMTier3; - } - if (fc.reqsForTier4 < reqCount && reqCount <= fc.reqsForTier5) { - return fc.fulfillmentFlatFeeLinkPPMTier4; - } - return fc.fulfillmentFlatFeeLinkPPMTier5; - } - - /* - * @notice Fulfill a randomness request - * @param proof contains the proof and randomness - * @param rc request commitment pre-image, committed to at request time - * @return payment amount billed to the subscription - * @dev simulated offchain to determine if sufficient balance is present to fulfill the request - */ - function fulfillRandomWords( - Proof calldata proof, - RequestCommitment calldata rc - ) external nonReentrant returns (uint96) { - uint256 startGas = gasleft(); - (bytes32 keyHash, uint256 requestId, uint256 randomness) = getRandomnessFromProof(proof, rc); - - uint256[] memory randomWords = new uint256[](rc.numWords); - for (uint256 i = 0; i < rc.numWords; i++) { - randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); - } - - delete s_requestCommitments[requestId]; - VRFConsumerBaseV2 v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - bool success = callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; - - // Increment the req count for fee tier selection. - uint64 reqCount = s_subscriptions[rc.subId].reqCount; - s_subscriptions[rc.subId].reqCount += 1; - - // We want to charge users exactly for how much gas they use in their callback. - // The gasAfterPaymentCalculation is meant to cover these additional operations where we - // decrement the subscription balance and increment the oracles withdrawable balance. - // We also add the flat link fee to the payment amount. - // Its specified in millionths of link, if s_config.fulfillmentFlatFeeLinkPPM = 1 - // 1 link / 1e6 = 1e18 juels / 1e6 = 1e12 juels. - uint96 payment = calculatePaymentAmount( - startGas, - s_config.gasAfterPaymentCalculation, - getFeeTier(reqCount), - tx.gasprice - ); - if (s_subscriptions[rc.subId].balance < payment) { - revert InsufficientBalance(); - } - s_subscriptions[rc.subId].balance -= payment; - s_withdrawableTokens[s_provingKeys[keyHash]] += payment; - // Include payment in the event for tracking costs. - emit RandomWordsFulfilled(requestId, randomness, payment, success); - return payment; - } - - // Get the amount of gas used for fulfillment - function calculatePaymentAmount( - uint256 startGas, - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeeLinkPPM, - uint256 weiPerUnitGas - ) internal view returns (uint96) { - int256 weiPerUnitLink; - weiPerUnitLink = getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // (1e18 juels/link) (wei/gas * gas) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft())) / - uint256(weiPerUnitLink); - uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); - if (paymentNoFee > (1e27 - fee)) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return uint96(paymentNoFee + fee); - } - - function getFeedData() private view returns (int256) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return weiPerUnitLink; - } - - /* - * @notice Oracle withdraw LINK earned through fulfilling requests - * @param recipient where to send the funds - * @param amount amount to withdraw - */ - function oracleWithdraw(address recipient, uint96 amount) external nonReentrant { - if (s_withdrawableTokens[msg.sender] < amount) { - revert InsufficientBalance(); - } - s_withdrawableTokens[msg.sender] -= amount; - s_totalBalance -= amount; - if (!LINK.transfer(recipient, amount)) { - revert InsufficientBalance(); - } - } - - function onTokenTransfer(address /* sender */, uint256 amount, bytes calldata data) external override nonReentrant { - if (msg.sender != address(LINK)) { - revert OnlyCallableFromLink(); - } - if (data.length != 32) { - revert InvalidCalldata(); - } - uint64 subId = abi.decode(data, (uint64)); - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - // We do not check that the msg.sender is the subscription owner, - // anyone can fund a subscription. - uint256 oldBalance = s_subscriptions[subId].balance; - s_subscriptions[subId].balance += uint96(amount); - s_totalBalance += uint96(amount); - emit SubscriptionFunded(subId, oldBalance, oldBalance + amount); - } - - function getCurrentSubId() external view returns (uint64) { - return s_currentSubId; - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function getSubscription( - uint64 subId - ) external view override returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - return ( - s_subscriptions[subId].balance, - s_subscriptions[subId].reqCount, - s_subscriptionConfigs[subId].owner, - s_subscriptionConfigs[subId].consumers - ); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function createSubscription() external override nonReentrant returns (uint64) { - s_currentSubId++; - uint64 currentSubId = s_currentSubId; - address[] memory consumers = new address[](0); - s_subscriptions[currentSubId] = Subscription({balance: 0, reqCount: 0}); - s_subscriptionConfigs[currentSubId] = SubscriptionConfig({ - owner: msg.sender, - requestedOwner: address(0), - consumers: consumers - }); - - emit SubscriptionCreated(currentSubId, msg.sender); - return currentSubId; - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function requestSubscriptionOwnerTransfer( - uint64 subId, - address newOwner - ) external override onlySubOwner(subId) nonReentrant { - // Proposing to address(0) would never be claimable so don't need to check. - if (s_subscriptionConfigs[subId].requestedOwner != newOwner) { - s_subscriptionConfigs[subId].requestedOwner = newOwner; - emit SubscriptionOwnerTransferRequested(subId, msg.sender, newOwner); - } - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function acceptSubscriptionOwnerTransfer(uint64 subId) external override nonReentrant { - if (s_subscriptionConfigs[subId].owner == address(0)) { - revert InvalidSubscription(); - } - if (s_subscriptionConfigs[subId].requestedOwner != msg.sender) { - revert MustBeRequestedOwner(s_subscriptionConfigs[subId].requestedOwner); - } - address oldOwner = s_subscriptionConfigs[subId].owner; - s_subscriptionConfigs[subId].owner = msg.sender; - s_subscriptionConfigs[subId].requestedOwner = address(0); - emit SubscriptionOwnerTransferred(subId, oldOwner, msg.sender); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function removeConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - if (s_consumers[consumer][subId] == 0) { - revert InvalidConsumer(subId, consumer); - } - // Note bounded by MAX_CONSUMERS - address[] memory consumers = s_subscriptionConfigs[subId].consumers; - uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; i++) { - if (consumers[i] == consumer) { - address last = consumers[lastConsumerIndex]; - // Storage write to preserve last element - s_subscriptionConfigs[subId].consumers[i] = last; - // Storage remove last element - s_subscriptionConfigs[subId].consumers.pop(); - break; - } - } - delete s_consumers[consumer][subId]; - emit SubscriptionConsumerRemoved(subId, consumer); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function addConsumer(uint64 subId, address consumer) external override onlySubOwner(subId) nonReentrant { - // Already maxed, cannot add any more consumers. - if (s_subscriptionConfigs[subId].consumers.length == MAX_CONSUMERS) { - revert TooManyConsumers(); - } - if (s_consumers[consumer][subId] != 0) { - // Idempotence - do nothing if already added. - // Ensures uniqueness in s_subscriptions[subId].consumers. - return; - } - // Initialize the nonce to 1, indicating the consumer is allocated. - s_consumers[consumer][subId] = 1; - s_subscriptionConfigs[subId].consumers.push(consumer); - - emit SubscriptionConsumerAdded(subId, consumer); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - */ - function cancelSubscription(uint64 subId, address to) external override onlySubOwner(subId) nonReentrant { - if (pendingRequestExists(subId)) { - revert PendingRequestExists(); - } - cancelSubscriptionHelper(subId, to); - } - - function cancelSubscriptionHelper(uint64 subId, address to) private nonReentrant { - SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; - Subscription memory sub = s_subscriptions[subId]; - uint96 balance = sub.balance; - // Note bounded by MAX_CONSUMERS; - // If no consumers, does nothing. - for (uint256 i = 0; i < subConfig.consumers.length; i++) { - delete s_consumers[subConfig.consumers[i]][subId]; - } - delete s_subscriptionConfigs[subId]; - delete s_subscriptions[subId]; - s_totalBalance -= balance; - if (!LINK.transfer(to, uint256(balance))) { - revert InsufficientBalance(); - } - emit SubscriptionCanceled(subId, to, balance); - } - - /** - * @inheritdoc VRFCoordinatorV2Interface - * @dev Looping is bounded to MAX_CONSUMERS*(number of keyhashes). - * @dev Used to disable subscription canceling while outstanding request are present. - */ - function pendingRequestExists(uint64 subId) public view override returns (bool) { - SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; - for (uint256 i = 0; i < subConfig.consumers.length; i++) { - for (uint256 j = 0; j < s_provingKeyHashes.length; j++) { - (uint256 reqId, ) = computeRequestId( - s_provingKeyHashes[j], - subConfig.consumers[i], - subId, - s_consumers[subConfig.consumers[i]][subId] - ); - if (s_requestCommitments[reqId] != 0) { - return true; - } - } - } - return false; - } - - modifier onlySubOwner(uint64 subId) { - address owner = s_subscriptionConfigs[subId].owner; - if (owner == address(0)) { - revert InvalidSubscription(); - } - if (msg.sender != owner) { - revert MustBeSubOwner(owner); - } - _; - } - - modifier nonReentrant() { - if (s_config.reentrancyLock) { - revert Reentrant(); - } - _; - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual override returns (string memory) { - return "VRFCoordinatorV2 1.0.0"; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol deleted file mode 100644 index c5d1d90..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFCoordinatorV2TestHelper.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; - -// Ideally this contract should inherit from VRFCoordinatorV2 and delegate calls to VRFCoordinatorV2 -// However, due to exceeding contract size limit, the logic from VRFCoordinatorV2 is ported over to this contract -contract VRFCoordinatorV2TestHelper { - uint96 internal s_paymentAmount; - - AggregatorV3Interface public immutable LINK_ETH_FEED; - - struct Config { - uint16 minimumRequestConfirmations; - uint32 maxGasLimit; - // Reentrancy protection. - bool reentrancyLock; - // stalenessSeconds is how long before we consider the feed price to be stale - // and fallback to fallbackWeiPerUnitLink. - uint32 stalenessSeconds; - // Gas to cover oracle payment after we calculate the payment. - // We make it configurable in case those operations are repriced. - uint32 gasAfterPaymentCalculation; - } - int256 private s_fallbackWeiPerUnitLink; - Config private s_config; - - constructor( - address linkEthFeed // solhint-disable-next-line no-empty-blocks - ) { - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - } - - function calculatePaymentAmountTest( - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeeLinkPPM, - uint256 weiPerUnitGas - ) external { - s_paymentAmount = calculatePaymentAmount( - gasleft(), - gasAfterPaymentCalculation, - fulfillmentFlatFeeLinkPPM, - weiPerUnitGas - ); - } - - error InvalidLinkWeiPrice(int256 linkWei); - error PaymentTooLarge(); - - function getFeedData() private view returns (int256) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 weiPerUnitLink; - (, weiPerUnitLink, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - // solhint-disable-next-line not-rely-on-time - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { - weiPerUnitLink = s_fallbackWeiPerUnitLink; - } - return weiPerUnitLink; - } - - // Get the amount of gas used for fulfillment - function calculatePaymentAmount( - uint256 startGas, - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeeLinkPPM, - uint256 weiPerUnitGas - ) internal view returns (uint96) { - int256 weiPerUnitLink; - weiPerUnitLink = getFeedData(); - if (weiPerUnitLink <= 0) { - revert InvalidLinkWeiPrice(weiPerUnitLink); - } - // (1e18 juels/link) (wei/gas * gas) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft())) / - uint256(weiPerUnitLink); - uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); - if (paymentNoFee > (1e27 - fee)) { - revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. - } - return uint96(paymentNoFee + fee); - } - - function getPaymentAmount() public view returns (uint96) { - return s_paymentAmount; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol deleted file mode 100644 index ee2a71d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFExternalSubOwnerExample.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -contract VRFExternalSubOwnerExample is VRFConsumerBaseV2 { - VRFCoordinatorV2Interface internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - - uint256[] public s_randomWords; - uint256 public s_requestId; - address internal s_owner; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - s_owner = msg.sender; - } - - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - s_randomWords = randomWords; - } - - function requestRandomWords( - uint64 subId, - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash - ) external onlyOwner { - // Will revert if subscription is not funded. - s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, requestConfirmations, callbackGasLimit, numWords); - } - - function transferOwnership(address newOwner) external onlyOwner { - s_owner = newOwner; - } - - modifier onlyOwner() { - require(msg.sender == s_owner); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol deleted file mode 100644 index 0193e3f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestExternalSubOwner.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -/** - * @title The VRFLoadTestExternalSubOwner contract. - * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. - */ -contract VRFLoadTestExternalSubOwner is VRFConsumerBaseV2, ConfirmedOwner { - VRFCoordinatorV2Interface public immutable COORDINATOR; - LinkTokenInterface public immutable LINK; - - uint256 public s_responseCount; - - constructor(address _vrfCoordinator, address _link) VRFConsumerBaseV2(_vrfCoordinator) ConfirmedOwner(msg.sender) { - COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); - LINK = LinkTokenInterface(_link); - } - - function fulfillRandomWords(uint256, uint256[] memory) internal override { - s_responseCount++; - } - - function requestRandomWords( - uint64 _subId, - uint16 _requestConfirmations, - bytes32 _keyHash, - uint16 _requestCount - ) external onlyOwner { - for (uint16 i = 0; i < _requestCount; i++) { - COORDINATOR.requestRandomWords(_keyHash, _subId, _requestConfirmations, 50_000, 1); - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol deleted file mode 100644 index a967c8a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFLoadTestOwnerlessConsumer.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFConsumerBase} from "../VRFConsumerBase.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; - -/** - * @title The VRFLoadTestOwnerlessConsumer contract. - * @notice Allows making many VRF V1 randomness requests in a single transaction for load testing. - */ -contract VRFLoadTestOwnerlessConsumer is VRFConsumerBase, IERC677Receiver { - // The price of each VRF request in Juels. 1 LINK = 1e18 Juels. - uint256 public immutable PRICE; - - uint256 public s_responseCount; - - constructor(address _vrfCoordinator, address _link, uint256 _price) VRFConsumerBase(_vrfCoordinator, _link) { - PRICE = _price; - } - - function fulfillRandomness(bytes32, uint256) internal override { - s_responseCount++; - } - - /** - * @dev Creates as many randomness requests as can be made with the funds transferred. - * @param _amount The amount of LINK transferred to pay for these requests. - * @param _data The data passed to transferAndCall on LinkToken. Must be an abi-encoded key hash. - */ - function onTokenTransfer(address, uint256 _amount, bytes calldata _data) external override { - if (msg.sender != address(LINK)) { - revert("only callable from LINK"); - } - bytes32 keyHash = abi.decode(_data, (bytes32)); - - uint256 spent = 0; - while (spent + PRICE <= _amount) { - requestRandomness(keyHash, PRICE); - spent += PRICE; - } - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol deleted file mode 100644 index be416e9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMaliciousConsumerV2.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -contract VRFMaliciousConsumerV2 is VRFConsumerBaseV2 { - uint256[] public s_randomWords; - uint256 public s_requestId; - VRFCoordinatorV2Interface internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - uint64 public s_subId; - uint256 public s_gasAvailable; - bytes32 internal s_keyHash; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - } - - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - s_gasAvailable = gasleft(); - s_randomWords = randomWords; - s_requestId = requestId; - // Should revert - COORDINATOR.requestRandomWords(s_keyHash, s_subId, 1, 200000, 1); - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness(bytes32 keyHash) external returns (uint256) { - s_keyHash = keyHash; - return COORDINATOR.requestRandomWords(keyHash, s_subId, 1, 500000, 1); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol deleted file mode 100644 index 4052c0d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFMockETHLINKAggregator.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "../../shared/interfaces/AggregatorV3Interface.sol"; - -contract VRFMockETHLINKAggregator is AggregatorV3Interface { - int256 public answer; - uint256 private blockTimestampDeduction = 0; - - constructor(int256 _answer) { - answer = _answer; - } - - function decimals() external pure override returns (uint8) { - return 18; - } - - function description() external pure override returns (string memory) { - return "VRFMockETHLINKAggregator"; - } - - function version() external pure override returns (uint256) { - return 1; - } - - function getRoundData( - uint80 /*_roundId*/ - ) - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); - } - - function latestRoundData() - external - view - override - returns (uint80 roundId, int256 ans, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) - { - return (1, answer, getDeductedBlockTimestamp(), getDeductedBlockTimestamp(), 1); - } - - function getDeductedBlockTimestamp() internal view returns (uint256) { - return block.timestamp - blockTimestampDeduction; - } - - function setBlockTimestampDeduction(uint256 _blockTimestampDeduction) external { - blockTimestampDeduction = _blockTimestampDeduction; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol deleted file mode 100644 index a641267..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFOwnerlessConsumerExample.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -// An example VRF V1 consumer contract that can be triggered using a transferAndCall from the link -// contract. -pragma solidity ^0.8.4; - -import {VRFConsumerBase} from "../VRFConsumerBase.sol"; -import {IERC677Receiver} from "../../shared/interfaces/IERC677Receiver.sol"; - -contract VRFOwnerlessConsumerExample is VRFConsumerBase, IERC677Receiver { - uint256 public s_randomnessOutput; - bytes32 public s_requestId; - - error OnlyCallableFromLink(); - - constructor(address _vrfCoordinator, address _link) VRFConsumerBase(_vrfCoordinator, _link) { - /* empty */ - } - - function fulfillRandomness(bytes32 requestId, uint256 _randomness) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - s_randomnessOutput = _randomness; - } - - /** - * @dev Creates a new randomness request. This function can only be used by calling - * transferAndCall on the LinkToken contract. - * @param _amount The amount of LINK transferred to pay for this request. - * @param _data The data passed to transferAndCall on LinkToken. Must be an abi-encoded key hash. - */ - function onTokenTransfer(address /* sender */, uint256 _amount, bytes calldata _data) external override { - if (msg.sender != address(LINK)) { - revert OnlyCallableFromLink(); - } - - bytes32 keyHash = abi.decode(_data, (bytes32)); - s_requestId = requestRandomness(keyHash, _amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol deleted file mode 100644 index 344797f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFRequestIDBaseTestHelper.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFRequestIDBase} from "../VRFRequestIDBase.sol"; - -contract VRFRequestIDBaseTestHelper is VRFRequestIDBase { - function makeVRFInputSeed_( - bytes32 _keyHash, - uint256 _userSeed, - address _requester, - uint256 _nonce - ) public pure returns (uint256) { - return makeVRFInputSeed(_keyHash, _userSeed, _requester, _nonce); - } - - function makeRequestId_(bytes32 _keyHash, uint256 _vRFInputSeed) public pure returns (bytes32) { - return makeRequestId(_keyHash, _vRFInputSeed); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol deleted file mode 100644 index 303394e..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSingleConsumerExample.sol +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: MIT -// Example of a single consumer contract which owns the subscription. -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -contract VRFSingleConsumerExample is VRFConsumerBaseV2 { - VRFCoordinatorV2Interface internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - - struct RequestConfig { - uint64 subId; - uint32 callbackGasLimit; - uint16 requestConfirmations; - uint32 numWords; - bytes32 keyHash; - } - RequestConfig public s_requestConfig; - uint256[] public s_randomWords; - uint256 public s_requestId; - address s_owner; - - constructor( - address vrfCoordinator, - address link, - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash - ) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - s_owner = msg.sender; - s_requestConfig = RequestConfig({ - subId: 0, // Unset initially - callbackGasLimit: callbackGasLimit, - requestConfirmations: requestConfirmations, - numWords: numWords, - keyHash: keyHash - }); - subscribe(); - } - - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { - require(requestId == s_requestId, "request ID is incorrect"); - s_randomWords = randomWords; - } - - // Assumes the subscription is funded sufficiently. - function requestRandomWords() external onlyOwner { - RequestConfig memory rc = s_requestConfig; - // Will revert if subscription is not set and funded. - s_requestId = COORDINATOR.requestRandomWords( - rc.keyHash, - rc.subId, - rc.requestConfirmations, - rc.callbackGasLimit, - rc.numWords - ); - } - - // Assumes this contract owns link - // This method is analogous to VRFv1, except the amount - // should be selected based on the keyHash (each keyHash functions like a "gas lane" - // with different link costs). - function fundAndRequestRandomWords(uint256 amount) external onlyOwner { - RequestConfig memory rc = s_requestConfig; - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_requestConfig.subId)); - // Will revert if subscription is not set and funded. - s_requestId = COORDINATOR.requestRandomWords( - rc.keyHash, - rc.subId, - rc.requestConfirmations, - rc.callbackGasLimit, - rc.numWords - ); - } - - // Assumes this contract owns link - function topUpSubscription(uint256 amount) external onlyOwner { - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_requestConfig.subId)); - } - - function withdraw(uint256 amount, address to) external onlyOwner { - LINKTOKEN.transfer(to, amount); - } - - function unsubscribe(address to) external onlyOwner { - // Returns funds to this address - COORDINATOR.cancelSubscription(s_requestConfig.subId, to); - s_requestConfig.subId = 0; - } - - // Keep this separate in case the contract want to unsubscribe and then - // resubscribe. - function subscribe() public onlyOwner { - // Create a subscription, current subId - address[] memory consumers = new address[](1); - consumers[0] = address(this); - s_requestConfig.subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_requestConfig.subId, consumers[0]); - } - - modifier onlyOwner() { - require(msg.sender == s_owner); - _; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol deleted file mode 100644 index 471b6f9..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFSubscriptionBalanceMonitorExposed.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.6; - -import {VRFSubscriptionBalanceMonitor} from "../dev/VRFSubscriptionBalanceMonitor.sol"; - -contract VRFSubscriptionBalanceMonitorExposed is VRFSubscriptionBalanceMonitor { - constructor( - address linkTokenAddress, - address coordinatorAddress, - address keeperRegistryAddress, - uint256 minWaitPeriodSeconds - ) VRFSubscriptionBalanceMonitor(linkTokenAddress, coordinatorAddress, keeperRegistryAddress, minWaitPeriodSeconds) {} - - function setLastTopUpXXXTestOnly(uint64 target, uint56 lastTopUpTimestamp) external { - s_targets[target].lastTopUpTimestamp = lastTopUpTimestamp; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol deleted file mode 100644 index 4b794d4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFTestHelper.sol +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRF} from "../VRF.sol"; - -/** *********************************************************************** - @notice Testing harness for VRF.sol, exposing its internal methods. Not to - @notice be used for production. -*/ -contract VRFTestHelper is VRF { - function bigModExp_(uint256 base, uint256 exponent) public view returns (uint256) { - return super._bigModExp(base, exponent); - } - - function squareRoot_(uint256 x) public view returns (uint256) { - return super._squareRoot(x); - } - - function ySquared_(uint256 x) public pure returns (uint256) { - return super._ySquared(x); - } - - function fieldHash_(bytes memory b) public pure returns (uint256) { - return super._fieldHash(b); - } - - function hashToCurve_(uint256[2] memory pk, uint256 x) public view returns (uint256[2] memory) { - return super._hashToCurve(pk, x); - } - - function ecmulVerify_(uint256[2] memory x, uint256 scalar, uint256[2] memory q) public pure returns (bool) { - return super._ecmulVerify(x, scalar, q); - } - - function projectiveECAdd_( - uint256 px, - uint256 py, - uint256 qx, - uint256 qy - ) public pure returns (uint256, uint256, uint256) { - return super._projectiveECAdd(px, py, qx, qy); - } - - function affineECAdd_( - uint256[2] memory p1, - uint256[2] memory p2, - uint256 invZ - ) public pure returns (uint256[2] memory) { - return super._affineECAdd(p1, p2, invZ); - } - - function verifyLinearCombinationWithGenerator_( - uint256 c, - uint256[2] memory p, - uint256 s, - address lcWitness - ) public pure returns (bool) { - return super._verifyLinearCombinationWithGenerator(c, p, s, lcWitness); - } - - function linearCombination_( - uint256 c, - uint256[2] memory p1, - uint256[2] memory cp1Witness, - uint256 s, - uint256[2] memory p2, - uint256[2] memory sp2Witness, - uint256 zInv - ) public pure returns (uint256[2] memory) { - return super._linearCombination(c, p1, cp1Witness, s, p2, sp2Witness, zInv); - } - - function scalarFromCurvePoints_( - uint256[2] memory hash, - uint256[2] memory pk, - uint256[2] memory gamma, - address uWitness, - uint256[2] memory v - ) public pure returns (uint256) { - return super._scalarFromCurvePoints(hash, pk, gamma, uWitness, v); - } - - function isOnCurve_(uint256[2] memory p) public pure returns (bool) { - return super._isOnCurve(p); - } - - function verifyVRFProof_( - uint256[2] memory pk, - uint256[2] memory gamma, - uint256 c, - uint256 s, - uint256 seed, - address uWitness, - uint256[2] memory cGammaWitness, - uint256[2] memory sHashWitness, - uint256 zInv - ) public view { - super._verifyVRFProof(pk, gamma, c, s, seed, uWitness, cGammaWitness, sHashWitness, zInv); - } - - function randomValueFromVRFProof_(Proof calldata proof, uint256 seed) public view returns (uint256 output) { - return super._randomValueFromVRFProof(proof, seed); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol deleted file mode 100644 index b4d0104..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2LoadTestWithMetrics.sol +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; - -/** - * @title The VRFLoadTestExternalSubOwner contract. - * @notice Allows making many VRF V2 randomness requests in a single transaction for load testing. - */ -contract VRFV2LoadTestWithMetrics is VRFConsumerBaseV2 { - VRFCoordinatorV2Interface public immutable COORDINATOR; - LinkTokenInterface public LINKTOKEN; - uint256 public s_responseCount; - uint256 public s_requestCount; - uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision - uint256 public s_slowestFulfillment = 0; - uint256 public s_fastestFulfillment = 999; - uint256 public s_lastRequestId; - mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made - - event SubscriptionCreatedFundedAndConsumerAdded(uint64 subId, address consumer, uint256 amount); - - struct RequestStatus { - bool fulfilled; - uint256[] randomWords; - uint requestTimestamp; - uint fulfilmentTimestamp; - uint256 requestBlockNumber; - uint256 fulfilmentBlockNumber; - } - - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor(address _vrfCoordinator) VRFConsumerBaseV2(_vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); - } - - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); - uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; - uint256 requestDelayInMillions = requestDelay * 1_000_000; - - if (requestDelay > s_slowestFulfillment) { - s_slowestFulfillment = requestDelay; - } - s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; - s_averageFulfillmentInMillions = s_responseCount > 0 - ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) - : requestDelayInMillions; - - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - s_requests[_requestId].fulfilmentTimestamp = block.timestamp; - s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; - - s_responseCount++; - } - - function requestRandomWords( - uint64 _subId, - uint16 _requestConfirmations, - bytes32 _keyHash, - uint32 _callbackGasLimit, - uint32 _numWords, - uint16 _requestCount - ) external { - _makeLoadTestRequests(_subId, _requestConfirmations, _keyHash, _callbackGasLimit, _numWords, _requestCount); - } - - function requestRandomWordsWithForceFulfill( - uint16 _requestConfirmations, - bytes32 _keyHash, - uint32 _callbackGasLimit, - uint32 _numWords, - uint16 _requestCount, - uint256 _subTopUpAmount, - address _link - ) external { - // create a subscription, address(this) will be the owner - uint64 _subId = COORDINATOR.createSubscription(); - // add address(this) as a consumer on the subscription - COORDINATOR.addConsumer(_subId, address(this)); - topUpSubscription(_subId, _subTopUpAmount, _link); - emit SubscriptionCreatedFundedAndConsumerAdded(_subId, address(this), _subTopUpAmount); - - _makeLoadTestRequests(_subId, _requestConfirmations, _keyHash, _callbackGasLimit, _numWords, _requestCount); - - COORDINATOR.removeConsumer(_subId, address(this)); - COORDINATOR.cancelSubscription(_subId, msg.sender); - } - - function reset() external { - s_averageFulfillmentInMillions = 0; // in millions for better precision - s_slowestFulfillment = 0; - s_fastestFulfillment = 999; - s_requestCount = 0; - s_responseCount = 0; - } - - function getRequestStatus( - uint256 _requestId - ) - external - view - returns ( - bool fulfilled, - uint256[] memory randomWords, - uint requestTimestamp, - uint fulfilmentTimestamp, - uint256 requestBlockNumber, - uint256 fulfilmentBlockNumber - ) - { - RequestStatus memory request = s_requests[_requestId]; - return ( - request.fulfilled, - request.randomWords, - request.requestTimestamp, - request.fulfilmentTimestamp, - request.requestBlockNumber, - request.fulfilmentBlockNumber - ); - } - - function _makeLoadTestRequests( - uint64 _subId, - uint16 _requestConfirmations, - bytes32 _keyHash, - uint32 _callbackGasLimit, - uint32 _numWords, - uint16 _requestCount - ) internal { - for (uint16 i = 0; i < _requestCount; i++) { - uint256 requestId = COORDINATOR.requestRandomWords( - _keyHash, - _subId, - _requestConfirmations, - _callbackGasLimit, - _numWords - ); - s_lastRequestId = requestId; - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - s_requests[requestId] = RequestStatus({ - randomWords: new uint256[](0), - fulfilled: false, - requestTimestamp: block.timestamp, - fulfilmentTimestamp: 0, - requestBlockNumber: requestBlockNumber, - fulfilmentBlockNumber: 0 - }); - s_requestCount++; - requestHeights[requestId] = requestBlockNumber; - } - } - - function topUpSubscription(uint64 _subId, uint256 _amount, address _link) public { - LINKTOKEN = LinkTokenInterface(_link); - LINKTOKEN.transferAndCall(address(COORDINATOR), _amount, abi.encode(_subId)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol deleted file mode 100644 index 8f1b275..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2OwnerTestConsumer.sol +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; - -contract VRFV2OwnerTestConsumer is VRFConsumerBaseV2, ConfirmedOwner { - VRFCoordinatorV2Interface public COORDINATOR; - LinkTokenInterface public LINKTOKEN; - uint64 public subId; - uint256 public s_responseCount; - uint256 public s_requestCount; - uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision - uint256 public s_slowestFulfillment = 0; - uint256 public s_fastestFulfillment = 999; - uint256 public s_lastRequestId; - mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made - - event SubscriptionCreatedFundedAndConsumerAdded(uint64 subId, address consumer, uint256 amount); - - struct RequestStatus { - bool fulfilled; - uint256[] randomWords; - uint requestTimestamp; - uint fulfilmentTimestamp; - uint256 requestBlockNumber; - uint256 fulfilmentBlockNumber; - } - - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor(address _vrfCoordinator, address _link) VRFConsumerBaseV2(_vrfCoordinator) ConfirmedOwner(msg.sender) { - COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); - LINKTOKEN = LinkTokenInterface(_link); - } - - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); - uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; - uint256 requestDelayInMillions = requestDelay * 1_000_000; - - if (requestDelay > s_slowestFulfillment) { - s_slowestFulfillment = requestDelay; - } - s_fastestFulfillment = requestDelay < s_fastestFulfillment ? requestDelay : s_fastestFulfillment; - s_averageFulfillmentInMillions = s_responseCount > 0 - ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) - : requestDelayInMillions; - - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - s_requests[_requestId].fulfilmentTimestamp = block.timestamp; - s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; - - s_responseCount++; - } - - function requestRandomWords( - uint16 _requestConfirmations, - bytes32 _keyHash, - uint32 _callbackGasLimit, - uint32 _numWords, - uint16 _requestCount, - uint256 _subTopUpAmount - ) external onlyOwner { - // create a subscription, address(this) will be the owner - subId = COORDINATOR.createSubscription(); - // add address(this) as a consumer on the subscription - COORDINATOR.addConsumer(subId, address(this)); - topUpSubscription(_subTopUpAmount); - emit SubscriptionCreatedFundedAndConsumerAdded(subId, address(this), _subTopUpAmount); - - for (uint16 i = 0; i < _requestCount; i++) { - uint256 requestId = COORDINATOR.requestRandomWords( - _keyHash, - subId, - _requestConfirmations, - _callbackGasLimit, - _numWords - ); - s_lastRequestId = requestId; - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - s_requests[requestId] = RequestStatus({ - randomWords: new uint256[](0), - fulfilled: false, - requestTimestamp: block.timestamp, - fulfilmentTimestamp: 0, - requestBlockNumber: requestBlockNumber, - fulfilmentBlockNumber: 0 - }); - s_requestCount++; - requestHeights[requestId] = requestBlockNumber; - } - - COORDINATOR.removeConsumer(subId, address(this)); - COORDINATOR.cancelSubscription(subId, msg.sender); - } - - function reset() external { - s_averageFulfillmentInMillions = 0; // in millions for better precision - s_slowestFulfillment = 0; - s_fastestFulfillment = 999; - s_requestCount = 0; - s_responseCount = 0; - } - - function getRequestStatus( - uint256 _requestId - ) - external - view - returns ( - bool fulfilled, - uint256[] memory randomWords, - uint requestTimestamp, - uint fulfilmentTimestamp, - uint256 requestBlockNumber, - uint256 fulfilmentBlockNumber - ) - { - RequestStatus memory request = s_requests[_requestId]; - return ( - request.fulfilled, - request.randomWords, - request.requestTimestamp, - request.fulfilmentTimestamp, - request.requestBlockNumber, - request.fulfilmentBlockNumber - ); - } - - function topUpSubscription(uint256 amount) public onlyOwner { - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(subId)); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol deleted file mode 100644 index 4b0a7fd..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2ProxyAdmin.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; - -contract VRFV2ProxyAdmin is ProxyAdmin { - // Nothing here, this is just to generate the gethwrapper for tests. -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol deleted file mode 100644 index 3d9cf30..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2RevertingExample.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; -import {VRFConsumerBaseV2} from "../VRFConsumerBaseV2.sol"; - -// VRFV2RevertingExample will always revert. Used for testing only, useless in prod. -contract VRFV2RevertingExample is VRFConsumerBaseV2 { - uint256[] public s_randomWords; - uint256 public s_requestId; - VRFCoordinatorV2Interface internal COORDINATOR; - LinkTokenInterface internal LINKTOKEN; - uint64 public s_subId; - uint256 public s_gasAvailable; - - constructor(address vrfCoordinator, address link) VRFConsumerBaseV2(vrfCoordinator) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - LINKTOKEN = LinkTokenInterface(link); - } - - function fulfillRandomWords(uint256, uint256[] memory) internal pure override { - // solhint-disable-next-line gas-custom-errors, reason-string - revert(); - } - - function createSubscriptionAndFund(uint96 amount) external { - if (s_subId == 0) { - s_subId = COORDINATOR.createSubscription(); - COORDINATOR.addConsumer(s_subId, address(this)); - } - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function topUpSubscription(uint96 amount) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "sub not set"); - // Approve the link transfer. - LINKTOKEN.transferAndCall(address(COORDINATOR), amount, abi.encode(s_subId)); - } - - function updateSubscription(address[] memory consumers) external { - // solhint-disable-next-line gas-custom-errors - require(s_subId != 0, "subID not set"); - for (uint256 i = 0; i < consumers.length; i++) { - COORDINATOR.addConsumer(s_subId, consumers[i]); - } - } - - function requestRandomness( - bytes32 keyHash, - uint64 subId, - uint16 minReqConfs, - uint32 callbackGasLimit, - uint32 numWords - ) external returns (uint256) { - s_requestId = COORDINATOR.requestRandomWords(keyHash, subId, minReqConfs, callbackGasLimit, numWords); - return s_requestId; - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol deleted file mode 100644 index f3364d0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2TransparentUpgradeableProxy.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; - -contract VRFV2TransparentUpgradeableProxy is TransparentUpgradeableProxy { - // Nothing special here, this is just to generate the gethwrapper for tests. - constructor( - address _logic, - address admin_, - bytes memory _data - ) payable TransparentUpgradeableProxy(_logic, admin_, _data) {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol deleted file mode 100644 index 924e3e4..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperConsumerExample.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -contract VRFV2WrapperConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { - event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); - event WrapperRequestMade(uint256 indexed requestId, uint256 paid); - - struct RequestStatus { - uint256 paid; - bool fulfilled; - uint256[] randomWords; - } - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - constructor( - address _link, - address _vrfV2Wrapper - ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} - - function makeRequest( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) external onlyOwner returns (uint256 requestId) { - requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); - uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); - s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false}); - emit WrapperRequestMade(requestId, paid); - return requestId; - } - - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); - } - - function getRequestStatus( - uint256 _requestId - ) external view returns (uint256 paid, bool fulfilled, uint256[] memory randomWords) { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - RequestStatus memory request = s_requests[_requestId]; - return (request.paid, request.fulfilled, request.randomWords); - } - - /// @notice withdrawLink withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in juels - function withdrawLink(uint256 amount) external onlyOwner { - LINK.transfer(owner(), amount); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol deleted file mode 100644 index 3da8f17..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperLoadTestConsumer.sol +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; -import {VRFV2WrapperInterface} from "../interfaces/VRFV2WrapperInterface.sol"; - -contract VRFV2WrapperLoadTestConsumer is VRFV2WrapperConsumerBase, ConfirmedOwner { - VRFV2WrapperInterface public immutable i_vrfV2Wrapper; - uint256 public s_responseCount; - uint256 public s_requestCount; - uint256 public s_averageFulfillmentInMillions = 0; // in millions for better precision - uint256 public s_slowestFulfillment = 0; - uint256 public s_fastestFulfillment = 999; - uint256 public s_lastRequestId; - // solhint-disable-next-line chainlink-solidity/prefix-storage-variables-with-s-underscore - mapping(uint256 => uint256) internal requestHeights; // requestIds to block number when rand request was made - mapping(uint256 => RequestStatus) /* requestId */ /* requestStatus */ public s_requests; - - event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment); - event WrapperRequestMade(uint256 indexed requestId, uint256 paid); - - struct RequestStatus { - uint256 paid; - bool fulfilled; - uint256[] randomWords; - uint256 requestTimestamp; - uint256 fulfilmentTimestamp; - uint256 requestBlockNumber; - uint256 fulfilmentBlockNumber; - } - - constructor( - address _link, - address _vrfV2Wrapper - ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) { - i_vrfV2Wrapper = VRFV2WrapperInterface(_vrfV2Wrapper); - } - - function makeRequests( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords, - uint16 _requestCount - ) external { - for (uint16 i = 0; i < _requestCount; i++) { - uint256 requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); - s_lastRequestId = requestId; - uint256 requestBlockNumber = ChainSpecificUtil._getBlockNumber(); - uint256 paid = VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit); - s_requests[requestId] = RequestStatus({ - paid: paid, - fulfilled: false, - randomWords: new uint256[](0), - requestTimestamp: block.timestamp, - fulfilmentTimestamp: 0, - requestBlockNumber: requestBlockNumber, - fulfilmentBlockNumber: 0 - }); - s_requestCount++; - requestHeights[requestId] = requestBlockNumber; - emit WrapperRequestMade(requestId, paid); - } - } - - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - uint256 fulfilmentBlockNumber = ChainSpecificUtil._getBlockNumber(); - uint256 requestDelay = fulfilmentBlockNumber - requestHeights[_requestId]; - uint256 requestDelayInMillions = requestDelay * 1_000_000; - - if (requestDelay > s_slowestFulfillment) { - s_slowestFulfillment = requestDelay; - } - if (requestDelay < s_fastestFulfillment) { - s_fastestFulfillment = requestDelay; - } - s_averageFulfillmentInMillions = s_responseCount > 0 - ? (s_averageFulfillmentInMillions * s_responseCount + requestDelayInMillions) / (s_responseCount + 1) - : requestDelayInMillions; - - s_responseCount++; - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - s_requests[_requestId].fulfilmentTimestamp = block.timestamp; - s_requests[_requestId].fulfilmentBlockNumber = fulfilmentBlockNumber; - - emit WrappedRequestFulfilled(_requestId, _randomWords, s_requests[_requestId].paid); - } - - function getRequestStatus( - uint256 _requestId - ) - external - view - returns ( - uint256 paid, - bool fulfilled, - uint256[] memory randomWords, - uint256 requestTimestamp, - uint256 fulfilmentTimestamp, - uint256 requestBlockNumber, - uint256 fulfilmentBlockNumber - ) - { - // solhint-disable-next-line gas-custom-errors - require(s_requests[_requestId].paid > 0, "request not found"); - RequestStatus memory request = s_requests[_requestId]; - return ( - request.paid, - request.fulfilled, - request.randomWords, - request.requestTimestamp, - request.fulfilmentTimestamp, - request.requestBlockNumber, - request.fulfilmentBlockNumber - ); - } - - /// @notice withdrawLink withdraws the amount specified in amount to the owner - /// @param amount the amount to withdraw, in juels - function withdrawLink(uint256 amount) external onlyOwner { - LINK.transfer(owner(), amount); - } - - function reset() external { - s_averageFulfillmentInMillions = 0; - s_slowestFulfillment = 0; - s_fastestFulfillment = 999; - s_requestCount = 0; - s_responseCount = 0; - } - - receive() external payable {} -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol deleted file mode 100644 index 353027d..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperOutOfGasConsumerExample.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -contract VRFV2WrapperOutOfGasConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { - constructor( - address _link, - address _vrfV2Wrapper - ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} - - function makeRequest( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) external onlyOwner returns (uint256 requestId) { - return requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); - } - - function fulfillRandomWords(uint256 /* _requestId */, uint256[] memory /* _randomWords */) internal view override { - while (gasleft() > 0) {} - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol deleted file mode 100644 index d78992a..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperRevertingConsumerExample.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.6; - -import {VRFV2WrapperConsumerBase} from "../VRFV2WrapperConsumerBase.sol"; -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; - -contract VRFV2WrapperRevertingConsumerExample is VRFV2WrapperConsumerBase, ConfirmedOwner { - constructor( - address _link, - address _vrfV2Wrapper - ) ConfirmedOwner(msg.sender) VRFV2WrapperConsumerBase(_link, _vrfV2Wrapper) {} - - function makeRequest( - uint32 _callbackGasLimit, - uint16 _requestConfirmations, - uint32 _numWords - ) external onlyOwner returns (uint256 requestId) { - return requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords); - } - - function fulfillRandomWords(uint256 /* _requestId */, uint256[] memory /* _randomWords */) internal pure override { - revert("reverting example"); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol deleted file mode 100644 index 3bae36f..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFV2WrapperUnderFundingConsumer.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; -import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; -import {VRFV2WrapperInterface} from "../interfaces/VRFV2WrapperInterface.sol"; - -contract VRFV2WrapperUnderFundingConsumer is ConfirmedOwner { - LinkTokenInterface internal immutable LINK; - VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; - - constructor(address _link, address _vrfV2Wrapper) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(_link); - VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); - } - - function makeRequest(uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords) external onlyOwner { - LINK.transferAndCall( - address(VRF_V2_WRAPPER), - // Pay less than the needed amount - VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit) - 1, - abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) - ); - } -} diff --git a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol b/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol deleted file mode 100644 index 4ec7ad0..0000000 --- a/packages/foundry/lib/chainlink/contracts/src/v0.8/vrf/testhelpers/VRFv2Consumer.sol +++ /dev/null @@ -1,64 +0,0 @@ -// SPDX-License-Identifier: MIT -// An example of a consumer contract that relies on a subscription for funding. -pragma solidity 0.8.6; - -import "../interfaces/VRFCoordinatorV2Interface.sol"; -import "../VRFConsumerBaseV2.sol"; -import "../../shared/access/ConfirmedOwner.sol"; - -/** - * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY. - * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. - * DO NOT USE THIS CODE IN PRODUCTION. - */ - -contract VRFv2Consumer is VRFConsumerBaseV2, ConfirmedOwner { - event RequestSent(uint256 requestId, uint32 numWords); - event RequestFulfilled(uint256 requestId, uint256[] randomWords); - - struct RequestStatus { - bool fulfilled; // whether the request has been successfully fulfilled - bool exists; // whether a requestId exists - uint256[] randomWords; - } - mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ - VRFCoordinatorV2Interface COORDINATOR; - - // past requests Id. - uint256[] public requestIds; - uint256 public lastRequestId; - - constructor(address vrfCoordinator) VRFConsumerBaseV2(vrfCoordinator) ConfirmedOwner(msg.sender) { - COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); - } - - // Assumes the subscription is funded sufficiently. - function requestRandomWords( - uint64 subId, - uint32 callbackGasLimit, - uint16 requestConfirmations, - uint32 numWords, - bytes32 keyHash - ) external onlyOwner returns (uint256 requestId) { - // Will revert if subscription is not set and funded. - requestId = COORDINATOR.requestRandomWords(keyHash, subId, requestConfirmations, callbackGasLimit, numWords); - s_requests[requestId] = RequestStatus({randomWords: new uint256[](0), exists: true, fulfilled: false}); - requestIds.push(requestId); - lastRequestId = requestId; - emit RequestSent(requestId, numWords); - return requestId; - } - - function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { - require(s_requests[_requestId].exists, "request not found"); - s_requests[_requestId].fulfilled = true; - s_requests[_requestId].randomWords = _randomWords; - emit RequestFulfilled(_requestId, _randomWords); - } - - function getRequestStatus(uint256 _requestId) external view returns (bool fulfilled, uint256[] memory randomWords) { - require(s_requests[_requestId].exists, "request not found"); - RequestStatus memory request = s_requests[_requestId]; - return (request.fulfilled, request.randomWords); - } -} From 7138098a3ba2568a8ddd33ddd2cf0d8f3ac4b4d5 Mon Sep 17 00:00:00 2001 From: vasu gupta Date: Sat, 16 Nov 2024 19:14:51 +0530 Subject: [PATCH 7/7] Oracle Integration --- packages/foundry/lib/solmate | 1 - 1 file changed, 1 deletion(-) delete mode 160000 packages/foundry/lib/solmate diff --git a/packages/foundry/lib/solmate b/packages/foundry/lib/solmate deleted file mode 160000 index c93f771..0000000 --- a/packages/foundry/lib/solmate +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c93f7716c9909175d45f6ef80a34a650e2d24e56